sky-vu.[ch]: prototype decls, cast floats to ints before register transfer
[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 address_word value = MEM_SIZE /* FIXME STATE_MEM_SIZE (sd) */;
1127 H2T (value);
1128 sim_write (sd, A0, (char *)&value, sizeof (value));
1129 /* sim_io_eprintf (sd, "sim: get_mem_info() depreciated\n"); */
1130 break;
1131 }
1132
1133 case 158 : /* PMON printf */
1134 /* in: A0 = pointer to format string */
1135 /* A1 = optional argument 1 */
1136 /* A2 = optional argument 2 */
1137 /* A3 = optional argument 3 */
1138 /* out: void */
1139 /* The following is based on the PMON printf source */
1140 {
1141 address_word s = A0;
1142 char c;
1143 signed_word *ap = &A1; /* 1st argument */
1144 /* This isn't the quickest way, since we call the host print
1145 routine for every character almost. But it does avoid
1146 having to allocate and manage a temporary string buffer. */
1147 /* TODO: Include check that we only use three arguments (A1,
1148 A2 and A3) */
1149 while (sim_read (sd, s++, &c, 1) && c != '\0')
1150 {
1151 if (c == '%')
1152 {
1153 char tmp[40];
1154 enum {FMT_RJUST, FMT_LJUST, FMT_RJUST0, FMT_CENTER} fmt = FMT_RJUST;
1155 int width = 0, trunc = 0, haddot = 0, longlong = 0;
1156 while (sim_read (sd, s++, &c, 1) && c != '\0')
1157 {
1158 if (strchr ("dobxXulscefg%", s))
1159 break;
1160 else if (c == '-')
1161 fmt = FMT_LJUST;
1162 else if (c == '0')
1163 fmt = FMT_RJUST0;
1164 else if (c == '~')
1165 fmt = FMT_CENTER;
1166 else if (c == '*')
1167 {
1168 if (haddot)
1169 trunc = (int)*ap++;
1170 else
1171 width = (int)*ap++;
1172 }
1173 else if (c >= '1' && c <= '9')
1174 {
1175 address_word t = s;
1176 unsigned int n;
1177 while (sim_read (sd, s++, &c, 1) == 1 && isdigit (c))
1178 tmp[s - t] = c;
1179 tmp[s - t] = '\0';
1180 n = (unsigned int)strtol(tmp,NULL,10);
1181 if (haddot)
1182 trunc = n;
1183 else
1184 width = n;
1185 s--;
1186 }
1187 else if (c == '.')
1188 haddot = 1;
1189 }
1190 switch (c)
1191 {
1192 case '%':
1193 sim_io_printf (sd, "%%");
1194 break;
1195 case 's':
1196 if ((int)*ap != 0)
1197 {
1198 address_word p = *ap++;
1199 char ch;
1200 while (sim_read (sd, p++, &ch, 1) == 1 && ch != '\0')
1201 sim_io_printf(sd, "%c", ch);
1202 }
1203 else
1204 sim_io_printf(sd,"(null)");
1205 break;
1206 case 'c':
1207 sim_io_printf (sd, "%c", (int)*ap++);
1208 break;
1209 default:
1210 if (c == 'l')
1211 {
1212 sim_read (sd, s++, &c, 1);
1213 if (c == 'l')
1214 {
1215 longlong = 1;
1216 sim_read (sd, s++, &c, 1);
1217 }
1218 }
1219 if (strchr ("dobxXu", c))
1220 {
1221 word64 lv = (word64) *ap++;
1222 if (c == 'b')
1223 sim_io_printf(sd,"<binary not supported>");
1224 else
1225 {
1226 sprintf (tmp, "%%%s%c", longlong ? "ll" : "", c);
1227 if (longlong)
1228 sim_io_printf(sd, tmp, lv);
1229 else
1230 sim_io_printf(sd, tmp, (int)lv);
1231 }
1232 }
1233 else if (strchr ("eEfgG", c))
1234 {
1235 double dbl = *(double*)(ap++);
1236 sprintf (tmp, "%%%d.%d%c", width, trunc, c);
1237 sim_io_printf (sd, tmp, dbl);
1238 trunc = 0;
1239 }
1240 }
1241 }
1242 else
1243 sim_io_printf(sd, "%c", c);
1244 }
1245 break;
1246 }
1247
1248 default:
1249 sim_io_error (sd, "TODO: sim_monitor(%d) : PC = 0x%s\n",
1250 reason, pr_addr(cia));
1251 break;
1252 }
1253 return;
1254 }
1255
1256 /* Store a word into memory. */
1257
1258 static void
1259 store_word (SIM_DESC sd,
1260 sim_cpu *cpu,
1261 address_word cia,
1262 uword64 vaddr,
1263 signed_word val)
1264 {
1265 address_word paddr;
1266 int uncached;
1267
1268 if ((vaddr & 3) != 0)
1269 SignalExceptionAddressStore ();
1270 else
1271 {
1272 if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
1273 isTARGET, isREAL))
1274 {
1275 const uword64 mask = 7;
1276 uword64 memval;
1277 unsigned int byte;
1278
1279 paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
1280 byte = (vaddr & mask) ^ (BigEndianCPU << 2);
1281 memval = ((uword64) val) << (8 * byte);
1282 StoreMemory (uncached, AccessLength_WORD, memval, 0, paddr, vaddr,
1283 isREAL);
1284 }
1285 }
1286 }
1287
1288 /* Load a word from memory. */
1289
1290 static signed_word
1291 load_word (SIM_DESC sd,
1292 sim_cpu *cpu,
1293 address_word cia,
1294 uword64 vaddr)
1295 {
1296 if ((vaddr & 3) != 0)
1297 SignalExceptionAddressLoad ();
1298 else
1299 {
1300 address_word paddr;
1301 int uncached;
1302
1303 if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
1304 isTARGET, isREAL))
1305 {
1306 const uword64 mask = 0x7;
1307 const unsigned int reverse = ReverseEndian ? 1 : 0;
1308 const unsigned int bigend = BigEndianCPU ? 1 : 0;
1309 uword64 memval;
1310 unsigned int byte;
1311
1312 paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
1313 LoadMemory (&memval,NULL,uncached, AccessLength_WORD, paddr, vaddr,
1314 isDATA, isREAL);
1315 byte = (vaddr & mask) ^ (bigend << 2);
1316 return SIGNEXTEND (((memval >> (8 * byte)) & 0xffffffff), 32);
1317 }
1318 }
1319
1320 return 0;
1321 }
1322
1323 /* Simulate the mips16 entry and exit pseudo-instructions. These
1324 would normally be handled by the reserved instruction exception
1325 code, but for ease of simulation we just handle them directly. */
1326
1327 static void
1328 mips16_entry (SIM_DESC sd,
1329 sim_cpu *cpu,
1330 address_word cia,
1331 unsigned int insn)
1332 {
1333 int aregs, sregs, rreg;
1334
1335 #ifdef DEBUG
1336 printf("DBG: mips16_entry: entered (insn = 0x%08X)\n",insn);
1337 #endif /* DEBUG */
1338
1339 aregs = (insn & 0x700) >> 8;
1340 sregs = (insn & 0x0c0) >> 6;
1341 rreg = (insn & 0x020) >> 5;
1342
1343 /* This should be checked by the caller. */
1344 if (sregs == 3)
1345 abort ();
1346
1347 if (aregs < 5)
1348 {
1349 int i;
1350 signed_word tsp;
1351
1352 /* This is the entry pseudo-instruction. */
1353
1354 for (i = 0; i < aregs; i++)
1355 store_word (SD, CPU, cia, (uword64) (SP + 4 * i), GPR[i + 4]);
1356
1357 tsp = SP;
1358 SP -= 32;
1359
1360 if (rreg)
1361 {
1362 tsp -= 4;
1363 store_word (SD, CPU, cia, (uword64) tsp, RA);
1364 }
1365
1366 for (i = 0; i < sregs; i++)
1367 {
1368 tsp -= 4;
1369 store_word (SD, CPU, cia, (uword64) tsp, GPR[16 + i]);
1370 }
1371 }
1372 else
1373 {
1374 int i;
1375 signed_word tsp;
1376
1377 /* This is the exit pseudo-instruction. */
1378
1379 tsp = SP + 32;
1380
1381 if (rreg)
1382 {
1383 tsp -= 4;
1384 RA = load_word (SD, CPU, cia, (uword64) tsp);
1385 }
1386
1387 for (i = 0; i < sregs; i++)
1388 {
1389 tsp -= 4;
1390 GPR[i + 16] = load_word (SD, CPU, cia, (uword64) tsp);
1391 }
1392
1393 SP += 32;
1394
1395 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
1396 {
1397 if (aregs == 5)
1398 {
1399 FGR[0] = WORD64LO (GPR[4]);
1400 FPR_STATE[0] = fmt_uninterpreted;
1401 }
1402 else if (aregs == 6)
1403 {
1404 FGR[0] = WORD64LO (GPR[5]);
1405 FGR[1] = WORD64LO (GPR[4]);
1406 FPR_STATE[0] = fmt_uninterpreted;
1407 FPR_STATE[1] = fmt_uninterpreted;
1408 }
1409 }
1410
1411 PC = RA;
1412 }
1413
1414 }
1415
1416 /*-- trace support ----------------------------------------------------------*/
1417
1418 /* The TRACE support is provided (if required) in the memory accessing
1419 routines. Since we are also providing the architecture specific
1420 features, the architecture simulation code can also deal with
1421 notifying the TRACE world of cache flushes, etc. Similarly we do
1422 not need to provide profiling support in the simulator engine,
1423 since we can sample in the instruction fetch control loop. By
1424 defining the TRACE manifest, we add tracing as a run-time
1425 option. */
1426
1427 #if defined(TRACE)
1428 /* Tracing by default produces "din" format (as required by
1429 dineroIII). Each line of such a trace file *MUST* have a din label
1430 and address field. The rest of the line is ignored, so comments can
1431 be included if desired. The first field is the label which must be
1432 one of the following values:
1433
1434 0 read data
1435 1 write data
1436 2 instruction fetch
1437 3 escape record (treated as unknown access type)
1438 4 escape record (causes cache flush)
1439
1440 The address field is a 32bit (lower-case) hexadecimal address
1441 value. The address should *NOT* be preceded by "0x".
1442
1443 The size of the memory transfer is not important when dealing with
1444 cache lines (as long as no more than a cache line can be
1445 transferred in a single operation :-), however more information
1446 could be given following the dineroIII requirement to allow more
1447 complete memory and cache simulators to provide better
1448 results. i.e. the University of Pisa has a cache simulator that can
1449 also take bus size and speed as (variable) inputs to calculate
1450 complete system performance (a much more useful ability when trying
1451 to construct an end product, rather than a processor). They
1452 currently have an ARM version of their tool called ChARM. */
1453
1454
1455 void
1456 dotrace (SIM_DESC sd,
1457 sim_cpu *cpu,
1458 FILE *tracefh,
1459 int type,
1460 SIM_ADDR address,
1461 int width,
1462 char *comment,...)
1463 {
1464 if (STATE & simTRACE) {
1465 va_list ap;
1466 fprintf(tracefh,"%d %s ; width %d ; ",
1467 type,
1468 pr_addr(address),
1469 width);
1470 va_start(ap,comment);
1471 vfprintf(tracefh,comment,ap);
1472 va_end(ap);
1473 fprintf(tracefh,"\n");
1474 }
1475 /* NOTE: Since the "din" format will only accept 32bit addresses, and
1476 we may be generating 64bit ones, we should put the hi-32bits of the
1477 address into the comment field. */
1478
1479 /* TODO: Provide a buffer for the trace lines. We can then avoid
1480 performing writes until the buffer is filled, or the file is
1481 being closed. */
1482
1483 /* NOTE: We could consider adding a comment field to the "din" file
1484 produced using type 3 markers (unknown access). This would then
1485 allow information about the program that the "din" is for, and
1486 the MIPs world that was being simulated, to be placed into the
1487 trace file. */
1488
1489 return;
1490 }
1491 #endif /* TRACE */
1492
1493 /*---------------------------------------------------------------------------*/
1494 /*-- simulator engine -------------------------------------------------------*/
1495 /*---------------------------------------------------------------------------*/
1496
1497 static void
1498 ColdReset (SIM_DESC sd)
1499 {
1500 int cpu_nr;
1501 for (cpu_nr = 0; cpu_nr < sim_engine_nr_cpus (sd); cpu_nr++)
1502 {
1503 sim_cpu *cpu = STATE_CPU (sd, cpu_nr);
1504 /* RESET: Fixed PC address: */
1505 PC = UNSIGNED64 (0xFFFFFFFFBFC00000);
1506 /* The reset vector address is in the unmapped, uncached memory space. */
1507
1508 SR &= ~(status_SR | status_TS | status_RP);
1509 SR |= (status_ERL | status_BEV);
1510
1511 /* Cheat and allow access to the complete register set immediately */
1512 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT
1513 && WITH_TARGET_WORD_BITSIZE == 64)
1514 SR |= status_FR; /* 64bit registers */
1515
1516 /* Ensure that any instructions with pending register updates are
1517 cleared: */
1518 PENDING_INVALIDATE();
1519
1520 /* Initialise the FPU registers to the unknown state */
1521 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
1522 {
1523 int rn;
1524 for (rn = 0; (rn < 32); rn++)
1525 FPR_STATE[rn] = fmt_uninterpreted;
1526 }
1527
1528 }
1529 }
1530
1531 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
1532 (revision 3.1) */
1533 /* Translate a virtual address to a physical address and cache
1534 coherence algorithm describing the mechanism used to resolve the
1535 memory reference. Given the virtual address vAddr, and whether the
1536 reference is to Instructions ot Data (IorD), find the corresponding
1537 physical address (pAddr) and the cache coherence algorithm (CCA)
1538 used to resolve the reference. If the virtual address is in one of
1539 the unmapped address spaces the physical address and the CCA are
1540 determined directly by the virtual address. If the virtual address
1541 is in one of the mapped address spaces then the TLB is used to
1542 determine the physical address and access type; if the required
1543 translation is not present in the TLB or the desired access is not
1544 permitted the function fails and an exception is taken.
1545
1546 NOTE: Normally (RAW == 0), when address translation fails, this
1547 function raises an exception and does not return. */
1548
1549 int
1550 address_translation (SIM_DESC sd,
1551 sim_cpu *cpu,
1552 address_word cia,
1553 address_word vAddr,
1554 int IorD,
1555 int LorS,
1556 address_word *pAddr,
1557 int *CCA,
1558 int raw)
1559 {
1560 int res = -1; /* TRUE : Assume good return */
1561
1562 #ifdef DEBUG
1563 sim_io_printf(sd,"AddressTranslation(0x%s,%s,%s,...);\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
1564 #endif
1565
1566 /* Check that the address is valid for this memory model */
1567
1568 /* For a simple (flat) memory model, we simply pass virtual
1569 addressess through (mostly) unchanged. */
1570 vAddr &= 0xFFFFFFFF;
1571
1572 *pAddr = vAddr; /* default for isTARGET */
1573 *CCA = Uncached; /* not used for isHOST */
1574
1575 return(res);
1576 }
1577
1578 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
1579 (revision 3.1) */
1580 /* Prefetch data from memory. Prefetch is an advisory instruction for
1581 which an implementation specific action is taken. The action taken
1582 may increase performance, but must not change the meaning of the
1583 program, or alter architecturally-visible state. */
1584
1585 void
1586 prefetch (SIM_DESC sd,
1587 sim_cpu *cpu,
1588 address_word cia,
1589 int CCA,
1590 address_word pAddr,
1591 address_word vAddr,
1592 int DATA,
1593 int hint)
1594 {
1595 #ifdef DEBUG
1596 sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
1597 #endif /* DEBUG */
1598
1599 /* For our simple memory model we do nothing */
1600 return;
1601 }
1602
1603 /* Description from page A-22 of the "MIPS IV Instruction Set" manual
1604 (revision 3.1) */
1605 /* Load a value from memory. Use the cache and main memory as
1606 specified in the Cache Coherence Algorithm (CCA) and the sort of
1607 access (IorD) to find the contents of AccessLength memory bytes
1608 starting at physical location pAddr. The data is returned in the
1609 fixed width naturally-aligned memory element (MemElem). The
1610 low-order two (or three) bits of the address and the AccessLength
1611 indicate which of the bytes within MemElem needs to be given to the
1612 processor. If the memory access type of the reference is uncached
1613 then only the referenced bytes are read from memory and valid
1614 within the memory element. If the access type is cached, and the
1615 data is not present in cache, an implementation specific size and
1616 alignment block of memory is read and loaded into the cache to
1617 satisfy a load reference. At a minimum, the block is the entire
1618 memory element. */
1619 void
1620 load_memory (SIM_DESC sd,
1621 sim_cpu *cpu,
1622 address_word cia,
1623 uword64* memvalp,
1624 uword64* memval1p,
1625 int CCA,
1626 int AccessLength,
1627 address_word pAddr,
1628 address_word vAddr,
1629 int IorD)
1630 {
1631 uword64 value = 0;
1632 uword64 value1 = 0;
1633
1634 #ifdef DEBUG
1635 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"));
1636 #endif /* DEBUG */
1637
1638 #if defined(WARN_MEM)
1639 if (CCA != uncached)
1640 sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
1641 #endif /* WARN_MEM */
1642
1643 /* If instruction fetch then we need to check that the two lo-order
1644 bits are zero, otherwise raise a InstructionFetch exception: */
1645 if ((IorD == isINSTRUCTION)
1646 && ((pAddr & 0x3) != 0)
1647 && (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
1648 SignalExceptionInstructionFetch ();
1649
1650 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
1651 {
1652 /* In reality this should be a Bus Error */
1653 sim_io_error (sd, "AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",
1654 AccessLength,
1655 (LOADDRMASK + 1) << 2,
1656 pr_addr (pAddr));
1657 }
1658
1659 #if defined(TRACE)
1660 dotrace (SD, CPU, tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction"));
1661 #endif /* TRACE */
1662
1663 /* Read the specified number of bytes from memory. Adjust for
1664 host/target byte ordering/ Align the least significant byte
1665 read. */
1666
1667 switch (AccessLength)
1668 {
1669 case AccessLength_QUADWORD :
1670 {
1671 unsigned_16 val = sim_core_read_aligned_16 (cpu, NULL_CIA, read_map, pAddr);
1672 value1 = VH8_16 (val);
1673 value = VL8_16 (val);
1674 break;
1675 }
1676 case AccessLength_DOUBLEWORD :
1677 value = sim_core_read_aligned_8 (cpu, NULL_CIA,
1678 read_map, pAddr);
1679 break;
1680 case AccessLength_SEPTIBYTE :
1681 value = sim_core_read_misaligned_7 (cpu, NULL_CIA,
1682 read_map, pAddr);
1683 break;
1684 case AccessLength_SEXTIBYTE :
1685 value = sim_core_read_misaligned_6 (cpu, NULL_CIA,
1686 read_map, pAddr);
1687 break;
1688 case AccessLength_QUINTIBYTE :
1689 value = sim_core_read_misaligned_5 (cpu, NULL_CIA,
1690 read_map, pAddr);
1691 break;
1692 case AccessLength_WORD :
1693 value = sim_core_read_aligned_4 (cpu, NULL_CIA,
1694 read_map, pAddr);
1695 break;
1696 case AccessLength_TRIPLEBYTE :
1697 value = sim_core_read_misaligned_3 (cpu, NULL_CIA,
1698 read_map, pAddr);
1699 break;
1700 case AccessLength_HALFWORD :
1701 value = sim_core_read_aligned_2 (cpu, NULL_CIA,
1702 read_map, pAddr);
1703 break;
1704 case AccessLength_BYTE :
1705 value = sim_core_read_aligned_1 (cpu, NULL_CIA,
1706 read_map, pAddr);
1707 break;
1708 default:
1709 abort ();
1710 }
1711
1712 #ifdef DEBUG
1713 printf("DBG: LoadMemory() : (offset %d) : value = 0x%s%s\n",
1714 (int)(pAddr & LOADDRMASK),pr_uword64(value1),pr_uword64(value));
1715 #endif /* DEBUG */
1716
1717 /* See also store_memory. */
1718 if (AccessLength <= AccessLength_DOUBLEWORD)
1719 {
1720 if (BigEndianMem)
1721 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
1722 shifted to the most significant byte position. */
1723 value <<= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
1724 else
1725 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
1726 is already in the correct postition. */
1727 value <<= ((pAddr & LOADDRMASK) * 8);
1728 }
1729
1730 #ifdef DEBUG
1731 printf("DBG: LoadMemory() : shifted value = 0x%s%s\n",
1732 pr_uword64(value1),pr_uword64(value));
1733 #endif /* DEBUG */
1734
1735 *memvalp = value;
1736 if (memval1p) *memval1p = value1;
1737 }
1738
1739
1740 /* Description from page A-23 of the "MIPS IV Instruction Set" manual
1741 (revision 3.1) */
1742 /* Store a value to memory. The specified data is stored into the
1743 physical location pAddr using the memory hierarchy (data caches and
1744 main memory) as specified by the Cache Coherence Algorithm
1745 (CCA). The MemElem contains the data for an aligned, fixed-width
1746 memory element (word for 32-bit processors, doubleword for 64-bit
1747 processors), though only the bytes that will actually be stored to
1748 memory need to be valid. The low-order two (or three) bits of pAddr
1749 and the AccessLength field indicates which of the bytes within the
1750 MemElem data should actually be stored; only these bytes in memory
1751 will be changed. */
1752
1753 void
1754 store_memory (SIM_DESC sd,
1755 sim_cpu *cpu,
1756 address_word cia,
1757 int CCA,
1758 int AccessLength,
1759 uword64 MemElem,
1760 uword64 MemElem1, /* High order 64 bits */
1761 address_word pAddr,
1762 address_word vAddr)
1763 {
1764 #ifdef DEBUG
1765 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));
1766 #endif /* DEBUG */
1767
1768 #if defined(WARN_MEM)
1769 if (CCA != uncached)
1770 sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
1771 #endif /* WARN_MEM */
1772
1773 if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
1774 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));
1775
1776 #if defined(TRACE)
1777 dotrace (SD, CPU, tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store");
1778 #endif /* TRACE */
1779
1780 #ifdef DEBUG
1781 printf("DBG: StoreMemory: offset = %d MemElem = 0x%s%s\n",(unsigned int)(pAddr & LOADDRMASK),pr_uword64(MemElem1),pr_uword64(MemElem));
1782 #endif /* DEBUG */
1783
1784 /* See also load_memory */
1785 if (AccessLength <= AccessLength_DOUBLEWORD)
1786 {
1787 if (BigEndianMem)
1788 /* for big endian target, byte (pAddr&LOADDRMASK == 0) is
1789 shifted to the most significant byte position. */
1790 MemElem >>= (((7 - (pAddr & LOADDRMASK)) - AccessLength) * 8);
1791 else
1792 /* For little endian target, byte (pAddr&LOADDRMASK == 0)
1793 is already in the correct postition. */
1794 MemElem >>= ((pAddr & LOADDRMASK) * 8);
1795 }
1796
1797 #ifdef DEBUG
1798 printf("DBG: StoreMemory: shift = %d MemElem = 0x%s%s\n",shift,pr_uword64(MemElem1),pr_uword64(MemElem));
1799 #endif /* DEBUG */
1800
1801 switch (AccessLength)
1802 {
1803 case AccessLength_QUADWORD :
1804 {
1805 unsigned_16 val = U16_8 (MemElem1, MemElem);
1806 sim_core_write_aligned_16 (cpu, NULL_CIA, write_map, pAddr, val);
1807 break;
1808 }
1809 case AccessLength_DOUBLEWORD :
1810 sim_core_write_aligned_8 (cpu, NULL_CIA,
1811 write_map, pAddr, MemElem);
1812 break;
1813 case AccessLength_SEPTIBYTE :
1814 sim_core_write_misaligned_7 (cpu, NULL_CIA,
1815 write_map, pAddr, MemElem);
1816 break;
1817 case AccessLength_SEXTIBYTE :
1818 sim_core_write_misaligned_6 (cpu, NULL_CIA,
1819 write_map, pAddr, MemElem);
1820 break;
1821 case AccessLength_QUINTIBYTE :
1822 sim_core_write_misaligned_5 (cpu, NULL_CIA,
1823 write_map, pAddr, MemElem);
1824 break;
1825 case AccessLength_WORD :
1826 sim_core_write_aligned_4 (cpu, NULL_CIA,
1827 write_map, pAddr, MemElem);
1828 break;
1829 case AccessLength_TRIPLEBYTE :
1830 sim_core_write_misaligned_3 (cpu, NULL_CIA,
1831 write_map, pAddr, MemElem);
1832 break;
1833 case AccessLength_HALFWORD :
1834 sim_core_write_aligned_2 (cpu, NULL_CIA,
1835 write_map, pAddr, MemElem);
1836 break;
1837 case AccessLength_BYTE :
1838 sim_core_write_aligned_1 (cpu, NULL_CIA,
1839 write_map, pAddr, MemElem);
1840 break;
1841 default:
1842 abort ();
1843 }
1844
1845 return;
1846 }
1847
1848
1849 unsigned32
1850 ifetch32 (SIM_DESC sd,
1851 sim_cpu *cpu,
1852 address_word cia,
1853 address_word vaddr)
1854 {
1855 /* Copy the action of the LW instruction */
1856 address_word reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
1857 address_word bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
1858 unsigned64 value;
1859 address_word paddr;
1860 unsigned32 instruction;
1861 unsigned byte;
1862 int cca;
1863 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &cca, isTARGET, isREAL);
1864 paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
1865 LoadMemory (&value, NULL, cca, AccessLength_WORD, paddr, vaddr, isINSTRUCTION, isREAL);
1866 byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
1867 instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
1868 return instruction;
1869 }
1870
1871
1872 unsigned16
1873 ifetch16 (SIM_DESC sd,
1874 sim_cpu *cpu,
1875 address_word cia,
1876 address_word vaddr)
1877 {
1878 /* Copy the action of the LW instruction */
1879 address_word reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
1880 address_word bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
1881 unsigned64 value;
1882 address_word paddr;
1883 unsigned16 instruction;
1884 unsigned byte;
1885 int cca;
1886 AddressTranslation (vaddr, isINSTRUCTION, isLOAD, &paddr, &cca, isTARGET, isREAL);
1887 paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
1888 LoadMemory (&value, NULL, cca, AccessLength_WORD, paddr, vaddr, isINSTRUCTION, isREAL);
1889 byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
1890 instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
1891 return instruction;
1892 }
1893
1894
1895 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1896 /* Order loads and stores to synchronise shared memory. Perform the
1897 action necessary to make the effects of groups of synchronizable
1898 loads and stores indicated by stype occur in the same order for all
1899 processors. */
1900 void
1901 sync_operation (SIM_DESC sd,
1902 sim_cpu *cpu,
1903 address_word cia,
1904 int stype)
1905 {
1906 #ifdef DEBUG
1907 sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
1908 #endif /* DEBUG */
1909 return;
1910 }
1911
1912 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
1913 /* Signal an exception condition. This will result in an exception
1914 that aborts the instruction. The instruction operation pseudocode
1915 will never see a return from this function call. */
1916
1917 void
1918 signal_exception (SIM_DESC sd,
1919 sim_cpu *cpu,
1920 address_word cia,
1921 int exception,...)
1922 {
1923 int vector;
1924
1925 #ifdef DEBUG
1926 sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia));
1927 #endif /* DEBUG */
1928
1929 /* Ensure that any active atomic read/modify/write operation will fail: */
1930 LLBIT = 0;
1931
1932 switch (exception) {
1933 /* TODO: For testing purposes I have been ignoring TRAPs. In
1934 reality we should either simulate them, or allow the user to
1935 ignore them at run-time.
1936 Same for SYSCALL */
1937 case Trap :
1938 sim_io_eprintf(sd,"Ignoring instruction TRAP (PC 0x%s)\n",pr_addr(cia));
1939 break;
1940
1941 case SystemCall :
1942 {
1943 va_list ap;
1944 unsigned int instruction;
1945 unsigned int code;
1946
1947 va_start(ap,exception);
1948 instruction = va_arg(ap,unsigned int);
1949 va_end(ap);
1950
1951 code = (instruction >> 6) & 0xFFFFF;
1952
1953 sim_io_eprintf(sd,"Ignoring instruction `syscall %d' (PC 0x%s)\n",
1954 code, pr_addr(cia));
1955 }
1956 break;
1957
1958 case DebugBreakPoint :
1959 if (! (Debug & Debug_DM))
1960 {
1961 if (INDELAYSLOT())
1962 {
1963 CANCELDELAYSLOT();
1964
1965 Debug |= Debug_DBD; /* signaled from within in delay slot */
1966 DEPC = cia - 4; /* reference the branch instruction */
1967 }
1968 else
1969 {
1970 Debug &= ~Debug_DBD; /* not signaled from within a delay slot */
1971 DEPC = cia;
1972 }
1973
1974 Debug |= Debug_DM; /* in debugging mode */
1975 Debug |= Debug_DBp; /* raising a DBp exception */
1976 PC = 0xBFC00200;
1977 sim_engine_restart (SD, CPU, NULL, NULL_CIA);
1978 }
1979 break;
1980
1981 case ReservedInstruction :
1982 {
1983 va_list ap;
1984 unsigned int instruction;
1985 va_start(ap,exception);
1986 instruction = va_arg(ap,unsigned int);
1987 va_end(ap);
1988 /* Provide simple monitor support using ReservedInstruction
1989 exceptions. The following code simulates the fixed vector
1990 entry points into the IDT monitor by causing a simulator
1991 trap, performing the monitor operation, and returning to
1992 the address held in the $ra register (standard PCS return
1993 address). This means we only need to pre-load the vector
1994 space with suitable instruction values. For systems were
1995 actual trap instructions are used, we would not need to
1996 perform this magic. */
1997 if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION)
1998 {
1999 sim_monitor (SD, CPU, cia, ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) );
2000 /* NOTE: This assumes that a branch-and-link style
2001 instruction was used to enter the vector (which is the
2002 case with the current IDT monitor). */
2003 sim_engine_restart (SD, CPU, NULL, RA);
2004 }
2005 /* Look for the mips16 entry and exit instructions, and
2006 simulate a handler for them. */
2007 else if ((cia & 1) != 0
2008 && (instruction & 0xf81f) == 0xe809
2009 && (instruction & 0x0c0) != 0x0c0)
2010 {
2011 mips16_entry (SD, CPU, cia, instruction);
2012 sim_engine_restart (sd, NULL, NULL, NULL_CIA);
2013 }
2014 /* else fall through to normal exception processing */
2015 sim_io_eprintf(sd,"ReservedInstruction 0x%08X at PC = 0x%s\n",instruction,pr_addr(cia));
2016 }
2017
2018 case BreakPoint:
2019 #ifdef DEBUG
2020 sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",exception,pr_addr(cia));
2021 #endif /* DEBUG */
2022 /* Keep a copy of the current A0 in-case this is the program exit
2023 breakpoint: */
2024 {
2025 va_list ap;
2026 unsigned int instruction;
2027 va_start(ap,exception);
2028 instruction = va_arg(ap,unsigned int);
2029 va_end(ap);
2030 /* Check for our special terminating BREAK: */
2031 if ((instruction & 0x03FFFFC0) == 0x03ff0000) {
2032 sim_engine_halt (SD, CPU, NULL, cia,
2033 sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
2034 }
2035 }
2036 if (STATE & simDELAYSLOT)
2037 PC = cia - 4; /* reference the branch instruction */
2038 else
2039 PC = cia;
2040 sim_engine_halt (SD, CPU, NULL, cia,
2041 sim_stopped, SIM_SIGTRAP);
2042
2043 default:
2044 /* Store exception code into current exception id variable (used
2045 by exit code): */
2046
2047 /* TODO: If not simulating exceptions then stop the simulator
2048 execution. At the moment we always stop the simulation. */
2049
2050 /* See figure 5-17 for an outline of the code below */
2051 if (! (SR & status_EXL))
2052 {
2053 CAUSE = (exception << 2);
2054 if (STATE & simDELAYSLOT)
2055 {
2056 STATE &= ~simDELAYSLOT;
2057 CAUSE |= cause_BD;
2058 EPC = (cia - 4); /* reference the branch instruction */
2059 }
2060 else
2061 EPC = cia;
2062 /* FIXME: TLB et.al. */
2063 vector = 0x180;
2064 }
2065 else
2066 {
2067 CAUSE = (exception << 2);
2068 vector = 0x180;
2069 }
2070 SR |= status_EXL;
2071 /* Store exception code into current exception id variable (used
2072 by exit code): */
2073 if (SR & status_BEV)
2074 PC = (signed)0xBFC00200 + 0x180;
2075 else
2076 PC = (signed)0x80000000 + 0x180;
2077
2078 switch ((CAUSE >> 2) & 0x1F)
2079 {
2080 case Interrupt:
2081 /* Interrupts arrive during event processing, no need to
2082 restart */
2083 return;
2084
2085 case TLBModification:
2086 case TLBLoad:
2087 case TLBStore:
2088 case AddressLoad:
2089 case AddressStore:
2090 case InstructionFetch:
2091 case DataReference:
2092 /* The following is so that the simulator will continue from the
2093 exception address on breakpoint operations. */
2094 PC = EPC;
2095 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2096 sim_stopped, SIM_SIGBUS);
2097
2098 case ReservedInstruction:
2099 case CoProcessorUnusable:
2100 PC = EPC;
2101 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2102 sim_stopped, SIM_SIGILL);
2103
2104 case IntegerOverflow:
2105 case FPE:
2106 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2107 sim_stopped, SIM_SIGFPE);
2108
2109 case Trap:
2110 case Watch:
2111 case SystemCall:
2112 PC = EPC;
2113 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2114 sim_stopped, SIM_SIGTRAP);
2115
2116 case BreakPoint:
2117 PC = EPC;
2118 sim_engine_abort (SD, CPU, NULL_CIA,
2119 "FATAL: Should not encounter a breakpoint\n");
2120
2121 default : /* Unknown internal exception */
2122 PC = EPC;
2123 sim_engine_halt (SD, CPU, NULL, NULL_CIA,
2124 sim_stopped, SIM_SIGABRT);
2125
2126 }
2127
2128 case SimulatorFault:
2129 {
2130 va_list ap;
2131 char *msg;
2132 va_start(ap,exception);
2133 msg = va_arg(ap,char *);
2134 va_end(ap);
2135 sim_engine_abort (SD, CPU, NULL_CIA,
2136 "FATAL: Simulator error \"%s\"\n",msg);
2137 }
2138 }
2139
2140 return;
2141 }
2142
2143 #if defined(WARN_RESULT)
2144 /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */
2145 /* This function indicates that the result of the operation is
2146 undefined. However, this should not affect the instruction
2147 stream. All that is meant to happen is that the destination
2148 register is set to an undefined result. To keep the simulator
2149 simple, we just don't bother updating the destination register, so
2150 the overall result will be undefined. If desired we can stop the
2151 simulator by raising a pseudo-exception. */
2152 #define UndefinedResult() undefined_result (sd,cia)
2153 static void
2154 undefined_result(sd,cia)
2155 SIM_DESC sd;
2156 address_word cia;
2157 {
2158 sim_io_eprintf(sd,"UndefinedResult: PC = 0x%s\n",pr_addr(cia));
2159 #if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
2160 state |= simSTOP;
2161 #endif
2162 return;
2163 }
2164 #endif /* WARN_RESULT */
2165
2166 void
2167 cache_op (SIM_DESC sd,
2168 sim_cpu *cpu,
2169 address_word cia,
2170 int op,
2171 address_word pAddr,
2172 address_word vAddr,
2173 unsigned int instruction)
2174 {
2175 #if 1 /* stop warning message being displayed (we should really just remove the code) */
2176 static int icache_warning = 1;
2177 static int dcache_warning = 1;
2178 #else
2179 static int icache_warning = 0;
2180 static int dcache_warning = 0;
2181 #endif
2182
2183 /* If CP0 is not useable (User or Supervisor mode) and the CP0
2184 enable bit in the Status Register is clear - a coprocessor
2185 unusable exception is taken. */
2186 #if 0
2187 sim_io_printf(sd,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(cia));
2188 #endif
2189
2190 switch (op & 0x3) {
2191 case 0: /* instruction cache */
2192 switch (op >> 2) {
2193 case 0: /* Index Invalidate */
2194 case 1: /* Index Load Tag */
2195 case 2: /* Index Store Tag */
2196 case 4: /* Hit Invalidate */
2197 case 5: /* Fill */
2198 case 6: /* Hit Writeback */
2199 if (!icache_warning)
2200 {
2201 sim_io_eprintf(sd,"Instruction CACHE operation %d to be coded\n",(op >> 2));
2202 icache_warning = 1;
2203 }
2204 break;
2205
2206 default:
2207 SignalException(ReservedInstruction,instruction);
2208 break;
2209 }
2210 break;
2211
2212 case 1: /* data cache */
2213 switch (op >> 2) {
2214 case 0: /* Index Writeback Invalidate */
2215 case 1: /* Index Load Tag */
2216 case 2: /* Index Store Tag */
2217 case 3: /* Create Dirty */
2218 case 4: /* Hit Invalidate */
2219 case 5: /* Hit Writeback Invalidate */
2220 case 6: /* Hit Writeback */
2221 if (!dcache_warning)
2222 {
2223 sim_io_eprintf(sd,"Data CACHE operation %d to be coded\n",(op >> 2));
2224 dcache_warning = 1;
2225 }
2226 break;
2227
2228 default:
2229 SignalException(ReservedInstruction,instruction);
2230 break;
2231 }
2232 break;
2233
2234 default: /* unrecognised cache ID */
2235 SignalException(ReservedInstruction,instruction);
2236 break;
2237 }
2238
2239 return;
2240 }
2241
2242 /*-- FPU support routines ---------------------------------------------------*/
2243
2244 /* Numbers are held in normalized form. The SINGLE and DOUBLE binary
2245 formats conform to ANSI/IEEE Std 754-1985. */
2246 /* SINGLE precision floating:
2247 * seeeeeeeefffffffffffffffffffffff
2248 * s = 1bit = sign
2249 * e = 8bits = exponent
2250 * f = 23bits = fraction
2251 */
2252 /* SINGLE precision fixed:
2253 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2254 * s = 1bit = sign
2255 * i = 31bits = integer
2256 */
2257 /* DOUBLE precision floating:
2258 * seeeeeeeeeeeffffffffffffffffffffffffffffffffffffffffffffffffffff
2259 * s = 1bit = sign
2260 * e = 11bits = exponent
2261 * f = 52bits = fraction
2262 */
2263 /* DOUBLE precision fixed:
2264 * siiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
2265 * s = 1bit = sign
2266 * i = 63bits = integer
2267 */
2268
2269 /* Extract sign-bit: */
2270 #define FP_S_s(v) (((v) & ((unsigned)1 << 31)) ? 1 : 0)
2271 #define FP_D_s(v) (((v) & ((uword64)1 << 63)) ? 1 : 0)
2272 /* Extract biased exponent: */
2273 #define FP_S_be(v) (((v) >> 23) & 0xFF)
2274 #define FP_D_be(v) (((v) >> 52) & 0x7FF)
2275 /* Extract unbiased Exponent: */
2276 #define FP_S_e(v) (FP_S_be(v) - 0x7F)
2277 #define FP_D_e(v) (FP_D_be(v) - 0x3FF)
2278 /* Extract complete fraction field: */
2279 #define FP_S_f(v) ((v) & ~((unsigned)0x1FF << 23))
2280 #define FP_D_f(v) ((v) & ~((uword64)0xFFF << 52))
2281 /* Extract numbered fraction bit: */
2282 #define FP_S_fb(b,v) (((v) & (1 << (23 - (b)))) ? 1 : 0)
2283 #define FP_D_fb(b,v) (((v) & (1 << (52 - (b)))) ? 1 : 0)
2284
2285 /* Explicit QNaN values used when value required: */
2286 #define FPQNaN_SINGLE (0x7FBFFFFF)
2287 #define FPQNaN_WORD (0x7FFFFFFF)
2288 #define FPQNaN_DOUBLE (((uword64)0x7FF7FFFF << 32) | 0xFFFFFFFF)
2289 #define FPQNaN_LONG (((uword64)0x7FFFFFFF << 32) | 0xFFFFFFFF)
2290
2291 /* Explicit Infinity values used when required: */
2292 #define FPINF_SINGLE (0x7F800000)
2293 #define FPINF_DOUBLE (((uword64)0x7FF00000 << 32) | 0x00000000)
2294
2295 #if 1 /* def DEBUG */
2296 #define RMMODE(v) (((v) == FP_RM_NEAREST) ? "Round" : (((v) == FP_RM_TOZERO) ? "Trunc" : (((v) == FP_RM_TOPINF) ? "Ceil" : "Floor")))
2297 #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>"))))))
2298 #endif /* DEBUG */
2299
2300 uword64
2301 value_fpr (SIM_DESC sd,
2302 sim_cpu *cpu,
2303 address_word cia,
2304 int fpr,
2305 FP_formats fmt)
2306 {
2307 uword64 value = 0;
2308 int err = 0;
2309
2310 /* Treat unused register values, as fixed-point 64bit values: */
2311 if ((fmt == fmt_uninterpreted) || (fmt == fmt_unknown))
2312 #if 1
2313 /* If request to read data as "uninterpreted", then use the current
2314 encoding: */
2315 fmt = FPR_STATE[fpr];
2316 #else
2317 fmt = fmt_long;
2318 #endif
2319
2320 /* For values not yet accessed, set to the desired format: */
2321 if (FPR_STATE[fpr] == fmt_uninterpreted) {
2322 FPR_STATE[fpr] = fmt;
2323 #ifdef DEBUG
2324 printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt));
2325 #endif /* DEBUG */
2326 }
2327 if (fmt != FPR_STATE[fpr]) {
2328 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));
2329 FPR_STATE[fpr] = fmt_unknown;
2330 }
2331
2332 if (FPR_STATE[fpr] == fmt_unknown) {
2333 /* Set QNaN value: */
2334 switch (fmt) {
2335 case fmt_single:
2336 value = FPQNaN_SINGLE;
2337 break;
2338
2339 case fmt_double:
2340 value = FPQNaN_DOUBLE;
2341 break;
2342
2343 case fmt_word:
2344 value = FPQNaN_WORD;
2345 break;
2346
2347 case fmt_long:
2348 value = FPQNaN_LONG;
2349 break;
2350
2351 default:
2352 err = -1;
2353 break;
2354 }
2355 } else if (SizeFGR() == 64) {
2356 switch (fmt) {
2357 case fmt_single:
2358 case fmt_word:
2359 value = (FGR[fpr] & 0xFFFFFFFF);
2360 break;
2361
2362 case fmt_uninterpreted:
2363 case fmt_double:
2364 case fmt_long:
2365 value = FGR[fpr];
2366 break;
2367
2368 default :
2369 err = -1;
2370 break;
2371 }
2372 } else {
2373 switch (fmt) {
2374 case fmt_single:
2375 case fmt_word:
2376 value = (FGR[fpr] & 0xFFFFFFFF);
2377 break;
2378
2379 case fmt_uninterpreted:
2380 case fmt_double:
2381 case fmt_long:
2382 if ((fpr & 1) == 0) { /* even registers only */
2383 value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
2384 } else {
2385 SignalException(ReservedInstruction,0);
2386 }
2387 break;
2388
2389 default :
2390 err = -1;
2391 break;
2392 }
2393 }
2394
2395 if (err)
2396 SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
2397
2398 #ifdef DEBUG
2399 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());
2400 #endif /* DEBUG */
2401
2402 return(value);
2403 }
2404
2405 void
2406 store_fpr (SIM_DESC sd,
2407 sim_cpu *cpu,
2408 address_word cia,
2409 int fpr,
2410 FP_formats fmt,
2411 uword64 value)
2412 {
2413 int err = 0;
2414
2415 #ifdef DEBUG
2416 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());
2417 #endif /* DEBUG */
2418
2419 if (SizeFGR() == 64) {
2420 switch (fmt) {
2421 case fmt_uninterpreted_32:
2422 fmt = fmt_uninterpreted;
2423 case fmt_single :
2424 case fmt_word :
2425 FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF));
2426 FPR_STATE[fpr] = fmt;
2427 break;
2428
2429 case fmt_uninterpreted_64:
2430 fmt = fmt_uninterpreted;
2431 case fmt_uninterpreted:
2432 case fmt_double :
2433 case fmt_long :
2434 FGR[fpr] = value;
2435 FPR_STATE[fpr] = fmt;
2436 break;
2437
2438 default :
2439 FPR_STATE[fpr] = fmt_unknown;
2440 err = -1;
2441 break;
2442 }
2443 } else {
2444 switch (fmt) {
2445 case fmt_uninterpreted_32:
2446 fmt = fmt_uninterpreted;
2447 case fmt_single :
2448 case fmt_word :
2449 FGR[fpr] = (value & 0xFFFFFFFF);
2450 FPR_STATE[fpr] = fmt;
2451 break;
2452
2453 case fmt_uninterpreted_64:
2454 fmt = fmt_uninterpreted;
2455 case fmt_uninterpreted:
2456 case fmt_double :
2457 case fmt_long :
2458 if ((fpr & 1) == 0) { /* even register number only */
2459 FGR[fpr+1] = (value >> 32);
2460 FGR[fpr] = (value & 0xFFFFFFFF);
2461 FPR_STATE[fpr + 1] = fmt;
2462 FPR_STATE[fpr] = fmt;
2463 } else {
2464 FPR_STATE[fpr] = fmt_unknown;
2465 FPR_STATE[fpr + 1] = fmt_unknown;
2466 SignalException(ReservedInstruction,0);
2467 }
2468 break;
2469
2470 default :
2471 FPR_STATE[fpr] = fmt_unknown;
2472 err = -1;
2473 break;
2474 }
2475 }
2476 #if defined(WARN_RESULT)
2477 else
2478 UndefinedResult();
2479 #endif /* WARN_RESULT */
2480
2481 if (err)
2482 SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
2483
2484 #ifdef DEBUG
2485 printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_addr(FGR[fpr]),DOFMT(fmt));
2486 #endif /* DEBUG */
2487
2488 return;
2489 }
2490
2491 int
2492 NaN(op,fmt)
2493 uword64 op;
2494 FP_formats fmt;
2495 {
2496 int boolean = 0;
2497 switch (fmt) {
2498 case fmt_single:
2499 case fmt_word:
2500 {
2501 sim_fpu wop;
2502 sim_fpu_32to (&wop, op);
2503 boolean = sim_fpu_is_nan (&wop);
2504 break;
2505 }
2506 case fmt_double:
2507 case fmt_long:
2508 {
2509 sim_fpu wop;
2510 sim_fpu_64to (&wop, op);
2511 boolean = sim_fpu_is_nan (&wop);
2512 break;
2513 }
2514 default:
2515 fprintf (stderr, "Bad switch\n");
2516 abort ();
2517 }
2518
2519 #ifdef DEBUG
2520 printf("DBG: NaN: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
2521 #endif /* DEBUG */
2522
2523 return(boolean);
2524 }
2525
2526 int
2527 Infinity(op,fmt)
2528 uword64 op;
2529 FP_formats fmt;
2530 {
2531 int boolean = 0;
2532
2533 #ifdef DEBUG
2534 printf("DBG: Infinity: format %s 0x%s\n",DOFMT(fmt),pr_addr(op));
2535 #endif /* DEBUG */
2536
2537 switch (fmt) {
2538 case fmt_single:
2539 {
2540 sim_fpu wop;
2541 sim_fpu_32to (&wop, op);
2542 boolean = sim_fpu_is_infinity (&wop);
2543 break;
2544 }
2545 case fmt_double:
2546 {
2547 sim_fpu wop;
2548 sim_fpu_64to (&wop, op);
2549 boolean = sim_fpu_is_infinity (&wop);
2550 break;
2551 }
2552 default:
2553 printf("DBG: TODO: unrecognised format (%s) for Infinity check\n",DOFMT(fmt));
2554 break;
2555 }
2556
2557 #ifdef DEBUG
2558 printf("DBG: Infinity: returning %d for 0x%s (format = %s)\n",boolean,pr_addr(op),DOFMT(fmt));
2559 #endif /* DEBUG */
2560
2561 return(boolean);
2562 }
2563
2564 int
2565 Less(op1,op2,fmt)
2566 uword64 op1;
2567 uword64 op2;
2568 FP_formats fmt;
2569 {
2570 int boolean = 0;
2571
2572 /* Argument checking already performed by the FPCOMPARE code */
2573
2574 #ifdef DEBUG
2575 printf("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2576 #endif /* DEBUG */
2577
2578 /* The format type should already have been checked: */
2579 switch (fmt) {
2580 case fmt_single:
2581 {
2582 sim_fpu wop1;
2583 sim_fpu wop2;
2584 sim_fpu_32to (&wop1, op1);
2585 sim_fpu_32to (&wop2, op2);
2586 boolean = sim_fpu_is_lt (&wop1, &wop2);
2587 break;
2588 }
2589 case fmt_double:
2590 {
2591 sim_fpu wop1;
2592 sim_fpu wop2;
2593 sim_fpu_64to (&wop1, op1);
2594 sim_fpu_64to (&wop2, op2);
2595 boolean = sim_fpu_is_lt (&wop1, &wop2);
2596 break;
2597 }
2598 default:
2599 fprintf (stderr, "Bad switch\n");
2600 abort ();
2601 }
2602
2603 #ifdef DEBUG
2604 printf("DBG: Less: returning %d (format = %s)\n",boolean,DOFMT(fmt));
2605 #endif /* DEBUG */
2606
2607 return(boolean);
2608 }
2609
2610 int
2611 Equal(op1,op2,fmt)
2612 uword64 op1;
2613 uword64 op2;
2614 FP_formats fmt;
2615 {
2616 int boolean = 0;
2617
2618 /* Argument checking already performed by the FPCOMPARE code */
2619
2620 #ifdef DEBUG
2621 printf("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2622 #endif /* DEBUG */
2623
2624 /* The format type should already have been checked: */
2625 switch (fmt) {
2626 case fmt_single:
2627 {
2628 sim_fpu wop1;
2629 sim_fpu wop2;
2630 sim_fpu_32to (&wop1, op1);
2631 sim_fpu_32to (&wop2, op2);
2632 boolean = sim_fpu_is_eq (&wop1, &wop2);
2633 break;
2634 }
2635 case fmt_double:
2636 {
2637 sim_fpu wop1;
2638 sim_fpu wop2;
2639 sim_fpu_64to (&wop1, op1);
2640 sim_fpu_64to (&wop2, op2);
2641 boolean = sim_fpu_is_eq (&wop1, &wop2);
2642 break;
2643 }
2644 default:
2645 fprintf (stderr, "Bad switch\n");
2646 abort ();
2647 }
2648
2649 #ifdef DEBUG
2650 printf("DBG: Equal: returning %d (format = %s)\n",boolean,DOFMT(fmt));
2651 #endif /* DEBUG */
2652
2653 return(boolean);
2654 }
2655
2656 uword64
2657 AbsoluteValue(op,fmt)
2658 uword64 op;
2659 FP_formats fmt;
2660 {
2661 uword64 result = 0;
2662
2663 #ifdef DEBUG
2664 printf("DBG: AbsoluteValue: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
2665 #endif /* DEBUG */
2666
2667 /* The format type should already have been checked: */
2668 switch (fmt) {
2669 case fmt_single:
2670 {
2671 sim_fpu wop;
2672 unsigned32 ans;
2673 sim_fpu_32to (&wop, op);
2674 sim_fpu_abs (&wop, &wop);
2675 sim_fpu_to32 (&ans, &wop);
2676 result = ans;
2677 break;
2678 }
2679 case fmt_double:
2680 {
2681 sim_fpu wop;
2682 unsigned64 ans;
2683 sim_fpu_64to (&wop, op);
2684 sim_fpu_abs (&wop, &wop);
2685 sim_fpu_to64 (&ans, &wop);
2686 result = ans;
2687 break;
2688 }
2689 default:
2690 fprintf (stderr, "Bad switch\n");
2691 abort ();
2692 }
2693
2694 return(result);
2695 }
2696
2697 uword64
2698 Negate(op,fmt)
2699 uword64 op;
2700 FP_formats fmt;
2701 {
2702 uword64 result = 0;
2703
2704 #ifdef DEBUG
2705 printf("DBG: Negate: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
2706 #endif /* DEBUG */
2707
2708 /* The format type should already have been checked: */
2709 switch (fmt) {
2710 case fmt_single:
2711 {
2712 sim_fpu wop;
2713 unsigned32 ans;
2714 sim_fpu_32to (&wop, op);
2715 sim_fpu_neg (&wop, &wop);
2716 sim_fpu_to32 (&ans, &wop);
2717 result = ans;
2718 break;
2719 }
2720 case fmt_double:
2721 {
2722 sim_fpu wop;
2723 unsigned64 ans;
2724 sim_fpu_64to (&wop, op);
2725 sim_fpu_neg (&wop, &wop);
2726 sim_fpu_to64 (&ans, &wop);
2727 result = ans;
2728 break;
2729 }
2730 default:
2731 fprintf (stderr, "Bad switch\n");
2732 abort ();
2733 }
2734
2735 return(result);
2736 }
2737
2738 uword64
2739 Add(op1,op2,fmt)
2740 uword64 op1;
2741 uword64 op2;
2742 FP_formats fmt;
2743 {
2744 uword64 result = 0;
2745
2746 #ifdef DEBUG
2747 printf("DBG: Add: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2748 #endif /* DEBUG */
2749
2750 /* The registers must specify FPRs valid for operands of type
2751 "fmt". If they are not valid, the result is undefined. */
2752
2753 /* The format type should already have been checked: */
2754 switch (fmt) {
2755 case fmt_single:
2756 {
2757 sim_fpu wop1;
2758 sim_fpu wop2;
2759 sim_fpu ans;
2760 unsigned32 res;
2761 sim_fpu_32to (&wop1, op1);
2762 sim_fpu_32to (&wop2, op2);
2763 sim_fpu_add (&ans, &wop1, &wop2);
2764 sim_fpu_to32 (&res, &ans);
2765 result = res;
2766 break;
2767 }
2768 case fmt_double:
2769 {
2770 sim_fpu wop1;
2771 sim_fpu wop2;
2772 sim_fpu ans;
2773 unsigned64 res;
2774 sim_fpu_64to (&wop1, op1);
2775 sim_fpu_64to (&wop2, op2);
2776 sim_fpu_add (&ans, &wop1, &wop2);
2777 sim_fpu_to64 (&res, &ans);
2778 result = res;
2779 break;
2780 }
2781 default:
2782 fprintf (stderr, "Bad switch\n");
2783 abort ();
2784 }
2785
2786 #ifdef DEBUG
2787 printf("DBG: Add: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2788 #endif /* DEBUG */
2789
2790 return(result);
2791 }
2792
2793 uword64
2794 Sub(op1,op2,fmt)
2795 uword64 op1;
2796 uword64 op2;
2797 FP_formats fmt;
2798 {
2799 uword64 result = 0;
2800
2801 #ifdef DEBUG
2802 printf("DBG: Sub: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2803 #endif /* DEBUG */
2804
2805 /* The registers must specify FPRs valid for operands of type
2806 "fmt". If they are not valid, the result is undefined. */
2807
2808 /* The format type should already have been checked: */
2809 switch (fmt) {
2810 case fmt_single:
2811 {
2812 sim_fpu wop1;
2813 sim_fpu wop2;
2814 sim_fpu ans;
2815 unsigned32 res;
2816 sim_fpu_32to (&wop1, op1);
2817 sim_fpu_32to (&wop2, op2);
2818 sim_fpu_sub (&ans, &wop1, &wop2);
2819 sim_fpu_to32 (&res, &ans);
2820 result = res;
2821 }
2822 break;
2823 case fmt_double:
2824 {
2825 sim_fpu wop1;
2826 sim_fpu wop2;
2827 sim_fpu ans;
2828 unsigned64 res;
2829 sim_fpu_64to (&wop1, op1);
2830 sim_fpu_64to (&wop2, op2);
2831 sim_fpu_sub (&ans, &wop1, &wop2);
2832 sim_fpu_to64 (&res, &ans);
2833 result = res;
2834 }
2835 break;
2836 default:
2837 fprintf (stderr, "Bad switch\n");
2838 abort ();
2839 }
2840
2841 #ifdef DEBUG
2842 printf("DBG: Sub: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2843 #endif /* DEBUG */
2844
2845 return(result);
2846 }
2847
2848 uword64
2849 Multiply(op1,op2,fmt)
2850 uword64 op1;
2851 uword64 op2;
2852 FP_formats fmt;
2853 {
2854 uword64 result = 0;
2855
2856 #ifdef DEBUG
2857 printf("DBG: Multiply: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2858 #endif /* DEBUG */
2859
2860 /* The registers must specify FPRs valid for operands of type
2861 "fmt". If they are not valid, the result is undefined. */
2862
2863 /* The format type should already have been checked: */
2864 switch (fmt) {
2865 case fmt_single:
2866 {
2867 sim_fpu wop1;
2868 sim_fpu wop2;
2869 sim_fpu ans;
2870 unsigned32 res;
2871 sim_fpu_32to (&wop1, op1);
2872 sim_fpu_32to (&wop2, op2);
2873 sim_fpu_mul (&ans, &wop1, &wop2);
2874 sim_fpu_to32 (&res, &ans);
2875 result = res;
2876 break;
2877 }
2878 case fmt_double:
2879 {
2880 sim_fpu wop1;
2881 sim_fpu wop2;
2882 sim_fpu ans;
2883 unsigned64 res;
2884 sim_fpu_64to (&wop1, op1);
2885 sim_fpu_64to (&wop2, op2);
2886 sim_fpu_mul (&ans, &wop1, &wop2);
2887 sim_fpu_to64 (&res, &ans);
2888 result = res;
2889 break;
2890 }
2891 default:
2892 fprintf (stderr, "Bad switch\n");
2893 abort ();
2894 }
2895
2896 #ifdef DEBUG
2897 printf("DBG: Multiply: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2898 #endif /* DEBUG */
2899
2900 return(result);
2901 }
2902
2903 uword64
2904 Divide(op1,op2,fmt)
2905 uword64 op1;
2906 uword64 op2;
2907 FP_formats fmt;
2908 {
2909 uword64 result = 0;
2910
2911 #ifdef DEBUG
2912 printf("DBG: Divide: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
2913 #endif /* DEBUG */
2914
2915 /* The registers must specify FPRs valid for operands of type
2916 "fmt". If they are not valid, the result is undefined. */
2917
2918 /* The format type should already have been checked: */
2919 switch (fmt) {
2920 case fmt_single:
2921 {
2922 sim_fpu wop1;
2923 sim_fpu wop2;
2924 sim_fpu ans;
2925 unsigned32 res;
2926 sim_fpu_32to (&wop1, op1);
2927 sim_fpu_32to (&wop2, op2);
2928 sim_fpu_div (&ans, &wop1, &wop2);
2929 sim_fpu_to32 (&res, &ans);
2930 result = res;
2931 break;
2932 }
2933 case fmt_double:
2934 {
2935 sim_fpu wop1;
2936 sim_fpu wop2;
2937 sim_fpu ans;
2938 unsigned64 res;
2939 sim_fpu_64to (&wop1, op1);
2940 sim_fpu_64to (&wop2, op2);
2941 sim_fpu_div (&ans, &wop1, &wop2);
2942 sim_fpu_to64 (&res, &ans);
2943 result = res;
2944 break;
2945 }
2946 default:
2947 fprintf (stderr, "Bad switch\n");
2948 abort ();
2949 }
2950
2951 #ifdef DEBUG
2952 printf("DBG: Divide: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
2953 #endif /* DEBUG */
2954
2955 return(result);
2956 }
2957
2958 uword64 UNUSED
2959 Recip(op,fmt)
2960 uword64 op;
2961 FP_formats fmt;
2962 {
2963 uword64 result = 0;
2964
2965 #ifdef DEBUG
2966 printf("DBG: Recip: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
2967 #endif /* DEBUG */
2968
2969 /* The registers must specify FPRs valid for operands of type
2970 "fmt". If they are not valid, the result is undefined. */
2971
2972 /* The format type should already have been checked: */
2973 switch (fmt) {
2974 case fmt_single:
2975 {
2976 sim_fpu wop;
2977 sim_fpu ans;
2978 unsigned32 res;
2979 sim_fpu_32to (&wop, op);
2980 sim_fpu_inv (&ans, &wop);
2981 sim_fpu_to32 (&res, &ans);
2982 result = res;
2983 break;
2984 }
2985 case fmt_double:
2986 {
2987 sim_fpu wop;
2988 sim_fpu ans;
2989 unsigned64 res;
2990 sim_fpu_64to (&wop, op);
2991 sim_fpu_inv (&ans, &wop);
2992 sim_fpu_to64 (&res, &ans);
2993 result = res;
2994 break;
2995 }
2996 default:
2997 fprintf (stderr, "Bad switch\n");
2998 abort ();
2999 }
3000
3001 #ifdef DEBUG
3002 printf("DBG: Recip: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3003 #endif /* DEBUG */
3004
3005 return(result);
3006 }
3007
3008 uword64
3009 SquareRoot(op,fmt)
3010 uword64 op;
3011 FP_formats fmt;
3012 {
3013 uword64 result = 0;
3014
3015 #ifdef DEBUG
3016 printf("DBG: SquareRoot: %s: op = 0x%s\n",DOFMT(fmt),pr_addr(op));
3017 #endif /* DEBUG */
3018
3019 /* The registers must specify FPRs valid for operands of type
3020 "fmt". If they are not valid, the result is undefined. */
3021
3022 /* The format type should already have been checked: */
3023 switch (fmt) {
3024 case fmt_single:
3025 {
3026 sim_fpu wop;
3027 sim_fpu ans;
3028 unsigned32 res;
3029 sim_fpu_32to (&wop, op);
3030 sim_fpu_sqrt (&ans, &wop);
3031 sim_fpu_to32 (&res, &ans);
3032 result = res;
3033 break;
3034 }
3035 case fmt_double:
3036 {
3037 sim_fpu wop;
3038 sim_fpu ans;
3039 unsigned64 res;
3040 sim_fpu_64to (&wop, op);
3041 sim_fpu_sqrt (&ans, &wop);
3042 sim_fpu_to64 (&res, &ans);
3043 result = res;
3044 break;
3045 }
3046 default:
3047 fprintf (stderr, "Bad switch\n");
3048 abort ();
3049 }
3050
3051 #ifdef DEBUG
3052 printf("DBG: SquareRoot: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3053 #endif /* DEBUG */
3054
3055 return(result);
3056 }
3057
3058 #if 0
3059 uword64
3060 Max (uword64 op1,
3061 uword64 op2,
3062 FP_formats fmt)
3063 {
3064 int cmp;
3065 unsigned64 result;
3066
3067 #ifdef DEBUG
3068 printf("DBG: Max: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
3069 #endif /* DEBUG */
3070
3071 /* The registers must specify FPRs valid for operands of type
3072 "fmt". If they are not valid, the result is undefined. */
3073
3074 /* The format type should already have been checked: */
3075 switch (fmt)
3076 {
3077 case fmt_single:
3078 {
3079 sim_fpu wop1;
3080 sim_fpu wop2;
3081 sim_fpu_32to (&wop1, op1);
3082 sim_fpu_32to (&wop2, op2);
3083 cmp = sim_fpu_cmp (&wop1, &wop2);
3084 break;
3085 }
3086 case fmt_double:
3087 {
3088 sim_fpu wop1;
3089 sim_fpu wop2;
3090 sim_fpu_64to (&wop1, op1);
3091 sim_fpu_64to (&wop2, op2);
3092 cmp = sim_fpu_cmp (&wop1, &wop2);
3093 break;
3094 }
3095 default:
3096 fprintf (stderr, "Bad switch\n");
3097 abort ();
3098 }
3099
3100 switch (cmp)
3101 {
3102 case SIM_FPU_IS_SNAN:
3103 case SIM_FPU_IS_QNAN:
3104 result = op1;
3105 case SIM_FPU_IS_NINF:
3106 case SIM_FPU_IS_NNUMBER:
3107 case SIM_FPU_IS_NDENORM:
3108 case SIM_FPU_IS_NZERO:
3109 result = op2; /* op1 - op2 < 0 */
3110 case SIM_FPU_IS_PINF:
3111 case SIM_FPU_IS_PNUMBER:
3112 case SIM_FPU_IS_PDENORM:
3113 case SIM_FPU_IS_PZERO:
3114 result = op1; /* op1 - op2 > 0 */
3115 default:
3116 fprintf (stderr, "Bad switch\n");
3117 abort ();
3118 }
3119
3120 #ifdef DEBUG
3121 printf("DBG: Max: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3122 #endif /* DEBUG */
3123
3124 return(result);
3125 }
3126 #endif
3127
3128 #if 0
3129 uword64
3130 Min (uword64 op1,
3131 uword64 op2,
3132 FP_formats fmt)
3133 {
3134 int cmp;
3135 unsigned64 result;
3136
3137 #ifdef DEBUG
3138 printf("DBG: Min: %s: op1 = 0x%s : op2 = 0x%s\n",DOFMT(fmt),pr_addr(op1),pr_addr(op2));
3139 #endif /* DEBUG */
3140
3141 /* The registers must specify FPRs valid for operands of type
3142 "fmt". If they are not valid, the result is undefined. */
3143
3144 /* The format type should already have been checked: */
3145 switch (fmt)
3146 {
3147 case fmt_single:
3148 {
3149 sim_fpu wop1;
3150 sim_fpu wop2;
3151 sim_fpu_32to (&wop1, op1);
3152 sim_fpu_32to (&wop2, op2);
3153 cmp = sim_fpu_cmp (&wop1, &wop2);
3154 break;
3155 }
3156 case fmt_double:
3157 {
3158 sim_fpu wop1;
3159 sim_fpu wop2;
3160 sim_fpu_64to (&wop1, op1);
3161 sim_fpu_64to (&wop2, op2);
3162 cmp = sim_fpu_cmp (&wop1, &wop2);
3163 break;
3164 }
3165 default:
3166 fprintf (stderr, "Bad switch\n");
3167 abort ();
3168 }
3169
3170 switch (cmp)
3171 {
3172 case SIM_FPU_IS_SNAN:
3173 case SIM_FPU_IS_QNAN:
3174 result = op1;
3175 case SIM_FPU_IS_NINF:
3176 case SIM_FPU_IS_NNUMBER:
3177 case SIM_FPU_IS_NDENORM:
3178 case SIM_FPU_IS_NZERO:
3179 result = op1; /* op1 - op2 < 0 */
3180 case SIM_FPU_IS_PINF:
3181 case SIM_FPU_IS_PNUMBER:
3182 case SIM_FPU_IS_PDENORM:
3183 case SIM_FPU_IS_PZERO:
3184 result = op2; /* op1 - op2 > 0 */
3185 default:
3186 fprintf (stderr, "Bad switch\n");
3187 abort ();
3188 }
3189
3190 #ifdef DEBUG
3191 printf("DBG: Min: returning 0x%s (format = %s)\n",pr_addr(result),DOFMT(fmt));
3192 #endif /* DEBUG */
3193
3194 return(result);
3195 }
3196 #endif
3197
3198 uword64
3199 convert (SIM_DESC sd,
3200 sim_cpu *cpu,
3201 address_word cia,
3202 int rm,
3203 uword64 op,
3204 FP_formats from,
3205 FP_formats to)
3206 {
3207 sim_fpu wop;
3208 sim_fpu_round round;
3209 unsigned32 result32;
3210 unsigned64 result64;
3211
3212 #ifdef DEBUG
3213 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));
3214 #endif /* DEBUG */
3215
3216 switch (rm)
3217 {
3218 case FP_RM_NEAREST:
3219 /* Round result to nearest representable value. When two
3220 representable values are equally near, round to the value
3221 that has a least significant bit of zero (i.e. is even). */
3222 round = sim_fpu_round_near;
3223 break;
3224 case FP_RM_TOZERO:
3225 /* Round result to the value closest to, and not greater in
3226 magnitude than, the result. */
3227 round = sim_fpu_round_zero;
3228 break;
3229 case FP_RM_TOPINF:
3230 /* Round result to the value closest to, and not less than,
3231 the result. */
3232 round = sim_fpu_round_up;
3233 break;
3234
3235 case FP_RM_TOMINF:
3236 /* Round result to the value closest to, and not greater than,
3237 the result. */
3238 round = sim_fpu_round_down;
3239 break;
3240 default:
3241 round = 0;
3242 fprintf (stderr, "Bad switch\n");
3243 abort ();
3244 }
3245
3246 /* Convert the input to sim_fpu internal format */
3247 switch (from)
3248 {
3249 case fmt_double:
3250 sim_fpu_64to (&wop, op);
3251 break;
3252 case fmt_single:
3253 sim_fpu_32to (&wop, op);
3254 break;
3255 case fmt_word:
3256 sim_fpu_i32to (&wop, op, round);
3257 break;
3258 case fmt_long:
3259 sim_fpu_i64to (&wop, op, round);
3260 break;
3261 default:
3262 fprintf (stderr, "Bad switch\n");
3263 abort ();
3264 }
3265
3266 /* Convert sim_fpu format into the output */
3267 /* The value WOP is converted to the destination format, rounding
3268 using mode RM. When the destination is a fixed-point format, then
3269 a source value of Infinity, NaN or one which would round to an
3270 integer outside the fixed point range then an IEEE Invalid
3271 Operation condition is raised. */
3272 switch (to)
3273 {
3274 case fmt_single:
3275 sim_fpu_round_32 (&wop, round, 0);
3276 sim_fpu_to32 (&result32, &wop);
3277 result64 = result32;
3278 break;
3279 case fmt_double:
3280 sim_fpu_round_64 (&wop, round, 0);
3281 sim_fpu_to64 (&result64, &wop);
3282 break;
3283 case fmt_word:
3284 sim_fpu_to32i (&result32, &wop, round);
3285 result64 = result32;
3286 break;
3287 case fmt_long:
3288 sim_fpu_to64i (&result64, &wop, round);
3289 break;
3290 default:
3291 result64 = 0;
3292 fprintf (stderr, "Bad switch\n");
3293 abort ();
3294 }
3295
3296 #ifdef DEBUG
3297 printf("DBG: Convert: returning 0x%s (to format = %s)\n",pr_addr(result64),DOFMT(to));
3298 #endif /* DEBUG */
3299
3300 return(result64);
3301 }
3302
3303
3304 /*-- co-processor support routines ------------------------------------------*/
3305
3306 static int UNUSED
3307 CoProcPresent(coproc_number)
3308 unsigned int coproc_number;
3309 {
3310 /* Return TRUE if simulator provides a model for the given co-processor number */
3311 return(0);
3312 }
3313
3314 void
3315 cop_lw (SIM_DESC sd,
3316 sim_cpu *cpu,
3317 address_word cia,
3318 int coproc_num,
3319 int coproc_reg,
3320 unsigned int memword)
3321 {
3322 switch (coproc_num)
3323 {
3324 case 1:
3325 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3326 {
3327 #ifdef DEBUG
3328 printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword));
3329 #endif
3330 StoreFPR(coproc_reg,fmt_word,(uword64)memword);
3331 FPR_STATE[coproc_reg] = fmt_uninterpreted;
3332 break;
3333 }
3334
3335 default:
3336 #if 0 /* this should be controlled by a configuration option */
3337 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));
3338 #endif
3339 break;
3340 }
3341
3342 return;
3343 }
3344
3345 void
3346 cop_ld (SIM_DESC sd,
3347 sim_cpu *cpu,
3348 address_word cia,
3349 int coproc_num,
3350 int coproc_reg,
3351 uword64 memword)
3352 {
3353 switch (coproc_num) {
3354 case 1:
3355 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3356 {
3357 StoreFPR(coproc_reg,fmt_uninterpreted,memword);
3358 break;
3359 }
3360
3361 default:
3362 #if 0 /* this message should be controlled by a configuration option */
3363 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));
3364 #endif
3365 break;
3366 }
3367
3368 return;
3369 }
3370
3371
3372 /* start-sanitize-sky */
3373 #ifdef TARGET_SKY
3374 void
3375 cop_lq (SIM_DESC sd,
3376 sim_cpu *cpu,
3377 address_word cia,
3378 int coproc_num,
3379 int coproc_reg,
3380 unsigned128 memword)
3381 {
3382 switch (coproc_num)
3383 {
3384 case 2:
3385 /* XXX COP2 */
3386 break;
3387
3388 default:
3389 sim_io_printf(sd,"COP_LQ(%d,%d,??) at PC = 0x%s : TODO (architecture specific)\n",
3390 coproc_num,coproc_reg,pr_addr(cia));
3391 break;
3392 }
3393
3394 return;
3395 }
3396 #endif /* TARGET_SKY */
3397 /* end-sanitize-sky */
3398
3399
3400 unsigned int
3401 cop_sw (SIM_DESC sd,
3402 sim_cpu *cpu,
3403 address_word cia,
3404 int coproc_num,
3405 int coproc_reg)
3406 {
3407 unsigned int value = 0;
3408
3409 switch (coproc_num)
3410 {
3411 case 1:
3412 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3413 {
3414 FP_formats hold;
3415 hold = FPR_STATE[coproc_reg];
3416 FPR_STATE[coproc_reg] = fmt_word;
3417 value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
3418 FPR_STATE[coproc_reg] = hold;
3419 break;
3420 }
3421
3422 default:
3423 #if 0 /* should be controlled by configuration option */
3424 sim_io_printf(sd,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));
3425 #endif
3426 break;
3427 }
3428
3429 return(value);
3430 }
3431
3432 uword64
3433 cop_sd (SIM_DESC sd,
3434 sim_cpu *cpu,
3435 address_word cia,
3436 int coproc_num,
3437 int coproc_reg)
3438 {
3439 uword64 value = 0;
3440 switch (coproc_num)
3441 {
3442 case 1:
3443 if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
3444 {
3445 value = ValueFPR(coproc_reg,fmt_uninterpreted);
3446 break;
3447 }
3448
3449 default:
3450 #if 0 /* should be controlled by configuration option */
3451 sim_io_printf(sd,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));
3452 #endif
3453 break;
3454 }
3455
3456 return(value);
3457 }
3458
3459
3460 /* start-sanitize-sky */
3461 #ifdef TARGET_SKY
3462 unsigned128
3463 cop_sq (SIM_DESC sd,
3464 sim_cpu *cpu,
3465 address_word cia,
3466 int coproc_num,
3467 int coproc_reg)
3468 {
3469 unsigned128 value = U16_8(0, 0);
3470 switch (coproc_num)
3471 {
3472 case 2:
3473 /* XXX COP2 */
3474 break;
3475
3476 default:
3477 sim_io_printf(sd,"COP_SQ(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",
3478 coproc_num,coproc_reg,pr_addr(cia));
3479 break;
3480 }
3481
3482 return(value);
3483 }
3484 #endif /* TARGET_SKY */
3485 /* end-sanitize-sky */
3486
3487
3488 void
3489 decode_coproc (SIM_DESC sd,
3490 sim_cpu *cpu,
3491 address_word cia,
3492 unsigned int instruction)
3493 {
3494 int coprocnum = ((instruction >> 26) & 3);
3495
3496 switch (coprocnum)
3497 {
3498 case 0: /* standard CPU control and cache registers */
3499 {
3500 int code = ((instruction >> 21) & 0x1F);
3501 /* R4000 Users Manual (second edition) lists the following CP0
3502 instructions:
3503 DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
3504 DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
3505 MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
3506 MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
3507 TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
3508 TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
3509 TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
3510 TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
3511 CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
3512 ERET Exception return (VR4100 = 01000010000000000000000000011000)
3513 */
3514 if (((code == 0x00) || (code == 0x04)) && ((instruction & 0x7FF) == 0))
3515 {
3516 int rt = ((instruction >> 16) & 0x1F);
3517 int rd = ((instruction >> 11) & 0x1F);
3518
3519 switch (rd) /* NOTEs: Standard CP0 registers */
3520 {
3521 /* 0 = Index R4000 VR4100 VR4300 */
3522 /* 1 = Random R4000 VR4100 VR4300 */
3523 /* 2 = EntryLo0 R4000 VR4100 VR4300 */
3524 /* 3 = EntryLo1 R4000 VR4100 VR4300 */
3525 /* 4 = Context R4000 VR4100 VR4300 */
3526 /* 5 = PageMask R4000 VR4100 VR4300 */
3527 /* 6 = Wired R4000 VR4100 VR4300 */
3528 /* 8 = BadVAddr R4000 VR4100 VR4300 */
3529 /* 9 = Count R4000 VR4100 VR4300 */
3530 /* 10 = EntryHi R4000 VR4100 VR4300 */
3531 /* 11 = Compare R4000 VR4100 VR4300 */
3532 /* 12 = SR R4000 VR4100 VR4300 */
3533 case 12:
3534 if (code == 0x00)
3535 GPR[rt] = SR;
3536 else
3537 SR = GPR[rt];
3538 break;
3539 /* 13 = Cause R4000 VR4100 VR4300 */
3540 case 13:
3541 if (code == 0x00)
3542 GPR[rt] = CAUSE;
3543 else
3544 CAUSE = GPR[rt];
3545 break;
3546 /* 14 = EPC R4000 VR4100 VR4300 */
3547 /* 15 = PRId R4000 VR4100 VR4300 */
3548 #ifdef SUBTARGET_R3900
3549 /* 16 = Debug */
3550 case 16:
3551 if (code == 0x00)
3552 GPR[rt] = Debug;
3553 else
3554 Debug = GPR[rt];
3555 break;
3556 #else
3557 /* 16 = Config R4000 VR4100 VR4300 */
3558 case 16:
3559 if (code == 0x00)
3560 GPR[rt] = C0_CONFIG;
3561 else
3562 C0_CONFIG = GPR[rt];
3563 break;
3564 #endif
3565 #ifdef SUBTARGET_R3900
3566 /* 17 = Debug */
3567 case 17:
3568 if (code == 0x00)
3569 GPR[rt] = DEPC;
3570 else
3571 DEPC = GPR[rt];
3572 break;
3573 #else
3574 /* 17 = LLAddr R4000 VR4100 VR4300 */
3575 #endif
3576 /* 18 = WatchLo R4000 VR4100 VR4300 */
3577 /* 19 = WatchHi R4000 VR4100 VR4300 */
3578 /* 20 = XContext R4000 VR4100 VR4300 */
3579 /* 26 = PErr or ECC R4000 VR4100 VR4300 */
3580 /* 27 = CacheErr R4000 VR4100 */
3581 /* 28 = TagLo R4000 VR4100 VR4300 */
3582 /* 29 = TagHi R4000 VR4100 VR4300 */
3583 /* 30 = ErrorEPC R4000 VR4100 VR4300 */
3584 GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
3585 /* CPR[0,rd] = GPR[rt]; */
3586 default:
3587 if (code == 0x00)
3588 sim_io_printf(sd,"Warning: MFC0 %d,%d ignored (architecture specific)\n",rt,rd);
3589 else
3590 sim_io_printf(sd,"Warning: MTC0 %d,%d ignored (architecture specific)\n",rt,rd);
3591 }
3592 }
3593 else if (code == 0x10 && (instruction & 0x3f) == 0x18)
3594 {
3595 /* ERET */
3596 if (SR & status_ERL)
3597 {
3598 /* Oops, not yet available */
3599 sim_io_printf(sd,"Warning: ERET when SR[ERL] set not handled yet");
3600 PC = EPC;
3601 SR &= ~status_ERL;
3602 }
3603 else
3604 {
3605 PC = EPC;
3606 SR &= ~status_EXL;
3607 }
3608 }
3609 else if (code == 0x10 && (instruction & 0x3f) == 0x10)
3610 {
3611 /* RFE */
3612 }
3613 else if (code == 0x10 && (instruction & 0x3f) == 0x1F)
3614 {
3615 /* DERET */
3616 Debug &= ~Debug_DM;
3617 DELAYSLOT();
3618 DSPC = DEPC;
3619 }
3620 else
3621 sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia));
3622 /* TODO: When executing an ERET or RFE instruction we should
3623 clear LLBIT, to ensure that any out-standing atomic
3624 read/modify/write sequence fails. */
3625 }
3626 break;
3627
3628 case 2: /* undefined co-processor */
3629 {
3630 int handle = 0;
3631
3632 /* start-sanitize-sky */
3633 #ifdef TARGET_SKY
3634 /* On the R5900, this refers to a "VU" vector co-processor. */
3635
3636 int i_25_21 = (instruction >> 21) & 0x1f;
3637 int i_20_16 = (instruction >> 16) & 0x1f;
3638 int i_15_11 = (instruction >> 11) & 0x1f;
3639 int i_15_0 = instruction & 0xffff;
3640 int i_10_1 = (instruction >> 1) & 0x3ff;
3641 int i_5_0 = instruction & 0x03f;
3642 int interlock = instruction & 0x01;
3643 int co = (instruction >> 25) & 0x01;
3644 /* setup for semantic.c-like actions below */
3645 typedef unsigned_4 instruction_word;
3646 int CIA = cia;
3647 int NIA = cia + 4;
3648 sim_cpu* CPU_ = cpu;
3649
3650 handle = 1;
3651
3652 /* test COP2 usability */
3653 if(! (SR & status_CU2))
3654 {
3655 SignalException(CoProcessorUnusable,instruction);
3656 /* NOTREACHED */
3657 }
3658
3659 /* classify & execute basic COP2 instructions */
3660 if(i_25_21 == 0x08 && i_20_16 == 0x00) /* BC2F */
3661 {
3662 address_word offset = EXTEND16(i_15_0) << 2;
3663 if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
3664 }
3665 else if(i_25_21 == 0x08 && i_20_16==0x02) /* BC2FL */
3666 {
3667 address_word offset = EXTEND16(i_15_0) << 2;
3668 if(! vu0_busy()) DELAY_SLOT(cia + 4 + offset);
3669 else NULLIFY_NEXT_INSTRUCTION();
3670 }
3671 else if(i_25_21 == 0x08 && i_20_16 == 0x01) /* BC2T */
3672 {
3673 address_word offset = EXTEND16(i_15_0) << 2;
3674 if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
3675 }
3676 else if(i_25_21 == 0x08 && i_20_16 == 0x03) /* BC2TL */
3677 {
3678 address_word offset = EXTEND16(i_15_0) << 2;
3679 if(vu0_busy()) DELAY_SLOT(cia + 4 + offset);
3680 else NULLIFY_NEXT_INSTRUCTION();
3681 }
3682 else if((i_25_21 == 0x02 && i_10_1 == 0x000) || /* CFC2 */
3683 (i_25_21 == 0x01)) /* QMFC2 */
3684 {
3685 int rt = i_20_16;
3686 int id = i_15_11;
3687 address_word vu_cr_addr; /* VU control register address */
3688 unsigned_4 data;
3689
3690 /* interlock checking */
3691 if(vu0_busy_in_macro_mode()) /* busy in macro mode */
3692 {
3693 /* interlock bit invalid here */
3694 if(interlock)
3695 ; /* XXX: warning */
3696
3697 /* always check data hazard */
3698 while(vu0_macro_hazard_check(id))
3699 vu0_issue(sd);
3700 }
3701 else if(vu0_busy_in_micro_mode() && interlock)
3702 {
3703 while(vu0_busy_in_micro_mode())
3704 vu0_issue(sd);
3705 }
3706
3707 /* compute VU register address */
3708 if(i_25_21 == 0x01) /* QMFC2 */
3709 vu_cr_addr = VU0_REGISTER_WINDOW_START + (id * 16);
3710 else /* CFC2 */
3711 vu_cr_addr = VU0_MST + (id * 16);
3712
3713 /* read or write word */
3714 data = sim_core_read_aligned_4(cpu, cia, read_map, vu_cr_addr);
3715 GPR[rt] = EXTEND64(data);
3716 }
3717 else if((i_25_21 == 0x06 && i_10_1 == 0x000) || /* CTC2 */
3718 (i_25_21 == 0x05)) /* QMTC2 */
3719 {
3720 int rt = i_20_16;
3721 int id = i_15_11;
3722 address_word vu_cr_addr; /* VU control register address */
3723 unsigned_4 data;
3724
3725 /* interlock checking */
3726 if(vu0_busy_in_macro_mode()) /* busy in macro mode */
3727 {
3728 /* interlock bit invalid here */
3729 if(interlock)
3730 ; /* XXX: warning */
3731
3732 /* always check data hazard */
3733 while(vu0_macro_hazard_check(id))
3734 vu0_issue(sd);
3735 }
3736 else if(vu0_busy_in_micro_mode())
3737 {
3738 if(interlock)
3739 {
3740 while(! vu0_micro_interlock_released())
3741 vu0_issue(sd);
3742 }
3743 }
3744
3745 /* compute VU register address */
3746 if(i_25_21 == 0x05) /* QMTC2 */
3747 vu_cr_addr = VU0_REGISTER_WINDOW_START + (id * 16);
3748 else /* CTC2 */
3749 vu_cr_addr = VU0_MST + (id * 16);
3750
3751 data = GPR[rt];
3752 sim_core_write_aligned_4(cpu, cia, write_map, vu_cr_addr, data);
3753 }
3754 else if( 0 /* XXX: ... upper ... */)
3755 {
3756 unsigned_4 vu_upper, vu_lower;
3757 vu_upper =
3758 0x00000000 | /* bits 31 .. 25 */
3759 instruction & 0x01ffffff; /* bits 24 .. 0 */
3760 vu_lower = 0x8000033c; /* NOP */
3761
3762 while(vu0_busy_in_micro_mode())
3763 vu0_issue(sd);
3764
3765 vu0_macro_issue(vu_upper, vu_lower);
3766 }
3767 else if( 0 /* XXX: ... lower ... */)
3768 {
3769 unsigned_4 vu_upper, vu_lower;
3770 vu_upper = 0x000002ff; /* NOP */
3771 vu_lower =
3772 0x10000000 | /* bits 31 .. 25 */
3773 instruction & 0x01ffffff; /* bits 24 .. 0 */
3774
3775 while(vu0_busy_in_micro_mode())
3776 vu0_issue(sd);
3777
3778 vu0_macro_issue(vu_upper, vu_lower);
3779 }
3780 /* XXX */
3781 /* ... other COP2 instructions ... */
3782 else
3783 {
3784 SignalException(ReservedInstruction, instruction);
3785 /* NOTREACHED */
3786 }
3787
3788 /* cleanup for semantic.c-like actions above */
3789 PC = NIA;
3790
3791 #endif /* TARGET_SKY */
3792 /* end-sanitize-sky */
3793
3794 if(! handle)
3795 {
3796 sim_io_eprintf(sd,"COP2 instruction 0x%08X at PC = 0x%s : No handler present\n",
3797 instruction,pr_addr(cia));
3798 }
3799 }
3800 break;
3801
3802 case 1: /* should not occur (FPU co-processor) */
3803 case 3: /* should not occur (FPU co-processor) */
3804 SignalException(ReservedInstruction,instruction);
3805 break;
3806 }
3807
3808 return;
3809 }
3810
3811
3812 /*-- instruction simulation -------------------------------------------------*/
3813
3814 /* When the IGEN simulator is being built, the function below is be
3815 replaced by a generated version. However, WITH_IGEN == 2 indicates
3816 that the fubction below should be compiled but under a different
3817 name (to allow backward compatibility) */
3818
3819 #if (WITH_IGEN != 1)
3820 #if (WITH_IGEN > 1)
3821 void old_engine_run PARAMS ((SIM_DESC sd, int next_cpu_nr, int siggnal));
3822 void
3823 old_engine_run (sd, next_cpu_nr, nr_cpus, siggnal)
3824 #else
3825 void
3826 sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal)
3827 #endif
3828 SIM_DESC sd;
3829 int next_cpu_nr; /* ignore */
3830 int nr_cpus; /* ignore */
3831 int siggnal; /* ignore */
3832 {
3833 sim_cpu *cpu = STATE_CPU (sd, 0); /* hardwire to cpu 0 */
3834 #if !defined(FASTSIM)
3835 unsigned int pipeline_count = 1;
3836 #endif
3837
3838 #ifdef DEBUG
3839 if (STATE_MEMORY (sd) == NULL) {
3840 printf("DBG: simulate() entered with no memory\n");
3841 exit(1);
3842 }
3843 #endif /* DEBUG */
3844
3845 #if 0 /* Disabled to check that everything works OK */
3846 /* The VR4300 seems to sign-extend the PC on its first
3847 access. However, this may just be because it is currently
3848 configured in 32bit mode. However... */
3849 PC = SIGNEXTEND(PC,32);
3850 #endif
3851
3852 /* main controlling loop */
3853 while (1) {
3854 /* vaddr is slowly being replaced with cia - current instruction
3855 address */
3856 address_word cia = (uword64)PC;
3857 address_word vaddr = cia;
3858 address_word paddr;
3859 int cca;
3860 unsigned int instruction; /* uword64? what's this used for? FIXME! */
3861
3862 #ifdef DEBUG
3863 {
3864 printf("DBG: state = 0x%08X :",state);
3865 if (state & simHALTEX) printf(" simHALTEX");
3866 if (state & simHALTIN) printf(" simHALTIN");
3867 printf("\n");
3868 }
3869 #endif /* DEBUG */
3870
3871 DSSTATE = (STATE & simDELAYSLOT);
3872 #ifdef DEBUG
3873 if (dsstate)
3874 sim_io_printf(sd,"DBG: DSPC = 0x%s\n",pr_addr(DSPC));
3875 #endif /* DEBUG */
3876
3877 /* Fetch the next instruction from the simulator memory: */
3878 if (AddressTranslation(cia,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) {
3879 if ((vaddr & 1) == 0) {
3880 /* Copy the action of the LW instruction */
3881 unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 2) : 0);
3882 unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 2) : 0);
3883 uword64 value;
3884 unsigned int byte;
3885 paddr = ((paddr & ~LOADDRMASK) | ((paddr & LOADDRMASK) ^ (reverse << 2)));
3886 LoadMemory(&value,NULL,cca,AccessLength_WORD,paddr,vaddr,isINSTRUCTION,isREAL);
3887 byte = ((vaddr & LOADDRMASK) ^ (bigend << 2));
3888 instruction = ((value >> (8 * byte)) & 0xFFFFFFFF);
3889 } else {
3890 /* Copy the action of the LH instruction */
3891 unsigned int reverse = (ReverseEndian ? (LOADDRMASK >> 1) : 0);
3892 unsigned int bigend = (BigEndianCPU ? (LOADDRMASK >> 1) : 0);
3893 uword64 value;
3894 unsigned int byte;
3895 paddr = (((paddr & ~ (uword64) 1) & ~LOADDRMASK)
3896 | (((paddr & ~ (uword64) 1) & LOADDRMASK) ^ (reverse << 1)));
3897 LoadMemory(&value,NULL,cca, AccessLength_HALFWORD,
3898 paddr & ~ (uword64) 1,
3899 vaddr, isINSTRUCTION, isREAL);
3900 byte = (((vaddr &~ (uword64) 1) & LOADDRMASK) ^ (bigend << 1));
3901 instruction = ((value >> (8 * byte)) & 0xFFFF);
3902 }
3903 } else {
3904 fprintf(stderr,"Cannot translate address for PC = 0x%s failed\n",pr_addr(PC));
3905 exit(1);
3906 }
3907
3908 #ifdef DEBUG
3909 sim_io_printf(sd,"DBG: fetched 0x%08X from PC = 0x%s\n",instruction,pr_addr(PC));
3910 #endif /* DEBUG */
3911
3912 /* This is required by exception processing, to ensure that we can
3913 cope with exceptions in the delay slots of branches that may
3914 already have changed the PC. */
3915 if ((vaddr & 1) == 0)
3916 PC += 4; /* increment ready for the next fetch */
3917 else
3918 PC += 2;
3919 /* NOTE: If we perform a delay slot change to the PC, this
3920 increment is not requuired. However, it would make the
3921 simulator more complicated to try and avoid this small hit. */
3922
3923 /* Currently this code provides a simple model. For more
3924 complicated models we could perform exception status checks at
3925 this point, and set the simSTOP state as required. This could
3926 also include processing any hardware interrupts raised by any
3927 I/O model attached to the simulator context.
3928
3929 Support for "asynchronous" I/O events within the simulated world
3930 could be providing by managing a counter, and calling a I/O
3931 specific handler when a particular threshold is reached. On most
3932 architectures a decrement and check for zero operation is
3933 usually quicker than an increment and compare. However, the
3934 process of managing a known value decrement to zero, is higher
3935 than the cost of using an explicit value UINT_MAX into the
3936 future. Which system is used will depend on how complicated the
3937 I/O model is, and how much it is likely to affect the simulator
3938 bandwidth.
3939
3940 If events need to be scheduled further in the future than
3941 UINT_MAX event ticks, then the I/O model should just provide its
3942 own counter, triggered from the event system. */
3943
3944 /* MIPS pipeline ticks. To allow for future support where the
3945 pipeline hit of individual instructions is known, this control
3946 loop manages a "pipeline_count" variable. It is initialised to
3947 1 (one), and will only be changed by the simulator engine when
3948 executing an instruction. If the engine does not have access to
3949 pipeline cycle count information then all instructions will be
3950 treated as using a single cycle. NOTE: A standard system is not
3951 provided by the default simulator because different MIPS
3952 architectures have different cycle counts for the same
3953 instructions.
3954
3955 [NOTE: pipeline_count has been replaced the event queue] */
3956
3957 /* shuffle the floating point status pipeline state */
3958 ENGINE_ISSUE_PREFIX_HOOK();
3959
3960 /* NOTE: For multi-context simulation environments the "instruction"
3961 variable should be local to this routine. */
3962
3963 /* Shorthand accesses for engine. Note: If we wanted to use global
3964 variables (and a single-threaded simulator engine), then we can
3965 create the actual variables with these names. */
3966
3967 if (!(STATE & simSKIPNEXT)) {
3968 /* Include the simulator engine */
3969 #include "oengine.c"
3970 #if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT)
3971 #error "Mismatch between run-time simulator code and simulation engine"
3972 #endif
3973 #if (WITH_TARGET_WORD_BITSIZE != GPRLEN)
3974 #error "Mismatch between configure WITH_TARGET_WORD_BITSIZE and gencode GPRLEN"
3975 #endif
3976 #if ((WITH_FLOATING_POINT == HARD_FLOATING_POINT) != defined (HASFPU))
3977 #error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU"
3978 #endif
3979
3980 #if defined(WARN_LOHI)
3981 /* Decrement the HI/LO validity ticks */
3982 if (HIACCESS > 0)
3983 HIACCESS--;
3984 if (LOACCESS > 0)
3985 LOACCESS--;
3986 /* start-sanitize-r5900 */
3987 if (HI1ACCESS > 0)
3988 HI1ACCESS--;
3989 if (LO1ACCESS > 0)
3990 LO1ACCESS--;
3991 /* end-sanitize-r5900 */
3992 #endif /* WARN_LOHI */
3993
3994 /* For certain MIPS architectures, GPR[0] is hardwired to zero. We
3995 should check for it being changed. It is better doing it here,
3996 than within the simulator, since it will help keep the simulator
3997 small. */
3998 if (ZERO != 0) {
3999 #if defined(WARN_ZERO)
4000 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));
4001 #endif /* WARN_ZERO */
4002 ZERO = 0; /* reset back to zero before next instruction */
4003 }
4004 } else /* simSKIPNEXT check */
4005 STATE &= ~simSKIPNEXT;
4006
4007 /* If the delay slot was active before the instruction is
4008 executed, then update the PC to its new value: */
4009 if (DSSTATE) {
4010 #ifdef DEBUG
4011 printf("DBG: dsstate set before instruction execution - updating PC to 0x%s\n",pr_addr(DSPC));
4012 #endif /* DEBUG */
4013 PC = DSPC;
4014 CANCELDELAYSLOT();
4015 }
4016
4017 if (MIPSISA < 4)
4018 PENDING_TICK();
4019
4020 #if !defined(FASTSIM)
4021 if (sim_events_tickn (sd, pipeline_count))
4022 {
4023 /* cpu->cia = cia; */
4024 sim_events_process (sd);
4025 }
4026 #else
4027 if (sim_events_tick (sd))
4028 {
4029 /* cpu->cia = cia; */
4030 sim_events_process (sd);
4031 }
4032 #endif /* FASTSIM */
4033 }
4034 }
4035 #endif
4036
4037
4038 /* This code copied from gdb's utils.c. Would like to share this code,
4039 but don't know of a common place where both could get to it. */
4040
4041 /* Temporary storage using circular buffer */
4042 #define NUMCELLS 16
4043 #define CELLSIZE 32
4044 static char*
4045 get_cell()
4046 {
4047 static char buf[NUMCELLS][CELLSIZE];
4048 static int cell=0;
4049 if (++cell>=NUMCELLS) cell=0;
4050 return buf[cell];
4051 }
4052
4053 /* Print routines to handle variable size regs, etc */
4054
4055 /* Eliminate warning from compiler on 32-bit systems */
4056 static int thirty_two = 32;
4057
4058 char*
4059 pr_addr(addr)
4060 SIM_ADDR addr;
4061 {
4062 char *paddr_str=get_cell();
4063 switch (sizeof(addr))
4064 {
4065 case 8:
4066 sprintf(paddr_str,"%08lx%08lx",
4067 (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff));
4068 break;
4069 case 4:
4070 sprintf(paddr_str,"%08lx",(unsigned long)addr);
4071 break;
4072 case 2:
4073 sprintf(paddr_str,"%04x",(unsigned short)(addr&0xffff));
4074 break;
4075 default:
4076 sprintf(paddr_str,"%x",addr);
4077 }
4078 return paddr_str;
4079 }
4080
4081 char*
4082 pr_uword64(addr)
4083 uword64 addr;
4084 {
4085 char *paddr_str=get_cell();
4086 sprintf(paddr_str,"%08lx%08lx",
4087 (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff));
4088 return paddr_str;
4089 }
4090
4091
4092 void
4093 pending_tick (SIM_DESC sd,
4094 sim_cpu *cpu,
4095 address_word cia)
4096 {
4097 if (PENDING_TRACE)
4098 sim_io_printf (sd, "PENDING_DRAIN - pending_in = %d, pending_out = %d, pending_total = %d\n", PENDING_IN, PENDING_OUT, PENDING_TOTAL);
4099 if (PENDING_OUT != PENDING_IN)
4100 {
4101 int loop;
4102 int index = PENDING_OUT;
4103 int total = PENDING_TOTAL;
4104 if (PENDING_TOTAL == 0)
4105 sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n");
4106 for (loop = 0; (loop < total); loop++)
4107 {
4108 if (PENDING_SLOT_DEST[index] != NULL)
4109 {
4110 PENDING_SLOT_DELAY[index] -= 1;
4111 if (PENDING_SLOT_DELAY[index] == 0)
4112 {
4113 if (PENDING_SLOT_BIT[index] >= 0)
4114 switch (PENDING_SLOT_SIZE[index])
4115 {
4116 case 32:
4117 if (PENDING_SLOT_VALUE[index])
4118 *(unsigned32*)PENDING_SLOT_DEST[index] |=
4119 BIT32 (PENDING_SLOT_BIT[index]);
4120 else
4121 *(unsigned32*)PENDING_SLOT_DEST[index] &=
4122 BIT32 (PENDING_SLOT_BIT[index]);
4123 break;
4124 case 64:
4125 if (PENDING_SLOT_VALUE[index])
4126 *(unsigned64*)PENDING_SLOT_DEST[index] |=
4127 BIT64 (PENDING_SLOT_BIT[index]);
4128 else
4129 *(unsigned64*)PENDING_SLOT_DEST[index] &=
4130 BIT64 (PENDING_SLOT_BIT[index]);
4131 break;
4132 break;
4133 }
4134 else
4135 switch (PENDING_SLOT_SIZE[index])
4136 {
4137 case 32:
4138 *(unsigned32*)PENDING_SLOT_DEST[index] =
4139 PENDING_SLOT_VALUE[index];
4140 break;
4141 case 64:
4142 *(unsigned64*)PENDING_SLOT_DEST[index] =
4143 PENDING_SLOT_VALUE[index];
4144 break;
4145 }
4146 }
4147 if (PENDING_OUT == index)
4148 {
4149 PENDING_SLOT_DEST[index] = NULL;
4150 PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
4151 PENDING_TOTAL--;
4152 }
4153 }
4154 }
4155 index = (index + 1) % PSLOTS;
4156 }
4157 }
4158
4159 /*---------------------------------------------------------------------------*/
4160 /*> EOF interp.c <*/
This page took 0.114537 seconds and 5 git commands to generate.