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