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