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