Update sim_fetch_register, sim_store_register for sh and mn10300.
[external/binutils.git] / sim / mn10300 / interp.c
1 #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 /* 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 uint8
335 get_byte (uint8 *x)
336 {
337   return *x;
338 }
339
340 uint16
341 get_half (uint8 *x)
342 {
343   uint8 *a = x;
344   return (a[1] << 8) + (a[0]);
345 }
346
347 uint32
348 get_word (uint8 *x)
349 {
350   uint8 *a = x;
351   return (a[3]<<24) + (a[2]<<16) + (a[1]<<8) + (a[0]);
352 }
353
354 void
355 put_byte (uint8 *addr, uint8 data)
356 {
357   uint8 *a = addr;
358   a[0] = data;
359 }
360
361 void
362 put_half (uint8 *addr, uint16 data)
363 {
364   uint8 *a = addr;
365   a[0] = data & 0xff;
366   a[1] = (data >> 8) & 0xff;
367 }
368
369 void
370 put_word (uint8 *addr, uint32 data)
371 {
372   uint8 *a = addr;
373   a[0] = data & 0xff;
374   a[1] = (data >> 8) & 0xff;
375   a[2] = (data >> 16) & 0xff;
376   a[3] = (data >> 24) & 0xff;
377 }
378
379 int
380 sim_fetch_register (SIM_DESC sd,
381                     int rn,
382                     unsigned char *memory,
383                     int length)
384 {
385   put_word (memory, State.regs[rn]);
386   return length;
387 }
388  
389 int
390 sim_store_register (SIM_DESC sd,
391                     int rn,
392                     unsigned char *memory,
393                     int length)
394 {
395   State.regs[rn] = get_word (memory);
396   return length;
397 }
398
399
400 void
401 mn10300_core_signal (SIM_DESC sd,
402                      sim_cpu *cpu,
403                      sim_cia cia,
404                      unsigned map,
405                      int nr_bytes,
406                      address_word addr,
407                      transfer_type transfer,
408                      sim_core_signals sig)
409 {
410   const char *copy = (transfer == read_transfer ? "read" : "write");
411   address_word ip = CIA_ADDR (cia);
412
413   switch (sig)
414     {
415     case sim_core_unmapped_signal:
416       sim_io_eprintf (sd, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
417                       nr_bytes, copy, 
418                       (unsigned long) addr, (unsigned long) ip);
419       program_interrupt(sd, cpu, cia, SIM_SIGSEGV);
420       break;
421
422     case sim_core_unaligned_signal:
423       sim_io_eprintf (sd, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
424                       nr_bytes, copy, 
425                       (unsigned long) addr, (unsigned long) ip);
426       program_interrupt(sd, cpu, cia, SIM_SIGBUS);
427       break;
428
429     default:
430       sim_engine_abort (sd, cpu, cia,
431                         "mn10300_core_signal - internal error - bad switch");
432     }
433 }
434
435
436 void
437 program_interrupt (SIM_DESC sd,
438                    sim_cpu *cpu,
439                    sim_cia cia,
440                    SIM_SIGNAL sig)
441 {
442   int status;
443   struct hw *device;
444   static int in_interrupt = 0;
445
446 #ifdef SIM_CPU_EXCEPTION_TRIGGER
447   SIM_CPU_EXCEPTION_TRIGGER(sd,cpu,cia);
448 #endif
449
450   /* avoid infinite recursion */
451   if (in_interrupt)
452     {
453       (*mn10300_callback->printf_filtered) (mn10300_callback, 
454                                             "ERROR: recursion in program_interrupt during software exception dispatch.");
455     }
456   else
457     {
458       in_interrupt = 1;
459       /* copy NMI handler code from dv-mn103cpu.c */
460       store_word (SP - 4, CIA_GET (cpu));
461       store_half (SP - 8, PSW);
462
463       /* Set the SYSEF flag in NMICR by backdoor method.  See
464          dv-mn103int.c:write_icr().  This is necessary because
465          software exceptions are not modelled by actually talking to
466          the interrupt controller, so it cannot set its own SYSEF
467          flag. */
468      if ((NULL != board) && (strcmp(board, BOARD_AM32) == 0))
469        store_byte (0x34000103, 0x04);
470     }
471
472   PSW &= ~PSW_IE;
473   SP = SP - 8;
474   CIA_SET (cpu, 0x40000008);
475
476   in_interrupt = 0;
477   sim_engine_halt(sd, cpu, NULL, cia, sim_stopped, sig);
478 }
479
480
481 void
482 mn10300_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia)
483 {
484   ASSERT(cpu != NULL);
485
486   if(State.exc_suspended > 0)
487     sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", State.exc_suspended); 
488
489   CIA_SET (cpu, cia);
490   memcpy(State.exc_trigger_regs, State.regs, sizeof(State.exc_trigger_regs));
491   State.exc_suspended = 0;
492 }
493
494 void
495 mn10300_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception)
496 {
497   ASSERT(cpu != NULL);
498
499   if(State.exc_suspended > 0)
500     sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n", 
501                    State.exc_suspended, exception); 
502
503   memcpy(State.exc_suspend_regs, State.regs, sizeof(State.exc_suspend_regs));
504   memcpy(State.regs, State.exc_trigger_regs, sizeof(State.regs));
505   CIA_SET (cpu, PC); /* copy PC back from new State.regs */
506   State.exc_suspended = exception;
507 }
508
509 void
510 mn10300_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception)
511 {
512   ASSERT(cpu != NULL);
513
514   if(exception == 0 && State.exc_suspended > 0)
515     {
516       if(State.exc_suspended != SIGTRAP) /* warn not for breakpoints */
517          sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n",
518                        State.exc_suspended); 
519     }
520   else if(exception != 0 && State.exc_suspended > 0)
521     {
522       if(exception != State.exc_suspended) 
523         sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
524                        State.exc_suspended, exception); 
525       
526       memcpy(State.regs, State.exc_suspend_regs, sizeof(State.regs)); 
527       CIA_SET (cpu, PC); /* copy PC back from new State.regs */
528     }
529   else if(exception != 0 && State.exc_suspended == 0)
530     {
531       sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception); 
532     }
533   State.exc_suspended = 0; 
534 }
535
536 /* This is called when an FP instruction is issued when the FP unit is
537    disabled, i.e., the FE bit of PSW is zero.  It raises interrupt
538    code 0x1c0.  */
539 void
540 fpu_disabled_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
541 {
542   sim_io_eprintf(sd, "FPU disabled exception\n");
543   program_interrupt (sd, cpu, cia, SIM_SIGFPE);
544 }
545
546 /* This is called when the FP unit is enabled but one of the
547    unimplemented insns is issued.  It raises interrupt code 0x1c8.  */
548 void
549 fpu_unimp_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
550 {
551   sim_io_eprintf(sd, "Unimplemented FPU instruction exception\n");
552   program_interrupt (sd, cpu, cia, SIM_SIGFPE);
553 }
554
555 /* This is called at the end of any FP insns that may have triggered
556    FP exceptions.  If no exception is enabled, it returns immediately.
557    Otherwise, it raises an exception code 0x1d0.  */
558 void
559 fpu_check_signal_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
560 {
561   if ((FPCR & EC_MASK) == 0)
562     return;
563
564   sim_io_eprintf(sd, "FPU %s%s%s%s%s exception\n",
565                  (FPCR & EC_V) ? "V" : "",
566                  (FPCR & EC_Z) ? "Z" : "",
567                  (FPCR & EC_O) ? "O" : "",
568                  (FPCR & EC_U) ? "U" : "",
569                  (FPCR & EC_I) ? "I" : "");
570   program_interrupt (sd, cpu, cia, SIM_SIGFPE);
571 }
572
573 /* Convert a 32-bit single-precision FP value in the target platform
574    format to a sim_fpu value.  */
575 static void
576 reg2val_32 (const void *reg, sim_fpu *val)
577 {
578   FS2FPU (*(reg_t *)reg, *val);
579 }
580
581 /* Round the given sim_fpu value to single precision, following the
582    target platform rounding and denormalization conventions.  On
583    AM33/2.0, round_near is the only rounding mode.  */
584 static int
585 round_32 (sim_fpu *val)
586 {
587   return sim_fpu_round_32 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
588 }
589
590 /* Convert a sim_fpu value to the 32-bit single-precision target
591    representation.  */
592 static void
593 val2reg_32 (const sim_fpu *val, void *reg)
594 {
595   FPU2FS (*val, *(reg_t *)reg);
596 }
597
598 /* Define the 32-bit single-precision conversion and rounding uniform
599    interface.  */
600 const struct fp_prec_t
601 fp_single_prec = {
602   reg2val_32, round_32, val2reg_32
603 };
604
605 /* Convert a 64-bit double-precision FP value in the target platform
606    format to a sim_fpu value.  */
607 static void
608 reg2val_64 (const void *reg, sim_fpu *val)
609 {
610   FD2FPU (*(dword *)reg, *val);
611 }
612
613 /* Round the given sim_fpu value to double precision, following the
614    target platform rounding and denormalization conventions.  On
615    AM33/2.0, round_near is the only rounding mode.  */
616 int
617 round_64 (sim_fpu *val)
618 {
619   return sim_fpu_round_64 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
620 }
621
622 /* Convert a sim_fpu value to the 64-bit double-precision target
623    representation.  */
624 static void
625 val2reg_64 (const sim_fpu *val, void *reg)
626 {
627   FPU2FD (*val, *(dword *)reg);
628 }
629
630 /* Define the 64-bit single-precision conversion and rounding uniform
631    interface.  */
632 const struct fp_prec_t
633 fp_double_prec = {
634   reg2val_64, round_64, val2reg_64
635 };
636
637 /* Define shortcuts to the uniform interface operations.  */
638 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
639 #define ROUND(val) (*ops->round) (val)
640 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
641
642 /* Check whether overflow, underflow or inexact exceptions should be
643    raised.  */
644 int
645 fpu_status_ok (sim_fpu_status stat)
646 {
647   if ((stat & sim_fpu_status_overflow)
648       && (FPCR & EE_O))
649     FPCR |= EC_O;
650   else if ((stat & (sim_fpu_status_underflow | sim_fpu_status_denorm))
651            && (FPCR & EE_U))
652     FPCR |= EC_U;
653   else if ((stat & (sim_fpu_status_inexact | sim_fpu_status_rounded))
654            && (FPCR & EE_I))
655     FPCR |= EC_I;
656   else if (stat & ~ (sim_fpu_status_overflow
657                      | sim_fpu_status_underflow
658                      | sim_fpu_status_denorm
659                      | sim_fpu_status_inexact
660                      | sim_fpu_status_rounded))
661     abort ();
662   else
663     return 1;
664   return 0;
665 }
666
667 /* Implement a 32/64 bit reciprocal square root, signaling FP
668    exceptions when appropriate.  */
669 void
670 fpu_rsqrt (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
671            const void *reg_in, void *reg_out, const struct fp_prec_t *ops)
672 {
673   sim_fpu in, med, out;
674
675   REG2VAL (reg_in, &in);
676   ROUND (&in);
677   FPCR &= ~ EC_MASK;
678   switch (sim_fpu_is (&in))
679     {
680     case SIM_FPU_IS_SNAN:
681     case SIM_FPU_IS_NNUMBER:
682     case SIM_FPU_IS_NINF:
683       if (FPCR & EE_V)
684         FPCR |= EC_V;
685       else
686         VAL2REG (&sim_fpu_qnan, reg_out);
687       break;
688             
689     case SIM_FPU_IS_QNAN:
690       VAL2REG (&sim_fpu_qnan, reg_out);
691       break;
692
693     case SIM_FPU_IS_PINF:
694       VAL2REG (&sim_fpu_zero, reg_out);
695       break;
696
697     case SIM_FPU_IS_PNUMBER:
698       {
699         /* Since we don't have a function to compute rsqrt directly,
700            use sqrt and inv.  */
701         sim_fpu_status stat = 0;
702         stat |= sim_fpu_sqrt (&med, &in);
703         stat |= sim_fpu_inv (&out, &med);
704         stat |= ROUND (&out);
705         if (fpu_status_ok (stat))
706           VAL2REG (&out, reg_out);
707       }
708       break;
709
710     case SIM_FPU_IS_NZERO:
711     case SIM_FPU_IS_PZERO:
712       if (FPCR & EE_Z)
713         FPCR |= EC_Z;
714       else
715         {
716           /* Generate an INF with the same sign.  */
717           sim_fpu_inv (&out, &in);
718           VAL2REG (&out, reg_out);
719         }
720       break;
721
722     default:
723       abort ();
724     }
725
726   fpu_check_signal_exception (sd, cpu, cia);
727 }
728
729 static inline reg_t
730 cmp2fcc (int res)
731 {
732   switch (res)
733     {
734     case SIM_FPU_IS_SNAN:
735     case SIM_FPU_IS_QNAN:
736       return FCC_U;
737       
738     case SIM_FPU_IS_NINF:
739     case SIM_FPU_IS_NNUMBER:
740     case SIM_FPU_IS_NDENORM:
741       return FCC_L;
742       
743     case SIM_FPU_IS_PINF:
744     case SIM_FPU_IS_PNUMBER:
745     case SIM_FPU_IS_PDENORM:
746       return FCC_G;
747       
748     case SIM_FPU_IS_NZERO:
749     case SIM_FPU_IS_PZERO:
750       return FCC_E;
751       
752     default:
753       abort ();
754     }
755 }
756
757 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
758    exception bits as specified.  */
759 void
760 fpu_cmp (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
761          const void *reg_in1, const void *reg_in2,
762          const struct fp_prec_t *ops)
763 {
764   sim_fpu m, n;
765
766   REG2VAL (reg_in1, &m);
767   REG2VAL (reg_in2, &n);
768   FPCR &= ~ EC_MASK;
769   FPCR &= ~ FCC_MASK;
770   ROUND (&m);
771   ROUND (&n);
772   if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n))
773     {
774       if (FPCR & EE_V)
775         FPCR |= EC_V;
776       else
777         FPCR |= FCC_U;
778     }
779   else
780     FPCR |= cmp2fcc (sim_fpu_cmp (&m, &n));
781
782   fpu_check_signal_exception (sd, cpu, cia);
783 }
784
785 /* Implement a 32/64 bit FP add, setting FP exception bits when
786    appropriate.  */
787 void
788 fpu_add (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_NINF)
802       || (sim_fpu_is (&m) == SIM_FPU_IS_NINF
803           && sim_fpu_is (&n) == SIM_FPU_IS_PINF))
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_add (&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 sub, setting FP exception bits when
822    appropriate.  */
823 void
824 fpu_sub (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 (&m) == SIM_FPU_IS_PINF
837           && sim_fpu_is (&n) == SIM_FPU_IS_PINF)
838       || (sim_fpu_is (&m) == SIM_FPU_IS_NINF
839           && sim_fpu_is (&n) == SIM_FPU_IS_NINF))
840     {
841       if (FPCR & EE_V)
842         FPCR |= EC_V;
843       else
844         VAL2REG (&sim_fpu_qnan, reg_out);
845     }
846   else
847     {
848       sim_fpu_status stat = sim_fpu_sub (&r, &m, &n);
849       stat |= ROUND (&r);
850       if (fpu_status_ok (stat))
851         VAL2REG (&r, reg_out);
852     }
853   
854   fpu_check_signal_exception (sd, cpu, cia);
855 }
856
857 /* Implement a 32/64 bit FP mul, setting FP exception bits when
858    appropriate.  */
859 void
860 fpu_mul (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
861          const void *reg_in1, const void *reg_in2,
862          void *reg_out, const struct fp_prec_t *ops)
863 {
864   sim_fpu m, n, r;
865
866   REG2VAL (reg_in1, &m);
867   REG2VAL (reg_in2, &n);
868   ROUND (&m);
869   ROUND (&n);
870   FPCR &= ~ EC_MASK;
871   if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
872       || (sim_fpu_is_infinity (&m) && sim_fpu_is_zero (&n))
873       || (sim_fpu_is_zero (&m) && sim_fpu_is_infinity (&n)))
874     {
875       if (FPCR & EE_V)
876         FPCR |= EC_V;
877       else
878         VAL2REG (&sim_fpu_qnan, reg_out);
879     }
880   else
881     {
882       sim_fpu_status stat = sim_fpu_mul (&r, &m, &n);
883       stat |= ROUND (&r);
884       if (fpu_status_ok (stat))
885         VAL2REG (&r, reg_out);
886     }
887   
888   fpu_check_signal_exception (sd, cpu, cia);
889 }
890
891 /* Implement a 32/64 bit FP div, setting FP exception bits when
892    appropriate.  */
893 void
894 fpu_div (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
895          const void *reg_in1, const void *reg_in2,
896          void *reg_out, const struct fp_prec_t *ops)
897 {
898   sim_fpu m, n, r;
899
900   REG2VAL (reg_in1, &m);
901   REG2VAL (reg_in2, &n);
902   ROUND (&m);
903   ROUND (&n);
904   FPCR &= ~ EC_MASK;
905   if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
906       || (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n))
907       || (sim_fpu_is_zero (&m) && sim_fpu_is_zero (&n)))
908     {
909       if (FPCR & EE_V)
910         FPCR |= EC_V;
911       else
912         VAL2REG (&sim_fpu_qnan, reg_out);
913     }
914   else if (sim_fpu_is_number (&m) && sim_fpu_is_zero (&n)
915            && (FPCR & EE_Z))
916     FPCR |= EC_Z;
917   else
918     {
919       sim_fpu_status stat = sim_fpu_div (&r, &m, &n);
920       stat |= ROUND (&r);
921       if (fpu_status_ok (stat))
922         VAL2REG (&r, reg_out);
923     }
924   
925   fpu_check_signal_exception (sd, cpu, cia);
926 }
927
928 /* Implement a 32/64 bit FP madd, setting FP exception bits when
929    appropriate.  */
930 void
931 fpu_fmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
932            const void *reg_in1, const void *reg_in2, const void *reg_in3,
933            void *reg_out, const struct fp_prec_t *ops)
934 {
935   sim_fpu m1, m2, m, n, r;
936
937   REG2VAL (reg_in1, &m1);
938   REG2VAL (reg_in2, &m2);
939   REG2VAL (reg_in3, &n);
940   ROUND (&m1);
941   ROUND (&m2);
942   ROUND (&n);
943   FPCR &= ~ EC_MASK;
944   if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
945       || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
946       || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
947     {
948     invalid_operands:
949       if (FPCR & EE_V)
950         FPCR |= EC_V;
951       else
952         VAL2REG (&sim_fpu_qnan, reg_out);
953     }
954   else
955     {
956       sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
957
958       if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
959           && sim_fpu_sign (&m) != sim_fpu_sign (&n))
960         goto invalid_operands;
961
962       stat |= sim_fpu_add (&r, &m, &n);
963       stat |= ROUND (&r);
964       if (fpu_status_ok (stat))
965         VAL2REG (&r, reg_out);
966     }
967   
968   fpu_check_signal_exception (sd, cpu, cia);
969 }
970
971 /* Implement a 32/64 bit FP msub, setting FP exception bits when
972    appropriate.  */
973 void
974 fpu_fmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
975            const void *reg_in1, const void *reg_in2, const void *reg_in3,
976            void *reg_out, const struct fp_prec_t *ops)
977 {
978   sim_fpu m1, m2, m, n, r;
979
980   REG2VAL (reg_in1, &m1);
981   REG2VAL (reg_in2, &m2);
982   REG2VAL (reg_in3, &n);
983   ROUND (&m1);
984   ROUND (&m2);
985   ROUND (&n);
986   FPCR &= ~ EC_MASK;
987   if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
988       || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
989       || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
990     {
991     invalid_operands:
992       if (FPCR & EE_V)
993         FPCR |= EC_V;
994       else
995         VAL2REG (&sim_fpu_qnan, reg_out);
996     }
997   else
998     {
999       sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
1000
1001       if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
1002           && sim_fpu_sign (&m) == sim_fpu_sign (&n))
1003         goto invalid_operands;
1004
1005       stat |= sim_fpu_sub (&r, &m, &n);
1006       stat |= ROUND (&r);
1007       if (fpu_status_ok (stat))
1008         VAL2REG (&r, reg_out);
1009     }
1010   
1011   fpu_check_signal_exception (sd, cpu, cia);
1012 }
1013
1014 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
1015    appropriate.  */
1016 void
1017 fpu_fnmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
1018             const void *reg_in1, const void *reg_in2, const void *reg_in3,
1019             void *reg_out, const struct fp_prec_t *ops)
1020 {
1021   sim_fpu m1, m2, m, mm, n, r;
1022
1023   REG2VAL (reg_in1, &m1);
1024   REG2VAL (reg_in2, &m2);
1025   REG2VAL (reg_in3, &n);
1026   ROUND (&m1);
1027   ROUND (&m2);
1028   ROUND (&n);
1029   FPCR &= ~ EC_MASK;
1030   if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
1031       || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
1032       || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
1033     {
1034     invalid_operands:
1035       if (FPCR & EE_V)
1036         FPCR |= EC_V;
1037       else
1038         VAL2REG (&sim_fpu_qnan, reg_out);
1039     }
1040   else
1041     {
1042       sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
1043
1044       if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
1045           && sim_fpu_sign (&m) == sim_fpu_sign (&n))
1046         goto invalid_operands;
1047
1048       stat |= sim_fpu_neg (&mm, &m);
1049       stat |= sim_fpu_add (&r, &mm, &n);
1050       stat |= ROUND (&r);
1051       if (fpu_status_ok (stat))
1052         VAL2REG (&r, reg_out);
1053     }
1054   
1055   fpu_check_signal_exception (sd, cpu, cia);
1056 }
1057
1058 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1059    appropriate.  */
1060 void
1061 fpu_fnmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
1062             const void *reg_in1, const void *reg_in2, const void *reg_in3,
1063             void *reg_out, const struct fp_prec_t *ops)
1064 {
1065   sim_fpu m1, m2, m, mm, n, r;
1066
1067   REG2VAL (reg_in1, &m1);
1068   REG2VAL (reg_in2, &m2);
1069   REG2VAL (reg_in3, &n);
1070   ROUND (&m1);
1071   ROUND (&m2);
1072   ROUND (&n);
1073   FPCR &= ~ EC_MASK;
1074   if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
1075       || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
1076       || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
1077     {
1078     invalid_operands:
1079       if (FPCR & EE_V)
1080         FPCR |= EC_V;
1081       else
1082         VAL2REG (&sim_fpu_qnan, reg_out);
1083     }
1084   else
1085     {
1086       sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
1087
1088       if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
1089           && sim_fpu_sign (&m) != sim_fpu_sign (&n))
1090         goto invalid_operands;
1091
1092       stat |= sim_fpu_neg (&mm, &m);
1093       stat |= sim_fpu_sub (&r, &mm, &n);
1094       stat |= ROUND (&r);
1095       if (fpu_status_ok (stat))
1096         VAL2REG (&r, reg_out);
1097     }
1098   
1099   fpu_check_signal_exception (sd, cpu, cia);
1100 }