Make read/write memory functions inlined
[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 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 if (step)
321 State.exception = SIGTRAP;
322 else
323 State.exception = 0;
324
325 do
326 {
327 uint32 byte_pc = ((uint32)PC) << 2;
328 if ((byte_pc < State.mem_min) || (byte_pc > State.mem_max))
329 {
330 (*d10v_callback->printf_filtered) (d10v_callback,
331 "PC (0x%lx) out of range, oldpc = 0x%lx, min = 0x%lx, max = 0x%lx\n",
332 (long)byte_pc, (long)oldpc, (long)State.mem_min, (long)State.mem_max);
333 State.exception = SIGILL;
334 }
335 else
336 {
337 inst = RLW (byte_pc);
338 oldpc = PC;
339 switch (inst & 0xC0000000)
340 {
341 case 0xC0000000:
342 /* long instruction */
343 do_long (inst & 0x3FFFFFFF);
344 break;
345 case 0x80000000:
346 /* R -> L */
347 do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, 0);
348 break;
349 case 0x40000000:
350 /* L -> R */
351 do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, 1);
352 break;
353 case 0:
354 do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF);
355 break;
356 }
357
358 if (State.RP && PC == RPT_E)
359 {
360 RPT_C -= 1;
361 if (RPT_C == 0)
362 State.RP = 0;
363 else
364 PC = RPT_S;
365 }
366
367 /* FIXME */
368 if (PC == oldpc)
369 PC++;
370 }
371 }
372 while (!State.exception);
373 }
374
375 int
376 sim_trace ()
377 {
378 #ifdef DEBUG
379 d10v_debug = DEBUG;
380 #endif
381 sim_resume (0, 0);
382 return 1;
383 }
384
385 void
386 sim_info (verbose)
387 int verbose;
388 {
389 char buf[40];
390 int size;
391 long total = (ins_type_counters[ (int)INS_LONG ]
392 + ins_type_counters[ (int)INS_LEFT ]
393 + ins_type_counters[ (int)INS_LEFT_PARALLEL ]
394 + ins_type_counters[ (int)INS_RIGHT ]
395 + ins_type_counters[ (int)INS_RIGHT_PARALLEL ]);
396
397 sprintf (buf, "%ld", total);
398 size = strlen (buf);
399
400 (*d10v_callback->printf_filtered) (d10v_callback,
401 "executed %*ld instructions in the left container, %*ld parallel, %*ld nops\n",
402 size, ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_PARALLEL ],
403 size, ins_type_counters[ (int)INS_LEFT_PARALLEL ],
404 size, left_nops);
405
406 (*d10v_callback->printf_filtered) (d10v_callback,
407 "executed %*ld instructions in the right container, %*ld parallel, %*ld nops\n",
408 size, ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_PARALLEL ],
409 size, ins_type_counters[ (int)INS_RIGHT_PARALLEL ],
410 size, right_nops);
411
412 (*d10v_callback->printf_filtered) (d10v_callback,
413 "executed %*ld long instructions\n",
414 size, ins_type_counters[ (int)INS_LONG ]);
415
416 (*d10v_callback->printf_filtered) (d10v_callback,
417 "executed %*ld total instructions\n",
418 size, total);
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 uint8 *imem, *dmem;
428 uint32 mem_min, mem_max;
429 #ifdef DEBUG
430 if (d10v_debug)
431 (*d10v_callback->printf_filtered) (d10v_callback, "sim_create_inferior: PC=0x%x\n", start_address);
432 #endif
433 /* save memory pointers */
434 imem = State.imem;
435 dmem = State.dmem;
436 mem_min = State.mem_min;
437 mem_max = State.mem_max;
438 /* reset all state information */
439 memset (&State, 0, sizeof(State));
440 /* restore memory pointers */
441 State.imem = imem;
442 State.dmem = dmem;
443 State.mem_min = mem_min;
444 State.mem_max = mem_max;
445 /* set PC */
446 PC = start_address >> 2;
447 }
448
449
450 void
451 sim_kill ()
452 {
453 /* nothing to do */
454 }
455
456 void
457 sim_set_callbacks(p)
458 host_callback *p;
459 {
460 /* printf ("sim_set_callbacks\n"); */
461 d10v_callback = p;
462 }
463
464 void
465 sim_stop_reason (reason, sigrc)
466 enum sim_stop *reason;
467 int *sigrc;
468 {
469 /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason: PC=0x%x\n",PC<<2); */
470
471 switch (State.exception)
472 {
473 case SIG_D10V_STOP: /* stop instruction */
474 *reason = sim_exited;
475 *sigrc = 0;
476 break;
477
478 case SIG_D10V_EXIT: /* exit trap */
479 *reason = sim_exited;
480 *sigrc = State.regs[2];
481 break;
482
483 default: /* some signal */
484 *reason = sim_stopped;
485 *sigrc = State.exception;
486 break;
487 }
488 }
489
490 void
491 sim_fetch_register (rn, memory)
492 int rn;
493 unsigned char *memory;
494 {
495 if (rn > 31)
496 {
497 WRITE_64 (memory, State.a[rn-32]);
498 /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%llx\n",rn,State.a[rn-32]); */
499 }
500 else
501 {
502 WRITE_16 (memory, State.regs[rn]);
503 /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%x\n",rn,State.regs[rn]); */
504 }
505 }
506
507 void
508 sim_store_register (rn, memory)
509 int rn;
510 unsigned char *memory;
511 {
512 if (rn > 31)
513 {
514 State.a[rn-32] = READ_64 (memory) & MASK40;
515 /* (*d10v_callback->printf_filtered) (d10v_callback, "store: a%d=0x%llx\n",rn-32,State.a[rn-32]); */
516 }
517 else
518 {
519 State.regs[rn]= READ_16 (memory);
520 /* (*d10v_callback->printf_filtered) (d10v_callback, "store: r%d=0x%x\n",rn,State.regs[rn]); */
521 }
522 }
523
524 sim_read (addr, buffer, size)
525 SIM_ADDR addr;
526 unsigned char *buffer;
527 int size;
528 {
529 int i;
530 for (i = 0; i < size; i++)
531 {
532 buffer[i] = State.imem[addr + i];
533 }
534 return size;
535 }
536
537 void
538 sim_do_command (cmd)
539 char *cmd;
540 {
541 (*d10v_callback->printf_filtered) (d10v_callback, "sim_do_command: %s\n",cmd);
542 }
543
544 int
545 sim_load (prog, from_tty)
546 char *prog;
547 int from_tty;
548 {
549 /* Return nonzero so GDB will handle it. */
550 return 1;
551 }
This page took 0.041436 seconds and 4 git commands to generate.