21 enum interrupt_cond_type
28 struct interrupt_generator
30 enum interrupt_type type;
31 enum interrupt_cond_type cond_type;
36 struct interrupt_generator *next;
39 char *interrupt_names[] = {
52 struct interrupt_generator *intgen_list;
54 /* True if a non-maskable (such as NMI or reset) interrupt generator
57 static int have_nm_generator;
67 /* These default values correspond to expected usage for the chip. */
69 SIM_ADDR rom_size = 0x8000;
70 SIM_ADDR low_end = 0x200000;
71 SIM_ADDR high_start = 0xffe000;
75 host_callback *v850_callback;
79 /* non-zero if we opened prog_bfd */
80 static int prog_bfd_was_opened_p;
83 static SIM_OPEN_KIND sim_kind;
88 static struct hash_entry *lookup_hash PARAMS ((uint32 ins));
89 static long hash PARAMS ((long));
90 static void do_format_1_2 PARAMS ((uint32));
91 static void do_format_3 PARAMS ((uint32));
92 static void do_format_4 PARAMS ((uint32));
93 static void do_format_5 PARAMS ((uint32));
94 static void do_format_6 PARAMS ((uint32));
95 static void do_format_7 PARAMS ((uint32));
96 static void do_format_8 PARAMS ((uint32));
97 static void do_format_9_10 PARAMS ((uint32));
98 static void init_system PARAMS ((void));
104 struct hash_entry *next;
110 struct hash_entry hash_table[MAX_HASH+1];
117 if ( (insn & 0x0600) == 0
118 || (insn & 0x0700) == 0x0200
119 || (insn & 0x0700) == 0x0600
120 || (insn & 0x0780) == 0x0700)
121 return (insn & 0x07e0) >> 5;
123 if ((insn & 0x0700) == 0x0300
124 || (insn & 0x0700) == 0x0400
125 || (insn & 0x0700) == 0x0500)
126 return (insn & 0x0780) >> 7;
128 if ((insn & 0x07c0) == 0x0780)
129 return (insn & 0x07c0) >> 6;
131 return (insn & 0x07e0) >> 5;
134 static struct hash_entry *
138 struct hash_entry *h;
140 h = &hash_table[hash(ins)];
142 while ((ins & h->mask) != h->opcode)
146 (*v850_callback->printf_filtered) (v850_callback, "ERROR looking up hash for 0x%x, PC=0x%x\n", ins, PC);
154 /* FIXME These would more efficient to use than load_mem/store_mem,
155 but need to be changed to use the memory map. */
169 return (a[1] << 8) + (a[0]);
177 return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
181 put_byte (addr, data)
190 put_half (addr, data)
196 a[1] = (data >> 8) & 0xff;
200 put_word (addr, data)
206 a[1] = (data >> 8) & 0xff;
207 a[2] = (data >> 16) & 0xff;
208 a[3] = (data >> 24) & 0xff;
217 /* Mask down to 24 bits. */
222 /* "Mirror" the addresses below 1MB. */
224 addr &= (rom_size - 1);
226 addr += (rom_size - 0x100000);
227 return (uint8 *) (addr + State.mem);
229 else if (addr >= high_start)
231 /* If in the peripheral I/O region, mirror 1K region across 4K,
232 and similarly if in the internal RAM region. */
233 if (addr >= 0xfff000)
235 else if (addr >= 0xffe000)
237 return (uint8 *) (addr - high_start + high_base + State.mem);
241 fprintf (stderr, "segmentation fault: access address: %x not below %x or above %x [ep = %x]\n", addr, low_end, high_start, State.regs[30]);
243 /* Signal a memory error. */
244 State.exception = SIGSEGV;
245 /* Point to a location not in main memory - renders invalid
246 addresses harmless until we get back to main insn loop. */
247 return (uint8 *) &(State.dummy_mem);
256 uint8 *p = map (addr);
263 return p[1] << 8 | p[0];
265 return p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
272 store_mem (addr, len, data)
277 uint8 *p = map (addr);
309 totsize = rom_size + (low_end - 0x100000) + (0x1000000 - high_start);
311 high_base = rom_size + (low_end - 0x100000);
313 State.mem = (uint8 *) calloc (1, totsize);
316 (*v850_callback->printf_filtered) (v850_callback, "Allocation of main memory failed.\n");
322 sim_set_memory_map (spec)
325 char *reststr, *nreststr;
326 SIM_ADDR new_low_end, new_high_start;
328 new_low_end = low_end;
329 new_high_start = high_start;
330 if (! strncmp (spec, "hole=", 5))
332 new_low_end = sim_parse_number (spec + 5, &reststr);
333 if (new_low_end < 0x100000)
335 (*v850_callback->printf_filtered) (v850_callback,
336 "Low end must be at least 0x100000\n");
342 new_high_start = sim_parse_number (reststr, &nreststr);
343 /* FIXME Check high_start also */
345 (*v850_callback->printf_filtered) (v850_callback,
346 "Hole goes from 0x%x to 0x%x\n",
347 new_low_end, new_high_start);
351 (*v850_callback->printf_filtered) (v850_callback, "Invalid specification for memory map, must be `hole=<m>[,<n>]'\n");
354 if (new_low_end != low_end || new_high_start != high_start)
356 low_end = new_low_end;
357 high_start = new_high_start;
360 (*v850_callback->printf_filtered) (v850_callback, "Reconfiguring memory (old contents will be lost)\n");
366 /* Parse a number in hex, octal, or decimal form. */
369 sim_parse_number (str, rest)
372 if (str[0] == '0' && str[1] == 'x')
373 return strtol (str, rest, 16);
374 else if (str[0] == '0')
375 return strtol (str, rest, 16);
377 return strtol (str, rest, 10);
388 sim_write (sd, addr, buffer, size)
391 unsigned char *buffer;
398 for (i = 0; i < size; i++)
399 store_mem (addr + i, 1, buffer[i]);
405 sim_open (kind, cb, abfd, argv)
412 struct hash_entry *h;
421 for (p = argv + 1; *p; ++p)
424 if (strcmp (*p, "-t") == 0)
428 (*v850_callback->printf_filtered) (v850_callback, "ERROR: unsupported option(s): %s\n",*p);
432 /* put all the opcodes in the hash table */
433 for (s = Simops; s->func; s++)
435 h = &hash_table[hash(s->opcode)];
437 /* go to the last entry in the chain */
443 h->next = (struct hash_entry *) calloc(1,sizeof(struct hash_entry));
448 h->opcode = s->opcode;
451 /* fudge our descriptor for now */
457 sim_close (sd, quitting)
461 if (prog_bfd != NULL && prog_bfd_was_opened_p)
462 bfd_close (prog_bfd);
469 (*v850_callback->printf_filtered) (v850_callback, "sim_set_profile %d\n", n);
473 sim_set_profile_size (n)
476 (*v850_callback->printf_filtered) (v850_callback, "sim_set_profile_size %d\n", n);
481 static void do_interrupt PARAMS ((enum interrupt_type));
491 sim_resume (sd, step, siggnal)
497 struct interrupt_generator *intgen;
501 State.exception = SIGTRAP;
509 struct hash_entry * h;
510 /* Fetch the current instruction. */
514 h = lookup_hash (inst);
516 OP[1] = (inst >> 11) & 0x1f;
517 OP[2] = (inst >> 16) & 0xffff;
520 // fprintf (stderr, "PC = %x, SP = %x\n", PC, SP );
524 fprintf (stderr, "NOP encountered!\n");
528 PC += h->ops->func ();
532 fprintf (stderr, "simulator loop at %x\n", PC );
536 /* Check for and handle pending interrupts. */
537 if (intgen_list && (have_nm_generator || !(PSW & PSW_ID)))
540 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
542 if (intgen->cond_type == int_cond_pc
543 && oldpc == intgen->address
548 else if (intgen->cond_type == int_cond_time
552 if (((long) now - (long) start_time) > intgen->time)
560 do_interrupt (intgen->type);
562 else if (State.pending_nmi)
564 State.pending_nmi = 0;
565 do_interrupt (int_nmi);
568 while (!State.exception);
572 do_interrupt (inttype)
573 enum interrupt_type inttype;
575 /* Disable further interrupts. */
577 /* Indicate that we're doing interrupt not exception processing. */
579 if (inttype == int_reset)
584 /* (Might be useful to init other regs with random values.) */
586 else if (inttype == int_nmi)
590 /* We're already working on an NMI, so this one must wait
591 around until the previous one is done. The processor
592 ignores subsequent NMIs, so we don't need to count them. */
593 State.pending_nmi = 1;
599 /* Set the FECC part of the ECR. */
610 /* Clear the EICC part of the ECR, will set below. */
639 /* Should never be possible. */
653 sim_resume (sd, 0, 0);
658 sim_info (sd, verbose)
662 (*v850_callback->printf_filtered) (v850_callback, "sim_info\n");
666 sim_create_inferior (sd, argv, env)
675 sim_set_callbacks (p)
681 /* All the code for exiting, signals, etc needs to be revamped.
683 This is enough to get c-torture limping though. */
686 sim_stop_reason (sd, reason, sigrc)
688 enum sim_stop *reason;
691 if (State.exception == SIG_V850_EXIT)
693 *reason = sim_exited;
694 *sigrc = State.regs[7];
698 *reason = sim_stopped;
699 *sigrc = State.exception;
704 sim_fetch_register (sd, rn, memory)
707 unsigned char *memory;
709 put_word (memory, State.regs[rn]);
713 sim_store_register (sd, rn, memory)
716 unsigned char *memory;
718 State.regs[rn] = get_word (memory);
722 sim_read (sd, addr, buffer, size)
725 unsigned char *buffer;
729 for (i = 0; i < size; i++)
730 buffer[i] = load_mem (addr + i, 1);
735 int current_intgen_number = 1;
738 sim_set_interrupt (spec)
743 struct interrupt_generator *intgen, *tmpgen;
744 extern char **buildargv ();
746 argv = buildargv (spec);
748 if (*argv && ! strcmp (*argv, "add"))
750 /* Create a new interrupt generator object. */
751 intgen = (struct interrupt_generator *)
752 malloc (sizeof(struct interrupt_generator));
753 intgen->type = int_none;
754 intgen->cond_type = int_cond_none;
759 /* Match on interrupt type name. */
760 for (i = 0; i < num_int_types; ++i)
762 if (*argv && ! strcmp (*argv, interrupt_names[i]))
768 if (intgen->type == int_none)
770 (*v850_callback->printf_filtered) (v850_callback, "Interrupt type unknown; known types are\n");
771 for (i = 0; i < num_int_types; ++i)
773 (*v850_callback->printf_filtered) (v850_callback, " %s", interrupt_names[i]);
775 (*v850_callback->printf_filtered) (v850_callback, "\n");
782 if (*argv && ! strcmp (*argv, "pc"))
784 intgen->cond_type = int_cond_pc;
786 intgen->address = sim_parse_number (*argv, NULL);
788 else if (*argv && ! strcmp (*argv, "time"))
790 intgen->cond_type = int_cond_time;
792 intgen->time = sim_parse_number (*argv, NULL);
796 (*v850_callback->printf_filtered) (v850_callback, "Condition type must be `pc' or `time'.\n");
800 /* We now have a valid interrupt generator. Number it and add
801 to the list of generators. */
802 intgen->number = current_intgen_number++;
804 intgen->next = intgen_list;
805 intgen_list = intgen;
806 (*v850_callback->printf_filtered) (v850_callback, "Interrupt generator %d (NMI) at pc=0x%x, time=%d.\n", intgen_list->number, intgen_list->address, intgen_list->time);
808 else if (*argv && !strcmp (*argv, "remove"))
811 num = sim_parse_number (*argv, NULL);
815 if (intgen_list->number == num)
817 tmpgen = intgen_list;
818 intgen_list = intgen_list->next;
822 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
824 if (intgen->next != NULL && intgen->next->number == num)
826 tmpgen = intgen->next;
827 intgen->next = intgen->next->next;
835 (*v850_callback->printf_filtered) (v850_callback,
836 "No interrupt generator numbered %d, ignoring.\n", num);
839 else if (*argv && !strcmp (*argv, "info"))
843 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
844 (*v850_callback->printf_filtered) (v850_callback,
845 "Interrupt generator %d (%s) at pc=0x%x/time=%d%s.\n",
847 interrupt_names[intgen->type],
850 (intgen->enabled ? "" : " (disabled)"));
854 (*v850_callback->printf_filtered) (v850_callback, "No interrupt generators defined.\n");
860 (*v850_callback->printf_filtered) (v850_callback,
861 "Invalid interrupt command, must be one of `add', `remove', or `info'.\n");
863 /* Cache the presence of a non-maskable generator. */
864 have_nm_generator = 0;
865 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
867 if (intgen->type == int_nmi || intgen->type == int_reset)
869 have_nm_generator = 1;
876 sim_do_command (sd, cmd)
880 char *mm_cmd = "memory-map";
881 char *int_cmd = "interrupt";
883 if (! strncmp (cmd, mm_cmd, strlen (mm_cmd))
884 && strchr (" ", cmd[strlen(mm_cmd)]))
885 sim_set_memory_map (cmd + strlen(mm_cmd) + 1);
887 else if (! strncmp (cmd, int_cmd, strlen (int_cmd))
888 && strchr (" ", cmd[strlen(int_cmd)]))
889 sim_set_interrupt (cmd + strlen(int_cmd) + 1);
891 else if (! strcmp (cmd, "help"))
893 (*v850_callback->printf_filtered) (v850_callback, "V850 simulator commands:\n\n");
894 (*v850_callback->printf_filtered) (v850_callback, "interrupt add <inttype> { pc | time } <value> -- Set up an interrupt generator\n");
895 (*v850_callback->printf_filtered) (v850_callback, "interrupt remove <n> -- Remove an existing interrupt generator\n");
896 (*v850_callback->printf_filtered) (v850_callback, "interrupt info -- List all the interrupt generators\n");
897 (*v850_callback->printf_filtered) (v850_callback, "memory-map hole=<m>,<n> -- Set the memory map to have a hole between <m> and <n>\n");
898 (*v850_callback->printf_filtered) (v850_callback, "\n");
901 (*v850_callback->printf_filtered) (v850_callback, "\"%s\" is not a valid V850 simulator command.\n",
906 sim_load (sd, prog, abfd, from_tty)
912 extern bfd *sim_load_file (); /* ??? Don't know where this should live. */
914 if (prog_bfd != NULL && prog_bfd_was_opened_p)
915 bfd_close (prog_bfd);
916 prog_bfd = sim_load_file (sd, myname, v850_callback, prog, abfd,
917 sim_kind == SIM_OPEN_DEBUG);
918 if (prog_bfd == NULL)
920 PC = bfd_get_start_address (prog_bfd);
921 prog_bfd_was_opened_p = abfd == NULL;