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