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