Replace memory model with one from sim/common directory.
[deliverable/binutils-gdb.git] / sim / v850 / interp.c
1 #include <signal.h>
2 #include "sim-main.h"
3 #include "sim-options.h"
4 #include "v850_sim.h"
5
6 #ifdef HAVE_STDLIB_H
7 #include <stdlib.h>
8 #endif
9
10 #ifdef HAVE_STRING_H
11 #include <string.h>
12 #else
13 #ifdef HAVE_STRINGS_H
14 #include <strings.h>
15 #endif
16 #endif
17
18 #include "bfd.h"
19
20
21 /* For compatibility */
22 SIM_DESC simulator;
23
24 enum interrupt_type
25 {
26 int_none,
27 int_reset,
28 int_nmi,
29 int_intov1,
30 int_intp10,
31 int_intp11,
32 int_intp12,
33 int_intp13,
34 int_intcm4,
35 num_int_types
36 };
37
38 enum interrupt_cond_type
39 {
40 int_cond_none,
41 int_cond_pc,
42 int_cond_time
43 };
44
45 struct interrupt_generator
46 {
47 enum interrupt_type type;
48 enum interrupt_cond_type cond_type;
49 int number;
50 SIM_ADDR address;
51 unsigned long time;
52 int enabled;
53 struct interrupt_generator *next;
54 };
55
56 char *interrupt_names[] = {
57 "",
58 "reset",
59 "nmi",
60 "intov1",
61 "intp10",
62 "intp11",
63 "intp12",
64 "intp13",
65 "intcm4",
66 NULL
67 };
68
69 struct interrupt_generator *intgen_list;
70
71 /* True if a non-maskable (such as NMI or reset) interrupt generator
72 is present. */
73
74 static int have_nm_generator;
75
76 #ifndef INLINE
77 #ifdef __GNUC__
78 #define INLINE inline
79 #else
80 #define INLINE
81 #endif
82 #endif
83
84 /* These default values correspond to expected usage for the chip. */
85
86 int v850_debug;
87
88 uint32 OP[4];
89
90 static struct hash_entry *lookup_hash PARAMS ((SIM_DESC sd, uint32 ins));
91 static long hash PARAMS ((long));
92 #if 0
93 static void do_format_1_2 PARAMS ((uint32));
94 static void do_format_3 PARAMS ((uint32));
95 static void do_format_4 PARAMS ((uint32));
96 static void do_format_5 PARAMS ((uint32));
97 static void do_format_6 PARAMS ((uint32));
98 static void do_format_7 PARAMS ((uint32));
99 static void do_format_8 PARAMS ((uint32));
100 static void do_format_9_10 PARAMS ((uint32));
101 #endif
102
103 #define MAX_HASH 63
104
105 struct hash_entry
106 {
107 struct hash_entry *next;
108 unsigned long opcode;
109 unsigned long mask;
110 struct simops *ops;
111 };
112
113 struct hash_entry hash_table[MAX_HASH+1];
114
115
116 static INLINE long
117 hash(insn)
118 long insn;
119 {
120 if ( (insn & 0x0600) == 0
121 || (insn & 0x0700) == 0x0200
122 || (insn & 0x0700) == 0x0600
123 || (insn & 0x0780) == 0x0700)
124 return (insn & 0x07e0) >> 5;
125
126 if ((insn & 0x0700) == 0x0300
127 || (insn & 0x0700) == 0x0400
128 || (insn & 0x0700) == 0x0500)
129 return (insn & 0x0780) >> 7;
130
131 if ((insn & 0x07c0) == 0x0780)
132 return (insn & 0x07c0) >> 6;
133
134 return (insn & 0x07e0) >> 5;
135 }
136
137 static struct hash_entry *
138 lookup_hash (sd, ins)
139 SIM_DESC sd;
140 uint32 ins;
141 {
142 struct hash_entry *h;
143
144 h = &hash_table[hash(ins)];
145
146 while ((ins & h->mask) != h->opcode)
147 {
148 if (h->next == NULL)
149 {
150 sim_io_error (sd, "ERROR looking up hash for 0x%lx, PC=0x%lx",
151 (long) ins, (long) PC);
152 }
153 h = h->next;
154 }
155 return (h);
156 }
157
158 SIM_DESC
159 sim_open (kind, cb, abfd, argv)
160 SIM_OPEN_KIND kind;
161 host_callback *cb;
162 struct _bfd *abfd;
163 char **argv;
164 {
165 char *buf;
166 SIM_DESC sd = sim_state_alloc (kind, cb);
167 struct simops *s;
168 struct hash_entry *h;
169
170 /* for compatibility */
171 simulator = sd;
172
173 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
174 return 0;
175
176 /* Allocate core managed memory */
177 /* "Mirror" the ROM addresses below 1MB. */
178 asprintf (&buf, "memory region 0,0x100000,0x%lx", V850_ROM_SIZE);
179 sim_do_command (sd, buf);
180 free (buf);
181 /* Chunk of ram adjacent to rom */
182 asprintf (&buf, "memory region 0x100000,0x%lx", V850_LOW_END - 0x100000);
183 sim_do_command (sd, buf);
184 free (buf);
185 /* peripheral I/O region - mirror 1K across 4k (0x1000) */
186 sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
187 /* similarly if in the internal RAM region */
188 sim_do_command (sd, "memory region 0xffe000,0x1000,1024");
189
190 /* getopt will print the error message so we just have to exit if this fails.
191 FIXME: Hmmm... in the case of gdb we need getopt to call
192 print_filtered. */
193 if (sim_parse_args (sd, argv) != SIM_RC_OK)
194 {
195 /* Uninstall the modules to avoid memory leaks,
196 file descriptor leaks, etc. */
197 sim_module_uninstall (sd);
198 return 0;
199 }
200
201 /* check for/establish the a reference program image */
202 if (sim_analyze_program (sd,
203 (STATE_PROG_ARGV (sd) != NULL
204 ? *STATE_PROG_ARGV (sd)
205 : NULL),
206 abfd) != SIM_RC_OK)
207 {
208 sim_module_uninstall (sd);
209 return 0;
210 }
211
212 /* establish any remaining configuration options */
213 if (sim_config (sd) != SIM_RC_OK)
214 {
215 sim_module_uninstall (sd);
216 return 0;
217 }
218
219 if (sim_post_argv_init (sd) != SIM_RC_OK)
220 {
221 /* Uninstall the modules to avoid memory leaks,
222 file descriptor leaks, etc. */
223 sim_module_uninstall (sd);
224 return 0;
225 }
226
227 /* put all the opcodes in the hash table */
228 for (s = Simops; s->func; s++)
229 {
230 h = &hash_table[hash(s->opcode)];
231
232 /* go to the last entry in the chain */
233 while (h->next)
234 h = h->next;
235
236 if (h->ops)
237 {
238 h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry));
239 h = h->next;
240 }
241 h->ops = s;
242 h->mask = s->mask;
243 h->opcode = s->opcode;
244 }
245
246 return sd;
247 }
248
249
250 void
251 sim_close (sd, quitting)
252 SIM_DESC sd;
253 int quitting;
254 {
255 sim_module_uninstall (sd);
256 }
257
258 static void do_interrupt PARAMS ((SIM_DESC sd, enum interrupt_type));
259
260 int
261 sim_stop (sd)
262 SIM_DESC sd;
263 {
264 return 0;
265 }
266
267 void
268 sim_resume (sd, step, siggnal)
269 SIM_DESC sd;
270 int step, siggnal;
271 {
272 SIM_ELAPSED_TIME start_time;
273 uint32 inst;
274 SIM_ADDR oldpc;
275 struct interrupt_generator *intgen;
276
277 if (step)
278 State.exception = SIGTRAP;
279 else
280 State.exception = 0;
281
282
283 start_time = sim_elapsed_time_get ();
284
285 do
286 {
287 struct hash_entry * h;
288 /* Fetch the current instruction. */
289 inst = RLW (PC);
290 oldpc = PC;
291
292 h = lookup_hash (sd, inst);
293 OP[0] = inst & 0x1f;
294 OP[1] = (inst >> 11) & 0x1f;
295 OP[2] = (inst >> 16) & 0xffff;
296 OP[3] = inst;
297
298 /* fprintf (stderr, "PC = %x, SP = %x\n", PC, SP ); */
299
300 if (inst == 0)
301 {
302 fprintf (stderr, "NOP encountered!\n");
303 break;
304 }
305
306 PC += h->ops->func ();
307
308 if (oldpc == PC)
309 {
310 sim_io_eprintf (sd, "simulator loop at %lx\n", (long) PC );
311 break;
312 }
313
314 /* Check for and handle pending interrupts. */
315 if (intgen_list && (have_nm_generator || !(PSW & PSW_ID)))
316 {
317 intgen = NULL;
318 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
319 {
320 if (intgen->cond_type == int_cond_pc
321 && oldpc == intgen->address
322 && intgen->enabled)
323 {
324 break;
325 }
326 else if (intgen->cond_type == int_cond_time
327 && intgen->enabled)
328 {
329 SIM_ELAPSED_TIME delta;
330 delta = sim_elapsed_time_since (start_time);
331 if (delta > intgen->time)
332 {
333 intgen->enabled = 0;
334 break;
335 }
336 }
337 }
338 if (intgen)
339 do_interrupt (sd, intgen->type);
340 }
341 else if (State.pending_nmi)
342 {
343 State.pending_nmi = 0;
344 do_interrupt (sd, int_nmi);
345 }
346 }
347 while (!State.exception);
348 }
349
350 static void
351 do_interrupt (sd, inttype)
352 SIM_DESC sd;
353 enum interrupt_type inttype;
354 {
355 /* Disable further interrupts. */
356 PSW |= PSW_ID;
357 /* Indicate that we're doing interrupt not exception processing. */
358 PSW &= ~PSW_EP;
359 if (inttype == int_reset)
360 {
361 PC = 0;
362 PSW = 0x20;
363 ECR = 0;
364 /* (Might be useful to init other regs with random values.) */
365 }
366 else if (inttype == int_nmi)
367 {
368 if (PSW & PSW_NP)
369 {
370 /* We're already working on an NMI, so this one must wait
371 around until the previous one is done. The processor
372 ignores subsequent NMIs, so we don't need to count them. */
373 State.pending_nmi = 1;
374 }
375 else
376 {
377 FEPC = PC;
378 FEPSW = PSW;
379 /* Set the FECC part of the ECR. */
380 ECR &= 0x0000ffff;
381 ECR |= 0x10;
382 PSW |= PSW_NP;
383 PC = 0x10;
384 }
385 }
386 else
387 {
388 EIPC = PC;
389 EIPSW = PSW;
390 /* Clear the EICC part of the ECR, will set below. */
391 ECR &= 0xffff0000;
392 switch (inttype)
393 {
394 case int_intov1:
395 PC = 0x80;
396 ECR |= 0x80;
397 break;
398 case int_intp10:
399 PC = 0x90;
400 ECR |= 0x90;
401 break;
402 case int_intp11:
403 PC = 0xa0;
404 ECR |= 0xa0;
405 break;
406 case int_intp12:
407 PC = 0xb0;
408 ECR |= 0xb0;
409 break;
410 case int_intp13:
411 PC = 0xc0;
412 ECR |= 0xc0;
413 break;
414 case int_intcm4:
415 PC = 0xd0;
416 ECR |= 0xd0;
417 break;
418 default:
419 /* Should never be possible. */
420 abort ();
421 break;
422 }
423 }
424 }
425
426 int
427 sim_trace (sd)
428 SIM_DESC sd;
429 {
430 #ifdef DEBUG
431 v850_debug = DEBUG;
432 #endif
433 sim_resume (sd, 0, 0);
434 return 1;
435 }
436
437 void
438 sim_info (sd, verbose)
439 SIM_DESC sd;
440 int verbose;
441 {
442 sim_io_printf (sd, "sim_info\n");
443 }
444
445 SIM_RC
446 sim_create_inferior (sd, prog_bfd, argv, env)
447 SIM_DESC sd;
448 struct _bfd *prog_bfd;
449 char **argv;
450 char **env;
451 {
452 memset (&State, 0, sizeof (State));
453 if (prog_bfd != NULL)
454 PC = bfd_get_start_address (prog_bfd);
455 return SIM_RC_OK;
456 }
457
458 /* All the code for exiting, signals, etc needs to be revamped.
459
460 This is enough to get c-torture limping though. */
461
462 void
463 sim_stop_reason (sd, reason, sigrc)
464 SIM_DESC sd;
465 enum sim_stop *reason;
466 int *sigrc;
467 {
468 if (State.exception == SIG_V850_EXIT)
469 {
470 *reason = sim_exited;
471 *sigrc = State.regs[7];
472 }
473 else
474 {
475 *reason = sim_stopped;
476 *sigrc = State.exception;
477 }
478 }
479
480 void
481 sim_fetch_register (sd, rn, memory)
482 SIM_DESC sd;
483 int rn;
484 unsigned char *memory;
485 {
486 *(unsigned32*)memory = H2T_4 (State.regs[rn]);
487 }
488
489 void
490 sim_store_register (sd, rn, memory)
491 SIM_DESC sd;
492 int rn;
493 unsigned char *memory;
494 {
495 State.regs[rn] = T2H_4 (*(unsigned32*)memory);
496 }
497
498 static int
499 sim_parse_number (str, rest)
500 char *str, **rest;
501 {
502 if (str[0] == '0' && str[1] == 'x')
503 return strtoul (str, rest, 16);
504 else if (str[0] == '0')
505 return strtoul (str, rest, 16);
506 else
507 return strtoul (str, rest, 10);
508 }
509
510 int current_intgen_number = 1;
511
512 static void
513 sim_set_interrupt (sd, spec)
514 SIM_DESC sd;
515 char *spec;
516 {
517 int i, num;
518 char **argv;
519 struct interrupt_generator *intgen, *tmpgen;
520 extern char **buildargv ();
521
522 argv = buildargv (spec);
523
524 if (*argv && ! strcmp (*argv, "add"))
525 {
526 /* Create a new interrupt generator object. */
527 intgen = (struct interrupt_generator *)
528 malloc (sizeof(struct interrupt_generator));
529 intgen->type = int_none;
530 intgen->cond_type = int_cond_none;
531 intgen->address = 0;
532 intgen->time = 0;
533 intgen->enabled = 0;
534 ++argv;
535 /* Match on interrupt type name. */
536 for (i = 0; i < num_int_types; ++i)
537 {
538 if (*argv && ! strcmp (*argv, interrupt_names[i]))
539 {
540 intgen->type = i;
541 break;
542 }
543 }
544 if (intgen->type == int_none)
545 {
546 sim_io_printf (sd, "Interrupt type unknown; known types are\n");
547 for (i = 0; i < num_int_types; ++i)
548 {
549 sim_io_printf (sd, " %s", interrupt_names[i]);
550 }
551 sim_io_printf (sd, "\n");
552 free (intgen);
553 return;
554 }
555 ++argv;
556 intgen->address = 0;
557 intgen->time = 0;
558 if (*argv && ! strcmp (*argv, "pc"))
559 {
560 intgen->cond_type = int_cond_pc;
561 ++argv;
562 intgen->address = sim_parse_number (*argv, NULL);
563 }
564 else if (*argv && ! strcmp (*argv, "time"))
565 {
566 intgen->cond_type = int_cond_time;
567 ++argv;
568 intgen->time = sim_parse_number (*argv, NULL);
569 }
570 else
571 {
572 sim_io_printf (sd, "Condition type must be `pc' or `time'.\n");
573 free (intgen);
574 return;
575 }
576 /* We now have a valid interrupt generator. Number it and add
577 to the list of generators. */
578 intgen->number = current_intgen_number++;
579 intgen->enabled = 1;
580 intgen->next = intgen_list;
581 intgen_list = intgen;
582 sim_io_printf (sd, "Interrupt generator %d (NMI) at pc=0x%x, time=%ld.\n", intgen_list->number, intgen_list->address, intgen_list->time);
583 }
584 else if (*argv && !strcmp (*argv, "remove"))
585 {
586 ++argv;
587 num = sim_parse_number (*argv, NULL);
588 tmpgen = NULL;
589 if (intgen_list)
590 {
591 if (intgen_list->number == num)
592 {
593 tmpgen = intgen_list;
594 intgen_list = intgen_list->next;
595 }
596 else
597 {
598 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
599 {
600 if (intgen->next != NULL && intgen->next->number == num)
601 {
602 tmpgen = intgen->next;
603 intgen->next = intgen->next->next;
604 break;
605 }
606 }
607 }
608 if (tmpgen)
609 free (tmpgen);
610 else
611 sim_io_printf (sd, "No interrupt generator numbered %d, ignoring.\n", num);
612 }
613 }
614 else if (*argv && !strcmp (*argv, "info"))
615 {
616 if (intgen_list)
617 {
618 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
619 sim_io_printf (sd, "Interrupt generator %d (%s) at pc=0x%lx/time=%ld%s.\n",
620 intgen->number,
621 interrupt_names[intgen->type],
622 (long) intgen->address,
623 intgen->time,
624 (intgen->enabled ? "" : " (disabled)"));
625 }
626 else
627 {
628 sim_io_printf (sd, "No interrupt generators defined.\n");
629 }
630
631 }
632 else
633 {
634 sim_io_printf (sd, "Invalid interrupt command, must be one of `add', `remove', or `info'.\n");
635 }
636 /* Cache the presence of a non-maskable generator. */
637 have_nm_generator = 0;
638 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
639 {
640 if (intgen->type == int_nmi || intgen->type == int_reset)
641 {
642 have_nm_generator = 1;
643 break;
644 }
645 }
646 }
647
648 void
649 sim_do_command (sd, cmd)
650 SIM_DESC sd;
651 char *cmd;
652 {
653 char *mm_cmd = "memory-map";
654 char *int_cmd = "interrupt";
655
656 if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
657 sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
658
659 else if (! strncmp (cmd, int_cmd, strlen (int_cmd))
660 && strchr (" ", cmd[strlen(int_cmd)]))
661 sim_set_interrupt (sd, cmd + strlen(int_cmd) + 1);
662
663 else if (sim_args_command (sd, cmd) != SIM_RC_OK)
664 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
665 }
This page took 0.043795 seconds and 5 git commands to generate.