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