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