]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/d10v/interp.c
* interp.c (UMEM_SEGMENTS): New define, set to 128.
[thirdparty/binutils-gdb.git] / sim / d10v / interp.c
CommitLineData
d70b4d42 1#include <signal.h>
2934d1c9 2#include "sysdep.h"
04885cc3 3#include "bfd.h"
cee402dd 4#include "callback.h"
2934d1c9 5#include "remote-sim.h"
2934d1c9
MH
6
7#include "d10v_sim.h"
8
cee68738
FF
9#define IMEM_SIZE 18 /* D10V instruction memory size is 18 bits */
10#define DMEM_SIZE 16 /* Data memory is 64K (but only 32K internal RAM) */
11#define UMEM_SIZE 17 /* Each unified memory segment is 17 bits */
12#define UMEM_SEGMENTS 128 /* Number of segments in unified memory region */
2934d1c9 13
87178dbd
MM
14enum _leftright { LEFT_FIRST, RIGHT_FIRST };
15
04885cc3
DE
16static char *myname;
17static SIM_OPEN_KIND sim_kind;
7eebfc62 18int d10v_debug;
87178dbd 19host_callback *d10v_callback;
aeb1f26b 20unsigned long ins_type_counters[ (int)INS_MAX ];
87178dbd 21
2934d1c9
MH
22uint16 OP[4];
23
b30cdd35 24static int init_text_p = 0;
04885cc3
DE
25/* non-zero if we opened prog_bfd */
26static int prog_bfd_was_opened_p;
27bfd *prog_bfd;
b30cdd35
MM
28asection *text;
29bfd_vma text_start;
30bfd_vma text_end;
31
aeb1f26b 32static long hash PARAMS ((long insn, int format));
2934d1c9 33static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size));
aeb1f26b
MM
34static void get_operands PARAMS ((struct simops *s, uint32 ins));
35static void do_long PARAMS ((uint32 ins));
36static void do_2_short PARAMS ((uint16 ins1, uint16 ins2, enum _leftright leftright));
37static void do_parallel PARAMS ((uint16 ins1, uint16 ins2));
38static char *add_commas PARAMS ((char *buf, int sizeof_buf, unsigned long value));
aeb1f26b 39static void init_system PARAMS ((void));
aeb1f26b
MM
40extern void sim_set_profile PARAMS ((int n));
41extern void sim_set_profile_size PARAMS ((int n));
aeb1f26b
MM
42
43#ifndef INLINE
44#if defined(__GNUC__) && defined(__OPTIMIZE__)
45#define INLINE __inline__
46#else
47#define INLINE
48#endif
49#endif
2934d1c9
MH
50
51#define MAX_HASH 63
52struct hash_entry
53{
54 struct hash_entry *next;
55 long opcode;
56 long mask;
cee402dd 57 int size;
2934d1c9
MH
58 struct simops *ops;
59};
60
61struct hash_entry hash_table[MAX_HASH+1];
62
aeb1f26b 63INLINE static long
2934d1c9
MH
64hash(insn, format)
65 long insn;
66 int format;
67{
68 if (format & LONG_OPCODE)
69 return ((insn & 0x3F000000) >> 24);
70 else
71 return((insn & 0x7E00) >> 9);
72}
73
aeb1f26b 74INLINE static struct hash_entry *
2934d1c9
MH
75lookup_hash (ins, size)
76 uint32 ins;
77 int size;
78{
79 struct hash_entry *h;
80
81 if (size)
82 h = &hash_table[(ins & 0x3F000000) >> 24];
83 else
84 h = &hash_table[(ins & 0x7E00) >> 9];
85
cee402dd 86 while ((ins & h->mask) != h->opcode || h->size != size)
2934d1c9
MH
87 {
88 if (h->next == NULL)
89 {
7eebfc62 90 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR looking up hash for %x at PC %x\n",ins, PC);
aeb1f26b 91 exit (1);
2934d1c9
MH
92 }
93 h = h->next;
94 }
95 return (h);
96}
97
aeb1f26b 98INLINE static void
2934d1c9
MH
99get_operands (struct simops *s, uint32 ins)
100{
101 int i, shift, bits, flags;
102 uint32 mask;
103 for (i=0; i < s->numops; i++)
104 {
105 shift = s->operands[3*i];
106 bits = s->operands[3*i+1];
107 flags = s->operands[3*i+2];
108 mask = 0x7FFFFFFF >> (31 - bits);
109 OP[i] = (ins >> shift) & mask;
110 }
111}
112
b30cdd35
MM
113bfd_vma
114decode_pc ()
115{
116 asection *s;
117 if (!init_text_p)
118 {
119 init_text_p = 1;
04885cc3
DE
120 for (s = prog_bfd->sections; s; s = s->next)
121 if (strcmp (bfd_get_section_name (prog_bfd, s), ".text") == 0)
b30cdd35
MM
122 {
123 text = s;
04885cc3
DE
124 text_start = bfd_get_section_vma (prog_bfd, s);
125 text_end = text_start + bfd_section_size (prog_bfd, s);
b30cdd35
MM
126 break;
127 }
128 }
129
130 return (PC << 2) + text_start;
131}
132
2934d1c9
MH
133static void
134do_long (ins)
135 uint32 ins;
136{
137 struct hash_entry *h;
7eebfc62
MM
138#ifdef DEBUG
139 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
140 (*d10v_callback->printf_filtered) (d10v_callback, "do_long 0x%x\n", ins);
141#endif
2934d1c9
MH
142 h = lookup_hash (ins, 1);
143 get_operands (h->ops, ins);
87178dbd 144 State.ins_type = INS_LONG;
7eebfc62 145 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9
MH
146 (h->ops->func)();
147}
215ac953 148
2934d1c9 149static void
87178dbd 150do_2_short (ins1, ins2, leftright)
2934d1c9 151 uint16 ins1, ins2;
87178dbd 152 enum _leftright leftright;
2934d1c9
MH
153{
154 struct hash_entry *h;
215ac953 155 reg_t orig_pc = PC;
c422ecc7 156 enum _ins_type first, second;
215ac953 157
7eebfc62
MM
158#ifdef DEBUG
159 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
160 (*d10v_callback->printf_filtered) (d10v_callback, "do_2_short 0x%x (%s) -> 0x%x\n",
161 ins1, (leftright) ? "left" : "right", ins2);
162#endif
c422ecc7
MH
163
164 if (leftright == LEFT_FIRST)
165 {
166 first = INS_LEFT;
167 second = INS_RIGHT;
168 ins_type_counters[ (int)INS_LEFTRIGHT ]++;
169 }
170 else
171 {
172 first = INS_RIGHT;
173 second = INS_LEFT;
174 ins_type_counters[ (int)INS_RIGHTLEFT ]++;
175 }
176
2934d1c9
MH
177 h = lookup_hash (ins1, 0);
178 get_operands (h->ops, ins1);
c422ecc7 179 State.ins_type = first;
7eebfc62 180 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9 181 (h->ops->func)();
215ac953
MM
182
183 /* If the PC has changed (ie, a jump), don't do the second instruction */
57bc1a72 184 if (orig_pc == PC && !State.exception)
215ac953
MM
185 {
186 h = lookup_hash (ins2, 0);
187 get_operands (h->ops, ins2);
c422ecc7 188 State.ins_type = second;
215ac953 189 ins_type_counters[ (int)State.ins_type ]++;
c422ecc7 190 ins_type_counters[ (int)INS_CYCLES ]++;
215ac953
MM
191 (h->ops->func)();
192 }
c422ecc7
MH
193 else if (orig_pc != PC && !State.exception)
194 ins_type_counters[ (int)INS_COND_JUMP ]++;
2934d1c9 195}
215ac953 196
2934d1c9
MH
197static void
198do_parallel (ins1, ins2)
199 uint16 ins1, ins2;
200{
201 struct hash_entry *h1, *h2;
7eebfc62
MM
202#ifdef DEBUG
203 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
204 (*d10v_callback->printf_filtered) (d10v_callback, "do_parallel 0x%x || 0x%x\n", ins1, ins2);
205#endif
c422ecc7 206 ins_type_counters[ (int)INS_PARALLEL ]++;
2934d1c9 207 h1 = lookup_hash (ins1, 0);
2934d1c9 208 h2 = lookup_hash (ins2, 0);
d70b4d42 209
2934d1c9
MH
210 if (h1->ops->exec_type == PARONLY)
211 {
d70b4d42 212 get_operands (h1->ops, ins1);
aeb1f26b 213 State.ins_type = INS_LEFT_COND_TEST;
7eebfc62 214 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9
MH
215 (h1->ops->func)();
216 if (State.exe)
d70b4d42 217 {
aeb1f26b 218 ins_type_counters[ (int)INS_COND_TRUE ]++;
d70b4d42 219 get_operands (h2->ops, ins2);
aeb1f26b
MM
220 State.ins_type = INS_RIGHT_COND_EXE;
221 ins_type_counters[ (int)State.ins_type ]++;
d70b4d42
MH
222 (h2->ops->func)();
223 }
aeb1f26b
MM
224 else
225 ins_type_counters[ (int)INS_COND_FALSE ]++;
2934d1c9
MH
226 }
227 else if (h2->ops->exec_type == PARONLY)
228 {
d70b4d42 229 get_operands (h2->ops, ins2);
aeb1f26b 230 State.ins_type = INS_RIGHT_COND_TEST;
7eebfc62 231 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9
MH
232 (h2->ops->func)();
233 if (State.exe)
d70b4d42 234 {
aeb1f26b 235 ins_type_counters[ (int)INS_COND_TRUE ]++;
d70b4d42 236 get_operands (h1->ops, ins1);
aeb1f26b
MM
237 State.ins_type = INS_LEFT_COND_EXE;
238 ins_type_counters[ (int)State.ins_type ]++;
d70b4d42
MH
239 (h1->ops->func)();
240 }
aeb1f26b
MM
241 else
242 ins_type_counters[ (int)INS_COND_FALSE ]++;
2934d1c9
MH
243 }
244 else
245 {
d70b4d42 246 get_operands (h1->ops, ins1);
87178dbd 247 State.ins_type = INS_LEFT_PARALLEL;
7eebfc62 248 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9 249 (h1->ops->func)();
57bc1a72
MM
250 if (!State.exception)
251 {
252 get_operands (h2->ops, ins2);
253 State.ins_type = INS_RIGHT_PARALLEL;
254 ins_type_counters[ (int)State.ins_type ]++;
255 (h2->ops->func)();
256 }
2934d1c9
MH
257 }
258}
259
aeb1f26b
MM
260static char *
261add_commas(buf, sizeof_buf, value)
262 char *buf;
263 int sizeof_buf;
264 unsigned long value;
265{
266 int comma = 3;
267 char *endbuf = buf + sizeof_buf - 1;
268
269 *--endbuf = '\0';
270 do {
271 if (comma-- == 0)
272 {
273 *--endbuf = ',';
274 comma = 2;
275 }
276
277 *--endbuf = (value % 10) + '0';
278 } while ((value /= 10) != 0);
279
280 return endbuf;
281}
2934d1c9
MH
282
283void
284sim_size (power)
285 int power;
286
287{
c422ecc7
MH
288 int i;
289
2934d1c9
MH
290 if (State.imem)
291 {
cee68738 292 for (i=0;i<UMEM_SEGMENTS;i++)
c422ecc7
MH
293 {
294 if (State.umem[i])
295 {
296 free (State.umem[i]);
297 State.umem[i] = NULL;
298 }
299 }
2934d1c9
MH
300 free (State.imem);
301 free (State.dmem);
302 }
303
304 State.imem = (uint8 *)calloc(1,1<<IMEM_SIZE);
305 State.dmem = (uint8 *)calloc(1,1<<DMEM_SIZE);
cee68738 306 for (i=1;i<(UMEM_SEGMENTS-1);i++)
c422ecc7
MH
307 State.umem[i] = NULL;
308 State.umem[0] = (uint8 *)calloc(1,1<<UMEM_SIZE);
309 State.umem[1] = (uint8 *)calloc(1,1<<UMEM_SIZE);
310 State.umem[2] = (uint8 *)calloc(1,1<<UMEM_SIZE);
cee68738
FF
311 State.umem[UMEM_SEGMENTS-1] = (uint8 *)calloc(1,1<<UMEM_SIZE);
312 if (!State.imem || !State.dmem || !State.umem[0] || !State.umem[1] || !State.umem[2] || !State.umem[UMEM_SEGMENTS-1] )
2934d1c9 313 {
7eebfc62 314 (*d10v_callback->printf_filtered) (d10v_callback, "Memory allocation failed.\n");
2934d1c9
MH
315 exit(1);
316 }
c422ecc7
MH
317
318 SET_IMAP0(0x1000);
319 SET_IMAP1(0x1000);
320 SET_DMAP(0);
57bc1a72 321
7eebfc62
MM
322#ifdef DEBUG
323 if ((d10v_debug & DEBUG_MEMSIZE) != 0)
324 {
aeb1f26b
MM
325 char buffer[20];
326 (*d10v_callback->printf_filtered) (d10v_callback,
327 "Allocated %s bytes instruction memory and\n",
328 add_commas (buffer, sizeof (buffer), (1UL<<IMEM_SIZE)));
329
330 (*d10v_callback->printf_filtered) (d10v_callback, " %s bytes data memory.\n",
331 add_commas (buffer, sizeof (buffer), (1UL<<IMEM_SIZE)));
7eebfc62 332 }
87178dbd 333#endif
2934d1c9
MH
334}
335
336static void
337init_system ()
338{
339 if (!State.imem)
340 sim_size(1);
341}
342
cee68738
FF
343/* Transfer data to/from simulated memory. Since a bug in either the
344 simulated program or in gdb or the simulator itself may cause a
345 bogus address to be passed in, we need to do some sanity checking
346 on addresses to make sure they are within bounds. When an address
347 fails the bounds check, treat it as a zero length read/write rather
348 than aborting the entire run. */
349
c422ecc7
MH
350static int
351xfer_mem (addr, buffer, size, write)
2934d1c9
MH
352 SIM_ADDR addr;
353 unsigned char *buffer;
354 int size;
c422ecc7 355 int write;
2934d1c9 356{
c422ecc7
MH
357 if (!State.imem)
358 init_system ();
2934d1c9 359
57bc1a72
MM
360#ifdef DEBUG
361 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
c422ecc7
MH
362 {
363 if (write)
cee68738
FF
364 {
365 (*d10v_callback->printf_filtered) (d10v_callback, "sim_write %d bytes to 0x%x\n", size, addr);
366 }
c422ecc7 367 else
cee68738
FF
368 {
369 (*d10v_callback->printf_filtered) (d10v_callback, "sim_read %d bytes from 0x%x\n", size, addr);
370 }
c422ecc7 371 }
57bc1a72
MM
372#endif
373
cee68738
FF
374 /* to access data, we use the following mapping
375 0x00000000 - 0x00ffffff : 16 Mb of external unified memory in segments of 128 Kb each
376 0x01000000 - 0x0103ffff : 256 Kb of external instruction memory
377 0x02000000 - 0x0200ffff : 32 Kb of on chip data memory + 16 Kb DMAP memory + 16 Kb I/O space */
57bc1a72 378
cee68738 379 if ((addr | 0x00ffffff) == 0x00ffffff)
c422ecc7 380 {
cee68738
FF
381 /* UNIFIED MEMORY (0x00000000 - 0x00ffffff) */
382 int startsegment, startoffset; /* Segment and offset within segment where xfer starts */
383 int endsegment, endoffset; /* Segment and offset within segment where xfer ends */
384
385 startsegment = addr >> UMEM_SIZE;
386 startoffset = addr & ((1 << UMEM_SIZE) - 1);
387 endsegment = (addr + size) >> UMEM_SIZE;
388 endoffset = (addr + size) & ((1 << UMEM_SIZE) - 1);
389
390 /* FIXME: We do not currently implement xfers across segments, so detect this case and fail gracefully. */
391
392 if ((startsegment != endsegment) && !((endsegment == (startsegment + 1)) && endoffset == 0))
393 {
394 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: Unimplemented support for transfers across unified memory segment boundaries\n");
395 return (0);
396 }
397 if (!State.umem[startsegment])
04885cc3
DE
398 {
399#ifdef DEBUG
cee68738
FF
400 if ((d10v_debug & DEBUG_MEMSIZE) != 0)
401 {
402 (*d10v_callback->printf_filtered) (d10v_callback,"Allocating %s bytes unified memory to region %d\n",
403 add_commas (buffer, sizeof (buffer), (1UL<<IMEM_SIZE)), startsegment);
404 }
04885cc3 405#endif
cee68738 406 State.umem[startsegment] = (uint8 *)calloc(1,1<<UMEM_SIZE);
04885cc3 407 }
cee68738 408 if (!State.umem[startsegment])
c422ecc7 409 {
cee68738
FF
410 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: Memory allocation of 0x%x bytes failed.\n", 1<<UMEM_SIZE);
411 return (0);
c422ecc7 412 }
c422ecc7 413 if (write)
cee68738
FF
414 {
415 memcpy (State.umem[startsegment]+startoffset, buffer, size);
416 }
c422ecc7 417 else
cee68738
FF
418 {
419 memcpy (buffer, State.umem[startsegment]+startoffset, size);
420 }
c422ecc7 421 }
cee68738 422 else if ((addr | 0x0003ffff) == 0x0103ffff)
c422ecc7 423 {
cee68738
FF
424 /* INSTRUCTION MEMORY (0x01000000 - 0x0103ffff) */
425 addr &= ((1 << IMEM_SIZE) - 1);
426 if ((addr + size) > (1 << IMEM_SIZE))
c422ecc7 427 {
cee68738
FF
428 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: instruction address 0x%x is outside range 0-0x%x.\n",
429 addr + size - 1, (1 << IMEM_SIZE) - 1);
430 return (0);
c422ecc7
MH
431 }
432 if (write)
cee68738
FF
433 {
434 memcpy (State.imem+addr, buffer, size);
435 }
c422ecc7 436 else
cee68738
FF
437 {
438 memcpy (buffer, State.imem+addr, size);
439 }
c422ecc7 440 }
cee68738 441 else if ((addr | 0x0000ffff) == 0x0200ffff)
c422ecc7 442 {
cee68738
FF
443 /* DATA MEMORY (0x02000000 - 0x0200ffff) */
444 addr &= ((1 << DMEM_SIZE) - 1);
445 if ((addr + size) > (1 << DMEM_SIZE))
c422ecc7 446 {
cee68738
FF
447 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: data address 0x%x is outside range 0-0x%x.\n",
448 addr + size - 1, (1 << DMEM_SIZE) - 1);
449 return (0);
c422ecc7
MH
450 }
451 if (write)
cee68738
FF
452 {
453 memcpy (State.dmem+addr, buffer, size);
454 }
c422ecc7 455 else
cee68738
FF
456 {
457 memcpy (buffer, State.dmem+addr, size);
458 }
c422ecc7 459 }
cee68738 460 else
c422ecc7
MH
461 {
462 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: address 0x%x is not in valid range\n",addr);
cee68738
FF
463 (*d10v_callback->printf_filtered) (d10v_callback, "Unified memory addresses are 0x00000000 - 0x00ffffff\n");
464 (*d10v_callback->printf_filtered) (d10v_callback, "Instruction addresses are 0x01000000 - 0x0103ffff\n");
465 (*d10v_callback->printf_filtered) (d10v_callback, "Data addresses are 0x02000000 - 0x0200ffff\n");
466 return (0);
c422ecc7 467 }
57bc1a72 468
2934d1c9
MH
469 return size;
470}
471
c422ecc7 472
9e03a68f
AC
473static int
474sim_write_phys (sd, addr, buffer, size)
475 SIM_DESC sd;
476 SIM_ADDR addr;
477 unsigned char *buffer;
478 int size;
479{
480 return xfer_mem( addr, buffer, size, 1);
481}
482
c422ecc7 483int
04885cc3
DE
484sim_write (sd, addr, buffer, size)
485 SIM_DESC sd;
c422ecc7
MH
486 SIM_ADDR addr;
487 unsigned char *buffer;
488 int size;
489{
9e03a68f 490 /* FIXME: this should be performing a virtual transfer */
c422ecc7
MH
491 return xfer_mem( addr, buffer, size, 1);
492}
493
494int
04885cc3
DE
495sim_read (sd, addr, buffer, size)
496 SIM_DESC sd;
c422ecc7
MH
497 SIM_ADDR addr;
498 unsigned char *buffer;
499 int size;
500{
9e03a68f 501 /* FIXME: this should be performing a virtual transfer */
c422ecc7
MH
502 return xfer_mem( addr, buffer, size, 0);
503}
504
505
04885cc3 506SIM_DESC
247fccde 507sim_open (kind, callback, abfd, argv)
04885cc3 508 SIM_OPEN_KIND kind;
247fccde
AC
509 host_callback *callback;
510 struct _bfd *abfd;
04885cc3 511 char **argv;
2934d1c9
MH
512{
513 struct simops *s;
aeb1f26b 514 struct hash_entry *h;
1eaaf305 515 static int init_p = 0;
04885cc3
DE
516 char **p;
517
518 sim_kind = kind;
247fccde 519 d10v_callback = callback;
04885cc3 520 myname = argv[0];
1eaaf305 521
04885cc3 522 for (p = argv + 1; *p; ++p)
1eaaf305
MM
523 {
524#ifdef DEBUG
04885cc3 525 if (strcmp (*p, "-t") == 0)
1eaaf305
MM
526 d10v_debug = DEBUG;
527 else
528#endif
04885cc3 529 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: unsupported option(s): %s\n",*p);
1eaaf305 530 }
c422ecc7 531
2934d1c9 532 /* put all the opcodes in the hash table */
1eaaf305 533 if (!init_p++)
2934d1c9 534 {
1eaaf305 535 for (s = Simops; s->func; s++)
2934d1c9 536 {
1eaaf305
MM
537 h = &hash_table[hash(s->opcode,s->format)];
538
539 /* go to the last entry in the chain */
540 while (h->next)
541 h = h->next;
542
543 if (h->ops)
544 {
04885cc3
DE
545 h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry));
546 if (!h->next)
547 perror ("malloc failure");
548
1eaaf305
MM
549 h = h->next;
550 }
551 h->ops = s;
552 h->mask = s->mask;
553 h->opcode = s->opcode;
cee402dd 554 h->size = s->is_long;
2934d1c9 555 }
2934d1c9 556 }
04885cc3
DE
557
558 /* Fudge our descriptor. */
559 return (SIM_DESC) 1;
2934d1c9
MH
560}
561
562
563void
04885cc3
DE
564sim_close (sd, quitting)
565 SIM_DESC sd;
2934d1c9
MH
566 int quitting;
567{
04885cc3 568 if (prog_bfd != NULL && prog_bfd_was_opened_p)
cee68738
FF
569 {
570 bfd_close (prog_bfd);
571 prog_bfd = NULL;
572 prog_bfd_was_opened_p = 0;
573 }
2934d1c9
MH
574}
575
576void
577sim_set_profile (n)
578 int n;
579{
7eebfc62 580 (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile %d\n",n);
2934d1c9
MH
581}
582
583void
584sim_set_profile_size (n)
585 int n;
586{
7eebfc62 587 (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile_size %d\n",n);
2934d1c9
MH
588}
589
c422ecc7
MH
590
591uint8 *
592dmem_addr( addr )
593 uint32 addr;
594{
595 int seg;
596
597 addr &= 0xffff;
598
599 if (addr > 0xbfff)
600 {
601 if ( (addr & 0xfff0) != 0xff00)
04885cc3
DE
602 {
603 (*d10v_callback->printf_filtered) (d10v_callback, "Data address 0x%lx is in I/O space, pc = 0x%lx.\n",
604 (long)addr, (long)decode_pc ());
605 State.exception = SIGBUS;
606 }
607
c422ecc7
MH
608 return State.dmem + addr;
609 }
610
611 if (addr > 0x7fff)
612 {
613 if (DMAP & 0x1000)
614 {
615 /* instruction memory */
616 return (DMAP & 0xf) * 0x4000 + State.imem;
617 }
618 /* unified memory */
619 /* this is ugly because we allocate unified memory in 128K segments and */
620 /* dmap addresses 16k segments */
cee402dd 621 seg = (DMAP & 0x3ff) >> 3;
c422ecc7
MH
622 if (State.umem[seg] == NULL)
623 {
b30cdd35
MM
624 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: unified memory region %d unmapped, pc = 0x%lx\n",
625 seg, (long)decode_pc ());
04885cc3 626 State.exception = SIGBUS;
c422ecc7 627 }
cee402dd 628 return State.umem[seg] + (DMAP & 7) * 0x4000;
c422ecc7
MH
629 }
630
631 return State.dmem + addr;
632}
633
634
635static uint8 *
636pc_addr()
637{
638 uint32 pc = ((uint32)PC) << 2;
639 uint16 imap;
640
641 if (pc & 0x20000)
642 imap = IMAP1;
643 else
644 imap = IMAP0;
645
646 if (imap & 0x1000)
647 return State.imem + pc;
648
649 if (State.umem[imap & 0xff] == NULL)
650 {
b30cdd35
MM
651 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: unified memory region %d unmapped, pc = 0x%lx\n",
652 imap & 0xff, (long)PC);
04885cc3 653 State.exception = SIGBUS;
c422ecc7
MH
654 return 0;
655 }
656
9e03a68f
AC
657 /* Discard upper bit(s) of PC in case IMAP1 selects unified memory. */
658 pc &= (1 << UMEM_SIZE) - 1;
659
c422ecc7
MH
660 return State.umem[imap & 0xff] + pc;
661}
662
663
193e528c 664static int stop_simulator = 0;
cee402dd 665
8517f62b
AC
666int
667sim_stop (sd)
668 SIM_DESC sd;
669{
670 stop_simulator = 1;
671 return 1;
672}
673
674
cee402dd 675/* Run (or resume) the program. */
2934d1c9 676void
04885cc3
DE
677sim_resume (sd, step, siggnal)
678 SIM_DESC sd;
2934d1c9
MH
679 int step, siggnal;
680{
681 uint32 inst;
cee68738 682 int do_iba;
2934d1c9 683
7eebfc62 684/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_resume (%d,%d) PC=0x%x\n",step,siggnal,PC); */
eca43eb1 685 State.exception = 0;
193e528c
FF
686 if (step)
687 sim_stop (sd);
cee402dd 688
aeb1f26b
MM
689 do
690 {
c422ecc7 691 inst = get_longword( pc_addr() );
cee402dd 692 State.pc_changed = 0;
c422ecc7 693 ins_type_counters[ (int)INS_CYCLES ]++;
cee68738
FF
694
695 /* check to see if IBA should be triggered after
696 this instruction */
697 if (State.DB && (PC == IBA))
698 do_iba = 1;
699 else
700 do_iba = 0;
701
c422ecc7 702 switch (inst & 0xC0000000)
aeb1f26b 703 {
c422ecc7
MH
704 case 0xC0000000:
705 /* long instruction */
706 do_long (inst & 0x3FFFFFFF);
707 break;
708 case 0x80000000:
709 /* R -> L */
193e528c 710 do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, RIGHT_FIRST);
c422ecc7
MH
711 break;
712 case 0x40000000:
713 /* L -> R */
193e528c 714 do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, LEFT_FIRST);
c422ecc7
MH
715 break;
716 case 0:
717 do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF);
718 break;
aeb1f26b 719 }
c422ecc7 720
193e528c
FF
721 /* calculate the next PC */
722 if (!State.pc_changed)
aeb1f26b 723 {
193e528c 724 if (State.RP && PC == RPT_E)
9e03a68f 725 {
193e528c
FF
726 /* Note: The behavour of a branch instruction at RPT_E
727 is implementation dependant, this simulator takes the
728 branch. Branching to RPT_E is valid, the instruction
729 must be executed before the loop is taken. */
730 RPT_C -= 1;
731 if (RPT_C == 0)
732 {
733 State.RP = 0;
734 PC++;
735 }
736 else
737 PC = RPT_S;
9e03a68f 738 }
c422ecc7 739 else
193e528c 740 PC++;
aeb1f26b 741 }
cee68738
FF
742
743 if (do_iba)
744 {
745 BPC = PC;
746 move_to_cr (BPSW_CR, PSW);
747 move_to_cr (PSW_CR, PSW & PSW_SM_BIT);
748 PC = SDBT_VECTOR_START;
749 }
193e528c 750 }
cee402dd 751 while ( !State.exception && !stop_simulator);
c422ecc7 752
aeb1f26b
MM
753 if (step && !State.exception)
754 State.exception = SIGTRAP;
2934d1c9
MH
755}
756
757int
04885cc3
DE
758sim_trace (sd)
759 SIM_DESC sd;
2934d1c9 760{
7eebfc62
MM
761#ifdef DEBUG
762 d10v_debug = DEBUG;
763#endif
04885cc3 764 sim_resume (sd, 0, 0);
7eebfc62 765 return 1;
2934d1c9
MH
766}
767
768void
04885cc3
DE
769sim_info (sd, verbose)
770 SIM_DESC sd;
2934d1c9
MH
771 int verbose;
772{
aeb1f26b
MM
773 char buf1[40];
774 char buf2[40];
775 char buf3[40];
776 char buf4[40];
777 char buf5[40];
778 unsigned long left = ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_COND_EXE ];
779 unsigned long left_nops = ins_type_counters[ (int)INS_LEFT_NOPS ];
780 unsigned long left_parallel = ins_type_counters[ (int)INS_LEFT_PARALLEL ];
781 unsigned long left_cond = ins_type_counters[ (int)INS_LEFT_COND_TEST ];
782 unsigned long left_total = left + left_parallel + left_cond + left_nops;
783
784 unsigned long right = ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_COND_EXE ];
785 unsigned long right_nops = ins_type_counters[ (int)INS_RIGHT_NOPS ];
786 unsigned long right_parallel = ins_type_counters[ (int)INS_RIGHT_PARALLEL ];
787 unsigned long right_cond = ins_type_counters[ (int)INS_RIGHT_COND_TEST ];
788 unsigned long right_total = right + right_parallel + right_cond + right_nops;
789
790 unsigned long unknown = ins_type_counters[ (int)INS_UNKNOWN ];
791 unsigned long ins_long = ins_type_counters[ (int)INS_LONG ];
c422ecc7
MH
792 unsigned long parallel = ins_type_counters[ (int)INS_PARALLEL ];
793 unsigned long leftright = ins_type_counters[ (int)INS_LEFTRIGHT ];
794 unsigned long rightleft = ins_type_counters[ (int)INS_RIGHTLEFT ];
aeb1f26b
MM
795 unsigned long cond_true = ins_type_counters[ (int)INS_COND_TRUE ];
796 unsigned long cond_false = ins_type_counters[ (int)INS_COND_FALSE ];
c422ecc7 797 unsigned long cond_jump = ins_type_counters[ (int)INS_COND_JUMP ];
aeb1f26b
MM
798 unsigned long cycles = ins_type_counters[ (int)INS_CYCLES ];
799 unsigned long total = (unknown + left_total + right_total + ins_long);
800
801 int size = strlen (add_commas (buf1, sizeof (buf1), total));
802 int parallel_size = strlen (add_commas (buf1, sizeof (buf1),
803 (left_parallel > right_parallel) ? left_parallel : right_parallel));
804 int cond_size = strlen (add_commas (buf1, sizeof (buf1), (left_cond > right_cond) ? left_cond : right_cond));
805 int nop_size = strlen (add_commas (buf1, sizeof (buf1), (left_nops > right_nops) ? left_nops : right_nops));
806 int normal_size = strlen (add_commas (buf1, sizeof (buf1), (left > right) ? left : right));
807
808 (*d10v_callback->printf_filtered) (d10v_callback,
c422ecc7 809 "executed %*s left instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n",
aeb1f26b
MM
810 size, add_commas (buf1, sizeof (buf1), left_total),
811 normal_size, add_commas (buf2, sizeof (buf2), left),
812 parallel_size, add_commas (buf3, sizeof (buf3), left_parallel),
813 cond_size, add_commas (buf4, sizeof (buf4), left_cond),
814 nop_size, add_commas (buf5, sizeof (buf5), left_nops));
815
816 (*d10v_callback->printf_filtered) (d10v_callback,
c422ecc7 817 "executed %*s right instruction(s), %*s normal, %*s parallel, %*s EXExxx, %*s nops\n",
aeb1f26b
MM
818 size, add_commas (buf1, sizeof (buf1), right_total),
819 normal_size, add_commas (buf2, sizeof (buf2), right),
820 parallel_size, add_commas (buf3, sizeof (buf3), right_parallel),
821 cond_size, add_commas (buf4, sizeof (buf4), right_cond),
822 nop_size, add_commas (buf5, sizeof (buf5), right_nops));
823
c422ecc7
MH
824 if (ins_long)
825 (*d10v_callback->printf_filtered) (d10v_callback,
826 "executed %*s long instruction(s)\n",
827 size, add_commas (buf1, sizeof (buf1), ins_long));
828
829 if (parallel)
830 (*d10v_callback->printf_filtered) (d10v_callback,
831 "executed %*s parallel instruction(s)\n",
832 size, add_commas (buf1, sizeof (buf1), parallel));
833
834 if (leftright)
835 (*d10v_callback->printf_filtered) (d10v_callback,
836 "executed %*s instruction(s) encoded L->R\n",
837 size, add_commas (buf1, sizeof (buf1), leftright));
838
839 if (rightleft)
840 (*d10v_callback->printf_filtered) (d10v_callback,
841 "executed %*s instruction(s) encoded R->L\n",
842 size, add_commas (buf1, sizeof (buf1), rightleft));
7eebfc62 843
aeb1f26b
MM
844 if (unknown)
845 (*d10v_callback->printf_filtered) (d10v_callback,
c422ecc7 846 "executed %*s unknown instruction(s)\n",
aeb1f26b 847 size, add_commas (buf1, sizeof (buf1), unknown));
7eebfc62 848
c422ecc7
MH
849 if (cond_true)
850 (*d10v_callback->printf_filtered) (d10v_callback,
851 "executed %*s instruction(s) due to EXExxx condition being true\n",
852 size, add_commas (buf1, sizeof (buf1), cond_true));
7eebfc62 853
c422ecc7
MH
854 if (cond_false)
855 (*d10v_callback->printf_filtered) (d10v_callback,
856 "skipped %*s instruction(s) due to EXExxx condition being false\n",
857 size, add_commas (buf1, sizeof (buf1), cond_false));
858
859 if (cond_jump)
860 (*d10v_callback->printf_filtered) (d10v_callback,
861 "skipped %*s instruction(s) due to conditional branch succeeding\n",
862 size, add_commas (buf1, sizeof (buf1), cond_jump));
7eebfc62
MM
863
864 (*d10v_callback->printf_filtered) (d10v_callback,
c422ecc7 865 "executed %*s cycle(s)\n",
aeb1f26b 866 size, add_commas (buf1, sizeof (buf1), cycles));
7eebfc62
MM
867
868 (*d10v_callback->printf_filtered) (d10v_callback,
aeb1f26b
MM
869 "executed %*s total instructions\n",
870 size, add_commas (buf1, sizeof (buf1), total));
2934d1c9
MH
871}
872
04885cc3 873SIM_RC
fafce69a 874sim_create_inferior (sd, abfd, argv, env)
04885cc3 875 SIM_DESC sd;
fafce69a 876 struct _bfd *abfd;
2934d1c9
MH
877 char **argv;
878 char **env;
879{
fafce69a 880 bfd_vma start_address;
c422ecc7 881
57bc1a72 882 /* reset all state information */
c422ecc7
MH
883 memset (&State.regs, 0, (int)&State.imem - (int)&State.regs[0]);
884
57bc1a72 885 /* set PC */
fafce69a 886 if (abfd != NULL)
cee68738 887 start_address = bfd_get_start_address (abfd);
fafce69a
AC
888 else
889 start_address = 0xffc0 << 2;
890#ifdef DEBUG
891 if (d10v_debug)
892 (*d10v_callback->printf_filtered) (d10v_callback, "sim_create_inferior: PC=0x%lx\n", (long) start_address);
893#endif
2934d1c9 894 PC = start_address >> 2;
c422ecc7
MH
895
896 /* cpu resets imap0 to 0 and imap1 to 0x7f, but D10V-EVA board */
897 /* resets imap0 and imap1 to 0x1000. */
898
899 SET_IMAP0(0x1000);
900 SET_IMAP1(0x1000);
901 SET_DMAP(0);
04885cc3
DE
902
903 return SIM_RC_OK;
2934d1c9
MH
904}
905
906
2934d1c9 907void
247fccde 908sim_set_callbacks (p)
2934d1c9
MH
909 host_callback *p;
910{
87178dbd 911 d10v_callback = p;
2934d1c9
MH
912}
913
914void
04885cc3
DE
915sim_stop_reason (sd, reason, sigrc)
916 SIM_DESC sd;
2934d1c9
MH
917 enum sim_stop *reason;
918 int *sigrc;
919{
7eebfc62 920/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason: PC=0x%x\n",PC<<2); */
d70b4d42 921
a49a15ad 922 switch (State.exception)
d70b4d42 923 {
a49a15ad 924 case SIG_D10V_STOP: /* stop instruction */
d70b4d42 925 *reason = sim_exited;
a49a15ad
MM
926 *sigrc = 0;
927 break;
928
929 case SIG_D10V_EXIT: /* exit trap */
930 *reason = sim_exited;
931 *sigrc = State.regs[2];
932 break;
933
934 default: /* some signal */
d70b4d42 935 *reason = sim_stopped;
193e528c
FF
936 if (stop_simulator && !State.exception)
937 *sigrc = SIGINT;
938 else
939 *sigrc = State.exception;
a49a15ad 940 break;
193e528c
FF
941 }
942
943 stop_simulator = 0;
d70b4d42
MH
944}
945
946void
04885cc3
DE
947sim_fetch_register (sd, rn, memory)
948 SIM_DESC sd;
d70b4d42
MH
949 int rn;
950 unsigned char *memory;
951{
c422ecc7
MH
952 if (!State.imem)
953 init_system();
954
955 if (rn > 34)
5c839c67 956 WRITE_64 (memory, State.a[rn-35]);
c422ecc7
MH
957 else if (rn == 32)
958 WRITE_16 (memory, IMAP0);
959 else if (rn == 33)
960 WRITE_16 (memory, IMAP1);
961 else if (rn == 34)
962 WRITE_16 (memory, DMAP);
cee68738
FF
963 else if (rn >= 16)
964 WRITE_16 (memory, move_from_cr (rn - 16));
d70b4d42 965 else
c422ecc7 966 WRITE_16 (memory, State.regs[rn]);
d70b4d42
MH
967}
968
969void
04885cc3
DE
970sim_store_register (sd, rn, memory)
971 SIM_DESC sd;
d70b4d42
MH
972 int rn;
973 unsigned char *memory;
974{
c422ecc7
MH
975 if (!State.imem)
976 init_system();
977
978 if (rn > 34)
5c839c67 979 State.a[rn-35] = READ_64 (memory) & MASK40;
c422ecc7
MH
980 else if (rn == 34)
981 SET_DMAP( READ_16(memory) );
982 else if (rn == 33)
983 SET_IMAP1( READ_16(memory) );
984 else if (rn == 32)
985 SET_IMAP0( READ_16(memory) );
cee68738
FF
986 else if (rn >= 16)
987 move_to_cr (rn - 16, READ_16 (memory));
d70b4d42 988 else
c422ecc7 989 State.regs[rn]= READ_16 (memory);
2934d1c9 990}
d70b4d42 991
d70b4d42
MH
992
993void
04885cc3
DE
994sim_do_command (sd, cmd)
995 SIM_DESC sd;
d70b4d42
MH
996 char *cmd;
997{
7eebfc62 998 (*d10v_callback->printf_filtered) (d10v_callback, "sim_do_command: %s\n",cmd);
d70b4d42
MH
999}
1000
04885cc3
DE
1001SIM_RC
1002sim_load (sd, prog, abfd, from_tty)
1003 SIM_DESC sd;
d70b4d42 1004 char *prog;
04885cc3 1005 bfd *abfd;
d70b4d42
MH
1006 int from_tty;
1007{
04885cc3
DE
1008 extern bfd *sim_load_file (); /* ??? Don't know where this should live. */
1009
1010 if (prog_bfd != NULL && prog_bfd_was_opened_p)
cee68738
FF
1011 {
1012 bfd_close (prog_bfd);
1013 prog_bfd_was_opened_p = 0;
1014 }
04885cc3 1015 prog_bfd = sim_load_file (sd, myname, d10v_callback, prog, abfd,
9e03a68f
AC
1016 sim_kind == SIM_OPEN_DEBUG,
1017 0, sim_write_phys);
04885cc3
DE
1018 if (prog_bfd == NULL)
1019 return SIM_RC_FAIL;
04885cc3
DE
1020 prog_bfd_was_opened_p = abfd == NULL;
1021 return SIM_RC_OK;
d70b4d42 1022}