Mon Oct 21 16:16:26 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
[platform/upstream/binutils.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 long ins_type_counters[ (int)INS_MAX ];
16 long left_nops, right_nops;
17
18 uint16 OP[4];
19
20 static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size));
21
22 #define MAX_HASH  63
23 struct hash_entry
24 {
25   struct hash_entry *next;
26   long opcode;
27   long mask;
28   struct simops *ops;
29 };
30
31 struct hash_entry hash_table[MAX_HASH+1];
32
33 static long 
34 hash(insn, format)
35      long insn;
36      int format;
37 {
38   if (format & LONG_OPCODE)
39     return ((insn & 0x3F000000) >> 24);
40   else
41     return((insn & 0x7E00) >> 9);
42 }
43
44 static struct hash_entry *
45 lookup_hash (ins, size)
46      uint32 ins;
47      int size;
48 {
49   struct hash_entry *h;
50
51   if (size)
52     h = &hash_table[(ins & 0x3F000000) >> 24];
53   else
54     h = &hash_table[(ins & 0x7E00) >> 9];
55
56   while ( (ins & h->mask) != h->opcode)
57     {
58       if (h->next == NULL)
59         {
60           (*d10v_callback->printf_filtered) (d10v_callback, "ERROR looking up hash for %x at PC %x\n",ins, PC);
61           exit(1);
62         }
63       h = h->next;
64     }
65   return (h);
66 }
67
68 static void
69 get_operands (struct simops *s, uint32 ins)
70 {
71   int i, shift, bits, flags;
72   uint32 mask;
73   for (i=0; i < s->numops; i++)
74     {
75       shift = s->operands[3*i];
76       bits = s->operands[3*i+1];
77       flags = s->operands[3*i+2];
78       mask = 0x7FFFFFFF >> (31 - bits);
79       OP[i] = (ins >> shift) & mask;
80     }
81 }
82
83 static void
84 do_long (ins)
85      uint32 ins;
86 {
87   struct hash_entry *h;
88 #ifdef DEBUG
89   if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
90     (*d10v_callback->printf_filtered) (d10v_callback, "do_long 0x%x\n", ins);
91 #endif
92   h = lookup_hash (ins, 1);
93   get_operands (h->ops, ins);
94   State.ins_type = INS_LONG;
95   ins_type_counters[ (int)State.ins_type ]++;
96   (h->ops->func)();
97 }
98
99 static void
100 do_2_short (ins1, ins2, leftright)
101      uint16 ins1, ins2;
102      enum _leftright leftright;
103 {
104   struct hash_entry *h;
105   reg_t orig_pc = PC;
106
107 #ifdef DEBUG
108   if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
109     (*d10v_callback->printf_filtered) (d10v_callback, "do_2_short 0x%x (%s) -> 0x%x\n",
110                                        ins1, (leftright) ? "left" : "right", ins2);
111 #endif
112   /*  printf ("do_2_short %x -> %x\n",ins1,ins2); */
113   h = lookup_hash (ins1, 0);
114   get_operands (h->ops, ins1);
115   State.ins_type = (leftright == LEFT_FIRST) ? INS_LEFT : INS_RIGHT;
116   ins_type_counters[ (int)State.ins_type ]++;
117   (h->ops->func)();
118
119   /* If the PC has changed (ie, a jump), don't do the second instruction */
120   if (orig_pc == PC && !State.exception)
121     {
122       h = lookup_hash (ins2, 0);
123       get_operands (h->ops, ins2);
124       State.ins_type = (leftright == LEFT_FIRST) ? INS_RIGHT : INS_LEFT;
125       ins_type_counters[ (int)State.ins_type ]++;
126       (h->ops->func)();
127     }
128 }
129
130 static void
131 do_parallel (ins1, ins2)
132      uint16 ins1, ins2;
133 {
134   struct hash_entry *h1, *h2;
135 #ifdef DEBUG
136   if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
137     (*d10v_callback->printf_filtered) (d10v_callback, "do_parallel 0x%x || 0x%x\n", ins1, ins2);
138 #endif
139   h1 = lookup_hash (ins1, 0);
140   h2 = lookup_hash (ins2, 0);
141
142   if (h1->ops->exec_type == PARONLY)
143     {
144       get_operands (h1->ops, ins1);
145       State.ins_type = INS_LEFT;
146       ins_type_counters[ (int)State.ins_type ]++;
147       (h1->ops->func)();
148       if (State.exe)
149         {
150           get_operands (h2->ops, ins2);
151           State.ins_type = INS_RIGHT;
152           (h2->ops->func)();
153         }
154     }
155   else if (h2->ops->exec_type == PARONLY)
156     {
157       get_operands (h2->ops, ins2);
158       State.ins_type = INS_RIGHT;
159       ins_type_counters[ (int)State.ins_type ]++;
160       (h2->ops->func)();
161       if (State.exe)
162         {
163           get_operands (h1->ops, ins1);
164           State.ins_type = INS_LEFT;
165           (h1->ops->func)();
166         }
167     }
168   else
169     {
170       get_operands (h1->ops, ins1);
171       State.ins_type = INS_LEFT_PARALLEL;
172       ins_type_counters[ (int)State.ins_type ]++;
173       (h1->ops->func)();
174       if (!State.exception)
175         {
176           get_operands (h2->ops, ins2);
177           State.ins_type = INS_RIGHT_PARALLEL;
178           ins_type_counters[ (int)State.ins_type ]++;
179           (h2->ops->func)();
180         }
181     }
182 }
183  
184
185 void
186 sim_size (power)
187      int power;
188
189 {
190   if (State.imem)
191     {
192       free (State.imem);
193       free (State.dmem);
194     }
195
196   State.imem = (uint8 *)calloc(1,1<<IMEM_SIZE);
197   State.dmem = (uint8 *)calloc(1,1<<DMEM_SIZE);
198   if (!State.imem || !State.dmem )
199     {
200       (*d10v_callback->printf_filtered) (d10v_callback, "Memory allocation failed.\n");
201       exit(1);
202     }
203
204   State.mem_min = 1<<IMEM_SIZE;
205   State.mem_max = 0;
206
207 #ifdef DEBUG
208   if ((d10v_debug & DEBUG_MEMSIZE) != 0)
209     {
210       (*d10v_callback->printf_filtered) (d10v_callback, "Allocated %d bytes instruction memory and\n",1<<IMEM_SIZE);
211       (*d10v_callback->printf_filtered) (d10v_callback, "          %d bytes data memory.\n",          1<<DMEM_SIZE);
212     }
213 #endif
214 }
215
216 static void
217 init_system ()
218 {
219   if (!State.imem)
220     sim_size(1);
221 }
222
223 int
224 sim_write (addr, buffer, size)
225      SIM_ADDR addr;
226      unsigned char *buffer;
227      int size;
228 {
229   init_system ();
230
231 #ifdef DEBUG
232   if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
233     (*d10v_callback->printf_filtered) (d10v_callback, "sim_write %d bytes to 0x%x, min = 0x%x, max = 0x%x\n",
234                                        size, addr, State.mem_min, State.mem_max);
235 #endif
236
237   if (State.mem_min > addr)
238     State.mem_min = addr;
239
240   if (State.mem_max < addr+size-1)
241     State.mem_max = addr+size-1;
242
243   memcpy (State.imem+addr, buffer, size);
244   return size;
245 }
246
247 void
248 sim_open (args)
249      char *args;
250 {
251   struct simops *s;
252   struct hash_entry *h, *prev;
253   static int init_p = 0;
254
255   if (args != NULL)
256     {
257 #ifdef DEBUG
258       if (strcmp (args, "-t") == 0)
259         d10v_debug = DEBUG;
260       else
261 #endif
262         (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: unsupported option(s): %s\n",args);
263     }
264
265   /* put all the opcodes in the hash table */
266   if (!init_p++)
267     {
268       for (s = Simops; s->func; s++)
269         {
270           h = &hash_table[hash(s->opcode,s->format)];
271       
272           /* go to the last entry in the chain */
273           while (h->next)
274             h = h->next;
275
276           if (h->ops)
277             {
278               h->next = calloc(1,sizeof(struct hash_entry));
279               h = h->next;
280             }
281           h->ops = s;
282           h->mask = s->mask;
283           h->opcode = s->opcode;
284         }
285     }
286 }
287
288
289 void
290 sim_close (quitting)
291      int quitting;
292 {
293   /* nothing to do */
294 }
295
296 void
297 sim_set_profile (n)
298      int n;
299 {
300   (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile %d\n",n);
301 }
302
303 void
304 sim_set_profile_size (n)
305      int n;
306 {
307   (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile_size %d\n",n);
308 }
309
310 void
311 sim_resume (step, siggnal)
312      int step, siggnal;
313 {
314   uint32 inst;
315   int i;
316   reg_t oldpc;
317
318 /*   (*d10v_callback->printf_filtered) (d10v_callback, "sim_resume (%d,%d)  PC=0x%x\n",step,siggnal,PC); */
319
320   State.exception = 0;
321  do
322    {
323      uint32 byte_pc = ((uint32)PC) << 2;
324      if ((byte_pc < State.mem_min) || (byte_pc > State.mem_max))
325        {
326          (*d10v_callback->printf_filtered) (d10v_callback,
327                                             "PC (0x%lx) out of range, oldpc = 0x%lx, min = 0x%lx, max = 0x%lx\n",
328                                             (long)byte_pc, (long)oldpc, (long)State.mem_min, (long)State.mem_max);
329          State.exception = SIGILL;
330        }
331      else
332        {
333          inst = RLW (byte_pc); 
334          oldpc = PC;
335          switch (inst & 0xC0000000)
336            {
337            case 0xC0000000:
338              /* long instruction */
339              do_long (inst & 0x3FFFFFFF);
340              break;
341            case 0x80000000:
342              /* R -> L */
343              do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, 0);
344              break;
345            case 0x40000000:
346              /* L -> R */
347              do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, 1);
348              break;
349            case 0:
350              do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF);
351              break;
352            }
353      
354          if (State.RP && PC == RPT_E)
355            {
356              RPT_C -= 1;
357              if (RPT_C == 0)
358                State.RP = 0;
359              else
360                PC = RPT_S;
361            }
362
363          /* FIXME */
364          if (PC == oldpc)
365            PC++;
366        }
367    } 
368  while ( !State.exception && !step);
369
370  if (step && !State.exception)
371    State.exception = SIGTRAP;
372 }
373
374 int
375 sim_trace ()
376 {
377 #ifdef DEBUG
378   d10v_debug = DEBUG;
379 #endif
380   sim_resume (0, 0);
381   return 1;
382 }
383
384 void
385 sim_info (verbose)
386      int verbose;
387 {
388   char buf[40];
389   int size;
390   long total = (ins_type_counters[ (int)INS_LONG ]
391                 + ins_type_counters[ (int)INS_LEFT ]
392                 + ins_type_counters[ (int)INS_LEFT_PARALLEL ]
393                 + ins_type_counters[ (int)INS_RIGHT ]
394                 + ins_type_counters[ (int)INS_RIGHT_PARALLEL ]);
395
396   sprintf (buf, "%ld", total);
397   size = strlen (buf);
398
399   (*d10v_callback->printf_filtered) (d10v_callback,
400                                      "executed %*ld instructions in the left  container, %*ld parallel, %*ld nops\n",
401                                      size, ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_PARALLEL ],
402                                      size, ins_type_counters[ (int)INS_LEFT_PARALLEL ],
403                                      size, left_nops);
404
405   (*d10v_callback->printf_filtered) (d10v_callback,
406                                      "executed %*ld instructions in the right container, %*ld parallel, %*ld nops\n",
407                                      size, ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_PARALLEL ],
408                                      size, ins_type_counters[ (int)INS_RIGHT_PARALLEL ],
409                                      size, right_nops);
410
411   (*d10v_callback->printf_filtered) (d10v_callback,
412                                      "executed %*ld long instructions\n",
413                                      size, ins_type_counters[ (int)INS_LONG ]);
414
415   (*d10v_callback->printf_filtered) (d10v_callback,
416                                      "executed %*ld total instructions\n",
417                                      size, total);
418 }
419
420 void
421 sim_create_inferior (start_address, argv, env)
422      SIM_ADDR start_address;
423      char **argv;
424      char **env;
425 {
426   uint8 *imem, *dmem;
427   uint32 mem_min, mem_max;
428 #ifdef DEBUG
429   if (d10v_debug)
430     (*d10v_callback->printf_filtered) (d10v_callback, "sim_create_inferior:  PC=0x%x\n", start_address);
431 #endif
432   /* save memory pointers */
433   imem = State.imem;
434   dmem = State.dmem;
435   mem_min = State.mem_min;
436   mem_max = State.mem_max;
437   /* reset all state information */
438   memset (&State, 0, sizeof(State));
439   /* restore memory pointers */
440   State.imem = imem;
441   State.dmem = dmem;
442   State.mem_min = mem_min;
443   State.mem_max = mem_max;
444   /* set PC */
445   PC = start_address >> 2;
446 }
447
448
449 void
450 sim_kill ()
451 {
452   /* nothing to do */
453 }
454
455 void
456 sim_set_callbacks(p)
457      host_callback *p;
458 {
459 /*  printf ("sim_set_callbacks\n"); */
460   d10v_callback = p;
461 }
462
463 void
464 sim_stop_reason (reason, sigrc)
465      enum sim_stop *reason;
466      int *sigrc;
467 {
468 /*   (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason:  PC=0x%x\n",PC<<2); */
469
470   switch (State.exception)
471     {
472     case SIG_D10V_STOP:                 /* stop instruction */
473       *reason = sim_exited;
474       *sigrc = 0;
475       break;
476
477     case SIG_D10V_EXIT:                 /* exit trap */
478       *reason = sim_exited;
479       *sigrc = State.regs[2];
480       break;
481
482     default:                            /* some signal */
483       *reason = sim_stopped;
484       *sigrc = State.exception;
485       break;
486     } 
487 }
488
489 void
490 sim_fetch_register (rn, memory)
491      int rn;
492      unsigned char *memory;
493 {
494   if (rn > 31)
495     {
496       WRITE_64 (memory, State.a[rn-32]);
497       /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%llx\n",rn,State.a[rn-32]); */
498     }
499   else
500     {
501       WRITE_16 (memory, State.regs[rn]);
502       /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%x\n",rn,State.regs[rn]); */
503     }
504 }
505  
506 void
507 sim_store_register (rn, memory)
508      int rn;
509      unsigned char *memory;
510 {
511   if (rn > 31)
512     {
513       State.a[rn-32] =  READ_64 (memory) & MASK40;
514       /* (*d10v_callback->printf_filtered) (d10v_callback, "store: a%d=0x%llx\n",rn-32,State.a[rn-32]); */
515     }
516   else
517     {
518       State.regs[rn]= READ_16 (memory);
519       /* (*d10v_callback->printf_filtered) (d10v_callback, "store: r%d=0x%x\n",rn,State.regs[rn]); */
520     }
521 }
522
523 sim_read (addr, buffer, size)
524      SIM_ADDR addr;
525      unsigned char *buffer;
526      int size;
527 {
528   int i;
529   for (i = 0; i < size; i++)
530     {
531       buffer[i] = State.imem[addr + i];
532     }
533   return size;
534
535
536 void
537 sim_do_command (cmd)
538      char *cmd;
539
540   (*d10v_callback->printf_filtered) (d10v_callback, "sim_do_command: %s\n",cmd);
541 }
542
543 int
544 sim_load (prog, from_tty)
545      char *prog;
546      int from_tty;
547 {
548   /* Return nonzero so GDB will handle it.  */
549   return 1;
550