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