77b7c6658c1a2451656692478a0549824d3e933c
[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 v850_debug = DEBUG;
291 else
292 #endif
293 (*v850_callback->printf_filtered) (v850_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 PC = State.sregs[0];
346
347 if (step)
348 State.exception = SIGTRAP;
349 else
350 State.exception = 0;
351
352 do
353 {
354 inst = RLW (PC);
355 oldpc = PC;
356 opcode = (inst & 0x07e0) >> 5;
357 if ((opcode & 0x30) == 0
358 || (opcode & 0x38) == 0x10)
359 {
360 do_format_1_2 (inst & 0xffff);
361 PC += 2;
362 }
363 else if ((opcode & 0x3C) == 0x18
364 || (opcode & 0x3C) == 0x1C
365 || (opcode & 0x3C) == 0x20
366 || (opcode & 0x3C) == 0x24
367 || (opcode & 0x3C) == 0x28)
368 {
369 do_format_4 (inst & 0xffff);
370 PC += 2;
371 }
372 else if ((opcode & 0x3C) == 0x2C)
373 {
374 do_format_3 (inst & 0xffff);
375 /* No PC update, it's done in the instruction. */
376 }
377 else if ((opcode & 0x38) == 0x30)
378 {
379 do_format_6 (inst);
380 PC += 4;
381 }
382 else if ((opcode & 0x3C) == 0x38)
383 {
384 do_format_7 (inst);
385 PC += 4;
386 }
387 else if ((opcode & 0x3E) == 0x3C)
388 {
389 do_format_5 (inst);
390 /* No PC update, it's done in the instruction. */
391 }
392 else if ((opcode & 0x3F) == 0x3E)
393 {
394 do_format_8 (inst);
395 PC += 4;
396 }
397 else
398 {
399 do_format_9_10 (inst);
400 PC += 4;
401 }
402 }
403 while (!State.exception);
404
405 State.sregs[0] = PC;
406 }
407
408 int
409 sim_trace ()
410 {
411 #ifdef DEBUG
412 v850_debug = DEBUG;
413 #endif
414 sim_resume (0, 0);
415 return 1;
416 }
417
418 void
419 sim_info (verbose)
420 int verbose;
421 {
422 (*v850_callback->printf_filtered) (v850_callback, "sim_info\n");
423 }
424
425 void
426 sim_create_inferior (start_address, argv, env)
427 SIM_ADDR start_address;
428 char **argv;
429 char **env;
430 {
431 PC = start_address;
432 }
433
434
435 void
436 sim_kill ()
437 {
438 /* nothing to do */
439 }
440
441 void
442 sim_set_callbacks(p)
443 host_callback *p;
444 {
445 v850_callback = p;
446 }
447
448 /* All the code for exiting, signals, etc needs to be revamped.
449
450 This is enough to get c-torture limping though. */
451 void
452 sim_stop_reason (reason, sigrc)
453 enum sim_stop *reason;
454 int *sigrc;
455 {
456
457 *reason = sim_stopped;
458 if (State.exception == SIGQUIT)
459 *sigrc = 0;
460 else
461 *sigrc = State.exception;
462 }
463
464 void
465 sim_fetch_register (rn, memory)
466 int rn;
467 unsigned char *memory;
468 {
469 put_word (memory, State.regs[rn]);
470 }
471
472 void
473 sim_store_register (rn, memory)
474 int rn;
475 unsigned char *memory;
476 {
477 State.regs[rn] = get_word (memory);
478 }
479
480 int
481 sim_read (addr, buffer, size)
482 SIM_ADDR addr;
483 unsigned char *buffer;
484 int size;
485 {
486 int i;
487 for (i = 0; i < size; i++)
488 {
489 buffer[i] = State.mem[addr + i];
490 }
491 return size;
492 }
493
494 void
495 sim_do_command (cmd)
496 char *cmd;
497 {
498 (*v850_callback->printf_filtered) (v850_callback, "sim_do_command: %s\n", cmd);
499 }
500
501 int
502 sim_load (prog, from_tty)
503 char *prog;
504 int from_tty;
505 {
506 /* Return nonzero so GDB will handle it. */
507 return 1;
508 }