Provide better statistics, particularly for doing VLIW work; Fix ldb to correctly...
[deliverable/binutils-gdb.git] / sim / d10v / interp.c
1 #include <signal.h>
2 #include "sysdep.h"
3 #include "bfd.h"
4 #include "remote-sim.h"
5
6 #include "d10v_sim.h"
7
8 #define IMEM_SIZE 18 /* D10V instruction memory size is 18 bits */
9 #define DMEM_SIZE 16 /* Data memory */
10
11 enum _leftright { LEFT_FIRST, RIGHT_FIRST };
12
13 int d10v_debug;
14 host_callback *d10v_callback;
15 unsigned long ins_type_counters[ (int)INS_MAX ];
16
17 uint16 OP[4];
18
19 static long hash PARAMS ((long insn, int format));
20 static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size));
21 static void get_operands PARAMS ((struct simops *s, uint32 ins));
22 static void do_long PARAMS ((uint32 ins));
23 static void do_2_short PARAMS ((uint16 ins1, uint16 ins2, enum _leftright leftright));
24 static void do_parallel PARAMS ((uint16 ins1, uint16 ins2));
25 static char *add_commas PARAMS ((char *buf, int sizeof_buf, unsigned long value));
26 extern void sim_size PARAMS ((int power));
27 static void init_system PARAMS ((void));
28 extern int sim_write PARAMS ((SIM_ADDR addr, unsigned char *buffer, int size));
29 extern void sim_open PARAMS ((char *args));
30 extern void sim_close PARAMS ((int quitting));
31 extern void sim_set_profile PARAMS ((int n));
32 extern void sim_set_profile_size PARAMS ((int n));
33 extern void sim_resume PARAMS ((int step, int siggnal));
34 extern void sim_info PARAMS ((int verbose));
35 extern void sim_create_inferior PARAMS ((SIM_ADDR start_address, char **argv, char **env));
36 extern void sim_kill PARAMS ((void));
37 extern void sim_set_callbacks PARAMS ((host_callback *p));
38 extern void sim_stop_reason PARAMS ((enum sim_stop *reason, int *sigrc));
39 extern void sim_fetch_register PARAMS ((int rn, unsigned char *memory));
40 extern void sim_store_register PARAMS ((int rn, unsigned char *memory));
41 extern int sim_read PARAMS ((SIM_ADDR addr, unsigned char *buffer, int size));
42 extern void sim_do_command PARAMS ((char *cmd));
43
44 #ifndef INLINE
45 #if defined(__GNUC__) && defined(__OPTIMIZE__)
46 #define INLINE __inline__
47 #else
48 #define INLINE
49 #endif
50 #endif
51
52 #define MAX_HASH 63
53 struct hash_entry
54 {
55 struct hash_entry *next;
56 long opcode;
57 long mask;
58 struct simops *ops;
59 };
60
61 struct hash_entry hash_table[MAX_HASH+1];
62
63 INLINE static long
64 hash(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
74 INLINE static struct hash_entry *
75 lookup_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
86 while ((ins & h->mask) != h->opcode)
87 {
88 if (h->next == NULL)
89 {
90 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR looking up hash for %x at PC %x\n",ins, PC);
91 exit (1);
92 }
93 h = h->next;
94 }
95 return (h);
96 }
97
98 INLINE static void
99 get_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
113 static void
114 do_long (ins)
115 uint32 ins;
116 {
117 struct hash_entry *h;
118 #ifdef DEBUG
119 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
120 (*d10v_callback->printf_filtered) (d10v_callback, "do_long 0x%x\n", ins);
121 #endif
122 h = lookup_hash (ins, 1);
123 get_operands (h->ops, ins);
124 State.ins_type = INS_LONG;
125 ins_type_counters[ (int)State.ins_type ]++;
126 (h->ops->func)();
127 }
128
129 static void
130 do_2_short (ins1, ins2, leftright)
131 uint16 ins1, ins2;
132 enum _leftright leftright;
133 {
134 struct hash_entry *h;
135 reg_t orig_pc = PC;
136
137 #ifdef DEBUG
138 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
139 (*d10v_callback->printf_filtered) (d10v_callback, "do_2_short 0x%x (%s) -> 0x%x\n",
140 ins1, (leftright) ? "left" : "right", ins2);
141 #endif
142 /* printf ("do_2_short %x -> %x\n",ins1,ins2); */
143 h = lookup_hash (ins1, 0);
144 get_operands (h->ops, ins1);
145 State.ins_type = (leftright == LEFT_FIRST) ? INS_LEFT : INS_RIGHT;
146 ins_type_counters[ (int)State.ins_type ]++;
147 (h->ops->func)();
148
149 /* If the PC has changed (ie, a jump), don't do the second instruction */
150 if (orig_pc == PC && !State.exception)
151 {
152 h = lookup_hash (ins2, 0);
153 get_operands (h->ops, ins2);
154 State.ins_type = (leftright == LEFT_FIRST) ? INS_RIGHT : INS_LEFT;
155 ins_type_counters[ (int)State.ins_type ]++;
156 (h->ops->func)();
157 }
158 }
159
160 static void
161 do_parallel (ins1, ins2)
162 uint16 ins1, ins2;
163 {
164 struct hash_entry *h1, *h2;
165 #ifdef DEBUG
166 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
167 (*d10v_callback->printf_filtered) (d10v_callback, "do_parallel 0x%x || 0x%x\n", ins1, ins2);
168 #endif
169 h1 = lookup_hash (ins1, 0);
170 h2 = lookup_hash (ins2, 0);
171
172 if (h1->ops->exec_type == PARONLY)
173 {
174 get_operands (h1->ops, ins1);
175 State.ins_type = INS_LEFT_COND_TEST;
176 ins_type_counters[ (int)State.ins_type ]++;
177 (h1->ops->func)();
178 if (State.exe)
179 {
180 ins_type_counters[ (int)INS_COND_TRUE ]++;
181 get_operands (h2->ops, ins2);
182 State.ins_type = INS_RIGHT_COND_EXE;
183 ins_type_counters[ (int)State.ins_type ]++;
184 (h2->ops->func)();
185 }
186 else
187 ins_type_counters[ (int)INS_COND_FALSE ]++;
188 }
189 else if (h2->ops->exec_type == PARONLY)
190 {
191 get_operands (h2->ops, ins2);
192 State.ins_type = INS_RIGHT_COND_TEST;
193 ins_type_counters[ (int)State.ins_type ]++;
194 (h2->ops->func)();
195 if (State.exe)
196 {
197 ins_type_counters[ (int)INS_COND_TRUE ]++;
198 get_operands (h1->ops, ins1);
199 State.ins_type = INS_LEFT_COND_EXE;
200 ins_type_counters[ (int)State.ins_type ]++;
201 (h1->ops->func)();
202 }
203 else
204 ins_type_counters[ (int)INS_COND_FALSE ]++;
205 }
206 else
207 {
208 get_operands (h1->ops, ins1);
209 State.ins_type = INS_LEFT_PARALLEL;
210 ins_type_counters[ (int)State.ins_type ]++;
211 (h1->ops->func)();
212 if (!State.exception)
213 {
214 get_operands (h2->ops, ins2);
215 State.ins_type = INS_RIGHT_PARALLEL;
216 ins_type_counters[ (int)State.ins_type ]++;
217 (h2->ops->func)();
218 }
219 }
220 }
221
222 static char *
223 add_commas(buf, sizeof_buf, value)
224 char *buf;
225 int sizeof_buf;
226 unsigned long value;
227 {
228 int comma = 3;
229 char *endbuf = buf + sizeof_buf - 1;
230
231 *--endbuf = '\0';
232 do {
233 if (comma-- == 0)
234 {
235 *--endbuf = ',';
236 comma = 2;
237 }
238
239 *--endbuf = (value % 10) + '0';
240 } while ((value /= 10) != 0);
241
242 return endbuf;
243 }
244
245 void
246 sim_size (power)
247 int power;
248
249 {
250 if (State.imem)
251 {
252 free (State.imem);
253 free (State.dmem);
254 }
255
256 State.imem = (uint8 *)calloc(1,1<<IMEM_SIZE);
257 State.dmem = (uint8 *)calloc(1,1<<DMEM_SIZE);
258 if (!State.imem || !State.dmem )
259 {
260 (*d10v_callback->printf_filtered) (d10v_callback, "Memory allocation failed.\n");
261 exit(1);
262 }
263
264 State.mem_min = 1<<IMEM_SIZE;
265 State.mem_max = 0;
266
267 #ifdef DEBUG
268 if ((d10v_debug & DEBUG_MEMSIZE) != 0)
269 {
270 char buffer[20];
271 (*d10v_callback->printf_filtered) (d10v_callback,
272 "Allocated %s bytes instruction memory and\n",
273 add_commas (buffer, sizeof (buffer), (1UL<<IMEM_SIZE)));
274
275 (*d10v_callback->printf_filtered) (d10v_callback, " %s bytes data memory.\n",
276 add_commas (buffer, sizeof (buffer), (1UL<<IMEM_SIZE)));
277 }
278 #endif
279 }
280
281 static void
282 init_system ()
283 {
284 if (!State.imem)
285 sim_size(1);
286 }
287
288 int
289 sim_write (addr, buffer, size)
290 SIM_ADDR addr;
291 unsigned char *buffer;
292 int size;
293 {
294 init_system ();
295
296 #ifdef DEBUG
297 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
298 (*d10v_callback->printf_filtered) (d10v_callback, "sim_write %d bytes to 0x%x, min = 0x%x, max = 0x%x\n",
299 size, addr, State.mem_min, State.mem_max);
300 #endif
301
302 if (State.mem_min > addr)
303 State.mem_min = addr;
304
305 if (State.mem_max < addr+size-1)
306 State.mem_max = addr+size-1;
307
308 memcpy (State.imem+addr, buffer, size);
309 return size;
310 }
311
312 void
313 sim_open (args)
314 char *args;
315 {
316 struct simops *s;
317 struct hash_entry *h;
318 static int init_p = 0;
319
320 if (args != NULL)
321 {
322 #ifdef DEBUG
323 if (strcmp (args, "-t") == 0)
324 d10v_debug = DEBUG;
325 else
326 #endif
327 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: unsupported option(s): %s\n",args);
328 }
329
330 /* put all the opcodes in the hash table */
331 if (!init_p++)
332 {
333 for (s = Simops; s->func; s++)
334 {
335 h = &hash_table[hash(s->opcode,s->format)];
336
337 /* go to the last entry in the chain */
338 while (h->next)
339 h = h->next;
340
341 if (h->ops)
342 {
343 h->next = calloc(1,sizeof(struct hash_entry));
344 h = h->next;
345 }
346 h->ops = s;
347 h->mask = s->mask;
348 h->opcode = s->opcode;
349 }
350 }
351 }
352
353
354 void
355 sim_close (quitting)
356 int quitting;
357 {
358 /* nothing to do */
359 }
360
361 void
362 sim_set_profile (n)
363 int n;
364 {
365 (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile %d\n",n);
366 }
367
368 void
369 sim_set_profile_size (n)
370 int n;
371 {
372 (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile_size %d\n",n);
373 }
374
375 void
376 sim_resume (step, siggnal)
377 int step, siggnal;
378 {
379 uint32 inst;
380 reg_t oldpc = 0;
381
382 /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_resume (%d,%d) PC=0x%x\n",step,siggnal,PC); */
383
384 State.exception = 0;
385 do
386 {
387 uint32 byte_pc = ((uint32)PC) << 2;
388 if ((byte_pc < State.mem_min) || (byte_pc > State.mem_max))
389 {
390 (*d10v_callback->printf_filtered) (d10v_callback,
391 "PC (0x%lx) out of range, oldpc = 0x%lx, min = 0x%lx, max = 0x%lx\n",
392 (long)byte_pc, (long)oldpc, (long)State.mem_min, (long)State.mem_max);
393 State.exception = SIGILL;
394 }
395 else
396 {
397 inst = RLW (byte_pc);
398 oldpc = PC;
399 ins_type_counters[ (int)INS_CYCLES ]++;
400 switch (inst & 0xC0000000)
401 {
402 case 0xC0000000:
403 /* long instruction */
404 do_long (inst & 0x3FFFFFFF);
405 break;
406 case 0x80000000:
407 /* R -> L */
408 do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, 0);
409 break;
410 case 0x40000000:
411 /* L -> R */
412 do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, 1);
413 break;
414 case 0:
415 do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF);
416 break;
417 }
418
419 if (State.RP && PC == RPT_E)
420 {
421 RPT_C -= 1;
422 if (RPT_C == 0)
423 State.RP = 0;
424 else
425 PC = RPT_S;
426 }
427
428 /* FIXME */
429 if (PC == oldpc)
430 PC++;
431 }
432 }
433 while ( !State.exception && !step);
434
435 if (step && !State.exception)
436 State.exception = SIGTRAP;
437 }
438
439 int
440 sim_trace ()
441 {
442 #ifdef DEBUG
443 d10v_debug = DEBUG;
444 #endif
445 sim_resume (0, 0);
446 return 1;
447 }
448
449 void
450 sim_info (verbose)
451 int verbose;
452 {
453 char buf1[40];
454 char buf2[40];
455 char buf3[40];
456 char buf4[40];
457 char buf5[40];
458 unsigned long left = ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_COND_EXE ];
459 unsigned long left_nops = ins_type_counters[ (int)INS_LEFT_NOPS ];
460 unsigned long left_parallel = ins_type_counters[ (int)INS_LEFT_PARALLEL ];
461 unsigned long left_cond = ins_type_counters[ (int)INS_LEFT_COND_TEST ];
462 unsigned long left_total = left + left_parallel + left_cond + left_nops;
463
464 unsigned long right = ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_COND_EXE ];
465 unsigned long right_nops = ins_type_counters[ (int)INS_RIGHT_NOPS ];
466 unsigned long right_parallel = ins_type_counters[ (int)INS_RIGHT_PARALLEL ];
467 unsigned long right_cond = ins_type_counters[ (int)INS_RIGHT_COND_TEST ];
468 unsigned long right_total = right + right_parallel + right_cond + right_nops;
469
470 unsigned long unknown = ins_type_counters[ (int)INS_UNKNOWN ];
471 unsigned long ins_long = ins_type_counters[ (int)INS_LONG ];
472 unsigned long cond_true = ins_type_counters[ (int)INS_COND_TRUE ];
473 unsigned long cond_false = ins_type_counters[ (int)INS_COND_FALSE ];
474 unsigned long cycles = ins_type_counters[ (int)INS_CYCLES ];
475 unsigned long total = (unknown + left_total + right_total + ins_long);
476
477 int size = strlen (add_commas (buf1, sizeof (buf1), total));
478 int parallel_size = strlen (add_commas (buf1, sizeof (buf1),
479 (left_parallel > right_parallel) ? left_parallel : right_parallel));
480 int cond_size = strlen (add_commas (buf1, sizeof (buf1), (left_cond > right_cond) ? left_cond : right_cond));
481 int nop_size = strlen (add_commas (buf1, sizeof (buf1), (left_nops > right_nops) ? left_nops : right_nops));
482 int normal_size = strlen (add_commas (buf1, sizeof (buf1), (left > right) ? left : right));
483
484 (*d10v_callback->printf_filtered) (d10v_callback,
485 "executed %*s left instructions, %*s normal, %*s parallel, %*s EXExxx, %*s nops\n",
486 size, add_commas (buf1, sizeof (buf1), left_total),
487 normal_size, add_commas (buf2, sizeof (buf2), left),
488 parallel_size, add_commas (buf3, sizeof (buf3), left_parallel),
489 cond_size, add_commas (buf4, sizeof (buf4), left_cond),
490 nop_size, add_commas (buf5, sizeof (buf5), left_nops));
491
492 (*d10v_callback->printf_filtered) (d10v_callback,
493 "executed %*s right instructions, %*s normal, %*s parallel, %*s EXExxx, %*s nops\n",
494 size, add_commas (buf1, sizeof (buf1), right_total),
495 normal_size, add_commas (buf2, sizeof (buf2), right),
496 parallel_size, add_commas (buf3, sizeof (buf3), right_parallel),
497 cond_size, add_commas (buf4, sizeof (buf4), right_cond),
498 nop_size, add_commas (buf5, sizeof (buf5), right_nops));
499
500 (*d10v_callback->printf_filtered) (d10v_callback,
501 "executed %*s long instructions\n",
502 size, add_commas (buf1, sizeof (buf1), ins_long));
503
504 if (unknown)
505 (*d10v_callback->printf_filtered) (d10v_callback,
506 "executed %*s unknown instructions\n",
507 size, add_commas (buf1, sizeof (buf1), unknown));
508
509 (*d10v_callback->printf_filtered) (d10v_callback,
510 "executed %*s instructions conditionally\n",
511 size, add_commas (buf1, sizeof (buf1), cond_true));
512
513 (*d10v_callback->printf_filtered) (d10v_callback,
514 "skipped %*s instructions due to conditional failure\n",
515 size, add_commas (buf1, sizeof (buf1), cond_false));
516
517 (*d10v_callback->printf_filtered) (d10v_callback,
518 "executed %*s cycles\n",
519 size, add_commas (buf1, sizeof (buf1), cycles));
520
521 (*d10v_callback->printf_filtered) (d10v_callback,
522 "executed %*s total instructions\n",
523 size, add_commas (buf1, sizeof (buf1), total));
524 }
525
526 void
527 sim_create_inferior (start_address, argv, env)
528 SIM_ADDR start_address;
529 char **argv;
530 char **env;
531 {
532 uint8 *imem, *dmem;
533 uint32 mem_min, mem_max;
534 #ifdef DEBUG
535 if (d10v_debug)
536 (*d10v_callback->printf_filtered) (d10v_callback, "sim_create_inferior: PC=0x%x\n", start_address);
537 #endif
538 /* save memory pointers */
539 imem = State.imem;
540 dmem = State.dmem;
541 mem_min = State.mem_min;
542 mem_max = State.mem_max;
543 /* reset all state information */
544 memset (&State, 0, sizeof(State));
545 /* restore memory pointers */
546 State.imem = imem;
547 State.dmem = dmem;
548 State.mem_min = mem_min;
549 State.mem_max = mem_max;
550 /* set PC */
551 PC = start_address >> 2;
552 }
553
554
555 void
556 sim_kill ()
557 {
558 /* nothing to do */
559 }
560
561 void
562 sim_set_callbacks(p)
563 host_callback *p;
564 {
565 /* printf ("sim_set_callbacks\n"); */
566 d10v_callback = p;
567 }
568
569 void
570 sim_stop_reason (reason, sigrc)
571 enum sim_stop *reason;
572 int *sigrc;
573 {
574 /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason: PC=0x%x\n",PC<<2); */
575
576 switch (State.exception)
577 {
578 case SIG_D10V_STOP: /* stop instruction */
579 *reason = sim_exited;
580 *sigrc = 0;
581 break;
582
583 case SIG_D10V_EXIT: /* exit trap */
584 *reason = sim_exited;
585 *sigrc = State.regs[2];
586 break;
587
588 default: /* some signal */
589 *reason = sim_stopped;
590 *sigrc = State.exception;
591 break;
592 }
593 }
594
595 void
596 sim_fetch_register (rn, memory)
597 int rn;
598 unsigned char *memory;
599 {
600 if (rn > 31)
601 {
602 WRITE_64 (memory, State.a[rn-32]);
603 /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%llx\n",rn,State.a[rn-32]); */
604 }
605 else
606 {
607 WRITE_16 (memory, State.regs[rn]);
608 /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%x\n",rn,State.regs[rn]); */
609 }
610 }
611
612 void
613 sim_store_register (rn, memory)
614 int rn;
615 unsigned char *memory;
616 {
617 if (rn > 31)
618 {
619 State.a[rn-32] = READ_64 (memory) & MASK40;
620 /* (*d10v_callback->printf_filtered) (d10v_callback, "store: a%d=0x%llx\n",rn-32,State.a[rn-32]); */
621 }
622 else
623 {
624 State.regs[rn]= READ_16 (memory);
625 /* (*d10v_callback->printf_filtered) (d10v_callback, "store: r%d=0x%x\n",rn,State.regs[rn]); */
626 }
627 }
628
629 int
630 sim_read (addr, buffer, size)
631 SIM_ADDR addr;
632 unsigned char *buffer;
633 int size;
634 {
635 int i;
636 for (i = 0; i < size; i++)
637 {
638 buffer[i] = State.imem[addr + i];
639 }
640 return size;
641 }
642
643 void
644 sim_do_command (cmd)
645 char *cmd;
646 {
647 (*d10v_callback->printf_filtered) (d10v_callback, "sim_do_command: %s\n",cmd);
648 }
649
650 int
651 sim_load (prog, from_tty)
652 char *prog;
653 int from_tty;
654 {
655 /* Return nonzero so GDB will handle it. */
656 return 1;
657 }
This page took 0.042322 seconds and 4 git commands to generate.