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