* interp.c (hash): Make this an inline function
[external/binutils.git] / sim / v850 / interp.c
1 #include <signal.h>
2 #include "sysdep.h"
3 #include "bfd.h"
4 #include "remote-sim.h"
5 #include "callback.h"
6
7 #include "v850_sim.h"
8
9 #ifndef INLINE
10 #ifdef __GNUC__
11 #define INLINE inline
12 #else
13 #define INLINE
14 #endif
15 #endif
16
17 #define MEM_SIZE 18     /* V850 memory size is 18 bits XXX */
18
19 host_callback *v850_callback;
20
21
22 uint32 OP[4];
23
24 static struct hash_entry *lookup_hash PARAMS ((uint32 ins));
25 static long hash PARAMS ((long));
26 static void do_format_1_2 PARAMS ((uint32));
27 static void do_format_3 PARAMS ((uint32));
28 static void do_format_4 PARAMS ((uint32));
29 static void do_format_5 PARAMS ((uint32));
30 static void do_format_6 PARAMS ((uint32));
31 static void do_format_7 PARAMS ((uint32));
32 static void do_format_8 PARAMS ((uint32));
33 static void do_format_9_10 PARAMS ((uint32));
34 static void init_system PARAMS ((void));
35
36 #define MAX_HASH  63
37 struct hash_entry
38 {
39   struct hash_entry *next;
40   long opcode;
41   long mask;
42   struct simops *ops;
43 };
44
45 struct hash_entry hash_table[MAX_HASH+1];
46
47
48 static INLINE long 
49 hash(insn)
50      long insn;
51 {
52   if ((insn & 0x0600) == 0
53       || (insn & 0x0700) == 0x0200
54       || (insn & 0x0700) == 0x0600
55       || (insn & 0x0780) == 0x0700)
56     return (insn & 0x07e0) >> 5;
57   if ((insn & 0x0700) == 0x0300
58       || (insn & 0x0700) == 0x0400
59       || (insn & 0x0700) == 0x0500)
60     return (insn & 0x0780) >> 7;
61   if ((insn & 0x07c0) == 0x0780)
62     return (insn & 0x07c0) >> 6;
63   return (insn & 0x07e0) >> 5;
64 }
65
66 static struct hash_entry *
67 lookup_hash (ins)
68      uint32 ins;
69 {
70   struct hash_entry *h;
71
72   h = &hash_table[hash(ins)];
73
74   while ((ins & h->mask) != h->opcode)
75     {
76       if (h->next == NULL)
77         {
78           printf ("ERROR looking up hash for %x\n",ins);
79           exit(1);
80         }
81       h = h->next;
82     }
83   return (h);
84 }
85
86 uint8
87 get_byte (x)
88      uint8 *x;
89 {
90   return *x;
91 }
92
93 uint16
94 get_half (x)
95      uint8 *x;
96 {
97   uint8 *a = x;
98   return (a[1] << 8) + (a[0]);
99 }
100
101 uint32
102 get_word (x)
103       uint8 *x;
104 {
105   uint8 *a = x;
106   return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
107 }
108
109 void
110 put_byte (addr, data)
111      uint8 *addr;
112      uint8 data;
113 {
114   uint8 *a = addr;
115   a[0] = data;
116 }
117
118 void
119 put_half (addr, data)
120      uint8 *addr;
121      uint16 data;
122 {
123   uint8 *a = addr;
124   a[0] = data & 0xff;
125   a[1] = (data >> 8) & 0xff;
126 }
127
128 void
129 put_word (addr, data)
130      uint8 *addr;
131      uint32 data;
132 {
133   uint8 *a = addr;
134   a[0] = data & 0xff;
135   a[1] = (data >> 8) & 0xff;
136   a[2] = (data >> 16) & 0xff;
137   a[3] = (data >> 24) & 0xff;
138 }
139
140 static void
141 do_format_1_2 (insn)
142      uint32 insn;
143 {
144   struct hash_entry *h;
145
146   h = lookup_hash (insn);
147   OP[0] = insn & 0x1f;
148   OP[1] = (insn >> 11) & 0x1f;
149   (h->ops->func) ();
150 }
151
152 static void
153 do_format_3 (insn)
154      uint32 insn;
155 {
156   struct hash_entry *h;
157
158   h = lookup_hash (insn);
159   OP[0] = (((insn & 0x70) >> 4) | ((insn & 0xf800) >> 8)) << 1;
160   (h->ops->func) ();
161 }
162
163 static void
164 do_format_4 (insn)
165      uint32 insn;
166 {
167   struct hash_entry *h;
168
169   h = lookup_hash (insn);
170   OP[0] = (insn >> 11) & 0x1f;
171   OP[1] = (insn & 0x7f);
172   (h->ops->func) ();
173 }
174
175 static void
176 do_format_5 (insn)
177      uint32 insn;
178 {
179   struct hash_entry *h;
180
181   h = lookup_hash (insn);
182   OP[0] = (((insn & 0x3f) << 15) | ((insn >> 17) & 0x7fff)) << 1;
183   OP[1] = (insn >> 11) & 0x1f;
184   (h->ops->func) ();
185 }
186
187 static void
188 do_format_6 (insn)
189      uint32 insn;
190 {
191   struct hash_entry *h;
192
193   h = lookup_hash (insn);
194   OP[0] = (insn >> 16) & 0xffff;
195   OP[1] = insn & 0x1f;
196   OP[2] = (insn >> 11) & 0x1f;
197   (h->ops->func) ();
198 }
199
200 static void
201 do_format_7 (insn)
202      uint32 insn;
203 {
204   struct hash_entry *h;
205
206   h = lookup_hash (insn);
207   OP[0] = insn & 0x1f;
208   OP[1] = (insn >> 11) & 0x1f;
209   OP[2] = (insn >> 16) & 0xffff;
210   (h->ops->func) ();
211 }
212
213 static void
214 do_format_8 (insn)
215      uint32 insn;
216 {
217   struct hash_entry *h;
218
219   h = lookup_hash (insn);
220   OP[0] = insn & 0x1f;
221   OP[1] = (insn >> 11) & 0x7;
222   OP[2] = (insn >> 16) & 0xffff;
223   (h->ops->func) ();
224 }
225
226 static void
227 do_format_9_10 (insn)
228      uint32 insn;
229 {
230   struct hash_entry *h;
231
232   h = lookup_hash (insn);
233   OP[0] = insn & 0x1f;
234   OP[1] = (insn >> 11) & 0x1f;
235   (h->ops->func) ();
236 }
237
238 void
239 sim_size (power)
240      int power;
241
242 {
243   if (State.mem)
244     {
245       free (State.mem);
246     }
247
248   State.mem = (uint8 *)calloc(1,1<<MEM_SIZE);
249   if (!State.mem)
250     {
251       fprintf (stderr,"Memory allocation failed.\n");
252       exit(1);
253     }
254 }
255
256 static void
257 init_system ()
258 {
259   if (!State.mem)
260     sim_size(1);
261 }
262
263 int
264 sim_write (addr, buffer, size)
265      SIM_ADDR addr;
266      unsigned char *buffer;
267      int size;
268 {
269   int i;
270   init_system ();
271
272   for (i = 0; i < size; i++)
273     {
274       State.mem[i+addr] = buffer[i]; 
275     }
276   return size;
277 }
278
279 void
280 sim_open (args)
281      char *args;
282 {
283   struct simops *s;
284   struct hash_entry *h;
285   if (args != NULL)
286       printf ("sim_open %s\n",args);
287
288   /* put all the opcodes in the hash table */
289   for (s = Simops; s->func; s++)
290     {
291       h = &hash_table[hash(s->opcode)];
292       
293       /* go to the last entry in the chain */
294       while (h->next)
295           h = h->next;
296
297       if (h->ops)
298         {
299           h->next = calloc(1,sizeof(struct hash_entry));
300           h = h->next;
301         }
302       h->ops = s;
303       h->mask = s->mask;
304       h->opcode = s->opcode;
305     }
306 }
307
308
309 void
310 sim_close (quitting)
311      int quitting;
312 {
313   /* nothing to do */
314 }
315
316 void
317 sim_set_profile (n)
318      int n;
319 {
320   printf ("sim_set_profile %d\n",n);
321 }
322
323 void
324 sim_set_profile_size (n)
325      int n;
326 {
327   printf ("sim_set_profile_size %d\n",n);
328 }
329
330 void
331 sim_resume (step, siggnal)
332      int step, siggnal;
333 {
334   uint32 inst, opcode;
335   reg_t oldpc;
336
337  if (step)
338    State.exception = SIGTRAP;
339  else
340    State.exception = 0;
341  
342  do
343    {
344      inst = RLW (PC);
345      oldpc = PC;
346      opcode = (inst & 0x07e0) >> 5;
347      if ((opcode & 0x30) == 0
348          || (opcode & 0x38) == 0x10)
349        {
350          do_format_1_2 (inst & 0xffff);
351          PC += 2;
352        }
353      else if ((opcode & 0x3C) == 0x18
354               || (opcode & 0x3C) == 0x1C
355               || (opcode & 0x3C) == 0x20
356               || (opcode & 0x3C) == 0x24
357               || (opcode & 0x3C) == 0x28)
358        {
359          do_format_4 (inst & 0xffff);
360          PC += 2;
361        }
362      else if ((opcode & 0x3C) == 0x2C)
363        {
364          do_format_3 (inst & 0xffff);
365          /* No PC update, it's done in the instruction.  */
366        }
367      else if ((opcode & 0x38) == 0x30)
368        {
369          do_format_6 (inst);
370          PC += 4;
371        }
372      else if ((opcode & 0x3C) == 0x38)
373        {
374          do_format_7 (inst);
375          PC += 4;
376        }
377      else if ((opcode & 0x3E) == 0x3C)
378        {
379          do_format_5 (inst);
380          /* No PC update, it's done in the instruction.  */
381        }
382      else if ((opcode & 0x3F) == 0x3E)
383        {
384          do_format_8 (inst);
385          PC += 4;
386        }
387      else
388        {
389          do_format_9_10 (inst);
390          PC += 4;
391        }
392    } 
393  while (!State.exception);
394 }
395
396 int
397 sim_trace ()
398 {
399   printf ("sim_trace\n");
400   return 0;
401 }
402
403 void
404 sim_info (verbose)
405      int verbose;
406 {
407   printf ("sim_info\n");
408 }
409
410 void
411 sim_create_inferior (start_address, argv, env)
412      SIM_ADDR start_address;
413      char **argv;
414      char **env;
415 {
416   PC = start_address;
417 }
418
419
420 void
421 sim_kill ()
422 {
423   /* nothing to do */
424 }
425
426 void
427 sim_set_callbacks(p)
428      host_callback *p;
429 {
430   v850_callback = p;
431 }
432
433 /* All the code for exiting, signals, etc needs to be revamped.
434
435    This is enough to get c-torture limping though.  */
436 void
437 sim_stop_reason (reason, sigrc)
438      enum sim_stop *reason;
439      int *sigrc;
440 {
441
442   *reason = sim_stopped;
443   if (State.exception == SIGQUIT)
444     *sigrc = 0;
445   else
446     *sigrc = State.exception;
447 }
448
449 void
450 sim_fetch_register (rn, memory)
451      int rn;
452      unsigned char *memory;
453 {
454   *(uint32 *)memory = State.regs[rn];
455 }
456  
457 void
458 sim_store_register (rn, memory)
459      int rn;
460      unsigned char *memory;
461 {
462   State.regs[rn]= *(uint32 *)memory;
463 }
464
465 int
466 sim_read (addr, buffer, size)
467      SIM_ADDR addr;
468      unsigned char *buffer;
469      int size;
470 {
471   int i;
472   for (i = 0; i < size; i++)
473     {
474       buffer[i] = State.mem[addr + i];
475     }
476   return size;
477
478
479 void
480 sim_do_command (cmd)
481      char *cmd;
482
483   printf("sim_do_command: %s\n",cmd);
484 }
485
486 int
487 sim_load (prog, from_tty)
488      char *prog;
489      int from_tty;
490 {
491   /* Return nonzero so GDB will handle it.  */
492   return 1;
493