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