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