This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / sim / mips / interp.c
1 /*> interp.c <*/
2 /* Simulator for the MIPS architecture.
3
4 This file is part of the MIPS sim
5
6 THIS SOFTWARE IS NOT COPYRIGHTED
7
8 Cygnus offers the following for use in the public domain. Cygnus
9 makes no warranty with regard to the software or it's performance
10 and the user accepts the software "AS IS" with all faults.
11
12 CYGNUS DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO
13 THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15
16 $Revision$
17 $Date$
18
19 NOTEs:
20
21 The IDT monitor (found on the VR4300 board), seems to lie about
22 register contents. It seems to treat the registers as sign-extended
23 32-bit values. This cause *REAL* problems when single-stepping 64-bit
24 code on the hardware.
25
26 */
27
28 /* The TRACE manifests enable the provision of extra features. If they
29 are not defined then a simpler (quicker) simulator is constructed
30 without the required run-time checks, etc. */
31 #if 1 /* 0 to allow user build selection, 1 to force inclusion */
32 #define TRACE (1)
33 #endif
34
35 #include "bfd.h"
36 #include "sim-main.h"
37 #include "sim-utils.h"
38 #include "sim-options.h"
39 #include "sim-assert.h"
40 #include "sim-hw.h"
41
42 #if WITH_IGEN
43 #include "itable.h"
44 #endif
45
46 /* start-sanitize-sky */
47 #ifdef TARGET_SKY
48 #include "sky-vu.h"
49 #include "sky-vpe.h"
50 #include "sky-libvpe.h"
51 #include "sky-vif.h"
52 #include "idecode.h"
53 #include "sky-gdb.h"
54 #endif
55 /* end-sanitize-sky */
56
57 #include "config.h"
58
59 #include <stdio.h>
60 #include <stdarg.h>
61 #include <ansidecl.h>
62 #include <ctype.h>
63 #include <limits.h>
64 #include <math.h>
65 #ifdef HAVE_STDLIB_H
66 #include <stdlib.h>
67 #endif
68 #ifdef HAVE_STRING_H
69 #include <string.h>
70 #else
71 #ifdef HAVE_STRINGS_H
72 #include <strings.h>
73 #endif
74 #endif
75
76 #include "getopt.h"
77 #include "libiberty.h"
78 #include "bfd.h"
79 #include "callback.h" /* GDB simulator callback interface */
80 #include "remote-sim.h" /* GDB simulator interface */
81
82 #include "sysdep.h"
83
84 #ifndef PARAMS
85 #define PARAMS(x)
86 #endif
87
88 char* pr_addr PARAMS ((SIM_ADDR addr));
89 char* pr_uword64 PARAMS ((uword64 addr));
90
91
92 /* Get the simulator engine description, without including the code: */
93 #if !(WITH_IGEN)
94 #define SIM_MANIFESTS
95 #include "oengine.c"
96 #undef SIM_MANIFESTS
97 #endif
98
99 /* Within interp.c we refer to the sim_state and sim_cpu directly. */
100 #define CPU cpu
101 #define SD sd
102
103
104 /* The following reserved instruction value is used when a simulator
105 trap is required. NOTE: Care must be taken, since this value may be
106 used in later revisions of the MIPS ISA. */
107
108 #define RSVD_INSTRUCTION (0x00000005)
109 #define RSVD_INSTRUCTION_MASK (0xFC00003F)
110
111 #define RSVD_INSTRUCTION_ARG_SHIFT 6
112 #define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
113
114
115 /* Bits in the Debug register */
116 #define Debug_DBD 0x80000000 /* Debug Branch Delay */
117 #define Debug_DM 0x40000000 /* Debug Mode */
118 #define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */
119
120 /*---------------------------------------------------------------------------*/
121 /*-- GDB simulator interface ------------------------------------------------*/
122 /*---------------------------------------------------------------------------*/
123
124 static void ColdReset PARAMS((SIM_DESC sd));
125
126 /*---------------------------------------------------------------------------*/
127
128
129
130 #define DELAYSLOT() {\
131 if (STATE & simDELAYSLOT)\
132 sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
133 STATE |= simDELAYSLOT;\
134 }
135
136 #define JALDELAYSLOT() {\
137 DELAYSLOT ();\
138 STATE |= simJALDELAYSLOT;\
139 }
140
141 #define NULLIFY() {\
142 STATE &= ~simDELAYSLOT;\
143 STATE |= simSKIPNEXT;\
144 }
145
146 #define CANCELDELAYSLOT() {\
147 DSSTATE = 0;\
148 STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
149 }
150
151 #define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
152 #define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
153
154 #define K0BASE (0x80000000)
155 #define K0SIZE (0x20000000)
156 #define K1BASE (0xA0000000)
157 #define K1SIZE (0x20000000)
158 #define MONITOR_BASE (0xBFC00000)
159 #define MONITOR_SIZE (1 << 11)
160 #define MEM_SIZE (2 << 20)
161
162 /* start-sanitize-sky */
163 #ifdef TARGET_SKY
164 #undef MEM_SIZE
165 #define MEM_SIZE (16 << 20) /* 16 MB */
166 #undef MONITOR_SIZE
167 #define MONITOR_SIZE 0x100000 /* 1MB */
168 #endif
169 /* end-sanitize-sky */
170
171 #if defined(TRACE)
172 static char *tracefile = "trace.din"; /* default filename for trace log */
173 FILE *tracefh = NULL;
174 static void open_trace PARAMS((SIM_DESC sd));
175 #endif /* TRACE */
176
177 #if WITH_IGEN
178 static const char * get_insn_name (sim_cpu *, int);
179 #endif
180
181 /* simulation target board. NULL=canonical */
182 static char* board = NULL;
183
184
185 static DECLARE_OPTION_HANDLER (mips_option_handler);
186
187 enum {
188 OPTION_DINERO_TRACE = OPTION_START,
189 OPTION_DINERO_FILE,
190 /* start-stanitize-branchbug4011 */
191 OPTION_BRANCH_BUG_4011,
192 /* end-stanitize-branchbug4011 */
193 OPTION_BOARD
194 };
195
196
197 static SIM_RC
198 mips_option_handler (sd, cpu, opt, arg, is_command)
199 SIM_DESC sd;
200 sim_cpu *cpu;
201 int opt;
202 char *arg;
203 int is_command;
204 {
205 int cpu_nr;
206 switch (opt)
207 {
208 /* start-sanitize-branchbug4011 */
209 case OPTION_BRANCH_BUG_4011:
210 {
211 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
212 {
213 sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
214 if (arg == NULL)
215 BRANCHBUG4011_OPTION = 1;
216 else if (strcmp (arg, "yes") == 0)
217 BRANCHBUG4011_OPTION = 1;
218 else if (strcmp (arg, "no") == 0)
219 BRANCHBUG4011_OPTION = 0;
220 else if (strcmp (arg, "on") == 0)
221 BRANCHBUG4011_OPTION = 1;
222 else if (strcmp (arg, "off") == 0)
223 BRANCHBUG4011_OPTION = 0;
224 else
225 {
226 fprintf (stderr, "Unrecognized check-4011-branch-bug option `%s'\n", arg);
227 return SIM_RC_FAIL;
228 }
229 }
230 return SIM_RC_OK;
231 }
232
233 /* end-sanitize-branchbug4011 */
234 case OPTION_DINERO_TRACE: /* ??? */
235 #if defined(TRACE)
236 /* Eventually the simTRACE flag could be treated as a toggle, to
237 allow external control of the program points being traced
238 (i.e. only from main onwards, excluding the run-time setup,
239 etc.). */
240 for (cpu_nr = 0; cpu_nr < MAX_NR_PROCESSORS; cpu_nr++)
241 {
242 sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
243 if (arg == NULL)
244 STATE |= simTRACE;
245 else if (strcmp (arg, "yes") == 0)
246 STATE |= simTRACE;
247 else if (strcmp (arg, "no") == 0)
248 STATE &= ~simTRACE;
249 else if (strcmp (arg, "on") == 0)
250 STATE |= simTRACE;
251 else if (strcmp (arg, "off") == 0)
252 STATE &= ~simTRACE;
253 else
254 {
255 fprintf (stderr, "Unrecognized dinero-trace option `%s'\n", arg);
256 return SIM_RC_FAIL;
257 }
258 }
259 return SIM_RC_OK;
260 #else /* !TRACE */
261 fprintf(stderr,"\
262 Simulator constructed without dinero tracing support (for performance).\n\
263 Re-compile simulator with \"-DTRACE\" to enable this option.\n");
264 return SIM_RC_FAIL;
265 #endif /* !TRACE */
266
267 case OPTION_DINERO_FILE:
268 #if defined(TRACE)
269 if (optarg != NULL) {
270 char *tmp;
271 tmp = (char *)malloc(strlen(optarg) + 1);
272 if (tmp == NULL)
273 {
274 sim_io_printf(sd,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg);
275 return SIM_RC_FAIL;
276 }
277 else {
278 strcpy(tmp,optarg);
279 tracefile = tmp;
280 sim_io_printf(sd,"Placing trace information into file \"%s\"\n",tracefile);
281 }
282 }
283 #endif /* TRACE */
284 return SIM_RC_OK;
285
286 case OPTION_BOARD:
287 {
288 if (arg)
289 {
290 board = zalloc(strlen(arg) + 1);
291 strcpy(board, arg);
292 }
293 return SIM_RC_OK;
294 }
295 }
296
297 return SIM_RC_OK;
298 }
299
300
301 static const OPTION mips_options[] =
302 {
303 { {"dinero-trace", optional_argument, NULL, OPTION_DINERO_TRACE},
304 '\0', "on|off", "Enable dinero tracing",
305 mips_option_handler },
306 /* start-sanitize-branchbug4011 */
307 { {"check-4011-branch-bug", optional_argument, NULL, OPTION_BRANCH_BUG_4011},
308 '\0', "on|off", "Enable checking for 4011 branch bug",
309 mips_option_handler },
310 /* end-sanitize-branchbug4011 */
311 { {"dinero-file", required_argument, NULL, OPTION_DINERO_FILE},
312 '\0', "FILE", "Write dinero trace to FILE",
313 mips_option_handler },
314 { {"board", required_argument, NULL, OPTION_BOARD},
315 '\0', "none" /* rely on compile-time string concatenation for other options */
316
317 /* start-sanitize-tx3904 */
318 #define BOARD_JMR3904 "jmr3904"
319 "|" BOARD_JMR3904
320 #define BOARD_JMR3904_PAL "jmr3904pal"
321 "|" BOARD_JMR3904_PAL
322 #define BOARD_JMR3904_DEBUG "jmr3904debug"
323 "|" BOARD_JMR3904_DEBUG
324 /* end-sanitize-tx3904 */
325
326 , "Customize simulation for a particular board.", mips_option_handler },
327
328 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
329 };
330
331
332 int interrupt_pending;
333
334 void
335 interrupt_event (SIM_DESC sd, void *data)
336 {
337 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
338 address_word cia = CIA_GET (cpu);
339 if (SR & status_IE)
340 {
341 interrupt_pending = 0;
342 SignalExceptionInterrupt (1); /* interrupt "1" */
343 }
344 else if (!interrupt_pending)
345 sim_events_schedule (sd, 1, interrupt_event, data);
346 }
347
348
349 /*---------------------------------------------------------------------------*/
350 /*-- Device registration hook -----------------------------------------------*/
351 /*---------------------------------------------------------------------------*/
352 static void device_init(SIM_DESC sd) {
353 #ifdef DEVICE_INIT
354 extern void register_devices(SIM_DESC);
355 register_devices(sd);
356 #endif
357 }
358
359 /*---------------------------------------------------------------------------*/
360 /*-- GDB simulator interface ------------------------------------------------*/
361 /*---------------------------------------------------------------------------*/
362
363 SIM_DESC
364 sim_open (kind, cb, abfd, argv)
365 SIM_OPEN_KIND kind;
366 host_callback *cb;
367 struct _bfd *abfd;
368 char **argv;
369 {
370 SIM_DESC sd = sim_state_alloc (kind, cb);
371 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
372
373 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
374
375 /* FIXME: watchpoints code shouldn't need this */
376 STATE_WATCHPOINTS (sd)->pc = &(PC);
377 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
378 STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event;
379
380 #if WITH_IGEN
381 /* Initialize the mechanism for doing insn profiling. */
382 CPU_INSN_NAME (cpu) = get_insn_name;
383 CPU_MAX_INSNS (cpu) = nr_itable_entries;
384 #endif
385
386 STATE = 0;
387
388 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
389 return 0;
390 sim_add_option_table (sd, NULL, mips_options);
391
392 /* start-sanitize-sky */
393 #ifdef TARGET_SKY
394 sky_command_options_open (sd);
395 #endif
396 /* end-sanitize-sky */
397
398 /* getopt will print the error message so we just have to exit if this fails.
399 FIXME: Hmmm... in the case of gdb we need getopt to call
400 print_filtered. */
401 if (sim_parse_args (sd, argv) != SIM_RC_OK)
402 {
403 /* Uninstall the modules to avoid memory leaks,
404 file descriptor leaks, etc. */
405 sim_module_uninstall (sd);
406 return 0;
407 }
408
409 /* handle board-specific memory maps */
410 if (board == NULL)
411 {
412 /* Allocate core managed memory */
413
414 /* start-sanitize-sky */
415 #ifndef TARGET_SKY
416 /* end-sanitize-sky */
417 /* the monitor */
418 sim_do_commandf (sd, "memory region 0x%lx,0x%lx", MONITOR_BASE, MONITOR_SIZE);
419 /* For compatibility with the old code - under this (at level one)
420 are the kernel spaces K0 & K1. Both of these map to a single
421 smaller sub region */
422 sim_do_command(sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
423 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx%%0x%lx,0x%0x",
424 K1BASE, K0SIZE,
425 MEM_SIZE, /* actual size */
426 K0BASE);
427 /* start-sanitize-sky */
428 #else
429 /* the monitor */
430 sim_do_commandf (sd, "memory region 0x%lx,0x%lx", MONITOR_BASE - K1BASE, MONITOR_SIZE);
431 sim_do_command (sd," memory region 0x7fff8000,0x8000") ; /* MTZ- 32 k stack */
432 /* 16M @ 0x0. Aliases at 0x80000000 and 0xA0000000 are handled by
433 address_translation() */
434 sim_do_commandf (sd, "memory size 0x%lx", MEM_SIZE);
435 #endif
436 /* end-sanitize-sky */
437
438 device_init(sd);
439 }
440
441 /* start-sanitize-tx3904 */
442 #if (WITH_HW)
443 if (board != NULL
444 && (strcmp(board, BOARD_JMR3904) == 0 ||
445 strcmp(board, BOARD_JMR3904_PAL) == 0 ||
446 strcmp(board, BOARD_JMR3904_DEBUG) == 0))
447 {
448 /* match VIRTUAL memory layout of JMR-TX3904 board */
449
450 /* --- environment --- */
451
452 STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
453
454 /* --- memory --- */
455
456 /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */
457 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
458 0x9FC00000,
459 4 * 1024 * 1024, /* 4 MB */
460 0xBFC00000);
461
462 /* SRAM: 0x8000_0000 - 0x803F_FFFF and 0xA000_0000 - 0xA03F_FFFF */
463 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
464 0x80000000,
465 4 * 1024 * 1024, /* 4 MB */
466 0xA0000000);
467
468 /* DRAM: 0x8800_0000 - 0x89FF_FFFF and 0xA800_0000 - 0xA9FF_FFFF */
469 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx,0x%0x",
470 0x88000000,
471 32 * 1024 * 1024, /* 32 MB */
472 0xA8000000);
473
474 /* Dummy memory regions for unsimulated devices */
475
476 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFE010, 0x00c); /* EBIF */
477 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFF9000, 0x200); /* EBIF */
478 sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFF500, 0x300); /* PIO */
479
480 /* --- simulated devices --- */
481 sim_hw_parse (sd, "/tx3904irc@0xffffc000/reg 0xffffc000 0x20");
482 sim_hw_parse (sd, "/tx3904cpu");
483 sim_hw_parse (sd, "/tx3904tmr@0xfffff000/reg 0xfffff000 0x100");
484 sim_hw_parse (sd, "/tx3904tmr@0xfffff100/reg 0xfffff100 0x100");
485 sim_hw_parse (sd, "/tx3904tmr@0xfffff200/reg 0xfffff200 0x100");
486 sim_hw_parse (sd, "/tx3904sio@0xfffff300/reg 0xfffff300 0x100");
487 {
488 /* FIXME: poking at dv-sockser internals, use tcp backend if
489 --sockser_addr option was given.*/
490 extern char* sockser_addr;
491 if(sockser_addr == NULL)
492 sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend stdio");
493 else
494 sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend tcp");
495 }
496 sim_hw_parse (sd, "/tx3904sio@0xfffff400/reg 0xfffff400 0x100");
497 sim_hw_parse (sd, "/tx3904sio@0xfffff400/backend stdio");
498
499 /* -- device connections --- */
500 sim_hw_parse (sd, "/tx3904irc > ip level /tx3904cpu");
501 sim_hw_parse (sd, "/tx3904tmr@0xfffff000 > int tmr0 /tx3904irc");
502 sim_hw_parse (sd, "/tx3904tmr@0xfffff100 > int tmr1 /tx3904irc");
503 sim_hw_parse (sd, "/tx3904tmr@0xfffff200 > int tmr2 /tx3904irc");
504 sim_hw_parse (sd, "/tx3904sio@0xfffff300 > int sio0 /tx3904irc");
505 sim_hw_parse (sd, "/tx3904sio@0xfffff400 > int sio1 /tx3904irc");
506
507 /* add PAL timer & I/O module */
508 if(! strcmp(board, BOARD_JMR3904_PAL))
509 {
510 /* the device */
511 sim_hw_parse (sd, "/pal@0xffff0000");
512 sim_hw_parse (sd, "/pal@0xffff0000/reg 0xffff0000 64");
513
514 /* wire up interrupt ports to irc */
515 sim_hw_parse (sd, "/pal@0x31000000 > countdown tmr0 /tx3904irc");
516 sim_hw_parse (sd, "/pal@0x31000000 > timer tmr1 /tx3904irc");
517 sim_hw_parse (sd, "/pal@0x31000000 > int int0 /tx3904irc");
518 }
519
520 if(! strcmp(board, BOARD_JMR3904_DEBUG))
521 {
522 /* -- DEBUG: glue interrupt generators --- */
523 sim_hw_parse (sd, "/glue@0xffff0000/reg 0xffff0000 0x50");
524 sim_hw_parse (sd, "/glue@0xffff0000 > int0 int0 /tx3904irc");
525 sim_hw_parse (sd, "/glue@0xffff0000 > int1 int1 /tx3904irc");
526 sim_hw_parse (sd, "/glue@0xffff0000 > int2 int2 /tx3904irc");
527 sim_hw_parse (sd, "/glue@0xffff0000 > int3 int3 /tx3904irc");
528 sim_hw_parse (sd, "/glue@0xffff0000 > int4 int4 /tx3904irc");
529 sim_hw_parse (sd, "/glue@0xffff0000 > int5 int5 /tx3904irc");
530 sim_hw_parse (sd, "/glue@0xffff0000 > int6 int6 /tx3904irc");
531 sim_hw_parse (sd, "/glue@0xffff0000 > int7 int7 /tx3904irc");
532 sim_hw_parse (sd, "/glue@0xffff0000 > int8 dmac0 /tx3904irc");
533 sim_hw_parse (sd, "/glue@0xffff0000 > int9 dmac1 /tx3904irc");
534 sim_hw_parse (sd, "/glue@0xffff0000 > int10 dmac2 /tx3904irc");
535 sim_hw_parse (sd, "/glue@0xffff0000 > int11 dmac3 /tx3904irc");
536 sim_hw_parse (sd, "/glue@0xffff0000 > int12 sio0 /tx3904irc");
537 sim_hw_parse (sd, "/glue@0xffff0000 > int13 sio1 /tx3904irc");
538 sim_hw_parse (sd, "/glue@0xffff0000 > int14 tmr0 /tx3904irc");
539 sim_hw_parse (sd, "/glue@0xffff0000 > int15 tmr1 /tx3904irc");
540 sim_hw_parse (sd, "/glue@0xffff0000 > int16 tmr2 /tx3904irc");
541 sim_hw_parse (sd, "/glue@0xffff0000 > int17 nmi /tx3904cpu");
542 }
543
544 device_init(sd);
545 }
546 #endif
547 /* end-sanitize-tx3904 */
548
549
550 /* check for/establish the a reference program image */
551 if (sim_analyze_program (sd,
552 (STATE_PROG_ARGV (sd) != NULL
553 ? *STATE_PROG_ARGV (sd)
554 : NULL),
555 abfd) != SIM_RC_OK)
556 {
557 sim_module_uninstall (sd);
558 return 0;
559 }
560
561 /* Configure/verify the target byte order and other runtime
562 configuration options */
563 if (sim_config (sd) != SIM_RC_OK)
564 {
565 sim_module_uninstall (sd);
566 return 0;
567 }
568
569 if (sim_post_argv_init (sd) != SIM_RC_OK)
570 {
571 /* Uninstall the modules to avoid memory leaks,
572 file descriptor leaks, etc. */
573 sim_module_uninstall (sd);
574 return 0;
575 }
576
577 /* verify assumptions the simulator made about the host type system.
578 This macro does not return if there is a problem */
579 SIM_ASSERT (sizeof(int) == (4 * sizeof(char)));
580 SIM_ASSERT (sizeof(word64) == (8 * sizeof(char)));
581
582 /* This is NASTY, in that we are assuming the size of specific
583 registers: */
584 {
585 int rn;
586 for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++)
587 {
588 if (rn < 32)
589 cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
590 else if ((rn >= FGRIDX) && (rn < (FGRIDX + NR_FGR)))
591 cpu->register_widths[rn] = WITH_TARGET_FLOATING_POINT_BITSIZE;
592 else if ((rn >= 33) && (rn <= 37))
593 cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
594 else if ((rn == SRIDX)
595 || (rn == FCR0IDX)
596 || (rn == FCR31IDX)
597 || ((rn >= 72) && (rn <= 89)))
598 cpu->register_widths[rn] = 32;
599 else
600 cpu->register_widths[rn] = 0;
601 }
602
603 /* start-sanitize-r5900 */
604 /* set the 5900 "upper" registers to 64 bits */
605 for( rn = LAST_EMBED_REGNUM+1; rn < FIRST_COP0_REG; rn++)
606 cpu->register_widths[rn] = 64;
607
608 for( rn = FIRST_COP0_REG; rn < NUM_REGS; rn++)
609 cpu->register_widths[rn] = 32;
610 /* end-sanitize-r5900 */
611
612 /* start-sanitize-sky */
613 #ifdef TARGET_SKY
614 /* Now the VU registers */
615 for( rn = 0; rn < NUM_VU_INTEGER_REGS; rn++ ) {
616 cpu->register_widths[rn + NUM_CORE_REGS] = 16;
617 cpu->register_widths[rn + NUM_CORE_REGS + NUM_VU_REGS] = 16;
618 }
619
620 for( rn = NUM_VU_INTEGER_REGS; rn < NUM_VU_REGS; rn++ ) {
621 cpu->register_widths[rn + NUM_CORE_REGS] = 32;
622 cpu->register_widths[rn + NUM_CORE_REGS + NUM_VU_REGS] = 32;
623 }
624
625 /* Finally the VIF registers */
626 for( rn = 2*NUM_VU_REGS; rn < 2*NUM_VU_REGS + 2*NUM_VIF_REGS; rn++ )
627 cpu->register_widths[rn + NUM_CORE_REGS] = 32;
628
629 cpu->cur_device = 0;
630 #endif
631 /* end-sanitize-sky */
632 }
633
634 #if defined(TRACE)
635 if (STATE & simTRACE)
636 open_trace(sd);
637 #endif /* TRACE */
638
639 /* Write an abort sequence into the TRAP (common) exception vector
640 addresses. This is to catch code executing a TRAP (et.al.)
641 instruction without installing a trap handler. */
642 {
643 unsigned32 halt[2] = { 0x2404002f /* addiu r4, r0, 47 */,
644 HALT_INSTRUCTION /* BREAK */ };
645 H2T (halt[0]);
646 H2T (halt[1]);
647 sim_write (sd, 0x80000000, (char *) halt, sizeof (halt));
648 sim_write (sd, 0x80000180, (char *) halt, sizeof (halt));
649 sim_write (sd, 0x80000200, (char *) halt, sizeof (halt));
650 sim_write (sd, 0xBFC00200, (char *) halt, sizeof (halt));
651 sim_write (sd, 0xBFC00380, (char *) halt, sizeof (halt));
652 sim_write (sd, 0xBFC00400, (char *) halt, sizeof (halt));
653 }
654
655
656 /* Write the monitor trap address handlers into the monitor (eeprom)
657 address space. This can only be done once the target endianness
658 has been determined. */
659 {
660 unsigned loop;
661 /* Entry into the IDT monitor is via fixed address vectors, and
662 not using machine instructions. To avoid clashing with use of
663 the MIPS TRAP system, we place our own (simulator specific)
664 "undefined" instructions into the relevant vector slots. */
665 for (loop = 0; (loop < MONITOR_SIZE); loop += 4)
666 {
667 address_word vaddr = (MONITOR_BASE + loop);
668 unsigned32 insn = (RSVD_INSTRUCTION | (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) << RSVD_INSTRUCTION_ARG_SHIFT));
669 H2T (insn);
670 sim_write (sd, vaddr, (char *)&insn, sizeof (insn));
671 }
672 /* The PMON monitor uses the same address space, but rather than
673 branching into it the address of a routine is loaded. We can
674 cheat for the moment, and direct the PMON routine to IDT style
675 instructions within the monitor space. This relies on the IDT
676 monitor not using the locations from 0xBFC00500 onwards as its
677 entry points.*/
678 for (loop = 0; (loop < 24); loop++)
679 {
680 address_word vaddr = (MONITOR_BASE + 0x500 + (loop * 4));
681 unsigned32 value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
682 switch (loop)
683 {
684 case 0: /* read */
685 value = 7;
686 break;
687 case 1: /* write */
688 value = 8;
689 break;
690 case 2: /* open */
691 value = 6;
692 break;
693 case 3: /* close */
694 value = 10;
695 break;
696 case 5: /* printf */
697 value = ((0x500 - 16) / 8); /* not an IDT reason code */
698 break;
699 case 8: /* cliexit */
700 value = 17;
701 break;
702 case 11: /* flush_cache */
703 value = 28;
704 break;
705 }
706 /* FIXME - should monitor_base be SIM_ADDR?? */
707 value = ((unsigned int)MONITOR_BASE + (value * 8));
708 H2T (value);
709 sim_write (sd, vaddr, (char *)&value, sizeof (value));
710
711 /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */
712 vaddr -= 0x300;
713 sim_write (sd, vaddr, (char *)&value, sizeof (value));
714 }
715 }
716
717
718 /* start-sanitize-sky */
719 #ifdef TARGET_SKY
720 /* Default TLB initialization... */
721
722 #define KPAGEMASK 0x001fe000
723 #define PAGE_MASK_4K 0x00000000
724 #define PAGE_MASK_16K 0x00006000
725 #define PAGE_MASK_64K 0x0001e000
726 #define PAGE_MASK_256K 0x0007e000
727 #define PAGE_MASK_1M 0x001fe000
728 #define PAGE_MASK_4M 0x007fe000
729 #define PAGE_MASK_16M 0x01ffe000
730
731 #define SET_TLB(index, page_mask, entry_hi, entry_lo0, entry_lo1) \
732 TLB[index].mask = page_mask; \
733 TLB[index].hi = entry_hi; \
734 TLB[index].lo0 = entry_lo0; \
735 TLB[index].lo1 = entry_lo1
736
737 SET_TLB(0, PAGE_MASK_16M, 0x00000000, 0x0000001e, 0x0004001e);/*0-32M*/
738
739 #endif /* TARGET_SKY */
740 /* end-sanitize-sky */
741
742 return sd;
743 }
744
745 #if defined(TRACE)
746 static void
747 open_trace(sd)
748 SIM_DESC sd;
749 {
750 tracefh = fopen(tracefile,"wb+");
751 if (tracefh == NULL)
752 {
753 sim_io_eprintf(sd,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile);
754 tracefh = stderr;
755 }
756 }
757 #endif /* TRACE */
758
759 #if WITH_IGEN
760 /* Return name of an insn, used by insn profiling. */
761 static const char *
762 get_insn_name (sim_cpu *cpu, int i)
763 {
764 return itable[i].name;
765 }
766 #endif
767
768 void
769 sim_close (sd, quitting)
770 SIM_DESC sd;
771 int quitting;
772 {
773 #ifdef DEBUG
774 printf("DBG: sim_close: entered (quitting = %d)\n",quitting);
775 #endif
776
777 /* start-sanitize-sky */
778 #ifdef TARGET_SKY
779 sky_command_options_close (sd);
780 #endif
781 /* end-sanitize-sky */
782
783
784 /* "quitting" is non-zero if we cannot hang on errors */
785
786 /* Ensure that any resources allocated through the callback
787 mechanism are released: */
788 sim_io_shutdown (sd);
789
790 #if defined(TRACE)
791 if (tracefh != NULL && tracefh != stderr)
792 fclose(tracefh);
793 tracefh = NULL;
794 #endif /* TRACE */
795
796 /* FIXME - free SD */
797
798 return;
799 }
800
801
802 int
803 sim_write (sd,addr,buffer,size)
804 SIM_DESC sd;
805 SIM_ADDR addr;
806 unsigned char *buffer;
807 int size;
808 {
809 int index;
810 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
811
812 /* Return the number of bytes written, or zero if error. */
813 #ifdef DEBUG
814 sim_io_printf(sd,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr),size);
815 #endif
816
817 /* We use raw read and write routines, since we do not want to count
818 the GDB memory accesses in our statistics gathering. */
819
820 for (index = 0; index < size; index++)
821 {
822 address_word vaddr = (address_word)addr + index;
823 address_word paddr;
824 int cca;
825 if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isSTORE, &paddr, &cca, isRAW))
826 break;
827 if (sim_core_write_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
828 break;
829 }
830
831 return(index);
832 }
833
834 int
835 sim_read (sd,addr,buffer,size)
836 SIM_DESC sd;
837 SIM_ADDR addr;
838 unsigned char *buffer;
839 int size;
840 {
841 int index;
842 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
843
844 /* Return the number of bytes read, or zero if error. */
845 #ifdef DEBUG
846 sim_io_printf(sd,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr),size);
847 #endif /* DEBUG */
848
849 for (index = 0; (index < size); index++)
850 {
851 address_word vaddr = (address_word)addr + index;
852 address_word paddr;
853 int cca;
854 if (!address_translation (SD, CPU, NULL_CIA, vaddr, isDATA, isLOAD, &paddr, &cca, isRAW))
855 break;
856 if (sim_core_read_buffer (SD, CPU, read_map, buffer + index, paddr, 1) != 1)
857 break;
858 }
859
860 return(index);
861 }
862
863 int
864 sim_store_register (sd,rn,memory,length)
865 SIM_DESC sd;
866 int rn;
867 unsigned char *memory;
868 int length;
869 {
870 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
871 /* NOTE: gdb (the client) stores registers in target byte order
872 while the simulator uses host byte order */
873 #ifdef DEBUG
874 sim_io_printf(sd,"sim_store_register(%d,*memory=0x%s);\n",rn,pr_addr(*((SIM_ADDR *)memory)));
875 #endif /* DEBUG */
876
877 /* Unfortunately this suffers from the same problem as the register
878 numbering one. We need to know what the width of each logical
879 register number is for the architecture being simulated. */
880
881 if (cpu->register_widths[rn] == 0)
882 {
883 sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn);
884 return 0;
885 }
886
887 /* start-sanitize-r5900 */
888 if (rn >= 90 && rn < 90 + 32)
889 {
890 GPR1[rn - 90] = T2H_8 (*(unsigned64*)memory);
891 return 8;
892 }
893 switch (rn)
894 {
895 case REGISTER_SA:
896 SA = T2H_8(*(unsigned64*)memory);
897 return 8;
898 case 122: /* FIXME */
899 LO1 = T2H_8(*(unsigned64*)memory);
900 return 8;
901 case 123: /* FIXME */
902 HI1 = T2H_8(*(unsigned64*)memory);
903 return 8;
904 }
905
906 if (rn >= FIRST_COP0_REG && rn < (FIRST_COP0_REG+NUM_COP0_REGS))
907 {
908 switch (rn - FIRST_COP0_REG)
909 {
910 case 12: /* Status */
911 case 13: /* Cause */
912 return -1; /* Already done in regular register set */
913 case 14:
914 EPC = T2H_4(*((unsigned32*) memory));
915 break;
916 case 16:
917 C0_CONFIG = T2H_4(*((unsigned32*) memory));
918 break;
919 case 17: /* Debug */
920 Debug = T2H_4(*((unsigned32*) memory));
921 break;
922 case 18: /* Perf */
923 COP0_GPR[rn - FIRST_COP0_REG + 7] = T2H_4(*((unsigned32*) memory));
924 break;
925 case 19: /* TagLo */
926 case 20: /* TagHi */
927 case 21: /* ErrorEPC */
928 COP0_GPR[rn - FIRST_COP0_REG + 9] = T2H_4(*((unsigned32*) memory));
929 break;
930 default:
931 COP0_GPR[rn - FIRST_COP0_REG] = T2H_4(*((unsigned32*) memory));
932 break;
933 }
934
935 return 4;
936 }
937 /* end-sanitize-r5900 */
938
939 /* start-sanitize-sky */
940 #ifdef TARGET_SKY
941 if (rn >= NUM_CORE_REGS)
942 {
943 rn = rn - NUM_CORE_REGS;
944
945 if( rn < NUM_VU_REGS )
946 {
947 #ifdef TARGET_SKY_B
948 sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
949 return 0;
950 #else
951 if (rn < NUM_VU_INTEGER_REGS)
952 return write_vu_int_reg (&(vu0_device.regs), rn, memory);
953 else if (rn >= FIRST_VEC_REG)
954 {
955 rn -= FIRST_VEC_REG;
956 return write_vu_vec_reg (&(vu0_device.regs), rn>>2, rn&3,
957 memory);
958 }
959 else switch (rn - NUM_VU_INTEGER_REGS)
960 {
961 case 0:
962 return write_vu_special_reg (&vu0_device, VU_REG_CIA, memory);
963
964 case 1: /* Can't write TPC register */
965 case 2: /* or VPU_STAT */
966 case 4: /* or MAC */
967 case 9: /* VU0 has no P register */
968 return 4;
969
970 case 3:
971 return write_vu_misc_reg(&(vu0_device.regs), VU_REG_MST, memory);
972 case 5:
973 return write_vu_misc_reg(&(vu0_device.regs), VU_REG_MCP, memory);
974 case 6:
975 return write_vu_special_reg (&vu0_device, VU_REG_CMSAR0, memory);
976 case 7:
977 return write_vu_special_reg (&vu0_device, VU_REG_FBRST, memory);
978 case 8:
979 return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MR, memory);
980 case 10:
981 return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MI, memory);
982 case 11:
983 return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ, memory);
984 default:
985 return write_vu_acc_reg (&(vu0_device.regs),
986 rn - (NUM_VU_INTEGER_REGS + 12),
987 memory);
988 }
989 #endif /* ! TARGET_SKY_B */
990 }
991
992 rn = rn - NUM_VU_REGS;
993
994 if (rn < NUM_VU_REGS)
995 {
996 if (rn < NUM_VU_INTEGER_REGS)
997 return write_vu_int_reg (&(vu1_device.regs), rn, memory);
998 else if (rn >= FIRST_VEC_REG)
999 {
1000 rn -= FIRST_VEC_REG;
1001 return write_vu_vec_reg (&(vu1_device.regs),
1002 rn >> 2, rn & 3, memory);
1003 }
1004 else switch (rn - NUM_VU_INTEGER_REGS)
1005 {
1006 case 0:
1007 return write_vu_special_reg (&vu1_device, VU_REG_CIA, memory);
1008
1009 case 1: /* Can't write TPC register */
1010 case 2: /* or VPU_STAT */
1011 case 4: /* or MAC */
1012 case 7: /* VU1 has no FBRST register */
1013 return 4;
1014
1015 case 3:
1016 return write_vu_misc_reg(&(vu1_device.regs), VU_REG_MST, memory);
1017 case 5:
1018 return write_vu_misc_reg(&(vu1_device.regs), VU_REG_MCP, memory);
1019 case 6: /* CMSAR1 is actually part of VU0 */
1020 #ifdef TARGET_SKY_B
1021 return 0;
1022 #else
1023 return write_vu_special_reg (&vu0_device, VU_REG_CMSAR1, memory);
1024 #endif /* ! TARGET_SKY_B */
1025 case 8:
1026 return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MR, memory);
1027 case 9:
1028 return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MP, memory);
1029 case 10:
1030 return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MI, memory);
1031 case 11:
1032 return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MQ, memory);
1033 default:
1034 return write_vu_acc_reg (&(vu1_device.regs),
1035 rn - (NUM_VU_INTEGER_REGS + 12),
1036 memory);
1037 }
1038 }
1039
1040 rn -= NUM_VU_REGS; /* VIF0 registers are next */
1041
1042 if (rn < NUM_VIF_REGS)
1043 {
1044 #ifdef TARGET_SKY_B
1045 sim_io_eprintf( sd, "Invalid VIF register (register store ignored)\n" );
1046 return 0;
1047 #else
1048 if (rn < NUM_VIF_REGS-1)
1049 return write_vif_reg (&vif0_device, rn, memory);
1050 else
1051 {
1052 sim_io_eprintf( sd, "Can't write vif0_pc (store ignored)\n" );
1053 return 0;
1054 }
1055 #endif /* ! TARGET_SKY_B */
1056 }
1057
1058 rn -= NUM_VIF_REGS; /* VIF1 registers are last */
1059
1060 if (rn < NUM_VIF_REGS)
1061 {
1062 if (rn < NUM_VIF_REGS-1)
1063 return write_vif_reg (&vif1_device, rn, memory);
1064 else
1065 {
1066 sim_io_eprintf( sd, "Can't write vif1_pc (store ignored)\n" );
1067 return 0;
1068 }
1069 }
1070
1071 sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" );
1072 return 0;
1073 }
1074 #endif
1075 /* end-sanitize-sky */
1076
1077 if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
1078 {
1079 if (cpu->register_widths[rn] == 32)
1080 {
1081 cpu->fgr[rn - FGRIDX] = T2H_4 (*(unsigned32*)memory);
1082 return 4;
1083 }
1084 else
1085 {
1086 cpu->fgr[rn - FGRIDX] = T2H_8 (*(unsigned64*)memory);
1087 return 8;
1088 }
1089 }
1090
1091 if (cpu->register_widths[rn] == 32)
1092 {
1093 cpu->registers[rn] = T2H_4 (*(unsigned32*)memory);
1094 return 4;
1095 }
1096 else
1097 {
1098 cpu->registers[rn] = T2H_8 (*(unsigned64*)memory);
1099 return 8;
1100 }
1101
1102 return 0;
1103 }
1104
1105 int
1106 sim_fetch_register (sd,rn,memory,length)
1107 SIM_DESC sd;
1108 int rn;
1109 unsigned char *memory;
1110 int length;
1111 {
1112 sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME */
1113 /* NOTE: gdb (the client) stores registers in target byte order
1114 while the simulator uses host byte order */
1115 #ifdef DEBUG
1116 sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn]));
1117 #endif /* DEBUG */
1118
1119 if (cpu->register_widths[rn] == 0)
1120 {
1121 sim_io_eprintf (sd, "Invalid register width for %d (register fetch ignored)\n",rn);
1122 return 0;
1123 }
1124
1125 /* start-sanitize-r5900 */
1126 if (rn >= 90 && rn < 90 + 32)
1127 {
1128 *((unsigned64*)memory) = H2T_8 (GPR1[rn - 90]);
1129 return 8;
1130 }
1131 switch (rn)
1132 {
1133 case REGISTER_SA:
1134 *((unsigned64*)memory) = H2T_8(SA);
1135 return 8;
1136 case 122: /* FIXME */
1137 *((unsigned64*)memory) = H2T_8(LO1);
1138 return 8;
1139 case 123: /* FIXME */
1140 *((unsigned64*)memory) = H2T_8(HI1);
1141 return 8;
1142 }
1143
1144 if (rn >= FIRST_COP0_REG && rn < (FIRST_COP0_REG+NUM_COP0_REGS))
1145 {
1146 switch (rn - FIRST_COP0_REG)
1147 {
1148 case 12: /* Status */
1149 case 13: /* Cause */
1150 return -1; /* Already done in regular register set */
1151 case 14:
1152 *((unsigned32*) memory) = H2T_4(EPC);
1153 break;
1154 case 16:
1155 *((unsigned32*) memory) = H2T_4(C0_CONFIG);
1156 break;
1157 case 17: /* Debug */
1158 *((unsigned32*) memory) = H2T_4(Debug);
1159 break;
1160 case 18: /* Perf */
1161 *((unsigned32*) memory) = H2T_4(COP0_GPR[rn - FIRST_COP0_REG + 7]);
1162 break;
1163 case 19: /* TagLo */
1164 case 20: /* TagHi */
1165 case 21: /* ErrorEPC */
1166 *((unsigned32*) memory) = H2T_4(COP0_GPR[rn - FIRST_COP0_REG + 9]);
1167 break;
1168 default:
1169 *((unsigned32*) memory) = H2T_4(COP0_GPR[rn - FIRST_COP0_REG]);
1170 break;
1171 }
1172
1173 return 4;
1174 }
1175 /* end-sanitize-r5900 */
1176
1177 /* start-sanitize-sky */
1178 #ifdef TARGET_SKY
1179 if (rn >= NUM_CORE_REGS)
1180 {
1181 rn = rn - NUM_CORE_REGS;
1182
1183 if (rn < NUM_VU_REGS)
1184 {
1185 #ifdef TARGET_SKY_B
1186 sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
1187 return 0;
1188 #else
1189 if (rn < NUM_VU_INTEGER_REGS)
1190 return read_vu_int_reg (&(vu0_device.regs), rn, memory);
1191 else if (rn >= FIRST_VEC_REG)
1192 {
1193 rn -= FIRST_VEC_REG;
1194 return read_vu_vec_reg (&(vu0_device.regs), rn>>2, rn & 3,
1195 memory);
1196 }
1197 else switch (rn - NUM_VU_INTEGER_REGS)
1198 {
1199 case 0:
1200 return read_vu_special_reg (&vu0_device, VU_REG_CIA, memory);
1201 case 1:
1202 return read_vu_misc_reg(&(vu0_device.regs), VU_REG_MTPC, memory);
1203 case 2:
1204 return read_vu_special_reg (&vu0_device, VU_REG_STAT, memory);
1205 case 3:
1206 return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MST, memory);
1207 case 4:
1208 return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MMC, memory);
1209 case 5:
1210 return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MCP, memory);
1211 case 6:
1212 return read_vu_special_reg (&vu0_device, VU_REG_CMSAR0, memory);
1213 case 7:
1214 return read_vu_special_reg (&vu0_device, VU_REG_FBRST, memory);
1215 case 8:
1216 return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MR, memory);
1217 case 9: /* VU0 has no P register */
1218 *((int *) memory) = 0;
1219 return 4;
1220 case 10:
1221 return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MI, memory);
1222 case 11:
1223 return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ, memory);
1224 default:
1225 return read_vu_acc_reg (&(vu0_device.regs),
1226 rn - (NUM_VU_INTEGER_REGS + 12),
1227 memory);
1228 }
1229 #endif /* ! TARGET_SKY_B */
1230 }
1231
1232 rn -= NUM_VU_REGS; /* VU1 registers are next */
1233
1234 if (rn < NUM_VU_REGS)
1235 {
1236 if (rn < NUM_VU_INTEGER_REGS)
1237 return read_vu_int_reg (&(vu1_device.regs), rn, memory);
1238 else if (rn >= FIRST_VEC_REG)
1239 {
1240 rn -= FIRST_VEC_REG;
1241 return read_vu_vec_reg (&(vu1_device.regs),
1242 rn >> 2, rn & 3, memory);
1243 }
1244 else switch (rn - NUM_VU_INTEGER_REGS)
1245 {
1246 case 0:
1247 return read_vu_special_reg (&vu1_device, VU_REG_CIA, memory);
1248 case 1:
1249 return read_vu_misc_reg(&(vu1_device.regs), VU_REG_MTPC, memory);
1250 case 2:
1251 return read_vu_special_reg (&vu1_device, VU_REG_STAT, memory);
1252 case 3:
1253 return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MST, memory);
1254 case 4:
1255 return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MMC, memory);
1256 case 5:
1257 return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MCP, memory);
1258 case 6: /* CMSAR1 is actually from VU0 */
1259 #ifdef TARGET_SKY_B
1260 return 0;
1261 #else
1262 return read_vu_special_reg (&vu0_device, VU_REG_CMSAR1, memory);
1263 #endif /* ! TARGET_SKY_B */
1264 case 7: /* VU1 has no FBRST register */
1265 *((int *) memory) = 0;
1266 return 4;
1267 case 8:
1268 return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MR, memory);
1269 case 9:
1270 return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MP, memory);
1271 case 10:
1272 return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MI, memory);
1273 case 11:
1274 return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MQ, memory);
1275 default:
1276 return read_vu_acc_reg (&(vu1_device.regs),
1277 rn - (NUM_VU_INTEGER_REGS + 12),
1278 memory);
1279 }
1280 }
1281
1282 rn -= NUM_VU_REGS; /* VIF0 registers are next */
1283
1284 if (rn < NUM_VIF_REGS)
1285 {
1286 #ifdef TARGET_SKY_B
1287 sim_io_eprintf( sd, "Invalid VIF register (register fetch ignored)\n" );
1288 return 0;
1289 #else
1290 if (rn < NUM_VIF_REGS-2)
1291 return read_vif_reg (&vif0_device, rn, memory);
1292 else if (rn == NUM_VIF_REGS-2)
1293 return read_vif_pc (&vif0_device, memory);
1294 else
1295 return read_vif_pcx (&vif0_device, memory);
1296 #endif /* ! TARGET_SKY_B */
1297 }
1298
1299 rn -= NUM_VIF_REGS; /* VIF1 registers are last */
1300
1301 if (rn < NUM_VIF_REGS)
1302 {
1303 if (rn < NUM_VIF_REGS-2)
1304 return read_vif_reg (&vif1_device, rn, memory);
1305 else if (rn == NUM_VIF_REGS-2)
1306 return read_vif_pc (&vif1_device, memory);
1307 else
1308 return read_vif_pcx (&vif1_device, memory);
1309 }
1310
1311 sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" );
1312 }
1313 #endif
1314 /* end-sanitize-sky */
1315
1316 /* Any floating point register */
1317 if (rn >= FGRIDX && rn < FGRIDX + NR_FGR)
1318 {
1319 if (cpu->register_widths[rn] == 32)
1320 {
1321 *(unsigned32*)memory = H2T_4 (cpu->fgr[rn - FGRIDX]);
1322 return 4;
1323 }
1324 else
1325 {
1326 *(unsigned64*)memory = H2T_8 (cpu->fgr[rn - FGRIDX]);
1327 return 8;
1328 }
1329 }
1330
1331 if (cpu->register_widths[rn] == 32)
1332 {
1333 *(unsigned32*)memory = H2T_4 ((unsigned32)(cpu->registers[rn]));
1334 return 4;
1335 }
1336 else
1337 {
1338 *(unsigned64*)memory = H2T_8 ((unsigned64)(cpu->registers[rn]));
1339 return 8;
1340 }
1341
1342 return 0;
1343 }
1344
1345
1346 SIM_RC
1347 sim_create_inferior (sd, abfd, argv,env)
1348 SIM_DESC sd;
1349 struct _bfd *abfd;
1350 char **argv;
1351 char **env;
1352 {
1353
1354 #ifdef DEBUG
1355 printf("DBG: sim_create_inferior entered: start_address = 0x%s\n",
1356 pr_addr(PC));
1357 #endif /* DEBUG */
1358
1359 ColdReset(sd);
1360
1361 if (abfd != NULL)
1362 {
1363 /* override PC value set by ColdReset () */
1364 int cpu_nr;
1365 for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
1366 {
1367 sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
1368 CIA_SET (cpu, (unsigned64) bfd_get_start_address (abfd));
1369 }
1370 }
1371
1372 #if 0 /* def DEBUG */
1373 if (argv || env)
1374 {
1375 /* We should really place the argv slot values into the argument
1376 registers, and onto the stack as required. However, this
1377 assumes that we have a stack defined, which is not
1378 necessarily true at the moment. */
1379 char **cptr;
1380 sim_io_printf(sd,"sim_create_inferior() : passed arguments ignored\n");
1381 for (cptr = argv; (cptr && *cptr); cptr++)
1382 printf("DBG: arg \"%s\"\n",*cptr);
1383 }
1384 #endif /* DEBUG */
1385
1386 return SIM_RC_OK;
1387 }
1388
1389 void
1390 sim_do_command (sd,cmd)
1391 SIM_DESC sd;
1392 char *cmd;
1393 {
1394 if (sim_args_command (sd, cmd) != SIM_RC_OK)
1395 sim_io_printf (sd, "Error: \"%s\" is not a valid MIPS simulator command.\n",
1396 cmd);
1397 }
1398
1399 /*---------------------------------------------------------------------------*/
1400 /*-- Private simulator support interface ------------------------------------*/
1401 /*---------------------------------------------------------------------------*/
1402
1403 /* Read a null terminated string from memory, return in a buffer */
1404 static char *
1405 fetch_str (SIM_DESC sd,
1406 address_word addr)
1407 {
1408 char *buf;
1409 int nr = 0;
1410 char null;
1411 while (sim_read (sd, addr + nr, &null, 1) == 1 && null != 0)
1412 nr++;
1413 buf = NZALLOC (char, nr + 1);
1414 sim_read (sd, addr, buf, nr);
1415 return buf;
1416 }
1417
1418 /* Simple monitor interface (currently setup for the IDT and PMON monitors) */
1419 static void
1420 sim_monitor (SIM_DESC sd,
1421 sim_cpu *cpu,
1422 address_word cia,
1423 unsigned int reason)
1424 {
1425 #ifdef DEBUG
1426 printf("DBG: sim_monitor: entered (reason = %d)\n",reason);
1427 #endif /* DEBUG */
1428
1429 /* The IDT monitor actually allows two instructions per vector
1430 slot. However, the simulator currently causes a trap on each
1431 individual instruction. We cheat, and lose the bottom bit. */
1432 reason >>= 1;
1433
1434 /* The following callback functions are available, however the
1435 monitor we are simulating does not make use of them: get_errno,
1436 isatty, lseek, rename, system, time and unlink */
1437 switch (reason)
1438 {
1439
1440 case 6: /* int open(char *path,int flags) */
1441 {
1442 char *path = fetch_str (sd, A0);
1443 V0 = sim_io_open (sd, path, (int)A1);
1444 zfree (path);
1445 break;
1446 }
1447
1448 case 7: /* int read(int file,char *ptr,int len) */
1449 {
1450 int fd = A0;
1451 int nr = A2;
1452 char *buf = zalloc (nr);
1453 V0 = sim_io_read (sd, fd, buf, nr);
1454 sim_write (sd, A1, buf, nr);
1455 zfree (buf);
1456 }
1457 break;
1458
1459 case 8: /* int write(int file,char *ptr,int len) */
1460 {
1461 int fd = A0;
1462 int nr = A2;
1463 char *buf = zalloc (nr);
1464 sim_read (sd, A1, buf, nr);
1465 V0 = sim_io_write (sd, fd, buf, nr);
1466 zfree (buf);
1467 break;
1468 }
1469
1470 case 10: /* int close(int file) */
1471 {
1472 V0 = sim_io_close (sd, (int)A0);
1473 break;
1474 }
1475
1476 case 2: /* Densan monitor: char inbyte(int waitflag) */
1477 {
1478 if (A0 == 0) /* waitflag == NOWAIT */
1479 V0 = (unsigned_word)-1;
1480 }
1481 /* Drop through to case 11 */
1482
1483 case 11: /* char inbyte(void) */
1484 {
1485 char tmp;
1486 if (sim_io_read_stdin (sd, &tmp, sizeof(char)) != sizeof(char))
1487 {
1488 sim_io_error(sd,"Invalid return from character read");
1489 V0 = (unsigned_word)-1;
1490 }
1491 else
1492 V0 = (unsigned_word)tmp;
1493 break;
1494 }
1495
1496 case 3: /* Densan monitor: void co(char chr) */
1497 case 12: /* void outbyte(char chr) : write a byte to "stdout" */
1498 {
1499 char tmp = (char)(A0 & 0xFF);
1500 sim_io_write_stdout (sd, &tmp, sizeof(char));
1501 break;
1502 }
1503
1504 case 17: /* void _exit() */
1505 {
1506 sim_io_eprintf (sd, "sim_monitor(17): _exit(int reason) to be coded\n");
1507 sim_engine_halt (SD, CPU, NULL, NULL_CIA, sim_exited,
1508 (unsigned int)(A0 & 0xFFFFFFFF));
1509 break;
1510 }
1511
1512 case 28 : /* PMON flush_cache */
1513 break;
1514
1515 case 55: /* void get_mem_info(unsigned int *ptr) */
1516 /* in: A0 = pointer to three word memory location */
1517 /* out: [A0 + 0] = size */
1518 /* [A0 + 4] = instruction cache size */
1519 /* [A0 + 8] = data cache size */
1520 {
1521 unsigned_4 value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
1522 unsigned_4 zero = 0;
1523 H2T (value);
1524 sim_write (sd, A0 + 0, (char *)&value, 4);
1525 sim_write (sd, A0 + 4, (char *)&zero, 4);
1526 sim_write (sd, A0 + 8, (char *)&zero, 4);
1527 /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
1528 break;
1529 }
1530
1531 case 158 : /* PMON printf */
1532 /* in: A0 = pointer to format string */
1533 /* A1 = optional argument 1 */
1534 /* A2 = optional argument 2 */
1535 /* A3 = optional argument 3 */
1536 /* out: void */
1537 /* The following is based on the PMON printf source */
1538 {
1539 address_word s = A0;
1540 char c;
1541 signed_word *ap = &A1; /* 1st argument */
1542 /* This isn't the quickest way, since we call the host print
1543 routine for every character almost. But it does avoid
1544 having to allocate and manage a temporary string buffer. */
1545 /* TODO: Include check that we only use three arguments (A1,
1546 A2 and A3) */
1547 while (sim_read (sd, s++, &c, 1) && c != '\0')
1548 {
1549 if (c == '%')
1550 {
1551 char tmp[40];
1552 enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST;
1553 int width = 0, trunc = 0, haddot = 0, longlong = 0;
1554 while (sim_read (sd, s++, &c, 1) && c != '\0')
1555 {
1556 if (strchr ("dobxXulscefg%", c))
1557 break;
1558 else if (c == '-')
1559 fmt = FMT_LJUST;
1560 else if (c == '0')
1561 fmt = FMT_RJUST0;
1562 else if (c == '~')
1563 fmt = FMT_CENTER;
1564 else if (c == '*')
1565 {
1566 if (haddot)
1567 trunc = (int)*ap++;
1568 else
1569 width = (int)*ap++;
1570 }
1571 else if (c >= '1' && c <= '9')
1572 {
1573 address_word t = s;
1574 unsigned int n;
1575 while (sim_read (sd, s++, &c, 1) == 1 && isdigit (c))
1576 tmp[s - t] = c;
1577 tmp[s - t] = '\0';
1578 n = (unsigned int)strtol(tmp,NULL,10);
1579 if (haddot)
1580 trunc = n;
1581 else
1582 width = n;
1583 s--;
1584 }
1585 else if (c == '.')
1586 haddot = 1;
1587 }
1588 switch (c)
1589 {
1590 case '%':
1591 sim_io_printf (sd, "%%");
1592 break;
1593 case 's':
1594 if ((int)*ap != 0)
1595 {
1596 address_word p = *ap++;
1597 char ch;
1598 while (sim_read (sd, p++, &ch, 1) == 1 && ch != '\0')
1599 sim_io_printf(sd, "%c", ch);
1600 }
1601 else
1602 sim_io_printf(sd,"(null)");
1603 break;
1604 case 'c':
1605 sim_io_printf (sd, "%c", (int)*ap++);
1606 break;
1607 default:
1608 if (c == 'l')
1609 {
1610 sim_read (sd, s++, &c, 1);
1611 if (c == 'l')
1612 {
1613 longlong = 1;
1614 sim_read (sd, s++, &c, 1);
1615 }
1616 }
1617 if (strchr ("dobxXu", c))
1618 {
1619 word64 lv = (word64) *ap++;
1620 if (c == 'b')
1621 sim_io_printf(sd,"<binary not supported>");
1622 else
1623 {
1624 sprintf (tmp, "%%%s%c", longlong ? "ll" : "", c);
1625 if (longlong)
1626 sim_io_printf(sd, tmp, lv);
1627 else
1628 sim_io_printf(sd, tmp, (int)lv);
1629 }
1630 }
1631 else if (strchr ("eEfgG", c))
1632 {
1633 double dbl = *(double*)(ap++);
1634 sprintf (tmp, "%%%d.%d%c", width, trunc, c);
1635 sim_io_printf (sd, tmp, dbl);
1636 trunc = 0;
1637 }
1638 }
1639 }
1640 else
1641 sim_io_printf(sd, "%c", c);
1642 }
1643 break;
1644 }
1645
1646 default:
1647 sim_io_error (sd, "TODO: sim_monitor(%d) : PC = 0x%s\n",
1648 reason, pr_addr(cia));
1649 break;
1650 }
1651 return;
1652 }
1653
1654 /* Store a word into memory. */
1655
1656 static void
1657 store_word (SIM_DESC sd,
1658 sim_cpu *cpu,
1659 address_word cia,
1660 uword64 vaddr,
1661 signed_word val)
1662 {
1663 address_word paddr;
1664 int uncached;
1665
1666 if ((vaddr & 3) != 0)
1667 SignalExceptionAddressStore ();
1668 else
1669 {
1670 if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
1671 isTARGET, isREAL))
1672 {
1673 const uword64 mask = 7;
1674 uword64 memval;
1675 unsigned int byte;
1676
1677 paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
1678 byte = (vaddr & mask) ^ (BigEndianCPU << 2);
1679 memval = ((uword64) val) << (8 * byte);
1680 StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr,
1681 isREAL);
1682 }
1683 }
1684 }
1685
1686 /* Load a word from memory. */
1687
1688 static signed_word
1689 load_word (SIM_DESC sd,
1690 sim_cpu *cpu,
1691 address_word cia,
1692 uword64 vaddr)
1693 {
1694 if ((vaddr & 3) != 0)
1695 SignalExceptionAddressLoad ();
1696 else
1697 {
1698 address_word paddr;
1699 int uncached;
1700
1701 if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
1702 isTARGET, isREAL))
1703 {
1704 const uword64 mask = 0x7;
1705 const unsigned int reverse = ReverseEndian ? 1 : 0;
1706 const unsigned int bigend = BigEndianCPU ? 1 : 0;
1707 uword64 memval;
1708 unsigned int byte;
1709
1710 paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
1711 LoadMemory (&memval,NULL,uncached, AccessLength_WORD, paddr, vaddr,
1712 isDATA, isREAL);
1713 byte = (vaddr & mask) ^ (bigend << 2);
1714 return SIGNEXTEND (((memval >> (8 * byte)) & 0xffffffff), 32);
1715 }
1716 }
1717
1718 return 0;
1719 }
1720
1721 /* Simulate the mips16 entry and exit pseudo-instructions. These
1722 would normally be handled by the reserved instruction exception
1723 code, but for ease of simulation we just handle them directly. */
1724
1725 static void
1726 mips16_entry (SIM_DESC sd,
1727 sim_cpu *cpu,
1728 address_word cia,
1729 unsigned int insn)
1730 {
1731 int aregs, sregs, rreg;
1732
1733 #ifdef DEBUG
1734 printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn);
1735 #endif /* DEBUG */
1736
1737 aregs = (insn & 0x700) >> 8;
1738 sregs = (insn & 0x0c0) >> 6;
1739 rreg = (insn & 0x020) >> 5;
1740
1741 /* This should be checked by the caller. */
1742 if (sregs == 3)
1743 abort ();
1744
1745 if (aregs < 5)
1746 {
1747 int i;
1748 signed_word tsp;
1749
1750 /* This is the entry pseudo-instruction. */
1751
1752 for (i = 0; i < aregs; i++)
1753 store_word (SD, CPU, cia, (uword64) (SP + 4 * i), GPR[i + 4]);
1754
1755 tsp = SP;
1756 SP -= 32;
1757
1758 if (rreg)
1759 {
1760 tsp -= 4;
1761 store_word (SD, CPU, cia, (uword64) tsp, RA);
1762 }
1763
1764 for (i = 0; i < sregs; i++)
1765 {
1766 tsp -= 4;
1767 store_word (SD, CPU, cia, (uword64) tsp, GPR[16 + i]);
1768 }
1769 }
1770 else
1771 {
1772 int i;
1773 signed_word tsp;
1774
1775 /* This is the exit pseudo-instruction. */
1776
1777 tsp = SP + 32;
1778
1779 if (rreg)
1780 {
1781 tsp -= 4;
1782 RA = load_word (SD, CPU, cia, (uword64) tsp);
1783 }
1784
1785 for (i = 0; i < sregs; i++)
1786 {
1787 tsp -= 4;
1788 GPR[i + 16] = load_word (SD, CPU, cia, (uword64) tsp);
1789 }
1790
1791 SP += 32;
1792
1793 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
1794 {
1795 if (aregs == 5)
1796 {
1797 FGR[0] = WORD64LO (GPR[4]);
1798 FPR_STATE[0] = fmt_uninterpreted;
1799 }
1800 else if (aregs == 6)
1801 {
1802 FGR[0] = WORD64LO (GPR[5]);
1803 FGR[1] = WORD64LO (GPR[4]);
1804 FPR_STATE[0] = fmt_uninterpreted;
1805 FPR_STATE[1] = fmt_uninterpreted;
1806 }
1807 }
1808
1809 PC = RA;
1810 }
1811
1812 }
1813
1814 /*-- trace support ----------------------------------------------------------*/
1815
1816 /* The TRACE support is provided (if required) in the memory accessing
1817 routines. Since we are also providing the architecture specific
1818 features, the architecture simulation code can also deal with
1819 notifying the TRACE world of cache flushes, etc. Similarly we do
1820 not need to provide profiling support in the simulator engine,
1821 since we can sample in the instruction fetch control loop. By
1822 defining the TRACE manifest, we add tracing as a run-time
1823 option. */
1824
1825 #if defined(TRACE)
1826 /* Tracing by default produces "din" format (as required by
1827 dineroIII). Each line of such a trace file *MUST* have a din label
1828 and address field. The rest of the line is ignored, so comments can
1829 be included if desired. The first field is the label which must be
1830 one of the following values:
1831
1832 0 read data
1833 1 write data
1834 2 instruction fetch
1835 3 escape record (treated as unknown access type)
1836 4 escape record (causes cache flush)
1837
1838 The address field is a 32bit (lower-case) hexadecimal address
1839 value. The address should *NOT* be preceded by "0x".
1840
1841 The size of the memory transfer is not important when dealing with
1842 cache lines (as long as no more than a cache line can be
1843 transferred in a single operation :-), however more information
1844 could be given following the dineroIII requirement to allow more
1845 complete memory and cache simulators to provide better
1846 results. i.e. the University of Pisa has a cache simulator that can
1847 also take bus size and speed as (variable) inputs to calculate
1848 complete system performance (a much more useful ability when trying
1849 to construct an end product, rather than a processor). They
1850 currently have an ARM version of their tool called ChARM. */
1851
1852
1853 void
1854 dotrace (SIM_DESC sd,
1855 sim_cpu *cpu,
1856 FILE *tracefh,
1857 int type,
1858 SIM_ADDR address,
1859 int width,
1860 char *comment,...)
1861 {
1862 if (STATE & simTRACE) {
1863 va_list ap;
1864 fprintf(tracefh,"%d %s ; width %d ; ",
1865 type,
1866 pr_addr(address),
1867 width);
1868 va_start(ap,comment);
1869 vfprintf(tracefh,comment,ap);
1870 va_end(ap);
1871 fprintf(tracefh,"\n");
1872 }
1873 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1874 we may be generating 64bit ones, we should put the hi-32bits of the
1875 address into the comment field. */
1876
1877 /* TODO: Provide a buffer for the trace lines. We can then avoid
1878 performing writes until the buffer is filled, or the file is
1879 being closed. */
1880
1881 /* NOTE: We could consider adding a comment field to the "din" file
1882 produced using type 3 markers (unknown access). This would then
1883 allow information about the program that the "din" is for, and
1884 the MIPs world that was being simulated, to be placed into the
1885 trace file. */
1886
1887 return;
1888 }
1889 #endif /* TRACE */
1890
1891 /*---------------------------------------------------------------------------*/
1892 /*-- simulator engine -------------------------------------------------------*/
1893 /*---------------------------------------------------------------------------*/
1894
1895 static void
1896 ColdReset (SIM_DESC sd)
1897 {
1898 int cpu_nr;
1899 for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
1900 {
1901 sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
1902 /* RESET: Fixed PC address: */
1903 PC = (unsigned_word) UNSIGNED64 (0xFFFFFFFFBFC00000);
1904 /* The reset vector address is in the unmapped, uncached memory space. */
1905
1906 SR &= ~(status_SR | status_TS | status_RP);
1907 SR |= (status_ERL | status_BEV);
1908
1909 /* Cheat and allow access to the complete register set immediately */
1910 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT
1911 && WITH_TARGET_WORD_BITSIZE == 64)
1912 SR |= status_FR; /* 64bit registers */
1913
1914 /* Ensure that any instructions with pending register updates are
1915 cleared: */
1916 PENDING_INVALIDATE();
1917
1918 /* Initialise the FPU registers to the unknown state */
1919 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
1920 {
1921 int rn;
1922 for (rn = 0; (rn < 32); rn++)
1923 FPR_STATE[rn] = fmt_uninterpreted;
1924 }
1925
1926 }
1927 }
1928
1929
1930
1931 /* start-sanitize-sky */
1932 #ifdef TARGET_SKY
1933
1934 /* See ch. 5 of the 5900 Users' Guide. */
1935 void
1936 signal_exception (SIM_DESC sd,
1937 sim_cpu *cpu,
1938 address_word cia,
1939 int cause, ...)
1940 {
1941 /* int vector; */
1942
1943 #ifdef DEBUG
1944 sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",cause,pr_addr(cia));
1945 #endif /* DEBUG */
1946
1947 /* Ensure that any active atomic read/modify/write operation will fail: */
1948 LLBIT = 0;
1949
1950 /* First, handle any simulator specific magic exceptions. These are not "real" exceptions, but
1951 are exceptions which the simulator uses to implement different features. */
1952
1953 switch (cause) {
1954
1955 case SimulatorFault:
1956 {
1957 va_list ap;
1958 char *msg;
1959 va_start(ap,cause);
1960 msg = va_arg(ap,char *);
1961 va_end(ap);
1962 sim_engine_abort (SD, CPU, NULL_CIA,
1963 "FATAL: Simulator error \"%s\"\n",msg);
1964 }
1965
1966 case DebugBreakPoint :
1967 if (! (Debug & Debug_DM))
1968 {
1969 if (INDELAYSLOT())
1970 {
1971 CANCELDELAYSLOT();
1972
1973 Debug |= Debug_DBD; /* signaled from within in delay slot */
1974 DEPC = cia - 4; /* reference the branch instruction */
1975 }
1976 else
1977 {
1978 Debug &= ~Debug_DBD; /* not signaled from within a delay slot */
1979 DEPC = cia;
1980 }
1981
1982 Debug |= Debug_DM; /* in debugging mode */
1983 Debug |= Debug_DBp; /* raising a DBp exception */
1984 PC = 0xBFC00200;
1985 sim_engine_restart (SD, CPU, NULL, NULL_CIA);
1986 }
1987 break;
1988
1989 case ReservedInstruction :
1990 {
1991 va_list ap;
1992 unsigned int instruction;
1993 va_start(ap,cause);
1994 instruction = va_arg(ap,unsigned int);
1995 va_end(ap);
1996 /* Provide simple monitor support using ReservedInstruction
1997 exceptions. The following code simulates the fixed vector
1998 entry points into the IDT monitor by causing a simulator
1999 trap, performing the monitor operation, and returning to
2000 the address held in the $ra register (standard PCS return
2001 address). This means we only need to pre-load the vector
2002 space with suitable instruction values. For systems were
2003 actual trap instructions are used, we would not need to
2004 perform this magic. */
2005 if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION)
2006 {
2007 sim_monitor (SD, CPU, cia, ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) );
2008 /* NOTE: This assumes that a branch-and-link style
2009 instruction was used to enter the vector (which is the
2010 case with the current IDT monitor). */
2011 sim_engine_restart (SD, CPU, NULL, RA);
2012 }
2013 /* Look for the mips16 entry and exit instructions, and
2014 simulate a handler for them. */
2015 else if ((cia & 1) != 0
2016 && (instruction & 0xf81f) == 0xe809
2017 && (instruction & 0x0c0) != 0x0c0)
2018 {
2019 mips16_entry (SD, CPU, cia, instruction);
2020 sim_engine_restart (sd, NULL, NULL, NULL_CIA);
2021 }
2022 /* else fall through to normal exception processing */
2023 sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia));
2024 }
2025 }
2026
2027 /* Now we have the code for processing "real" exceptions. */
2028
2029 if (is5900Level2Exception(cause)) {
2030 switch(cause) {
2031 case NMIReset:
2032 cause_set_EXC2(1);
2033 break;
2034 default:
2035 sim_engine_abort (SD, CPU, NULL_CIA,
2036 "FATAL: Unexpected level 2 exception %d\n", cause);
2037 }
2038 if (STATE & simDELAYSLOT)
2039 {
2040 STATE &= ~simDELAYSLOT;
2041 COP0_ERROREPC = (cia - 4); /* reference the branch instruction */
2042 CAUSE |= cause_BD2;
2043 }
2044 else
2045 {
2046 COP0_ERROREPC = cia;
2047 CAUSE &= ~cause_BD2;
2048 }
2049
2050 SR |= status_ERL;
2051
2052 if (cause == NMIReset)
2053 PC = 0xBFC0000;
2054 else
2055 {
2056 ASSERT(0); /* At the moment, COUNTER, DEBUG never generated. */
2057 }
2058 sim_engine_restart (SD, CPU, NULL, PC);
2059 } else {
2060 /* A level 1 exception. */
2061 int refill, vector_offset;
2062
2063 cause_set_EXC(cause);
2064 if (SR & status_EXL)
2065 vector_offset = 0x180;
2066 else
2067 {
2068 if (cause == TLBLoad || cause == TLBStore) {
2069 va_list ap;
2070 va_start(ap, cause);
2071 refill = va_arg(ap,int);
2072 va_end(ap);
2073 }
2074
2075 if (STATE & simDELAYSLOT)
2076 {
2077 STATE &= ~simDELAYSLOT;
2078 CAUSE |= cause_BD;
2079 COP0_EPC = (cia - 4); /* reference the branch instruction */
2080 }
2081 else
2082 {
2083 COP0_EPC = cia;
2084 CAUSE &= ~cause_BD;
2085 }
2086
2087 SR |= status_EXL;
2088
2089 if ((cause == TLBLoad || cause == TLBStore) && refill == TLB_REFILL)
2090 vector_offset = 0x000;
2091 else if (cause == Interrupt)
2092 vector_offset = 0x200;
2093 else
2094 vector_offset = 0x180;
2095
2096 if (SR & status_BEV)
2097 PC = (signed)0xBFC00200 + vector_offset;
2098 else
2099 PC = (signed)0x80000000 + vector_offset;
2100 }
2101
2102 /* Now, handle the exception. */
2103 switch (cause)
2104 {
2105 case Interrupt:
2106 {
2107 va_list ap;
2108 unsigned int level;
2109 va_start(ap, cause);
2110 level = va_arg(ap,unsigned int);
2111 va_end(ap);
2112 /* Interrupts arrive during event processing, no need to restart.
2113 Hardware interrupts on sky target are INT1 and INT2. */
2114 if ( level == 1 )
2115 CAUSE |= cause_IP3; /* bit 11 */
2116 else if ( level == 2 )
2117 CAUSE |= cause_IP7; /* bit 15 */
2118 else
2119 sim_engine_abort (SD, CPU, NULL_CIA,
2120 "FATAL: Unexpected interrupt level %d\n", level);
2121 return;
2122 }
2123
2124 case NMIReset:
2125 ASSERT(0); /* NMIReset is a level 0 exception. */
2126 return;
2127
2128 case AddressLoad:
2129 case AddressStore:
2130 case InstructionFetch:
2131 case DataReference:
2132 /* The following is so that the simulator will continue from the
2133 exception address on breakpoint operations. */
2134 PC = COP0_EPC;
2135 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2136 sim_stopped, SIM_SIGBUS);
2137 break;
2138
2139 case ReservedInstruction:
2140 case CoProcessorUnusable:
2141 PC = COP0_EPC;
2142 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2143 sim_stopped, SIM_SIGILL);
2144 break;
2145
2146 case IntegerOverflow:
2147 case FPE:
2148 PC = COP0_EPC;
2149 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2150 sim_stopped, SIM_SIGFPE);
2151 break;
2152
2153 case TLBModification:
2154 case TLBLoad:
2155 case TLBStore:
2156 case BreakPoint:
2157 case SystemCall:
2158 case Trap:
2159 sim_engine_restart (SD, CPU, NULL, PC);
2160 break;
2161
2162 case Watch:
2163 PC = COP0_EPC;
2164 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2165 sim_stopped, SIM_SIGTRAP);
2166 break;
2167
2168 default : /* Unknown internal exception */
2169 PC = COP0_EPC;
2170 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2171 sim_stopped, SIM_SIGABRT);
2172 break;
2173
2174 }
2175 }
2176 return;
2177 }
2178
2179 #else /* TARGET_SKY */
2180 /* end-sanitize-sky */
2181
2182 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2183 /* Signal an exception condition. This will result in an exception
2184 that aborts the instruction. The instruction operation pseudocode
2185 will never see a return from this function call. */
2186
2187 void
2188 signal_exception (SIM_DESC sd,
2189 sim_cpu *cpu,
2190 address_word cia,
2191 int exception,...)
2192 {
2193 /* int vector; */
2194
2195 #ifdef DEBUG
2196 sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia));
2197 #endif /* DEBUG */
2198
2199 /* Ensure that any active atomic read/modify/write operation will fail: */
2200 LLBIT = 0;
2201
2202 switch (exception) {
2203
2204 case DebugBreakPoint :
2205 if (! (Debug & Debug_DM))
2206 {
2207 if (INDELAYSLOT())
2208 {
2209 CANCELDELAYSLOT();
2210
2211 Debug |= Debug_DBD; /* signaled from within in delay slot */
2212 DEPC = cia - 4; /* reference the branch instruction */
2213 }
2214 else
2215 {
2216 Debug &= ~Debug_DBD; /* not signaled from within a delay slot */
2217 DEPC = cia;
2218 }
2219
2220 Debug |= Debug_DM; /* in debugging mode */
2221 Debug |= Debug_DBp; /* raising a DBp exception */
2222 PC = 0xBFC00200;
2223 sim_engine_restart (SD, CPU, NULL, NULL_CIA);
2224 }
2225 break;
2226
2227 case ReservedInstruction :
2228 {
2229 va_list ap;
2230 unsigned int instruction;
2231 va_start(ap,exception);
2232 instruction = va_arg(ap,unsigned int);
2233 va_end(ap);
2234 /* Provide simple monitor support using ReservedInstruction
2235 exceptions. The following code simulates the fixed vector
2236 entry points into the IDT monitor by causing a simulator
2237 trap, performing the monitor operation, and returning to
2238 the address held in the $ra register (standard PCS return
2239 address). This means we only need to pre-load the vector
2240 space with suitable instruction values. For systems were
2241 actual trap instructions are used, we would not need to
2242 perform this magic. */
2243 if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION)
2244 {
2245 sim_monitor (SD, CPU, cia, ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) );
2246 /* NOTE: This assumes that a branch-and-link style
2247 instruction was used to enter the vector (which is the
2248 case with the current IDT monitor). */
2249 sim_engine_restart (SD, CPU, NULL, RA);
2250 }
2251 /* Look for the mips16 entry and exit instructions, and
2252 simulate a handler for them. */
2253 else if ((cia & 1) != 0
2254 && (instruction & 0xf81f) == 0xe809
2255 && (instruction & 0x0c0) != 0x0c0)
2256 {
2257 mips16_entry (SD, CPU, cia, instruction);
2258 sim_engine_restart (sd, NULL, NULL, NULL_CIA);
2259 }
2260 /* else fall through to normal exception processing */
2261 sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia));
2262 }
2263
2264 default:
2265 /* Store exception code into current exception id variable (used
2266 by exit code): */
2267
2268 /* TODO: If not simulating exceptions then stop the simulator
2269 execution. At the moment we always stop the simulation. */
2270
2271 #ifdef SUBTARGET_R3900
2272 /* update interrupt-related registers */
2273
2274 /* insert exception code in bits 6:2 */
2275 CAUSE = LSMASKED32(CAUSE, 31, 7) | LSINSERTED32(exception, 6, 2);
2276 /* shift IE/KU history bits left */
2277 SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 3, 0), 5, 2);
2278
2279 if (STATE & simDELAYSLOT)
2280 {
2281 STATE &= ~simDELAYSLOT;
2282 CAUSE |= cause_BD;
2283 EPC = (cia - 4); /* reference the branch instruction */
2284 }
2285 else
2286 EPC = cia;
2287
2288 if (SR & status_BEV)
2289 PC = (signed)0xBFC00000 + 0x180;
2290 else
2291 PC = (signed)0x80000000 + 0x080;
2292 #else
2293 /* See figure 5-17 for an outline of the code below */
2294 if (! (SR & status_EXL))
2295 {
2296 CAUSE = (exception << 2);
2297 if (STATE & simDELAYSLOT)
2298 {
2299 STATE &= ~simDELAYSLOT;
2300 CAUSE |= cause_BD;
2301 EPC = (cia - 4); /* reference the branch instruction */
2302 }
2303 else
2304 EPC = cia;
2305 /* FIXME: TLB et.al. */
2306 /* vector = 0x180; */
2307 }
2308 else
2309 {
2310 CAUSE = (exception << 2);
2311 /* vector = 0x180; */
2312 }
2313 SR |= status_EXL;
2314 /* Store exception code into current exception id variable (used
2315 by exit code): */
2316
2317 if (SR & status_BEV)
2318 PC = (signed)0xBFC00200 + 0x180;
2319 else
2320 PC = (signed)0x80000000 + 0x180;
2321 #endif
2322
2323 switch ((CAUSE >> 2) & 0x1F)
2324 {
2325 case Interrupt:
2326 /* Interrupts arrive during event processing, no need to
2327 restart */
2328 return;
2329
2330 case NMIReset:
2331 /* Ditto */
2332 #ifdef SUBTARGET_3900
2333 /* Exception vector: BEV=0 BFC00000 / BEF=1 BFC00000 */
2334 PC = (signed)0xBFC00000;
2335 #endif SUBTARGET_3900
2336 return;
2337
2338 case TLBModification:
2339 case TLBLoad:
2340 case TLBStore:
2341 case AddressLoad:
2342 case AddressStore:
2343 case InstructionFetch:
2344 case DataReference:
2345 /* The following is so that the simulator will continue from the
2346 exception address on breakpoint operations. */
2347 PC = EPC;
2348 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2349 sim_stopped, SIM_SIGBUS);
2350
2351 case ReservedInstruction:
2352 case CoProcessorUnusable:
2353 PC = EPC;
2354 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2355 sim_stopped, SIM_SIGILL);
2356
2357 case IntegerOverflow:
2358 case FPE:
2359 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2360 sim_stopped, SIM_SIGFPE);
2361
2362 case BreakPoint:
2363 case SystemCall:
2364 case Trap:
2365 sim_engine_restart (SD, CPU, NULL, PC);
2366 break;
2367
2368 case Watch:
2369 PC = EPC;
2370 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2371 sim_stopped, SIM_SIGTRAP);
2372
2373 default : /* Unknown internal exception */
2374 PC = EPC;
2375 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2376 sim_stopped, SIM_SIGABRT);
2377
2378 }
2379
2380 case SimulatorFault:
2381 {
2382 va_list ap;
2383 char *msg;
2384 va_start(ap,exception);
2385 msg = va_arg(ap,char *);
2386 va_end(ap);
2387 sim_engine_abort (SD, CPU, NULL_CIA,
2388 "FATAL: Simulator error \"%s\"\n",msg);
2389 }
2390 }
2391
2392 return;
2393 }
2394
2395 /* start-sanitize-sky */
2396 #endif /* ! TARGET_SKY */
2397 /* end-sanitize-sky */
2398
2399
2400 #if defined(WARN_RESULT)
2401 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2402 /* This function indicates that the result of the operation is
2403 undefined. However, this should not affect the instruction
2404 stream. All that is meant to happen is that the destination
2405 register is set to an undefined result. To keep the simulator
2406 simple, we just don't bother updating the destination register, so
2407 the overall result will be undefined. If desired we can stop the
2408 simulator by raising a pseudo-exception. */
2409 #define UndefinedResult() undefined_result (sd,cia)
2410 static void
2411 undefined_result(sd,cia)
2412 SIM_DESC sd;
2413 address_word cia;
2414 {
2415 sim_io_eprintf(sd,"UndefinedResult: PC = 0x%s\n",pr_addr(cia));
2416 #if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
2417 state |= simSTOP;
2418 #endif
2419 return;
2420 }
2421 #endif /* WARN_RESULT */
2422
2423 /*-- FPU support routines ---------------------------------------------------*/
2424
2425 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
2426 formats conform to ANSI/IEEE Std 754-1985. */
2427 /* SINGLE precision floating:
2428 * seeeeeeeefffffffffffffffffffffff
2429 * s = 1bit = sign
2430 * e = 8bits = exponent
2431 * f = 23bits = fraction
2432 */
2433 /* SINGLE precision fixed:
2434 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2435 * s = 1bit = sign
2436 * i = 31bits = integer
2437 */
2438 /* DOUBLE precision floating:
2439 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
2440 * s = 1bit = sign
2441 * e = 11bits = exponent
2442 * f = 52bits = fraction
2443 */
2444 /* DOUBLE precision fixed:
2445 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2446 * s = 1bit = sign
2447 * i = 63bits = integer
2448 */
2449
2450 /* Extract sign-bit: */
2451 #define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
2452 #define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
2453 /* Extract biased exponent: */
2454 #define FP_S_be(v) (((v) >> 23) & 0xFF)
2455 #define FP_D_be(v) (((v) >> 52) & 0x7FF)
2456 /* Extract unbiased Exponent: */
2457 #define FP_S_e(v) (FP_S_be(v) - 0x7F)
2458 #define FP_D_e(v) (FP_D_be(v) - 0x3FF)
2459 /* Extract complete fraction field: */
2460 #define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
2461 #define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
2462 /* Extract numbered fraction bit: */
2463 #define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
2464 #define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
2465
2466 /* Explicit QNaN values used when value required: */
2467 #define FPQNaN_SINGLE (0x7FBFFFFF)
2468 #define FPQNaN_WORD (0x7FFFFFFF)
2469 #define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
2470 #define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
2471
2472 /* Explicit Infinity values used when required: */
2473 #define FPINF_SINGLE (0x7F800000)
2474 #define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
2475
2476 #if 1 /* def DEBUG */
2477 #define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
2478 #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>" : "<format error>"))))))
2479 #endif /* DEBUG */
2480
2481 uword64
2482 value_fpr (SIM_DESC sd,
2483 sim_cpu *cpu,
2484 address_word cia,
2485 int fpr,
2486 FP_formats fmt)
2487 {
2488 uword64 value = 0;
2489 int err = 0;
2490
2491 /* Treat unused register values, as fixed-point 64bit values: */
2492 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
2493 #if 1
2494 /* If request to read data as "uninterpreted", then use the current
2495 encoding: */
2496 fmt = FPR_STATE[fpr];
2497 #else
2498 fmt = fmt_long;
2499 #endif
2500
2501 /* For values not yet accessed, set to the desired format: */
2502 if (FPR_STATE[fpr] == fmt_uninterpreted) {
2503 FPR_STATE[fpr] = fmt;
2504 #ifdef DEBUG
2505 printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
2506 #endif /* DEBUG */
2507 }
2508 if (fmt != FPR_STATE[fpr]) {
2509 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));
2510 FPR_STATE[fpr] = fmt_unknown;
2511 }
2512
2513 if (FPR_STATE[fpr] == fmt_unknown) {
2514 /* Set QNaN value: */
2515 switch (fmt) {
2516 case fmt_single:
2517 value = FPQNaN_SINGLE;
2518 break;
2519
2520 case fmt_double:
2521 value = FPQNaN_DOUBLE;
2522 break;
2523
2524 case fmt_word:
2525 value = FPQNaN_WORD;
2526 break;
2527
2528 case fmt_long:
2529 value = FPQNaN_LONG;
2530 break;
2531
2532 default:
2533 err = -1;
2534 break;
2535 }
2536 } else if (SizeFGR() == 64) {
2537 switch (fmt) {
2538 case fmt_single:
2539 case fmt_word:
2540 value = (FGR[fpr] & 0xFFFFFFFF);
2541 break;
2542
2543 case fmt_uninterpreted:
2544 case fmt_double:
2545 case fmt_long:
2546 value = FGR[fpr];
2547 break;
2548
2549 default :
2550 err = -1;
2551 break;
2552 }
2553 } else {
2554 switch (fmt) {
2555 case fmt_single:
2556 case fmt_word:
2557 value = (FGR[fpr] & 0xFFFFFFFF);
2558 break;
2559
2560 case fmt_uninterpreted:
2561 case fmt_double:
2562 case fmt_long:
2563 if ((fpr & 1) == 0) { /* even registers only */
2564 value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
2565 } else {
2566 SignalException(ReservedInstruction,0);
2567 }
2568 break;
2569
2570 default :
2571 err = -1;
2572 break;
2573 }
2574 }
2575
2576 if (err)
2577 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
2578
2579 #ifdef DEBUG
2580 printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_addr(value),pr_addr(cia),SizeFGR());
2581 #endif /* DEBUG */
2582
2583 return(value);
2584 }
2585
2586 void
2587 store_fpr (SIM_DESC sd,
2588 sim_cpu *cpu,
2589 address_word cia,
2590 int fpr,
2591 FP_formats fmt,
2592 uword64 value)
2593 {
2594 int err = 0;
2595
2596 #ifdef DEBUG
2597 printf("DBG: StoreFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_addr(value),pr_addr(cia),SizeFGR());
2598 #endif /* DEBUG */
2599
2600 if (SizeFGR() == 64) {
2601 switch (fmt) {
2602 case fmt_uninterpreted_32:
2603 fmt = fmt_uninterpreted;
2604 case fmt_single :
2605 case fmt_word :
2606 FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
2607 FPR_STATE[fpr] = fmt;
2608 break;
2609
2610 case fmt_uninterpreted_64:
2611 fmt = fmt_uninterpreted;
2612 case fmt_uninterpreted:
2613 case fmt_double :
2614 case fmt_long :
2615 FGR[fpr] = value;
2616 FPR_STATE[fpr] = fmt;
2617 break;
2618
2619 default :
2620 FPR_STATE[fpr] = fmt_unknown;
2621 err = -1;
2622 break;
2623 }
2624 } else {
2625 switch (fmt) {
2626 case fmt_uninterpreted_32:
2627 fmt = fmt_uninterpreted;
2628 case fmt_single :
2629 case fmt_word :
2630 FGR[fpr] = (value & 0xFFFFFFFF);
2631 FPR_STATE[fpr] = fmt;
2632 break;
2633
2634 case fmt_uninterpreted_64:
2635 fmt = fmt_uninterpreted;
2636 case fmt_uninterpreted:
2637 case fmt_double :
2638 case fmt_long :
2639 if ((fpr & 1) == 0) { /* even register number only */
2640 FGR[fpr+1] = (value >> 32);
2641 FGR[fpr] = (value & 0xFFFFFFFF);
2642 FPR_STATE[fpr + 1] = fmt;
2643 FPR_STATE[fpr] = fmt;
2644 } else {
2645 FPR_STATE[fpr] = fmt_unknown;
2646 FPR_STATE[fpr + 1] = fmt_unknown;
2647 SignalException(ReservedInstruction,0);
2648 }
2649 break;
2650
2651 default :
2652 FPR_STATE[fpr] = fmt_unknown;
2653 err = -1;
2654 break;
2655 }
2656 }
2657 #if defined(WARN_RESULT)
2658 else
2659 UndefinedResult();
2660 #endif /* WARN_RESULT */
2661
2662 if (err)
2663 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
2664
2665 #ifdef DEBUG
2666 printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_addr(FGR[fpr]),DOFMT(fmt));
2667 #endif /* DEBUG */
2668
2669 return;
2670 }
2671
2672 int
2673 NaN(op,fmt)
2674 uword64 op;
2675 FP_formats fmt;
2676 {
2677 int boolean = 0;
2678 switch (fmt) {
2679 case fmt_single:
2680 case fmt_word:
2681 {
2682 sim_fpu wop;
2683 sim_fpu_32to (&wop, op);
2684 boolean = sim_fpu_is_nan (&wop);
2685 break;
2686 }
2687 case fmt_double:
2688 case fmt_long:
2689 {
2690 sim_fpu wop;
2691 sim_fpu_64to (&wop, op);
2692 boolean = sim_fpu_is_nan (&wop);
2693 break;
2694 }
2695 default:
2696 fprintf (stderr, "Bad switch\n");
2697 abort ();
2698 }
2699
2700 #ifdef DEBUG
2701 printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
2702 #endif /* DEBUG */
2703
2704 return(boolean);
2705 }
2706
2707 int
2708 Infinity(op,fmt)
2709 uword64 op;
2710 FP_formats fmt;
2711 {
2712 int boolean = 0;
2713
2714 #ifdef DEBUG
2715 printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op));
2716 #endif /* DEBUG */
2717
2718 switch (fmt) {
2719 case fmt_single:
2720 {
2721 sim_fpu wop;
2722 sim_fpu_32to (&wop, op);
2723 boolean = sim_fpu_is_infinity (&wop);
2724 break;
2725 }
2726 case fmt_double:
2727 {
2728 sim_fpu wop;
2729 sim_fpu_64to (&wop, op);
2730 boolean = sim_fpu_is_infinity (&wop);
2731 break;
2732 }
2733 default:
2734 printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt));
2735 break;
2736 }
2737
2738 #ifdef DEBUG
2739 printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
2740 #endif /* DEBUG */
2741
2742 return(boolean);
2743 }
2744
2745 int
2746 Less(op1,op2,fmt)
2747 uword64 op1;
2748 uword64 op2;
2749 FP_formats fmt;
2750 {
2751 int boolean = 0;
2752
2753 /* Argument checking already performed by the FPCOMPARE code */
2754
2755 #ifdef DEBUG
2756 printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2757 #endif /* DEBUG */
2758
2759 /* The format type should already have been checked: */
2760 switch (fmt) {
2761 case fmt_single:
2762 {
2763 sim_fpu wop1;
2764 sim_fpu wop2;
2765 sim_fpu_32to (&wop1, op1);
2766 sim_fpu_32to (&wop2, op2);
2767 boolean = sim_fpu_is_lt (&wop1, &wop2);
2768 break;
2769 }
2770 case fmt_double:
2771 {
2772 sim_fpu wop1;
2773 sim_fpu wop2;
2774 sim_fpu_64to (&wop1, op1);
2775 sim_fpu_64to (&wop2, op2);
2776 boolean = sim_fpu_is_lt (&wop1, &wop2);
2777 break;
2778 }
2779 default:
2780 fprintf (stderr, "Bad switch\n");
2781 abort ();
2782 }
2783
2784 #ifdef DEBUG
2785 printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt));
2786 #endif /* DEBUG */
2787
2788 return(boolean);
2789 }
2790
2791 int
2792 Equal(op1,op2,fmt)
2793 uword64 op1;
2794 uword64 op2;
2795 FP_formats fmt;
2796 {
2797 int boolean = 0;
2798
2799 /* Argument checking already performed by the FPCOMPARE code */
2800
2801 #ifdef DEBUG
2802 printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2803 #endif /* DEBUG */
2804
2805 /* The format type should already have been checked: */
2806 switch (fmt) {
2807 case fmt_single:
2808 {
2809 sim_fpu wop1;
2810 sim_fpu wop2;
2811 sim_fpu_32to (&wop1, op1);
2812 sim_fpu_32to (&wop2, op2);
2813 boolean = sim_fpu_is_eq (&wop1, &wop2);
2814 break;
2815 }
2816 case fmt_double:
2817 {
2818 sim_fpu wop1;
2819 sim_fpu wop2;
2820 sim_fpu_64to (&wop1, op1);
2821 sim_fpu_64to (&wop2, op2);
2822 boolean = sim_fpu_is_eq (&wop1, &wop2);
2823 break;
2824 }
2825 default:
2826 fprintf (stderr, "Bad switch\n");
2827 abort ();
2828 }
2829
2830 #ifdef DEBUG
2831 printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt));
2832 #endif /* DEBUG */
2833
2834 return(boolean);
2835 }
2836
2837 uword64
2838 AbsoluteValue(op,fmt)
2839 uword64 op;
2840 FP_formats fmt;
2841 {
2842 uword64 result = 0;
2843
2844 #ifdef DEBUG
2845 printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
2846 #endif /* DEBUG */
2847
2848 /* The format type should already have been checked: */
2849 switch (fmt) {
2850 case fmt_single:
2851 {
2852 sim_fpu wop;
2853 unsigned32 ans;
2854 sim_fpu_32to (&wop, op);
2855 sim_fpu_abs (&wop, &wop);
2856 sim_fpu_to32 (&ans, &wop);
2857 result = ans;
2858 break;
2859 }
2860 case fmt_double:
2861 {
2862 sim_fpu wop;
2863 unsigned64 ans;
2864 sim_fpu_64to (&wop, op);
2865 sim_fpu_abs (&wop, &wop);
2866 sim_fpu_to64 (&ans, &wop);
2867 result = ans;
2868 break;
2869 }
2870 default:
2871 fprintf (stderr, "Bad switch\n");
2872 abort ();
2873 }
2874
2875 return(result);
2876 }
2877
2878 uword64
2879 Negate(op,fmt)
2880 uword64 op;
2881 FP_formats fmt;
2882 {
2883 uword64 result = 0;
2884
2885 #ifdef DEBUG
2886 printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
2887 #endif /* DEBUG */
2888
2889 /* The format type should already have been checked: */
2890 switch (fmt) {
2891 case fmt_single:
2892 {
2893 sim_fpu wop;
2894 unsigned32 ans;
2895 sim_fpu_32to (&wop, op);
2896 sim_fpu_neg (&wop, &wop);
2897 sim_fpu_to32 (&ans, &wop);
2898 result = ans;
2899 break;
2900 }
2901 case fmt_double:
2902 {
2903 sim_fpu wop;
2904 unsigned64 ans;
2905 sim_fpu_64to (&wop, op);
2906 sim_fpu_neg (&wop, &wop);
2907 sim_fpu_to64 (&ans, &wop);
2908 result = ans;
2909 break;
2910 }
2911 default:
2912 fprintf (stderr, "Bad switch\n");
2913 abort ();
2914 }
2915
2916 return(result);
2917 }
2918
2919 uword64
2920 Add(op1,op2,fmt)
2921 uword64 op1;
2922 uword64 op2;
2923 FP_formats fmt;
2924 {
2925 uword64 result = 0;
2926
2927 #ifdef DEBUG
2928 printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2929 #endif /* DEBUG */
2930
2931 /* The registers must specify FPRs valid for operands of type
2932 "fmt". If they are not valid, the result is undefined. */
2933
2934 /* The format type should already have been checked: */
2935 switch (fmt) {
2936 case fmt_single:
2937 {
2938 sim_fpu wop1;
2939 sim_fpu wop2;
2940 sim_fpu ans;
2941 unsigned32 res;
2942 sim_fpu_32to (&wop1, op1);
2943 sim_fpu_32to (&wop2, op2);
2944 sim_fpu_add (&ans, &wop1, &wop2);
2945 sim_fpu_to32 (&res, &ans);
2946 result = res;
2947 break;
2948 }
2949 case fmt_double:
2950 {
2951 sim_fpu wop1;
2952 sim_fpu wop2;
2953 sim_fpu ans;
2954 unsigned64 res;
2955 sim_fpu_64to (&wop1, op1);
2956 sim_fpu_64to (&wop2, op2);
2957 sim_fpu_add (&ans, &wop1, &wop2);
2958 sim_fpu_to64 (&res, &ans);
2959 result = res;
2960 break;
2961 }
2962 default:
2963 fprintf (stderr, "Bad switch\n");
2964 abort ();
2965 }
2966
2967 #ifdef DEBUG
2968 printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2969 #endif /* DEBUG */
2970
2971 return(result);
2972 }
2973
2974 uword64
2975 Sub(op1,op2,fmt)
2976 uword64 op1;
2977 uword64 op2;
2978 FP_formats fmt;
2979 {
2980 uword64 result = 0;
2981
2982 #ifdef DEBUG
2983 printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2984 #endif /* DEBUG */
2985
2986 /* The registers must specify FPRs valid for operands of type
2987 "fmt". If they are not valid, the result is undefined. */
2988
2989 /* The format type should already have been checked: */
2990 switch (fmt) {
2991 case fmt_single:
2992 {
2993 sim_fpu wop1;
2994 sim_fpu wop2;
2995 sim_fpu ans;
2996 unsigned32 res;
2997 sim_fpu_32to (&wop1, op1);
2998 sim_fpu_32to (&wop2, op2);
2999 sim_fpu_sub (&ans, &wop1, &wop2);
3000 sim_fpu_to32 (&res, &ans);
3001 result = res;
3002 }
3003 break;
3004 case fmt_double:
3005 {
3006 sim_fpu wop1;
3007 sim_fpu wop2;
3008 sim_fpu ans;
3009 unsigned64 res;
3010 sim_fpu_64to (&wop1, op1);
3011 sim_fpu_64to (&wop2, op2);
3012 sim_fpu_sub (&ans, &wop1, &wop2);
3013 sim_fpu_to64 (&res, &ans);
3014 result = res;
3015 }
3016 break;
3017 default:
3018 fprintf (stderr, "Bad switch\n");
3019 abort ();
3020 }
3021
3022 #ifdef DEBUG
3023 printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3024 #endif /* DEBUG */
3025
3026 return(result);
3027 }
3028
3029 uword64
3030 Multiply(op1,op2,fmt)
3031 uword64 op1;
3032 uword64 op2;
3033 FP_formats fmt;
3034 {
3035 uword64 result = 0;
3036
3037 #ifdef DEBUG
3038 printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
3039 #endif /* DEBUG */
3040
3041 /* The registers must specify FPRs valid for operands of type
3042 "fmt". If they are not valid, the result is undefined. */
3043
3044 /* The format type should already have been checked: */
3045 switch (fmt) {
3046 case fmt_single:
3047 {
3048 sim_fpu wop1;
3049 sim_fpu wop2;
3050 sim_fpu ans;
3051 unsigned32 res;
3052 sim_fpu_32to (&wop1, op1);
3053 sim_fpu_32to (&wop2, op2);
3054 sim_fpu_mul (&ans, &wop1, &wop2);
3055 sim_fpu_to32 (&res, &ans);
3056 result = res;
3057 break;
3058 }
3059 case fmt_double:
3060 {
3061 sim_fpu wop1;
3062 sim_fpu wop2;
3063 sim_fpu ans;
3064 unsigned64 res;
3065 sim_fpu_64to (&wop1, op1);
3066 sim_fpu_64to (&wop2, op2);
3067 sim_fpu_mul (&ans, &wop1, &wop2);
3068 sim_fpu_to64 (&res, &ans);
3069 result = res;
3070 break;
3071 }
3072 default:
3073 fprintf (stderr, "Bad switch\n");
3074 abort ();
3075 }
3076
3077 #ifdef DEBUG
3078 printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3079 #endif /* DEBUG */
3080
3081 return(result);
3082 }
3083
3084 uword64
3085 Divide(op1,op2,fmt)
3086 uword64 op1;
3087 uword64 op2;
3088 FP_formats fmt;
3089 {
3090 uword64 result = 0;
3091
3092 #ifdef DEBUG
3093 printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
3094 #endif /* DEBUG */
3095
3096 /* The registers must specify FPRs valid for operands of type
3097 "fmt". If they are not valid, the result is undefined. */
3098
3099 /* The format type should already have been checked: */
3100 switch (fmt) {
3101 case fmt_single:
3102 {
3103 sim_fpu wop1;
3104 sim_fpu wop2;
3105 sim_fpu ans;
3106 unsigned32 res;
3107 sim_fpu_32to (&wop1, op1);
3108 sim_fpu_32to (&wop2, op2);
3109 sim_fpu_div (&ans, &wop1, &wop2);
3110 sim_fpu_to32 (&res, &ans);
3111 result = res;
3112 break;
3113 }
3114 case fmt_double:
3115 {
3116 sim_fpu wop1;
3117 sim_fpu wop2;
3118 sim_fpu ans;
3119 unsigned64 res;
3120 sim_fpu_64to (&wop1, op1);
3121 sim_fpu_64to (&wop2, op2);
3122 sim_fpu_div (&ans, &wop1, &wop2);
3123 sim_fpu_to64 (&res, &ans);
3124 result = res;
3125 break;
3126 }
3127 default:
3128 fprintf (stderr, "Bad switch\n");
3129 abort ();
3130 }
3131
3132 #ifdef DEBUG
3133 printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3134 #endif /* DEBUG */
3135
3136 return(result);
3137 }
3138
3139 uword64 UNUSED
3140 Recip(op,fmt)
3141 uword64 op;
3142 FP_formats fmt;
3143 {
3144 uword64 result = 0;
3145
3146 #ifdef DEBUG
3147 printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
3148 #endif /* DEBUG */
3149
3150 /* The registers must specify FPRs valid for operands of type
3151 "fmt". If they are not valid, the result is undefined. */
3152
3153 /* The format type should already have been checked: */
3154 switch (fmt) {
3155 case fmt_single:
3156 {
3157 sim_fpu wop;
3158 sim_fpu ans;
3159 unsigned32 res;
3160 sim_fpu_32to (&wop, op);
3161 sim_fpu_inv (&ans, &wop);
3162 sim_fpu_to32 (&res, &ans);
3163 result = res;
3164 break;
3165 }
3166 case fmt_double:
3167 {
3168 sim_fpu wop;
3169 sim_fpu ans;
3170 unsigned64 res;
3171 sim_fpu_64to (&wop, op);
3172 sim_fpu_inv (&ans, &wop);
3173 sim_fpu_to64 (&res, &ans);
3174 result = res;
3175 break;
3176 }
3177 default:
3178 fprintf (stderr, "Bad switch\n");
3179 abort ();
3180 }
3181
3182 #ifdef DEBUG
3183 printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3184 #endif /* DEBUG */
3185
3186 return(result);
3187 }
3188
3189 uword64
3190 SquareRoot(op,fmt)
3191 uword64 op;
3192 FP_formats fmt;
3193 {
3194 uword64 result = 0;
3195
3196 #ifdef DEBUG
3197 printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
3198 #endif /* DEBUG */
3199
3200 /* The registers must specify FPRs valid for operands of type
3201 "fmt". If they are not valid, the result is undefined. */
3202
3203 /* The format type should already have been checked: */
3204 switch (fmt) {
3205 case fmt_single:
3206 {
3207 sim_fpu wop;
3208 sim_fpu ans;
3209 unsigned32 res;
3210 sim_fpu_32to (&wop, op);
3211 sim_fpu_sqrt (&ans, &wop);
3212 sim_fpu_to32 (&res, &ans);
3213 result = res;
3214 break;
3215 }
3216 case fmt_double:
3217 {
3218 sim_fpu wop;
3219 sim_fpu ans;
3220 unsigned64 res;
3221 sim_fpu_64to (&wop, op);
3222 sim_fpu_sqrt (&ans, &wop);
3223 sim_fpu_to64 (&res, &ans);
3224 result = res;
3225 break;
3226 }
3227 default:
3228 fprintf (stderr, "Bad switch\n");
3229 abort ();
3230 }
3231
3232 #ifdef DEBUG
3233 printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3234 #endif /* DEBUG */
3235
3236 return(result);
3237 }
3238
3239 #if 0
3240 uword64
3241 Max (uword64 op1,
3242 uword64 op2,
3243 FP_formats fmt)
3244 {
3245 int cmp;
3246 unsigned64 result;
3247
3248 #ifdef DEBUG
3249 printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
3250 #endif /* DEBUG */
3251
3252 /* The registers must specify FPRs valid for operands of type
3253 "fmt". If they are not valid, the result is undefined. */
3254
3255 /* The format type should already have been checked: */
3256 switch (fmt)
3257 {
3258 case fmt_single:
3259 {
3260 sim_fpu wop1;
3261 sim_fpu wop2;
3262 sim_fpu_32to (&wop1, op1);
3263 sim_fpu_32to (&wop2, op2);
3264 cmp = sim_fpu_cmp (&wop1, &wop2);
3265 break;
3266 }
3267 case fmt_double:
3268 {
3269 sim_fpu wop1;
3270 sim_fpu wop2;
3271 sim_fpu_64to (&wop1, op1);
3272 sim_fpu_64to (&wop2, op2);
3273 cmp = sim_fpu_cmp (&wop1, &wop2);
3274 break;
3275 }
3276 default:
3277 fprintf (stderr, "Bad switch\n");
3278 abort ();
3279 }
3280
3281 switch (cmp)
3282 {
3283 case SIM_FPU_IS_SNAN:
3284 case SIM_FPU_IS_QNAN:
3285 result = op1;
3286 case SIM_FPU_IS_NINF:
3287 case SIM_FPU_IS_NNUMBER:
3288 case SIM_FPU_IS_NDENORM:
3289 case SIM_FPU_IS_NZERO:
3290 result = op2; /* op1 - op2 < 0 */
3291 case SIM_FPU_IS_PINF:
3292 case SIM_FPU_IS_PNUMBER:
3293 case SIM_FPU_IS_PDENORM:
3294 case SIM_FPU_IS_PZERO:
3295 result = op1; /* op1 - op2 > 0 */
3296 default:
3297 fprintf (stderr, "Bad switch\n");
3298 abort ();
3299 }
3300
3301 #ifdef DEBUG
3302 printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3303 #endif /* DEBUG */
3304
3305 return(result);
3306 }
3307 #endif
3308
3309 #if 0
3310 uword64
3311 Min (uword64 op1,
3312 uword64 op2,
3313 FP_formats fmt)
3314 {
3315 int cmp;
3316 unsigned64 result;
3317
3318 #ifdef DEBUG
3319 printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
3320 #endif /* DEBUG */
3321
3322 /* The registers must specify FPRs valid for operands of type
3323 "fmt". If they are not valid, the result is undefined. */
3324
3325 /* The format type should already have been checked: */
3326 switch (fmt)
3327 {
3328 case fmt_single:
3329 {
3330 sim_fpu wop1;
3331 sim_fpu wop2;
3332 sim_fpu_32to (&wop1, op1);
3333 sim_fpu_32to (&wop2, op2);
3334 cmp = sim_fpu_cmp (&wop1, &wop2);
3335 break;
3336 }
3337 case fmt_double:
3338 {
3339 sim_fpu wop1;
3340 sim_fpu wop2;
3341 sim_fpu_64to (&wop1, op1);
3342 sim_fpu_64to (&wop2, op2);
3343 cmp = sim_fpu_cmp (&wop1, &wop2);
3344 break;
3345 }
3346 default:
3347 fprintf (stderr, "Bad switch\n");
3348 abort ();
3349 }
3350
3351 switch (cmp)
3352 {
3353 case SIM_FPU_IS_SNAN:
3354 case SIM_FPU_IS_QNAN:
3355 result = op1;
3356 case SIM_FPU_IS_NINF:
3357 case SIM_FPU_IS_NNUMBER:
3358 case SIM_FPU_IS_NDENORM:
3359 case SIM_FPU_IS_NZERO:
3360 result = op1; /* op1 - op2 < 0 */
3361 case SIM_FPU_IS_PINF:
3362 case SIM_FPU_IS_PNUMBER:
3363 case SIM_FPU_IS_PDENORM:
3364 case SIM_FPU_IS_PZERO:
3365 result = op2; /* op1 - op2 > 0 */
3366 default:
3367 fprintf (stderr, "Bad switch\n");
3368 abort ();
3369 }
3370
3371 #ifdef DEBUG
3372 printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3373 #endif /* DEBUG */
3374
3375 return(result);
3376 }
3377 #endif
3378
3379 uword64
3380 convert (SIM_DESC sd,
3381 sim_cpu *cpu,
3382 address_word cia,
3383 int rm,
3384 uword64 op,
3385 FP_formats from,
3386 FP_formats to)
3387 {
3388 sim_fpu wop;
3389 sim_fpu_round round;
3390 unsigned32 result32;
3391 unsigned64 result64;
3392
3393 #ifdef DEBUG
3394 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));
3395 #endif /* DEBUG */
3396
3397 switch (rm)
3398 {
3399 case FP_RM_NEAREST:
3400 /* Round result to nearest representable value. When two
3401 representable values are equally near, round to the value
3402 that has a least significant bit of zero (i.e. is even). */
3403 round = sim_fpu_round_near;
3404 break;
3405 case FP_RM_TOZERO:
3406 /* Round result to the value closest to, and not greater in
3407 magnitude than, the result. */
3408 round = sim_fpu_round_zero;
3409 break;
3410 case FP_RM_TOPINF:
3411 /* Round result to the value closest to, and not less than,
3412 the result. */
3413 round = sim_fpu_round_up;
3414 break;
3415
3416 case FP_RM_TOMINF:
3417 /* Round result to the value closest to, and not greater than,
3418 the result. */
3419 round = sim_fpu_round_down;
3420 break;
3421 default:
3422 round = 0;
3423 fprintf (stderr, "Bad switch\n");
3424 abort ();
3425 }
3426
3427 /* Convert the input to sim_fpu internal format */
3428 switch (from)
3429 {
3430 case fmt_double:
3431 sim_fpu_64to (&wop, op);
3432 break;
3433 case fmt_single:
3434 sim_fpu_32to (&wop, op);
3435 break;
3436 case fmt_word:
3437 sim_fpu_i32to (&wop, op, round);
3438 break;
3439 case fmt_long:
3440 sim_fpu_i64to (&wop, op, round);
3441 break;
3442 default:
3443 fprintf (stderr, "Bad switch\n");
3444 abort ();
3445 }
3446
3447 /* Convert sim_fpu format into the output */
3448 /* The value WOP is converted to the destination format, rounding
3449 using mode RM. When the destination is a fixed-point format, then
3450 a source value of Infinity, NaN or one which would round to an
3451 integer outside the fixed point range then an IEEE Invalid
3452 Operation condition is raised. */
3453 switch (to)
3454 {
3455 case fmt_single:
3456 sim_fpu_round_32 (&wop, round, 0);
3457 sim_fpu_to32 (&result32, &wop);
3458 result64 = result32;
3459 break;
3460 case fmt_double:
3461 sim_fpu_round_64 (&wop, round, 0);
3462 sim_fpu_to64 (&result64, &wop);
3463 break;
3464 case fmt_word:
3465 sim_fpu_to32i (&result32, &wop, round);
3466 result64 = result32;
3467 break;
3468 case fmt_long:
3469 sim_fpu_to64i (&result64, &wop, round);
3470 break;
3471 default:
3472 result64 = 0;
3473 fprintf (stderr, "Bad switch\n");
3474 abort ();
3475 }
3476
3477 #ifdef DEBUG
3478 printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to));
3479 #endif /* DEBUG */
3480
3481 return(result64);
3482 }
3483
3484
3485 /*-- co-processor support routines ------------------------------------------*/
3486
3487 static int UNUSED
3488 CoProcPresent(unsigned int coproc_number)
3489 {
3490 /* Return TRUE if simulator provides a model for the given co-processor number */
3491 return(0);
3492 }
3493
3494 void
3495 cop_lw (SIM_DESC sd,
3496 sim_cpu *cpu,
3497 address_word cia,
3498 int coproc_num,
3499 int coproc_reg,
3500 unsigned int memword)
3501 {
3502 switch (coproc_num)
3503 {
3504 case 1:
3505 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3506 {
3507 #ifdef DEBUG
3508 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword));
3509 #endif
3510 StoreFPR(coproc_reg,fmt_word,(uword64)memword);
3511 FPR_STATE[coproc_reg] = fmt_uninterpreted;
3512 break;
3513 }
3514
3515 default:
3516 #if 0 /* this should be controlled by a configuration option */
3517 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));
3518 #endif
3519 break;
3520 }
3521
3522 return;
3523 }
3524
3525 void
3526 cop_ld (SIM_DESC sd,
3527 sim_cpu *cpu,
3528 address_word cia,
3529 int coproc_num,
3530 int coproc_reg,
3531 uword64 memword)
3532 {
3533 switch (coproc_num) {
3534 case 1:
3535 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3536 {
3537 StoreFPR(coproc_reg,fmt_uninterpreted,memword);
3538 break;
3539 }
3540
3541 default:
3542 #if 0 /* this message should be controlled by a configuration option */
3543 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));
3544 #endif
3545 break;
3546 }
3547
3548 return;
3549 }
3550
3551
3552 /* start-sanitize-sky */
3553 #if defined(TARGET_SKY) && !defined(TARGET_SKY_B)
3554 void
3555 cop_lq (SIM_DESC sd,
3556 sim_cpu *cpu,
3557 address_word cia,
3558 int coproc_num,
3559 int coproc_reg,
3560 unsigned128 memword)
3561 {
3562 switch (coproc_num)
3563 {
3564 case 2:
3565 {
3566 int i;
3567
3568 while(vu0_busy())
3569 vu0_issue(sd);
3570
3571 /* one word at a time, argh! */
3572 for(i=0; i<4; i++)
3573 {
3574 unsigned_4 value;
3575 value = H2T_4(*A4_16(& memword, 3-i));
3576 write_vu_vec_reg(&(vu0_device.regs), coproc_reg, i, & value);
3577 }
3578 }
3579 break;
3580
3581 default:
3582 sim_io_printf(sd,"COP_LQ(%d,%d,??) at PC = 0x%s : TODO (architecture specific)\n",
3583 coproc_num,coproc_reg,pr_addr(cia));
3584 break;
3585 }
3586
3587 return;
3588 }
3589 #endif /* TARGET_SKY */
3590 /* end-sanitize-sky */
3591
3592
3593 unsigned int
3594 cop_sw (SIM_DESC sd,
3595 sim_cpu *cpu,
3596 address_word cia,
3597 int coproc_num,
3598 int coproc_reg)
3599 {
3600 unsigned int value = 0;
3601
3602 switch (coproc_num)
3603 {
3604 case 1:
3605 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3606 {
3607 FP_formats hold;
3608 hold = FPR_STATE[coproc_reg];
3609 FPR_STATE[coproc_reg] = fmt_word;
3610 value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
3611 FPR_STATE[coproc_reg] = hold;
3612 break;
3613 }
3614
3615 default:
3616 #if 0 /* should be controlled by configuration option */
3617 sim_io_printf(sd,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));
3618 #endif
3619 break;
3620 }
3621
3622 return(value);
3623 }
3624
3625 uword64
3626 cop_sd (SIM_DESC sd,
3627 sim_cpu *cpu,
3628 address_word cia,
3629 int coproc_num,
3630 int coproc_reg)
3631 {
3632 uword64 value = 0;
3633 switch (coproc_num)
3634 {
3635 case 1:
3636 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3637 {
3638 value = ValueFPR(coproc_reg,fmt_uninterpreted);
3639 break;
3640 }
3641
3642 default:
3643 #if 0 /* should be controlled by configuration option */
3644 sim_io_printf(sd,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));
3645 #endif
3646 break;
3647 }
3648
3649 return(value);
3650 }
3651
3652
3653 /* start-sanitize-sky */
3654 #if defined(TARGET_SKY) && !defined(TARGET_SKY_B)
3655 unsigned128
3656 cop_sq (SIM_DESC sd,
3657 sim_cpu *cpu,
3658 address_word cia,
3659 int coproc_num,
3660 int coproc_reg)
3661 {
3662 unsigned128 value = U16_8(0, 0);
3663 switch (coproc_num)
3664 {
3665 case 2:
3666 {
3667 unsigned_16 xyzw;
3668 int i;
3669
3670 while(vu0_busy())
3671 vu0_issue(sd);
3672
3673 /* one word at a time, argh! */
3674 for(i=0; i<4; i++)
3675 {
3676 unsigned_4 value;
3677 read_vu_vec_reg(&(vu0_device.regs), coproc_reg, i, & value);
3678 *A4_16(& xyzw, 3-i) = T2H_4(value);
3679 }
3680 return xyzw;
3681 }
3682 break;
3683
3684 default:
3685 sim_io_printf(sd,"COP_SQ(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",
3686 coproc_num,coproc_reg,pr_addr(cia));
3687 break;
3688 }
3689
3690 return(value);
3691 }
3692 #endif /* TARGET_SKY */
3693 /* end-sanitize-sky */
3694
3695
3696 void
3697 decode_coproc (SIM_DESC sd,
3698 sim_cpu *cpu,
3699 address_word cia,
3700 unsigned int instruction)
3701 {
3702 int coprocnum = ((instruction >> 26) & 3);
3703
3704 switch (coprocnum)
3705 {
3706 case 0: /* standard CPU control and cache registers */
3707 {
3708 int code = ((instruction >> 21) & 0x1F);
3709 int rt = ((instruction >> 16) & 0x1F);
3710 int rd = ((instruction >> 11) & 0x1F);
3711 int tail = instruction & 0x3ff;
3712 /* R4000 Users Manual (second edition) lists the following CP0
3713 instructions:
3714 CODE><-RT><RD-><--TAIL--->
3715 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
3716 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
3717 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
3718 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
3719 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
3720 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
3721 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
3722 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
3723 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
3724 ERET Exception return (VR4100 = 01000010000000000000000000011000)
3725 */
3726 if (((code == 0x00) || (code == 0x04)) && tail == 0)
3727 {
3728 /* M[TF]C0 - 32 bit word */
3729
3730 switch (rd) /* NOTEs: Standard CP0 registers */
3731 {
3732 /* 0 = Index R4000 VR4100 VR4300 */
3733 /* 1 = Random R4000 VR4100 VR4300 */
3734 /* 2 = EntryLo0 R4000 VR4100 VR4300 */
3735 /* 3 = EntryLo1 R4000 VR4100 VR4300 */
3736 /* 4 = Context R4000 VR4100 VR4300 */
3737 /* 5 = PageMask R4000 VR4100 VR4300 */
3738 /* 6 = Wired R4000 VR4100 VR4300 */
3739 /* 8 = BadVAddr R4000 VR4100 VR4300 */
3740 /* 9 = Count R4000 VR4100 VR4300 */
3741 /* 10 = EntryHi R4000 VR4100 VR4300 */
3742 /* 11 = Compare R4000 VR4100 VR4300 */
3743 /* 12 = SR R4000 VR4100 VR4300 */
3744 #ifdef SUBTARGET_R3900
3745 case 3:
3746 /* ignore */
3747 break;
3748 /* 3 = Config R3900 */
3749
3750 case 7:
3751 /* ignore */
3752 break;
3753 /* 3 = Cache R3900 */
3754
3755 #endif /* SUBTARGET_R3900 */
3756 case 12:
3757 if (code == 0x00)
3758 GPR[rt] = SR;
3759 else
3760 SR = GPR[rt];
3761 break;
3762 /* 13 = Cause R4000 VR4100 VR4300 */
3763 case 13:
3764 if (code == 0x00)
3765 GPR[rt] = CAUSE;
3766 else
3767 CAUSE = GPR[rt];
3768 break;
3769 /* 14 = EPC R4000 VR4100 VR4300 */
3770 case 14:
3771 if (code == 0x00)
3772 GPR[rt] = (signed_word) (signed_address) EPC;
3773 else
3774 EPC = GPR[rt];
3775 break;
3776 /* 15 = PRId R4000 VR4100 VR4300 */
3777 #ifdef SUBTARGET_R3900
3778 /* 16 = Debug */
3779 case 16:
3780 if (code == 0x00)
3781 GPR[rt] = Debug;
3782 else
3783 Debug = GPR[rt];
3784 break;
3785 #else
3786 /* 16 = Config R4000 VR4100 VR4300 */
3787 case 16:
3788 if (code == 0x00)
3789 GPR[rt] = C0_CONFIG;
3790 else
3791 C0_CONFIG = GPR[rt];
3792 break;
3793 #endif
3794 #ifdef SUBTARGET_R3900
3795 /* 17 = Debug */
3796 case 17:
3797 if (code == 0x00)
3798 GPR[rt] = DEPC;
3799 else
3800 DEPC = GPR[rt];
3801 break;
3802 #else
3803 /* 17 = LLAddr R4000 VR4100 VR4300 */
3804 #endif
3805 /* 18 = WatchLo R4000 VR4100 VR4300 */
3806 /* 19 = WatchHi R4000 VR4100 VR4300 */
3807 /* 20 = XContext R4000 VR4100 VR4300 */
3808 /* 26 = PErr or ECC R4000 VR4100 VR4300 */
3809 /* 27 = CacheErr R4000 VR4100 */
3810 /* 28 = TagLo R4000 VR4100 VR4300 */
3811 /* 29 = TagHi R4000 VR4100 VR4300 */
3812 /* 30 = ErrorEPC R4000 VR4100 VR4300 */
3813 GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
3814 /* CPR[0,rd] = GPR[rt]; */
3815 default:
3816 if (code == 0x00)
3817 GPR[rt] = (signed_word) (signed32) COP0_GPR[rd];
3818 else
3819 COP0_GPR[rd] = GPR[rt];
3820 #if 0
3821 if (code == 0x00)
3822 sim_io_printf(sd,"Warning: MFC0 %d,%d ignored (architecture specific)\n",rt,rd);
3823 else
3824 sim_io_printf(sd,"Warning: MTC0 %d,%d ignored (architecture specific)\n",rt,rd);
3825 #endif
3826 }
3827 }
3828 /* start-sanitize-r5900 */
3829 else if (((code == 0x00) || (code == 0x04)) && rd == 0x18 && tail > 0 && tail < NR_COP0_BP)
3830 /* Break-point registers */
3831 {
3832 if (code == 0x00)
3833 GPR[rt] = (signed_word) (signed32) COP0_BP[tail];
3834 else
3835 COP0_BP[tail] = GPR[rt];
3836 }
3837 else if (((code == 0x00) || (code == 0x04)) && rd == 0x19 && tail > 0 && tail < NR_COP0_P)
3838 /* Performance registers */
3839 {
3840 if (code == 0x00)
3841 GPR[rt] = (signed_word) (signed32) COP0_P[tail];
3842 else
3843 COP0_P[tail] = GPR[rt];
3844 }
3845 /* end-sanitize-r5900 */
3846 else if (code == 0x10 && (tail & 0x3f) == 0x18)
3847 {
3848 /* ERET */
3849 if (SR & status_ERL)
3850 {
3851 /* Oops, not yet available */
3852 sim_io_printf(sd,"Warning: ERET when SR[ERL] set not handled yet");
3853 PC = EPC;
3854 SR &= ~status_ERL;
3855 }
3856 else
3857 {
3858 PC = EPC;
3859 SR &= ~status_EXL;
3860 }
3861 }
3862 else if (code == 0x10 && (tail & 0x3f) == 0x10)
3863 {
3864 /* RFE */
3865 #ifdef SUBTARGET_R3900
3866 /* TX39: Copy IEp/KUp -> IEc/KUc, and IEo/KUo -> IEp/KUp */
3867
3868 /* shift IE/KU history bits right */
3869 SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 5, 2), 3, 0);
3870
3871 /* TODO: CACHE register */
3872 #endif /* SUBTARGET_R3900 */
3873 }
3874 else if (code == 0x10 && (tail & 0x3f) == 0x1F)
3875 {
3876 /* DERET */
3877 Debug &= ~Debug_DM;
3878 DELAYSLOT();
3879 DSPC = DEPC;
3880 }
3881 else
3882 sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia));
3883 /* TODO: When executing an ERET or RFE instruction we should
3884 clear LLBIT, to ensure that any out-standing atomic
3885 read/modify/write sequence fails. */
3886 }
3887 break;
3888
3889 case 2: /* co-processor 2 */
3890 {
3891 int handle = 0;
3892
3893 /* start-sanitize-sky */
3894 #if defined(TARGET_SKY) && !defined(TARGET_SKY_B)
3895 /* On the R5900, this refers to a "VU" vector co-processor. */
3896
3897 int i_25_21 = (instruction >> 21) & 0x1f;
3898 int i_20_16 = (instruction >> 16) & 0x1f;
3899 int i_20_6 = (instruction >> 6) & 0x7fff;
3900 int i_15_11 = (instruction >> 11) & 0x1f;
3901 int i_15_0 = instruction & 0xffff;
3902 int i_10_1 = (instruction >> 1) & 0x3ff;
3903 int i_10_0 = instruction & 0x7ff;
3904 int i_10_6 = (instruction >> 6) & 0x1f;
3905 int i_5_0 = instruction & 0x03f;
3906 int interlock = instruction & 0x01;
3907
3908 handle = 1;
3909
3910 /* test COP2 usability */
3911 if(! (SR & status_CU2))
3912 {
3913 SignalException(CoProcessorUnusable,instruction);
3914 /* NOTREACHED */
3915 }
3916
3917 /* BC2T/BC2F/BC2TL/BC2FL handled in r5900.igen */
3918
3919 else if((i_25_21 == 0x02 && i_10_1 == 0x000) || /* CFC2 */
3920 (i_25_21 == 0x01)) /* QMFC2 */
3921 {
3922 int rt = i_20_16;
3923 int id = i_15_11;
3924
3925 /* interlock checking */
3926 /* POLICY: never busy in macro mode */
3927 while(vu0_busy() && interlock)
3928 vu0_issue(sd);
3929
3930 /* perform VU register access */
3931 if(i_25_21 == 0x01) /* QMFC2 */
3932 {
3933 unsigned_4 x,y,z,w;
3934
3935 /* one word at a time, argh! */
3936 read_vu_vec_reg(&(vu0_device.regs), id, 3, &w);
3937 read_vu_vec_reg(&(vu0_device.regs), id, 2, &z);
3938 read_vu_vec_reg(&(vu0_device.regs), id, 1, &y);
3939 read_vu_vec_reg(&(vu0_device.regs), id, 0, &x);
3940
3941 GPR[rt] = U8_4(T2H_4(y), T2H_4(x));
3942 GPR1[rt] = U8_4(T2H_4(w), T2H_4(z));
3943 }
3944 else /* CFC2 */
3945 {
3946 GPR[rt] = vu0_read_cop2_register(id);
3947 }
3948 }
3949 else if((i_25_21 == 0x06 && i_10_1 == 0x000) || /* CTC2 */
3950 (i_25_21 == 0x05)) /* QMTC2 */
3951 {
3952 int rt = i_20_16;
3953 int id = i_15_11;
3954
3955 /* interlock checking: wait until M or E bits set */
3956 /* POLICY: never busy in macro mode */
3957 while(vu0_busy() && interlock)
3958 {
3959 if(vu0_micro_interlock_released())
3960 {
3961 vu0_micro_interlock_clear();
3962 break;
3963 }
3964
3965 vu0_issue(sd);
3966 }
3967
3968 /* perform VU register access */
3969 if(i_25_21 == 0x05) /* QMTC2 */
3970 {
3971 unsigned_4 x,y,z,w;
3972
3973 x = H2T_4(V4_8(GPR[rt], 1));
3974 y = H2T_4(V4_8(GPR[rt], 0));
3975 z = H2T_4(V4_8(GPR1[rt], 1));
3976 w = H2T_4(V4_8(GPR1[rt], 0));
3977
3978 /* one word at a time, argh! */
3979 write_vu_vec_reg(&(vu0_device.regs), id, 3, & w);
3980 write_vu_vec_reg(&(vu0_device.regs), id, 2, & z);
3981 write_vu_vec_reg(&(vu0_device.regs), id, 1, & y);
3982 write_vu_vec_reg(&(vu0_device.regs), id, 0, & x);
3983 }
3984 else /* CTC2 */
3985 {
3986 vu0_write_cop2_register(id, GPR[rt]);
3987 }
3988 }
3989 else if(i_10_0 == 0x3bf) /* VWAITQ */
3990 {
3991 while(vu0_q_busy())
3992 vu0_issue(sd);
3993 }
3994 else if(i_5_0 == 0x38) /* VCALLMS */
3995 {
3996 unsigned_4 data = H2T_2(i_20_6);
3997
3998 while(vu0_busy())
3999 vu0_issue(sd);
4000
4001 /* write to reserved CIA register to get VU0 moving */
4002 write_vu_special_reg(& vu0_device, VU_REG_CIA, & data);
4003
4004 ASSERT(vu0_busy());
4005 }
4006 else if(i_5_0 == 0x39) /* VCALLMSR */
4007 {
4008 unsigned_4 data;
4009
4010 while(vu0_busy())
4011 vu0_issue(sd);
4012
4013 read_vu_special_reg(& vu0_device, VU_REG_CMSAR0, & data);
4014 /* write to reserved CIA register to get VU0 moving */
4015 write_vu_special_reg(& vu0_device, VU_REG_CIA, & data);
4016
4017 ASSERT(vu0_busy());
4018 }
4019 /* handle all remaining UPPER VU instructions in one block */
4020 else if((i_5_0 < 0x30) || /* VADDx .. VMINI */
4021 (i_5_0 >= 0x3c && i_10_6 < 0x0c)) /* VADDAx .. VNOP */
4022 {
4023 unsigned_4 vu_upper, vu_lower;
4024 vu_upper =
4025 0x00000000 | /* bits 31 .. 25 */
4026 (instruction & 0x01ffffff); /* bits 24 .. 0 */
4027 vu_lower = 0x8000033c; /* NOP */
4028
4029 /* POLICY: never busy in macro mode */
4030 while(vu0_busy())
4031 vu0_issue(sd);
4032
4033 vu0_macro_issue(vu_upper, vu_lower);
4034
4035 /* POLICY: wait for completion of macro-instruction */
4036 while(vu0_busy())
4037 vu0_issue(sd);
4038 }
4039 /* handle all remaining LOWER VU instructions in one block */
4040 else if((i_5_0 >= 0x30 && i_5_0 <= 0x35) || /* VIADD .. VIOR */
4041 (i_5_0 >= 0x3c && i_10_6 >= 0x0c)) /* VMOVE .. VRXOR */
4042 { /* N.B.: VWAITQ already covered by prior case */
4043 unsigned_4 vu_upper, vu_lower;
4044 vu_upper = 0x000002ff; /* NOP/NOP */
4045 vu_lower =
4046 0x80000000 | /* bits 31 .. 25 */
4047 (instruction & 0x01ffffff); /* bits 24 .. 0 */
4048
4049 /* POLICY: never busy in macro mode */
4050 while(vu0_busy())
4051 vu0_issue(sd);
4052
4053 vu0_macro_issue(vu_upper, vu_lower);
4054
4055 /* POLICY: wait for completion of macro-instruction */
4056 while(vu0_busy())
4057 vu0_issue(sd);
4058 }
4059 /* ... no other COP2 instructions ... */
4060 else
4061 {
4062 SignalException(ReservedInstruction, instruction);
4063 /* NOTREACHED */
4064 }
4065
4066 #endif /* TARGET_SKY */
4067 /* end-sanitize-sky */
4068
4069 if(! handle)
4070 {
4071 sim_io_eprintf(sd, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
4072 instruction,pr_addr(cia));
4073 }
4074 }
4075 break;
4076
4077 case 1: /* should not occur (FPU co-processor) */
4078 case 3: /* should not occur (FPU co-processor) */
4079 SignalException(ReservedInstruction,instruction);
4080 break;
4081 }
4082
4083 return;
4084 }
4085
4086
4087 /*-- instruction simulation -------------------------------------------------*/
4088
4089 /* When the IGEN simulator is being built, the function below is be
4090 replaced by a generated version. However, WITH_IGEN == 2 indicates
4091 that the fubction below should be compiled but under a different
4092 name (to allow backward compatibility) */
4093
4094 #if (WITH_IGEN != 1)
4095 #if (WITH_IGEN > 1)
4096 void old_engine_run PARAMS ((SIM_DESC sd, int next_cpu_nr, int siggnal));
4097 void
4098 old_engine_run (sd, next_cpu_nr, nr_cpus, siggnal)
4099 #else
4100 void
4101 sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal)
4102 #endif
4103 SIM_DESC sd;
4104 int next_cpu_nr; /* ignore */
4105 int nr_cpus; /* ignore */
4106 int siggnal; /* ignore */
4107 {
4108 sim_cpu *cpu = STATE_CPU (sd, 0); /* hardwire to cpu 0 */
4109 #if !defined(FASTSIM)
4110 unsigned int pipeline_count = 1;
4111 #endif
4112
4113 #ifdef DEBUG
4114 if (STATE_MEMORY (sd) == NULL) {
4115 printf("DBG: simulate() entered with no memory\n");
4116 exit(1);
4117 }
4118 #endif /* DEBUG */
4119
4120 #if 0 /* Disabled to check that everything works OK */
4121 /* The VR4300 seems to sign-extend the PC on its first
4122 access. However, this may just be because it is currently
4123 configured in 32bit mode. However... */
4124 PC = SIGNEXTEND(PC,32);
4125 #endif
4126
4127 /* main controlling loop */
4128 while (1) {
4129 /* vaddr is slowly being replaced with cia - current instruction
4130 address */
4131 address_word cia = (uword64)PC;
4132 address_word vaddr = cia;
4133 address_word paddr;
4134 int cca;
4135 unsigned int instruction; /* uword64? what's this used for? FIXME! */
4136
4137 #ifdef DEBUG
4138 {
4139 printf("DBG: state = 0x%08X :",state);
4140 if (state & simHALTEX) printf(" simHALTEX");
4141 if (state & simHALTIN) printf(" simHALTIN");
4142 printf("\n");
4143 }
4144 #endif /* DEBUG */
4145
4146 DSSTATE = (STATE & simDELAYSLOT);
4147 #ifdef DEBUG
4148 if (dsstate)
4149 sim_io_printf(sd,"DBG: DSPC = 0x%s\n",pr_addr(DSPC));
4150 #endif /* DEBUG */
4151
4152 /* Fetch the next instruction from the simulator memory: */
4153 if (AddressTranslation(cia,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) {
4154 if ((vaddr & 1) == 0) {
4155 /* Copy the action of the LW instruction */
4156 unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
4157 unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
4158 uword64 value;
4159 unsigned int byte;
4160 paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
4161 LoadMemory(&value,NULL,cca,AccessLength_WORD,paddr,vaddr,isINSTRUCTION,isREAL);
4162 byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
4163 instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
4164 } else {
4165 /* Copy the action of the LH instruction */
4166 unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 1) : 0);
4167 unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 1) : 0);
4168 uword64 value;
4169 unsigned int byte;
4170 paddr = (((paddr & ~ (uword64) 1) & ~LOADDRMASK)
4171 | (((paddr & ~ (uword64) 1) & LOADDRMASK) ^ (reverse << 1)));
4172 LoadMemory(&value,NULL,cca, AccessLength_HALFWORD,
4173 paddr & ~ (uword64) 1,
4174 vaddr, isINSTRUCTION, isREAL);
4175 byte = (((vaddr &~ (uword64) 1) & LOADDRMASK) ^ (bigend << 1));
4176 instruction = ((value >> (8 * byte)) & 0xFFFF);
4177 }
4178 } else {
4179 fprintf(stderr,"Cannot translate address for PC = 0x%s failed\n",pr_addr(PC));
4180 exit(1);
4181 }
4182
4183 #ifdef DEBUG
4184 sim_io_printf(sd,"DBG: fetched 0x%08X from PC = 0x%s\n",instruction,pr_addr(PC));
4185 #endif /* DEBUG */
4186
4187 /* This is required by exception processing, to ensure that we can
4188 cope with exceptions in the delay slots of branches that may
4189 already have changed the PC. */
4190 if ((vaddr & 1) == 0)
4191 PC += 4; /* increment ready for the next fetch */
4192 else
4193 PC += 2;
4194 /* NOTE: If we perform a delay slot change to the PC, this
4195 increment is not requuired. However, it would make the
4196 simulator more complicated to try and avoid this small hit. */
4197
4198 /* Currently this code provides a simple model. For more
4199 complicated models we could perform exception status checks at
4200 this point, and set the simSTOP state as required. This could
4201 also include processing any hardware interrupts raised by any
4202 I/O model attached to the simulator context.
4203
4204 Support for "asynchronous" I/O events within the simulated world
4205 could be providing by managing a counter, and calling a I/O
4206 specific handler when a particular threshold is reached. On most
4207 architectures a decrement and check for zero operation is
4208 usually quicker than an increment and compare. However, the
4209 process of managing a known value decrement to zero, is higher
4210 than the cost of using an explicit value UINT_MAX into the
4211 future. Which system is used will depend on how complicated the
4212 I/O model is, and how much it is likely to affect the simulator
4213 bandwidth.
4214
4215 If events need to be scheduled further in the future than
4216 UINT_MAX event ticks, then the I/O model should just provide its
4217 own counter, triggered from the event system. */
4218
4219 /* MIPS pipeline ticks. To allow for future support where the
4220 pipeline hit of individual instructions is known, this control
4221 loop manages a "pipeline_count" variable. It is initialised to
4222 1 (one), and will only be changed by the simulator engine when
4223 executing an instruction. If the engine does not have access to
4224 pipeline cycle count information then all instructions will be
4225 treated as using a single cycle. NOTE: A standard system is not
4226 provided by the default simulator because different MIPS
4227 architectures have different cycle counts for the same
4228 instructions.
4229
4230 [NOTE: pipeline_count has been replaced the event queue] */
4231
4232 /* shuffle the floating point status pipeline state */
4233 ENGINE_ISSUE_PREFIX_HOOK();
4234
4235 /* NOTE: For multi-context simulation environments the "instruction"
4236 variable should be local to this routine. */
4237
4238 /* Shorthand accesses for engine. Note: If we wanted to use global
4239 variables (and a single-threaded simulator engine), then we can
4240 create the actual variables with these names. */
4241
4242 if (!(STATE & simSKIPNEXT)) {
4243 /* Include the simulator engine */
4244 #include "oengine.c"
4245 #if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
4246 #error "Mismatch between run-time simulator code and simulation engine"
4247 #endif
4248 #if (WITH_TARGET_WORD_BITSIZE != GPRLEN)
4249 #error "Mismatch between configure WITH_TARGET_WORD_BITSIZE and gencode GPRLEN"
4250 #endif
4251 #if ((WITH_FLOATING_POINT == HARD_FLOATING_POINT) != defined (HASFPU))
4252 #error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU"
4253 #endif
4254
4255 /* For certain MIPS architectures, GPR[0] is hardwired to zero. We
4256 should check for it being changed. It is better doing it here,
4257 than within the simulator, since it will help keep the simulator
4258 small. */
4259 if (ZERO != 0) {
4260 #if defined(WARN_ZERO)
4261 sim_io_eprintf(sd,"The ZERO register has been updated with 0x%s (PC = 0x%s) (reset back to zero)\n",pr_addr(ZERO),pr_addr(cia));
4262 #endif /* WARN_ZERO */
4263 ZERO = 0; /* reset back to zero before next instruction */
4264 }
4265 } else /* simSKIPNEXT check */
4266 STATE &= ~simSKIPNEXT;
4267
4268 /* If the delay slot was active before the instruction is
4269 executed, then update the PC to its new value: */
4270 if (DSSTATE) {
4271 #ifdef DEBUG
4272 printf("DBG: dsstate set before instruction execution - updating PC to 0x%s\n",pr_addr(DSPC));
4273 #endif /* DEBUG */
4274 PC = DSPC;
4275 CANCELDELAYSLOT();
4276 }
4277
4278 #if !defined(FASTSIM)
4279 if (sim_events_tickn (sd, pipeline_count))
4280 {
4281 /* cpu->cia = cia; */
4282 sim_events_process (sd);
4283 }
4284 #else
4285 if (sim_events_tick (sd))
4286 {
4287 /* cpu->cia = cia; */
4288 sim_events_process (sd);
4289 }
4290 #endif /* FASTSIM */
4291 }
4292 }
4293 #endif
4294
4295
4296 /* This code copied from gdb's utils.c. Would like to share this code,
4297 but don't know of a common place where both could get to it. */
4298
4299 /* Temporary storage using circular buffer */
4300 #define NUMCELLS 16
4301 #define CELLSIZE 32
4302 static char*
4303 get_cell (void)
4304 {
4305 static char buf[NUMCELLS][CELLSIZE];
4306 static int cell=0;
4307 if (++cell>=NUMCELLS) cell=0;
4308 return buf[cell];
4309 }
4310
4311 /* Print routines to handle variable size regs, etc */
4312
4313 /* Eliminate warning from compiler on 32-bit systems */
4314 static int thirty_two = 32;
4315
4316 char*
4317 pr_addr(addr)
4318 SIM_ADDR addr;
4319 {
4320 char *paddr_str=get_cell();
4321 switch (sizeof(addr))
4322 {
4323 case 8:
4324 sprintf(paddr_str,"%08lx%08lx",
4325 (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff));
4326 break;
4327 case 4:
4328 sprintf(paddr_str,"%08lx",(unsigned long)addr);
4329 break;
4330 case 2:
4331 sprintf(paddr_str,"%04x",(unsigned short)(addr&0xffff));
4332 break;
4333 default:
4334 sprintf(paddr_str,"%x",addr);
4335 }
4336 return paddr_str;
4337 }
4338
4339 char*
4340 pr_uword64(addr)
4341 uword64 addr;
4342 {
4343 char *paddr_str=get_cell();
4344 sprintf(paddr_str,"%08lx%08lx",
4345 (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff));
4346 return paddr_str;
4347 }
4348
4349
4350
4351 /*---------------------------------------------------------------------------*/
4352 /*> EOF interp.c <*/
This page took 0.129525 seconds and 5 git commands to generate.