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