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