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