1 1.1 christos /*> interp.c <*/ 2 1.1 christos /* Simulator for the MIPS architecture. 3 1.1 christos 4 1.1 christos This file is part of the MIPS sim 5 1.1 christos 6 1.1 christos THIS SOFTWARE IS NOT COPYRIGHTED 7 1.1 christos 8 1.1 christos Cygnus offers the following for use in the public domain. Cygnus 9 1.1 christos makes no warranty with regard to the software or it's performance 10 1.1 christos and the user accepts the software "AS IS" with all faults. 11 1.1 christos 12 1.1 christos CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO 13 1.1 christos THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 14 1.1 christos MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 15 1.1 christos 16 1.1 christos NOTEs: 17 1.1 christos 18 1.1 christos The IDT monitor (found on the VR4300 board), seems to lie about 19 1.1 christos register contents. It seems to treat the registers as sign-extended 20 1.1 christos 32-bit values. This cause *REAL* problems when single-stepping 64-bit 21 1.1 christos code on the hardware. 22 1.1 christos 23 1.1 christos */ 24 1.1 christos 25 1.7 christos /* This must come before any other includes. */ 26 1.7 christos #include "defs.h" 27 1.7 christos 28 1.1 christos #include "bfd.h" 29 1.1 christos #include "sim-main.h" 30 1.1 christos #include "sim-utils.h" 31 1.1 christos #include "sim-options.h" 32 1.1 christos #include "sim-assert.h" 33 1.1 christos #include "sim-hw.h" 34 1.7 christos #include "sim-signal.h" 35 1.1 christos 36 1.1 christos #include "itable.h" 37 1.1 christos 38 1.1 christos #include <stdio.h> 39 1.1 christos #include <stdarg.h> 40 1.1 christos #include <ansidecl.h> 41 1.1 christos #include <ctype.h> 42 1.1 christos #include <limits.h> 43 1.1 christos #include <math.h> 44 1.1 christos #include <stdlib.h> 45 1.1 christos #include <string.h> 46 1.1 christos 47 1.1 christos #include "getopt.h" 48 1.1 christos #include "libiberty.h" 49 1.1 christos #include "bfd.h" 50 1.8 christos #include "bfd/elf-bfd.h" 51 1.7 christos #include "sim/callback.h" /* GDB simulator callback interface */ 52 1.7 christos #include "sim/sim.h" /* GDB simulator interface */ 53 1.7 christos #include "sim-syscall.h" /* Simulator system call support */ 54 1.1 christos 55 1.8 christos char* pr_addr (address_word addr); 56 1.1 christos char* pr_uword64 (uword64 addr); 57 1.1 christos 58 1.1 christos 59 1.1 christos /* Within interp.c we refer to the sim_state and sim_cpu directly. */ 60 1.1 christos #define CPU cpu 61 1.1 christos #define SD sd 62 1.1 christos 63 1.1 christos 64 1.1 christos /* The following reserved instruction value is used when a simulator 65 1.1 christos trap is required. NOTE: Care must be taken, since this value may be 66 1.1 christos used in later revisions of the MIPS ISA. */ 67 1.1 christos 68 1.6 christos #define RSVD_INSTRUCTION (0x00000039) 69 1.1 christos #define RSVD_INSTRUCTION_MASK (0xFC00003F) 70 1.1 christos 71 1.1 christos #define RSVD_INSTRUCTION_ARG_SHIFT 6 72 1.7 christos #define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF 73 1.1 christos 74 1.1 christos 75 1.1 christos /* Bits in the Debug register */ 76 1.1 christos #define Debug_DBD 0x80000000 /* Debug Branch Delay */ 77 1.1 christos #define Debug_DM 0x40000000 /* Debug Mode */ 78 1.1 christos #define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */ 79 1.1 christos 80 1.1 christos /*---------------------------------------------------------------------------*/ 81 1.1 christos /*-- GDB simulator interface ------------------------------------------------*/ 82 1.1 christos /*---------------------------------------------------------------------------*/ 83 1.1 christos 84 1.1 christos static void ColdReset (SIM_DESC sd); 85 1.1 christos 86 1.1 christos /*---------------------------------------------------------------------------*/ 87 1.1 christos 88 1.1 christos 89 1.1 christos 90 1.1 christos #define DELAYSLOT() {\ 91 1.1 christos if (STATE & simDELAYSLOT)\ 92 1.1 christos sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\ 93 1.1 christos STATE |= simDELAYSLOT;\ 94 1.1 christos } 95 1.1 christos 96 1.1 christos #define JALDELAYSLOT() {\ 97 1.1 christos DELAYSLOT ();\ 98 1.1 christos STATE |= simJALDELAYSLOT;\ 99 1.1 christos } 100 1.1 christos 101 1.1 christos #define NULLIFY() {\ 102 1.1 christos STATE &= ~simDELAYSLOT;\ 103 1.1 christos STATE |= simSKIPNEXT;\ 104 1.1 christos } 105 1.1 christos 106 1.1 christos #define CANCELDELAYSLOT() {\ 107 1.1 christos DSSTATE = 0;\ 108 1.1 christos STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\ 109 1.1 christos } 110 1.1 christos 111 1.1 christos #define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0) 112 1.1 christos #define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0) 113 1.1 christos 114 1.1 christos /* Note that the monitor code essentially assumes this layout of memory. 115 1.1 christos If you change these, change the monitor code, too. */ 116 1.1 christos /* FIXME Currently addresses are truncated to 32-bits, see 117 1.1 christos mips/sim-main.c:address_translation(). If that changes, then these 118 1.1 christos values will need to be extended, and tested for more carefully. */ 119 1.1 christos #define K0BASE (0x80000000) 120 1.1 christos #define K0SIZE (0x20000000) 121 1.1 christos #define K1BASE (0xA0000000) 122 1.1 christos #define K1SIZE (0x20000000) 123 1.1 christos 124 1.1 christos /* Simple run-time monitor support. 125 1.7 christos 126 1.1 christos We emulate the monitor by placing magic reserved instructions at 127 1.1 christos the monitor's entry points; when we hit these instructions, instead 128 1.1 christos of raising an exception (as we would normally), we look at the 129 1.1 christos instruction and perform the appropriate monitory operation. 130 1.7 christos 131 1.7 christos `*_monitor_base' are the physical addresses at which the corresponding 132 1.1 christos monitor vectors are located. `0' means none. By default, 133 1.1 christos install all three. 134 1.1 christos The RSVD_INSTRUCTION... macros specify the magic instructions we 135 1.1 christos use at the monitor entry points. */ 136 1.1 christos static int firmware_option_p = 0; 137 1.8 christos static address_word idt_monitor_base = 0xBFC00000; 138 1.8 christos static address_word pmon_monitor_base = 0xBFC00500; 139 1.8 christos static address_word lsipmon_monitor_base = 0xBFC00200; 140 1.1 christos 141 1.1 christos static SIM_RC sim_firmware_command (SIM_DESC sd, char* arg); 142 1.1 christos 143 1.1 christos #define MEM_SIZE (8 << 20) /* 8 MBytes */ 144 1.1 christos 145 1.1 christos 146 1.5 christos #if WITH_TRACE_ANY_P 147 1.1 christos static char *tracefile = "trace.din"; /* default filename for trace log */ 148 1.1 christos FILE *tracefh = NULL; 149 1.1 christos static void open_trace (SIM_DESC sd); 150 1.5 christos #else 151 1.5 christos #define open_trace(sd) 152 1.5 christos #endif 153 1.1 christos 154 1.1 christos static const char * get_insn_name (sim_cpu *, int); 155 1.1 christos 156 1.1 christos /* simulation target board. NULL=canonical */ 157 1.1 christos static char* board = NULL; 158 1.1 christos 159 1.1 christos 160 1.1 christos static DECLARE_OPTION_HANDLER (mips_option_handler); 161 1.1 christos 162 1.1 christos enum { 163 1.1 christos OPTION_DINERO_TRACE = OPTION_START, 164 1.1 christos OPTION_DINERO_FILE, 165 1.1 christos OPTION_FIRMWARE, 166 1.1 christos OPTION_INFO_MEMORY, 167 1.1 christos OPTION_BOARD 168 1.1 christos }; 169 1.1 christos 170 1.1 christos static int display_mem_info = 0; 171 1.1 christos 172 1.1 christos static SIM_RC 173 1.5 christos mips_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, char *arg, 174 1.5 christos int is_command) 175 1.1 christos { 176 1.1 christos int cpu_nr; 177 1.1 christos switch (opt) 178 1.1 christos { 179 1.1 christos case OPTION_DINERO_TRACE: /* ??? */ 180 1.5 christos #if WITH_TRACE_ANY_P 181 1.1 christos /* Eventually the simTRACE flag could be treated as a toggle, to 182 1.1 christos allow external control of the program points being traced 183 1.1 christos (i.e. only from main onwards, excluding the run-time setup, 184 1.1 christos etc.). */ 185 1.1 christos for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++) 186 1.1 christos { 187 1.8 christos cpu = STATE_CPU (sd, cpu_nr); 188 1.1 christos if (arg == NULL) 189 1.1 christos STATE |= simTRACE; 190 1.1 christos else if (strcmp (arg, "yes") == 0) 191 1.1 christos STATE |= simTRACE; 192 1.1 christos else if (strcmp (arg, "no") == 0) 193 1.1 christos STATE &= ~simTRACE; 194 1.1 christos else if (strcmp (arg, "on") == 0) 195 1.1 christos STATE |= simTRACE; 196 1.1 christos else if (strcmp (arg, "off") == 0) 197 1.1 christos STATE &= ~simTRACE; 198 1.1 christos else 199 1.1 christos { 200 1.1 christos fprintf (stderr, "Unrecognized dinero-trace option `%s'\n", arg); 201 1.1 christos return SIM_RC_FAIL; 202 1.1 christos } 203 1.1 christos } 204 1.1 christos return SIM_RC_OK; 205 1.5 christos #else /* !WITH_TRACE_ANY_P */ 206 1.1 christos fprintf(stderr,"\ 207 1.1 christos Simulator constructed without dinero tracing support (for performance).\n\ 208 1.5 christos Re-compile simulator with \"-DWITH_TRACE_ANY_P\" to enable this option.\n"); 209 1.1 christos return SIM_RC_FAIL; 210 1.5 christos #endif /* !WITH_TRACE_ANY_P */ 211 1.1 christos 212 1.1 christos case OPTION_DINERO_FILE: 213 1.5 christos #if WITH_TRACE_ANY_P 214 1.1 christos if (optarg != NULL) { 215 1.1 christos char *tmp; 216 1.1 christos tmp = (char *)malloc(strlen(optarg) + 1); 217 1.1 christos if (tmp == NULL) 218 1.1 christos { 219 1.1 christos sim_io_printf(sd,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg); 220 1.1 christos return SIM_RC_FAIL; 221 1.1 christos } 222 1.1 christos else { 223 1.1 christos strcpy(tmp,optarg); 224 1.1 christos tracefile = tmp; 225 1.1 christos sim_io_printf(sd,"Placing trace information into file \"%s\"\n",tracefile); 226 1.1 christos } 227 1.1 christos } 228 1.5 christos #endif /* WITH_TRACE_ANY_P */ 229 1.1 christos return SIM_RC_OK; 230 1.1 christos 231 1.1 christos case OPTION_FIRMWARE: 232 1.1 christos return sim_firmware_command (sd, arg); 233 1.1 christos 234 1.1 christos case OPTION_BOARD: 235 1.1 christos { 236 1.1 christos if (arg) 237 1.1 christos { 238 1.1 christos board = zalloc(strlen(arg) + 1); 239 1.1 christos strcpy(board, arg); 240 1.1 christos } 241 1.1 christos return SIM_RC_OK; 242 1.1 christos } 243 1.1 christos 244 1.1 christos case OPTION_INFO_MEMORY: 245 1.1 christos display_mem_info = 1; 246 1.1 christos break; 247 1.1 christos } 248 1.7 christos 249 1.1 christos return SIM_RC_OK; 250 1.1 christos } 251 1.1 christos 252 1.1 christos 253 1.1 christos static const OPTION mips_options[] = 254 1.1 christos { 255 1.1 christos { {"dinero-trace", optional_argument, NULL, OPTION_DINERO_TRACE}, 256 1.1 christos '\0', "on|off", "Enable dinero tracing", 257 1.1 christos mips_option_handler }, 258 1.1 christos { {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE}, 259 1.1 christos '\0', "FILE", "Write dinero trace to FILE", 260 1.1 christos mips_option_handler }, 261 1.1 christos { {"firmware", required_argument, NULL, OPTION_FIRMWARE}, 262 1.1 christos '\0', "[idt|pmon|lsipmon|none][@ADDRESS]", "Emulate ROM monitor", 263 1.1 christos mips_option_handler }, 264 1.1 christos { {"board", required_argument, NULL, OPTION_BOARD}, 265 1.1 christos '\0', "none" /* rely on compile-time string concatenation for other options */ 266 1.1 christos 267 1.1 christos #define BOARD_JMR3904 "jmr3904" 268 1.1 christos "|" BOARD_JMR3904 269 1.1 christos #define BOARD_JMR3904_PAL "jmr3904pal" 270 1.1 christos "|" BOARD_JMR3904_PAL 271 1.1 christos #define BOARD_JMR3904_DEBUG "jmr3904debug" 272 1.1 christos "|" BOARD_JMR3904_DEBUG 273 1.1 christos #define BOARD_BSP "bsp" 274 1.1 christos "|" BOARD_BSP 275 1.1 christos 276 1.1 christos , "Customize simulation for a particular board.", mips_option_handler }, 277 1.1 christos 278 1.1 christos /* These next two options have the same names as ones found in the 279 1.1 christos memory_options[] array in common/sim-memopt.c. This is because 280 1.1 christos the intention is to provide an alternative handler for those two 281 1.1 christos options. We need an alternative handler because the memory 282 1.1 christos regions are not set up until after the command line arguments 283 1.1 christos have been parsed, and so we cannot display the memory info whilst 284 1.1 christos processing the command line. There is a hack in sim_open to 285 1.1 christos remove these handlers when we want the real --memory-info option 286 1.1 christos to work. */ 287 1.1 christos { { "info-memory", no_argument, NULL, OPTION_INFO_MEMORY }, 288 1.1 christos '\0', NULL, "List configured memory regions", mips_option_handler }, 289 1.1 christos { { "memory-info", no_argument, NULL, OPTION_INFO_MEMORY }, 290 1.1 christos '\0', NULL, NULL, mips_option_handler }, 291 1.7 christos 292 1.1 christos { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } 293 1.1 christos }; 294 1.1 christos 295 1.1 christos 296 1.1 christos int interrupt_pending; 297 1.1 christos 298 1.1 christos void 299 1.1 christos interrupt_event (SIM_DESC sd, void *data) 300 1.1 christos { 301 1.1 christos sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */ 302 1.5 christos address_word cia = CPU_PC_GET (cpu); 303 1.1 christos if (SR & status_IE) 304 1.1 christos { 305 1.1 christos interrupt_pending = 0; 306 1.1 christos SignalExceptionInterrupt (1); /* interrupt "1" */ 307 1.1 christos } 308 1.1 christos else if (!interrupt_pending) 309 1.1 christos sim_events_schedule (sd, 1, interrupt_event, data); 310 1.1 christos } 311 1.1 christos 312 1.1 christos 313 1.1 christos /*---------------------------------------------------------------------------*/ 314 1.1 christos /*-- Device registration hook -----------------------------------------------*/ 315 1.1 christos /*---------------------------------------------------------------------------*/ 316 1.1 christos static void device_init(SIM_DESC sd) { 317 1.1 christos #ifdef DEVICE_INIT 318 1.1 christos extern void register_devices(SIM_DESC); 319 1.1 christos register_devices(sd); 320 1.1 christos #endif 321 1.1 christos } 322 1.1 christos 323 1.1 christos /*---------------------------------------------------------------------------*/ 324 1.1 christos /*-- GDB simulator interface ------------------------------------------------*/ 325 1.1 christos /*---------------------------------------------------------------------------*/ 326 1.1 christos 327 1.5 christos static sim_cia 328 1.5 christos mips_pc_get (sim_cpu *cpu) 329 1.5 christos { 330 1.5 christos return PC; 331 1.5 christos } 332 1.5 christos 333 1.5 christos static void 334 1.5 christos mips_pc_set (sim_cpu *cpu, sim_cia pc) 335 1.5 christos { 336 1.5 christos PC = pc; 337 1.5 christos } 338 1.5 christos 339 1.7 christos static int mips_reg_fetch (SIM_CPU *, int, void *, int); 340 1.7 christos static int mips_reg_store (SIM_CPU *, int, const void *, int); 341 1.6 christos 342 1.1 christos SIM_DESC 343 1.6 christos sim_open (SIM_OPEN_KIND kind, host_callback *cb, 344 1.6 christos struct bfd *abfd, char * const *argv) 345 1.1 christos { 346 1.5 christos int i; 347 1.7 christos SIM_DESC sd = sim_state_alloc_extra (kind, cb, 348 1.7 christos sizeof (struct mips_sim_state)); 349 1.5 christos sim_cpu *cpu; 350 1.1 christos 351 1.1 christos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 352 1.1 christos 353 1.5 christos /* The cpu data is kept in a separately allocated chunk of memory. */ 354 1.8 christos if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct mips_sim_cpu)) 355 1.8 christos != SIM_RC_OK) 356 1.5 christos return 0; 357 1.5 christos 358 1.5 christos cpu = STATE_CPU (sd, 0); /* FIXME */ 359 1.5 christos 360 1.1 christos /* FIXME: watchpoints code shouldn't need this */ 361 1.1 christos STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event; 362 1.1 christos 363 1.1 christos /* Initialize the mechanism for doing insn profiling. */ 364 1.1 christos CPU_INSN_NAME (cpu) = get_insn_name; 365 1.1 christos CPU_MAX_INSNS (cpu) = nr_itable_entries; 366 1.1 christos 367 1.1 christos STATE = 0; 368 1.7 christos 369 1.1 christos if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) 370 1.1 christos return 0; 371 1.1 christos sim_add_option_table (sd, NULL, mips_options); 372 1.1 christos 373 1.1 christos 374 1.6 christos /* The parser will print an error message for us, so we silently return. */ 375 1.1 christos if (sim_parse_args (sd, argv) != SIM_RC_OK) 376 1.1 christos { 377 1.1 christos /* Uninstall the modules to avoid memory leaks, 378 1.1 christos file descriptor leaks, etc. */ 379 1.1 christos sim_module_uninstall (sd); 380 1.1 christos return 0; 381 1.1 christos } 382 1.1 christos 383 1.1 christos /* handle board-specific memory maps */ 384 1.1 christos if (board == NULL) 385 1.1 christos { 386 1.1 christos /* Allocate core managed memory */ 387 1.1 christos sim_memopt *entry, *match = NULL; 388 1.1 christos address_word mem_size = 0; 389 1.1 christos int mapped = 0; 390 1.1 christos 391 1.1 christos /* For compatibility with the old code - under this (at level one) 392 1.1 christos are the kernel spaces K0 & K1. Both of these map to a single 393 1.1 christos smaller sub region */ 394 1.1 christos sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */ 395 1.1 christos 396 1.1 christos /* Look for largest memory region defined on command-line at 397 1.1 christos phys address 0. */ 398 1.1 christos for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next) 399 1.1 christos { 400 1.1 christos /* If we find an entry at address 0, then we will end up 401 1.1 christos allocating a new buffer in the "memory alias" command 402 1.1 christos below. The region at address 0 will be deleted. */ 403 1.1 christos if (entry->addr == 0 404 1.1 christos && (!match || entry->level < match->level)) 405 1.1 christos match = entry; 406 1.1 christos else if (entry->addr == K0BASE || entry->addr == K1BASE) 407 1.1 christos mapped = 1; 408 1.1 christos else 409 1.1 christos { 410 1.1 christos sim_memopt *alias; 411 1.1 christos for (alias = entry->alias; alias != NULL; alias = alias->next) 412 1.1 christos { 413 1.1 christos if (alias->addr == 0 414 1.1 christos && (!match || entry->level < match->level)) 415 1.1 christos match = entry; 416 1.1 christos else if (alias->addr == K0BASE || alias->addr == K1BASE) 417 1.1 christos mapped = 1; 418 1.1 christos } 419 1.1 christos } 420 1.1 christos } 421 1.1 christos 422 1.1 christos if (!mapped) 423 1.1 christos { 424 1.1 christos if (match) 425 1.1 christos { 426 1.1 christos /* Get existing memory region size. */ 427 1.1 christos mem_size = (match->modulo != 0 428 1.1 christos ? match->modulo : match->nr_bytes); 429 1.1 christos /* Delete old region. */ 430 1.7 christos sim_do_commandf (sd, "memory delete %d:0x%" PRIxTW "@%d", 431 1.1 christos match->space, match->addr, match->level); 432 1.7 christos } 433 1.1 christos else if (mem_size == 0) 434 1.1 christos mem_size = MEM_SIZE; 435 1.1 christos /* Limit to KSEG1 size (512MB) */ 436 1.1 christos if (mem_size > K1SIZE) 437 1.1 christos mem_size = K1SIZE; 438 1.1 christos /* memory alias K1BASE@1,K1SIZE%MEMSIZE,K0BASE */ 439 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x%%0x%lx,0x%0x", 440 1.1 christos K1BASE, K1SIZE, (long)mem_size, K0BASE); 441 1.7 christos if (WITH_TARGET_WORD_BITSIZE == 64) 442 1.7 christos sim_do_commandf (sd, "memory alias 0x%x,0x%" PRIxTW ",0x%" PRIxTA, 443 1.7 christos (K0BASE), mem_size, EXTENDED(K0BASE)); 444 1.1 christos } 445 1.1 christos 446 1.1 christos device_init(sd); 447 1.1 christos } 448 1.1 christos else if (board != NULL 449 1.1 christos && (strcmp(board, BOARD_BSP) == 0)) 450 1.1 christos { 451 1.1 christos STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT; 452 1.1 christos 453 1.1 christos /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */ 454 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x", 455 1.7 christos 0x9FC00000, 456 1.1 christos 4 * 1024 * 1024, /* 4 MB */ 457 1.1 christos 0xBFC00000); 458 1.1 christos 459 1.1 christos /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */ 460 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x", 461 1.7 christos 0x80000000, 462 1.1 christos 4 * 1024 * 1024, /* 4 MB */ 463 1.1 christos 0xA0000000); 464 1.1 christos 465 1.1 christos /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */ 466 1.1 christos for (i=0; i<8; i++) /* 32 MB total */ 467 1.1 christos { 468 1.1 christos unsigned size = 4 * 1024 * 1024; /* 4 MB */ 469 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x", 470 1.7 christos 0x88000000 + (i * size), 471 1.7 christos size, 472 1.1 christos 0xA8000000 + (i * size)); 473 1.1 christos } 474 1.1 christos } 475 1.1 christos #if (WITH_HW) 476 1.1 christos else if (board != NULL 477 1.1 christos && (strcmp(board, BOARD_JMR3904) == 0 || 478 1.1 christos strcmp(board, BOARD_JMR3904_PAL) == 0 || 479 1.1 christos strcmp(board, BOARD_JMR3904_DEBUG) == 0)) 480 1.1 christos { 481 1.1 christos /* match VIRTUAL memory layout of JMR-TX3904 board */ 482 1.1 christos 483 1.1 christos /* --- disable monitor unless forced on by user --- */ 484 1.1 christos 485 1.1 christos if (! firmware_option_p) 486 1.1 christos { 487 1.1 christos idt_monitor_base = 0; 488 1.1 christos pmon_monitor_base = 0; 489 1.1 christos lsipmon_monitor_base = 0; 490 1.1 christos } 491 1.1 christos 492 1.1 christos /* --- environment --- */ 493 1.1 christos 494 1.1 christos STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT; 495 1.1 christos 496 1.1 christos /* --- memory --- */ 497 1.1 christos 498 1.1 christos /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */ 499 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x", 500 1.7 christos 0x9FC00000, 501 1.1 christos 4 * 1024 * 1024, /* 4 MB */ 502 1.1 christos 0xBFC00000); 503 1.1 christos 504 1.1 christos /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */ 505 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x", 506 1.7 christos 0x80000000, 507 1.1 christos 4 * 1024 * 1024, /* 4 MB */ 508 1.1 christos 0xA0000000); 509 1.1 christos 510 1.1 christos /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */ 511 1.1 christos for (i=0; i<8; i++) /* 32 MB total */ 512 1.1 christos { 513 1.1 christos unsigned size = 4 * 1024 * 1024; /* 4 MB */ 514 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x,0x%0x", 515 1.7 christos 0x88000000 + (i * size), 516 1.7 christos size, 517 1.1 christos 0xA8000000 + (i * size)); 518 1.1 christos } 519 1.1 christos 520 1.1 christos /* Dummy memory regions for unsimulated devices - sorted by address */ 521 1.1 christos 522 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB1000000, 0x400); /* ISA I/O */ 523 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB2100000, 0x004); /* ISA ctl */ 524 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB2500000, 0x004); /* LED/switch */ 525 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB2700000, 0x004); /* RTC */ 526 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xB3C00000, 0x004); /* RTC */ 527 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xFFFF8000, 0x900); /* DRAMC */ 528 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xFFFF9000, 0x200); /* EBIF */ 529 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xFFFFE000, 0x01c); /* EBIF */ 530 1.7 christos sim_do_commandf (sd, "memory alias 0x%x@1,0x%x", 0xFFFFF500, 0x300); /* PIO */ 531 1.1 christos 532 1.1 christos 533 1.1 christos /* --- simulated devices --- */ 534 1.1 christos sim_hw_parse (sd, "/tx3904irc@0xffffc000/reg 0xffffc000 0x20"); 535 1.1 christos sim_hw_parse (sd, "/tx3904cpu"); 536 1.1 christos sim_hw_parse (sd, "/tx3904tmr@0xfffff000/reg 0xfffff000 0x100"); 537 1.1 christos sim_hw_parse (sd, "/tx3904tmr@0xfffff100/reg 0xfffff100 0x100"); 538 1.1 christos sim_hw_parse (sd, "/tx3904tmr@0xfffff200/reg 0xfffff200 0x100"); 539 1.1 christos sim_hw_parse (sd, "/tx3904sio@0xfffff300/reg 0xfffff300 0x100"); 540 1.1 christos { 541 1.1 christos /* FIXME: poking at dv-sockser internals, use tcp backend if 542 1.1 christos --sockser_addr option was given.*/ 543 1.7 christos #ifdef HAVE_DV_SOCKSER 544 1.1 christos extern char* sockser_addr; 545 1.7 christos #else 546 1.7 christos # define sockser_addr NULL 547 1.7 christos #endif 548 1.7 christos if (sockser_addr == NULL) 549 1.1 christos sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend stdio"); 550 1.1 christos else 551 1.1 christos sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend tcp"); 552 1.1 christos } 553 1.1 christos sim_hw_parse (sd, "/tx3904sio@0xfffff400/reg 0xfffff400 0x100"); 554 1.1 christos sim_hw_parse (sd, "/tx3904sio@0xfffff400/backend stdio"); 555 1.1 christos 556 1.1 christos /* -- device connections --- */ 557 1.1 christos sim_hw_parse (sd, "/tx3904irc > ip level /tx3904cpu"); 558 1.1 christos sim_hw_parse (sd, "/tx3904tmr@0xfffff000 > int tmr0 /tx3904irc"); 559 1.1 christos sim_hw_parse (sd, "/tx3904tmr@0xfffff100 > int tmr1 /tx3904irc"); 560 1.1 christos sim_hw_parse (sd, "/tx3904tmr@0xfffff200 > int tmr2 /tx3904irc"); 561 1.1 christos sim_hw_parse (sd, "/tx3904sio@0xfffff300 > int sio0 /tx3904irc"); 562 1.1 christos sim_hw_parse (sd, "/tx3904sio@0xfffff400 > int sio1 /tx3904irc"); 563 1.1 christos 564 1.1 christos /* add PAL timer & I/O module */ 565 1.7 christos if (!strcmp(board, BOARD_JMR3904_PAL)) 566 1.1 christos { 567 1.1 christos /* the device */ 568 1.1 christos sim_hw_parse (sd, "/pal@0xffff0000"); 569 1.1 christos sim_hw_parse (sd, "/pal@0xffff0000/reg 0xffff0000 64"); 570 1.1 christos 571 1.1 christos /* wire up interrupt ports to irc */ 572 1.1 christos sim_hw_parse (sd, "/pal@0x31000000 > countdown tmr0 /tx3904irc"); 573 1.1 christos sim_hw_parse (sd, "/pal@0x31000000 > timer tmr1 /tx3904irc"); 574 1.1 christos sim_hw_parse (sd, "/pal@0x31000000 > int int0 /tx3904irc"); 575 1.1 christos } 576 1.1 christos 577 1.7 christos if (!strcmp(board, BOARD_JMR3904_DEBUG)) 578 1.1 christos { 579 1.1 christos /* -- DEBUG: glue interrupt generators --- */ 580 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000/reg 0xffff0000 0x50"); 581 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int0 int0 /tx3904irc"); 582 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int1 int1 /tx3904irc"); 583 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int2 int2 /tx3904irc"); 584 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int3 int3 /tx3904irc"); 585 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int4 int4 /tx3904irc"); 586 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int5 int5 /tx3904irc"); 587 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int6 int6 /tx3904irc"); 588 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int7 int7 /tx3904irc"); 589 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int8 dmac0 /tx3904irc"); 590 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int9 dmac1 /tx3904irc"); 591 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int10 dmac2 /tx3904irc"); 592 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int11 dmac3 /tx3904irc"); 593 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int12 sio0 /tx3904irc"); 594 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int13 sio1 /tx3904irc"); 595 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int14 tmr0 /tx3904irc"); 596 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int15 tmr1 /tx3904irc"); 597 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int16 tmr2 /tx3904irc"); 598 1.1 christos sim_hw_parse (sd, "/glue@0xffff0000 > int17 nmi /tx3904cpu"); 599 1.1 christos } 600 1.1 christos 601 1.1 christos device_init(sd); 602 1.1 christos } 603 1.1 christos #endif 604 1.1 christos 605 1.1 christos if (display_mem_info) 606 1.1 christos { 607 1.1 christos struct option_list * ol; 608 1.1 christos struct option_list * prev; 609 1.1 christos 610 1.1 christos /* This is a hack. We want to execute the real --memory-info command 611 1.1 christos line switch which is handled in common/sim-memopts.c, not the 612 1.1 christos override we have defined in this file. So we remove the 613 1.1 christos mips_options array from the state options list. This is safe 614 1.1 christos because we have now processed all of the command line. */ 615 1.1 christos for (ol = STATE_OPTIONS (sd), prev = NULL; 616 1.1 christos ol != NULL; 617 1.1 christos prev = ol, ol = ol->next) 618 1.1 christos if (ol->options == mips_options) 619 1.1 christos break; 620 1.1 christos 621 1.1 christos SIM_ASSERT (ol != NULL); 622 1.1 christos 623 1.1 christos if (prev == NULL) 624 1.1 christos STATE_OPTIONS (sd) = ol->next; 625 1.1 christos else 626 1.1 christos prev->next = ol->next; 627 1.1 christos 628 1.1 christos sim_do_commandf (sd, "memory-info"); 629 1.1 christos } 630 1.1 christos 631 1.1 christos /* check for/establish the a reference program image */ 632 1.7 christos if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK) 633 1.1 christos { 634 1.1 christos sim_module_uninstall (sd); 635 1.1 christos return 0; 636 1.1 christos } 637 1.1 christos 638 1.1 christos /* Configure/verify the target byte order and other runtime 639 1.1 christos configuration options */ 640 1.1 christos if (sim_config (sd) != SIM_RC_OK) 641 1.1 christos { 642 1.1 christos sim_module_uninstall (sd); 643 1.1 christos return 0; 644 1.1 christos } 645 1.1 christos 646 1.1 christos if (sim_post_argv_init (sd) != SIM_RC_OK) 647 1.1 christos { 648 1.1 christos /* Uninstall the modules to avoid memory leaks, 649 1.1 christos file descriptor leaks, etc. */ 650 1.1 christos sim_module_uninstall (sd); 651 1.1 christos return 0; 652 1.1 christos } 653 1.1 christos 654 1.1 christos /* verify assumptions the simulator made about the host type system. 655 1.1 christos This macro does not return if there is a problem */ 656 1.1 christos SIM_ASSERT (sizeof(int) == (4 * sizeof(char))); 657 1.1 christos SIM_ASSERT (sizeof(word64) == (8 * sizeof(char))); 658 1.1 christos 659 1.1 christos /* This is NASTY, in that we are assuming the size of specific 660 1.1 christos registers: */ 661 1.1 christos { 662 1.1 christos int rn; 663 1.1 christos for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) 664 1.1 christos { 665 1.8 christos struct mips_sim_cpu *mips_cpu = MIPS_SIM_CPU (cpu); 666 1.8 christos 667 1.1 christos if (rn < 32) 668 1.8 christos mips_cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE; 669 1.1 christos else if ((rn >= FGR_BASE) && (rn < (FGR_BASE + NR_FGR))) 670 1.8 christos mips_cpu->register_widths[rn] = WITH_TARGET_FLOATING_POINT_BITSIZE; 671 1.1 christos else if ((rn >= 33) && (rn <= 37)) 672 1.8 christos mips_cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE; 673 1.1 christos else if ((rn == SRIDX) 674 1.1 christos || (rn == FCR0IDX) 675 1.1 christos || (rn == FCR31IDX) 676 1.1 christos || ((rn >= 72) && (rn <= 89))) 677 1.8 christos mips_cpu->register_widths[rn] = 32; 678 1.1 christos else 679 1.8 christos mips_cpu->register_widths[rn] = 0; 680 1.1 christos } 681 1.1 christos 682 1.1 christos 683 1.1 christos } 684 1.1 christos 685 1.1 christos if (STATE & simTRACE) 686 1.1 christos open_trace(sd); 687 1.1 christos 688 1.1 christos /* 689 1.7 christos sim_io_eprintf (sd, "idt@%x pmon@%x lsipmon@%x\n", 690 1.1 christos idt_monitor_base, 691 1.7 christos pmon_monitor_base, 692 1.1 christos lsipmon_monitor_base); 693 1.1 christos */ 694 1.1 christos 695 1.1 christos /* Write the monitor trap address handlers into the monitor (eeprom) 696 1.1 christos address space. This can only be done once the target endianness 697 1.1 christos has been determined. */ 698 1.1 christos if (idt_monitor_base != 0) 699 1.1 christos { 700 1.1 christos unsigned loop; 701 1.7 christos address_word idt_monitor_size = 1 << 11; 702 1.1 christos 703 1.1 christos /* the default monitor region */ 704 1.7 christos if (WITH_TARGET_WORD_BITSIZE == 64) 705 1.8 christos sim_do_commandf (sd, "memory alias %#" PRIxTA ",%#" PRIxTA ",%#" PRIxTA, 706 1.7 christos idt_monitor_base, idt_monitor_size, 707 1.7 christos EXTENDED (idt_monitor_base)); 708 1.7 christos else 709 1.8 christos sim_do_commandf (sd, "memory region %#" PRIxTA ",%#" PRIxTA, 710 1.7 christos idt_monitor_base, idt_monitor_size); 711 1.1 christos 712 1.1 christos /* Entry into the IDT monitor is via fixed address vectors, and 713 1.1 christos not using machine instructions. To avoid clashing with use of 714 1.1 christos the MIPS TRAP system, we place our own (simulator specific) 715 1.1 christos "undefined" instructions into the relevant vector slots. */ 716 1.1 christos for (loop = 0; (loop < idt_monitor_size); loop += 4) 717 1.1 christos { 718 1.1 christos address_word vaddr = (idt_monitor_base + loop); 719 1.7 christos uint32_t insn = (RSVD_INSTRUCTION | 720 1.1 christos (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) 721 1.1 christos << RSVD_INSTRUCTION_ARG_SHIFT)); 722 1.1 christos H2T (insn); 723 1.7 christos sim_write (sd, vaddr, &insn, sizeof (insn)); 724 1.1 christos } 725 1.1 christos } 726 1.1 christos 727 1.1 christos if ((pmon_monitor_base != 0) || (lsipmon_monitor_base != 0)) 728 1.1 christos { 729 1.1 christos /* The PMON monitor uses the same address space, but rather than 730 1.1 christos branching into it the address of a routine is loaded. We can 731 1.1 christos cheat for the moment, and direct the PMON routine to IDT style 732 1.1 christos instructions within the monitor space. This relies on the IDT 733 1.1 christos monitor not using the locations from 0xBFC00500 onwards as its 734 1.1 christos entry points.*/ 735 1.1 christos unsigned loop; 736 1.1 christos for (loop = 0; (loop < 24); loop++) 737 1.1 christos { 738 1.7 christos uint32_t value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */ 739 1.1 christos switch (loop) 740 1.1 christos { 741 1.1 christos case 0: /* read */ 742 1.1 christos value = 7; 743 1.1 christos break; 744 1.1 christos case 1: /* write */ 745 1.1 christos value = 8; 746 1.1 christos break; 747 1.1 christos case 2: /* open */ 748 1.1 christos value = 6; 749 1.1 christos break; 750 1.1 christos case 3: /* close */ 751 1.1 christos value = 10; 752 1.1 christos break; 753 1.1 christos case 5: /* printf */ 754 1.1 christos value = ((0x500 - 16) / 8); /* not an IDT reason code */ 755 1.1 christos break; 756 1.1 christos case 8: /* cliexit */ 757 1.1 christos value = 17; 758 1.1 christos break; 759 1.1 christos case 11: /* flush_cache */ 760 1.1 christos value = 28; 761 1.1 christos break; 762 1.1 christos } 763 1.1 christos 764 1.1 christos SIM_ASSERT (idt_monitor_base != 0); 765 1.1 christos value = ((unsigned int) idt_monitor_base + (value * 8)); 766 1.1 christos H2T (value); 767 1.1 christos 768 1.1 christos if (pmon_monitor_base != 0) 769 1.1 christos { 770 1.1 christos address_word vaddr = (pmon_monitor_base + (loop * 4)); 771 1.7 christos sim_write (sd, vaddr, &value, sizeof (value)); 772 1.1 christos } 773 1.1 christos 774 1.1 christos if (lsipmon_monitor_base != 0) 775 1.1 christos { 776 1.1 christos address_word vaddr = (lsipmon_monitor_base + (loop * 4)); 777 1.7 christos sim_write (sd, vaddr, &value, sizeof (value)); 778 1.1 christos } 779 1.1 christos } 780 1.1 christos 781 1.1 christos /* Write an abort sequence into the TRAP (common) exception vector 782 1.1 christos addresses. This is to catch code executing a TRAP (et.al.) 783 1.1 christos instruction without installing a trap handler. */ 784 1.7 christos if ((idt_monitor_base != 0) || 785 1.7 christos (pmon_monitor_base != 0) || 786 1.1 christos (lsipmon_monitor_base != 0)) 787 1.1 christos { 788 1.7 christos uint32_t halt[2] = { 0x2404002f /* addiu r4, r0, 47 */, 789 1.1 christos HALT_INSTRUCTION /* BREAK */ }; 790 1.1 christos H2T (halt[0]); 791 1.1 christos H2T (halt[1]); 792 1.7 christos sim_write (sd, 0x80000000, halt, sizeof (halt)); 793 1.7 christos sim_write (sd, 0x80000180, halt, sizeof (halt)); 794 1.7 christos sim_write (sd, 0x80000200, halt, sizeof (halt)); 795 1.1 christos /* XXX: Write here unconditionally? */ 796 1.7 christos sim_write (sd, 0xBFC00200, halt, sizeof (halt)); 797 1.7 christos sim_write (sd, 0xBFC00380, halt, sizeof (halt)); 798 1.7 christos sim_write (sd, 0xBFC00400, halt, sizeof (halt)); 799 1.1 christos } 800 1.1 christos } 801 1.1 christos 802 1.5 christos /* CPU specific initialization. */ 803 1.5 christos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 804 1.5 christos { 805 1.8 christos cpu = STATE_CPU (sd, i); 806 1.1 christos 807 1.6 christos CPU_REG_FETCH (cpu) = mips_reg_fetch; 808 1.6 christos CPU_REG_STORE (cpu) = mips_reg_store; 809 1.5 christos CPU_PC_FETCH (cpu) = mips_pc_get; 810 1.5 christos CPU_PC_STORE (cpu) = mips_pc_set; 811 1.5 christos } 812 1.1 christos 813 1.1 christos return sd; 814 1.1 christos } 815 1.1 christos 816 1.5 christos #if WITH_TRACE_ANY_P 817 1.1 christos static void 818 1.5 christos open_trace (SIM_DESC sd) 819 1.1 christos { 820 1.1 christos tracefh = fopen(tracefile,"wb+"); 821 1.1 christos if (tracefh == NULL) 822 1.1 christos { 823 1.1 christos sim_io_eprintf(sd,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile); 824 1.1 christos tracefh = stderr; 825 1.1 christos } 826 1.1 christos } 827 1.5 christos #endif 828 1.1 christos 829 1.1 christos /* Return name of an insn, used by insn profiling. */ 830 1.1 christos static const char * 831 1.1 christos get_insn_name (sim_cpu *cpu, int i) 832 1.1 christos { 833 1.1 christos return itable[i].name; 834 1.1 christos } 835 1.1 christos 836 1.1 christos void 837 1.6 christos mips_sim_close (SIM_DESC sd, int quitting) 838 1.1 christos { 839 1.5 christos #if WITH_TRACE_ANY_P 840 1.1 christos if (tracefh != NULL && tracefh != stderr) 841 1.1 christos fclose(tracefh); 842 1.1 christos tracefh = NULL; 843 1.5 christos #endif 844 1.1 christos } 845 1.1 christos 846 1.6 christos static int 847 1.7 christos mips_reg_store (SIM_CPU *cpu, int rn, const void *memory, int length) 848 1.1 christos { 849 1.1 christos /* NOTE: gdb (the client) stores registers in target byte order 850 1.1 christos while the simulator uses host byte order */ 851 1.1 christos 852 1.1 christos /* Unfortunately this suffers from the same problem as the register 853 1.1 christos numbering one. We need to know what the width of each logical 854 1.1 christos register number is for the architecture being simulated. */ 855 1.1 christos 856 1.8 christos struct mips_sim_cpu *mips_cpu = MIPS_SIM_CPU (cpu); 857 1.8 christos 858 1.8 christos if (mips_cpu->register_widths[rn] == 0) 859 1.1 christos { 860 1.6 christos sim_io_eprintf (CPU_STATE (cpu), "Invalid register width for %d (register store ignored)\n", rn); 861 1.1 christos return 0; 862 1.1 christos } 863 1.1 christos 864 1.1 christos if (rn >= FGR_BASE && rn < FGR_BASE + NR_FGR) 865 1.1 christos { 866 1.8 christos mips_cpu->fpr_state[rn - FGR_BASE] = fmt_uninterpreted; 867 1.8 christos if (mips_cpu->register_widths[rn] == 32) 868 1.1 christos { 869 1.1 christos if (length == 8) 870 1.1 christos { 871 1.8 christos mips_cpu->fgr[rn - FGR_BASE] = 872 1.7 christos (uint32_t) T2H_8 (*(uint64_t*)memory); 873 1.1 christos return 8; 874 1.1 christos } 875 1.1 christos else 876 1.1 christos { 877 1.8 christos mips_cpu->fgr[rn - FGR_BASE] = T2H_4 (*(uint32_t*)memory); 878 1.1 christos return 4; 879 1.1 christos } 880 1.1 christos } 881 1.1 christos else 882 1.1 christos { 883 1.1 christos if (length == 8) 884 1.1 christos { 885 1.8 christos mips_cpu->fgr[rn - FGR_BASE] = T2H_8 (*(uint64_t*)memory); 886 1.1 christos return 8; 887 1.1 christos } 888 1.1 christos else 889 1.1 christos { 890 1.8 christos mips_cpu->fgr[rn - FGR_BASE] = T2H_4 (*(uint32_t*)memory); 891 1.1 christos return 4; 892 1.1 christos } 893 1.1 christos } 894 1.1 christos } 895 1.1 christos 896 1.8 christos if (mips_cpu->register_widths[rn] == 32) 897 1.1 christos { 898 1.1 christos if (length == 8) 899 1.1 christos { 900 1.8 christos mips_cpu->registers[rn] = 901 1.7 christos (uint32_t) T2H_8 (*(uint64_t*)memory); 902 1.1 christos return 8; 903 1.1 christos } 904 1.1 christos else 905 1.1 christos { 906 1.8 christos mips_cpu->registers[rn] = T2H_4 (*(uint32_t*)memory); 907 1.1 christos return 4; 908 1.1 christos } 909 1.1 christos } 910 1.1 christos else 911 1.1 christos { 912 1.1 christos if (length == 8) 913 1.1 christos { 914 1.8 christos mips_cpu->registers[rn] = T2H_8 (*(uint64_t*)memory); 915 1.1 christos return 8; 916 1.1 christos } 917 1.1 christos else 918 1.1 christos { 919 1.8 christos mips_cpu->registers[rn] = (int32_t) T2H_4(*(uint32_t*)memory); 920 1.1 christos return 4; 921 1.1 christos } 922 1.1 christos } 923 1.1 christos 924 1.1 christos return 0; 925 1.1 christos } 926 1.1 christos 927 1.6 christos static int 928 1.7 christos mips_reg_fetch (SIM_CPU *cpu, int rn, void *memory, int length) 929 1.1 christos { 930 1.1 christos /* NOTE: gdb (the client) stores registers in target byte order 931 1.1 christos while the simulator uses host byte order */ 932 1.1 christos 933 1.8 christos struct mips_sim_cpu *mips_cpu = MIPS_SIM_CPU (cpu); 934 1.8 christos 935 1.8 christos if (mips_cpu->register_widths[rn] == 0) 936 1.1 christos { 937 1.6 christos sim_io_eprintf (CPU_STATE (cpu), "Invalid register width for %d (register fetch ignored)\n", rn); 938 1.1 christos return 0; 939 1.1 christos } 940 1.1 christos 941 1.1 christos /* Any floating point register */ 942 1.1 christos if (rn >= FGR_BASE && rn < FGR_BASE + NR_FGR) 943 1.1 christos { 944 1.8 christos if (mips_cpu->register_widths[rn] == 32) 945 1.1 christos { 946 1.1 christos if (length == 8) 947 1.1 christos { 948 1.7 christos *(uint64_t*)memory = 949 1.8 christos H2T_8 ((uint32_t) (mips_cpu->fgr[rn - FGR_BASE])); 950 1.1 christos return 8; 951 1.1 christos } 952 1.1 christos else 953 1.1 christos { 954 1.8 christos *(uint32_t*)memory = H2T_4 (mips_cpu->fgr[rn - FGR_BASE]); 955 1.1 christos return 4; 956 1.1 christos } 957 1.1 christos } 958 1.1 christos else 959 1.1 christos { 960 1.1 christos if (length == 8) 961 1.1 christos { 962 1.8 christos *(uint64_t*)memory = H2T_8 (mips_cpu->fgr[rn - FGR_BASE]); 963 1.1 christos return 8; 964 1.1 christos } 965 1.1 christos else 966 1.1 christos { 967 1.8 christos *(uint32_t*)memory = H2T_4 ((uint32_t)(mips_cpu->fgr[rn - FGR_BASE])); 968 1.1 christos return 4; 969 1.1 christos } 970 1.1 christos } 971 1.1 christos } 972 1.1 christos 973 1.8 christos if (mips_cpu->register_widths[rn] == 32) 974 1.1 christos { 975 1.1 christos if (length == 8) 976 1.1 christos { 977 1.7 christos *(uint64_t*)memory = 978 1.8 christos H2T_8 ((uint32_t) (mips_cpu->registers[rn])); 979 1.1 christos return 8; 980 1.1 christos } 981 1.1 christos else 982 1.1 christos { 983 1.8 christos *(uint32_t*)memory = H2T_4 ((uint32_t)(mips_cpu->registers[rn])); 984 1.1 christos return 4; 985 1.1 christos } 986 1.1 christos } 987 1.1 christos else 988 1.1 christos { 989 1.1 christos if (length == 8) 990 1.1 christos { 991 1.7 christos *(uint64_t*)memory = 992 1.8 christos H2T_8 ((uint64_t) (mips_cpu->registers[rn])); 993 1.1 christos return 8; 994 1.1 christos } 995 1.1 christos else 996 1.1 christos { 997 1.8 christos *(uint32_t*)memory = H2T_4 ((uint32_t)(mips_cpu->registers[rn])); 998 1.1 christos return 4; 999 1.1 christos } 1000 1.1 christos } 1001 1.1 christos 1002 1.1 christos return 0; 1003 1.1 christos } 1004 1.1 christos 1005 1.1 christos SIM_RC 1006 1.6 christos sim_create_inferior (SIM_DESC sd, struct bfd *abfd, 1007 1.6 christos char * const *argv, char * const *env) 1008 1.1 christos { 1009 1.1 christos 1010 1.1 christos #ifdef DEBUG 1011 1.1 christos #if 0 /* FIXME: doesn't compile */ 1012 1.1 christos printf("DBG: sim_create_inferior entered: start_address = 0x%s\n", 1013 1.1 christos pr_addr(PC)); 1014 1.1 christos #endif 1015 1.1 christos #endif /* DEBUG */ 1016 1.1 christos 1017 1.1 christos ColdReset(sd); 1018 1.1 christos 1019 1.1 christos if (abfd != NULL) 1020 1.1 christos { 1021 1.1 christos /* override PC value set by ColdReset () */ 1022 1.1 christos int cpu_nr; 1023 1.1 christos for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++) 1024 1.1 christos { 1025 1.1 christos sim_cpu *cpu = STATE_CPU (sd, cpu_nr); 1026 1.6 christos sim_cia pc = bfd_get_start_address (abfd); 1027 1.6 christos 1028 1.7 christos /* The 64-bit BFD sign-extends MIPS addresses to model 1029 1.7 christos 32-bit compatibility segments with 64-bit addressing. 1030 1.7 christos These addresses work as is on 64-bit targets but 1031 1.7 christos can be truncated for 32-bit targets. */ 1032 1.7 christos if (WITH_TARGET_WORD_BITSIZE == 32) 1033 1.7 christos pc = (uint32_t) pc; 1034 1.6 christos 1035 1.6 christos CPU_PC_SET (cpu, pc); 1036 1.1 christos } 1037 1.1 christos } 1038 1.1 christos 1039 1.1 christos #if 0 /* def DEBUG */ 1040 1.1 christos if (argv || env) 1041 1.1 christos { 1042 1.1 christos /* We should really place the argv slot values into the argument 1043 1.1 christos registers, and onto the stack as required. However, this 1044 1.1 christos assumes that we have a stack defined, which is not 1045 1.1 christos necessarily true at the moment. */ 1046 1.1 christos char **cptr; 1047 1.1 christos sim_io_printf(sd,"sim_create_inferior() : passed arguments ignored\n"); 1048 1.1 christos for (cptr = argv; (cptr && *cptr); cptr++) 1049 1.1 christos printf("DBG: arg \"%s\"\n",*cptr); 1050 1.1 christos } 1051 1.1 christos #endif /* DEBUG */ 1052 1.1 christos 1053 1.1 christos return SIM_RC_OK; 1054 1.1 christos } 1055 1.1 christos 1056 1.1 christos /*---------------------------------------------------------------------------*/ 1057 1.1 christos /*-- Private simulator support interface ------------------------------------*/ 1058 1.1 christos /*---------------------------------------------------------------------------*/ 1059 1.1 christos 1060 1.1 christos /* Read a null terminated string from memory, return in a buffer */ 1061 1.1 christos static char * 1062 1.1 christos fetch_str (SIM_DESC sd, 1063 1.1 christos address_word addr) 1064 1.1 christos { 1065 1.1 christos char *buf; 1066 1.1 christos int nr = 0; 1067 1.5 christos unsigned char null; 1068 1.1 christos while (sim_read (sd, addr + nr, &null, 1) == 1 && null != 0) 1069 1.1 christos nr++; 1070 1.1 christos buf = NZALLOC (char, nr + 1); 1071 1.7 christos sim_read (sd, addr, buf, nr); 1072 1.1 christos return buf; 1073 1.1 christos } 1074 1.1 christos 1075 1.1 christos 1076 1.1 christos /* Implements the "sim firmware" command: 1077 1.1 christos sim firmware NAME[@ADDRESS] --- emulate ROM monitor named NAME. 1078 1.1 christos NAME can be idt, pmon, or lsipmon. If omitted, ADDRESS 1079 1.1 christos defaults to the normal address for that monitor. 1080 1.1 christos sim firmware none --- don't emulate any ROM monitor. Useful 1081 1.1 christos if you need a clean address space. */ 1082 1.1 christos static SIM_RC 1083 1.1 christos sim_firmware_command (SIM_DESC sd, char *arg) 1084 1.1 christos { 1085 1.1 christos int address_present = 0; 1086 1.8 christos address_word address; 1087 1.1 christos 1088 1.1 christos /* Signal occurrence of this option. */ 1089 1.1 christos firmware_option_p = 1; 1090 1.1 christos 1091 1.1 christos /* Parse out the address, if present. */ 1092 1.1 christos { 1093 1.1 christos char *p = strchr (arg, '@'); 1094 1.1 christos if (p) 1095 1.1 christos { 1096 1.1 christos char *q; 1097 1.1 christos address_present = 1; 1098 1.1 christos p ++; /* skip over @ */ 1099 1.1 christos 1100 1.1 christos address = strtoul (p, &q, 0); 1101 1.7 christos if (*q != '\0') 1102 1.1 christos { 1103 1.1 christos sim_io_printf (sd, "Invalid address given to the" 1104 1.1 christos "`sim firmware NAME@ADDRESS' command: %s\n", 1105 1.1 christos p); 1106 1.1 christos return SIM_RC_FAIL; 1107 1.1 christos } 1108 1.1 christos } 1109 1.1 christos else 1110 1.1 christos { 1111 1.1 christos address_present = 0; 1112 1.1 christos address = -1; /* Dummy value. */ 1113 1.1 christos } 1114 1.1 christos } 1115 1.1 christos 1116 1.1 christos if (! strncmp (arg, "idt", 3)) 1117 1.1 christos { 1118 1.1 christos idt_monitor_base = address_present ? address : 0xBFC00000; 1119 1.1 christos pmon_monitor_base = 0; 1120 1.1 christos lsipmon_monitor_base = 0; 1121 1.1 christos } 1122 1.1 christos else if (! strncmp (arg, "pmon", 4)) 1123 1.1 christos { 1124 1.1 christos /* pmon uses indirect calls. Hook into implied idt. */ 1125 1.1 christos pmon_monitor_base = address_present ? address : 0xBFC00500; 1126 1.1 christos idt_monitor_base = pmon_monitor_base - 0x500; 1127 1.1 christos lsipmon_monitor_base = 0; 1128 1.1 christos } 1129 1.1 christos else if (! strncmp (arg, "lsipmon", 7)) 1130 1.1 christos { 1131 1.1 christos /* lsipmon uses indirect calls. Hook into implied idt. */ 1132 1.1 christos pmon_monitor_base = 0; 1133 1.1 christos lsipmon_monitor_base = address_present ? address : 0xBFC00200; 1134 1.1 christos idt_monitor_base = lsipmon_monitor_base - 0x200; 1135 1.1 christos } 1136 1.1 christos else if (! strncmp (arg, "none", 4)) 1137 1.1 christos { 1138 1.1 christos if (address_present) 1139 1.1 christos { 1140 1.1 christos sim_io_printf (sd, 1141 1.1 christos "The `sim firmware none' command does " 1142 1.1 christos "not take an `ADDRESS' argument.\n"); 1143 1.1 christos return SIM_RC_FAIL; 1144 1.1 christos } 1145 1.1 christos idt_monitor_base = 0; 1146 1.1 christos pmon_monitor_base = 0; 1147 1.1 christos lsipmon_monitor_base = 0; 1148 1.1 christos } 1149 1.1 christos else 1150 1.1 christos { 1151 1.1 christos sim_io_printf (sd, "\ 1152 1.1 christos Unrecognized name given to the `sim firmware NAME' command: %s\n\ 1153 1.1 christos Recognized firmware names are: `idt', `pmon', `lsipmon', and `none'.\n", 1154 1.1 christos arg); 1155 1.1 christos return SIM_RC_FAIL; 1156 1.1 christos } 1157 1.7 christos 1158 1.1 christos return SIM_RC_OK; 1159 1.1 christos } 1160 1.1 christos 1161 1.7 christos /* stat structures from MIPS32/64. */ 1162 1.7 christos static const char stat32_map[] = 1163 1.7 christos "st_dev,2:st_ino,2:st_mode,4:st_nlink,2:st_uid,2:st_gid,2" 1164 1.7 christos ":st_rdev,2:st_size,4:st_atime,4:st_spare1,4:st_mtime,4:st_spare2,4" 1165 1.7 christos ":st_ctime,4:st_spare3,4:st_blksize,4:st_blocks,4:st_spare4,8"; 1166 1.7 christos 1167 1.7 christos static const char stat64_map[] = 1168 1.7 christos "st_dev,2:st_ino,2:st_mode,4:st_nlink,2:st_uid,2:st_gid,2" 1169 1.7 christos ":st_rdev,2:st_size,8:st_atime,8:st_spare1,8:st_mtime,8:st_spare2,8" 1170 1.7 christos ":st_ctime,8:st_spare3,8:st_blksize,8:st_blocks,8:st_spare4,16"; 1171 1.7 christos 1172 1.7 christos /* Map for calls using the host struct stat. */ 1173 1.7 christos static const CB_TARGET_DEFS_MAP CB_stat_map[] = 1174 1.7 christos { 1175 1.7 christos { "stat", CB_SYS_stat, 15 }, 1176 1.7 christos { 0, -1, -1 } 1177 1.7 christos }; 1178 1.1 christos 1179 1.1 christos 1180 1.1 christos /* Simple monitor interface (currently setup for the IDT and PMON monitors) */ 1181 1.1 christos int 1182 1.1 christos sim_monitor (SIM_DESC sd, 1183 1.1 christos sim_cpu *cpu, 1184 1.1 christos address_word cia, 1185 1.1 christos unsigned int reason) 1186 1.1 christos { 1187 1.1 christos #ifdef DEBUG 1188 1.1 christos printf("DBG: sim_monitor: entered (reason = %d)\n",reason); 1189 1.1 christos #endif /* DEBUG */ 1190 1.1 christos 1191 1.1 christos /* The IDT monitor actually allows two instructions per vector 1192 1.1 christos slot. However, the simulator currently causes a trap on each 1193 1.1 christos individual instruction. We cheat, and lose the bottom bit. */ 1194 1.1 christos reason >>= 1; 1195 1.1 christos 1196 1.1 christos /* The following callback functions are available, however the 1197 1.1 christos monitor we are simulating does not make use of them: get_errno, 1198 1.7 christos isatty, rename, system and time. */ 1199 1.1 christos switch (reason) 1200 1.1 christos { 1201 1.1 christos 1202 1.1 christos case 6: /* int open(char *path,int flags) */ 1203 1.1 christos { 1204 1.1 christos char *path = fetch_str (sd, A0); 1205 1.1 christos V0 = sim_io_open (sd, path, (int)A1); 1206 1.1 christos free (path); 1207 1.1 christos break; 1208 1.1 christos } 1209 1.1 christos 1210 1.1 christos case 7: /* int read(int file,char *ptr,int len) */ 1211 1.1 christos { 1212 1.1 christos int fd = A0; 1213 1.1 christos int nr = A2; 1214 1.1 christos char *buf = zalloc (nr); 1215 1.1 christos V0 = sim_io_read (sd, fd, buf, nr); 1216 1.7 christos sim_write (sd, A1, buf, nr); 1217 1.1 christos free (buf); 1218 1.1 christos } 1219 1.1 christos break; 1220 1.1 christos 1221 1.1 christos case 8: /* int write(int file,char *ptr,int len) */ 1222 1.1 christos { 1223 1.1 christos int fd = A0; 1224 1.1 christos int nr = A2; 1225 1.1 christos char *buf = zalloc (nr); 1226 1.7 christos sim_read (sd, A1, buf, nr); 1227 1.1 christos V0 = sim_io_write (sd, fd, buf, nr); 1228 1.1 christos if (fd == 1) 1229 1.1 christos sim_io_flush_stdout (sd); 1230 1.1 christos else if (fd == 2) 1231 1.1 christos sim_io_flush_stderr (sd); 1232 1.1 christos free (buf); 1233 1.1 christos break; 1234 1.1 christos } 1235 1.1 christos 1236 1.1 christos case 10: /* int close(int file) */ 1237 1.1 christos { 1238 1.1 christos V0 = sim_io_close (sd, (int)A0); 1239 1.1 christos break; 1240 1.1 christos } 1241 1.1 christos 1242 1.1 christos case 2: /* Densan monitor: char inbyte(int waitflag) */ 1243 1.1 christos { 1244 1.1 christos if (A0 == 0) /* waitflag == NOWAIT */ 1245 1.1 christos V0 = (unsigned_word)-1; 1246 1.1 christos } 1247 1.8 christos ATTRIBUTE_FALLTHROUGH; 1248 1.1 christos 1249 1.1 christos case 11: /* char inbyte(void) */ 1250 1.1 christos { 1251 1.1 christos char tmp; 1252 1.1 christos /* ensure that all output has gone... */ 1253 1.1 christos sim_io_flush_stdout (sd); 1254 1.1 christos if (sim_io_read_stdin (sd, &tmp, sizeof(char)) != sizeof(char)) 1255 1.1 christos { 1256 1.1 christos sim_io_error(sd,"Invalid return from character read"); 1257 1.1 christos V0 = (unsigned_word)-1; 1258 1.1 christos } 1259 1.1 christos else 1260 1.1 christos V0 = (unsigned_word)tmp; 1261 1.1 christos break; 1262 1.1 christos } 1263 1.1 christos 1264 1.1 christos case 3: /* Densan monitor: void co(char chr) */ 1265 1.1 christos case 12: /* void outbyte(char chr) : write a byte to "stdout" */ 1266 1.1 christos { 1267 1.1 christos char tmp = (char)(A0 & 0xFF); 1268 1.1 christos sim_io_write_stdout (sd, &tmp, sizeof(char)); 1269 1.1 christos break; 1270 1.1 christos } 1271 1.1 christos 1272 1.7 christos case 13: /* int unlink(const char *path) */ 1273 1.7 christos { 1274 1.7 christos char *path = fetch_str (sd, A0); 1275 1.7 christos V0 = sim_io_unlink (sd, path); 1276 1.7 christos free (path); 1277 1.7 christos break; 1278 1.7 christos } 1279 1.7 christos 1280 1.7 christos case 14: /* int lseek(int fd, int offset, int whence) */ 1281 1.7 christos { 1282 1.7 christos V0 = sim_io_lseek (sd, A0, A1, A2); 1283 1.7 christos break; 1284 1.7 christos } 1285 1.7 christos 1286 1.7 christos case 15: /* int stat(const char *path, struct stat *buf); */ 1287 1.7 christos { 1288 1.7 christos /* As long as the infrastructure doesn't cache anything 1289 1.7 christos related to the stat mapping, this trick gets us a dual 1290 1.7 christos "struct stat"-type mapping in the least error-prone way. */ 1291 1.7 christos host_callback *cb = STATE_CALLBACK (sd); 1292 1.7 christos const char *saved_map = cb->stat_map; 1293 1.7 christos CB_TARGET_DEFS_MAP *saved_syscall_map = cb->syscall_map; 1294 1.7 christos bfd *prog_bfd = STATE_PROG_BFD (sd); 1295 1.7 christos int is_elf32bit = (elf_elfheader(prog_bfd)->e_ident[EI_CLASS] == 1296 1.7 christos ELFCLASS32); 1297 1.7 christos static CB_SYSCALL s; 1298 1.7 christos CB_SYSCALL_INIT (&s); 1299 1.7 christos s.func = 15; 1300 1.7 christos /* Mask out the sign extension part for 64-bit targets because the 1301 1.7 christos MIPS simulator's memory model is still 32-bit. */ 1302 1.7 christos s.arg1 = A0 & 0xFFFFFFFF; 1303 1.7 christos s.arg2 = A1 & 0xFFFFFFFF; 1304 1.7 christos s.p1 = sd; 1305 1.7 christos s.p2 = cpu; 1306 1.7 christos s.read_mem = sim_syscall_read_mem; 1307 1.7 christos s.write_mem = sim_syscall_write_mem; 1308 1.7 christos 1309 1.7 christos cb->syscall_map = (CB_TARGET_DEFS_MAP *) CB_stat_map; 1310 1.7 christos cb->stat_map = is_elf32bit ? stat32_map : stat64_map; 1311 1.7 christos 1312 1.7 christos if (cb_syscall (cb, &s) != CB_RC_OK) 1313 1.7 christos sim_engine_halt (sd, cpu, NULL, mips_pc_get (cpu), 1314 1.7 christos sim_stopped, SIM_SIGILL); 1315 1.7 christos 1316 1.7 christos V0 = s.result; 1317 1.7 christos cb->stat_map = saved_map; 1318 1.7 christos cb->syscall_map = saved_syscall_map; 1319 1.7 christos break; 1320 1.7 christos } 1321 1.7 christos 1322 1.1 christos case 17: /* void _exit() */ 1323 1.1 christos { 1324 1.1 christos sim_io_eprintf (sd, "sim_monitor(17): _exit(int reason) to be coded\n"); 1325 1.1 christos sim_engine_halt (SD, CPU, NULL, NULL_CIA, sim_exited, 1326 1.1 christos (unsigned int)(A0 & 0xFFFFFFFF)); 1327 1.1 christos break; 1328 1.1 christos } 1329 1.1 christos 1330 1.1 christos case 28: /* PMON flush_cache */ 1331 1.1 christos break; 1332 1.1 christos 1333 1.1 christos case 55: /* void get_mem_info(unsigned int *ptr) */ 1334 1.1 christos /* in: A0 = pointer to three word memory location */ 1335 1.1 christos /* out: [A0 + 0] = size */ 1336 1.1 christos /* [A0 + 4] = instruction cache size */ 1337 1.1 christos /* [A0 + 8] = data cache size */ 1338 1.1 christos { 1339 1.1 christos unsigned_4 value; 1340 1.1 christos unsigned_4 zero = 0; 1341 1.1 christos address_word mem_size; 1342 1.1 christos sim_memopt *entry, *match = NULL; 1343 1.1 christos 1344 1.1 christos /* Search for memory region mapped to KSEG0 or KSEG1. */ 1345 1.7 christos for (entry = STATE_MEMOPT (sd); 1346 1.1 christos entry != NULL; 1347 1.1 christos entry = entry->next) 1348 1.1 christos { 1349 1.1 christos if ((entry->addr == K0BASE || entry->addr == K1BASE) 1350 1.1 christos && (!match || entry->level < match->level)) 1351 1.1 christos match = entry; 1352 1.1 christos else 1353 1.1 christos { 1354 1.1 christos sim_memopt *alias; 1355 1.7 christos for (alias = entry->alias; 1356 1.1 christos alias != NULL; 1357 1.1 christos alias = alias->next) 1358 1.1 christos if ((alias->addr == K0BASE || alias->addr == K1BASE) 1359 1.1 christos && (!match || entry->level < match->level)) 1360 1.1 christos match = entry; 1361 1.1 christos } 1362 1.1 christos } 1363 1.1 christos 1364 1.1 christos /* Get region size, limit to KSEG1 size (512MB). */ 1365 1.1 christos SIM_ASSERT (match != NULL); 1366 1.1 christos mem_size = (match->modulo != 0 1367 1.1 christos ? match->modulo : match->nr_bytes); 1368 1.1 christos if (mem_size > K1SIZE) 1369 1.1 christos mem_size = K1SIZE; 1370 1.1 christos 1371 1.1 christos value = mem_size; 1372 1.1 christos H2T (value); 1373 1.7 christos sim_write (sd, A0 + 0, &value, 4); 1374 1.7 christos sim_write (sd, A0 + 4, &zero, 4); 1375 1.7 christos sim_write (sd, A0 + 8, &zero, 4); 1376 1.1 christos /* sim_io_eprintf (sd, "sim: get_mem_info() deprecated\n"); */ 1377 1.1 christos break; 1378 1.1 christos } 1379 1.7 christos 1380 1.1 christos case 158: /* PMON printf */ 1381 1.1 christos /* in: A0 = pointer to format string */ 1382 1.1 christos /* A1 = optional argument 1 */ 1383 1.1 christos /* A2 = optional argument 2 */ 1384 1.1 christos /* A3 = optional argument 3 */ 1385 1.1 christos /* out: void */ 1386 1.1 christos /* The following is based on the PMON printf source */ 1387 1.1 christos { 1388 1.1 christos address_word s = A0; 1389 1.5 christos unsigned char c; 1390 1.7 christos address_word *ap = &A1; /* 1st argument */ 1391 1.1 christos /* This isn't the quickest way, since we call the host print 1392 1.1 christos routine for every character almost. But it does avoid 1393 1.1 christos having to allocate and manage a temporary string buffer. */ 1394 1.1 christos /* TODO: Include check that we only use three arguments (A1, 1395 1.1 christos A2 and A3) */ 1396 1.1 christos while (sim_read (sd, s++, &c, 1) && c != '\0') 1397 1.1 christos { 1398 1.1 christos if (c == '%') 1399 1.1 christos { 1400 1.1 christos char tmp[40]; 1401 1.8 christos /* The format logic isn't passed down. 1402 1.1 christos enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST; 1403 1.8 christos */ 1404 1.1 christos int width = 0, trunc = 0, haddot = 0, longlong = 0; 1405 1.1 christos while (sim_read (sd, s++, &c, 1) && c != '\0') 1406 1.1 christos { 1407 1.1 christos if (strchr ("dobxXulscefg%", c)) 1408 1.1 christos break; 1409 1.1 christos else if (c == '-') 1410 1.8 christos /* fmt = FMT_LJUST */; 1411 1.1 christos else if (c == '0') 1412 1.8 christos /* fmt = FMT_RJUST0 */; 1413 1.1 christos else if (c == '~') 1414 1.8 christos /* fmt = FMT_CENTER */; 1415 1.1 christos else if (c == '*') 1416 1.1 christos { 1417 1.1 christos if (haddot) 1418 1.1 christos trunc = (int)*ap++; 1419 1.1 christos else 1420 1.1 christos width = (int)*ap++; 1421 1.1 christos } 1422 1.1 christos else if (c >= '1' && c <= '9') 1423 1.1 christos { 1424 1.1 christos address_word t = s; 1425 1.1 christos unsigned int n; 1426 1.1 christos while (sim_read (sd, s++, &c, 1) == 1 && isdigit (c)) 1427 1.1 christos tmp[s - t] = c; 1428 1.1 christos tmp[s - t] = '\0'; 1429 1.1 christos n = (unsigned int)strtol(tmp,NULL,10); 1430 1.1 christos if (haddot) 1431 1.1 christos trunc = n; 1432 1.1 christos else 1433 1.1 christos width = n; 1434 1.1 christos s--; 1435 1.1 christos } 1436 1.1 christos else if (c == '.') 1437 1.1 christos haddot = 1; 1438 1.1 christos } 1439 1.1 christos switch (c) 1440 1.1 christos { 1441 1.1 christos case '%': 1442 1.1 christos sim_io_printf (sd, "%%"); 1443 1.1 christos break; 1444 1.1 christos case 's': 1445 1.1 christos if ((int)*ap != 0) 1446 1.1 christos { 1447 1.1 christos address_word p = *ap++; 1448 1.5 christos unsigned char ch; 1449 1.1 christos while (sim_read (sd, p++, &ch, 1) == 1 && ch != '\0') 1450 1.1 christos sim_io_printf(sd, "%c", ch); 1451 1.1 christos } 1452 1.1 christos else 1453 1.1 christos sim_io_printf(sd,"(null)"); 1454 1.1 christos break; 1455 1.1 christos case 'c': 1456 1.1 christos sim_io_printf (sd, "%c", (int)*ap++); 1457 1.1 christos break; 1458 1.1 christos default: 1459 1.1 christos if (c == 'l') 1460 1.1 christos { 1461 1.1 christos sim_read (sd, s++, &c, 1); 1462 1.1 christos if (c == 'l') 1463 1.1 christos { 1464 1.1 christos longlong = 1; 1465 1.1 christos sim_read (sd, s++, &c, 1); 1466 1.1 christos } 1467 1.1 christos } 1468 1.1 christos if (strchr ("dobxXu", c)) 1469 1.1 christos { 1470 1.1 christos word64 lv = (word64) *ap++; 1471 1.1 christos if (c == 'b') 1472 1.1 christos sim_io_printf(sd,"<binary not supported>"); 1473 1.1 christos else 1474 1.1 christos { 1475 1.7 christos #define P_(c, fmt64, fmt32) \ 1476 1.7 christos case c: \ 1477 1.7 christos if (longlong) \ 1478 1.7 christos sim_io_printf (sd, "%" fmt64, lv); \ 1479 1.7 christos else \ 1480 1.7 christos sim_io_printf (sd, "%" fmt32, (int)lv); \ 1481 1.7 christos break; 1482 1.7 christos #define P(c, fmtc) P_(c, PRI##fmtc##64, PRI##fmtc##32) 1483 1.7 christos switch (c) 1484 1.7 christos { 1485 1.7 christos P('d', d) 1486 1.7 christos P('o', o) 1487 1.7 christos P('x', x) 1488 1.7 christos P('X', X) 1489 1.7 christos P('u', u) 1490 1.7 christos } 1491 1.1 christos } 1492 1.7 christos #undef P 1493 1.7 christos #undef P_ 1494 1.1 christos } 1495 1.1 christos else if (strchr ("eEfgG", c)) 1496 1.1 christos { 1497 1.1 christos double dbl = *(double*)(ap++); 1498 1.7 christos 1499 1.7 christos #define P(c, fmtc) \ 1500 1.7 christos case c: \ 1501 1.7 christos sim_io_printf (sd, "%*.*" #fmtc, width, trunc, dbl); \ 1502 1.7 christos break; 1503 1.7 christos switch (c) 1504 1.7 christos { 1505 1.7 christos P('e', e) 1506 1.7 christos P('E', E) 1507 1.7 christos P('f', f) 1508 1.7 christos P('g', g) 1509 1.7 christos P('G', G) 1510 1.7 christos } 1511 1.7 christos #undef P 1512 1.1 christos trunc = 0; 1513 1.1 christos } 1514 1.1 christos } 1515 1.1 christos } 1516 1.1 christos else 1517 1.1 christos sim_io_printf(sd, "%c", c); 1518 1.1 christos } 1519 1.1 christos break; 1520 1.1 christos } 1521 1.1 christos 1522 1.1 christos default: 1523 1.1 christos /* Unknown reason. */ 1524 1.1 christos return 0; 1525 1.1 christos } 1526 1.1 christos return 1; 1527 1.1 christos } 1528 1.1 christos 1529 1.1 christos /* Store a word into memory. */ 1530 1.1 christos 1531 1.1 christos static void 1532 1.1 christos store_word (SIM_DESC sd, 1533 1.1 christos sim_cpu *cpu, 1534 1.1 christos address_word cia, 1535 1.1 christos uword64 vaddr, 1536 1.1 christos signed_word val) 1537 1.1 christos { 1538 1.6 christos address_word paddr = vaddr; 1539 1.1 christos 1540 1.1 christos if ((vaddr & 3) != 0) 1541 1.1 christos SignalExceptionAddressStore (); 1542 1.1 christos else 1543 1.1 christos { 1544 1.6 christos const uword64 mask = 7; 1545 1.6 christos uword64 memval; 1546 1.6 christos unsigned int byte; 1547 1.6 christos 1548 1.6 christos paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)); 1549 1.6 christos byte = (vaddr & mask) ^ (BigEndianCPU << 2); 1550 1.6 christos memval = ((uword64) val) << (8 * byte); 1551 1.6 christos StoreMemory (AccessLength_WORD, memval, 0, paddr, vaddr, 1552 1.6 christos isREAL); 1553 1.1 christos } 1554 1.1 christos } 1555 1.1 christos 1556 1.7 christos #define MIPSR6_P(abfd) \ 1557 1.8 christos ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6 \ 1558 1.8 christos || (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) 1559 1.7 christos 1560 1.1 christos /* Load a word from memory. */ 1561 1.1 christos 1562 1.1 christos static signed_word 1563 1.1 christos load_word (SIM_DESC sd, 1564 1.1 christos sim_cpu *cpu, 1565 1.1 christos address_word cia, 1566 1.1 christos uword64 vaddr) 1567 1.1 christos { 1568 1.7 christos if ((vaddr & 3) != 0 && !MIPSR6_P (STATE_PROG_BFD (sd))) 1569 1.1 christos { 1570 1.1 christos SIM_CORE_SIGNAL (SD, cpu, cia, read_map, AccessLength_WORD+1, vaddr, read_transfer, sim_core_unaligned_signal); 1571 1.1 christos } 1572 1.1 christos else 1573 1.1 christos { 1574 1.6 christos address_word paddr = vaddr; 1575 1.6 christos const uword64 mask = 0x7; 1576 1.6 christos const unsigned int reverse = ReverseEndian ? 1 : 0; 1577 1.6 christos const unsigned int bigend = BigEndianCPU ? 1 : 0; 1578 1.6 christos uword64 memval; 1579 1.6 christos unsigned int byte; 1580 1.6 christos 1581 1.6 christos paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2)); 1582 1.6 christos LoadMemory (&memval, NULL, AccessLength_WORD, paddr, vaddr, isDATA, 1583 1.6 christos isREAL); 1584 1.6 christos byte = (vaddr & mask) ^ (bigend << 2); 1585 1.6 christos return EXTEND32 (memval >> (8 * byte)); 1586 1.1 christos } 1587 1.1 christos 1588 1.1 christos return 0; 1589 1.1 christos } 1590 1.1 christos 1591 1.1 christos /* Simulate the mips16 entry and exit pseudo-instructions. These 1592 1.1 christos would normally be handled by the reserved instruction exception 1593 1.1 christos code, but for ease of simulation we just handle them directly. */ 1594 1.1 christos 1595 1.1 christos static void 1596 1.1 christos mips16_entry (SIM_DESC sd, 1597 1.1 christos sim_cpu *cpu, 1598 1.1 christos address_word cia, 1599 1.1 christos unsigned int insn) 1600 1.1 christos { 1601 1.1 christos int aregs, sregs, rreg; 1602 1.1 christos 1603 1.1 christos #ifdef DEBUG 1604 1.1 christos printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn); 1605 1.1 christos #endif /* DEBUG */ 1606 1.1 christos 1607 1.1 christos aregs = (insn & 0x700) >> 8; 1608 1.1 christos sregs = (insn & 0x0c0) >> 6; 1609 1.1 christos rreg = (insn & 0x020) >> 5; 1610 1.1 christos 1611 1.1 christos /* This should be checked by the caller. */ 1612 1.1 christos if (sregs == 3) 1613 1.1 christos abort (); 1614 1.1 christos 1615 1.1 christos if (aregs < 5) 1616 1.1 christos { 1617 1.1 christos int i; 1618 1.1 christos signed_word tsp; 1619 1.1 christos 1620 1.1 christos /* This is the entry pseudo-instruction. */ 1621 1.1 christos 1622 1.1 christos for (i = 0; i < aregs; i++) 1623 1.1 christos store_word (SD, CPU, cia, (uword64) (SP + 4 * i), GPR[i + 4]); 1624 1.1 christos 1625 1.1 christos tsp = SP; 1626 1.1 christos SP -= 32; 1627 1.1 christos 1628 1.1 christos if (rreg) 1629 1.1 christos { 1630 1.1 christos tsp -= 4; 1631 1.1 christos store_word (SD, CPU, cia, (uword64) tsp, RA); 1632 1.1 christos } 1633 1.1 christos 1634 1.1 christos for (i = 0; i < sregs; i++) 1635 1.1 christos { 1636 1.1 christos tsp -= 4; 1637 1.1 christos store_word (SD, CPU, cia, (uword64) tsp, GPR[16 + i]); 1638 1.1 christos } 1639 1.1 christos } 1640 1.1 christos else 1641 1.1 christos { 1642 1.1 christos int i; 1643 1.1 christos signed_word tsp; 1644 1.1 christos 1645 1.1 christos /* This is the exit pseudo-instruction. */ 1646 1.1 christos 1647 1.1 christos tsp = SP + 32; 1648 1.1 christos 1649 1.1 christos if (rreg) 1650 1.1 christos { 1651 1.1 christos tsp -= 4; 1652 1.1 christos RA = load_word (SD, CPU, cia, (uword64) tsp); 1653 1.1 christos } 1654 1.1 christos 1655 1.1 christos for (i = 0; i < sregs; i++) 1656 1.1 christos { 1657 1.1 christos tsp -= 4; 1658 1.1 christos GPR[i + 16] = load_word (SD, CPU, cia, (uword64) tsp); 1659 1.1 christos } 1660 1.1 christos 1661 1.1 christos SP += 32; 1662 1.1 christos 1663 1.1 christos if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) 1664 1.1 christos { 1665 1.1 christos if (aregs == 5) 1666 1.1 christos { 1667 1.1 christos FGR[0] = WORD64LO (GPR[4]); 1668 1.1 christos FPR_STATE[0] = fmt_uninterpreted; 1669 1.1 christos } 1670 1.1 christos else if (aregs == 6) 1671 1.1 christos { 1672 1.1 christos FGR[0] = WORD64LO (GPR[5]); 1673 1.1 christos FGR[1] = WORD64LO (GPR[4]); 1674 1.1 christos FPR_STATE[0] = fmt_uninterpreted; 1675 1.1 christos FPR_STATE[1] = fmt_uninterpreted; 1676 1.1 christos } 1677 1.7 christos } 1678 1.1 christos 1679 1.1 christos PC = RA; 1680 1.1 christos } 1681 1.7 christos 1682 1.1 christos } 1683 1.1 christos 1684 1.1 christos /*-- trace support ----------------------------------------------------------*/ 1685 1.1 christos 1686 1.5 christos /* The trace support is provided (if required) in the memory accessing 1687 1.1 christos routines. Since we are also providing the architecture specific 1688 1.1 christos features, the architecture simulation code can also deal with 1689 1.5 christos notifying the trace world of cache flushes, etc. Similarly we do 1690 1.1 christos not need to provide profiling support in the simulator engine, 1691 1.1 christos since we can sample in the instruction fetch control loop. By 1692 1.5 christos defining the trace manifest, we add tracing as a run-time 1693 1.1 christos option. */ 1694 1.1 christos 1695 1.5 christos #if WITH_TRACE_ANY_P 1696 1.1 christos /* Tracing by default produces "din" format (as required by 1697 1.1 christos dineroIII). Each line of such a trace file *MUST* have a din label 1698 1.1 christos and address field. The rest of the line is ignored, so comments can 1699 1.1 christos be included if desired. The first field is the label which must be 1700 1.1 christos one of the following values: 1701 1.1 christos 1702 1.1 christos 0 read data 1703 1.1 christos 1 write data 1704 1.1 christos 2 instruction fetch 1705 1.1 christos 3 escape record (treated as unknown access type) 1706 1.1 christos 4 escape record (causes cache flush) 1707 1.1 christos 1708 1.1 christos The address field is a 32bit (lower-case) hexadecimal address 1709 1.1 christos value. The address should *NOT* be preceded by "0x". 1710 1.1 christos 1711 1.1 christos The size of the memory transfer is not important when dealing with 1712 1.1 christos cache lines (as long as no more than a cache line can be 1713 1.1 christos transferred in a single operation :-), however more information 1714 1.1 christos could be given following the dineroIII requirement to allow more 1715 1.1 christos complete memory and cache simulators to provide better 1716 1.1 christos results. i.e. the University of Pisa has a cache simulator that can 1717 1.1 christos also take bus size and speed as (variable) inputs to calculate 1718 1.1 christos complete system performance (a much more useful ability when trying 1719 1.1 christos to construct an end product, rather than a processor). They 1720 1.1 christos currently have an ARM version of their tool called ChARM. */ 1721 1.1 christos 1722 1.1 christos 1723 1.1 christos void 1724 1.1 christos dotrace (SIM_DESC sd, 1725 1.1 christos sim_cpu *cpu, 1726 1.1 christos FILE *tracefh, 1727 1.1 christos int type, 1728 1.8 christos address_word address, 1729 1.1 christos int width, 1730 1.7 christos const char *comment, ...) 1731 1.1 christos { 1732 1.1 christos if (STATE & simTRACE) { 1733 1.1 christos va_list ap; 1734 1.7 christos fprintf(tracefh,"%d %s ; width %d ; ", 1735 1.1 christos type, 1736 1.1 christos pr_addr(address), 1737 1.1 christos width); 1738 1.1 christos va_start(ap,comment); 1739 1.1 christos vfprintf(tracefh,comment,ap); 1740 1.1 christos va_end(ap); 1741 1.1 christos fprintf(tracefh,"\n"); 1742 1.1 christos } 1743 1.1 christos /* NOTE: Since the "din" format will only accept 32bit addresses, and 1744 1.1 christos we may be generating 64bit ones, we should put the hi-32bits of the 1745 1.1 christos address into the comment field. */ 1746 1.1 christos 1747 1.1 christos /* TODO: Provide a buffer for the trace lines. We can then avoid 1748 1.1 christos performing writes until the buffer is filled, or the file is 1749 1.1 christos being closed. */ 1750 1.1 christos 1751 1.1 christos /* NOTE: We could consider adding a comment field to the "din" file 1752 1.1 christos produced using type 3 markers (unknown access). This would then 1753 1.1 christos allow information about the program that the "din" is for, and 1754 1.1 christos the MIPs world that was being simulated, to be placed into the 1755 1.1 christos trace file. */ 1756 1.1 christos 1757 1.1 christos return; 1758 1.1 christos } 1759 1.5 christos #endif /* WITH_TRACE_ANY_P */ 1760 1.1 christos 1761 1.1 christos /*---------------------------------------------------------------------------*/ 1762 1.1 christos /*-- simulator engine -------------------------------------------------------*/ 1763 1.1 christos /*---------------------------------------------------------------------------*/ 1764 1.1 christos 1765 1.1 christos static void 1766 1.1 christos ColdReset (SIM_DESC sd) 1767 1.1 christos { 1768 1.1 christos int cpu_nr; 1769 1.1 christos for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++) 1770 1.1 christos { 1771 1.1 christos sim_cpu *cpu = STATE_CPU (sd, cpu_nr); 1772 1.1 christos /* RESET: Fixed PC address: */ 1773 1.1 christos PC = (unsigned_word) UNSIGNED64 (0xFFFFFFFFBFC00000); 1774 1.1 christos /* The reset vector address is in the unmapped, uncached memory space. */ 1775 1.7 christos 1776 1.1 christos SR &= ~(status_SR | status_TS | status_RP); 1777 1.1 christos SR |= (status_ERL | status_BEV); 1778 1.7 christos 1779 1.1 christos /* Cheat and allow access to the complete register set immediately */ 1780 1.1 christos if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT 1781 1.1 christos && WITH_TARGET_WORD_BITSIZE == 64) 1782 1.1 christos SR |= status_FR; /* 64bit registers */ 1783 1.7 christos 1784 1.1 christos /* Ensure that any instructions with pending register updates are 1785 1.1 christos cleared: */ 1786 1.1 christos PENDING_INVALIDATE(); 1787 1.7 christos 1788 1.1 christos /* Initialise the FPU registers to the unknown state */ 1789 1.1 christos if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) 1790 1.1 christos { 1791 1.1 christos int rn; 1792 1.1 christos for (rn = 0; (rn < 32); rn++) 1793 1.1 christos FPR_STATE[rn] = fmt_uninterpreted; 1794 1.1 christos } 1795 1.7 christos 1796 1.1 christos /* Initialise the Config0 register. */ 1797 1.1 christos C0_CONFIG = 0x80000000 /* Config1 present */ 1798 1.1 christos | 2; /* KSEG0 uncached */ 1799 1.1 christos if (WITH_TARGET_WORD_BITSIZE == 64) 1800 1.1 christos { 1801 1.1 christos /* FIXME Currently mips/sim-main.c:address_translation() 1802 1.1 christos truncates all addresses to 32-bits. */ 1803 1.1 christos if (0 && WITH_TARGET_ADDRESS_BITSIZE == 64) 1804 1.1 christos C0_CONFIG |= (2 << 13); /* MIPS64, 64-bit addresses */ 1805 1.1 christos else 1806 1.1 christos C0_CONFIG |= (1 << 13); /* MIPS64, 32-bit addresses */ 1807 1.1 christos } 1808 1.1 christos if (BigEndianMem) 1809 1.1 christos C0_CONFIG |= 0x00008000; /* Big Endian */ 1810 1.1 christos } 1811 1.1 christos } 1812 1.1 christos 1813 1.1 christos 1814 1.1 christos 1815 1.1 christos 1816 1.1 christos /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ 1817 1.1 christos /* Signal an exception condition. This will result in an exception 1818 1.1 christos that aborts the instruction. The instruction operation pseudocode 1819 1.1 christos will never see a return from this function call. */ 1820 1.1 christos 1821 1.1 christos void 1822 1.1 christos signal_exception (SIM_DESC sd, 1823 1.1 christos sim_cpu *cpu, 1824 1.1 christos address_word cia, 1825 1.1 christos int exception,...) 1826 1.1 christos { 1827 1.1 christos /* int vector; */ 1828 1.1 christos 1829 1.1 christos #ifdef DEBUG 1830 1.1 christos sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia)); 1831 1.1 christos #endif /* DEBUG */ 1832 1.1 christos 1833 1.1 christos /* Ensure that any active atomic read/modify/write operation will fail: */ 1834 1.1 christos LLBIT = 0; 1835 1.1 christos 1836 1.1 christos /* Save registers before interrupt dispatching */ 1837 1.1 christos #ifdef SIM_CPU_EXCEPTION_TRIGGER 1838 1.1 christos SIM_CPU_EXCEPTION_TRIGGER(sd, cpu, cia); 1839 1.1 christos #endif 1840 1.1 christos 1841 1.1 christos switch (exception) { 1842 1.1 christos 1843 1.1 christos case DebugBreakPoint: 1844 1.1 christos if (! (Debug & Debug_DM)) 1845 1.1 christos { 1846 1.1 christos if (INDELAYSLOT()) 1847 1.1 christos { 1848 1.1 christos CANCELDELAYSLOT(); 1849 1.7 christos 1850 1.1 christos Debug |= Debug_DBD; /* signaled from within in delay slot */ 1851 1.1 christos DEPC = cia - 4; /* reference the branch instruction */ 1852 1.1 christos } 1853 1.1 christos else 1854 1.1 christos { 1855 1.1 christos Debug &= ~Debug_DBD; /* not signaled from within a delay slot */ 1856 1.1 christos DEPC = cia; 1857 1.1 christos } 1858 1.7 christos 1859 1.1 christos Debug |= Debug_DM; /* in debugging mode */ 1860 1.1 christos Debug |= Debug_DBp; /* raising a DBp exception */ 1861 1.1 christos PC = 0xBFC00200; 1862 1.1 christos sim_engine_restart (SD, CPU, NULL, NULL_CIA); 1863 1.1 christos } 1864 1.1 christos break; 1865 1.1 christos 1866 1.1 christos case ReservedInstruction: 1867 1.1 christos { 1868 1.1 christos va_list ap; 1869 1.1 christos unsigned int instruction; 1870 1.1 christos va_start(ap,exception); 1871 1.1 christos instruction = va_arg(ap,unsigned int); 1872 1.1 christos va_end(ap); 1873 1.1 christos /* Provide simple monitor support using ReservedInstruction 1874 1.1 christos exceptions. The following code simulates the fixed vector 1875 1.1 christos entry points into the IDT monitor by causing a simulator 1876 1.1 christos trap, performing the monitor operation, and returning to 1877 1.1 christos the address held in the $ra register (standard PCS return 1878 1.1 christos address). This means we only need to pre-load the vector 1879 1.1 christos space with suitable instruction values. For systems were 1880 1.1 christos actual trap instructions are used, we would not need to 1881 1.1 christos perform this magic. */ 1882 1.1 christos if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION) 1883 1.1 christos { 1884 1.1 christos int reason = (instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK; 1885 1.1 christos if (!sim_monitor (SD, CPU, cia, reason)) 1886 1.1 christos sim_io_error (sd, "sim_monitor: unhandled reason = %d, pc = 0x%s\n", reason, pr_addr (cia)); 1887 1.1 christos 1888 1.1 christos /* NOTE: This assumes that a branch-and-link style 1889 1.1 christos instruction was used to enter the vector (which is the 1890 1.1 christos case with the current IDT monitor). */ 1891 1.1 christos sim_engine_restart (SD, CPU, NULL, RA); 1892 1.1 christos } 1893 1.1 christos /* Look for the mips16 entry and exit instructions, and 1894 1.1 christos simulate a handler for them. */ 1895 1.1 christos else if ((cia & 1) != 0 1896 1.1 christos && (instruction & 0xf81f) == 0xe809 1897 1.1 christos && (instruction & 0x0c0) != 0x0c0) 1898 1.1 christos { 1899 1.1 christos mips16_entry (SD, CPU, cia, instruction); 1900 1.1 christos sim_engine_restart (sd, NULL, NULL, NULL_CIA); 1901 1.1 christos } 1902 1.1 christos /* else fall through to normal exception processing */ 1903 1.1 christos sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia)); 1904 1.8 christos ATTRIBUTE_FALLTHROUGH; 1905 1.1 christos } 1906 1.1 christos 1907 1.1 christos default: 1908 1.1 christos /* Store exception code into current exception id variable (used 1909 1.1 christos by exit code): */ 1910 1.1 christos 1911 1.1 christos /* TODO: If not simulating exceptions then stop the simulator 1912 1.1 christos execution. At the moment we always stop the simulation. */ 1913 1.1 christos 1914 1.1 christos #ifdef SUBTARGET_R3900 1915 1.1 christos /* update interrupt-related registers */ 1916 1.1 christos 1917 1.1 christos /* insert exception code in bits 6:2 */ 1918 1.1 christos CAUSE = LSMASKED32(CAUSE, 31, 7) | LSINSERTED32(exception, 6, 2); 1919 1.1 christos /* shift IE/KU history bits left */ 1920 1.1 christos SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 3, 0), 5, 2); 1921 1.1 christos 1922 1.1 christos if (STATE & simDELAYSLOT) 1923 1.1 christos { 1924 1.1 christos STATE &= ~simDELAYSLOT; 1925 1.1 christos CAUSE |= cause_BD; 1926 1.1 christos EPC = (cia - 4); /* reference the branch instruction */ 1927 1.1 christos } 1928 1.1 christos else 1929 1.1 christos EPC = cia; 1930 1.1 christos 1931 1.1 christos if (SR & status_BEV) 1932 1.1 christos PC = (signed)0xBFC00000 + 0x180; 1933 1.1 christos else 1934 1.1 christos PC = (signed)0x80000000 + 0x080; 1935 1.1 christos #else 1936 1.1 christos /* See figure 5-17 for an outline of the code below */ 1937 1.1 christos if (! (SR & status_EXL)) 1938 1.1 christos { 1939 1.1 christos CAUSE = (exception << 2); 1940 1.1 christos if (STATE & simDELAYSLOT) 1941 1.1 christos { 1942 1.1 christos STATE &= ~simDELAYSLOT; 1943 1.1 christos CAUSE |= cause_BD; 1944 1.1 christos EPC = (cia - 4); /* reference the branch instruction */ 1945 1.1 christos } 1946 1.1 christos else 1947 1.1 christos EPC = cia; 1948 1.1 christos /* FIXME: TLB et.al. */ 1949 1.1 christos /* vector = 0x180; */ 1950 1.1 christos } 1951 1.1 christos else 1952 1.1 christos { 1953 1.1 christos CAUSE = (exception << 2); 1954 1.1 christos /* vector = 0x180; */ 1955 1.1 christos } 1956 1.1 christos SR |= status_EXL; 1957 1.1 christos /* Store exception code into current exception id variable (used 1958 1.1 christos by exit code): */ 1959 1.1 christos 1960 1.1 christos if (SR & status_BEV) 1961 1.1 christos PC = (signed)0xBFC00200 + 0x180; 1962 1.1 christos else 1963 1.1 christos PC = (signed)0x80000000 + 0x180; 1964 1.1 christos #endif 1965 1.1 christos 1966 1.1 christos switch ((CAUSE >> 2) & 0x1F) 1967 1.1 christos { 1968 1.1 christos case Interrupt: 1969 1.1 christos /* Interrupts arrive during event processing, no need to 1970 1.1 christos restart */ 1971 1.1 christos return; 1972 1.1 christos 1973 1.1 christos case NMIReset: 1974 1.1 christos /* Ditto */ 1975 1.1 christos #ifdef SUBTARGET_3900 1976 1.1 christos /* Exception vector: BEV=0 BFC00000 / BEF=1 BFC00000 */ 1977 1.1 christos PC = (signed)0xBFC00000; 1978 1.1 christos #endif /* SUBTARGET_3900 */ 1979 1.1 christos return; 1980 1.1 christos 1981 1.1 christos case TLBModification: 1982 1.1 christos case TLBLoad: 1983 1.1 christos case TLBStore: 1984 1.1 christos case AddressLoad: 1985 1.1 christos case AddressStore: 1986 1.1 christos case InstructionFetch: 1987 1.1 christos case DataReference: 1988 1.1 christos /* The following is so that the simulator will continue from the 1989 1.1 christos exception handler address. */ 1990 1.1 christos sim_engine_halt (SD, CPU, NULL, PC, 1991 1.1 christos sim_stopped, SIM_SIGBUS); 1992 1.1 christos 1993 1.1 christos case ReservedInstruction: 1994 1.1 christos case CoProcessorUnusable: 1995 1.1 christos PC = EPC; 1996 1.1 christos sim_engine_halt (SD, CPU, NULL, PC, 1997 1.1 christos sim_stopped, SIM_SIGILL); 1998 1.1 christos 1999 1.1 christos case IntegerOverflow: 2000 1.1 christos case FPE: 2001 1.1 christos sim_engine_halt (SD, CPU, NULL, PC, 2002 1.1 christos sim_stopped, SIM_SIGFPE); 2003 1.7 christos 2004 1.1 christos case BreakPoint: 2005 1.1 christos sim_engine_halt (SD, CPU, NULL, PC, sim_stopped, SIM_SIGTRAP); 2006 1.1 christos break; 2007 1.1 christos 2008 1.1 christos case SystemCall: 2009 1.1 christos case Trap: 2010 1.1 christos sim_engine_restart (SD, CPU, NULL, PC); 2011 1.1 christos break; 2012 1.1 christos 2013 1.1 christos case Watch: 2014 1.1 christos PC = EPC; 2015 1.1 christos sim_engine_halt (SD, CPU, NULL, PC, 2016 1.1 christos sim_stopped, SIM_SIGTRAP); 2017 1.1 christos 2018 1.1 christos default: /* Unknown internal exception */ 2019 1.1 christos PC = EPC; 2020 1.1 christos sim_engine_halt (SD, CPU, NULL, PC, 2021 1.1 christos sim_stopped, SIM_SIGABRT); 2022 1.1 christos 2023 1.1 christos } 2024 1.1 christos 2025 1.1 christos case SimulatorFault: 2026 1.1 christos { 2027 1.1 christos va_list ap; 2028 1.1 christos char *msg; 2029 1.1 christos va_start(ap,exception); 2030 1.1 christos msg = va_arg(ap,char *); 2031 1.1 christos va_end(ap); 2032 1.1 christos sim_engine_abort (SD, CPU, NULL_CIA, 2033 1.1 christos "FATAL: Simulator error \"%s\"\n",msg); 2034 1.1 christos } 2035 1.1 christos } 2036 1.1 christos 2037 1.1 christos return; 2038 1.1 christos } 2039 1.1 christos 2040 1.1 christos 2041 1.1 christos 2042 1.1 christos /* This function implements what the MIPS32 and MIPS64 ISAs define as 2043 1.1 christos "UNPREDICTABLE" behaviour. 2044 1.1 christos 2045 1.1 christos About UNPREDICTABLE behaviour they say: "UNPREDICTABLE results 2046 1.1 christos may vary from processor implementation to processor implementation, 2047 1.1 christos instruction to instruction, or as a function of time on the same 2048 1.1 christos implementation or instruction. Software can never depend on results 2049 1.1 christos that are UNPREDICTABLE. ..." (MIPS64 Architecture for Programmers 2050 1.1 christos Volume II, The MIPS64 Instruction Set. MIPS Document MD00087 revision 2051 1.1 christos 0.95, page 2.) 2052 1.7 christos 2053 1.1 christos For UNPREDICTABLE behaviour, we print a message, if possible print 2054 1.1 christos the offending instructions mips.igen instruction name (provided by 2055 1.1 christos the caller), and stop the simulator. 2056 1.1 christos 2057 1.1 christos XXX FIXME: eventually, stopping the simulator should be made conditional 2058 1.1 christos on a command-line option. */ 2059 1.1 christos void 2060 1.1 christos unpredictable_action(sim_cpu *cpu, address_word cia) 2061 1.1 christos { 2062 1.1 christos SIM_DESC sd = CPU_STATE(cpu); 2063 1.1 christos 2064 1.1 christos sim_io_eprintf(sd, "UNPREDICTABLE: PC = 0x%s\n", pr_addr (cia)); 2065 1.1 christos sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGABRT); 2066 1.1 christos } 2067 1.1 christos 2068 1.1 christos 2069 1.1 christos /*-- co-processor support routines ------------------------------------------*/ 2070 1.1 christos 2071 1.1 christos static int UNUSED 2072 1.1 christos CoProcPresent(unsigned int coproc_number) 2073 1.1 christos { 2074 1.1 christos /* Return TRUE if simulator provides a model for the given co-processor number */ 2075 1.1 christos return(0); 2076 1.1 christos } 2077 1.1 christos 2078 1.1 christos void 2079 1.1 christos cop_lw (SIM_DESC sd, 2080 1.1 christos sim_cpu *cpu, 2081 1.1 christos address_word cia, 2082 1.1 christos int coproc_num, 2083 1.1 christos int coproc_reg, 2084 1.1 christos unsigned int memword) 2085 1.1 christos { 2086 1.1 christos switch (coproc_num) 2087 1.1 christos { 2088 1.1 christos case 1: 2089 1.1 christos if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) 2090 1.1 christos { 2091 1.1 christos #ifdef DEBUG 2092 1.1 christos printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword)); 2093 1.1 christos #endif 2094 1.1 christos StoreFPR(coproc_reg,fmt_uninterpreted_32,(uword64)memword); 2095 1.1 christos break; 2096 1.1 christos } 2097 1.1 christos 2098 1.1 christos default: 2099 1.1 christos #if 0 /* this should be controlled by a configuration option */ 2100 1.1 christos sim_io_printf(sd,"COP_LW(%d,%d,0x%08X) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,pr_addr(cia)); 2101 1.1 christos #endif 2102 1.1 christos break; 2103 1.1 christos } 2104 1.1 christos 2105 1.1 christos return; 2106 1.1 christos } 2107 1.1 christos 2108 1.1 christos void 2109 1.1 christos cop_ld (SIM_DESC sd, 2110 1.1 christos sim_cpu *cpu, 2111 1.1 christos address_word cia, 2112 1.1 christos int coproc_num, 2113 1.1 christos int coproc_reg, 2114 1.1 christos uword64 memword) 2115 1.1 christos { 2116 1.1 christos 2117 1.1 christos #ifdef DEBUG 2118 1.7 christos printf("DBG: COP_LD: coproc_num = %d, coproc_reg = %d, value = 0x%s : PC = 0x%s\n", coproc_num, coproc_reg, pr_uword64(memword), pr_addr(cia)); 2119 1.1 christos #endif 2120 1.1 christos 2121 1.1 christos switch (coproc_num) { 2122 1.1 christos case 1: 2123 1.1 christos if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) 2124 1.1 christos { 2125 1.1 christos StoreFPR(coproc_reg,fmt_uninterpreted_64,memword); 2126 1.1 christos break; 2127 1.1 christos } 2128 1.1 christos 2129 1.1 christos default: 2130 1.1 christos #if 0 /* this message should be controlled by a configuration option */ 2131 1.1 christos sim_io_printf(sd,"COP_LD(%d,%d,0x%s) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(memword),pr_addr(cia)); 2132 1.1 christos #endif 2133 1.1 christos break; 2134 1.1 christos } 2135 1.1 christos 2136 1.1 christos return; 2137 1.1 christos } 2138 1.1 christos 2139 1.1 christos 2140 1.1 christos 2141 1.1 christos 2142 1.1 christos unsigned int 2143 1.1 christos cop_sw (SIM_DESC sd, 2144 1.1 christos sim_cpu *cpu, 2145 1.1 christos address_word cia, 2146 1.1 christos int coproc_num, 2147 1.1 christos int coproc_reg) 2148 1.1 christos { 2149 1.1 christos unsigned int value = 0; 2150 1.1 christos 2151 1.1 christos switch (coproc_num) 2152 1.1 christos { 2153 1.1 christos case 1: 2154 1.1 christos if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) 2155 1.1 christos { 2156 1.1 christos value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted_32); 2157 1.1 christos break; 2158 1.1 christos } 2159 1.1 christos 2160 1.1 christos default: 2161 1.1 christos #if 0 /* should be controlled by configuration option */ 2162 1.1 christos sim_io_printf(sd,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia)); 2163 1.1 christos #endif 2164 1.1 christos break; 2165 1.1 christos } 2166 1.1 christos 2167 1.1 christos return(value); 2168 1.1 christos } 2169 1.1 christos 2170 1.1 christos uword64 2171 1.1 christos cop_sd (SIM_DESC sd, 2172 1.1 christos sim_cpu *cpu, 2173 1.1 christos address_word cia, 2174 1.1 christos int coproc_num, 2175 1.1 christos int coproc_reg) 2176 1.1 christos { 2177 1.1 christos uword64 value = 0; 2178 1.1 christos switch (coproc_num) 2179 1.1 christos { 2180 1.1 christos case 1: 2181 1.1 christos if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) 2182 1.1 christos { 2183 1.1 christos value = ValueFPR(coproc_reg,fmt_uninterpreted_64); 2184 1.1 christos break; 2185 1.1 christos } 2186 1.1 christos 2187 1.1 christos default: 2188 1.1 christos #if 0 /* should be controlled by configuration option */ 2189 1.1 christos sim_io_printf(sd,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia)); 2190 1.1 christos #endif 2191 1.1 christos break; 2192 1.1 christos } 2193 1.1 christos 2194 1.1 christos return(value); 2195 1.1 christos } 2196 1.1 christos 2197 1.1 christos 2198 1.1 christos 2199 1.1 christos 2200 1.1 christos void 2201 1.1 christos decode_coproc (SIM_DESC sd, 2202 1.1 christos sim_cpu *cpu, 2203 1.1 christos address_word cia, 2204 1.6 christos unsigned int instruction, 2205 1.6 christos int coprocnum, 2206 1.6 christos CP0_operation op, 2207 1.6 christos int rt, 2208 1.6 christos int rd, 2209 1.6 christos int sel) 2210 1.1 christos { 2211 1.1 christos switch (coprocnum) 2212 1.1 christos { 2213 1.1 christos case 0: /* standard CPU control and cache registers */ 2214 1.1 christos { 2215 1.1 christos /* R4000 Users Manual (second edition) lists the following CP0 2216 1.1 christos instructions: 2217 1.1 christos CODE><-RT><RD-><--TAIL---> 2218 1.1 christos DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000) 2219 1.1 christos DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000) 2220 1.1 christos MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000) 2221 1.1 christos MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000) 2222 1.1 christos TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001) 2223 1.1 christos TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010) 2224 1.1 christos TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110) 2225 1.1 christos TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000) 2226 1.1 christos CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii) 2227 1.1 christos ERET Exception return (VR4100 = 01000010000000000000000000011000) 2228 1.1 christos */ 2229 1.6 christos if (((op == cp0_mfc0) || (op == cp0_mtc0) /* MFC0 / MTC0 */ 2230 1.6 christos || (op == cp0_dmfc0) || (op == cp0_dmtc0)) /* DMFC0 / DMTC0 */ 2231 1.6 christos && sel == 0) 2232 1.1 christos { 2233 1.1 christos switch (rd) /* NOTEs: Standard CP0 registers */ 2234 1.1 christos { 2235 1.1 christos /* 0 = Index R4000 VR4100 VR4300 */ 2236 1.1 christos /* 1 = Random R4000 VR4100 VR4300 */ 2237 1.1 christos /* 2 = EntryLo0 R4000 VR4100 VR4300 */ 2238 1.1 christos /* 3 = EntryLo1 R4000 VR4100 VR4300 */ 2239 1.1 christos /* 4 = Context R4000 VR4100 VR4300 */ 2240 1.1 christos /* 5 = PageMask R4000 VR4100 VR4300 */ 2241 1.1 christos /* 6 = Wired R4000 VR4100 VR4300 */ 2242 1.1 christos /* 8 = BadVAddr R4000 VR4100 VR4300 */ 2243 1.1 christos /* 9 = Count R4000 VR4100 VR4300 */ 2244 1.1 christos /* 10 = EntryHi R4000 VR4100 VR4300 */ 2245 1.1 christos /* 11 = Compare R4000 VR4100 VR4300 */ 2246 1.1 christos /* 12 = SR R4000 VR4100 VR4300 */ 2247 1.1 christos #ifdef SUBTARGET_R3900 2248 1.1 christos case 3: 2249 1.1 christos /* 3 = Config R3900 */ 2250 1.1 christos case 7: 2251 1.1 christos /* 7 = Cache R3900 */ 2252 1.1 christos case 15: 2253 1.1 christos /* 15 = PRID R3900 */ 2254 1.1 christos 2255 1.1 christos /* ignore */ 2256 1.1 christos break; 2257 1.1 christos 2258 1.1 christos case 8: 2259 1.1 christos /* 8 = BadVAddr R4000 VR4100 VR4300 */ 2260 1.6 christos if (op == cp0_mfc0 || op == cp0_dmfc0) 2261 1.1 christos GPR[rt] = (signed_word) (signed_address) COP0_BADVADDR; 2262 1.1 christos else 2263 1.1 christos COP0_BADVADDR = GPR[rt]; 2264 1.1 christos break; 2265 1.1 christos 2266 1.1 christos #endif /* SUBTARGET_R3900 */ 2267 1.1 christos case 12: 2268 1.6 christos if (op == cp0_mfc0 || op == cp0_dmfc0) 2269 1.1 christos GPR[rt] = SR; 2270 1.1 christos else 2271 1.1 christos SR = GPR[rt]; 2272 1.1 christos break; 2273 1.1 christos /* 13 = Cause R4000 VR4100 VR4300 */ 2274 1.1 christos case 13: 2275 1.6 christos if (op == cp0_mfc0 || op == cp0_dmfc0) 2276 1.1 christos GPR[rt] = CAUSE; 2277 1.1 christos else 2278 1.1 christos CAUSE = GPR[rt]; 2279 1.1 christos break; 2280 1.1 christos /* 14 = EPC R4000 VR4100 VR4300 */ 2281 1.1 christos case 14: 2282 1.6 christos if (op == cp0_mfc0 || op == cp0_dmfc0) 2283 1.1 christos GPR[rt] = (signed_word) (signed_address) EPC; 2284 1.1 christos else 2285 1.1 christos EPC = GPR[rt]; 2286 1.1 christos break; 2287 1.1 christos /* 15 = PRId R4000 VR4100 VR4300 */ 2288 1.1 christos #ifdef SUBTARGET_R3900 2289 1.1 christos /* 16 = Debug */ 2290 1.1 christos case 16: 2291 1.6 christos if (op == cp0_mfc0 || op == cp0_dmfc0) 2292 1.1 christos GPR[rt] = Debug; 2293 1.1 christos else 2294 1.1 christos Debug = GPR[rt]; 2295 1.1 christos break; 2296 1.1 christos #else 2297 1.1 christos /* 16 = Config R4000 VR4100 VR4300 */ 2298 1.1 christos case 16: 2299 1.6 christos if (op == cp0_mfc0 || op == cp0_dmfc0) 2300 1.1 christos GPR[rt] = C0_CONFIG; 2301 1.1 christos else 2302 1.1 christos /* only bottom three bits are writable */ 2303 1.1 christos C0_CONFIG = (C0_CONFIG & ~0x7) | (GPR[rt] & 0x7); 2304 1.1 christos break; 2305 1.1 christos #endif 2306 1.1 christos #ifdef SUBTARGET_R3900 2307 1.1 christos /* 17 = Debug */ 2308 1.1 christos case 17: 2309 1.6 christos if (op == cp0_mfc0 || op == cp0_dmfc0) 2310 1.1 christos GPR[rt] = DEPC; 2311 1.1 christos else 2312 1.1 christos DEPC = GPR[rt]; 2313 1.1 christos break; 2314 1.1 christos #else 2315 1.1 christos /* 17 = LLAddr R4000 VR4100 VR4300 */ 2316 1.1 christos #endif 2317 1.1 christos /* 18 = WatchLo R4000 VR4100 VR4300 */ 2318 1.1 christos /* 19 = WatchHi R4000 VR4100 VR4300 */ 2319 1.1 christos /* 20 = XContext R4000 VR4100 VR4300 */ 2320 1.1 christos /* 26 = PErr or ECC R4000 VR4100 VR4300 */ 2321 1.1 christos /* 27 = CacheErr R4000 VR4100 */ 2322 1.1 christos /* 28 = TagLo R4000 VR4100 VR4300 */ 2323 1.1 christos /* 29 = TagHi R4000 VR4100 VR4300 */ 2324 1.1 christos /* 30 = ErrorEPC R4000 VR4100 VR4300 */ 2325 1.1 christos if (STATE_VERBOSE_P(SD)) 2326 1.7 christos sim_io_eprintf (SD, 2327 1.1 christos "Warning: PC 0x%lx:interp.c decode_coproc DEADC0DE\n", 2328 1.1 christos (unsigned long)cia); 2329 1.1 christos GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */ 2330 1.8 christos ATTRIBUTE_FALLTHROUGH; 2331 1.1 christos /* CPR[0,rd] = GPR[rt]; */ 2332 1.1 christos default: 2333 1.6 christos if (op == cp0_mfc0 || op == cp0_dmfc0) 2334 1.7 christos GPR[rt] = (signed_word) (int32_t) COP0_GPR[rd]; 2335 1.1 christos else 2336 1.1 christos COP0_GPR[rd] = GPR[rt]; 2337 1.1 christos #if 0 2338 1.1 christos if (code == 0x00) 2339 1.1 christos sim_io_printf(sd,"Warning: MFC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia); 2340 1.1 christos else 2341 1.1 christos sim_io_printf(sd,"Warning: MTC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia); 2342 1.1 christos #endif 2343 1.1 christos } 2344 1.1 christos } 2345 1.6 christos else if ((op == cp0_mfc0 || op == cp0_dmfc0) 2346 1.1 christos && rd == 16) 2347 1.1 christos { 2348 1.1 christos /* [D]MFC0 RT,C0_CONFIG,SEL */ 2349 1.7 christos int32_t cfg = 0; 2350 1.6 christos switch (sel) 2351 1.1 christos { 2352 1.1 christos case 0: 2353 1.1 christos cfg = C0_CONFIG; 2354 1.1 christos break; 2355 1.1 christos case 1: 2356 1.7 christos /* MIPS32 r/o Config1: 2357 1.1 christos Config2 present */ 2358 1.1 christos cfg = 0x80000000; 2359 1.7 christos /* MIPS16 implemented. 2360 1.1 christos XXX How to check configuration? */ 2361 1.1 christos cfg |= 0x0000004; 2362 1.1 christos if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) 2363 1.1 christos /* MDMX & FPU implemented */ 2364 1.1 christos cfg |= 0x00000021; 2365 1.1 christos break; 2366 1.1 christos case 2: 2367 1.7 christos /* MIPS32 r/o Config2: 2368 1.1 christos Config3 present. */ 2369 1.1 christos cfg = 0x80000000; 2370 1.1 christos break; 2371 1.1 christos case 3: 2372 1.7 christos /* MIPS32 r/o Config3: 2373 1.1 christos SmartMIPS implemented. */ 2374 1.1 christos cfg = 0x00000002; 2375 1.1 christos break; 2376 1.1 christos } 2377 1.1 christos GPR[rt] = cfg; 2378 1.1 christos } 2379 1.6 christos else if (op == cp0_eret && sel == 0x18) 2380 1.1 christos { 2381 1.1 christos /* ERET */ 2382 1.1 christos if (SR & status_ERL) 2383 1.1 christos { 2384 1.1 christos /* Oops, not yet available */ 2385 1.1 christos sim_io_printf(sd,"Warning: ERET when SR[ERL] set not handled yet"); 2386 1.1 christos PC = EPC; 2387 1.1 christos SR &= ~status_ERL; 2388 1.1 christos } 2389 1.1 christos else 2390 1.1 christos { 2391 1.1 christos PC = EPC; 2392 1.1 christos SR &= ~status_EXL; 2393 1.1 christos } 2394 1.1 christos } 2395 1.6 christos else if (op == cp0_rfe && sel == 0x10) 2396 1.1 christos { 2397 1.1 christos /* RFE */ 2398 1.1 christos #ifdef SUBTARGET_R3900 2399 1.1 christos /* TX39: Copy IEp/KUp -> IEc/KUc, and IEo/KUo -> IEp/KUp */ 2400 1.1 christos 2401 1.1 christos /* shift IE/KU history bits right */ 2402 1.1 christos SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 5, 2), 3, 0); 2403 1.1 christos 2404 1.1 christos /* TODO: CACHE register */ 2405 1.1 christos #endif /* SUBTARGET_R3900 */ 2406 1.1 christos } 2407 1.6 christos else if (op == cp0_deret && sel == 0x1F) 2408 1.1 christos { 2409 1.1 christos /* DERET */ 2410 1.1 christos Debug &= ~Debug_DM; 2411 1.1 christos DELAYSLOT(); 2412 1.1 christos DSPC = DEPC; 2413 1.1 christos } 2414 1.1 christos else 2415 1.1 christos sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia)); 2416 1.1 christos /* TODO: When executing an ERET or RFE instruction we should 2417 1.1 christos clear LLBIT, to ensure that any out-standing atomic 2418 1.1 christos read/modify/write sequence fails. */ 2419 1.1 christos } 2420 1.1 christos break; 2421 1.7 christos 2422 1.1 christos case 2: /* co-processor 2 */ 2423 1.1 christos { 2424 1.1 christos int handle = 0; 2425 1.1 christos 2426 1.1 christos 2427 1.7 christos if (!handle) 2428 1.1 christos { 2429 1.1 christos sim_io_eprintf(sd, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n", 2430 1.1 christos instruction,pr_addr(cia)); 2431 1.1 christos } 2432 1.1 christos } 2433 1.1 christos break; 2434 1.7 christos 2435 1.1 christos case 1: /* should not occur (FPU co-processor) */ 2436 1.1 christos case 3: /* should not occur (FPU co-processor) */ 2437 1.1 christos SignalException(ReservedInstruction,instruction); 2438 1.1 christos break; 2439 1.1 christos } 2440 1.7 christos 2441 1.1 christos return; 2442 1.1 christos } 2443 1.1 christos 2444 1.1 christos 2445 1.1 christos /* This code copied from gdb's utils.c. Would like to share this code, 2446 1.1 christos but don't know of a common place where both could get to it. */ 2447 1.1 christos 2448 1.1 christos /* Temporary storage using circular buffer */ 2449 1.1 christos #define NUMCELLS 16 2450 1.1 christos #define CELLSIZE 32 2451 1.1 christos static char* 2452 1.1 christos get_cell (void) 2453 1.1 christos { 2454 1.1 christos static char buf[NUMCELLS][CELLSIZE]; 2455 1.1 christos static int cell=0; 2456 1.1 christos if (++cell>=NUMCELLS) cell=0; 2457 1.1 christos return buf[cell]; 2458 1.7 christos } 2459 1.1 christos 2460 1.1 christos /* Print routines to handle variable size regs, etc */ 2461 1.1 christos 2462 1.7 christos char* 2463 1.8 christos pr_addr (address_word addr) 2464 1.1 christos { 2465 1.1 christos char *paddr_str=get_cell(); 2466 1.8 christos sprintf (paddr_str, "%0*" PRIxTA, (int) (sizeof (addr) * 2), addr); 2467 1.1 christos return paddr_str; 2468 1.1 christos } 2469 1.1 christos 2470 1.7 christos char* 2471 1.5 christos pr_uword64 (uword64 addr) 2472 1.1 christos { 2473 1.1 christos char *paddr_str=get_cell(); 2474 1.8 christos sprintf (paddr_str, "%016" PRIx64, addr); 2475 1.1 christos return paddr_str; 2476 1.1 christos } 2477 1.1 christos 2478 1.1 christos 2479 1.1 christos void 2480 1.1 christos mips_core_signal (SIM_DESC sd, 2481 1.1 christos sim_cpu *cpu, 2482 1.1 christos sim_cia cia, 2483 1.1 christos unsigned map, 2484 1.1 christos int nr_bytes, 2485 1.1 christos address_word addr, 2486 1.1 christos transfer_type transfer, 2487 1.1 christos sim_core_signals sig) 2488 1.1 christos { 2489 1.1 christos const char *copy = (transfer == read_transfer ? "read" : "write"); 2490 1.1 christos address_word ip = CIA_ADDR (cia); 2491 1.1 christos 2492 1.1 christos switch (sig) 2493 1.1 christos { 2494 1.1 christos case sim_core_unmapped_signal: 2495 1.1 christos sim_io_eprintf (sd, "mips-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n", 2496 1.7 christos nr_bytes, copy, 2497 1.1 christos (unsigned long) addr, (unsigned long) ip); 2498 1.1 christos COP0_BADVADDR = addr; 2499 1.1 christos SignalExceptionDataReference(); 2500 1.8 christos /* Shouldn't actually be reached. */ 2501 1.8 christos abort (); 2502 1.1 christos 2503 1.1 christos case sim_core_unaligned_signal: 2504 1.1 christos sim_io_eprintf (sd, "mips-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n", 2505 1.7 christos nr_bytes, copy, 2506 1.1 christos (unsigned long) addr, (unsigned long) ip); 2507 1.1 christos COP0_BADVADDR = addr; 2508 1.7 christos if (transfer == read_transfer) 2509 1.1 christos SignalExceptionAddressLoad(); 2510 1.1 christos else 2511 1.1 christos SignalExceptionAddressStore(); 2512 1.8 christos /* Shouldn't actually be reached. */ 2513 1.8 christos abort (); 2514 1.1 christos 2515 1.1 christos default: 2516 1.1 christos sim_engine_abort (sd, cpu, cia, 2517 1.1 christos "mips_core_signal - internal error - bad switch"); 2518 1.1 christos } 2519 1.1 christos } 2520 1.1 christos 2521 1.1 christos 2522 1.1 christos void 2523 1.1 christos mips_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia) 2524 1.1 christos { 2525 1.8 christos struct mips_sim_cpu *mips_cpu = MIPS_SIM_CPU (cpu); 2526 1.8 christos 2527 1.1 christos ASSERT(cpu != NULL); 2528 1.1 christos 2529 1.8 christos if (mips_cpu->exc_suspended > 0) 2530 1.8 christos sim_io_eprintf (sd, "Warning, nested exception triggered (%d)\n", 2531 1.8 christos mips_cpu->exc_suspended); 2532 1.1 christos 2533 1.1 christos PC = cia; 2534 1.8 christos memcpy (mips_cpu->exc_trigger_registers, mips_cpu->registers, 2535 1.8 christos sizeof (mips_cpu->exc_trigger_registers)); 2536 1.8 christos mips_cpu->exc_suspended = 0; 2537 1.1 christos } 2538 1.1 christos 2539 1.1 christos void 2540 1.1 christos mips_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception) 2541 1.1 christos { 2542 1.8 christos struct mips_sim_cpu *mips_cpu = MIPS_SIM_CPU (cpu); 2543 1.8 christos 2544 1.1 christos ASSERT(cpu != NULL); 2545 1.1 christos 2546 1.8 christos if (mips_cpu->exc_suspended > 0) 2547 1.7 christos sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n", 2548 1.8 christos mips_cpu->exc_suspended, exception); 2549 1.1 christos 2550 1.8 christos memcpy (mips_cpu->exc_suspend_registers, mips_cpu->registers, 2551 1.8 christos sizeof (mips_cpu->exc_suspend_registers)); 2552 1.8 christos memcpy (mips_cpu->registers, mips_cpu->exc_trigger_registers, 2553 1.8 christos sizeof (mips_cpu->registers)); 2554 1.8 christos mips_cpu->exc_suspended = exception; 2555 1.1 christos } 2556 1.1 christos 2557 1.1 christos void 2558 1.1 christos mips_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception) 2559 1.1 christos { 2560 1.8 christos struct mips_sim_cpu *mips_cpu = MIPS_SIM_CPU (cpu); 2561 1.8 christos 2562 1.1 christos ASSERT(cpu != NULL); 2563 1.1 christos 2564 1.8 christos if (exception == 0 && mips_cpu->exc_suspended > 0) 2565 1.1 christos { 2566 1.1 christos /* warn not for breakpoints */ 2567 1.8 christos if (mips_cpu->exc_suspended != sim_signal_to_host(sd, SIM_SIGTRAP)) 2568 1.1 christos sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n", 2569 1.8 christos mips_cpu->exc_suspended); 2570 1.1 christos } 2571 1.8 christos else if (exception != 0 && mips_cpu->exc_suspended > 0) 2572 1.1 christos { 2573 1.8 christos if (exception != mips_cpu->exc_suspended) 2574 1.1 christos sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n", 2575 1.8 christos mips_cpu->exc_suspended, exception); 2576 1.7 christos 2577 1.8 christos memcpy (mips_cpu->registers, mips_cpu->exc_suspend_registers, 2578 1.8 christos sizeof (mips_cpu->registers)); 2579 1.1 christos } 2580 1.8 christos else if (exception != 0 && mips_cpu->exc_suspended == 0) 2581 1.1 christos { 2582 1.9 christos sim_io_eprintf(sd, "Warning, ignoring spontaneous exception signal (%d)\n", exception); 2583 1.1 christos } 2584 1.8 christos mips_cpu->exc_suspended = 0; 2585 1.1 christos } 2586 1.1 christos 2587 1.1 christos 2588 1.1 christos /*---------------------------------------------------------------------------*/ 2589 1.1 christos /*> EOF interp.c <*/ 2590