OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [sim/] [mips/] [interp.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.