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