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