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