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