1#include "sim-main.h" 2#include "sim-options.h" 3#include "v850_sim.h" 4#include "sim-assert.h" 5#include "itable.h" 6 7#ifdef HAVE_STDLIB_H 8#include <stdlib.h> 9#endif 10 11#ifdef HAVE_STRING_H 12#include <string.h> 13#else 14#ifdef HAVE_STRINGS_H 15#include <strings.h> 16#endif 17#endif 18 19#include "bfd.h" 20 21#ifndef INLINE 22#ifdef __GNUC__ 23#define INLINE inline 24#else 25#define INLINE 26#endif 27#endif 28 29static const char * get_insn_name (sim_cpu *, int); 30 31/* For compatibility */ 32SIM_DESC simulator; 33 34 35 36/* v850 interrupt model */ 37 38enum interrupt_type 39{ 40 int_reset, 41 int_nmi, 42 int_intov1, 43 int_intp10, 44 int_intp11, 45 int_intp12, 46 int_intp13, 47 int_intcm4, 48 num_int_types 49}; 50 51char *interrupt_names[] = { 52 "reset", 53 "nmi", 54 "intov1", 55 "intp10", 56 "intp11", 57 "intp12", 58 "intp13", 59 "intcm4", 60 NULL 61}; 62 63static void 64do_interrupt (sd, data) 65 SIM_DESC sd; 66 void *data; 67{ 68 char **interrupt_name = (char**)data; 69 enum interrupt_type inttype; 70 inttype = (interrupt_name - STATE_WATCHPOINTS (sd)->interrupt_names); 71 72 /* For a hardware reset, drop everything and jump to the start 73 address */ 74 if (inttype == int_reset) 75 { 76 PC = 0; 77 PSW = 0x20; 78 ECR = 0; 79 sim_engine_restart (sd, NULL, NULL, NULL_CIA); 80 } 81 82 /* Deliver an NMI when allowed */ 83 if (inttype == int_nmi) 84 { 85 if (PSW & PSW_NP) 86 { 87 /* We're already working on an NMI, so this one must wait 88 around until the previous one is done. The processor 89 ignores subsequent NMIs, so we don't need to count them. 90 Just keep re-scheduling a single NMI until it manages to 91 be delivered */ 92 if (STATE_CPU (sd, 0)->pending_nmi != NULL) 93 sim_events_deschedule (sd, STATE_CPU (sd, 0)->pending_nmi); 94 STATE_CPU (sd, 0)->pending_nmi = 95 sim_events_schedule (sd, 1, do_interrupt, data); 96 return; 97 } 98 else 99 { 100 /* NMI can be delivered. Do not deschedule pending_nmi as 101 that, if still in the event queue, is a second NMI that 102 needs to be delivered later. */ 103 FEPC = PC; 104 FEPSW = PSW; 105 /* Set the FECC part of the ECR. */ 106 ECR &= 0x0000ffff; 107 ECR |= 0x10; 108 PSW |= PSW_NP; 109 PSW &= ~PSW_EP; 110 PSW |= PSW_ID; 111 PC = 0x10; 112 sim_engine_restart (sd, NULL, NULL, NULL_CIA); 113 } 114 } 115 116 /* deliver maskable interrupt when allowed */ 117 if (inttype > int_nmi && inttype < num_int_types) 118 { 119 if ((PSW & PSW_NP) || (PSW & PSW_ID)) 120 { 121 /* Can't deliver this interrupt, reschedule it for later */ 122 sim_events_schedule (sd, 1, do_interrupt, data); 123 return; 124 } 125 else 126 { 127 /* save context */ 128 EIPC = PC; 129 EIPSW = PSW; 130 /* Disable further interrupts. */ 131 PSW |= PSW_ID; 132 /* Indicate that we're doing interrupt not exception processing. */ 133 PSW &= ~PSW_EP; 134 /* Clear the EICC part of the ECR, will set below. */ 135 ECR &= 0xffff0000; 136 switch (inttype) 137 { 138 case int_intov1: 139 PC = 0x80; 140 ECR |= 0x80; 141 break; 142 case int_intp10: 143 PC = 0x90; 144 ECR |= 0x90; 145 break; 146 case int_intp11: 147 PC = 0xa0; 148 ECR |= 0xa0; 149 break; 150 case int_intp12: 151 PC = 0xb0; 152 ECR |= 0xb0; 153 break; 154 case int_intp13: 155 PC = 0xc0; 156 ECR |= 0xc0; 157 break; 158 case int_intcm4: 159 PC = 0xd0; 160 ECR |= 0xd0; 161 break; 162 default: 163 /* Should never be possible. */ 164 sim_engine_abort (sd, NULL, NULL_CIA, 165 "do_interrupt - internal error - bad switch"); 166 break; 167 } 168 } 169 sim_engine_restart (sd, NULL, NULL, NULL_CIA); 170 } 171 172 /* some other interrupt? */ 173 sim_engine_abort (sd, NULL, NULL_CIA, 174 "do_interrupt - internal error - interrupt %d unknown", 175 inttype); 176} 177 178/* Return name of an insn, used by insn profiling. */ 179 180static const char * 181get_insn_name (sim_cpu *cpu, int i) 182{ 183 return itable[i].name; 184} 185 186/* These default values correspond to expected usage for the chip. */ 187 188uint32 OP[4]; 189 190 191SIM_DESC 192sim_open (kind, cb, abfd, argv) 193 SIM_OPEN_KIND kind; 194 host_callback *cb; 195 struct bfd *abfd; 196 char **argv; 197{ 198 SIM_DESC sd = sim_state_alloc (kind, cb); 199 int mach; 200 201 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 202 203 /* for compatibility */ 204 simulator = sd; 205 206 /* FIXME: should be better way of setting up interrupts */ 207 STATE_WATCHPOINTS (sd)->pc = &(PC); 208 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC); 209 STATE_WATCHPOINTS (sd)->interrupt_handler = do_interrupt; 210 STATE_WATCHPOINTS (sd)->interrupt_names = interrupt_names; 211 212 /* Initialize the mechanism for doing insn profiling. */ 213 CPU_INSN_NAME (STATE_CPU (sd, 0)) = get_insn_name; 214 CPU_MAX_INSNS (STATE_CPU (sd, 0)) = nr_itable_entries; 215 216 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) 217 return 0; 218 219 /* Allocate core managed memory */ 220 221 /* "Mirror" the ROM addresses below 1MB. */ 222 sim_do_commandf (sd, "memory region 0,0x100000,0x%lx", V850_ROM_SIZE); 223 /* Chunk of ram adjacent to rom */ 224 sim_do_commandf (sd, "memory region 0x100000,0x%lx", V850_LOW_END-0x100000); 225 /* peripheral I/O region - mirror 1K across 4k (0x1000) */ 226 sim_do_command (sd, "memory region 0xfff000,0x1000,1024"); 227 /* similarly if in the internal RAM region */ 228 sim_do_command (sd, "memory region 0xffe000,0x1000,1024"); 229 230 /* getopt will print the error message so we just have to exit if this fails. 231 FIXME: Hmmm... in the case of gdb we need getopt to call 232 print_filtered. */ 233 if (sim_parse_args (sd, argv) != SIM_RC_OK) 234 { 235 /* Uninstall the modules to avoid memory leaks, 236 file descriptor leaks, etc. */ 237 sim_module_uninstall (sd); 238 return 0; 239 } 240 241 /* check for/establish the a reference program image */ 242 if (sim_analyze_program (sd, 243 (STATE_PROG_ARGV (sd) != NULL 244 ? *STATE_PROG_ARGV (sd) 245 : NULL), 246 abfd) != SIM_RC_OK) 247 { 248 sim_module_uninstall (sd); 249 return 0; 250 } 251 252 /* establish any remaining configuration options */ 253 if (sim_config (sd) != SIM_RC_OK) 254 { 255 sim_module_uninstall (sd); 256 return 0; 257 } 258 259 if (sim_post_argv_init (sd) != SIM_RC_OK) 260 { 261 /* Uninstall the modules to avoid memory leaks, 262 file descriptor leaks, etc. */ 263 sim_module_uninstall (sd); 264 return 0; 265 } 266 267 268 /* determine the machine type */ 269 if (STATE_ARCHITECTURE (sd) != NULL 270 && STATE_ARCHITECTURE (sd)->arch == bfd_arch_v850) 271 mach = STATE_ARCHITECTURE (sd)->mach; 272 else 273 mach = bfd_mach_v850; /* default */ 274 275 /* set machine specific configuration */ 276 switch (mach) 277 { 278 case bfd_mach_v850: 279 case bfd_mach_v850e: 280 case bfd_mach_v850e1: 281 STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT 282 | PSW_CY | PSW_OV | PSW_S | PSW_Z); 283 break; 284 } 285 286 return sd; 287} 288 289 290void 291sim_close (sd, quitting) 292 SIM_DESC sd; 293 int quitting; 294{ 295 sim_module_uninstall (sd); 296} 297 298SIM_RC 299sim_create_inferior (sd, prog_bfd, argv, env) 300 SIM_DESC sd; 301 struct bfd *prog_bfd; 302 char **argv; 303 char **env; 304{ 305 memset (&State, 0, sizeof (State)); 306 if (prog_bfd != NULL) 307 PC = bfd_get_start_address (prog_bfd); 308 return SIM_RC_OK; 309} 310 311int 312sim_fetch_register (sd, rn, memory, length) 313 SIM_DESC sd; 314 int rn; 315 unsigned char *memory; 316 int length; 317{ 318 *(unsigned32*)memory = H2T_4 (State.regs[rn]); 319 return -1; 320} 321 322int 323sim_store_register (sd, rn, memory, length) 324 SIM_DESC sd; 325 int rn; 326 unsigned char *memory; 327 int length; 328{ 329 State.regs[rn] = T2H_4 (*(unsigned32*)memory); 330 return -1; 331} 332 333void 334sim_do_command (sd, cmd) 335 SIM_DESC sd; 336 char *cmd; 337{ 338 char *mm_cmd = "memory-map"; 339 char *int_cmd = "interrupt"; 340 341 if (sim_args_command (sd, cmd) != SIM_RC_OK) 342 { 343 if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0)) 344 sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n"); 345 else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0) 346 sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n"); 347 else 348 sim_io_eprintf (sd, "Unknown command `%s'\n", cmd); 349 } 350} 351