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