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