a0327636506db684876e36ee3e51c08464fe97bf
[deliverable/binutils-gdb.git] / sim / mips / interp.c
1 /*> interp.c <*/
2 /* Simulator for the MIPS architecture.
3
4 This file is part of the MIPS sim
5
6 THIS SOFTWARE IS NOT COPYRIGHTED
7
8 Cygnus offers the following for use in the public domain. Cygnus
9 makes no warranty with regard to the software or it's performance
10 and the user accepts the software "AS IS" with all faults.
11
12 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
13 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15
16 NOTEs:
17
18 The IDT monitor (found on the VR4300 board), seems to lie about
19 register contents. It seems to treat the registers as sign-extended
20 32-bit values. This cause *REAL* problems when single-stepping 64-bit
21 code on the hardware.
22
23 */
24
25 /* The TRACE manifests enable the provision of extra features. If they
26 are not defined then a simpler (quicker) simulator is constructed
27 without the required run-time checks, etc. */
28 #if 1 /* 0 to allow user build selection, 1 to force inclusion */
29 #define TRACE (1)
30 #endif
31
32 #include "bfd.h"
33 #include "sim-main.h"
34 #include "sim-utils.h"
35 #include "sim-options.h"
36 #include "sim-assert.h"
37 #include "sim-hw.h"
38
39 #include "itable.h"
40
41
42 #include "config.h"
43
44 #include <stdio.h>
45 #include <stdarg.h>
46 #include <ansidecl.h>
47 #include <ctype.h>
48 #include <limits.h>
49 #include <math.h>
50 #ifdef HAVE_STDLIB_H
51 #include <stdlib.h>
52 #endif
53 #ifdef HAVE_STRING_H
54 #include <string.h>
55 #else
56 #ifdef HAVE_STRINGS_H
57 #include <strings.h>
58 #endif
59 #endif
60
61 #include "getopt.h"
62 #include "libiberty.h"
63 #include "bfd.h"
64 #include "callback.h" /* GDB simulator callback interface */
65 #include "remote-sim.h" /* GDB simulator interface */
66
67 #include "sysdep.h"
68
69 #ifndef PARAMS
70 #define PARAMS(x)
71 #endif
72
73 char* pr_addr PARAMS ((SIM_ADDR addr));
74 char* pr_uword64 PARAMS ((uword64 addr));
75
76
77 /* Within interp.c we refer to the sim_state and sim_cpu directly. */
78 #define CPU cpu
79 #define SD sd
80
81
82 /* The following reserved instruction value is used when a simulator
83 trap is required. NOTE: Care must be taken, since this value may be
84 used in later revisions of the MIPS ISA. */
85
86 #define RSVD_INSTRUCTION (0x00000005)
87 #define RSVD_INSTRUCTION_MASK (0xFC00003F)
88
89 #define RSVD_INSTRUCTION_ARG_SHIFT 6
90 #define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
91
92
93 /* Bits in the Debug register */
94 #define Debug_DBD 0x80000000 /* Debug Branch Delay */
95 #define Debug_DM 0x40000000 /* Debug Mode */
96 #define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */
97
98 /*---------------------------------------------------------------------------*/
99 /*-- GDB simulator interface ------------------------------------------------*/
100 /*---------------------------------------------------------------------------*/
101
102 static void ColdReset PARAMS((SIM_DESC sd));
103
104 /*---------------------------------------------------------------------------*/
105
106
107
108 #define DELAYSLOT() {\
109 if (STATE & simDELAYSLOT)\
110 sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
111 STATE |= simDELAYSLOT;\
112 }
113
114 #define JALDELAYSLOT() {\
115 DELAYSLOT ();\
116 STATE |= simJALDELAYSLOT;\
117 }
118
119 #define NULLIFY() {\
120 STATE &= ~simDELAYSLOT;\
121 STATE |= simSKIPNEXT;\
122 }
123
124 #define CANCELDELAYSLOT() {\
125 DSSTATE = 0;\
126 STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
127 }
128
129 #define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
130 #define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
131
132 /* Note that the monitor code essentially assumes this layout of memory.
133 If you change these, change the monitor code, too. */
134 #define K0BASE (0x80000000)
135 #define K0SIZE (0x20000000)
136 #define K1BASE (0xA0000000)
137 #define K1SIZE (0x20000000)
138
139 /* Simple run-time monitor support.
140
141 We emulate the monitor by placing magic reserved instructions at
142 the monitor's entry points; when we hit these instructions, instead
143 of raising an exception (as we would normally), we look at the
144 instruction and perform the appropriate monitory operation.
145
146 `*_monitor_base' are the physical addresses at which the corresponding
147 monitor vectors are located. `0' means none. By default,
148 install all three.
149 The RSVD_INSTRUCTION... macros specify the magic instructions we
150 use at the monitor entry points. */
151 static int firmware_option_p = 0;
152 static SIM_ADDR idt_monitor_base = 0xBFC00000;
153 static SIM_ADDR pmon_monitor_base = 0xBFC00500;
154 static SIM_ADDR lsipmon_monitor_base = 0xBFC00200;
155
156 static SIM_RC sim_firmware_command (SIM_DESC sd, char* arg);
157
158
159 #define MEM_SIZE (2 << 20)
160
161
162 #if defined(TRACE)
163 static char *tracefile = "trace.din"; /* default filename for trace log */
164 FILE *tracefh = NULL;
165 static void open_trace PARAMS((SIM_DESC sd));
166 #endif /* TRACE */
167
168 static const char * get_insn_name (sim_cpu *, int);
169
170 /* simulation target board. NULL=canonical */
171 static char* board = NULL;
172
173
174 static DECLARE_OPTION_HANDLER (mips_option_handler);
175
176 enum {
177 OPTION_DINERO_TRACE = OPTION_START,
178 OPTION_DINERO_FILE,
179 OPTION_FIRMWARE,
180 OPTION_BOARD
181 };
182
183
184 static SIM_RC
185 mips_option_handler (sd, cpu, opt, arg, is_command)
186 SIM_DESC sd;
187 sim_cpu *cpu;
188 int opt;
189 char *arg;
190 int is_command;
191 {
192 int cpu_nr;
193 switch (opt)
194 {
195 case OPTION_DINERO_TRACE: /* ??? */
196 #if defined(TRACE)
197 /* Eventually the simTRACE flag could be treated as a toggle, to
198 allow external control of the program points being traced
199 (i.e. only from main onwards, excluding the run-time setup,
200 etc.). */
201 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
202 {
203 sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
204 if (arg == NULL)
205 STATE |= simTRACE;
206 else if (strcmp (arg, "yes") == 0)
207 STATE |= simTRACE;
208 else if (strcmp (arg, "no") == 0)
209 STATE &= ~simTRACE;
210 else if (strcmp (arg, "on") == 0)
211 STATE |= simTRACE;
212 else if (strcmp (arg, "off") == 0)
213 STATE &= ~simTRACE;
214 else
215 {
216 fprintf (stderr, "Unrecognized dinero-trace option `%s'\n", arg);
217 return SIM_RC_FAIL;
218 }
219 }
220 return SIM_RC_OK;
221 #else /* !TRACE */
222 fprintf(stderr,"\
223 Simulator constructed without dinero tracing support (for performance).\n\
224 Re-compile simulator with \"-DTRACE\" to enable this option.\n");
225 return SIM_RC_FAIL;
226 #endif /* !TRACE */
227
228 case OPTION_DINERO_FILE:
229 #if defined(TRACE)
230 if (optarg != NULL) {
231 char *tmp;
232 tmp = (char *)malloc(strlen(optarg) + 1);
233 if (tmp == NULL)
234 {
235 sim_io_printf(sd,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg);
236 return SIM_RC_FAIL;
237 }
238 else {
239 strcpy(tmp,optarg);
240 tracefile = tmp;
241 sim_io_printf(sd,"Placing trace information into file \"%s\"\n",tracefile);
242 }
243 }
244 #endif /* TRACE */
245 return SIM_RC_OK;
246
247 case OPTION_FIRMWARE:
248 return sim_firmware_command (sd, arg);
249
250 case OPTION_BOARD:
251 {
252 if (arg)
253 {
254 board = zalloc(strlen(arg) + 1);
255 strcpy(board, arg);
256 }
257 return SIM_RC_OK;
258 }
259 }
260
261 return SIM_RC_OK;
262 }
263
264
265 static const OPTION mips_options[] =
266 {
267 { {"dinero-trace", optional_argument, NULL, OPTION_DINERO_TRACE},
268 '\0', "on|off", "Enable dinero tracing",
269 mips_option_handler },
270 { {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE},
271 '\0', "FILE", "Write dinero trace to FILE",
272 mips_option_handler },
273 { {"firmware", required_argument, NULL, OPTION_FIRMWARE},
274 '\0', "[idt|pmon|lsipmon|none][@ADDRESS]", "Emulate ROM monitor",
275 mips_option_handler },
276 { {"board", required_argument, NULL, OPTION_BOARD},
277 '\0', "none" /* rely on compile-time string concatenation for other options */
278
279 #define BOARD_JMR3904 "jmr3904"
280 "|" BOARD_JMR3904
281 #define BOARD_JMR3904_PAL "jmr3904pal"
282 "|" BOARD_JMR3904_PAL
283 #define BOARD_JMR3904_DEBUG "jmr3904debug"
284 "|" BOARD_JMR3904_DEBUG
285 #define BOARD_BSP "bsp"
286 "|" BOARD_BSP
287
288 , "Customize simulation for a particular board.", mips_option_handler },
289
290 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
291 };
292
293
294 int interrupt_pending;
295
296 void
297 interrupt_event (SIM_DESC sd, void *data)
298 {
299 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
300 address_word cia = CIA_GET (cpu);
301 if (SR & status_IE)
302 {
303 interrupt_pending = 0;
304 SignalExceptionInterrupt (1); /* interrupt "1" */
305 }
306 else if (!interrupt_pending)
307 sim_events_schedule (sd, 1, interrupt_event, data);
308 }
309
310
311 /*---------------------------------------------------------------------------*/
312 /*-- Device registration hook -----------------------------------------------*/
313 /*---------------------------------------------------------------------------*/
314 static void device_init(SIM_DESC sd) {
315 #ifdef DEVICE_INIT
316 extern void register_devices(SIM_DESC);
317 register_devices(sd);
318 #endif
319 }
320
321 /*---------------------------------------------------------------------------*/
322 /*-- GDB simulator interface ------------------------------------------------*/
323 /*---------------------------------------------------------------------------*/
324
325 SIM_DESC
326 sim_open (kind, cb, abfd, argv)
327 SIM_OPEN_KIND kind;
328 host_callback *cb;
329 struct _bfd *abfd;
330 char **argv;
331 {
332 SIM_DESC sd = sim_state_alloc (kind, cb);
333 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
334
335 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
336
337 /* FIXME: watchpoints code shouldn't need this */
338 STATE_WATCHPOINTS (sd)->pc = &(PC);
339 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
340 STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event;
341
342 /* Initialize the mechanism for doing insn profiling. */
343 CPU_INSN_NAME (cpu) = get_insn_name;
344 CPU_MAX_INSNS (cpu) = nr_itable_entries;
345
346 STATE = 0;
347
348 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
349 return 0;
350 sim_add_option_table (sd, NULL, mips_options);
351
352
353 /* getopt will print the error message so we just have to exit if this fails.
354 FIXME: Hmmm... in the case of gdb we need getopt to call
355 print_filtered. */
356 if (sim_parse_args (sd, argv) != SIM_RC_OK)
357 {
358 /* Uninstall the modules to avoid memory leaks,
359 file descriptor leaks, etc. */
360 sim_module_uninstall (sd);
361 return 0;
362 }
363
364 /* handle board-specific memory maps */
365 if (board == NULL)
366 {
367 /* Allocate core managed memory */
368
369
370 /* For compatibility with the old code - under this (at level one)
371 are the kernel spaces K0 & K1. Both of these map to a single
372 smaller sub region */
373 sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
374 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
375 K1BASE, K0SIZE,
376 MEM_SIZE, /* actual size */
377 K0BASE);
378
379 device_init(sd);
380 }
381 else if (board != NULL
382 && (strcmp(board, BOARD_BSP) == 0))
383 {
384 int i;
385
386 STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
387
388 /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
389 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
390 0x9FC00000,
391 4 * 1024 * 1024, /* 4 MB */
392 0xBFC00000);
393
394 /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
395 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
396 0x80000000,
397 4 * 1024 * 1024, /* 4 MB */
398 0xA0000000);
399
400 /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
401 for (i=0; i<8; i++) /* 32 MB total */
402 {
403 unsigned size = 4 * 1024 * 1024; /* 4 MB */
404 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
405 0x88000000 + (i * size),
406 size,
407 0xA8000000 + (i * size));
408 }
409 }
410 #if (WITH_HW)
411 else if (board != NULL
412 && (strcmp(board, BOARD_JMR3904) == 0 ||
413 strcmp(board, BOARD_JMR3904_PAL) == 0 ||
414 strcmp(board, BOARD_JMR3904_DEBUG) == 0))
415 {
416 /* match VIRTUAL memory layout of JMR-TX3904 board */
417 int i;
418
419 /* --- disable monitor unless forced on by user --- */
420
421 if (! firmware_option_p)
422 {
423 idt_monitor_base = 0;
424 pmon_monitor_base = 0;
425 lsipmon_monitor_base = 0;
426 }
427
428 /* --- environment --- */
429
430 STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
431
432 /* --- memory --- */
433
434 /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
435 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
436 0x9FC00000,
437 4 * 1024 * 1024, /* 4 MB */
438 0xBFC00000);
439
440 /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
441 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
442 0x80000000,
443 4 * 1024 * 1024, /* 4 MB */
444 0xA0000000);
445
446 /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
447 for (i=0; i<8; i++) /* 32 MB total */
448 {
449 unsigned size = 4 * 1024 * 1024; /* 4 MB */
450 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
451 0x88000000 + (i * size),
452 size,
453 0xA8000000 + (i * size));
454 }
455
456 /* Dummy memory regions for unsimulated devices - sorted by address */
457
458 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB1000000, 0x400); /* ISA I/O */
459 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB2100000, 0x004); /* ISA ctl */
460 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB2500000, 0x004); /* LED/switch */
461 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB2700000, 0x004); /* RTC */
462 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xB3C00000, 0x004); /* RTC */
463 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFF8000, 0x900); /* DRAMC */
464 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFF9000, 0x200); /* EBIF */
465 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFE000, 0x01c); /* EBIF */
466 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFF500, 0x300); /* PIO */
467
468
469 /* --- simulated devices --- */
470 sim_hw_parse (sd, "/tx3904irc@0xffffc000/reg 0xffffc000 0x20");
471 sim_hw_parse (sd, "/tx3904cpu");
472 sim_hw_parse (sd, "/tx3904tmr@0xfffff000/reg 0xfffff000 0x100");
473 sim_hw_parse (sd, "/tx3904tmr@0xfffff100/reg 0xfffff100 0x100");
474 sim_hw_parse (sd, "/tx3904tmr@0xfffff200/reg 0xfffff200 0x100");
475 sim_hw_parse (sd, "/tx3904sio@0xfffff300/reg 0xfffff300 0x100");
476 {
477 /* FIXME: poking at dv-sockser internals, use tcp backend if
478 --sockser_addr option was given.*/
479 extern char* sockser_addr;
480 if(sockser_addr == NULL)
481 sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend stdio");
482 else
483 sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend tcp");
484 }
485 sim_hw_parse (sd, "/tx3904sio@0xfffff400/reg 0xfffff400 0x100");
486 sim_hw_parse (sd, "/tx3904sio@0xfffff400/backend stdio");
487
488 /* -- device connections --- */
489 sim_hw_parse (sd, "/tx3904irc > ip level /tx3904cpu");
490 sim_hw_parse (sd, "/tx3904tmr@0xfffff000 > int tmr0 /tx3904irc");
491 sim_hw_parse (sd, "/tx3904tmr@0xfffff100 > int tmr1 /tx3904irc");
492 sim_hw_parse (sd, "/tx3904tmr@0xfffff200 > int tmr2 /tx3904irc");
493 sim_hw_parse (sd, "/tx3904sio@0xfffff300 > int sio0 /tx3904irc");
494 sim_hw_parse (sd, "/tx3904sio@0xfffff400 > int sio1 /tx3904irc");
495
496 /* add PAL timer & I/O module */
497 if(! strcmp(board, BOARD_JMR3904_PAL))
498 {
499 /* the device */
500 sim_hw_parse (sd, "/pal@0xffff0000");
501 sim_hw_parse (sd, "/pal@0xffff0000/reg 0xffff0000 64");
502
503 /* wire up interrupt ports to irc */
504 sim_hw_parse (sd, "/pal@0x31000000 > countdown tmr0 /tx3904irc");
505 sim_hw_parse (sd, "/pal@0x31000000 > timer tmr1 /tx3904irc");
506 sim_hw_parse (sd, "/pal@0x31000000 > int int0 /tx3904irc");
507 }
508
509 if(! strcmp(board, BOARD_JMR3904_DEBUG))
510 {
511 /* -- DEBUG: glue interrupt generators --- */
512 sim_hw_parse (sd, "/glue@0xffff0000/reg 0xffff0000 0x50");
513 sim_hw_parse (sd, "/glue@0xffff0000 > int0 int0 /tx3904irc");
514 sim_hw_parse (sd, "/glue@0xffff0000 > int1 int1 /tx3904irc");
515 sim_hw_parse (sd, "/glue@0xffff0000 > int2 int2 /tx3904irc");
516 sim_hw_parse (sd, "/glue@0xffff0000 > int3 int3 /tx3904irc");
517 sim_hw_parse (sd, "/glue@0xffff0000 > int4 int4 /tx3904irc");
518 sim_hw_parse (sd, "/glue@0xffff0000 > int5 int5 /tx3904irc");
519 sim_hw_parse (sd, "/glue@0xffff0000 > int6 int6 /tx3904irc");
520 sim_hw_parse (sd, "/glue@0xffff0000 > int7 int7 /tx3904irc");
521 sim_hw_parse (sd, "/glue@0xffff0000 > int8 dmac0 /tx3904irc");
522 sim_hw_parse (sd, "/glue@0xffff0000 > int9 dmac1 /tx3904irc");
523 sim_hw_parse (sd, "/glue@0xffff0000 > int10 dmac2 /tx3904irc");
524 sim_hw_parse (sd, "/glue@0xffff0000 > int11 dmac3 /tx3904irc");
525 sim_hw_parse (sd, "/glue@0xffff0000 > int12 sio0 /tx3904irc");
526 sim_hw_parse (sd, "/glue@0xffff0000 > int13 sio1 /tx3904irc");
527 sim_hw_parse (sd, "/glue@0xffff0000 > int14 tmr0 /tx3904irc");
528 sim_hw_parse (sd, "/glue@0xffff0000 > int15 tmr1 /tx3904irc");
529 sim_hw_parse (sd, "/glue@0xffff0000 > int16 tmr2 /tx3904irc");
530 sim_hw_parse (sd, "/glue@0xffff0000 > int17 nmi /tx3904cpu");
531 }
532
533 device_init(sd);
534 }
535 #endif
536
537
538 /* check for/establish the a reference program image */
539 if (sim_analyze_program (sd,
540 (STATE_PROG_ARGV (sd) != NULL
541 ? *STATE_PROG_ARGV (sd)
542 : NULL),
543 abfd) != SIM_RC_OK)
544 {
545 sim_module_uninstall (sd);
546 return 0;
547 }
548
549 /* Configure/verify the target byte order and other runtime
550 configuration options */
551 if (sim_config (sd) != SIM_RC_OK)
552 {
553 sim_module_uninstall (sd);
554 return 0;
555 }
556
557 if (sim_post_argv_init (sd) != SIM_RC_OK)
558 {
559 /* Uninstall the modules to avoid memory leaks,
560 file descriptor leaks, etc. */
561 sim_module_uninstall (sd);
562 return 0;
563 }
564
565 /* verify assumptions the simulator made about the host type system.
566 This macro does not return if there is a problem */
567 SIM_ASSERT (sizeof(int) == (4 * sizeof(char)));
568 SIM_ASSERT (sizeof(word64) == (8 * sizeof(char)));
569
570 /* This is NASTY, in that we are assuming the size of specific
571 registers: */
572 {
573 int rn;
574 for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++)
575 {
576 if (rn < 32)
577 cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
578 else if ((rn >= FGRIDX) && (rn < (FGRIDX + NR_FGR)))
579 cpu->register_widths[rn] = WITH_TARGET_FLOATING_POINT_BITSIZE;
580 else if ((rn >= 33) && (rn <= 37))
581 cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
582 else if ((rn == SRIDX)
583 || (rn == FCR0IDX)
584 || (rn == FCR31IDX)
585 || ((rn >= 72) && (rn <= 89)))
586 cpu->register_widths[rn] = 32;
587 else
588 cpu->register_widths[rn] = 0;
589 }
590
591
592 }
593
594 #if defined(TRACE)
595 if (STATE & simTRACE)
596 open_trace(sd);
597 #endif /* TRACE */
598
599 /*
600 sim_io_eprintf (sd, "idt@%x pmon@%x lsipmon@%x\n",
601 idt_monitor_base,
602 pmon_monitor_base,
603 lsipmon_monitor_base);
604 */
605
606 /* Write the monitor trap address handlers into the monitor (eeprom)
607 address space. This can only be done once the target endianness
608 has been determined. */
609 if (idt_monitor_base != 0)
610 {
611 unsigned loop;
612 unsigned idt_monitor_size = 1 << 11;
613
614 /* the default monitor region */
615 sim_do_commandf (sd, "memory region 0x%x,0x%x",
616 idt_monitor_base, idt_monitor_size);
617
618 /* Entry into the IDT monitor is via fixed address vectors, and
619 not using machine instructions. To avoid clashing with use of
620 the MIPS TRAP system, we place our own (simulator specific)
621 "undefined" instructions into the relevant vector slots. */
622 for (loop = 0; (loop < idt_monitor_size); loop += 4)
623 {
624 address_word vaddr = (idt_monitor_base + loop);
625 unsigned32 insn = (RSVD_INSTRUCTION |
626 (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK)
627 << RSVD_INSTRUCTION_ARG_SHIFT));
628 H2T (insn);
629 sim_write (sd, vaddr, (char *)&insn, sizeof (insn));
630 }
631 }
632
633 if ((pmon_monitor_base != 0) || (lsipmon_monitor_base != 0))
634 {
635 /* The PMON monitor uses the same address space, but rather than
636 branching into it the address of a routine is loaded. We can
637 cheat for the moment, and direct the PMON routine to IDT style
638 instructions within the monitor space. This relies on the IDT
639 monitor not using the locations from 0xBFC00500 onwards as its
640 entry points.*/
641 unsigned loop;
642 for (loop = 0; (loop < 24); loop++)
643 {
644 unsigned32 value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
645 switch (loop)
646 {
647 case 0: /* read */
648 value = 7;
649 break;
650 case 1: /* write */
651 value = 8;
652 break;
653 case 2: /* open */
654 value = 6;
655 break;
656 case 3: /* close */
657 value = 10;
658 break;
659 case 5: /* printf */
660 value = ((0x500 - 16) / 8); /* not an IDT reason code */
661 break;
662 case 8: /* cliexit */
663 value = 17;
664 break;
665 case 11: /* flush_cache */
666 value = 28;
667 break;
668 }
669
670 SIM_ASSERT (idt_monitor_base != 0);
671 value = ((unsigned int) idt_monitor_base + (value * 8));
672 H2T (value);
673
674 if (pmon_monitor_base != 0)
675 {
676 address_word vaddr = (pmon_monitor_base + (loop * 4));
677 sim_write (sd, vaddr, (char *)&value, sizeof (value));
678 }
679
680 if (lsipmon_monitor_base != 0)
681 {
682 address_word vaddr = (lsipmon_monitor_base + (loop * 4));
683 sim_write (sd, vaddr, (char *)&value, sizeof (value));
684 }
685 }
686
687 /* Write an abort sequence into the TRAP (common) exception vector
688 addresses. This is to catch code executing a TRAP (et.al.)
689 instruction without installing a trap handler. */
690 if ((idt_monitor_base != 0) ||
691 (pmon_monitor_base != 0) ||
692 (lsipmon_monitor_base != 0))
693 {
694 unsigned32 halt[2] = { 0x2404002f /* addiu r4, r0, 47 */,
695 HALT_INSTRUCTION /* BREAK */ };
696 H2T (halt[0]);
697 H2T (halt[1]);
698 sim_write (sd, 0x80000000, (char *) halt, sizeof (halt));
699 sim_write (sd, 0x80000180, (char *) halt, sizeof (halt));
700 sim_write (sd, 0x80000200, (char *) halt, sizeof (halt));
701 /* XXX: Write here unconditionally? */
702 sim_write (sd, 0xBFC00200, (char *) halt, sizeof (halt));
703 sim_write (sd, 0xBFC00380, (char *) halt, sizeof (halt));
704 sim_write (sd, 0xBFC00400, (char *) halt, sizeof (halt));
705 }
706 }
707
708
709
710 return sd;
711 }
712
713 #if defined(TRACE)
714 static void
715 open_trace(sd)
716 SIM_DESC sd;
717 {
718 tracefh = fopen(tracefile,"wb+");
719 if (tracefh == NULL)
720 {
721 sim_io_eprintf(sd,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile);
722 tracefh = stderr;
723 }
724 }
725 #endif /* TRACE */
726
727 /* Return name of an insn, used by insn profiling. */
728 static const char *
729 get_insn_name (sim_cpu *cpu, int i)
730 {
731 return itable[i].name;
732 }
733
734 void
735 sim_close (sd, quitting)
736 SIM_DESC sd;
737 int quitting;
738 {
739 #ifdef DEBUG
740 printf("DBG: sim_close: entered (quitting = %d)\n",quitting);
741 #endif
742
743
744 /* "quitting" is non-zero if we cannot hang on errors */
745
746 /* shut down modules */
747 sim_module_uninstall (sd);
748
749 /* Ensure that any resources allocated through the callback
750 mechanism are released: */
751 sim_io_shutdown (sd);
752
753 #if defined(TRACE)
754 if (tracefh != NULL && tracefh != stderr)
755 fclose(tracefh);
756 tracefh = NULL;
757 #endif /* TRACE */
758
759 /* FIXME - free SD */
760
761 return;
762 }
763
764
765 int
766 sim_write (sd,addr,buffer,size)
767 SIM_DESC sd;
768 SIM_ADDR addr;
769 unsigned char *buffer;
770 int size;
771 {
772 int index;
773 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
774
775 /* Return the number of bytes written, or zero if error. */
776 #ifdef DEBUG
777 sim_io_printf(sd,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr),size);
778 #endif
779
780 /* We use raw read and write routines, since we do not want to count
781 the GDB memory accesses in our statistics gathering. */
782
783 for (index = 0; index < size; index++)
784 {
785 address_word vaddr = (address_word)addr + index;
786 address_word paddr;
787 int cca;
788 if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isSTORE, &paddr, &cca, isRAW))
789 break;
790 if (sim_core_write_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
791 break;
792 }
793
794 return(index);
795 }
796
797 int
798 sim_read (sd,addr,buffer,size)
799 SIM_DESC sd;
800 SIM_ADDR addr;
801 unsigned char *buffer;
802 int size;
803 {
804 int index;
805 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
806
807 /* Return the number of bytes read, or zero if error. */
808 #ifdef DEBUG
809 sim_io_printf(sd,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr),size);
810 #endif /* DEBUG */
811
812 for (index = 0; (index < size); index++)
813 {
814 address_word vaddr = (address_word)addr + index;
815 address_word paddr;
816 int cca;
817 if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isLOAD, &paddr, &cca, isRAW))
818 break;
819 if (sim_core_read_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
820 break;
821 }
822
823 return(index);
824 }
825
826 int
827 sim_store_register (sd,rn,memory,length)
828 SIM_DESC sd;
829 int rn;
830 unsigned char *memory;
831 int length;
832 {
833 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
834 /* NOTE: gdb (the client) stores registers in target byte order
835 while the simulator uses host byte order */
836 #ifdef DEBUG
837 sim_io_printf(sd,"sim_store_register(%d,*memory=0x%s);\n",rn,pr_addr(*((SIM_ADDR *)memory)));
838 #endif /* DEBUG */
839
840 /* Unfortunately this suffers from the same problem as the register
841 numbering one. We need to know what the width of each logical
842 register number is for the architecture being simulated. */
843
844 if (cpu->register_widths[rn] == 0)
845 {
846 sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
847 return 0;
848 }
849
850
851
852 if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
853 {
854 cpu->fpr_state[rn - FGRIDX] = fmt_uninterpreted;
855 if (cpu->register_widths[rn] == 32)
856 {
857 if (length == 8)
858 {
859 cpu->fgr[rn - FGRIDX] =
860 (unsigned32) T2H_8 (*(unsigned64*)memory);
861 return 8;
862 }
863 else
864 {
865 cpu->fgr[rn - FGRIDX] = T2H_4 (*(unsigned32*)memory);
866 return 4;
867 }
868 }
869 else
870 {
871 cpu->fgr[rn - FGRIDX] = T2H_8 (*(unsigned64*)memory);
872 return 8;
873 }
874 }
875
876 if (cpu->register_widths[rn] == 32)
877 {
878 if (length == 8)
879 {
880 cpu->registers[rn] =
881 (unsigned32) T2H_8 (*(unsigned64*)memory);
882 return 8;
883 }
884 else
885 {
886 cpu->registers[rn] = T2H_4 (*(unsigned32*)memory);
887 return 4;
888 }
889 }
890 else
891 {
892 cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
893 return 8;
894 }
895
896 return 0;
897 }
898
899 int
900 sim_fetch_register (sd,rn,memory,length)
901 SIM_DESC sd;
902 int rn;
903 unsigned char *memory;
904 int length;
905 {
906 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
907 /* NOTE: gdb (the client) stores registers in target byte order
908 while the simulator uses host byte order */
909 #ifdef DEBUG
910 #if 0 /* FIXME: doesn't compile */
911 sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn]));
912 #endif
913 #endif /* DEBUG */
914
915 if (cpu->register_widths[rn] == 0)
916 {
917 sim_io_eprintf (sd, "Invalid register width for %d (register fetch ignored)\n",rn);
918 return 0;
919 }
920
921
922
923 /* Any floating point register */
924 if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
925 {
926 if (cpu->register_widths[rn] == 32)
927 {
928 if (length == 8)
929 {
930 *(unsigned64*)memory =
931 H2T_8 ((unsigned32) (cpu->fgr[rn - FGRIDX]));
932 return 8;
933 }
934 else
935 {
936 *(unsigned32*)memory = H2T_4 (cpu->fgr[rn - FGRIDX]);
937 return 4;
938 }
939 }
940 else
941 {
942 *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGRIDX]);
943 return 8;
944 }
945 }
946
947 if (cpu->register_widths[rn] == 32)
948 {
949 if (length == 8)
950 {
951 *(unsigned64*)memory =
952 H2T_8 ((unsigned32) (cpu->registers[rn]));
953 return 8;
954 }
955 else
956 {
957 *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn]));
958 return 4;
959 }
960 }
961 else
962 {
963 *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
964 return 8;
965 }
966
967 return 0;
968 }
969
970
971 SIM_RC
972 sim_create_inferior (sd, abfd, argv,env)
973 SIM_DESC sd;
974 struct _bfd *abfd;
975 char **argv;
976 char **env;
977 {
978
979 #ifdef DEBUG
980 #if 0 /* FIXME: doesn't compile */
981 printf("DBG: sim_create_inferior entered: start_address = 0x%s\n",
982 pr_addr(PC));
983 #endif
984 #endif /* DEBUG */
985
986 ColdReset(sd);
987
988 if (abfd != NULL)
989 {
990 /* override PC value set by ColdReset () */
991 int cpu_nr;
992 for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
993 {
994 sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
995 CIA_SET (cpu, (unsigned64) bfd_get_start_address (abfd));
996 }
997 }
998
999 #if 0 /* def DEBUG */
1000 if (argv || env)
1001 {
1002 /* We should really place the argv slot values into the argument
1003 registers, and onto the stack as required. However, this
1004 assumes that we have a stack defined, which is not
1005 necessarily true at the moment. */
1006 char **cptr;
1007 sim_io_printf(sd,"sim_create_inferior() : passed arguments ignored\n");
1008 for (cptr = argv; (cptr && *cptr); cptr++)
1009 printf("DBG: arg \"%s\"\n",*cptr);
1010 }
1011 #endif /* DEBUG */
1012
1013 return SIM_RC_OK;
1014 }
1015
1016 void
1017 sim_do_command (sd,cmd)
1018 SIM_DESC sd;
1019 char *cmd;
1020 {
1021 if (sim_args_command (sd, cmd) != SIM_RC_OK)
1022 sim_io_printf (sd, "Error: \"%s\" is not a valid MIPS simulator command.\n",
1023 cmd);
1024 }
1025
1026 /*---------------------------------------------------------------------------*/
1027 /*-- Private simulator support interface ------------------------------------*/
1028 /*---------------------------------------------------------------------------*/
1029
1030 /* Read a null terminated string from memory, return in a buffer */
1031 static char *
1032 fetch_str (SIM_DESC sd,
1033 address_word addr)
1034 {
1035 char *buf;
1036 int nr = 0;
1037 char null;
1038 while (sim_read (sd, addr + nr, &null, 1) == 1 && null != 0)
1039 nr++;
1040 buf = NZALLOC (char, nr + 1);
1041 sim_read (sd, addr, buf, nr);
1042 return buf;
1043 }
1044
1045
1046 /* Implements the "sim firmware" command:
1047 sim firmware NAME[@ADDRESS] --- emulate ROM monitor named NAME.
1048 NAME can be idt, pmon, or lsipmon. If omitted, ADDRESS
1049 defaults to the normal address for that monitor.
1050 sim firmware none --- don't emulate any ROM monitor. Useful
1051 if you need a clean address space. */
1052 static SIM_RC
1053 sim_firmware_command (SIM_DESC sd, char *arg)
1054 {
1055 int address_present = 0;
1056 SIM_ADDR address;
1057
1058 /* Signal occurrence of this option. */
1059 firmware_option_p = 1;
1060
1061 /* Parse out the address, if present. */
1062 {
1063 char *p = strchr (arg, '@');
1064 if (p)
1065 {
1066 char *q;
1067 address_present = 1;
1068 p ++; /* skip over @ */
1069
1070 address = strtoul (p, &q, 0);
1071 if (*q != '\0')
1072 {
1073 sim_io_printf (sd, "Invalid address given to the"
1074 "`sim firmware NAME@ADDRESS' command: %s\n",
1075 p);
1076 return SIM_RC_FAIL;
1077 }
1078 }
1079 else
1080 address_present = 0;
1081 }
1082
1083 if (! strncmp (arg, "idt", 3))
1084 {
1085 idt_monitor_base = address_present ? address : 0xBFC00000;
1086 pmon_monitor_base = 0;
1087 lsipmon_monitor_base = 0;
1088 }
1089 else if (! strncmp (arg, "pmon", 4))
1090 {
1091 /* pmon uses indirect calls. Hook into implied idt. */
1092 pmon_monitor_base = address_present ? address : 0xBFC00500;
1093 idt_monitor_base = pmon_monitor_base - 0x500;
1094 lsipmon_monitor_base = 0;
1095 }
1096 else if (! strncmp (arg, "lsipmon", 7))
1097 {
1098 /* lsipmon uses indirect calls. Hook into implied idt. */
1099 pmon_monitor_base = 0;
1100 lsipmon_monitor_base = address_present ? address : 0xBFC00200;
1101 idt_monitor_base = lsipmon_monitor_base - 0x200;
1102 }
1103 else if (! strncmp (arg, "none", 4))
1104 {
1105 if (address_present)
1106 {
1107 sim_io_printf (sd,
1108 "The `sim firmware none' command does "
1109 "not take an `ADDRESS' argument.\n");
1110 return SIM_RC_FAIL;
1111 }
1112 idt_monitor_base = 0;
1113 pmon_monitor_base = 0;
1114 lsipmon_monitor_base = 0;
1115 }
1116 else
1117 {
1118 sim_io_printf (sd, "\
1119 Unrecognized name given to the `sim firmware NAME' command: %s\n\
1120 Recognized firmware names are: `idt', `pmon', `lsipmon', and `none'.\n",
1121 arg);
1122 return SIM_RC_FAIL;
1123 }
1124
1125 return SIM_RC_OK;
1126 }
1127
1128
1129
1130 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
1131 int
1132 sim_monitor (SIM_DESC sd,
1133 sim_cpu *cpu,
1134 address_word cia,
1135 unsigned int reason)
1136 {
1137 #ifdef DEBUG
1138 printf("DBG: sim_monitor: entered (reason = %d)\n",reason);
1139 #endif /* DEBUG */
1140
1141 /* The IDT monitor actually allows two instructions per vector
1142 slot. However, the simulator currently causes a trap on each
1143 individual instruction. We cheat, and lose the bottom bit. */
1144 reason >>= 1;
1145
1146 /* The following callback functions are available, however the
1147 monitor we are simulating does not make use of them: get_errno,
1148 isatty, lseek, rename, system, time and unlink */
1149 switch (reason)
1150 {
1151
1152 case 6: /* int open(char *path,int flags) */
1153 {
1154 char *path = fetch_str (sd, A0);
1155 V0 = sim_io_open (sd, path, (int)A1);
1156 zfree (path);
1157 break;
1158 }
1159
1160 case 7: /* int read(int file,char *ptr,int len) */
1161 {
1162 int fd = A0;
1163 int nr = A2;
1164 char *buf = zalloc (nr);
1165 V0 = sim_io_read (sd, fd, buf, nr);
1166 sim_write (sd, A1, buf, nr);
1167 zfree (buf);
1168 }
1169 break;
1170
1171 case 8: /* int write(int file,char *ptr,int len) */
1172 {
1173 int fd = A0;
1174 int nr = A2;
1175 char *buf = zalloc (nr);
1176 sim_read (sd, A1, buf, nr);
1177 V0 = sim_io_write (sd, fd, buf, nr);
1178 zfree (buf);
1179 break;
1180 }
1181
1182 case 10: /* int close(int file) */
1183 {
1184 V0 = sim_io_close (sd, (int)A0);
1185 break;
1186 }
1187
1188 case 2: /* Densan monitor: char inbyte(int waitflag) */
1189 {
1190 if (A0 == 0) /* waitflag == NOWAIT */
1191 V0 = (unsigned_word)-1;
1192 }
1193 /* Drop through to case 11 */
1194
1195 case 11: /* char inbyte(void) */
1196 {
1197 char tmp;
1198 /* ensure that all output has gone... */
1199 sim_io_flush_stdout (sd);
1200 if (sim_io_read_stdin (sd, &tmp, sizeof(char)) != sizeof(char))
1201 {
1202 sim_io_error(sd,"Invalid return from character read");
1203 V0 = (unsigned_word)-1;
1204 }
1205 else
1206 V0 = (unsigned_word)tmp;
1207 break;
1208 }
1209
1210 case 3: /* Densan monitor: void co(char chr) */
1211 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
1212 {
1213 char tmp = (char)(A0 & 0xFF);
1214 sim_io_write_stdout (sd, &tmp, sizeof(char));
1215 break;
1216 }
1217
1218 case 17: /* void _exit() */
1219 {
1220 sim_io_eprintf (sd, "sim_monitor(17): _exit(int reason) to be coded\n");
1221 sim_engine_halt (SD, CPU, NULL, NULL_CIA, sim_exited,
1222 (unsigned int)(A0 & 0xFFFFFFFF));
1223 break;
1224 }
1225
1226 case 28 : /* PMON flush_cache */
1227 break;
1228
1229 case 55: /* void get_mem_info(unsigned int *ptr) */
1230 /* in: A0 = pointer to three word memory location */
1231 /* out: [A0 + 0] = size */
1232 /* [A0 + 4] = instruction cache size */
1233 /* [A0 + 8] = data cache size */
1234 {
1235 unsigned_4 value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
1236 unsigned_4 zero = 0;
1237 H2T (value);
1238 sim_write (sd, A0 + 0, (char *)&value, 4);
1239 sim_write (sd, A0 + 4, (char *)&zero, 4);
1240 sim_write (sd, A0 + 8, (char *)&zero, 4);
1241 /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
1242 break;
1243 }
1244
1245 case 158 : /* PMON printf */
1246 /* in: A0 = pointer to format string */
1247 /* A1 = optional argument 1 */
1248 /* A2 = optional argument 2 */
1249 /* A3 = optional argument 3 */
1250 /* out: void */
1251 /* The following is based on the PMON printf source */
1252 {
1253 address_word s = A0;
1254 char c;
1255 signed_word *ap = &A1; /* 1st argument */
1256 /* This isn't the quickest way, since we call the host print
1257 routine for every character almost. But it does avoid
1258 having to allocate and manage a temporary string buffer. */
1259 /* TODO: Include check that we only use three arguments (A1,
1260 A2 and A3) */
1261 while (sim_read (sd, s++, &c, 1) && c != '\0')
1262 {
1263 if (c == '%')
1264 {
1265 char tmp[40];
1266 enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST;
1267 int width = 0, trunc = 0, haddot = 0, longlong = 0;
1268 while (sim_read (sd, s++, &c, 1) && c != '\0')
1269 {
1270 if (strchr ("dobxXulscefg%", c))
1271 break;
1272 else if (c == '-')
1273 fmt = FMT_LJUST;
1274 else if (c == '0')
1275 fmt = FMT_RJUST0;
1276 else if (c == '~')
1277 fmt = FMT_CENTER;
1278 else if (c == '*')
1279 {
1280 if (haddot)
1281 trunc = (int)*ap++;
1282 else
1283 width = (int)*ap++;
1284 }
1285 else if (c >= '1' && c <= '9')
1286 {
1287 address_word t = s;
1288 unsigned int n;
1289 while (sim_read (sd, s++, &c, 1) == 1 && isdigit (c))
1290 tmp[s - t] = c;
1291 tmp[s - t] = '\0';
1292 n = (unsigned int)strtol(tmp,NULL,10);
1293 if (haddot)
1294 trunc = n;
1295 else
1296 width = n;
1297 s--;
1298 }
1299 else if (c == '.')
1300 haddot = 1;
1301 }
1302 switch (c)
1303 {
1304 case '%':
1305 sim_io_printf (sd, "%%");
1306 break;
1307 case 's':
1308 if ((int)*ap != 0)
1309 {
1310 address_word p = *ap++;
1311 char ch;
1312 while (sim_read (sd, p++, &ch, 1) == 1 && ch != '\0')
1313 sim_io_printf(sd, "%c", ch);
1314 }
1315 else
1316 sim_io_printf(sd,"(null)");
1317 break;
1318 case 'c':
1319 sim_io_printf (sd, "%c", (int)*ap++);
1320 break;
1321 default:
1322 if (c == 'l')
1323 {
1324 sim_read (sd, s++, &c, 1);
1325 if (c == 'l')
1326 {
1327 longlong = 1;
1328 sim_read (sd, s++, &c, 1);
1329 }
1330 }
1331 if (strchr ("dobxXu", c))
1332 {
1333 word64 lv = (word64) *ap++;
1334 if (c == 'b')
1335 sim_io_printf(sd,"<binary not supported>");
1336 else
1337 {
1338 sprintf (tmp, "%%%s%c", longlong ? "ll" : "", c);
1339 if (longlong)
1340 sim_io_printf(sd, tmp, lv);
1341 else
1342 sim_io_printf(sd, tmp, (int)lv);
1343 }
1344 }
1345 else if (strchr ("eEfgG", c))
1346 {
1347 double dbl = *(double*)(ap++);
1348 sprintf (tmp, "%%%d.%d%c", width, trunc, c);
1349 sim_io_printf (sd, tmp, dbl);
1350 trunc = 0;
1351 }
1352 }
1353 }
1354 else
1355 sim_io_printf(sd, "%c", c);
1356 }
1357 break;
1358 }
1359
1360 default:
1361 /* Unknown reason. */
1362 return 0;
1363 }
1364 return 1;
1365 }
1366
1367 /* Store a word into memory. */
1368
1369 static void
1370 store_word (SIM_DESC sd,
1371 sim_cpu *cpu,
1372 address_word cia,
1373 uword64 vaddr,
1374 signed_word val)
1375 {
1376 address_word paddr;
1377 int uncached;
1378
1379 if ((vaddr & 3) != 0)
1380 SignalExceptionAddressStore ();
1381 else
1382 {
1383 if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
1384 isTARGET, isREAL))
1385 {
1386 const uword64 mask = 7;
1387 uword64 memval;
1388 unsigned int byte;
1389
1390 paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
1391 byte = (vaddr & mask) ^ (BigEndianCPU << 2);
1392 memval = ((uword64) val) << (8 * byte);
1393 StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr,
1394 isREAL);
1395 }
1396 }
1397 }
1398
1399 /* Load a word from memory. */
1400
1401 static signed_word
1402 load_word (SIM_DESC sd,
1403 sim_cpu *cpu,
1404 address_word cia,
1405 uword64 vaddr)
1406 {
1407 if ((vaddr & 3) != 0)
1408 {
1409 SIM_CORE_SIGNAL (SD, cpu, cia, read_map, AccessLength_WORD+1, vaddr, read_transfer, sim_core_unaligned_signal);
1410 }
1411 else
1412 {
1413 address_word paddr;
1414 int uncached;
1415
1416 if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
1417 isTARGET, isREAL))
1418 {
1419 const uword64 mask = 0x7;
1420 const unsigned int reverse = ReverseEndian ? 1 : 0;
1421 const unsigned int bigend = BigEndianCPU ? 1 : 0;
1422 uword64 memval;
1423 unsigned int byte;
1424
1425 paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
1426 LoadMemory (&memval,NULL,uncached, AccessLength_WORD, paddr, vaddr,
1427 isDATA, isREAL);
1428 byte = (vaddr & mask) ^ (bigend << 2);
1429 return SIGNEXTEND (((memval >> (8 * byte)) & 0xffffffff), 32);
1430 }
1431 }
1432
1433 return 0;
1434 }
1435
1436 /* Simulate the mips16 entry and exit pseudo-instructions. These
1437 would normally be handled by the reserved instruction exception
1438 code, but for ease of simulation we just handle them directly. */
1439
1440 static void
1441 mips16_entry (SIM_DESC sd,
1442 sim_cpu *cpu,
1443 address_word cia,
1444 unsigned int insn)
1445 {
1446 int aregs, sregs, rreg;
1447
1448 #ifdef DEBUG
1449 printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn);
1450 #endif /* DEBUG */
1451
1452 aregs = (insn & 0x700) >> 8;
1453 sregs = (insn & 0x0c0) >> 6;
1454 rreg = (insn & 0x020) >> 5;
1455
1456 /* This should be checked by the caller. */
1457 if (sregs == 3)
1458 abort ();
1459
1460 if (aregs < 5)
1461 {
1462 int i;
1463 signed_word tsp;
1464
1465 /* This is the entry pseudo-instruction. */
1466
1467 for (i = 0; i < aregs; i++)
1468 store_word (SD, CPU, cia, (uword64) (SP + 4 * i), GPR[i + 4]);
1469
1470 tsp = SP;
1471 SP -= 32;
1472
1473 if (rreg)
1474 {
1475 tsp -= 4;
1476 store_word (SD, CPU, cia, (uword64) tsp, RA);
1477 }
1478
1479 for (i = 0; i < sregs; i++)
1480 {
1481 tsp -= 4;
1482 store_word (SD, CPU, cia, (uword64) tsp, GPR[16 + i]);
1483 }
1484 }
1485 else
1486 {
1487 int i;
1488 signed_word tsp;
1489
1490 /* This is the exit pseudo-instruction. */
1491
1492 tsp = SP + 32;
1493
1494 if (rreg)
1495 {
1496 tsp -= 4;
1497 RA = load_word (SD, CPU, cia, (uword64) tsp);
1498 }
1499
1500 for (i = 0; i < sregs; i++)
1501 {
1502 tsp -= 4;
1503 GPR[i + 16] = load_word (SD, CPU, cia, (uword64) tsp);
1504 }
1505
1506 SP += 32;
1507
1508 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
1509 {
1510 if (aregs == 5)
1511 {
1512 FGR[0] = WORD64LO (GPR[4]);
1513 FPR_STATE[0] = fmt_uninterpreted;
1514 }
1515 else if (aregs == 6)
1516 {
1517 FGR[0] = WORD64LO (GPR[5]);
1518 FGR[1] = WORD64LO (GPR[4]);
1519 FPR_STATE[0] = fmt_uninterpreted;
1520 FPR_STATE[1] = fmt_uninterpreted;
1521 }
1522 }
1523
1524 PC = RA;
1525 }
1526
1527 }
1528
1529 /*-- trace support ----------------------------------------------------------*/
1530
1531 /* The TRACE support is provided (if required) in the memory accessing
1532 routines. Since we are also providing the architecture specific
1533 features, the architecture simulation code can also deal with
1534 notifying the TRACE world of cache flushes, etc. Similarly we do
1535 not need to provide profiling support in the simulator engine,
1536 since we can sample in the instruction fetch control loop. By
1537 defining the TRACE manifest, we add tracing as a run-time
1538 option. */
1539
1540 #if defined(TRACE)
1541 /* Tracing by default produces "din" format (as required by
1542 dineroIII). Each line of such a trace file *MUST* have a din label
1543 and address field. The rest of the line is ignored, so comments can
1544 be included if desired. The first field is the label which must be
1545 one of the following values:
1546
1547 0 read data
1548 1 write data
1549 2 instruction fetch
1550 3 escape record (treated as unknown access type)
1551 4 escape record (causes cache flush)
1552
1553 The address field is a 32bit (lower-case) hexadecimal address
1554 value. The address should *NOT* be preceded by "0x".
1555
1556 The size of the memory transfer is not important when dealing with
1557 cache lines (as long as no more than a cache line can be
1558 transferred in a single operation :-), however more information
1559 could be given following the dineroIII requirement to allow more
1560 complete memory and cache simulators to provide better
1561 results. i.e. the University of Pisa has a cache simulator that can
1562 also take bus size and speed as (variable) inputs to calculate
1563 complete system performance (a much more useful ability when trying
1564 to construct an end product, rather than a processor). They
1565 currently have an ARM version of their tool called ChARM. */
1566
1567
1568 void
1569 dotrace (SIM_DESC sd,
1570 sim_cpu *cpu,
1571 FILE *tracefh,
1572 int type,
1573 SIM_ADDR address,
1574 int width,
1575 char *comment,...)
1576 {
1577 if (STATE & simTRACE) {
1578 va_list ap;
1579 fprintf(tracefh,"%d %s ; width %d ; ",
1580 type,
1581 pr_addr(address),
1582 width);
1583 va_start(ap,comment);
1584 vfprintf(tracefh,comment,ap);
1585 va_end(ap);
1586 fprintf(tracefh,"\n");
1587 }
1588 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1589 we may be generating 64bit ones, we should put the hi-32bits of the
1590 address into the comment field. */
1591
1592 /* TODO: Provide a buffer for the trace lines. We can then avoid
1593 performing writes until the buffer is filled, or the file is
1594 being closed. */
1595
1596 /* NOTE: We could consider adding a comment field to the "din" file
1597 produced using type 3 markers (unknown access). This would then
1598 allow information about the program that the "din" is for, and
1599 the MIPs world that was being simulated, to be placed into the
1600 trace file. */
1601
1602 return;
1603 }
1604 #endif /* TRACE */
1605
1606 /*---------------------------------------------------------------------------*/
1607 /*-- simulator engine -------------------------------------------------------*/
1608 /*---------------------------------------------------------------------------*/
1609
1610 static void
1611 ColdReset (SIM_DESC sd)
1612 {
1613 int cpu_nr;
1614 for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
1615 {
1616 sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
1617 /* RESET: Fixed PC address: */
1618 PC = (unsigned_word) UNSIGNED64 (0xFFFFFFFFBFC00000);
1619 /* The reset vector address is in the unmapped, uncached memory space. */
1620
1621 SR &= ~(status_SR | status_TS | status_RP);
1622 SR |= (status_ERL | status_BEV);
1623
1624 /* Cheat and allow access to the complete register set immediately */
1625 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT
1626 && WITH_TARGET_WORD_BITSIZE == 64)
1627 SR |= status_FR; /* 64bit registers */
1628
1629 /* Ensure that any instructions with pending register updates are
1630 cleared: */
1631 PENDING_INVALIDATE();
1632
1633 /* Initialise the FPU registers to the unknown state */
1634 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
1635 {
1636 int rn;
1637 for (rn = 0; (rn < 32); rn++)
1638 FPR_STATE[rn] = fmt_uninterpreted;
1639 }
1640
1641 }
1642 }
1643
1644
1645
1646
1647 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1648 /* Signal an exception condition. This will result in an exception
1649 that aborts the instruction. The instruction operation pseudocode
1650 will never see a return from this function call. */
1651
1652 void
1653 signal_exception (SIM_DESC sd,
1654 sim_cpu *cpu,
1655 address_word cia,
1656 int exception,...)
1657 {
1658 /* int vector; */
1659
1660 #ifdef DEBUG
1661 sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia));
1662 #endif /* DEBUG */
1663
1664 /* Ensure that any active atomic read/modify/write operation will fail: */
1665 LLBIT = 0;
1666
1667 /* Save registers before interrupt dispatching */
1668 #ifdef SIM_CPU_EXCEPTION_TRIGGER
1669 SIM_CPU_EXCEPTION_TRIGGER(sd, cpu, cia);
1670 #endif
1671
1672 switch (exception) {
1673
1674 case DebugBreakPoint :
1675 if (! (Debug & Debug_DM))
1676 {
1677 if (INDELAYSLOT())
1678 {
1679 CANCELDELAYSLOT();
1680
1681 Debug |= Debug_DBD; /* signaled from within in delay slot */
1682 DEPC = cia - 4; /* reference the branch instruction */
1683 }
1684 else
1685 {
1686 Debug &= ~Debug_DBD; /* not signaled from within a delay slot */
1687 DEPC = cia;
1688 }
1689
1690 Debug |= Debug_DM; /* in debugging mode */
1691 Debug |= Debug_DBp; /* raising a DBp exception */
1692 PC = 0xBFC00200;
1693 sim_engine_restart (SD, CPU, NULL, NULL_CIA);
1694 }
1695 break;
1696
1697 case ReservedInstruction :
1698 {
1699 va_list ap;
1700 unsigned int instruction;
1701 va_start(ap,exception);
1702 instruction = va_arg(ap,unsigned int);
1703 va_end(ap);
1704 /* Provide simple monitor support using ReservedInstruction
1705 exceptions. The following code simulates the fixed vector
1706 entry points into the IDT monitor by causing a simulator
1707 trap, performing the monitor operation, and returning to
1708 the address held in the $ra register (standard PCS return
1709 address). This means we only need to pre-load the vector
1710 space with suitable instruction values. For systems were
1711 actual trap instructions are used, we would not need to
1712 perform this magic. */
1713 if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION)
1714 {
1715 int reason = (instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK;
1716 if (!sim_monitor (SD, CPU, cia, reason))
1717 sim_io_error (sd, "sim_monitor: unhandled reason = %d, pc = 0x%s\n", reason, pr_addr (cia));
1718
1719 /* NOTE: This assumes that a branch-and-link style
1720 instruction was used to enter the vector (which is the
1721 case with the current IDT monitor). */
1722 sim_engine_restart (SD, CPU, NULL, RA);
1723 }
1724 /* Look for the mips16 entry and exit instructions, and
1725 simulate a handler for them. */
1726 else if ((cia & 1) != 0
1727 && (instruction & 0xf81f) == 0xe809
1728 && (instruction & 0x0c0) != 0x0c0)
1729 {
1730 mips16_entry (SD, CPU, cia, instruction);
1731 sim_engine_restart (sd, NULL, NULL, NULL_CIA);
1732 }
1733 /* else fall through to normal exception processing */
1734 sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia));
1735 }
1736
1737 default:
1738 /* Store exception code into current exception id variable (used
1739 by exit code): */
1740
1741 /* TODO: If not simulating exceptions then stop the simulator
1742 execution. At the moment we always stop the simulation. */
1743
1744 #ifdef SUBTARGET_R3900
1745 /* update interrupt-related registers */
1746
1747 /* insert exception code in bits 6:2 */
1748 CAUSE = LSMASKED32(CAUSE, 31, 7) | LSINSERTED32(exception, 6, 2);
1749 /* shift IE/KU history bits left */
1750 SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 3, 0), 5, 2);
1751
1752 if (STATE & simDELAYSLOT)
1753 {
1754 STATE &= ~simDELAYSLOT;
1755 CAUSE |= cause_BD;
1756 EPC = (cia - 4); /* reference the branch instruction */
1757 }
1758 else
1759 EPC = cia;
1760
1761 if (SR & status_BEV)
1762 PC = (signed)0xBFC00000 + 0x180;
1763 else
1764 PC = (signed)0x80000000 + 0x080;
1765 #else
1766 /* See figure 5-17 for an outline of the code below */
1767 if (! (SR & status_EXL))
1768 {
1769 CAUSE = (exception << 2);
1770 if (STATE & simDELAYSLOT)
1771 {
1772 STATE &= ~simDELAYSLOT;
1773 CAUSE |= cause_BD;
1774 EPC = (cia - 4); /* reference the branch instruction */
1775 }
1776 else
1777 EPC = cia;
1778 /* FIXME: TLB et.al. */
1779 /* vector = 0x180; */
1780 }
1781 else
1782 {
1783 CAUSE = (exception << 2);
1784 /* vector = 0x180; */
1785 }
1786 SR |= status_EXL;
1787 /* Store exception code into current exception id variable (used
1788 by exit code): */
1789
1790 if (SR & status_BEV)
1791 PC = (signed)0xBFC00200 + 0x180;
1792 else
1793 PC = (signed)0x80000000 + 0x180;
1794 #endif
1795
1796 switch ((CAUSE >> 2) & 0x1F)
1797 {
1798 case Interrupt:
1799 /* Interrupts arrive during event processing, no need to
1800 restart */
1801 return;
1802
1803 case NMIReset:
1804 /* Ditto */
1805 #ifdef SUBTARGET_3900
1806 /* Exception vector: BEV=0 BFC00000 / BEF=1 BFC00000 */
1807 PC = (signed)0xBFC00000;
1808 #endif SUBTARGET_3900
1809 return;
1810
1811 case TLBModification:
1812 case TLBLoad:
1813 case TLBStore:
1814 case AddressLoad:
1815 case AddressStore:
1816 case InstructionFetch:
1817 case DataReference:
1818 /* The following is so that the simulator will continue from the
1819 exception handler address. */
1820 sim_engine_halt (SD, CPU, NULL, PC,
1821 sim_stopped, SIM_SIGBUS);
1822
1823 case ReservedInstruction:
1824 case CoProcessorUnusable:
1825 PC = EPC;
1826 sim_engine_halt (SD, CPU, NULL, PC,
1827 sim_stopped, SIM_SIGILL);
1828
1829 case IntegerOverflow:
1830 case FPE:
1831 sim_engine_halt (SD, CPU, NULL, PC,
1832 sim_stopped, SIM_SIGFPE);
1833
1834 case BreakPoint:
1835 sim_engine_halt (SD, CPU, NULL, PC, sim_stopped, SIM_SIGTRAP);
1836 break;
1837
1838 case SystemCall:
1839 case Trap:
1840 sim_engine_restart (SD, CPU, NULL, PC);
1841 break;
1842
1843 case Watch:
1844 PC = EPC;
1845 sim_engine_halt (SD, CPU, NULL, PC,
1846 sim_stopped, SIM_SIGTRAP);
1847
1848 default : /* Unknown internal exception */
1849 PC = EPC;
1850 sim_engine_halt (SD, CPU, NULL, PC,
1851 sim_stopped, SIM_SIGABRT);
1852
1853 }
1854
1855 case SimulatorFault:
1856 {
1857 va_list ap;
1858 char *msg;
1859 va_start(ap,exception);
1860 msg = va_arg(ap,char *);
1861 va_end(ap);
1862 sim_engine_abort (SD, CPU, NULL_CIA,
1863 "FATAL: Simulator error \"%s\"\n",msg);
1864 }
1865 }
1866
1867 return;
1868 }
1869
1870
1871
1872 #if defined(WARN_RESULT)
1873 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1874 /* This function indicates that the result of the operation is
1875 undefined. However, this should not affect the instruction
1876 stream. All that is meant to happen is that the destination
1877 register is set to an undefined result. To keep the simulator
1878 simple, we just don't bother updating the destination register, so
1879 the overall result will be undefined. If desired we can stop the
1880 simulator by raising a pseudo-exception. */
1881 #define UndefinedResult() undefined_result (sd,cia)
1882 static void
1883 undefined_result(sd,cia)
1884 SIM_DESC sd;
1885 address_word cia;
1886 {
1887 sim_io_eprintf(sd,"UndefinedResult: PC = 0x%s\n",pr_addr(cia));
1888 #if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
1889 state |= simSTOP;
1890 #endif
1891 return;
1892 }
1893 #endif /* WARN_RESULT */
1894
1895 /*-- FPU support routines ---------------------------------------------------*/
1896
1897 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
1898 formats conform to ANSI/IEEE Std 754-1985. */
1899 /* SINGLE precision floating:
1900 * seeeeeeeefffffffffffffffffffffff
1901 * s = 1bit = sign
1902 * e = 8bits = exponent
1903 * f = 23bits = fraction
1904 */
1905 /* SINGLE precision fixed:
1906 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
1907 * s = 1bit = sign
1908 * i = 31bits = integer
1909 */
1910 /* DOUBLE precision floating:
1911 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
1912 * s = 1bit = sign
1913 * e = 11bits = exponent
1914 * f = 52bits = fraction
1915 */
1916 /* DOUBLE precision fixed:
1917 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
1918 * s = 1bit = sign
1919 * i = 63bits = integer
1920 */
1921
1922 /* Extract sign-bit: */
1923 #define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
1924 #define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
1925 /* Extract biased exponent: */
1926 #define FP_S_be(v) (((v) >> 23) & 0xFF)
1927 #define FP_D_be(v) (((v) >> 52) & 0x7FF)
1928 /* Extract unbiased Exponent: */
1929 #define FP_S_e(v) (FP_S_be(v) - 0x7F)
1930 #define FP_D_e(v) (FP_D_be(v) - 0x3FF)
1931 /* Extract complete fraction field: */
1932 #define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
1933 #define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
1934 /* Extract numbered fraction bit: */
1935 #define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
1936 #define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
1937
1938 /* Explicit QNaN values used when value required: */
1939 #define FPQNaN_SINGLE (0x7FBFFFFF)
1940 #define FPQNaN_WORD (0x7FFFFFFF)
1941 #define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
1942 #define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
1943
1944 /* Explicit Infinity values used when required: */
1945 #define FPINF_SINGLE (0x7F800000)
1946 #define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
1947
1948 #define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
1949 #define DOFMT(v) (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : (((v) == fmt_uninterpreted_32) ? "<uninterpreted_32>" : (((v) == fmt_uninterpreted_64) ? "<uninterpreted_64>" : "<format error>"))))))))
1950
1951 uword64
1952 value_fpr (SIM_DESC sd,
1953 sim_cpu *cpu,
1954 address_word cia,
1955 int fpr,
1956 FP_formats fmt)
1957 {
1958 uword64 value = 0;
1959 int err = 0;
1960
1961 /* Treat unused register values, as fixed-point 64bit values: */
1962 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
1963 #if 1
1964 /* If request to read data as "uninterpreted", then use the current
1965 encoding: */
1966 fmt = FPR_STATE[fpr];
1967 #else
1968 fmt = fmt_long;
1969 #endif
1970
1971 /* For values not yet accessed, set to the desired format: */
1972 if (FPR_STATE[fpr] == fmt_uninterpreted) {
1973 FPR_STATE[fpr] = fmt;
1974 #ifdef DEBUG
1975 printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
1976 #endif /* DEBUG */
1977 }
1978 if (fmt != FPR_STATE[fpr]) {
1979 sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(cia));
1980 FPR_STATE[fpr] = fmt_unknown;
1981 }
1982
1983 if (FPR_STATE[fpr] == fmt_unknown) {
1984 /* Set QNaN value: */
1985 switch (fmt) {
1986 case fmt_single:
1987 value = FPQNaN_SINGLE;
1988 break;
1989
1990 case fmt_double:
1991 value = FPQNaN_DOUBLE;
1992 break;
1993
1994 case fmt_word:
1995 value = FPQNaN_WORD;
1996 break;
1997
1998 case fmt_long:
1999 value = FPQNaN_LONG;
2000 break;
2001
2002 default:
2003 err = -1;
2004 break;
2005 }
2006 } else if (SizeFGR() == 64) {
2007 switch (fmt) {
2008 case fmt_single:
2009 case fmt_word:
2010 value = (FGR[fpr] & 0xFFFFFFFF);
2011 break;
2012
2013 case fmt_uninterpreted:
2014 case fmt_double:
2015 case fmt_long:
2016 value = FGR[fpr];
2017 break;
2018
2019 default :
2020 err = -1;
2021 break;
2022 }
2023 } else {
2024 switch (fmt) {
2025 case fmt_single:
2026 case fmt_word:
2027 value = (FGR[fpr] & 0xFFFFFFFF);
2028 break;
2029
2030 case fmt_uninterpreted:
2031 case fmt_double:
2032 case fmt_long:
2033 if ((fpr & 1) == 0) { /* even registers only */
2034 #ifdef DEBUG
2035 printf("DBG: ValueFPR: FGR[%d] = %s, FGR[%d] = %s\n",
2036 fpr+1, pr_uword64( (uword64) FGR[fpr+1] ),
2037 fpr, pr_uword64( (uword64) FGR[fpr] ));
2038 #endif
2039 value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
2040 } else {
2041 SignalException(ReservedInstruction,0);
2042 }
2043 break;
2044
2045 default :
2046 err = -1;
2047 break;
2048 }
2049 }
2050
2051 if (err)
2052 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
2053
2054 #ifdef DEBUG
2055 printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR());
2056 #endif /* DEBUG */
2057
2058 return(value);
2059 }
2060
2061 void
2062 store_fpr (SIM_DESC sd,
2063 sim_cpu *cpu,
2064 address_word cia,
2065 int fpr,
2066 FP_formats fmt,
2067 uword64 value)
2068 {
2069 int err = 0;
2070
2071 #ifdef DEBUG
2072 printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d,\n",fpr,DOFMT(fmt),pr_uword64(value),pr_addr(cia),SizeFGR());
2073 #endif /* DEBUG */
2074
2075 if (SizeFGR() == 64) {
2076 switch (fmt) {
2077 case fmt_uninterpreted_32:
2078 fmt = fmt_uninterpreted;
2079 case fmt_single :
2080 case fmt_word :
2081 if (STATE_VERBOSE_P(SD))
2082 sim_io_eprintf (SD, "Warning: PC 0x%s: interp.c store_fpr DEADCODE\n",
2083 pr_addr(cia));
2084 FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
2085 FPR_STATE[fpr] = fmt;
2086 break;
2087
2088 case fmt_uninterpreted_64:
2089 fmt = fmt_uninterpreted;
2090 case fmt_uninterpreted:
2091 case fmt_double :
2092 case fmt_long :
2093 FGR[fpr] = value;
2094 FPR_STATE[fpr] = fmt;
2095 break;
2096
2097 default :
2098 FPR_STATE[fpr] = fmt_unknown;
2099 err = -1;
2100 break;
2101 }
2102 } else {
2103 switch (fmt) {
2104 case fmt_uninterpreted_32:
2105 fmt = fmt_uninterpreted;
2106 case fmt_single :
2107 case fmt_word :
2108 FGR[fpr] = (value & 0xFFFFFFFF);
2109 FPR_STATE[fpr] = fmt;
2110 break;
2111
2112 case fmt_uninterpreted_64:
2113 fmt = fmt_uninterpreted;
2114 case fmt_uninterpreted:
2115 case fmt_double :
2116 case fmt_long :
2117 if ((fpr & 1) == 0) { /* even register number only */
2118 FGR[fpr+1] = (value >> 32);
2119 FGR[fpr] = (value & 0xFFFFFFFF);
2120 FPR_STATE[fpr + 1] = fmt;
2121 FPR_STATE[fpr] = fmt;
2122 } else {
2123 FPR_STATE[fpr] = fmt_unknown;
2124 FPR_STATE[fpr + 1] = fmt_unknown;
2125 SignalException(ReservedInstruction,0);
2126 }
2127 break;
2128
2129 default :
2130 FPR_STATE[fpr] = fmt_unknown;
2131 err = -1;
2132 break;
2133 }
2134 }
2135 #if defined(WARN_RESULT)
2136 else
2137 UndefinedResult();
2138 #endif /* WARN_RESULT */
2139
2140 if (err)
2141 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
2142
2143 #ifdef DEBUG
2144 printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_uword64(FGR[fpr]),DOFMT(fmt));
2145 #endif /* DEBUG */
2146
2147 return;
2148 }
2149
2150 int
2151 NaN(op,fmt)
2152 uword64 op;
2153 FP_formats fmt;
2154 {
2155 int boolean = 0;
2156 switch (fmt) {
2157 case fmt_single:
2158 case fmt_word:
2159 {
2160 sim_fpu wop;
2161 sim_fpu_32to (&wop, op);
2162 boolean = sim_fpu_is_nan (&wop);
2163 break;
2164 }
2165 case fmt_double:
2166 case fmt_long:
2167 {
2168 sim_fpu wop;
2169 sim_fpu_64to (&wop, op);
2170 boolean = sim_fpu_is_nan (&wop);
2171 break;
2172 }
2173 default:
2174 fprintf (stderr, "Bad switch\n");
2175 abort ();
2176 }
2177
2178 #ifdef DEBUG
2179 printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
2180 #endif /* DEBUG */
2181
2182 return(boolean);
2183 }
2184
2185 int
2186 Infinity(op,fmt)
2187 uword64 op;
2188 FP_formats fmt;
2189 {
2190 int boolean = 0;
2191
2192 #ifdef DEBUG
2193 printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op));
2194 #endif /* DEBUG */
2195
2196 switch (fmt) {
2197 case fmt_single:
2198 {
2199 sim_fpu wop;
2200 sim_fpu_32to (&wop, op);
2201 boolean = sim_fpu_is_infinity (&wop);
2202 break;
2203 }
2204 case fmt_double:
2205 {
2206 sim_fpu wop;
2207 sim_fpu_64to (&wop, op);
2208 boolean = sim_fpu_is_infinity (&wop);
2209 break;
2210 }
2211 default:
2212 printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt));
2213 break;
2214 }
2215
2216 #ifdef DEBUG
2217 printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
2218 #endif /* DEBUG */
2219
2220 return(boolean);
2221 }
2222
2223 int
2224 Less(op1,op2,fmt)
2225 uword64 op1;
2226 uword64 op2;
2227 FP_formats fmt;
2228 {
2229 int boolean = 0;
2230
2231 /* Argument checking already performed by the FPCOMPARE code */
2232
2233 #ifdef DEBUG
2234 printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2235 #endif /* DEBUG */
2236
2237 /* The format type should already have been checked: */
2238 switch (fmt) {
2239 case fmt_single:
2240 {
2241 sim_fpu wop1;
2242 sim_fpu wop2;
2243 sim_fpu_32to (&wop1, op1);
2244 sim_fpu_32to (&wop2, op2);
2245 boolean = sim_fpu_is_lt (&wop1, &wop2);
2246 break;
2247 }
2248 case fmt_double:
2249 {
2250 sim_fpu wop1;
2251 sim_fpu wop2;
2252 sim_fpu_64to (&wop1, op1);
2253 sim_fpu_64to (&wop2, op2);
2254 boolean = sim_fpu_is_lt (&wop1, &wop2);
2255 break;
2256 }
2257 default:
2258 fprintf (stderr, "Bad switch\n");
2259 abort ();
2260 }
2261
2262 #ifdef DEBUG
2263 printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt));
2264 #endif /* DEBUG */
2265
2266 return(boolean);
2267 }
2268
2269 int
2270 Equal(op1,op2,fmt)
2271 uword64 op1;
2272 uword64 op2;
2273 FP_formats fmt;
2274 {
2275 int boolean = 0;
2276
2277 /* Argument checking already performed by the FPCOMPARE code */
2278
2279 #ifdef DEBUG
2280 printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2281 #endif /* DEBUG */
2282
2283 /* The format type should already have been checked: */
2284 switch (fmt) {
2285 case fmt_single:
2286 {
2287 sim_fpu wop1;
2288 sim_fpu wop2;
2289 sim_fpu_32to (&wop1, op1);
2290 sim_fpu_32to (&wop2, op2);
2291 boolean = sim_fpu_is_eq (&wop1, &wop2);
2292 break;
2293 }
2294 case fmt_double:
2295 {
2296 sim_fpu wop1;
2297 sim_fpu wop2;
2298 sim_fpu_64to (&wop1, op1);
2299 sim_fpu_64to (&wop2, op2);
2300 boolean = sim_fpu_is_eq (&wop1, &wop2);
2301 break;
2302 }
2303 default:
2304 fprintf (stderr, "Bad switch\n");
2305 abort ();
2306 }
2307
2308 #ifdef DEBUG
2309 printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt));
2310 #endif /* DEBUG */
2311
2312 return(boolean);
2313 }
2314
2315 uword64
2316 AbsoluteValue(op,fmt)
2317 uword64 op;
2318 FP_formats fmt;
2319 {
2320 uword64 result = 0;
2321
2322 #ifdef DEBUG
2323 printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
2324 #endif /* DEBUG */
2325
2326 /* The format type should already have been checked: */
2327 switch (fmt) {
2328 case fmt_single:
2329 {
2330 sim_fpu wop;
2331 unsigned32 ans;
2332 sim_fpu_32to (&wop, op);
2333 sim_fpu_abs (&wop, &wop);
2334 sim_fpu_to32 (&ans, &wop);
2335 result = ans;
2336 break;
2337 }
2338 case fmt_double:
2339 {
2340 sim_fpu wop;
2341 unsigned64 ans;
2342 sim_fpu_64to (&wop, op);
2343 sim_fpu_abs (&wop, &wop);
2344 sim_fpu_to64 (&ans, &wop);
2345 result = ans;
2346 break;
2347 }
2348 default:
2349 fprintf (stderr, "Bad switch\n");
2350 abort ();
2351 }
2352
2353 return(result);
2354 }
2355
2356 uword64
2357 Negate(op,fmt)
2358 uword64 op;
2359 FP_formats fmt;
2360 {
2361 uword64 result = 0;
2362
2363 #ifdef DEBUG
2364 printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
2365 #endif /* DEBUG */
2366
2367 /* The format type should already have been checked: */
2368 switch (fmt) {
2369 case fmt_single:
2370 {
2371 sim_fpu wop;
2372 unsigned32 ans;
2373 sim_fpu_32to (&wop, op);
2374 sim_fpu_neg (&wop, &wop);
2375 sim_fpu_to32 (&ans, &wop);
2376 result = ans;
2377 break;
2378 }
2379 case fmt_double:
2380 {
2381 sim_fpu wop;
2382 unsigned64 ans;
2383 sim_fpu_64to (&wop, op);
2384 sim_fpu_neg (&wop, &wop);
2385 sim_fpu_to64 (&ans, &wop);
2386 result = ans;
2387 break;
2388 }
2389 default:
2390 fprintf (stderr, "Bad switch\n");
2391 abort ();
2392 }
2393
2394 return(result);
2395 }
2396
2397 uword64
2398 Add(op1,op2,fmt)
2399 uword64 op1;
2400 uword64 op2;
2401 FP_formats fmt;
2402 {
2403 uword64 result = 0;
2404
2405 #ifdef DEBUG
2406 printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2407 #endif /* DEBUG */
2408
2409 /* The registers must specify FPRs valid for operands of type
2410 "fmt". If they are not valid, the result is undefined. */
2411
2412 /* The format type should already have been checked: */
2413 switch (fmt) {
2414 case fmt_single:
2415 {
2416 sim_fpu wop1;
2417 sim_fpu wop2;
2418 sim_fpu ans;
2419 unsigned32 res;
2420 sim_fpu_32to (&wop1, op1);
2421 sim_fpu_32to (&wop2, op2);
2422 sim_fpu_add (&ans, &wop1, &wop2);
2423 sim_fpu_to32 (&res, &ans);
2424 result = res;
2425 break;
2426 }
2427 case fmt_double:
2428 {
2429 sim_fpu wop1;
2430 sim_fpu wop2;
2431 sim_fpu ans;
2432 unsigned64 res;
2433 sim_fpu_64to (&wop1, op1);
2434 sim_fpu_64to (&wop2, op2);
2435 sim_fpu_add (&ans, &wop1, &wop2);
2436 sim_fpu_to64 (&res, &ans);
2437 result = res;
2438 break;
2439 }
2440 default:
2441 fprintf (stderr, "Bad switch\n");
2442 abort ();
2443 }
2444
2445 #ifdef DEBUG
2446 printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2447 #endif /* DEBUG */
2448
2449 return(result);
2450 }
2451
2452 uword64
2453 Sub(op1,op2,fmt)
2454 uword64 op1;
2455 uword64 op2;
2456 FP_formats fmt;
2457 {
2458 uword64 result = 0;
2459
2460 #ifdef DEBUG
2461 printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2462 #endif /* DEBUG */
2463
2464 /* The registers must specify FPRs valid for operands of type
2465 "fmt". If they are not valid, the result is undefined. */
2466
2467 /* The format type should already have been checked: */
2468 switch (fmt) {
2469 case fmt_single:
2470 {
2471 sim_fpu wop1;
2472 sim_fpu wop2;
2473 sim_fpu ans;
2474 unsigned32 res;
2475 sim_fpu_32to (&wop1, op1);
2476 sim_fpu_32to (&wop2, op2);
2477 sim_fpu_sub (&ans, &wop1, &wop2);
2478 sim_fpu_to32 (&res, &ans);
2479 result = res;
2480 }
2481 break;
2482 case fmt_double:
2483 {
2484 sim_fpu wop1;
2485 sim_fpu wop2;
2486 sim_fpu ans;
2487 unsigned64 res;
2488 sim_fpu_64to (&wop1, op1);
2489 sim_fpu_64to (&wop2, op2);
2490 sim_fpu_sub (&ans, &wop1, &wop2);
2491 sim_fpu_to64 (&res, &ans);
2492 result = res;
2493 }
2494 break;
2495 default:
2496 fprintf (stderr, "Bad switch\n");
2497 abort ();
2498 }
2499
2500 #ifdef DEBUG
2501 printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2502 #endif /* DEBUG */
2503
2504 return(result);
2505 }
2506
2507 uword64
2508 Multiply(op1,op2,fmt)
2509 uword64 op1;
2510 uword64 op2;
2511 FP_formats fmt;
2512 {
2513 uword64 result = 0;
2514
2515 #ifdef DEBUG
2516 printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2517 #endif /* DEBUG */
2518
2519 /* The registers must specify FPRs valid for operands of type
2520 "fmt". If they are not valid, the result is undefined. */
2521
2522 /* The format type should already have been checked: */
2523 switch (fmt) {
2524 case fmt_single:
2525 {
2526 sim_fpu wop1;
2527 sim_fpu wop2;
2528 sim_fpu ans;
2529 unsigned32 res;
2530 sim_fpu_32to (&wop1, op1);
2531 sim_fpu_32to (&wop2, op2);
2532 sim_fpu_mul (&ans, &wop1, &wop2);
2533 sim_fpu_to32 (&res, &ans);
2534 result = res;
2535 break;
2536 }
2537 case fmt_double:
2538 {
2539 sim_fpu wop1;
2540 sim_fpu wop2;
2541 sim_fpu ans;
2542 unsigned64 res;
2543 sim_fpu_64to (&wop1, op1);
2544 sim_fpu_64to (&wop2, op2);
2545 sim_fpu_mul (&ans, &wop1, &wop2);
2546 sim_fpu_to64 (&res, &ans);
2547 result = res;
2548 break;
2549 }
2550 default:
2551 fprintf (stderr, "Bad switch\n");
2552 abort ();
2553 }
2554
2555 #ifdef DEBUG
2556 printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2557 #endif /* DEBUG */
2558
2559 return(result);
2560 }
2561
2562 uword64
2563 Divide(op1,op2,fmt)
2564 uword64 op1;
2565 uword64 op2;
2566 FP_formats fmt;
2567 {
2568 uword64 result = 0;
2569
2570 #ifdef DEBUG
2571 printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2572 #endif /* DEBUG */
2573
2574 /* The registers must specify FPRs valid for operands of type
2575 "fmt". If they are not valid, the result is undefined. */
2576
2577 /* The format type should already have been checked: */
2578 switch (fmt) {
2579 case fmt_single:
2580 {
2581 sim_fpu wop1;
2582 sim_fpu wop2;
2583 sim_fpu ans;
2584 unsigned32 res;
2585 sim_fpu_32to (&wop1, op1);
2586 sim_fpu_32to (&wop2, op2);
2587 sim_fpu_div (&ans, &wop1, &wop2);
2588 sim_fpu_to32 (&res, &ans);
2589 result = res;
2590 break;
2591 }
2592 case fmt_double:
2593 {
2594 sim_fpu wop1;
2595 sim_fpu wop2;
2596 sim_fpu ans;
2597 unsigned64 res;
2598 sim_fpu_64to (&wop1, op1);
2599 sim_fpu_64to (&wop2, op2);
2600 sim_fpu_div (&ans, &wop1, &wop2);
2601 sim_fpu_to64 (&res, &ans);
2602 result = res;
2603 break;
2604 }
2605 default:
2606 fprintf (stderr, "Bad switch\n");
2607 abort ();
2608 }
2609
2610 #ifdef DEBUG
2611 printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2612 #endif /* DEBUG */
2613
2614 return(result);
2615 }
2616
2617 uword64 UNUSED
2618 Recip(op,fmt)
2619 uword64 op;
2620 FP_formats fmt;
2621 {
2622 uword64 result = 0;
2623
2624 #ifdef DEBUG
2625 printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
2626 #endif /* DEBUG */
2627
2628 /* The registers must specify FPRs valid for operands of type
2629 "fmt". If they are not valid, the result is undefined. */
2630
2631 /* The format type should already have been checked: */
2632 switch (fmt) {
2633 case fmt_single:
2634 {
2635 sim_fpu wop;
2636 sim_fpu ans;
2637 unsigned32 res;
2638 sim_fpu_32to (&wop, op);
2639 sim_fpu_inv (&ans, &wop);
2640 sim_fpu_to32 (&res, &ans);
2641 result = res;
2642 break;
2643 }
2644 case fmt_double:
2645 {
2646 sim_fpu wop;
2647 sim_fpu ans;
2648 unsigned64 res;
2649 sim_fpu_64to (&wop, op);
2650 sim_fpu_inv (&ans, &wop);
2651 sim_fpu_to64 (&res, &ans);
2652 result = res;
2653 break;
2654 }
2655 default:
2656 fprintf (stderr, "Bad switch\n");
2657 abort ();
2658 }
2659
2660 #ifdef DEBUG
2661 printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2662 #endif /* DEBUG */
2663
2664 return(result);
2665 }
2666
2667 uword64
2668 SquareRoot(op,fmt)
2669 uword64 op;
2670 FP_formats fmt;
2671 {
2672 uword64 result = 0;
2673
2674 #ifdef DEBUG
2675 printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
2676 #endif /* DEBUG */
2677
2678 /* The registers must specify FPRs valid for operands of type
2679 "fmt". If they are not valid, the result is undefined. */
2680
2681 /* The format type should already have been checked: */
2682 switch (fmt) {
2683 case fmt_single:
2684 {
2685 sim_fpu wop;
2686 sim_fpu ans;
2687 unsigned32 res;
2688 sim_fpu_32to (&wop, op);
2689 sim_fpu_sqrt (&ans, &wop);
2690 sim_fpu_to32 (&res, &ans);
2691 result = res;
2692 break;
2693 }
2694 case fmt_double:
2695 {
2696 sim_fpu wop;
2697 sim_fpu ans;
2698 unsigned64 res;
2699 sim_fpu_64to (&wop, op);
2700 sim_fpu_sqrt (&ans, &wop);
2701 sim_fpu_to64 (&res, &ans);
2702 result = res;
2703 break;
2704 }
2705 default:
2706 fprintf (stderr, "Bad switch\n");
2707 abort ();
2708 }
2709
2710 #ifdef DEBUG
2711 printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2712 #endif /* DEBUG */
2713
2714 return(result);
2715 }
2716
2717 #if 0
2718 uword64
2719 Max (uword64 op1,
2720 uword64 op2,
2721 FP_formats fmt)
2722 {
2723 int cmp;
2724 unsigned64 result;
2725
2726 #ifdef DEBUG
2727 printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2728 #endif /* DEBUG */
2729
2730 /* The registers must specify FPRs valid for operands of type
2731 "fmt". If they are not valid, the result is undefined. */
2732
2733 /* The format type should already have been checked: */
2734 switch (fmt)
2735 {
2736 case fmt_single:
2737 {
2738 sim_fpu wop1;
2739 sim_fpu wop2;
2740 sim_fpu_32to (&wop1, op1);
2741 sim_fpu_32to (&wop2, op2);
2742 cmp = sim_fpu_cmp (&wop1, &wop2);
2743 break;
2744 }
2745 case fmt_double:
2746 {
2747 sim_fpu wop1;
2748 sim_fpu wop2;
2749 sim_fpu_64to (&wop1, op1);
2750 sim_fpu_64to (&wop2, op2);
2751 cmp = sim_fpu_cmp (&wop1, &wop2);
2752 break;
2753 }
2754 default:
2755 fprintf (stderr, "Bad switch\n");
2756 abort ();
2757 }
2758
2759 switch (cmp)
2760 {
2761 case SIM_FPU_IS_SNAN:
2762 case SIM_FPU_IS_QNAN:
2763 result = op1;
2764 case SIM_FPU_IS_NINF:
2765 case SIM_FPU_IS_NNUMBER:
2766 case SIM_FPU_IS_NDENORM:
2767 case SIM_FPU_IS_NZERO:
2768 result = op2; /* op1 - op2 < 0 */
2769 case SIM_FPU_IS_PINF:
2770 case SIM_FPU_IS_PNUMBER:
2771 case SIM_FPU_IS_PDENORM:
2772 case SIM_FPU_IS_PZERO:
2773 result = op1; /* op1 - op2 > 0 */
2774 default:
2775 fprintf (stderr, "Bad switch\n");
2776 abort ();
2777 }
2778
2779 #ifdef DEBUG
2780 printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2781 #endif /* DEBUG */
2782
2783 return(result);
2784 }
2785 #endif
2786
2787 #if 0
2788 uword64
2789 Min (uword64 op1,
2790 uword64 op2,
2791 FP_formats fmt)
2792 {
2793 int cmp;
2794 unsigned64 result;
2795
2796 #ifdef DEBUG
2797 printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2798 #endif /* DEBUG */
2799
2800 /* The registers must specify FPRs valid for operands of type
2801 "fmt". If they are not valid, the result is undefined. */
2802
2803 /* The format type should already have been checked: */
2804 switch (fmt)
2805 {
2806 case fmt_single:
2807 {
2808 sim_fpu wop1;
2809 sim_fpu wop2;
2810 sim_fpu_32to (&wop1, op1);
2811 sim_fpu_32to (&wop2, op2);
2812 cmp = sim_fpu_cmp (&wop1, &wop2);
2813 break;
2814 }
2815 case fmt_double:
2816 {
2817 sim_fpu wop1;
2818 sim_fpu wop2;
2819 sim_fpu_64to (&wop1, op1);
2820 sim_fpu_64to (&wop2, op2);
2821 cmp = sim_fpu_cmp (&wop1, &wop2);
2822 break;
2823 }
2824 default:
2825 fprintf (stderr, "Bad switch\n");
2826 abort ();
2827 }
2828
2829 switch (cmp)
2830 {
2831 case SIM_FPU_IS_SNAN:
2832 case SIM_FPU_IS_QNAN:
2833 result = op1;
2834 case SIM_FPU_IS_NINF:
2835 case SIM_FPU_IS_NNUMBER:
2836 case SIM_FPU_IS_NDENORM:
2837 case SIM_FPU_IS_NZERO:
2838 result = op1; /* op1 - op2 < 0 */
2839 case SIM_FPU_IS_PINF:
2840 case SIM_FPU_IS_PNUMBER:
2841 case SIM_FPU_IS_PDENORM:
2842 case SIM_FPU_IS_PZERO:
2843 result = op2; /* op1 - op2 > 0 */
2844 default:
2845 fprintf (stderr, "Bad switch\n");
2846 abort ();
2847 }
2848
2849 #ifdef DEBUG
2850 printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2851 #endif /* DEBUG */
2852
2853 return(result);
2854 }
2855 #endif
2856
2857 uword64
2858 convert (SIM_DESC sd,
2859 sim_cpu *cpu,
2860 address_word cia,
2861 int rm,
2862 uword64 op,
2863 FP_formats from,
2864 FP_formats to)
2865 {
2866 sim_fpu wop;
2867 sim_fpu_round round;
2868 unsigned32 result32;
2869 unsigned64 result64;
2870
2871 #ifdef DEBUG
2872 #if 0 /* FIXME: doesn't compile */
2873 printf("DBG: Convert: mode %s : op 0x%s : from %s : to %s : (PC = 0x%s)\n",RMMODE(rm),pr_addr(op),DOFMT(from),DOFMT(to),pr_addr(IPC));
2874 #endif
2875 #endif /* DEBUG */
2876
2877 switch (rm)
2878 {
2879 case FP_RM_NEAREST:
2880 /* Round result to nearest representable value. When two
2881 representable values are equally near, round to the value
2882 that has a least significant bit of zero (i.e. is even). */
2883 round = sim_fpu_round_near;
2884 break;
2885 case FP_RM_TOZERO:
2886 /* Round result to the value closest to, and not greater in
2887 magnitude than, the result. */
2888 round = sim_fpu_round_zero;
2889 break;
2890 case FP_RM_TOPINF:
2891 /* Round result to the value closest to, and not less than,
2892 the result. */
2893 round = sim_fpu_round_up;
2894 break;
2895
2896 case FP_RM_TOMINF:
2897 /* Round result to the value closest to, and not greater than,
2898 the result. */
2899 round = sim_fpu_round_down;
2900 break;
2901 default:
2902 round = 0;
2903 fprintf (stderr, "Bad switch\n");
2904 abort ();
2905 }
2906
2907 /* Convert the input to sim_fpu internal format */
2908 switch (from)
2909 {
2910 case fmt_double:
2911 sim_fpu_64to (&wop, op);
2912 break;
2913 case fmt_single:
2914 sim_fpu_32to (&wop, op);
2915 break;
2916 case fmt_word:
2917 sim_fpu_i32to (&wop, op, round);
2918 break;
2919 case fmt_long:
2920 sim_fpu_i64to (&wop, op, round);
2921 break;
2922 default:
2923 fprintf (stderr, "Bad switch\n");
2924 abort ();
2925 }
2926
2927 /* Convert sim_fpu format into the output */
2928 /* The value WOP is converted to the destination format, rounding
2929 using mode RM. When the destination is a fixed-point format, then
2930 a source value of Infinity, NaN or one which would round to an
2931 integer outside the fixed point range then an IEEE Invalid
2932 Operation condition is raised. */
2933 switch (to)
2934 {
2935 case fmt_single:
2936 sim_fpu_round_32 (&wop, round, 0);
2937 sim_fpu_to32 (&result32, &wop);
2938 result64 = result32;
2939 break;
2940 case fmt_double:
2941 sim_fpu_round_64 (&wop, round, 0);
2942 sim_fpu_to64 (&result64, &wop);
2943 break;
2944 case fmt_word:
2945 sim_fpu_to32i (&result32, &wop, round);
2946 result64 = result32;
2947 break;
2948 case fmt_long:
2949 sim_fpu_to64i (&result64, &wop, round);
2950 break;
2951 default:
2952 result64 = 0;
2953 fprintf (stderr, "Bad switch\n");
2954 abort ();
2955 }
2956
2957 #ifdef DEBUG
2958 printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to));
2959 #endif /* DEBUG */
2960
2961 return(result64);
2962 }
2963
2964
2965 /*-- co-processor support routines ------------------------------------------*/
2966
2967 static int UNUSED
2968 CoProcPresent(unsigned int coproc_number)
2969 {
2970 /* Return TRUE if simulator provides a model for the given co-processor number */
2971 return(0);
2972 }
2973
2974 void
2975 cop_lw (SIM_DESC sd,
2976 sim_cpu *cpu,
2977 address_word cia,
2978 int coproc_num,
2979 int coproc_reg,
2980 unsigned int memword)
2981 {
2982 switch (coproc_num)
2983 {
2984 case 1:
2985 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
2986 {
2987 #ifdef DEBUG
2988 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword));
2989 #endif
2990 StoreFPR(coproc_reg,fmt_word,(uword64)memword);
2991 FPR_STATE[coproc_reg] = fmt_uninterpreted;
2992 break;
2993 }
2994
2995 default:
2996 #if 0 /* this should be controlled by a configuration option */
2997 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));
2998 #endif
2999 break;
3000 }
3001
3002 return;
3003 }
3004
3005 void
3006 cop_ld (SIM_DESC sd,
3007 sim_cpu *cpu,
3008 address_word cia,
3009 int coproc_num,
3010 int coproc_reg,
3011 uword64 memword)
3012 {
3013
3014 #ifdef DEBUG
3015 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) );
3016 #endif
3017
3018 switch (coproc_num) {
3019 case 1:
3020 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3021 {
3022 StoreFPR(coproc_reg,fmt_uninterpreted,memword);
3023 break;
3024 }
3025
3026 default:
3027 #if 0 /* this message should be controlled by a configuration option */
3028 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));
3029 #endif
3030 break;
3031 }
3032
3033 return;
3034 }
3035
3036
3037
3038
3039 unsigned int
3040 cop_sw (SIM_DESC sd,
3041 sim_cpu *cpu,
3042 address_word cia,
3043 int coproc_num,
3044 int coproc_reg)
3045 {
3046 unsigned int value = 0;
3047
3048 switch (coproc_num)
3049 {
3050 case 1:
3051 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3052 {
3053 FP_formats hold;
3054 hold = FPR_STATE[coproc_reg];
3055 FPR_STATE[coproc_reg] = fmt_word;
3056 value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
3057 FPR_STATE[coproc_reg] = hold;
3058 break;
3059 }
3060
3061 default:
3062 #if 0 /* should be controlled by configuration option */
3063 sim_io_printf(sd,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));
3064 #endif
3065 break;
3066 }
3067
3068 return(value);
3069 }
3070
3071 uword64
3072 cop_sd (SIM_DESC sd,
3073 sim_cpu *cpu,
3074 address_word cia,
3075 int coproc_num,
3076 int coproc_reg)
3077 {
3078 uword64 value = 0;
3079 switch (coproc_num)
3080 {
3081 case 1:
3082 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3083 {
3084 value = ValueFPR(coproc_reg,fmt_uninterpreted);
3085 break;
3086 }
3087
3088 default:
3089 #if 0 /* should be controlled by configuration option */
3090 sim_io_printf(sd,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));
3091 #endif
3092 break;
3093 }
3094
3095 return(value);
3096 }
3097
3098
3099
3100
3101 void
3102 decode_coproc (SIM_DESC sd,
3103 sim_cpu *cpu,
3104 address_word cia,
3105 unsigned int instruction)
3106 {
3107 int coprocnum = ((instruction >> 26) & 3);
3108
3109 switch (coprocnum)
3110 {
3111 case 0: /* standard CPU control and cache registers */
3112 {
3113 int code = ((instruction >> 21) & 0x1F);
3114 int rt = ((instruction >> 16) & 0x1F);
3115 int rd = ((instruction >> 11) & 0x1F);
3116 int tail = instruction & 0x3ff;
3117 /* R4000 Users Manual (second edition) lists the following CP0
3118 instructions:
3119 CODE><-RT><RD-><--TAIL--->
3120 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
3121 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
3122 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
3123 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
3124 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
3125 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
3126 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
3127 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
3128 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
3129 ERET Exception return (VR4100 = 01000010000000000000000000011000)
3130 */
3131 if (((code == 0x00) || (code == 0x04) /* MFC0 / MTC0 */
3132 || (code == 0x01) || (code == 0x05)) /* DMFC0 / DMTC0 */
3133 && tail == 0)
3134 {
3135 /* Clear double/single coprocessor move bit. */
3136 code &= ~1;
3137
3138 /* M[TF]C0 (32 bits) | DM[TF]C0 (64 bits) */
3139
3140 switch (rd) /* NOTEs: Standard CP0 registers */
3141 {
3142 /* 0 = Index R4000 VR4100 VR4300 */
3143 /* 1 = Random R4000 VR4100 VR4300 */
3144 /* 2 = EntryLo0 R4000 VR4100 VR4300 */
3145 /* 3 = EntryLo1 R4000 VR4100 VR4300 */
3146 /* 4 = Context R4000 VR4100 VR4300 */
3147 /* 5 = PageMask R4000 VR4100 VR4300 */
3148 /* 6 = Wired R4000 VR4100 VR4300 */
3149 /* 8 = BadVAddr R4000 VR4100 VR4300 */
3150 /* 9 = Count R4000 VR4100 VR4300 */
3151 /* 10 = EntryHi R4000 VR4100 VR4300 */
3152 /* 11 = Compare R4000 VR4100 VR4300 */
3153 /* 12 = SR R4000 VR4100 VR4300 */
3154 #ifdef SUBTARGET_R3900
3155 case 3:
3156 /* 3 = Config R3900 */
3157 case 7:
3158 /* 7 = Cache R3900 */
3159 case 15:
3160 /* 15 = PRID R3900 */
3161
3162 /* ignore */
3163 break;
3164
3165 case 8:
3166 /* 8 = BadVAddr R4000 VR4100 VR4300 */
3167 if (code == 0x00)
3168 GPR[rt] = COP0_BADVADDR;
3169 else
3170 COP0_BADVADDR = GPR[rt];
3171 break;
3172
3173 #endif /* SUBTARGET_R3900 */
3174 case 12:
3175 if (code == 0x00)
3176 GPR[rt] = SR;
3177 else
3178 SR = GPR[rt];
3179 break;
3180 /* 13 = Cause R4000 VR4100 VR4300 */
3181 case 13:
3182 if (code == 0x00)
3183 GPR[rt] = CAUSE;
3184 else
3185 CAUSE = GPR[rt];
3186 break;
3187 /* 14 = EPC R4000 VR4100 VR4300 */
3188 case 14:
3189 if (code == 0x00)
3190 GPR[rt] = (signed_word) (signed_address) EPC;
3191 else
3192 EPC = GPR[rt];
3193 break;
3194 /* 15 = PRId R4000 VR4100 VR4300 */
3195 #ifdef SUBTARGET_R3900
3196 /* 16 = Debug */
3197 case 16:
3198 if (code == 0x00)
3199 GPR[rt] = Debug;
3200 else
3201 Debug = GPR[rt];
3202 break;
3203 #else
3204 /* 16 = Config R4000 VR4100 VR4300 */
3205 case 16:
3206 if (code == 0x00)
3207 GPR[rt] = C0_CONFIG;
3208 else
3209 C0_CONFIG = GPR[rt];
3210 break;
3211 #endif
3212 #ifdef SUBTARGET_R3900
3213 /* 17 = Debug */
3214 case 17:
3215 if (code == 0x00)
3216 GPR[rt] = DEPC;
3217 else
3218 DEPC = GPR[rt];
3219 break;
3220 #else
3221 /* 17 = LLAddr R4000 VR4100 VR4300 */
3222 #endif
3223 /* 18 = WatchLo R4000 VR4100 VR4300 */
3224 /* 19 = WatchHi R4000 VR4100 VR4300 */
3225 /* 20 = XContext R4000 VR4100 VR4300 */
3226 /* 26 = PErr or ECC R4000 VR4100 VR4300 */
3227 /* 27 = CacheErr R4000 VR4100 */
3228 /* 28 = TagLo R4000 VR4100 VR4300 */
3229 /* 29 = TagHi R4000 VR4100 VR4300 */
3230 /* 30 = ErrorEPC R4000 VR4100 VR4300 */
3231 if (STATE_VERBOSE_P(SD))
3232 sim_io_eprintf (SD,
3233 "Warning: PC 0x%lx:interp.c decode_coproc DEADC0DE\n",
3234 (unsigned long)cia);
3235 GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
3236 /* CPR[0,rd] = GPR[rt]; */
3237 default:
3238 if (code == 0x00)
3239 GPR[rt] = (signed_word) (signed32) COP0_GPR[rd];
3240 else
3241 COP0_GPR[rd] = GPR[rt];
3242 #if 0
3243 if (code == 0x00)
3244 sim_io_printf(sd,"Warning: MFC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia);
3245 else
3246 sim_io_printf(sd,"Warning: MTC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia);
3247 #endif
3248 }
3249 }
3250 else if (code == 0x10 && (tail & 0x3f) == 0x18)
3251 {
3252 /* ERET */
3253 if (SR & status_ERL)
3254 {
3255 /* Oops, not yet available */
3256 sim_io_printf(sd,"Warning: ERET when SR[ERL] set not handled yet");
3257 PC = EPC;
3258 SR &= ~status_ERL;
3259 }
3260 else
3261 {
3262 PC = EPC;
3263 SR &= ~status_EXL;
3264 }
3265 }
3266 else if (code == 0x10 && (tail & 0x3f) == 0x10)
3267 {
3268 /* RFE */
3269 #ifdef SUBTARGET_R3900
3270 /* TX39: Copy IEp/KUp -> IEc/KUc, and IEo/KUo -> IEp/KUp */
3271
3272 /* shift IE/KU history bits right */
3273 SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 5, 2), 3, 0);
3274
3275 /* TODO: CACHE register */
3276 #endif /* SUBTARGET_R3900 */
3277 }
3278 else if (code == 0x10 && (tail & 0x3f) == 0x1F)
3279 {
3280 /* DERET */
3281 Debug &= ~Debug_DM;
3282 DELAYSLOT();
3283 DSPC = DEPC;
3284 }
3285 else
3286 sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia));
3287 /* TODO: When executing an ERET or RFE instruction we should
3288 clear LLBIT, to ensure that any out-standing atomic
3289 read/modify/write sequence fails. */
3290 }
3291 break;
3292
3293 case 2: /* co-processor 2 */
3294 {
3295 int handle = 0;
3296
3297
3298 if(! handle)
3299 {
3300 sim_io_eprintf(sd, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
3301 instruction,pr_addr(cia));
3302 }
3303 }
3304 break;
3305
3306 case 1: /* should not occur (FPU co-processor) */
3307 case 3: /* should not occur (FPU co-processor) */
3308 SignalException(ReservedInstruction,instruction);
3309 break;
3310 }
3311
3312 return;
3313 }
3314
3315
3316 /* This code copied from gdb's utils.c. Would like to share this code,
3317 but don't know of a common place where both could get to it. */
3318
3319 /* Temporary storage using circular buffer */
3320 #define NUMCELLS 16
3321 #define CELLSIZE 32
3322 static char*
3323 get_cell (void)
3324 {
3325 static char buf[NUMCELLS][CELLSIZE];
3326 static int cell=0;
3327 if (++cell>=NUMCELLS) cell=0;
3328 return buf[cell];
3329 }
3330
3331 /* Print routines to handle variable size regs, etc */
3332
3333 /* Eliminate warning from compiler on 32-bit systems */
3334 static int thirty_two = 32;
3335
3336 char*
3337 pr_addr(addr)
3338 SIM_ADDR addr;
3339 {
3340 char *paddr_str=get_cell();
3341 switch (sizeof(addr))
3342 {
3343 case 8:
3344 sprintf(paddr_str,"%08lx%08lx",
3345 (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff));
3346 break;
3347 case 4:
3348 sprintf(paddr_str,"%08lx",(unsigned long)addr);
3349 break;
3350 case 2:
3351 sprintf(paddr_str,"%04x",(unsigned short)(addr&0xffff));
3352 break;
3353 default:
3354 sprintf(paddr_str,"%x",addr);
3355 }
3356 return paddr_str;
3357 }
3358
3359 char*
3360 pr_uword64(addr)
3361 uword64 addr;
3362 {
3363 char *paddr_str=get_cell();
3364 sprintf(paddr_str,"%08lx%08lx",
3365 (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff));
3366 return paddr_str;
3367 }
3368
3369
3370 void
3371 mips_core_signal (SIM_DESC sd,
3372 sim_cpu *cpu,
3373 sim_cia cia,
3374 unsigned map,
3375 int nr_bytes,
3376 address_word addr,
3377 transfer_type transfer,
3378 sim_core_signals sig)
3379 {
3380 const char *copy = (transfer == read_transfer ? "read" : "write");
3381 address_word ip = CIA_ADDR (cia);
3382
3383 switch (sig)
3384 {
3385 case sim_core_unmapped_signal:
3386 sim_io_eprintf (sd, "mips-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
3387 nr_bytes, copy,
3388 (unsigned long) addr, (unsigned long) ip);
3389 COP0_BADVADDR = addr;
3390 SignalExceptionDataReference();
3391 break;
3392
3393 case sim_core_unaligned_signal:
3394 sim_io_eprintf (sd, "mips-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
3395 nr_bytes, copy,
3396 (unsigned long) addr, (unsigned long) ip);
3397 COP0_BADVADDR = addr;
3398 if(transfer == read_transfer)
3399 SignalExceptionAddressLoad();
3400 else
3401 SignalExceptionAddressStore();
3402 break;
3403
3404 default:
3405 sim_engine_abort (sd, cpu, cia,
3406 "mips_core_signal - internal error - bad switch");
3407 }
3408 }
3409
3410
3411 void
3412 mips_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia)
3413 {
3414 ASSERT(cpu != NULL);
3415
3416 if(cpu->exc_suspended > 0)
3417 sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", cpu->exc_suspended);
3418
3419 PC = cia;
3420 memcpy(cpu->exc_trigger_registers, cpu->registers, sizeof(cpu->exc_trigger_registers));
3421 cpu->exc_suspended = 0;
3422 }
3423
3424 void
3425 mips_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception)
3426 {
3427 ASSERT(cpu != NULL);
3428
3429 if(cpu->exc_suspended > 0)
3430 sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n",
3431 cpu->exc_suspended, exception);
3432
3433 memcpy(cpu->exc_suspend_registers, cpu->registers, sizeof(cpu->exc_suspend_registers));
3434 memcpy(cpu->registers, cpu->exc_trigger_registers, sizeof(cpu->registers));
3435 cpu->exc_suspended = exception;
3436 }
3437
3438 void
3439 mips_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception)
3440 {
3441 ASSERT(cpu != NULL);
3442
3443 if(exception == 0 && cpu->exc_suspended > 0)
3444 {
3445 /* warn not for breakpoints */
3446 if(cpu->exc_suspended != sim_signal_to_host(sd, SIM_SIGTRAP))
3447 sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n",
3448 cpu->exc_suspended);
3449 }
3450 else if(exception != 0 && cpu->exc_suspended > 0)
3451 {
3452 if(exception != cpu->exc_suspended)
3453 sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
3454 cpu->exc_suspended, exception);
3455
3456 memcpy(cpu->registers, cpu->exc_suspend_registers, sizeof(cpu->registers));
3457 }
3458 else if(exception != 0 && cpu->exc_suspended == 0)
3459 {
3460 sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception);
3461 }
3462 cpu->exc_suspended = 0;
3463 }
3464
3465
3466 /*---------------------------------------------------------------------------*/
3467 /*> EOF interp.c <*/
This page took 0.107386 seconds and 4 git commands to generate.