123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- #include "sim-main.h"
- #include "sim-options.h"
- #include "v850_sim.h"
- #include "sim-assert.h"
- #include "itable.h"
- #ifdef HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #ifdef HAVE_STRING_H
- #include <string.h>
- #else
- #ifdef HAVE_STRINGS_H
- #include <strings.h>
- #endif
- #endif
- #include "bfd.h"
- static const char * get_insn_name (sim_cpu *, int);
- /* For compatibility. */
- SIM_DESC simulator;
- /* V850 interrupt model. */
- enum interrupt_type
- {
- int_reset,
- int_nmi,
- int_intov1,
- int_intp10,
- int_intp11,
- int_intp12,
- int_intp13,
- int_intcm4,
- num_int_types
- };
- const char *interrupt_names[] =
- {
- "reset",
- "nmi",
- "intov1",
- "intp10",
- "intp11",
- "intp12",
- "intp13",
- "intcm4",
- NULL
- };
- static void
- do_interrupt (SIM_DESC sd, void *data)
- {
- const char **interrupt_name = (const char**)data;
- enum interrupt_type inttype;
- inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names);
- /* For a hardware reset, drop everything and jump to the start
- address */
- if (inttype == int_reset)
- {
- PC = 0;
- PSW = 0x20;
- ECR = 0;
- sim_engine_restart (sd, NULL, NULL, NULL_CIA);
- }
- /* Deliver an NMI when allowed */
- if (inttype == int_nmi)
- {
- if (PSW & PSW_NP)
- {
- /* We're already working on an NMI, so this one must wait
- around until the previous one is done. The processor
- ignores subsequent NMIs, so we don't need to count them.
- Just keep re-scheduling a single NMI until it manages to
- be delivered */
- if (STATE_CPU (sd, 0)->pending_nmi != NULL)
- sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi);
- STATE_CPU (sd, 0)->pending_nmi =
- sim_events_schedule (sd, 1, do_interrupt, data);
- return;
- }
- else
- {
- /* NMI can be delivered. Do not deschedule pending_nmi as
- that, if still in the event queue, is a second NMI that
- needs to be delivered later. */
- FEPC = PC;
- FEPSW = PSW;
- /* Set the FECC part of the ECR. */
- ECR &= 0x0000ffff;
- ECR |= 0x10;
- PSW |= PSW_NP;
- PSW &= ~PSW_EP;
- PSW |= PSW_ID;
- PC = 0x10;
- sim_engine_restart (sd, NULL, NULL, NULL_CIA);
- }
- }
- /* deliver maskable interrupt when allowed */
- if (inttype > int_nmi && inttype < num_int_types)
- {
- if ((PSW & PSW_NP) || (PSW & PSW_ID))
- {
- /* Can't deliver this interrupt, reschedule it for later */
- sim_events_schedule (sd, 1, do_interrupt, data);
- return;
- }
- else
- {
- /* save context */
- EIPC = PC;
- EIPSW = PSW;
- /* Disable further interrupts. */
- PSW |= PSW_ID;
- /* Indicate that we're doing interrupt not exception processing. */
- PSW &= ~PSW_EP;
- /* Clear the EICC part of the ECR, will set below. */
- ECR &= 0xffff0000;
- switch (inttype)
- {
- case int_intov1:
- PC = 0x80;
- ECR |= 0x80;
- break;
- case int_intp10:
- PC = 0x90;
- ECR |= 0x90;
- break;
- case int_intp11:
- PC = 0xa0;
- ECR |= 0xa0;
- break;
- case int_intp12:
- PC = 0xb0;
- ECR |= 0xb0;
- break;
- case int_intp13:
- PC = 0xc0;
- ECR |= 0xc0;
- break;
- case int_intcm4:
- PC = 0xd0;
- ECR |= 0xd0;
- break;
- default:
- /* Should never be possible. */
- sim_engine_abort (sd, NULL, NULL_CIA,
- "do_interrupt - internal error - bad switch");
- break;
- }
- }
- sim_engine_restart (sd, NULL, NULL, NULL_CIA);
- }
-
- /* some other interrupt? */
- sim_engine_abort (sd, NULL, NULL_CIA,
- "do_interrupt - internal error - interrupt %d unknown",
- inttype);
- }
- /* Return name of an insn, used by insn profiling. */
- static const char *
- get_insn_name (sim_cpu *cpu, int i)
- {
- return itable[i].name;
- }
- /* These default values correspond to expected usage for the chip. */
- uint32 OP[4];
- static sim_cia
- v850_pc_get (sim_cpu *cpu)
- {
- return PC;
- }
- static void
- v850_pc_set (sim_cpu *cpu, sim_cia pc)
- {
- PC = pc;
- }
- SIM_DESC
- sim_open (SIM_OPEN_KIND kind,
- host_callback * cb,
- struct bfd * abfd,
- char ** argv)
- {
- int i;
- SIM_DESC sd = sim_state_alloc (kind, cb);
- int mach;
- SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
- /* The cpu data is kept in a separately allocated chunk of memory. */
- if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
- return 0;
- /* for compatibility */
- simulator = sd;
- /* FIXME: should be better way of setting up interrupts */
- STATE_WATCHPOINTS (sd)->pc = &(PC);
- STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
- STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt;
- STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names;
- /* Initialize the mechanism for doing insn profiling. */
- CPU_INSN_NAME (STATE_CPU (sd, 0)) = get_insn_name;
- CPU_MAX_INSNS (STATE_CPU (sd, 0)) = nr_itable_entries;
- if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
- return 0;
- /* Allocate core managed memory */
- /* "Mirror" the ROM addresses below 1MB. */
- sim_do_commandf (sd, "memory region 0,0x100000,0x%lx", V850_ROM_SIZE);
- /* Chunk of ram adjacent to rom */
- sim_do_commandf (sd, "memory region 0x100000,0x%lx", V850_LOW_END-0x100000);
- /* peripheral I/O region - mirror 1K across 4k (0x1000) */
- sim_do_command (sd, "memory region 0xfff000,0x1000,1024");
- /* similarly if in the internal RAM region */
- sim_do_command (sd, "memory region 0xffe000,0x1000,1024");
- /* getopt will print the error message so we just have to exit if this fails.
- FIXME: Hmmm... in the case of gdb we need getopt to call
- print_filtered. */
- if (sim_parse_args (sd, argv) != SIM_RC_OK)
- {
- /* Uninstall the modules to avoid memory leaks,
- file descriptor leaks, etc. */
- sim_module_uninstall (sd);
- return 0;
- }
- /* check for/establish the a reference program image */
- if (sim_analyze_program (sd,
- (STATE_PROG_ARGV (sd) != NULL
- ? *STATE_PROG_ARGV (sd)
- : NULL),
- abfd) != SIM_RC_OK)
- {
- sim_module_uninstall (sd);
- return 0;
- }
- /* establish any remaining configuration options */
- if (sim_config (sd) != SIM_RC_OK)
- {
- sim_module_uninstall (sd);
- return 0;
- }
- if (sim_post_argv_init (sd) != SIM_RC_OK)
- {
- /* Uninstall the modules to avoid memory leaks,
- file descriptor leaks, etc. */
- sim_module_uninstall (sd);
- return 0;
- }
- /* determine the machine type */
- if (STATE_ARCHITECTURE (sd) != NULL
- && (STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850
- || STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850_rh850))
- mach = STATE_ARCHITECTURE (sd)->mach;
- else
- mach = bfd_mach_v850; /* default */
- /* set machine specific configuration */
- switch (mach)
- {
- case bfd_mach_v850:
- case bfd_mach_v850e:
- case bfd_mach_v850e1:
- case bfd_mach_v850e2:
- case bfd_mach_v850e2v3:
- case bfd_mach_v850e3v5:
- STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT
- | PSW_CY | PSW_OV | PSW_S | PSW_Z);
- break;
- }
- /* CPU specific initialization. */
- for (i = 0; i < MAX_NR_PROCESSORS; ++i)
- {
- SIM_CPU *cpu = STATE_CPU (sd, i);
- CPU_PC_FETCH (cpu) = v850_pc_get;
- CPU_PC_STORE (cpu) = v850_pc_set;
- }
- return sd;
- }
- void
- sim_close (SIM_DESC sd, int quitting)
- {
- sim_module_uninstall (sd);
- }
- SIM_RC
- sim_create_inferior (SIM_DESC sd,
- struct bfd * prog_bfd,
- char ** argv,
- char ** env)
- {
- memset (&State, 0, sizeof (State));
- if (prog_bfd != NULL)
- PC = bfd_get_start_address (prog_bfd);
- return SIM_RC_OK;
- }
- int
- sim_fetch_register (SIM_DESC sd,
- int rn,
- unsigned char * memory,
- int length)
- {
- *(unsigned32*)memory = H2T_4 (State.regs[rn]);
- return -1;
- }
-
- int
- sim_store_register (SIM_DESC sd,
- int rn,
- unsigned char * memory,
- int length)
- {
- State.regs[rn] = T2H_4 (*(unsigned32 *) memory);
- return length;
- }
|