bfd/ELF: refine segment index in filepos assignment diag
[binutils-gdb.git] / sim / arm / armsupp.c
blob9fcc7f646faf473c247c249c05bc1dbfff0a45c6
1 /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>. */
17 /* This must come before any other includes. */
18 #include "defs.h"
20 #include "armdefs.h"
21 #include "armemu.h"
22 #include "ansidecl.h"
23 #include "libiberty.h"
24 #include <math.h>
26 /* Definitions for the support routines. */
28 static ARMword ModeToBank (ARMword);
29 static void EnvokeList (ARMul_State *, unsigned long, unsigned long);
31 struct EventNode
32 { /* An event list node. */
33 unsigned (*func) (ARMul_State *); /* The function to call. */
34 struct EventNode *next;
37 /* This routine returns the value of a register from a mode. */
39 ARMword
40 ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
42 mode &= MODEBITS;
43 if (mode != state->Mode)
44 return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
45 else
46 return (state->Reg[reg]);
49 /* This routine sets the value of a register for a mode. */
51 void
52 ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
54 mode &= MODEBITS;
55 if (mode != state->Mode)
56 state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
57 else
58 state->Reg[reg] = value;
61 /* This routine returns the value of the PC, mode independently. */
63 ARMword
64 ARMul_GetPC (ARMul_State * state)
66 if (state->Mode > SVC26MODE)
67 return state->Reg[15];
68 else
69 return R15PC;
72 /* This routine returns the value of the PC, mode independently. */
74 ARMword
75 ARMul_GetNextPC (ARMul_State * state)
77 if (state->Mode > SVC26MODE)
78 return state->Reg[15] + isize;
79 else
80 return (state->Reg[15] + isize) & R15PCBITS;
83 /* This routine sets the value of the PC. */
85 void
86 ARMul_SetPC (ARMul_State * state, ARMword value)
88 if (ARMul_MODE32BIT)
89 state->Reg[15] = value & PCBITS;
90 else
91 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
92 FLUSHPIPE;
95 /* This routine returns the value of register 15, mode independently. */
97 ARMword
98 ARMul_GetR15 (ARMul_State * state)
100 if (state->Mode > SVC26MODE)
101 return (state->Reg[15]);
102 else
103 return (R15PC | ECC | ER15INT | EMODE);
106 /* This routine sets the value of Register 15. */
108 void
109 ARMul_SetR15 (ARMul_State * state, ARMword value)
111 if (ARMul_MODE32BIT)
112 state->Reg[15] = value & PCBITS;
113 else
115 state->Reg[15] = value;
116 ARMul_R15Altered (state);
118 FLUSHPIPE;
121 /* This routine returns the value of the CPSR. */
123 ARMword
124 ARMul_GetCPSR (ARMul_State * state)
126 return (CPSR | state->Cpsr);
129 /* This routine sets the value of the CPSR. */
131 void
132 ARMul_SetCPSR (ARMul_State * state, ARMword value)
134 state->Cpsr = value;
135 ARMul_CPSRAltered (state);
138 /* This routine does all the nasty bits involved in a write to the CPSR,
139 including updating the register bank, given a MSR instruction. */
141 void
142 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
144 state->Cpsr = ARMul_GetCPSR (state);
146 if (state->Mode != USER26MODE
147 && state->Mode != USER32MODE)
149 /* In user mode, only write flags. */
150 if (BIT (16))
151 SETPSR_C (state->Cpsr, rhs);
152 if (BIT (17))
153 SETPSR_X (state->Cpsr, rhs);
154 if (BIT (18))
155 SETPSR_S (state->Cpsr, rhs);
157 if (BIT (19))
158 SETPSR_F (state->Cpsr, rhs);
159 ARMul_CPSRAltered (state);
162 /* Get an SPSR from the specified mode. */
164 ARMword
165 ARMul_GetSPSR (ARMul_State * state, ARMword mode)
167 ARMword bank = ModeToBank (mode & MODEBITS);
169 if (! BANK_CAN_ACCESS_SPSR (bank))
170 return ARMul_GetCPSR (state);
172 return state->Spsr[bank];
175 /* This routine does a write to an SPSR. */
177 void
178 ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
180 ARMword bank = ModeToBank (mode & MODEBITS);
182 if (BANK_CAN_ACCESS_SPSR (bank))
183 state->Spsr[bank] = value;
186 /* This routine does a write to the current SPSR, given an MSR instruction. */
188 void
189 ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
191 if (BANK_CAN_ACCESS_SPSR (state->Bank))
193 if (BIT (16))
194 SETPSR_C (state->Spsr[state->Bank], rhs);
195 if (BIT (17))
196 SETPSR_X (state->Spsr[state->Bank], rhs);
197 if (BIT (18))
198 SETPSR_S (state->Spsr[state->Bank], rhs);
199 if (BIT (19))
200 SETPSR_F (state->Spsr[state->Bank], rhs);
204 /* This routine updates the state of the emulator after the Cpsr has been
205 changed. Both the processor flags and register bank are updated. */
207 void
208 ARMul_CPSRAltered (ARMul_State * state)
210 ARMword oldmode;
212 if (state->prog32Sig == LOW)
213 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
215 oldmode = state->Mode;
217 if (state->Mode != (state->Cpsr & MODEBITS))
219 state->Mode =
220 ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
222 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
224 state->Cpsr &= ~MODEBITS;
226 ASSIGNINT (state->Cpsr & INTBITS);
227 state->Cpsr &= ~INTBITS;
228 ASSIGNN ((state->Cpsr & NBIT) != 0);
229 state->Cpsr &= ~NBIT;
230 ASSIGNZ ((state->Cpsr & ZBIT) != 0);
231 state->Cpsr &= ~ZBIT;
232 ASSIGNC ((state->Cpsr & CBIT) != 0);
233 state->Cpsr &= ~CBIT;
234 ASSIGNV ((state->Cpsr & VBIT) != 0);
235 state->Cpsr &= ~VBIT;
236 ASSIGNS ((state->Cpsr & SBIT) != 0);
237 state->Cpsr &= ~SBIT;
238 #ifdef MODET
239 ASSIGNT ((state->Cpsr & TBIT) != 0);
240 state->Cpsr &= ~TBIT;
241 #endif
243 if (oldmode > SVC26MODE)
245 if (state->Mode <= SVC26MODE)
247 state->Emulate = CHANGEMODE;
248 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
251 else
253 if (state->Mode > SVC26MODE)
255 state->Emulate = CHANGEMODE;
256 state->Reg[15] = R15PC;
258 else
259 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
263 /* This routine updates the state of the emulator after register 15 has
264 been changed. Both the processor flags and register bank are updated.
265 This routine should only be called from a 26 bit mode. */
267 void
268 ARMul_R15Altered (ARMul_State * state)
270 if (state->Mode != R15MODE)
272 state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
273 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
276 if (state->Mode > SVC26MODE)
277 state->Emulate = CHANGEMODE;
279 ASSIGNR15INT (R15INT);
281 ASSIGNN ((state->Reg[15] & NBIT) != 0);
282 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
283 ASSIGNC ((state->Reg[15] & CBIT) != 0);
284 ASSIGNV ((state->Reg[15] & VBIT) != 0);
287 /* This routine controls the saving and restoring of registers across mode
288 changes. The regbank matrix is largely unused, only rows 13 and 14 are
289 used across all modes, 8 to 14 are used for FIQ, all others use the USER
290 column. It's easier this way. old and new parameter are modes numbers.
291 Notice the side effect of changing the Bank variable. */
293 ARMword
294 ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
296 unsigned i;
297 ARMword oldbank;
298 ARMword newbank;
300 oldbank = ModeToBank (oldmode);
301 newbank = state->Bank = ModeToBank (newmode);
303 /* Do we really need to do it? */
304 if (oldbank != newbank)
306 /* Save away the old registers. */
307 switch (oldbank)
309 case USERBANK:
310 case IRQBANK:
311 case SVCBANK:
312 case ABORTBANK:
313 case UNDEFBANK:
314 if (newbank == FIQBANK)
315 for (i = 8; i < 13; i++)
316 state->RegBank[USERBANK][i] = state->Reg[i];
317 state->RegBank[oldbank][13] = state->Reg[13];
318 state->RegBank[oldbank][14] = state->Reg[14];
319 break;
320 case FIQBANK:
321 for (i = 8; i < 15; i++)
322 state->RegBank[FIQBANK][i] = state->Reg[i];
323 break;
324 case DUMMYBANK:
325 for (i = 8; i < 15; i++)
326 state->RegBank[DUMMYBANK][i] = 0;
327 break;
328 default:
329 abort ();
332 /* Restore the new registers. */
333 switch (newbank)
335 case USERBANK:
336 case IRQBANK:
337 case SVCBANK:
338 case ABORTBANK:
339 case UNDEFBANK:
340 if (oldbank == FIQBANK)
341 for (i = 8; i < 13; i++)
342 state->Reg[i] = state->RegBank[USERBANK][i];
343 state->Reg[13] = state->RegBank[newbank][13];
344 state->Reg[14] = state->RegBank[newbank][14];
345 break;
346 case FIQBANK:
347 for (i = 8; i < 15; i++)
348 state->Reg[i] = state->RegBank[FIQBANK][i];
349 break;
350 case DUMMYBANK:
351 for (i = 8; i < 15; i++)
352 state->Reg[i] = 0;
353 break;
354 default:
355 abort ();
359 return newmode;
362 /* Given a processor mode, this routine returns the
363 register bank that will be accessed in that mode. */
365 static ARMword
366 ModeToBank (ARMword mode)
368 static ARMword bankofmode[] =
370 USERBANK, FIQBANK, IRQBANK, SVCBANK,
371 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
372 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
373 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
374 USERBANK, FIQBANK, IRQBANK, SVCBANK,
375 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
376 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
377 DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
380 if (mode >= ARRAY_SIZE (bankofmode))
381 return DUMMYBANK;
383 return bankofmode[mode];
386 /* Returns the register number of the nth register in a reg list. */
388 unsigned
389 ARMul_NthReg (ARMword instr, unsigned number)
391 unsigned bit, up_to;
393 for (bit = 0, up_to = 0; up_to <= number; bit ++)
394 if (BIT (bit))
395 up_to ++;
397 return (bit - 1);
400 /* Assigns the N and Z flags depending on the value of result. */
402 void
403 ARMul_NegZero (ARMul_State * state, ARMword result)
405 if (NEG (result))
407 SETN;
408 CLEARZ;
410 else if (result == 0)
412 CLEARN;
413 SETZ;
415 else
417 CLEARN;
418 CLEARZ;
422 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
425 AddOverflow (ARMword a, ARMword b, ARMword result)
427 return ((NEG (a) && NEG (b) && POS (result))
428 || (POS (a) && POS (b) && NEG (result)));
431 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
434 SubOverflow (ARMword a, ARMword b, ARMword result)
436 return ((NEG (a) && POS (b) && POS (result))
437 || (POS (a) && NEG (b) && NEG (result)));
440 /* Assigns the C flag after an addition of a and b to give result. */
442 void
443 ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
445 ASSIGNC ((NEG (a) && NEG (b)) ||
446 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
449 /* Assigns the V flag after an addition of a and b to give result. */
451 void
452 ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
454 ASSIGNV (AddOverflow (a, b, result));
457 /* Assigns the C flag after an subtraction of a and b to give result. */
459 void
460 ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
462 ASSIGNC ((NEG (a) && POS (b)) ||
463 (NEG (a) && POS (result)) || (POS (b) && POS (result)));
466 /* Assigns the V flag after an subtraction of a and b to give result. */
468 void
469 ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
471 ASSIGNV (SubOverflow (a, b, result));
474 static void
475 handle_VFP_xfer (ARMul_State * state, ARMword instr)
477 if (TOPBITS (28) == NV)
479 fprintf (stderr, "SIM: UNDEFINED VFP instruction\n");
480 return;
483 if (BITS (25, 27) != 0x6)
485 fprintf (stderr, "SIM: ISE: VFP handler called incorrectly\n");
486 return;
489 switch (BITS (20, 24))
491 case 0x04:
492 case 0x05:
494 /* VMOV double precision to/from two ARM registers. */
495 int vm = BITS (0, 3);
496 int rt1 = BITS (12, 15);
497 int rt2 = BITS (16, 19);
499 /* FIXME: UNPREDICTABLE if rt1 == 15 or rt2 == 15. */
500 if (BIT (20))
502 /* Transfer to ARM. */
503 /* FIXME: UPPREDICTABLE if rt1 == rt2. */
504 state->Reg[rt1] = VFP_dword (vm) & 0xffffffff;
505 state->Reg[rt2] = VFP_dword (vm) >> 32;
507 else
509 VFP_dword (vm) = state->Reg[rt2];
510 VFP_dword (vm) <<= 32;
511 VFP_dword (vm) |= (state->Reg[rt1] & 0xffffffff);
513 return;
516 case 0x08:
517 case 0x0A:
518 case 0x0C:
519 case 0x0E:
521 /* VSTM with PUW=011 or PUW=010. */
522 int n = BITS (16, 19);
523 int imm8 = BITS (0, 7);
525 ARMword address = state->Reg[n];
526 if (BIT (21))
527 state->Reg[n] = address + (imm8 << 2);
529 if (BIT (8))
531 int src = (BIT (22) << 4) | BITS (12, 15);
532 imm8 >>= 1;
533 while (imm8--)
535 if (state->bigendSig)
537 ARMul_StoreWordN (state, address, VFP_dword (src) >> 32);
538 ARMul_StoreWordN (state, address + 4, VFP_dword (src));
540 else
542 ARMul_StoreWordN (state, address, VFP_dword (src));
543 ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32);
545 address += 8;
546 src += 1;
549 else
551 int src = (BITS (12, 15) << 1) | BIT (22);
552 while (imm8--)
554 ARMul_StoreWordN (state, address, VFP_uword (src));
555 address += 4;
556 src += 1;
560 return;
562 case 0x10:
563 case 0x14:
564 case 0x18:
565 case 0x1C:
567 /* VSTR */
568 ARMword imm32 = BITS (0, 7) << 2;
569 int base = state->Reg[LHSReg];
570 ARMword address;
571 int dest;
573 if (LHSReg == 15)
574 base = (base + 3) & ~3;
576 address = base + (BIT (23) ? imm32 : - imm32);
578 if (CPNum == 10)
580 dest = (DESTReg << 1) + BIT (22);
582 ARMul_StoreWordN (state, address, VFP_uword (dest));
584 else
586 dest = (BIT (22) << 4) + DESTReg;
588 if (state->bigendSig)
590 ARMul_StoreWordN (state, address, VFP_dword (dest) >> 32);
591 ARMul_StoreWordN (state, address + 4, VFP_dword (dest));
593 else
595 ARMul_StoreWordN (state, address, VFP_dword (dest));
596 ARMul_StoreWordN (state, address + 4, VFP_dword (dest) >> 32);
600 return;
602 case 0x12:
603 case 0x16:
604 if (BITS (16, 19) == 13)
606 /* VPUSH */
607 ARMword address = state->Reg[13] - (BITS (0, 7) << 2);
608 state->Reg[13] = address;
610 if (BIT (8))
612 int dreg = (BIT (22) << 4) | BITS (12, 15);
613 int num = BITS (0, 7) >> 1;
614 while (num--)
616 if (state->bigendSig)
618 ARMul_StoreWordN (state, address, VFP_dword (dreg) >> 32);
619 ARMul_StoreWordN (state, address + 4, VFP_dword (dreg));
621 else
623 ARMul_StoreWordN (state, address, VFP_dword (dreg));
624 ARMul_StoreWordN (state, address + 4, VFP_dword (dreg) >> 32);
626 address += 8;
627 dreg += 1;
630 else
632 int sreg = (BITS (12, 15) << 1) | BIT (22);
633 int num = BITS (0, 7);
634 while (num--)
636 ARMul_StoreWordN (state, address, VFP_uword (sreg));
637 address += 4;
638 sreg += 1;
642 else if (BITS (9, 11) != 0x5)
643 break;
644 else
646 /* VSTM PUW=101 */
647 int n = BITS (16, 19);
648 int imm8 = BITS (0, 7);
649 ARMword address = state->Reg[n] - (imm8 << 2);
650 state->Reg[n] = address;
652 if (BIT (8))
654 int src = (BIT (22) << 4) | BITS (12, 15);
656 imm8 >>= 1;
657 while (imm8--)
659 if (state->bigendSig)
661 ARMul_StoreWordN (state, address, VFP_dword (src) >> 32);
662 ARMul_StoreWordN (state, address + 4, VFP_dword (src));
664 else
666 ARMul_StoreWordN (state, address, VFP_dword (src));
667 ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32);
669 address += 8;
670 src += 1;
673 else
675 int src = (BITS (12, 15) << 1) | BIT (22);
677 while (imm8--)
679 ARMul_StoreWordN (state, address, VFP_uword (src));
680 address += 4;
681 src += 1;
685 return;
687 case 0x13:
688 case 0x17:
689 /* VLDM PUW=101 */
690 case 0x09:
691 case 0x0D:
692 /* VLDM PUW=010 */
694 int n = BITS (16, 19);
695 int imm8 = BITS (0, 7);
697 ARMword address = state->Reg[n];
698 if (BIT (23) == 0)
699 address -= imm8 << 2;
700 if (BIT (21))
701 state->Reg[n] = BIT (23) ? address + (imm8 << 2) : address;
703 if (BIT (8))
705 int dest = (BIT (22) << 4) | BITS (12, 15);
706 imm8 >>= 1;
707 while (imm8--)
709 if (state->bigendSig)
711 VFP_dword (dest) = ARMul_LoadWordN (state, address);
712 VFP_dword (dest) <<= 32;
713 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
715 else
717 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
718 VFP_dword (dest) <<= 32;
719 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
722 if (trace)
723 fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest));
725 address += 8;
726 dest += 1;
729 else
731 int dest = (BITS (12, 15) << 1) | BIT (22);
733 while (imm8--)
735 VFP_uword (dest) = ARMul_LoadWordN (state, address);
736 address += 4;
737 dest += 1;
741 return;
743 case 0x0B:
744 case 0x0F:
745 if (BITS (16, 19) == 13)
747 /* VPOP */
748 ARMword address = state->Reg[13];
749 state->Reg[13] = address + (BITS (0, 7) << 2);
751 if (BIT (8))
753 int dest = (BIT (22) << 4) | BITS (12, 15);
754 int num = BITS (0, 7) >> 1;
756 while (num--)
758 if (state->bigendSig)
760 VFP_dword (dest) = ARMul_LoadWordN (state, address);
761 VFP_dword (dest) <<= 32;
762 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
764 else
766 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
767 VFP_dword (dest) <<= 32;
768 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
771 if (trace)
772 fprintf (stderr, " VFP: VPOP: D%d = %g\n", dest, VFP_dval (dest));
774 address += 8;
775 dest += 1;
778 else
780 int sreg = (BITS (12, 15) << 1) | BIT (22);
781 int num = BITS (0, 7);
783 while (num--)
785 VFP_uword (sreg) = ARMul_LoadWordN (state, address);
786 address += 4;
787 sreg += 1;
791 else if (BITS (9, 11) != 0x5)
792 break;
793 else
795 /* VLDM PUW=011 */
796 int n = BITS (16, 19);
797 int imm8 = BITS (0, 7);
798 ARMword address = state->Reg[n];
799 state->Reg[n] += imm8 << 2;
801 if (BIT (8))
803 int dest = (BIT (22) << 4) | BITS (12, 15);
805 imm8 >>= 1;
806 while (imm8--)
808 if (state->bigendSig)
810 VFP_dword (dest) = ARMul_LoadWordN (state, address);
811 VFP_dword (dest) <<= 32;
812 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
814 else
816 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
817 VFP_dword (dest) <<= 32;
818 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
821 if (trace)
822 fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest));
824 address += 8;
825 dest += 1;
828 else
830 int dest = (BITS (12, 15) << 1) | BIT (22);
831 while (imm8--)
833 VFP_uword (dest) = ARMul_LoadWordN (state, address);
834 address += 4;
835 dest += 1;
839 return;
841 case 0x11:
842 case 0x15:
843 case 0x19:
844 case 0x1D:
846 /* VLDR */
847 ARMword imm32 = BITS (0, 7) << 2;
848 int base = state->Reg[LHSReg];
849 ARMword address;
850 int dest;
852 if (LHSReg == 15)
853 base = (base + 3) & ~3;
855 address = base + (BIT (23) ? imm32 : - imm32);
857 if (CPNum == 10)
859 dest = (DESTReg << 1) + BIT (22);
861 VFP_uword (dest) = ARMul_LoadWordN (state, address);
863 else
865 dest = (BIT (22) << 4) + DESTReg;
867 if (state->bigendSig)
869 VFP_dword (dest) = ARMul_LoadWordN (state, address);
870 VFP_dword (dest) <<= 32;
871 VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4);
873 else
875 VFP_dword (dest) = ARMul_LoadWordN (state, address + 4);
876 VFP_dword (dest) <<= 32;
877 VFP_dword (dest) |= ARMul_LoadWordN (state, address);
880 if (trace)
881 fprintf (stderr, " VFP: VLDR: D%d = %g\n", dest, VFP_dval (dest));
884 return;
887 fprintf (stderr, "SIM: VFP: Unimplemented: %0x\n", BITS (20, 24));
890 /* This function does the work of generating the addresses used in an
891 LDC instruction. The code here is always post-indexed, it's up to the
892 caller to get the input address correct and to handle base register
893 modification. It also handles the Busy-Waiting. */
895 void
896 ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
898 unsigned cpab;
899 ARMword data;
901 if (CPNum == 10 || CPNum == 11)
903 handle_VFP_xfer (state, instr);
904 return;
907 UNDEF_LSCPCBaseWb;
909 if (! CP_ACCESS_ALLOWED (state, CPNum))
911 ARMul_UndefInstr (state, instr);
912 return;
915 if (ADDREXCEPT (address))
916 INTERNALABORT (address);
918 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
919 while (cpab == ARMul_BUSY)
921 ARMul_Icycles (state, 1, 0);
923 if (IntPending (state))
925 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
926 return;
928 else
929 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
931 if (cpab == ARMul_CANT)
933 CPTAKEABORT;
934 return;
937 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
938 data = ARMul_LoadWordN (state, address);
939 BUSUSEDINCPCN;
941 if (BIT (21))
942 LSBase = state->Base;
943 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
945 while (cpab == ARMul_INC)
947 address += 4;
948 data = ARMul_LoadWordN (state, address);
949 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
952 if (state->abortSig || state->Aborted)
953 TAKEABORT;
956 /* This function does the work of generating the addresses used in an
957 STC instruction. The code here is always post-indexed, it's up to the
958 caller to get the input address correct and to handle base register
959 modification. It also handles the Busy-Waiting. */
961 void
962 ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
964 unsigned cpab;
965 ARMword data;
967 if (CPNum == 10 || CPNum == 11)
969 handle_VFP_xfer (state, instr);
970 return;
973 UNDEF_LSCPCBaseWb;
975 if (! CP_ACCESS_ALLOWED (state, CPNum))
977 ARMul_UndefInstr (state, instr);
978 return;
981 if (ADDREXCEPT (address) || VECTORACCESS (address))
982 INTERNALABORT (address);
984 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
985 while (cpab == ARMul_BUSY)
987 ARMul_Icycles (state, 1, 0);
988 if (IntPending (state))
990 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
991 return;
993 else
994 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
997 if (cpab == ARMul_CANT)
999 CPTAKEABORT;
1000 return;
1002 #ifndef MODE32
1003 if (ADDREXCEPT (address) || VECTORACCESS (address))
1004 INTERNALABORT (address);
1005 #endif
1006 BUSUSEDINCPCN;
1007 if (BIT (21))
1008 LSBase = state->Base;
1009 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
1010 ARMul_StoreWordN (state, address, data);
1012 while (cpab == ARMul_INC)
1014 address += 4;
1015 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
1016 ARMul_StoreWordN (state, address, data);
1019 if (state->abortSig || state->Aborted)
1020 TAKEABORT;
1023 /* This function does the Busy-Waiting for an MCR instruction. */
1025 void
1026 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
1028 unsigned cpab;
1030 if (! CP_ACCESS_ALLOWED (state, CPNum))
1032 ARMul_UndefInstr (state, instr);
1033 return;
1036 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
1038 while (cpab == ARMul_BUSY)
1040 ARMul_Icycles (state, 1, 0);
1042 if (IntPending (state))
1044 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
1045 return;
1047 else
1048 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
1051 if (cpab == ARMul_CANT)
1052 ARMul_Abort (state, ARMul_UndefinedInstrV);
1053 else
1055 BUSUSEDINCPCN;
1056 ARMul_Ccycles (state, 1, 0);
1060 /* This function does the Busy-Waiting for an MRC instruction. */
1062 ARMword
1063 ARMul_MRC (ARMul_State * state, ARMword instr)
1065 unsigned cpab;
1066 ARMword result = 0;
1068 if (! CP_ACCESS_ALLOWED (state, CPNum))
1070 ARMul_UndefInstr (state, instr);
1071 return result;
1074 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
1075 while (cpab == ARMul_BUSY)
1077 ARMul_Icycles (state, 1, 0);
1078 if (IntPending (state))
1080 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
1081 return (0);
1083 else
1084 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
1086 if (cpab == ARMul_CANT)
1088 ARMul_Abort (state, ARMul_UndefinedInstrV);
1089 /* Parent will destroy the flags otherwise. */
1090 result = ECC;
1092 else
1094 BUSUSEDINCPCN;
1095 ARMul_Ccycles (state, 1, 0);
1096 ARMul_Icycles (state, 1, 0);
1099 return result;
1102 static void
1103 handle_VFP_op (ARMul_State * state, ARMword instr)
1105 int dest;
1106 int srcN;
1107 int srcM;
1109 if (BITS (9, 11) != 0x5 || BIT (4) != 0)
1111 fprintf (stderr, "SIM: VFP: Unimplemented: Float op: %08x\n", BITS (0,31));
1112 return;
1115 if (BIT (8))
1117 dest = BITS(12,15) + (BIT (22) << 4);
1118 srcN = LHSReg + (BIT (7) << 4);
1119 srcM = BITS (0,3) + (BIT (5) << 4);
1121 else
1123 dest = (BITS(12,15) << 1) + BIT (22);
1124 srcN = (LHSReg << 1) + BIT (7);
1125 srcM = (BITS (0,3) << 1) + BIT (5);
1128 switch (BITS (20, 27))
1130 case 0xE0:
1131 case 0xE4:
1132 /* VMLA VMLS */
1133 if (BIT (8))
1135 ARMdval val = VFP_dval (srcN) * VFP_dval (srcM);
1137 if (BIT (6))
1139 if (trace)
1140 fprintf (stderr, " VFP: VMLS: %g = %g - %g * %g\n",
1141 VFP_dval (dest) - val,
1142 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
1143 VFP_dval (dest) -= val;
1145 else
1147 if (trace)
1148 fprintf (stderr, " VFP: VMLA: %g = %g + %g * %g\n",
1149 VFP_dval (dest) + val,
1150 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
1151 VFP_dval (dest) += val;
1154 else
1156 ARMfval val = VFP_fval (srcN) * VFP_fval (srcM);
1158 if (BIT (6))
1160 if (trace)
1161 fprintf (stderr, " VFP: VMLS: %g = %g - %g * %g\n",
1162 VFP_fval (dest) - val,
1163 VFP_fval (dest), VFP_fval (srcN), VFP_fval (srcM));
1164 VFP_fval (dest) -= val;
1166 else
1168 if (trace)
1169 fprintf (stderr, " VFP: VMLA: %g = %g + %g * %g\n",
1170 VFP_fval (dest) + val,
1171 VFP_fval (dest), VFP_fval (srcN), VFP_fval (srcM));
1172 VFP_fval (dest) += val;
1175 return;
1177 case 0xE1:
1178 case 0xE5:
1179 if (BIT (8))
1181 ARMdval product = VFP_dval (srcN) * VFP_dval (srcM);
1183 if (BIT (6))
1185 /* VNMLA */
1186 if (trace)
1187 fprintf (stderr, " VFP: VNMLA: %g = -(%g + (%g * %g))\n",
1188 -(VFP_dval (dest) + product),
1189 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
1190 VFP_dval (dest) = -(product + VFP_dval (dest));
1192 else
1194 /* VNMLS */
1195 if (trace)
1196 fprintf (stderr, " VFP: VNMLS: %g = -(%g + (%g * %g))\n",
1197 -(VFP_dval (dest) + product),
1198 VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM));
1199 VFP_dval (dest) = product - VFP_dval (dest);
1202 else
1204 ARMfval product = VFP_fval (srcN) * VFP_fval (srcM);
1206 if (BIT (6))
1207 /* VNMLA */
1208 VFP_fval (dest) = -(product + VFP_fval (dest));
1209 else
1210 /* VNMLS */
1211 VFP_fval (dest) = product - VFP_fval (dest);
1213 return;
1215 case 0xE2:
1216 case 0xE6:
1217 if (BIT (8))
1219 ARMdval product = VFP_dval (srcN) * VFP_dval (srcM);
1221 if (BIT (6))
1223 if (trace)
1224 fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
1225 - product, VFP_dval (srcN), VFP_dval (srcM));
1226 /* VNMUL */
1227 VFP_dval (dest) = - product;
1229 else
1231 if (trace)
1232 fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
1233 product, VFP_dval (srcN), VFP_dval (srcM));
1234 /* VMUL */
1235 VFP_dval (dest) = product;
1238 else
1240 ARMfval product = VFP_fval (srcN) * VFP_fval (srcM);
1242 if (BIT (6))
1244 if (trace)
1245 fprintf (stderr, " VFP: VNMUL: %g = %g * %g\n",
1246 - product, VFP_fval (srcN), VFP_fval (srcM));
1248 VFP_fval (dest) = - product;
1250 else
1252 if (trace)
1253 fprintf (stderr, " VFP: VMUL: %g = %g * %g\n",
1254 product, VFP_fval (srcN), VFP_fval (srcM));
1256 VFP_fval (dest) = product;
1259 return;
1261 case 0xE3:
1262 case 0xE7:
1263 if (BIT (6) == 0)
1265 /* VADD */
1266 if (BIT(8))
1268 if (trace)
1269 fprintf (stderr, " VFP: VADD %g = %g + %g\n",
1270 VFP_dval (srcN) + VFP_dval (srcM),
1271 VFP_dval (srcN),
1272 VFP_dval (srcM));
1273 VFP_dval (dest) = VFP_dval (srcN) + VFP_dval (srcM);
1275 else
1276 VFP_fval (dest) = VFP_fval (srcN) + VFP_fval (srcM);
1279 else
1281 /* VSUB */
1282 if (BIT(8))
1284 if (trace)
1285 fprintf (stderr, " VFP: VSUB %g = %g - %g\n",
1286 VFP_dval (srcN) - VFP_dval (srcM),
1287 VFP_dval (srcN),
1288 VFP_dval (srcM));
1289 VFP_dval (dest) = VFP_dval (srcN) - VFP_dval (srcM);
1291 else
1292 VFP_fval (dest) = VFP_fval (srcN) - VFP_fval (srcM);
1294 return;
1296 case 0xE8:
1297 case 0xEC:
1298 if (BIT (6) == 1)
1299 break;
1301 /* VDIV */
1302 if (BIT (8))
1304 ARMdval res = VFP_dval (srcN) / VFP_dval (srcM);
1305 if (trace)
1306 fprintf (stderr, " VFP: VDIV (64bit): %g = %g / %g\n",
1307 res, VFP_dval (srcN), VFP_dval (srcM));
1308 VFP_dval (dest) = res;
1310 else
1312 if (trace)
1313 fprintf (stderr, " VFP: VDIV: %g = %g / %g\n",
1314 VFP_fval (srcN) / VFP_fval (srcM),
1315 VFP_fval (srcN), VFP_fval (srcM));
1317 VFP_fval (dest) = VFP_fval (srcN) / VFP_fval (srcM);
1319 return;
1321 case 0xEB:
1322 case 0xEF:
1323 if (BIT (6) != 1)
1324 break;
1326 switch (BITS (16, 19))
1328 case 0x0:
1329 if (BIT (7) == 0)
1331 if (BIT (8))
1333 /* VMOV.F64 <Dd>, <Dm>. */
1334 VFP_dval (dest) = VFP_dval (srcM);
1335 if (trace)
1336 fprintf (stderr, " VFP: VMOV d%d, d%d: %g\n", dest, srcM, VFP_dval (srcM));
1338 else
1340 /* VMOV.F32 <Sd>, <Sm>. */
1341 VFP_fval (dest) = VFP_fval (srcM);
1342 if (trace)
1343 fprintf (stderr, " VFP: VMOV s%d, s%d: %g\n", dest, srcM, VFP_fval (srcM));
1346 else
1348 /* VABS */
1349 if (BIT (8))
1351 ARMdval src = VFP_dval (srcM);
1353 VFP_dval (dest) = fabs (src);
1354 if (trace)
1355 fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_dval (dest));
1357 else
1359 ARMfval src = VFP_fval (srcM);
1361 VFP_fval (dest) = fabsf (src);
1362 if (trace)
1363 fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_fval (dest));
1366 return;
1368 case 0x1:
1369 if (BIT (7) == 0)
1371 /* VNEG */
1372 if (BIT (8))
1373 VFP_dval (dest) = - VFP_dval (srcM);
1374 else
1375 VFP_fval (dest) = - VFP_fval (srcM);
1377 else
1379 /* VSQRT */
1380 if (BIT (8))
1382 if (trace)
1383 fprintf (stderr, " VFP: %g = root(%g)\n",
1384 sqrt (VFP_dval (srcM)), VFP_dval (srcM));
1386 VFP_dval (dest) = sqrt (VFP_dval (srcM));
1388 else
1390 if (trace)
1391 fprintf (stderr, " VFP: %g = root(%g)\n",
1392 sqrtf (VFP_fval (srcM)), VFP_fval (srcM));
1394 VFP_fval (dest) = sqrtf (VFP_fval (srcM));
1397 return;
1399 case 0x4:
1400 case 0x5:
1401 /* VCMP, VCMPE */
1402 if (BIT(8))
1404 ARMdval res = VFP_dval (dest);
1406 if (BIT (16) == 0)
1408 ARMdval src = VFP_dval (srcM);
1410 if (isinf (res) && isinf (src))
1412 if (res > 0.0 && src > 0.0)
1413 res = 0.0;
1414 else if (res < 0.0 && src < 0.0)
1415 res = 0.0;
1416 /* else leave res alone. */
1418 else
1419 res -= src;
1422 /* FIXME: Add handling of signalling NaNs and the E bit. */
1424 state->FPSCR &= 0x0FFFFFFF;
1425 if (res < 0.0)
1426 state->FPSCR |= NBIT;
1427 else
1428 state->FPSCR |= CBIT;
1429 if (res == 0.0)
1430 state->FPSCR |= ZBIT;
1431 if (isnan (res))
1432 state->FPSCR |= VBIT;
1434 if (trace)
1435 fprintf (stderr, " VFP: VCMP (64bit) %g vs %g res %g, flags: %c%c%c%c\n",
1436 VFP_dval (dest), BIT (16) ? 0.0 : VFP_dval (srcM), res,
1437 state->FPSCR & NBIT ? 'N' : '-',
1438 state->FPSCR & ZBIT ? 'Z' : '-',
1439 state->FPSCR & CBIT ? 'C' : '-',
1440 state->FPSCR & VBIT ? 'V' : '-');
1442 else
1444 ARMfval res = VFP_fval (dest);
1446 if (BIT (16) == 0)
1448 ARMfval src = VFP_fval (srcM);
1450 if (isinf (res) && isinf (src))
1452 if (res > 0.0 && src > 0.0)
1453 res = 0.0;
1454 else if (res < 0.0 && src < 0.0)
1455 res = 0.0;
1456 /* else leave res alone. */
1458 else
1459 res -= src;
1462 /* FIXME: Add handling of signalling NaNs and the E bit. */
1464 state->FPSCR &= 0x0FFFFFFF;
1465 if (res < 0.0)
1466 state->FPSCR |= NBIT;
1467 else
1468 state->FPSCR |= CBIT;
1469 if (res == 0.0)
1470 state->FPSCR |= ZBIT;
1471 if (isnan (res))
1472 state->FPSCR |= VBIT;
1474 if (trace)
1475 fprintf (stderr, " VFP: VCMP (32bit) %g vs %g res %g, flags: %c%c%c%c\n",
1476 VFP_fval (dest), BIT (16) ? 0.0 : VFP_fval (srcM), res,
1477 state->FPSCR & NBIT ? 'N' : '-',
1478 state->FPSCR & ZBIT ? 'Z' : '-',
1479 state->FPSCR & CBIT ? 'C' : '-',
1480 state->FPSCR & VBIT ? 'V' : '-');
1482 return;
1484 case 0x7:
1485 if (BIT (8))
1487 dest = (DESTReg << 1) + BIT (22);
1488 VFP_fval (dest) = VFP_dval (srcM);
1490 else
1492 dest = DESTReg + (BIT (22) << 4);
1493 VFP_dval (dest) = VFP_fval (srcM);
1495 return;
1497 case 0x8:
1498 case 0xC:
1499 case 0xD:
1500 /* VCVT integer <-> FP */
1501 if (BIT (18))
1503 /* To integer. */
1504 if (BIT (8))
1506 dest = (BITS(12,15) << 1) + BIT (22);
1507 if (BIT (16))
1508 VFP_sword (dest) = VFP_dval (srcM);
1509 else
1510 VFP_uword (dest) = VFP_dval (srcM);
1512 else
1514 if (BIT (16))
1515 VFP_sword (dest) = VFP_fval (srcM);
1516 else
1517 VFP_uword (dest) = VFP_fval (srcM);
1520 else
1522 /* From integer. */
1523 if (BIT (8))
1525 srcM = (BITS (0,3) << 1) + BIT (5);
1526 if (BIT (7))
1527 VFP_dval (dest) = VFP_sword (srcM);
1528 else
1529 VFP_dval (dest) = VFP_uword (srcM);
1531 else
1533 if (BIT (7))
1534 VFP_fval (dest) = VFP_sword (srcM);
1535 else
1536 VFP_fval (dest) = VFP_uword (srcM);
1539 return;
1542 fprintf (stderr, "SIM: VFP: Unimplemented: Float op3: %03x\n", BITS (16,27));
1543 return;
1546 fprintf (stderr, "SIM: VFP: Unimplemented: Float op2: %02x\n", BITS (20, 27));
1547 return;
1550 /* This function does the Busy-Waiting for an CDP instruction. */
1552 void
1553 ARMul_CDP (ARMul_State * state, ARMword instr)
1555 unsigned cpab;
1557 if (CPNum == 10 || CPNum == 11)
1559 handle_VFP_op (state, instr);
1560 return;
1563 if (! CP_ACCESS_ALLOWED (state, CPNum))
1565 ARMul_UndefInstr (state, instr);
1566 return;
1569 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
1570 while (cpab == ARMul_BUSY)
1572 ARMul_Icycles (state, 1, 0);
1573 if (IntPending (state))
1575 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
1576 return;
1578 else
1579 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
1581 if (cpab == ARMul_CANT)
1582 ARMul_Abort (state, ARMul_UndefinedInstrV);
1583 else
1584 BUSUSEDN;
1587 /* This function handles Undefined instructions, as CP isntruction. */
1589 void
1590 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
1592 ARMul_Abort (state, ARMul_UndefinedInstrV);
1595 /* Return TRUE if an interrupt is pending, FALSE otherwise. */
1597 unsigned
1598 IntPending (ARMul_State * state)
1600 if (state->Exception)
1602 /* Any exceptions. */
1603 if (state->NresetSig == LOW)
1605 ARMul_Abort (state, ARMul_ResetV);
1606 return TRUE;
1608 else if (!state->NfiqSig && !FFLAG)
1610 ARMul_Abort (state, ARMul_FIQV);
1611 return TRUE;
1613 else if (!state->NirqSig && !IFLAG)
1615 ARMul_Abort (state, ARMul_IRQV);
1616 return TRUE;
1620 return FALSE;
1623 /* Align a word access to a non word boundary. */
1625 ARMword
1626 ARMul_Align (ARMul_State *state ATTRIBUTE_UNUSED, ARMword address, ARMword data)
1628 /* This code assumes the address is really unaligned,
1629 as a shift by 32 is undefined in C. */
1631 address = (address & 3) << 3; /* Get the word address. */
1632 return ((data >> address) | (data << (32 - address))); /* rot right */
1635 /* This routine is used to call another routine after a certain number of
1636 cycles have been executed. The first parameter is the number of cycles
1637 delay before the function is called, the second argument is a pointer
1638 to the function. A delay of zero doesn't work, just call the function. */
1640 void
1641 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
1642 unsigned (*what) (ARMul_State *))
1644 unsigned long when;
1645 struct EventNode *event;
1647 if (state->EventSet++ == 0)
1648 state->Now = ARMul_Time (state);
1649 when = (state->Now + delay) % EVENTLISTSIZE;
1650 event = (struct EventNode *) malloc (sizeof (struct EventNode));
1651 event->func = what;
1652 event->next = *(state->EventPtr + when);
1653 *(state->EventPtr + when) = event;
1656 /* This routine is called at the beginning of
1657 every cycle, to envoke scheduled events. */
1659 void
1660 ARMul_EnvokeEvent (ARMul_State * state)
1662 static unsigned long then;
1664 then = state->Now;
1665 state->Now = ARMul_Time (state) % EVENTLISTSIZE;
1666 if (then < state->Now)
1667 /* Schedule events. */
1668 EnvokeList (state, then, state->Now);
1669 else if (then > state->Now)
1671 /* Need to wrap around the list. */
1672 EnvokeList (state, then, EVENTLISTSIZE - 1L);
1673 EnvokeList (state, 0L, state->Now);
1677 /* Envokes all the entries in a range. */
1679 static void
1680 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
1682 for (; from <= to; from++)
1684 struct EventNode *anevent;
1686 anevent = *(state->EventPtr + from);
1687 while (anevent)
1689 (anevent->func) (state);
1690 state->EventSet--;
1691 anevent = anevent->next;
1693 *(state->EventPtr + from) = NULL;
1697 /* This routine is returns the number of clock ticks since the last reset. */
1699 unsigned long
1700 ARMul_Time (ARMul_State * state)
1702 return (state->NumScycles + state->NumNcycles +
1703 state->NumIcycles + state->NumCcycles + state->NumFcycles);