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