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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [sim/] [mn10300/] [interp.c] - Blame information for rev 868

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
#include <signal.h>
2
 
3
#include "sim-main.h"
4
#include "sim-options.h"
5
#include "sim-hw.h"
6
 
7
#include "sysdep.h"
8
#include "bfd.h"
9
#include "sim-assert.h"
10
 
11
 
12
#ifdef HAVE_STDLIB_H
13
#include <stdlib.h>
14
#endif
15
 
16
#ifdef HAVE_STRING_H
17
#include <string.h>
18
#else
19
#ifdef HAVE_STRINGS_H
20
#include <strings.h>
21
#endif
22
#endif
23
 
24
#include "bfd.h"
25
 
26
#ifndef INLINE
27
#ifdef __GNUC__
28
#define INLINE inline
29
#else
30
#define INLINE
31
#endif
32
#endif
33
 
34
 
35
host_callback *mn10300_callback;
36
int mn10300_debug;
37
struct _state State;
38
 
39
 
40
/* simulation target board.  NULL=default configuration */
41
static char* board = NULL;
42
 
43
static DECLARE_OPTION_HANDLER (mn10300_option_handler);
44
 
45
enum {
46
  OPTION_BOARD = OPTION_START,
47
};
48
 
49
static SIM_RC
50
mn10300_option_handler (SIM_DESC sd,
51
                        sim_cpu *cpu,
52
                        int opt,
53
                        char *arg,
54
                        int is_command)
55
{
56
  int cpu_nr;
57
  switch (opt)
58
    {
59
    case OPTION_BOARD:
60
      {
61
        if (arg)
62
          {
63
            board = zalloc(strlen(arg) + 1);
64
            strcpy(board, arg);
65
          }
66
        return SIM_RC_OK;
67
      }
68
    }
69
 
70
  return SIM_RC_OK;
71
}
72
 
73
static const OPTION mn10300_options[] =
74
{
75
#define BOARD_AM32 "stdeval1"
76
  { {"board", required_argument, NULL, OPTION_BOARD},
77
     '\0', "none" /* rely on compile-time string concatenation for other options */
78
           "|" BOARD_AM32
79
    , "Customize simulation for a particular board.", mn10300_option_handler },
80
 
81
  { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
82
};
83
 
84
/* For compatibility */
85
SIM_DESC simulator;
86
 
87
/* These default values correspond to expected usage for the chip.  */
88
 
89
SIM_DESC
90
sim_open (SIM_OPEN_KIND kind,
91
          host_callback *cb,
92
          struct bfd *abfd,
93
          char **argv)
94
{
95
  SIM_DESC sd = sim_state_alloc (kind, cb);
96
  mn10300_callback = cb;
97
 
98
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
99
 
100
  /* for compatibility */
101
  simulator = sd;
102
 
103
  /* FIXME: should be better way of setting up interrupts.  For
104
     moment, only support watchpoints causing a breakpoint (gdb
105
     halt). */
106
  STATE_WATCHPOINTS (sd)->pc = &(PC);
107
  STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
108
  STATE_WATCHPOINTS (sd)->interrupt_handler = NULL;
109
  STATE_WATCHPOINTS (sd)->interrupt_names = NULL;
110
 
111
  if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
112
    return 0;
113
  sim_add_option_table (sd, NULL, mn10300_options);
114
 
115
  /* Allocate core managed memory */
116
  sim_do_command (sd, "memory region 0,0x100000");
117
  sim_do_command (sd, "memory region 0x40000000,0x200000");
118
 
119
  /* getopt will print the error message so we just have to exit if this fails.
120
     FIXME: Hmmm...  in the case of gdb we need getopt to call
121
     print_filtered.  */
122
  if (sim_parse_args (sd, argv) != SIM_RC_OK)
123
    {
124
      /* Uninstall the modules to avoid memory leaks,
125
         file descriptor leaks, etc.  */
126
      sim_module_uninstall (sd);
127
      return 0;
128
    }
129
 
130
  if ( NULL != board
131
       && (strcmp(board, BOARD_AM32) == 0 ) )
132
    {
133
      /* environment */
134
      STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
135
 
136
      sim_do_command (sd, "memory region 0x44000000,0x40000");
137
      sim_do_command (sd, "memory region 0x48000000,0x400000");
138
 
139
      /* device support for mn1030002 */
140
      /* interrupt controller */
141
 
142
      sim_hw_parse (sd, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
143
 
144
      /* DEBUG: NMI input's */
145
      sim_hw_parse (sd, "/glue@0x30000000/reg 0x30000000 12");
146
      sim_hw_parse (sd, "/glue@0x30000000 > int0 nmirq /mn103int");
147
      sim_hw_parse (sd, "/glue@0x30000000 > int1 watchdog /mn103int");
148
      sim_hw_parse (sd, "/glue@0x30000000 > int2 syserr /mn103int");
149
 
150
      /* DEBUG: ACK input */
151
      sim_hw_parse (sd, "/glue@0x30002000/reg 0x30002000 4");
152
      sim_hw_parse (sd, "/glue@0x30002000 > int ack /mn103int");
153
 
154
      /* DEBUG: LEVEL output */
155
      sim_hw_parse (sd, "/glue@0x30004000/reg 0x30004000 8");
156
      sim_hw_parse (sd, "/mn103int > nmi int0 /glue@0x30004000");
157
      sim_hw_parse (sd, "/mn103int > level int1 /glue@0x30004000");
158
 
159
      /* DEBUG: A bunch of interrupt inputs */
160
      sim_hw_parse (sd, "/glue@0x30006000/reg 0x30006000 32");
161
      sim_hw_parse (sd, "/glue@0x30006000 > int0 irq-0 /mn103int");
162
      sim_hw_parse (sd, "/glue@0x30006000 > int1 irq-1 /mn103int");
163
      sim_hw_parse (sd, "/glue@0x30006000 > int2 irq-2 /mn103int");
164
      sim_hw_parse (sd, "/glue@0x30006000 > int3 irq-3 /mn103int");
165
      sim_hw_parse (sd, "/glue@0x30006000 > int4 irq-4 /mn103int");
166
      sim_hw_parse (sd, "/glue@0x30006000 > int5 irq-5 /mn103int");
167
      sim_hw_parse (sd, "/glue@0x30006000 > int6 irq-6 /mn103int");
168
      sim_hw_parse (sd, "/glue@0x30006000 > int7 irq-7 /mn103int");
169
 
170
      /* processor interrupt device */
171
 
172
      /* the device */
173
      sim_hw_parse (sd, "/mn103cpu@0x20000000");
174
      sim_hw_parse (sd, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
175
 
176
      /* DEBUG: ACK output wired upto a glue device */
177
      sim_hw_parse (sd, "/glue@0x20002000");
178
      sim_hw_parse (sd, "/glue@0x20002000/reg 0x20002000 4");
179
      sim_hw_parse (sd, "/mn103cpu > ack int0 /glue@0x20002000");
180
 
181
      /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
182
      sim_hw_parse (sd, "/glue@0x20004000");
183
      sim_hw_parse (sd, "/glue@0x20004000/reg 0x20004000 12");
184
      sim_hw_parse (sd, "/glue@0x20004000 > int0 reset /mn103cpu");
185
      sim_hw_parse (sd, "/glue@0x20004000 > int1 nmi /mn103cpu");
186
      sim_hw_parse (sd, "/glue@0x20004000 > int2 level /mn103cpu");
187
 
188
      /* REAL: The processor wired up to the real interrupt controller */
189
      sim_hw_parse (sd, "/mn103cpu > ack ack /mn103int");
190
      sim_hw_parse (sd, "/mn103int > level level /mn103cpu");
191
      sim_hw_parse (sd, "/mn103int > nmi nmi /mn103cpu");
192
 
193
 
194
      /* PAL */
195
 
196
      /* the device */
197
      sim_hw_parse (sd, "/pal@0x31000000");
198
      sim_hw_parse (sd, "/pal@0x31000000/reg 0x31000000 64");
199
      sim_hw_parse (sd, "/pal@0x31000000/poll? true");
200
 
201
      /* DEBUG: PAL wired up to a glue device */
202
      sim_hw_parse (sd, "/glue@0x31002000");
203
      sim_hw_parse (sd, "/glue@0x31002000/reg 0x31002000 16");
204
      sim_hw_parse (sd, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
205
      sim_hw_parse (sd, "/pal@0x31000000 > timer int1 /glue@0x31002000");
206
      sim_hw_parse (sd, "/pal@0x31000000 > int int2 /glue@0x31002000");
207
      sim_hw_parse (sd, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
208
      sim_hw_parse (sd, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
209
      sim_hw_parse (sd, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
210
 
211
      /* REAL: The PAL wired up to the real interrupt controller */
212
      sim_hw_parse (sd, "/pal@0x31000000 > countdown irq-0 /mn103int");
213
      sim_hw_parse (sd, "/pal@0x31000000 > timer irq-1 /mn103int");
214
      sim_hw_parse (sd, "/pal@0x31000000 > int irq-2 /mn103int");
215
 
216
      /* 8 and 16 bit timers */
217
      sim_hw_parse (sd, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
218
 
219
      /* Hook timer interrupts up to interrupt controller */
220
      sim_hw_parse (sd, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
221
      sim_hw_parse (sd, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
222
      sim_hw_parse (sd, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
223
      sim_hw_parse (sd, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
224
      sim_hw_parse (sd, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
225
      sim_hw_parse (sd, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
226
      sim_hw_parse (sd, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
227
      sim_hw_parse (sd, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
228
      sim_hw_parse (sd, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
229
 
230
 
231
      /* Serial devices 0,1,2 */
232
      sim_hw_parse (sd, "/mn103ser@0x34000800/reg 0x34000800 48");
233
      sim_hw_parse (sd, "/mn103ser@0x34000800/poll? true");
234
 
235
      /* Hook serial interrupts up to interrupt controller */
236
      sim_hw_parse (sd, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
237
      sim_hw_parse (sd, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
238
      sim_hw_parse (sd, "/mn103ser > serial-1-receive serial-1-receive /mn103int");
239
      sim_hw_parse (sd, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int");
240
      sim_hw_parse (sd, "/mn103ser > serial-2-receive serial-2-receive /mn103int");
241
      sim_hw_parse (sd, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int");
242
 
243
      sim_hw_parse (sd, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
244
 
245
      /* Memory control registers */
246
      sim_do_command (sd, "memory region 0x32000020,0x30");
247
      /* Cache control register */
248
      sim_do_command (sd, "memory region 0x20000070,0x4");
249
      /* Cache purge regions */
250
      sim_do_command (sd, "memory region 0x28400000,0x800");
251
      sim_do_command (sd, "memory region 0x28401000,0x800");
252
      /* DMA registers */
253
      sim_do_command (sd, "memory region 0x32000100,0xF");
254
      sim_do_command (sd, "memory region 0x32000200,0xF");
255
      sim_do_command (sd, "memory region 0x32000400,0xF");
256
      sim_do_command (sd, "memory region 0x32000800,0xF");
257
    }
258
  else
259
    {
260
      if (board != NULL)
261
        {
262
          sim_io_eprintf (sd, "Error: Board `%s' unknown.\n", board);
263
          return 0;
264
        }
265
    }
266
 
267
 
268
 
269
  /* check for/establish the a reference program image */
270
  if (sim_analyze_program (sd,
271
                           (STATE_PROG_ARGV (sd) != NULL
272
                            ? *STATE_PROG_ARGV (sd)
273
                            : NULL),
274
                           abfd) != SIM_RC_OK)
275
    {
276
      sim_module_uninstall (sd);
277
      return 0;
278
    }
279
 
280
  /* establish any remaining configuration options */
281
  if (sim_config (sd) != SIM_RC_OK)
282
    {
283
      sim_module_uninstall (sd);
284
      return 0;
285
    }
286
 
287
  if (sim_post_argv_init (sd) != SIM_RC_OK)
288
    {
289
      /* Uninstall the modules to avoid memory leaks,
290
         file descriptor leaks, etc.  */
291
      sim_module_uninstall (sd);
292
      return 0;
293
    }
294
 
295
 
296
  /* set machine specific configuration */
297
/*   STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
298
/*                           | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
299
 
300
  return sd;
301
}
302
 
303
 
304
void
305
sim_close (SIM_DESC sd, int quitting)
306
{
307
  sim_module_uninstall (sd);
308
}
309
 
310
 
311
SIM_RC
312
sim_create_inferior (SIM_DESC sd,
313
                     struct bfd *prog_bfd,
314
                     char **argv,
315
                     char **env)
316
{
317
  memset (&State, 0, sizeof (State));
318
  if (prog_bfd != NULL) {
319
    PC = bfd_get_start_address (prog_bfd);
320
  } else {
321
    PC = 0;
322
  }
323
  CIA_SET (STATE_CPU (sd, 0), (unsigned64) PC);
324
 
325
  if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_am33_2)
326
    PSW |= PSW_FE;
327
 
328
  return SIM_RC_OK;
329
}
330
 
331
void
332
sim_do_command (SIM_DESC sd, char *cmd)
333
{
334
  char *mm_cmd = "memory-map";
335
  char *int_cmd = "interrupt";
336
 
337
  if (sim_args_command (sd, cmd) != SIM_RC_OK)
338
    {
339
      if (strncmp (cmd, mm_cmd, strlen (mm_cmd) == 0))
340
        sim_io_eprintf (sd, "`memory-map' command replaced by `sim memory'\n");
341
      else if (strncmp (cmd, int_cmd, strlen (int_cmd)) == 0)
342
        sim_io_eprintf (sd, "`interrupt' command replaced by `sim watch'\n");
343
      else
344
        sim_io_eprintf (sd, "Unknown command `%s'\n", cmd);
345
    }
346
}
347
 
348
/* FIXME These would more efficient to use than load_mem/store_mem,
349
   but need to be changed to use the memory map.  */
350
 
351
uint8
352
get_byte (uint8 *x)
353
{
354
  return *x;
355
}
356
 
357
uint16
358
get_half (uint8 *x)
359
{
360
  uint8 *a = x;
361
  return (a[1] << 8) + (a[0]);
362
}
363
 
364
uint32
365
get_word (uint8 *x)
366
{
367
  uint8 *a = x;
368
  return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
369
}
370
 
371
void
372
put_byte (uint8 *addr, uint8 data)
373
{
374
  uint8 *a = addr;
375
  a[0] = data;
376
}
377
 
378
void
379
put_half (uint8 *addr, uint16 data)
380
{
381
  uint8 *a = addr;
382
  a[0] = data & 0xff;
383
  a[1] = (data >> 8) & 0xff;
384
}
385
 
386
void
387
put_word (uint8 *addr, uint32 data)
388
{
389
  uint8 *a = addr;
390
  a[0] = data & 0xff;
391
  a[1] = (data >> 8) & 0xff;
392
  a[2] = (data >> 16) & 0xff;
393
  a[3] = (data >> 24) & 0xff;
394
}
395
 
396
int
397
sim_fetch_register (SIM_DESC sd,
398
                    int rn,
399
                    unsigned char *memory,
400
                    int length)
401
{
402
  put_word (memory, State.regs[rn]);
403
  return -1;
404
}
405
 
406
int
407
sim_store_register (SIM_DESC sd,
408
                    int rn,
409
                    unsigned char *memory,
410
                    int length)
411
{
412
  State.regs[rn] = get_word (memory);
413
  return -1;
414
}
415
 
416
 
417
void
418
mn10300_core_signal (SIM_DESC sd,
419
                     sim_cpu *cpu,
420
                     sim_cia cia,
421
                     unsigned map,
422
                     int nr_bytes,
423
                     address_word addr,
424
                     transfer_type transfer,
425
                     sim_core_signals sig)
426
{
427
  const char *copy = (transfer == read_transfer ? "read" : "write");
428
  address_word ip = CIA_ADDR (cia);
429
 
430
  switch (sig)
431
    {
432
    case sim_core_unmapped_signal:
433
      sim_io_eprintf (sd, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
434
                      nr_bytes, copy,
435
                      (unsigned long) addr, (unsigned long) ip);
436
      program_interrupt(sd, cpu, cia, SIM_SIGSEGV);
437
      break;
438
 
439
    case sim_core_unaligned_signal:
440
      sim_io_eprintf (sd, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
441
                      nr_bytes, copy,
442
                      (unsigned long) addr, (unsigned long) ip);
443
      program_interrupt(sd, cpu, cia, SIM_SIGBUS);
444
      break;
445
 
446
    default:
447
      sim_engine_abort (sd, cpu, cia,
448
                        "mn10300_core_signal - internal error - bad switch");
449
    }
450
}
451
 
452
 
453
void
454
program_interrupt (SIM_DESC sd,
455
                   sim_cpu *cpu,
456
                   sim_cia cia,
457
                   SIM_SIGNAL sig)
458
{
459
  int status;
460
  struct hw *device;
461
  static int in_interrupt = 0;
462
 
463
#ifdef SIM_CPU_EXCEPTION_TRIGGER
464
  SIM_CPU_EXCEPTION_TRIGGER(sd,cpu,cia);
465
#endif
466
 
467
  /* avoid infinite recursion */
468
  if (in_interrupt)
469
    {
470
      (*mn10300_callback->printf_filtered) (mn10300_callback,
471
                                            "ERROR: recursion in program_interrupt during software exception dispatch.");
472
    }
473
  else
474
    {
475
      in_interrupt = 1;
476
      /* copy NMI handler code from dv-mn103cpu.c */
477
      store_word (SP - 4, CIA_GET (cpu));
478
      store_half (SP - 8, PSW);
479
 
480
      /* Set the SYSEF flag in NMICR by backdoor method.  See
481
         dv-mn103int.c:write_icr().  This is necessary because
482
         software exceptions are not modelled by actually talking to
483
         the interrupt controller, so it cannot set its own SYSEF
484
         flag. */
485
     if ((NULL != board) && (strcmp(board, BOARD_AM32) == 0))
486
       store_byte (0x34000103, 0x04);
487
    }
488
 
489
  PSW &= ~PSW_IE;
490
  SP = SP - 8;
491
  CIA_SET (cpu, 0x40000008);
492
 
493
  in_interrupt = 0;
494
  sim_engine_halt(sd, cpu, NULL, cia, sim_stopped, sig);
495
}
496
 
497
 
498
void
499
mn10300_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia)
500
{
501
  ASSERT(cpu != NULL);
502
 
503
  if(State.exc_suspended > 0)
504
    sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", State.exc_suspended);
505
 
506
  CIA_SET (cpu, cia);
507
  memcpy(State.exc_trigger_regs, State.regs, sizeof(State.exc_trigger_regs));
508
  State.exc_suspended = 0;
509
}
510
 
511
void
512
mn10300_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception)
513
{
514
  ASSERT(cpu != NULL);
515
 
516
  if(State.exc_suspended > 0)
517
    sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n",
518
                   State.exc_suspended, exception);
519
 
520
  memcpy(State.exc_suspend_regs, State.regs, sizeof(State.exc_suspend_regs));
521
  memcpy(State.regs, State.exc_trigger_regs, sizeof(State.regs));
522
  CIA_SET (cpu, PC); /* copy PC back from new State.regs */
523
  State.exc_suspended = exception;
524
}
525
 
526
void
527
mn10300_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception)
528
{
529
  ASSERT(cpu != NULL);
530
 
531
  if(exception == 0 && State.exc_suspended > 0)
532
    {
533
      if(State.exc_suspended != SIGTRAP) /* warn not for breakpoints */
534
         sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n",
535
                       State.exc_suspended);
536
    }
537
  else if(exception != 0 && State.exc_suspended > 0)
538
    {
539
      if(exception != State.exc_suspended)
540
        sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
541
                       State.exc_suspended, exception);
542
 
543
      memcpy(State.regs, State.exc_suspend_regs, sizeof(State.regs));
544
      CIA_SET (cpu, PC); /* copy PC back from new State.regs */
545
    }
546
  else if(exception != 0 && State.exc_suspended == 0)
547
    {
548
      sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception);
549
    }
550
  State.exc_suspended = 0;
551
}
552
 
553
/* This is called when an FP instruction is issued when the FP unit is
554
   disabled, i.e., the FE bit of PSW is zero.  It raises interrupt
555
   code 0x1c0.  */
556
void
557
fpu_disabled_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
558
{
559
  sim_io_eprintf(sd, "FPU disabled exception\n");
560
  program_interrupt (sd, cpu, cia, SIM_SIGFPE);
561
}
562
 
563
/* This is called when the FP unit is enabled but one of the
564
   unimplemented insns is issued.  It raises interrupt code 0x1c8.  */
565
void
566
fpu_unimp_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
567
{
568
  sim_io_eprintf(sd, "Unimplemented FPU instruction exception\n");
569
  program_interrupt (sd, cpu, cia, SIM_SIGFPE);
570
}
571
 
572
/* This is called at the end of any FP insns that may have triggered
573
   FP exceptions.  If no exception is enabled, it returns immediately.
574
   Otherwise, it raises an exception code 0x1d0.  */
575
void
576
fpu_check_signal_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
577
{
578
  if ((FPCR & EC_MASK) == 0)
579
    return;
580
 
581
  sim_io_eprintf(sd, "FPU %s%s%s%s%s exception\n",
582
                 (FPCR & EC_V) ? "V" : "",
583
                 (FPCR & EC_Z) ? "Z" : "",
584
                 (FPCR & EC_O) ? "O" : "",
585
                 (FPCR & EC_U) ? "U" : "",
586
                 (FPCR & EC_I) ? "I" : "");
587
  program_interrupt (sd, cpu, cia, SIM_SIGFPE);
588
}
589
 
590
/* Convert a 32-bit single-precision FP value in the target platform
591
   format to a sim_fpu value.  */
592
static void
593
reg2val_32 (const void *reg, sim_fpu *val)
594
{
595
  FS2FPU (*(reg_t *)reg, *val);
596
}
597
 
598
/* Round the given sim_fpu value to single precision, following the
599
   target platform rounding and denormalization conventions.  On
600
   AM33/2.0, round_near is the only rounding mode.  */
601
static int
602
round_32 (sim_fpu *val)
603
{
604
  return sim_fpu_round_32 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
605
}
606
 
607
/* Convert a sim_fpu value to the 32-bit single-precision target
608
   representation.  */
609
static void
610
val2reg_32 (const sim_fpu *val, void *reg)
611
{
612
  FPU2FS (*val, *(reg_t *)reg);
613
}
614
 
615
/* Define the 32-bit single-precision conversion and rounding uniform
616
   interface.  */
617
const struct fp_prec_t
618
fp_single_prec = {
619
  reg2val_32, round_32, val2reg_32
620
};
621
 
622
/* Convert a 64-bit double-precision FP value in the target platform
623
   format to a sim_fpu value.  */
624
static void
625
reg2val_64 (const void *reg, sim_fpu *val)
626
{
627
  FD2FPU (*(dword *)reg, *val);
628
}
629
 
630
/* Round the given sim_fpu value to double precision, following the
631
   target platform rounding and denormalization conventions.  On
632
   AM33/2.0, round_near is the only rounding mode.  */
633
int
634
round_64 (sim_fpu *val)
635
{
636
  return sim_fpu_round_64 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
637
}
638
 
639
/* Convert a sim_fpu value to the 64-bit double-precision target
640
   representation.  */
641
static void
642
val2reg_64 (const sim_fpu *val, void *reg)
643
{
644
  FPU2FD (*val, *(dword *)reg);
645
}
646
 
647
/* Define the 64-bit single-precision conversion and rounding uniform
648
   interface.  */
649
const struct fp_prec_t
650
fp_double_prec = {
651
  reg2val_64, round_64, val2reg_64
652
};
653
 
654
/* Define shortcuts to the uniform interface operations.  */
655
#define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
656
#define ROUND(val) (*ops->round) (val)
657
#define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
658
 
659
/* Check whether overflow, underflow or inexact exceptions should be
660
   raised.  */
661
int
662
fpu_status_ok (sim_fpu_status stat)
663
{
664
  if ((stat & sim_fpu_status_overflow)
665
      && (FPCR & EE_O))
666
    FPCR |= EC_O;
667
  else if ((stat & (sim_fpu_status_underflow | sim_fpu_status_denorm))
668
           && (FPCR & EE_U))
669
    FPCR |= EC_U;
670
  else if ((stat & (sim_fpu_status_inexact | sim_fpu_status_rounded))
671
           && (FPCR & EE_I))
672
    FPCR |= EC_I;
673
  else if (stat & ~ (sim_fpu_status_overflow
674
                     | sim_fpu_status_underflow
675
                     | sim_fpu_status_denorm
676
                     | sim_fpu_status_inexact
677
                     | sim_fpu_status_rounded))
678
    abort ();
679
  else
680
    return 1;
681
  return 0;
682
}
683
 
684
/* Implement a 32/64 bit reciprocal square root, signaling FP
685
   exceptions when appropriate.  */
686
void
687
fpu_rsqrt (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
688
           const void *reg_in, void *reg_out, const struct fp_prec_t *ops)
689
{
690
  sim_fpu in, med, out;
691
 
692
  REG2VAL (reg_in, &in);
693
  ROUND (&in);
694
  FPCR &= ~ EC_MASK;
695
  switch (sim_fpu_is (&in))
696
    {
697
    case SIM_FPU_IS_SNAN:
698
    case SIM_FPU_IS_NNUMBER:
699
    case SIM_FPU_IS_NINF:
700
      if (FPCR & EE_V)
701
        FPCR |= EC_V;
702
      else
703
        VAL2REG (&sim_fpu_qnan, reg_out);
704
      break;
705
 
706
    case SIM_FPU_IS_QNAN:
707
      VAL2REG (&sim_fpu_qnan, reg_out);
708
      break;
709
 
710
    case SIM_FPU_IS_PINF:
711
      VAL2REG (&sim_fpu_zero, reg_out);
712
      break;
713
 
714
    case SIM_FPU_IS_PNUMBER:
715
      {
716
        /* Since we don't have a function to compute rsqrt directly,
717
           use sqrt and inv.  */
718
        sim_fpu_status stat = 0;
719
        stat |= sim_fpu_sqrt (&med, &in);
720
        stat |= sim_fpu_inv (&out, &med);
721
        stat |= ROUND (&out);
722
        if (fpu_status_ok (stat))
723
          VAL2REG (&out, reg_out);
724
      }
725
      break;
726
 
727
    case SIM_FPU_IS_NZERO:
728
    case SIM_FPU_IS_PZERO:
729
      if (FPCR & EE_Z)
730
        FPCR |= EC_Z;
731
      else
732
        {
733
          /* Generate an INF with the same sign.  */
734
          sim_fpu_inv (&out, &in);
735
          VAL2REG (&out, reg_out);
736
        }
737
      break;
738
 
739
    default:
740
      abort ();
741
    }
742
 
743
  fpu_check_signal_exception (sd, cpu, cia);
744
}
745
 
746
static inline reg_t
747
cmp2fcc (int res)
748
{
749
  switch (res)
750
    {
751
    case SIM_FPU_IS_SNAN:
752
    case SIM_FPU_IS_QNAN:
753
      return FCC_U;
754
 
755
    case SIM_FPU_IS_NINF:
756
    case SIM_FPU_IS_NNUMBER:
757
    case SIM_FPU_IS_NDENORM:
758
      return FCC_L;
759
 
760
    case SIM_FPU_IS_PINF:
761
    case SIM_FPU_IS_PNUMBER:
762
    case SIM_FPU_IS_PDENORM:
763
      return FCC_G;
764
 
765
    case SIM_FPU_IS_NZERO:
766
    case SIM_FPU_IS_PZERO:
767
      return FCC_E;
768
 
769
    default:
770
      abort ();
771
    }
772
}
773
 
774
/* Implement a 32/64 bit FP compare, setting the FPCR status and/or
775
   exception bits as specified.  */
776
void
777
fpu_cmp (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
778
         const void *reg_in1, const void *reg_in2,
779
         const struct fp_prec_t *ops)
780
{
781
  sim_fpu m, n;
782
 
783
  REG2VAL (reg_in1, &m);
784
  REG2VAL (reg_in2, &n);
785
  FPCR &= ~ EC_MASK;
786
  FPCR &= ~ FCC_MASK;
787
  ROUND (&m);
788
  ROUND (&n);
789
  if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n))
790
    {
791
      if (FPCR & EE_V)
792
        FPCR |= EC_V;
793
      else
794
        FPCR |= FCC_U;
795
    }
796
  else
797
    FPCR |= cmp2fcc (sim_fpu_cmp (&m, &n));
798
 
799
  fpu_check_signal_exception (sd, cpu, cia);
800
}
801
 
802
/* Implement a 32/64 bit FP add, setting FP exception bits when
803
   appropriate.  */
804
void
805
fpu_add (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
806
         const void *reg_in1, const void *reg_in2,
807
         void *reg_out, const struct fp_prec_t *ops)
808
{
809
  sim_fpu m, n, r;
810
 
811
  REG2VAL (reg_in1, &m);
812
  REG2VAL (reg_in2, &n);
813
  ROUND (&m);
814
  ROUND (&n);
815
  FPCR &= ~ EC_MASK;
816
  if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
817
      || (sim_fpu_is (&m) == SIM_FPU_IS_PINF
818
          && sim_fpu_is (&n) == SIM_FPU_IS_NINF)
819
      || (sim_fpu_is (&m) == SIM_FPU_IS_NINF
820
          && sim_fpu_is (&n) == SIM_FPU_IS_PINF))
821
    {
822
      if (FPCR & EE_V)
823
        FPCR |= EC_V;
824
      else
825
        VAL2REG (&sim_fpu_qnan, reg_out);
826
    }
827
  else
828
    {
829
      sim_fpu_status stat = sim_fpu_add (&r, &m, &n);
830
      stat |= ROUND (&r);
831
      if (fpu_status_ok (stat))
832
        VAL2REG (&r, reg_out);
833
    }
834
 
835
  fpu_check_signal_exception (sd, cpu, cia);
836
}
837
 
838
/* Implement a 32/64 bit FP sub, setting FP exception bits when
839
   appropriate.  */
840
void
841
fpu_sub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
842
         const void *reg_in1, const void *reg_in2,
843
         void *reg_out, const struct fp_prec_t *ops)
844
{
845
  sim_fpu m, n, r;
846
 
847
  REG2VAL (reg_in1, &m);
848
  REG2VAL (reg_in2, &n);
849
  ROUND (&m);
850
  ROUND (&n);
851
  FPCR &= ~ EC_MASK;
852
  if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
853
      || (sim_fpu_is (&m) == SIM_FPU_IS_PINF
854
          && sim_fpu_is (&n) == SIM_FPU_IS_PINF)
855
      || (sim_fpu_is (&m) == SIM_FPU_IS_NINF
856
          && sim_fpu_is (&n) == SIM_FPU_IS_NINF))
857
    {
858
      if (FPCR & EE_V)
859
        FPCR |= EC_V;
860
      else
861
        VAL2REG (&sim_fpu_qnan, reg_out);
862
    }
863
  else
864
    {
865
      sim_fpu_status stat = sim_fpu_sub (&r, &m, &n);
866
      stat |= ROUND (&r);
867
      if (fpu_status_ok (stat))
868
        VAL2REG (&r, reg_out);
869
    }
870
 
871
  fpu_check_signal_exception (sd, cpu, cia);
872
}
873
 
874
/* Implement a 32/64 bit FP mul, setting FP exception bits when
875
   appropriate.  */
876
void
877
fpu_mul (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
878
         const void *reg_in1, const void *reg_in2,
879
         void *reg_out, const struct fp_prec_t *ops)
880
{
881
  sim_fpu m, n, r;
882
 
883
  REG2VAL (reg_in1, &m);
884
  REG2VAL (reg_in2, &n);
885
  ROUND (&m);
886
  ROUND (&n);
887
  FPCR &= ~ EC_MASK;
888
  if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
889
      || (sim_fpu_is_infinity (&m) && sim_fpu_is_zero (&n))
890
      || (sim_fpu_is_zero (&m) && sim_fpu_is_infinity (&n)))
891
    {
892
      if (FPCR & EE_V)
893
        FPCR |= EC_V;
894
      else
895
        VAL2REG (&sim_fpu_qnan, reg_out);
896
    }
897
  else
898
    {
899
      sim_fpu_status stat = sim_fpu_mul (&r, &m, &n);
900
      stat |= ROUND (&r);
901
      if (fpu_status_ok (stat))
902
        VAL2REG (&r, reg_out);
903
    }
904
 
905
  fpu_check_signal_exception (sd, cpu, cia);
906
}
907
 
908
/* Implement a 32/64 bit FP div, setting FP exception bits when
909
   appropriate.  */
910
void
911
fpu_div (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
912
         const void *reg_in1, const void *reg_in2,
913
         void *reg_out, const struct fp_prec_t *ops)
914
{
915
  sim_fpu m, n, r;
916
 
917
  REG2VAL (reg_in1, &m);
918
  REG2VAL (reg_in2, &n);
919
  ROUND (&m);
920
  ROUND (&n);
921
  FPCR &= ~ EC_MASK;
922
  if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
923
      || (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n))
924
      || (sim_fpu_is_zero (&m) && sim_fpu_is_zero (&n)))
925
    {
926
      if (FPCR & EE_V)
927
        FPCR |= EC_V;
928
      else
929
        VAL2REG (&sim_fpu_qnan, reg_out);
930
    }
931
  else if (sim_fpu_is_number (&m) && sim_fpu_is_zero (&n)
932
           && (FPCR & EE_Z))
933
    FPCR |= EC_Z;
934
  else
935
    {
936
      sim_fpu_status stat = sim_fpu_div (&r, &m, &n);
937
      stat |= ROUND (&r);
938
      if (fpu_status_ok (stat))
939
        VAL2REG (&r, reg_out);
940
    }
941
 
942
  fpu_check_signal_exception (sd, cpu, cia);
943
}
944
 
945
/* Implement a 32/64 bit FP madd, setting FP exception bits when
946
   appropriate.  */
947
void
948
fpu_fmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
949
           const void *reg_in1, const void *reg_in2, const void *reg_in3,
950
           void *reg_out, const struct fp_prec_t *ops)
951
{
952
  sim_fpu m1, m2, m, n, r;
953
 
954
  REG2VAL (reg_in1, &m1);
955
  REG2VAL (reg_in2, &m2);
956
  REG2VAL (reg_in3, &n);
957
  ROUND (&m1);
958
  ROUND (&m2);
959
  ROUND (&n);
960
  FPCR &= ~ EC_MASK;
961
  if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
962
      || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
963
      || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
964
    {
965
    invalid_operands:
966
      if (FPCR & EE_V)
967
        FPCR |= EC_V;
968
      else
969
        VAL2REG (&sim_fpu_qnan, reg_out);
970
    }
971
  else
972
    {
973
      sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
974
 
975
      if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
976
          && sim_fpu_sign (&m) != sim_fpu_sign (&n))
977
        goto invalid_operands;
978
 
979
      stat |= sim_fpu_add (&r, &m, &n);
980
      stat |= ROUND (&r);
981
      if (fpu_status_ok (stat))
982
        VAL2REG (&r, reg_out);
983
    }
984
 
985
  fpu_check_signal_exception (sd, cpu, cia);
986
}
987
 
988
/* Implement a 32/64 bit FP msub, setting FP exception bits when
989
   appropriate.  */
990
void
991
fpu_fmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
992
           const void *reg_in1, const void *reg_in2, const void *reg_in3,
993
           void *reg_out, const struct fp_prec_t *ops)
994
{
995
  sim_fpu m1, m2, m, n, r;
996
 
997
  REG2VAL (reg_in1, &m1);
998
  REG2VAL (reg_in2, &m2);
999
  REG2VAL (reg_in3, &n);
1000
  ROUND (&m1);
1001
  ROUND (&m2);
1002
  ROUND (&n);
1003
  FPCR &= ~ EC_MASK;
1004
  if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
1005
      || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
1006
      || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
1007
    {
1008
    invalid_operands:
1009
      if (FPCR & EE_V)
1010
        FPCR |= EC_V;
1011
      else
1012
        VAL2REG (&sim_fpu_qnan, reg_out);
1013
    }
1014
  else
1015
    {
1016
      sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
1017
 
1018
      if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
1019
          && sim_fpu_sign (&m) == sim_fpu_sign (&n))
1020
        goto invalid_operands;
1021
 
1022
      stat |= sim_fpu_sub (&r, &m, &n);
1023
      stat |= ROUND (&r);
1024
      if (fpu_status_ok (stat))
1025
        VAL2REG (&r, reg_out);
1026
    }
1027
 
1028
  fpu_check_signal_exception (sd, cpu, cia);
1029
}
1030
 
1031
/* Implement a 32/64 bit FP nmadd, setting FP exception bits when
1032
   appropriate.  */
1033
void
1034
fpu_fnmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
1035
            const void *reg_in1, const void *reg_in2, const void *reg_in3,
1036
            void *reg_out, const struct fp_prec_t *ops)
1037
{
1038
  sim_fpu m1, m2, m, mm, n, r;
1039
 
1040
  REG2VAL (reg_in1, &m1);
1041
  REG2VAL (reg_in2, &m2);
1042
  REG2VAL (reg_in3, &n);
1043
  ROUND (&m1);
1044
  ROUND (&m2);
1045
  ROUND (&n);
1046
  FPCR &= ~ EC_MASK;
1047
  if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
1048
      || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
1049
      || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
1050
    {
1051
    invalid_operands:
1052
      if (FPCR & EE_V)
1053
        FPCR |= EC_V;
1054
      else
1055
        VAL2REG (&sim_fpu_qnan, reg_out);
1056
    }
1057
  else
1058
    {
1059
      sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
1060
 
1061
      if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
1062
          && sim_fpu_sign (&m) == sim_fpu_sign (&n))
1063
        goto invalid_operands;
1064
 
1065
      stat |= sim_fpu_neg (&mm, &m);
1066
      stat |= sim_fpu_add (&r, &mm, &n);
1067
      stat |= ROUND (&r);
1068
      if (fpu_status_ok (stat))
1069
        VAL2REG (&r, reg_out);
1070
    }
1071
 
1072
  fpu_check_signal_exception (sd, cpu, cia);
1073
}
1074
 
1075
/* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1076
   appropriate.  */
1077
void
1078
fpu_fnmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
1079
            const void *reg_in1, const void *reg_in2, const void *reg_in3,
1080
            void *reg_out, const struct fp_prec_t *ops)
1081
{
1082
  sim_fpu m1, m2, m, mm, n, r;
1083
 
1084
  REG2VAL (reg_in1, &m1);
1085
  REG2VAL (reg_in2, &m2);
1086
  REG2VAL (reg_in3, &n);
1087
  ROUND (&m1);
1088
  ROUND (&m2);
1089
  ROUND (&n);
1090
  FPCR &= ~ EC_MASK;
1091
  if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
1092
      || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
1093
      || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
1094
    {
1095
    invalid_operands:
1096
      if (FPCR & EE_V)
1097
        FPCR |= EC_V;
1098
      else
1099
        VAL2REG (&sim_fpu_qnan, reg_out);
1100
    }
1101
  else
1102
    {
1103
      sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
1104
 
1105
      if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
1106
          && sim_fpu_sign (&m) != sim_fpu_sign (&n))
1107
        goto invalid_operands;
1108
 
1109
      stat |= sim_fpu_neg (&mm, &m);
1110
      stat |= sim_fpu_sub (&r, &mm, &n);
1111
      stat |= ROUND (&r);
1112
      if (fpu_status_ok (stat))
1113
        VAL2REG (&r, reg_out);
1114
    }
1115
 
1116
  fpu_check_signal_exception (sd, cpu, cia);
1117
}

powered by: WebSVN 2.1.0

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