xref: /netbsd-src/external/gpl3/gdb.old/dist/sim/mn10300/interp.c (revision 32d1c65c71fbdb65a012e8392a62a757dd6853e9)
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 }
1055