Better error messages when a program stops due to signal; support d10v getpid/kill
[deliverable/binutils-gdb.git] / sim / d10v / interp.c
CommitLineData
d70b4d42 1#include <signal.h>
2934d1c9
MH
2#include "sysdep.h"
3#include "bfd.h"
4#include "remote-sim.h"
2934d1c9
MH
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
87178dbd
MM
11enum _leftright { LEFT_FIRST, RIGHT_FIRST };
12
7eebfc62 13int d10v_debug;
87178dbd 14host_callback *d10v_callback;
7eebfc62
MM
15long ins_type_counters[ (int)INS_MAX ];
16long left_nops, right_nops;
87178dbd 17
2934d1c9
MH
18uint16 OP[4];
19
20static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size));
21
22#define MAX_HASH 63
23struct hash_entry
24{
25 struct hash_entry *next;
26 long opcode;
27 long mask;
28 struct simops *ops;
29};
30
31struct hash_entry hash_table[MAX_HASH+1];
32
33static long
34hash(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
44static struct hash_entry *
45lookup_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 {
7eebfc62 60 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR looking up hash for %x at PC %x\n",ins, PC);
2934d1c9
MH
61 exit(1);
62 }
63 h = h->next;
64 }
65 return (h);
66}
67
68uint32
d70b4d42
MH
69get_longword (x)
70 uint8 *x;
2934d1c9 71{
d70b4d42 72 uint8 *a = x;
2934d1c9
MH
73 return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + (a[3]);
74}
75
d70b4d42
MH
76int64
77get_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
2934d1c9 85uint16
d70b4d42
MH
86get_word (x)
87 uint8 *x;
2934d1c9 88{
d70b4d42
MH
89 uint8 *a = x;
90 return ((uint16)a[0]<<8) + a[1];
2934d1c9
MH
91}
92
87178dbd 93
2934d1c9 94void
d70b4d42
MH
95write_word (addr, data)
96 uint8 *addr;
97 uint16 data;
2934d1c9 98{
d70b4d42 99 uint8 *a = addr;
2934d1c9
MH
100 a[0] = data >> 8;
101 a[1] = data & 0xff;
102}
103
87178dbd
MM
104void
105write_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
d70b4d42
MH
115void
116write_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
2934d1c9
MH
131static void
132get_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
146static void
147do_long (ins)
148 uint32 ins;
149{
150 struct hash_entry *h;
7eebfc62
MM
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
2934d1c9
MH
155 h = lookup_hash (ins, 1);
156 get_operands (h->ops, ins);
87178dbd 157 State.ins_type = INS_LONG;
7eebfc62 158 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9
MH
159 (h->ops->func)();
160}
215ac953 161
2934d1c9 162static void
87178dbd 163do_2_short (ins1, ins2, leftright)
2934d1c9 164 uint16 ins1, ins2;
87178dbd 165 enum _leftright leftright;
2934d1c9
MH
166{
167 struct hash_entry *h;
215ac953
MM
168 reg_t orig_pc = PC;
169
7eebfc62
MM
170#ifdef DEBUG
171 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
172 (*d10v_callback->printf_filtered) (d10v_callback, "do_2_short 0x%x (%s) -> 0x%x\n",
173 ins1, (leftright) ? "left" : "right", ins2);
174#endif
2934d1c9
MH
175 /* printf ("do_2_short %x -> %x\n",ins1,ins2); */
176 h = lookup_hash (ins1, 0);
177 get_operands (h->ops, ins1);
87178dbd 178 State.ins_type = (leftright == LEFT_FIRST) ? INS_LEFT : INS_RIGHT;
7eebfc62 179 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9 180 (h->ops->func)();
215ac953
MM
181
182 /* If the PC has changed (ie, a jump), don't do the second instruction */
57bc1a72 183 if (orig_pc == PC && !State.exception)
215ac953
MM
184 {
185 h = lookup_hash (ins2, 0);
186 get_operands (h->ops, ins2);
187 State.ins_type = (leftright == LEFT_FIRST) ? INS_RIGHT : INS_LEFT;
188 ins_type_counters[ (int)State.ins_type ]++;
189 (h->ops->func)();
190 }
2934d1c9 191}
215ac953 192
2934d1c9
MH
193static void
194do_parallel (ins1, ins2)
195 uint16 ins1, ins2;
196{
197 struct hash_entry *h1, *h2;
7eebfc62
MM
198#ifdef DEBUG
199 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
200 (*d10v_callback->printf_filtered) (d10v_callback, "do_parallel 0x%x || 0x%x\n", ins1, ins2);
201#endif
2934d1c9 202 h1 = lookup_hash (ins1, 0);
2934d1c9 203 h2 = lookup_hash (ins2, 0);
d70b4d42 204
2934d1c9
MH
205 if (h1->ops->exec_type == PARONLY)
206 {
d70b4d42 207 get_operands (h1->ops, ins1);
87178dbd 208 State.ins_type = INS_LEFT;
7eebfc62 209 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9
MH
210 (h1->ops->func)();
211 if (State.exe)
d70b4d42
MH
212 {
213 get_operands (h2->ops, ins2);
87178dbd 214 State.ins_type = INS_RIGHT;
d70b4d42
MH
215 (h2->ops->func)();
216 }
2934d1c9
MH
217 }
218 else if (h2->ops->exec_type == PARONLY)
219 {
d70b4d42 220 get_operands (h2->ops, ins2);
87178dbd 221 State.ins_type = INS_RIGHT;
7eebfc62 222 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9
MH
223 (h2->ops->func)();
224 if (State.exe)
d70b4d42
MH
225 {
226 get_operands (h1->ops, ins1);
87178dbd 227 State.ins_type = INS_LEFT;
d70b4d42
MH
228 (h1->ops->func)();
229 }
2934d1c9
MH
230 }
231 else
232 {
d70b4d42 233 get_operands (h1->ops, ins1);
87178dbd 234 State.ins_type = INS_LEFT_PARALLEL;
7eebfc62 235 ins_type_counters[ (int)State.ins_type ]++;
2934d1c9 236 (h1->ops->func)();
57bc1a72
MM
237 if (!State.exception)
238 {
239 get_operands (h2->ops, ins2);
240 State.ins_type = INS_RIGHT_PARALLEL;
241 ins_type_counters[ (int)State.ins_type ]++;
242 (h2->ops->func)();
243 }
2934d1c9
MH
244 }
245}
246
247
248void
249sim_size (power)
250 int power;
251
252{
253 if (State.imem)
254 {
255 free (State.imem);
256 free (State.dmem);
257 }
258
259 State.imem = (uint8 *)calloc(1,1<<IMEM_SIZE);
260 State.dmem = (uint8 *)calloc(1,1<<DMEM_SIZE);
261 if (!State.imem || !State.dmem )
262 {
7eebfc62 263 (*d10v_callback->printf_filtered) (d10v_callback, "Memory allocation failed.\n");
2934d1c9
MH
264 exit(1);
265 }
7eebfc62 266
57bc1a72
MM
267 State.mem_min = 1<<IMEM_SIZE;
268 State.mem_max = 0;
269
7eebfc62
MM
270#ifdef DEBUG
271 if ((d10v_debug & DEBUG_MEMSIZE) != 0)
272 {
273 (*d10v_callback->printf_filtered) (d10v_callback, "Allocated %d bytes instruction memory and\n",1<<IMEM_SIZE);
274 (*d10v_callback->printf_filtered) (d10v_callback, " %d bytes data memory.\n", 1<<DMEM_SIZE);
275 }
87178dbd 276#endif
2934d1c9
MH
277}
278
279static void
280init_system ()
281{
282 if (!State.imem)
283 sim_size(1);
284}
285
286int
287sim_write (addr, buffer, size)
288 SIM_ADDR addr;
289 unsigned char *buffer;
290 int size;
291{
2934d1c9
MH
292 init_system ();
293
57bc1a72
MM
294#ifdef DEBUG
295 if ((d10v_debug & DEBUG_INSTRUCTION) != 0)
296 (*d10v_callback->printf_filtered) (d10v_callback, "sim_write %d bytes to 0x%x, min = 0x%x, max = 0x%x\n",
297 size, addr, State.mem_min, State.mem_max);
298#endif
299
300 if (State.mem_min > addr)
301 State.mem_min = addr;
302
303 if (State.mem_max < addr+size-1)
304 State.mem_max = addr+size-1;
305
306 memcpy (State.imem+addr, buffer, size);
2934d1c9
MH
307 return size;
308}
309
310void
311sim_open (args)
312 char *args;
313{
314 struct simops *s;
315 struct hash_entry *h, *prev;
1eaaf305
MM
316 static int init_p = 0;
317
2934d1c9 318 if (args != NULL)
1eaaf305
MM
319 {
320#ifdef DEBUG
321 if (strcmp (args, "-t") == 0)
322 d10v_debug = DEBUG;
323 else
324#endif
325 (*d10v_callback->printf_filtered) (d10v_callback, "ERROR: unsupported option(s): %s\n",args);
326 }
2934d1c9
MH
327
328 /* put all the opcodes in the hash table */
1eaaf305 329 if (!init_p++)
2934d1c9 330 {
1eaaf305 331 for (s = Simops; s->func; s++)
2934d1c9 332 {
1eaaf305
MM
333 h = &hash_table[hash(s->opcode,s->format)];
334
335 /* go to the last entry in the chain */
336 while (h->next)
337 h = h->next;
338
339 if (h->ops)
340 {
341 h->next = calloc(1,sizeof(struct hash_entry));
342 h = h->next;
343 }
344 h->ops = s;
345 h->mask = s->mask;
346 h->opcode = s->opcode;
2934d1c9 347 }
2934d1c9
MH
348 }
349}
350
351
352void
353sim_close (quitting)
354 int quitting;
355{
356 /* nothing to do */
357}
358
359void
360sim_set_profile (n)
361 int n;
362{
7eebfc62 363 (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile %d\n",n);
2934d1c9
MH
364}
365
366void
367sim_set_profile_size (n)
368 int n;
369{
7eebfc62 370 (*d10v_callback->printf_filtered) (d10v_callback, "sim_set_profile_size %d\n",n);
2934d1c9
MH
371}
372
373void
374sim_resume (step, siggnal)
375 int step, siggnal;
376{
377 uint32 inst;
378 int i;
379 reg_t oldpc;
380
7eebfc62 381/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_resume (%d,%d) PC=0x%x\n",step,siggnal,PC); */
2934d1c9 382
d70b4d42
MH
383 if (step)
384 State.exception = SIGTRAP;
385 else
386 State.exception = 0;
387
388 do
389 {
57bc1a72
MM
390 uint32 byte_pc = ((uint32)PC) << 2;
391 if ((byte_pc < State.mem_min) || (byte_pc > State.mem_max))
d70b4d42 392 {
57bc1a72
MM
393 (*d10v_callback->printf_filtered) (d10v_callback,
394 "PC (0x%lx) out of range, oldpc = 0x%lx, min = 0x%lx, max = 0x%lx\n",
395 (long)byte_pc, (long)oldpc, (long)State.mem_min, (long)State.mem_max);
396 State.exception = SIGILL;
d70b4d42 397 }
57bc1a72 398 else
d70b4d42 399 {
57bc1a72
MM
400 inst = RLW (byte_pc);
401 oldpc = PC;
402 switch (inst & 0xC0000000)
403 {
404 case 0xC0000000:
405 /* long instruction */
406 do_long (inst & 0x3FFFFFFF);
407 break;
408 case 0x80000000:
409 /* R -> L */
410 do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15, 0);
411 break;
412 case 0x40000000:
413 /* L -> R */
414 do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF, 1);
415 break;
416 case 0:
417 do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF);
418 break;
419 }
d70b4d42 420
57bc1a72
MM
421 if (State.RP && PC == RPT_E)
422 {
423 RPT_C -= 1;
424 if (RPT_C == 0)
425 State.RP = 0;
426 else
427 PC = RPT_S;
428 }
429
430 /* FIXME */
431 if (PC == oldpc)
432 PC++;
433 }
d70b4d42
MH
434 }
435 while (!State.exception);
2934d1c9
MH
436}
437
438int
439sim_trace ()
440{
7eebfc62
MM
441#ifdef DEBUG
442 d10v_debug = DEBUG;
443#endif
444 sim_resume (0, 0);
445 return 1;
2934d1c9
MH
446}
447
448void
449sim_info (verbose)
450 int verbose;
451{
7eebfc62
MM
452 char buf[40];
453 int size;
454 long total = (ins_type_counters[ (int)INS_LONG ]
455 + ins_type_counters[ (int)INS_LEFT ]
456 + ins_type_counters[ (int)INS_LEFT_PARALLEL ]
457 + ins_type_counters[ (int)INS_RIGHT ]
458 + ins_type_counters[ (int)INS_RIGHT_PARALLEL ]);
459
460 sprintf (buf, "%ld", total);
461 size = strlen (buf);
462
463 (*d10v_callback->printf_filtered) (d10v_callback,
464 "executed %*ld instructions in the left container, %*ld parallel, %*ld nops\n",
465 size, ins_type_counters[ (int)INS_LEFT ] + ins_type_counters[ (int)INS_LEFT_PARALLEL ],
466 size, ins_type_counters[ (int)INS_LEFT_PARALLEL ],
467 size, left_nops);
468
469 (*d10v_callback->printf_filtered) (d10v_callback,
470 "executed %*ld instructions in the right container, %*ld parallel, %*ld nops\n",
471 size, ins_type_counters[ (int)INS_RIGHT ] + ins_type_counters[ (int)INS_RIGHT_PARALLEL ],
472 size, ins_type_counters[ (int)INS_RIGHT_PARALLEL ],
473 size, right_nops);
474
475 (*d10v_callback->printf_filtered) (d10v_callback,
476 "executed %*ld long instructions\n",
477 size, ins_type_counters[ (int)INS_LONG ]);
478
479 (*d10v_callback->printf_filtered) (d10v_callback,
480 "executed %*ld total instructions\n",
481 size, total);
2934d1c9
MH
482}
483
484void
485sim_create_inferior (start_address, argv, env)
486 SIM_ADDR start_address;
487 char **argv;
488 char **env;
489{
57bc1a72
MM
490 uint8 *imem, *dmem;
491 uint32 mem_min, mem_max;
7eebfc62
MM
492#ifdef DEBUG
493 if (d10v_debug)
494 (*d10v_callback->printf_filtered) (d10v_callback, "sim_create_inferior: PC=0x%x\n", start_address);
495#endif
57bc1a72
MM
496 /* save memory pointers */
497 imem = State.imem;
498 dmem = State.dmem;
499 mem_min = State.mem_min;
500 mem_max = State.mem_max;
501 /* reset all state information */
502 memset (&State, 0, sizeof(State));
503 /* restore memory pointers */
504 State.imem = imem;
505 State.dmem = dmem;
506 State.mem_min = mem_min;
507 State.mem_max = mem_max;
508 /* set PC */
2934d1c9
MH
509 PC = start_address >> 2;
510}
511
512
513void
514sim_kill ()
515{
516 /* nothing to do */
517}
518
519void
520sim_set_callbacks(p)
521 host_callback *p;
522{
87178dbd
MM
523/* printf ("sim_set_callbacks\n"); */
524 d10v_callback = p;
2934d1c9
MH
525}
526
527void
528sim_stop_reason (reason, sigrc)
529 enum sim_stop *reason;
530 int *sigrc;
531{
7eebfc62 532/* (*d10v_callback->printf_filtered) (d10v_callback, "sim_stop_reason: PC=0x%x\n",PC<<2); */
d70b4d42 533
a49a15ad 534 switch (State.exception)
d70b4d42 535 {
a49a15ad 536 case SIG_D10V_STOP: /* stop instruction */
d70b4d42 537 *reason = sim_exited;
a49a15ad
MM
538 *sigrc = 0;
539 break;
540
541 case SIG_D10V_EXIT: /* exit trap */
542 *reason = sim_exited;
543 *sigrc = State.regs[2];
544 break;
545
546 default: /* some signal */
d70b4d42
MH
547 *reason = sim_stopped;
548 *sigrc = State.exception;
a49a15ad 549 break;
d70b4d42
MH
550 }
551}
552
553void
554sim_fetch_register (rn, memory)
555 int rn;
556 unsigned char *memory;
557{
558 if (rn > 31)
559 {
560 WRITE_64 (memory, State.a[rn-32]);
7eebfc62 561 /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%llx\n",rn,State.a[rn-32]); */
d70b4d42
MH
562 }
563 else
564 {
565 WRITE_16 (memory, State.regs[rn]);
7eebfc62 566 /* (*d10v_callback->printf_filtered) (d10v_callback, "sim_fetch_register %d 0x%x\n",rn,State.regs[rn]); */
d70b4d42
MH
567 }
568}
569
570void
571sim_store_register (rn, memory)
572 int rn;
573 unsigned char *memory;
574{
575 if (rn > 31)
576 {
577 State.a[rn-32] = READ_64 (memory) & MASK40;
7eebfc62 578 /* (*d10v_callback->printf_filtered) (d10v_callback, "store: a%d=0x%llx\n",rn-32,State.a[rn-32]); */
d70b4d42
MH
579 }
580 else
581 {
582 State.regs[rn]= READ_16 (memory);
7eebfc62 583 /* (*d10v_callback->printf_filtered) (d10v_callback, "store: r%d=0x%x\n",rn,State.regs[rn]); */
d70b4d42 584 }
2934d1c9 585}
d70b4d42
MH
586
587sim_read (addr, buffer, size)
588 SIM_ADDR addr;
589 unsigned char *buffer;
590 int size;
591{
592 int i;
593 for (i = 0; i < size; i++)
594 {
595 buffer[i] = State.imem[addr + i];
596 }
597 return size;
598}
599
600void
601sim_do_command (cmd)
602 char *cmd;
603{
7eebfc62 604 (*d10v_callback->printf_filtered) (d10v_callback, "sim_do_command: %s\n",cmd);
d70b4d42
MH
605}
606
607int
608sim_load (prog, from_tty)
609 char *prog;
610 int from_tty;
611{
612 /* Return nonzero so GDB will handle it. */
613 return 1;
614}
This page took 0.054185 seconds and 4 git commands to generate.