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