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)
682 sim_set_callbacks (p)
688 /* All the code for exiting, signals, etc needs to be revamped.
690 This is enough to get c-torture limping though. */
693 sim_stop_reason (sd, reason, sigrc)
695 enum sim_stop *reason;
698 if (State.exception == SIG_V850_EXIT)
700 *reason = sim_exited;
701 *sigrc = State.regs[7];
705 *reason = sim_stopped;
706 *sigrc = State.exception;
711 sim_fetch_register (sd, rn, memory)
714 unsigned char *memory;
716 put_word (memory, State.regs[rn]);
720 sim_store_register (sd, rn, memory)
723 unsigned char *memory;
725 State.regs[rn] = get_word (memory);
729 sim_read (sd, addr, buffer, size)
732 unsigned char *buffer;
736 for (i = 0; i < size; i++)
737 buffer[i] = load_mem (addr + i, 1);
742 int current_intgen_number = 1;
745 sim_set_interrupt (spec)
750 struct interrupt_generator *intgen, *tmpgen;
751 extern char **buildargv ();
753 argv = buildargv (spec);
755 if (*argv && ! strcmp (*argv, "add"))
757 /* Create a new interrupt generator object. */
758 intgen = (struct interrupt_generator *)
759 malloc (sizeof(struct interrupt_generator));
760 intgen->type = int_none;
761 intgen->cond_type = int_cond_none;
766 /* Match on interrupt type name. */
767 for (i = 0; i < num_int_types; ++i)
769 if (*argv && ! strcmp (*argv, interrupt_names[i]))
775 if (intgen->type == int_none)
777 (*v850_callback->printf_filtered) (v850_callback, "Interrupt type unknown; known types are\n");
778 for (i = 0; i < num_int_types; ++i)
780 (*v850_callback->printf_filtered) (v850_callback, " %s", interrupt_names[i]);
782 (*v850_callback->printf_filtered) (v850_callback, "\n");
789 if (*argv && ! strcmp (*argv, "pc"))
791 intgen->cond_type = int_cond_pc;
793 intgen->address = sim_parse_number (*argv, NULL);
795 else if (*argv && ! strcmp (*argv, "time"))
797 intgen->cond_type = int_cond_time;
799 intgen->time = sim_parse_number (*argv, NULL);
803 (*v850_callback->printf_filtered) (v850_callback, "Condition type must be `pc' or `time'.\n");
807 /* We now have a valid interrupt generator. Number it and add
808 to the list of generators. */
809 intgen->number = current_intgen_number++;
811 intgen->next = intgen_list;
812 intgen_list = intgen;
813 (*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);
815 else if (*argv && !strcmp (*argv, "remove"))
818 num = sim_parse_number (*argv, NULL);
822 if (intgen_list->number == num)
824 tmpgen = intgen_list;
825 intgen_list = intgen_list->next;
829 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
831 if (intgen->next != NULL && intgen->next->number == num)
833 tmpgen = intgen->next;
834 intgen->next = intgen->next->next;
842 (*v850_callback->printf_filtered) (v850_callback,
843 "No interrupt generator numbered %d, ignoring.\n", num);
846 else if (*argv && !strcmp (*argv, "info"))
850 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
851 (*v850_callback->printf_filtered) (v850_callback,
852 "Interrupt generator %d (%s) at pc=0x%x/time=%d%s.\n",
854 interrupt_names[intgen->type],
857 (intgen->enabled ? "" : " (disabled)"));
861 (*v850_callback->printf_filtered) (v850_callback, "No interrupt generators defined.\n");
867 (*v850_callback->printf_filtered) (v850_callback,
868 "Invalid interrupt command, must be one of `add', `remove', or `info'.\n");
870 /* Cache the presence of a non-maskable generator. */
871 have_nm_generator = 0;
872 for (intgen = intgen_list; intgen != NULL; intgen = intgen->next)
874 if (intgen->type == int_nmi || intgen->type == int_reset)
876 have_nm_generator = 1;
883 sim_do_command (sd, cmd)
887 char *mm_cmd = "memory-map";
888 char *int_cmd = "interrupt";
890 if (! strncmp (cmd, mm_cmd, strlen (mm_cmd))
891 && strchr (" ", cmd[strlen(mm_cmd)]))
892 sim_set_memory_map (cmd + strlen(mm_cmd) + 1);
894 else if (! strncmp (cmd, int_cmd, strlen (int_cmd))
895 && strchr (" ", cmd[strlen(int_cmd)]))
896 sim_set_interrupt (cmd + strlen(int_cmd) + 1);
898 else if (! strcmp (cmd, "help"))
900 (*v850_callback->printf_filtered) (v850_callback, "V850 simulator commands:\n\n");
901 (*v850_callback->printf_filtered) (v850_callback, "interrupt add <inttype> { pc | time } <value> -- Set up an interrupt generator\n");
902 (*v850_callback->printf_filtered) (v850_callback, "interrupt remove <n> -- Remove an existing interrupt generator\n");
903 (*v850_callback->printf_filtered) (v850_callback, "interrupt info -- List all the interrupt generators\n");
904 (*v850_callback->printf_filtered) (v850_callback, "memory-map hole=<m>,<n> -- Set the memory map to have a hole between <m> and <n>\n");
905 (*v850_callback->printf_filtered) (v850_callback, "\n");
908 (*v850_callback->printf_filtered) (v850_callback, "\"%s\" is not a valid V850 simulator command.\n",
913 sim_load (sd, prog, abfd, from_tty)
919 extern bfd *sim_load_file (); /* ??? Don't know where this should live. */
921 if (prog_bfd != NULL && prog_bfd_was_opened_p)
922 bfd_close (prog_bfd);
923 prog_bfd = sim_load_file (sd, myname, v850_callback, prog, abfd,
924 sim_kind == SIM_OPEN_DEBUG);
925 if (prog_bfd == NULL)
927 PC = bfd_get_start_address (prog_bfd);
928 prog_bfd_was_opened_p = abfd == NULL;