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