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