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/>. */
20 #include "libiberty.h"
23 /* Definitions for the support routines. */
25 static ARMword
ModeToBank (ARMword
);
26 static void EnvokeList (ARMul_State
*, unsigned long, unsigned long);
29 { /* An event list node. */
30 unsigned (*func
) (ARMul_State
*); /* The function to call. */
31 struct EventNode
*next
;
34 /* This routine returns the value of a register from a mode. */
37 ARMul_GetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
)
40 if (mode
!= state
->Mode
)
41 return (state
->RegBank
[ModeToBank ((ARMword
) mode
)][reg
]);
43 return (state
->Reg
[reg
]);
46 /* This routine sets the value of a register for a mode. */
49 ARMul_SetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
, ARMword value
)
52 if (mode
!= state
->Mode
)
53 state
->RegBank
[ModeToBank ((ARMword
) mode
)][reg
] = value
;
55 state
->Reg
[reg
] = value
;
58 /* This routine returns the value of the PC, mode independently. */
61 ARMul_GetPC (ARMul_State
* state
)
63 if (state
->Mode
> SVC26MODE
)
64 return state
->Reg
[15];
69 /* This routine returns the value of the PC, mode independently. */
72 ARMul_GetNextPC (ARMul_State
* state
)
74 if (state
->Mode
> SVC26MODE
)
75 return state
->Reg
[15] + isize
;
77 return (state
->Reg
[15] + isize
) & R15PCBITS
;
80 /* This routine sets the value of the PC. */
83 ARMul_SetPC (ARMul_State
* state
, ARMword value
)
86 state
->Reg
[15] = value
& PCBITS
;
88 state
->Reg
[15] = R15CCINTMODE
| (value
& R15PCBITS
);
92 /* This routine returns the value of register 15, mode independently. */
95 ARMul_GetR15 (ARMul_State
* state
)
97 if (state
->Mode
> SVC26MODE
)
98 return (state
->Reg
[15]);
100 return (R15PC
| ECC
| ER15INT
| EMODE
);
103 /* This routine sets the value of Register 15. */
106 ARMul_SetR15 (ARMul_State
* state
, ARMword value
)
109 state
->Reg
[15] = value
& PCBITS
;
112 state
->Reg
[15] = value
;
113 ARMul_R15Altered (state
);
118 /* This routine returns the value of the CPSR. */
121 ARMul_GetCPSR (ARMul_State
* state
)
123 return (CPSR
| state
->Cpsr
);
126 /* This routine sets the value of the CPSR. */
129 ARMul_SetCPSR (ARMul_State
* state
, ARMword value
)
132 ARMul_CPSRAltered (state
);
135 /* This routine does all the nasty bits involved in a write to the CPSR,
136 including updating the register bank, given a MSR instruction. */
139 ARMul_FixCPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
)
141 state
->Cpsr
= ARMul_GetCPSR (state
);
143 if (state
->Mode
!= USER26MODE
144 && state
->Mode
!= USER32MODE
)
146 /* In user mode, only write flags. */
148 SETPSR_C (state
->Cpsr
, rhs
);
150 SETPSR_X (state
->Cpsr
, rhs
);
152 SETPSR_S (state
->Cpsr
, rhs
);
155 SETPSR_F (state
->Cpsr
, rhs
);
156 ARMul_CPSRAltered (state
);
159 /* Get an SPSR from the specified mode. */
162 ARMul_GetSPSR (ARMul_State
* state
, ARMword mode
)
164 ARMword bank
= ModeToBank (mode
& MODEBITS
);
166 if (! BANK_CAN_ACCESS_SPSR (bank
))
167 return ARMul_GetCPSR (state
);
169 return state
->Spsr
[bank
];
172 /* This routine does a write to an SPSR. */
175 ARMul_SetSPSR (ARMul_State
* state
, ARMword mode
, ARMword value
)
177 ARMword bank
= ModeToBank (mode
& MODEBITS
);
179 if (BANK_CAN_ACCESS_SPSR (bank
))
180 state
->Spsr
[bank
] = value
;
183 /* This routine does a write to the current SPSR, given an MSR instruction. */
186 ARMul_FixSPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
)
188 if (BANK_CAN_ACCESS_SPSR (state
->Bank
))
191 SETPSR_C (state
->Spsr
[state
->Bank
], rhs
);
193 SETPSR_X (state
->Spsr
[state
->Bank
], rhs
);
195 SETPSR_S (state
->Spsr
[state
->Bank
], rhs
);
197 SETPSR_F (state
->Spsr
[state
->Bank
], rhs
);
201 /* This routine updates the state of the emulator after the Cpsr has been
202 changed. Both the processor flags and register bank are updated. */
205 ARMul_CPSRAltered (ARMul_State
* state
)
209 if (state
->prog32Sig
== LOW
)
210 state
->Cpsr
&= (CCBITS
| INTBITS
| R15MODEBITS
);
212 oldmode
= state
->Mode
;
214 if (state
->Mode
!= (state
->Cpsr
& MODEBITS
))
217 ARMul_SwitchMode (state
, state
->Mode
, state
->Cpsr
& MODEBITS
);
219 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
221 state
->Cpsr
&= ~MODEBITS
;
223 ASSIGNINT (state
->Cpsr
& INTBITS
);
224 state
->Cpsr
&= ~INTBITS
;
225 ASSIGNN ((state
->Cpsr
& NBIT
) != 0);
226 state
->Cpsr
&= ~NBIT
;
227 ASSIGNZ ((state
->Cpsr
& ZBIT
) != 0);
228 state
->Cpsr
&= ~ZBIT
;
229 ASSIGNC ((state
->Cpsr
& CBIT
) != 0);
230 state
->Cpsr
&= ~CBIT
;
231 ASSIGNV ((state
->Cpsr
& VBIT
) != 0);
232 state
->Cpsr
&= ~VBIT
;
233 ASSIGNS ((state
->Cpsr
& SBIT
) != 0);
234 state
->Cpsr
&= ~SBIT
;
236 ASSIGNT ((state
->Cpsr
& TBIT
) != 0);
237 state
->Cpsr
&= ~TBIT
;
240 if (oldmode
> SVC26MODE
)
242 if (state
->Mode
<= SVC26MODE
)
244 state
->Emulate
= CHANGEMODE
;
245 state
->Reg
[15] = ECC
| ER15INT
| EMODE
| R15PC
;
250 if (state
->Mode
> SVC26MODE
)
252 state
->Emulate
= CHANGEMODE
;
253 state
->Reg
[15] = R15PC
;
256 state
->Reg
[15] = ECC
| ER15INT
| EMODE
| R15PC
;
260 /* This routine updates the state of the emulator after register 15 has
261 been changed. Both the processor flags and register bank are updated.
262 This routine should only be called from a 26 bit mode. */
265 ARMul_R15Altered (ARMul_State
* state
)
267 if (state
->Mode
!= R15MODE
)
269 state
->Mode
= ARMul_SwitchMode (state
, state
->Mode
, R15MODE
);
270 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
273 if (state
->Mode
> SVC26MODE
)
274 state
->Emulate
= CHANGEMODE
;
276 ASSIGNR15INT (R15INT
);
278 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
279 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
280 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
281 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
284 /* This routine controls the saving and restoring of registers across mode
285 changes. The regbank matrix is largely unused, only rows 13 and 14 are
286 used across all modes, 8 to 14 are used for FIQ, all others use the USER
287 column. It's easier this way. old and new parameter are modes numbers.
288 Notice the side effect of changing the Bank variable. */
291 ARMul_SwitchMode (ARMul_State
* state
, ARMword oldmode
, ARMword newmode
)
297 oldbank
= ModeToBank (oldmode
);
298 newbank
= state
->Bank
= ModeToBank (newmode
);
300 /* Do we really need to do it? */
301 if (oldbank
!= newbank
)
303 /* Save away the old registers. */
311 if (newbank
== FIQBANK
)
312 for (i
= 8; i
< 13; i
++)
313 state
->RegBank
[USERBANK
][i
] = state
->Reg
[i
];
314 state
->RegBank
[oldbank
][13] = state
->Reg
[13];
315 state
->RegBank
[oldbank
][14] = state
->Reg
[14];
318 for (i
= 8; i
< 15; i
++)
319 state
->RegBank
[FIQBANK
][i
] = state
->Reg
[i
];
322 for (i
= 8; i
< 15; i
++)
323 state
->RegBank
[DUMMYBANK
][i
] = 0;
329 /* Restore the new registers. */
337 if (oldbank
== FIQBANK
)
338 for (i
= 8; i
< 13; i
++)
339 state
->Reg
[i
] = state
->RegBank
[USERBANK
][i
];
340 state
->Reg
[13] = state
->RegBank
[newbank
][13];
341 state
->Reg
[14] = state
->RegBank
[newbank
][14];
344 for (i
= 8; i
< 15; i
++)
345 state
->Reg
[i
] = state
->RegBank
[FIQBANK
][i
];
348 for (i
= 8; i
< 15; i
++)
359 /* Given a processor mode, this routine returns the
360 register bank that will be accessed in that mode. */
363 ModeToBank (ARMword mode
)
365 static ARMword bankofmode
[] =
367 USERBANK
, FIQBANK
, IRQBANK
, SVCBANK
,
368 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, DUMMYBANK
,
369 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, DUMMYBANK
,
370 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, DUMMYBANK
,
371 USERBANK
, FIQBANK
, IRQBANK
, SVCBANK
,
372 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, ABORTBANK
,
373 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, UNDEFBANK
,
374 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, SYSTEMBANK
377 if (mode
>= ARRAY_SIZE (bankofmode
))
380 return bankofmode
[mode
];
383 /* Returns the register number of the nth register in a reg list. */
386 ARMul_NthReg (ARMword instr
, unsigned number
)
390 for (bit
= 0, upto
= 0; upto
<= number
; bit
++)
397 /* Assigns the N and Z flags depending on the value of result. */
400 ARMul_NegZero (ARMul_State
* state
, ARMword result
)
407 else if (result
== 0)
419 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
422 AddOverflow (ARMword a
, ARMword b
, ARMword result
)
424 return ((NEG (a
) && NEG (b
) && POS (result
))
425 || (POS (a
) && POS (b
) && NEG (result
)));
428 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
431 SubOverflow (ARMword a
, ARMword b
, ARMword result
)
433 return ((NEG (a
) && POS (b
) && POS (result
))
434 || (POS (a
) && NEG (b
) && NEG (result
)));
437 /* Assigns the C flag after an addition of a and b to give result. */
440 ARMul_AddCarry (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
442 ASSIGNC ((NEG (a
) && NEG (b
)) ||
443 (NEG (a
) && POS (result
)) || (NEG (b
) && POS (result
)));
446 /* Assigns the V flag after an addition of a and b to give result. */
449 ARMul_AddOverflow (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
451 ASSIGNV (AddOverflow (a
, b
, result
));
454 /* Assigns the C flag after an subtraction of a and b to give result. */
457 ARMul_SubCarry (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
459 ASSIGNC ((NEG (a
) && POS (b
)) ||
460 (NEG (a
) && POS (result
)) || (POS (b
) && POS (result
)));
463 /* Assigns the V flag after an subtraction of a and b to give result. */
466 ARMul_SubOverflow (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
468 ASSIGNV (SubOverflow (a
, b
, result
));
472 handle_VFP_xfer (ARMul_State
* state
, ARMword instr
)
474 if (TOPBITS (28) == NV
)
476 fprintf (stderr
, "SIM: UNDEFINED VFP instruction\n");
480 if (BITS (25, 27) != 0x6)
482 fprintf (stderr
, "SIM: ISE: VFP handler called incorrectly\n");
486 switch (BITS (20, 24))
491 /* VMOV double precision to/from two ARM registers. */
492 int vm
= BITS (0, 3);
493 int rt1
= BITS (12, 15);
494 int rt2
= BITS (16, 19);
496 /* FIXME: UNPREDICTABLE if rt1 == 15 or rt2 == 15. */
499 /* Transfer to ARM. */
500 /* FIXME: UPPREDICTABLE if rt1 == rt2. */
501 state
->Reg
[rt1
] = VFP_dword (vm
) & 0xffffffff;
502 state
->Reg
[rt2
] = VFP_dword (vm
) >> 32;
506 VFP_dword (vm
) = state
->Reg
[rt2
];
507 VFP_dword (vm
) <<= 32;
508 VFP_dword (vm
) |= (state
->Reg
[rt1
] & 0xffffffff);
518 /* VSTM with PUW=011 or PUW=010. */
519 int n
= BITS (16, 19);
520 int imm8
= BITS (0, 7);
522 ARMword address
= state
->Reg
[n
];
524 state
->Reg
[n
] = address
+ (imm8
<< 2);
528 int src
= (BIT (22) << 4) | BITS (12, 15);
532 if (state
->bigendSig
)
534 ARMul_StoreWordN (state
, address
, VFP_dword (src
) >> 32);
535 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
));
539 ARMul_StoreWordN (state
, address
, VFP_dword (src
));
540 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
) >> 32);
548 int src
= (BITS (12, 15) << 1) | BIT (22);
551 ARMul_StoreWordN (state
, address
, VFP_uword (src
));
565 ARMword imm32
= BITS (0, 7) << 2;
566 int base
= state
->Reg
[LHSReg
];
571 base
= (base
+ 3) & ~3;
573 address
= base
+ (BIT (23) ? imm32
: - imm32
);
577 dest
= (DESTReg
<< 1) + BIT (22);
579 ARMul_StoreWordN (state
, address
, VFP_uword (dest
));
583 dest
= (BIT (22) << 4) + DESTReg
;
585 if (state
->bigendSig
)
587 ARMul_StoreWordN (state
, address
, VFP_dword (dest
) >> 32);
588 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dest
));
592 ARMul_StoreWordN (state
, address
, VFP_dword (dest
));
593 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dest
) >> 32);
601 if (BITS (16, 19) == 13)
604 ARMword address
= state
->Reg
[13] - (BITS (0, 7) << 2);
605 state
->Reg
[13] = address
;
609 int dreg
= (BIT (22) << 4) | BITS (12, 15);
610 int num
= BITS (0, 7) >> 1;
613 if (state
->bigendSig
)
615 ARMul_StoreWordN (state
, address
, VFP_dword (dreg
) >> 32);
616 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dreg
));
620 ARMul_StoreWordN (state
, address
, VFP_dword (dreg
));
621 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dreg
) >> 32);
629 int sreg
= (BITS (12, 15) << 1) | BIT (22);
630 int num
= BITS (0, 7);
633 ARMul_StoreWordN (state
, address
, VFP_uword (sreg
));
639 else if (BITS (9, 11) != 0x5)
644 int n
= BITS (16, 19);
645 int imm8
= BITS (0, 7);
646 ARMword address
= state
->Reg
[n
] - (imm8
<< 2);
647 state
->Reg
[n
] = address
;
651 int src
= (BIT (22) << 4) | BITS (12, 15);
656 if (state
->bigendSig
)
658 ARMul_StoreWordN (state
, address
, VFP_dword (src
) >> 32);
659 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
));
663 ARMul_StoreWordN (state
, address
, VFP_dword (src
));
664 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
) >> 32);
672 int src
= (BITS (12, 15) << 1) | BIT (22);
676 ARMul_StoreWordN (state
, address
, VFP_uword (src
));
691 int n
= BITS (16, 19);
692 int imm8
= BITS (0, 7);
694 ARMword address
= state
->Reg
[n
];
696 address
-= imm8
<< 2;
698 state
->Reg
[n
] = BIT (23) ? address
+ (imm8
<< 2) : address
;
702 int dest
= (BIT (22) << 4) | BITS (12, 15);
706 if (state
->bigendSig
)
708 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
);
709 VFP_dword (dest
) <<= 32;
710 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
+ 4);
714 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
715 VFP_dword (dest
) <<= 32;
716 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
720 fprintf (stderr
, " VFP: VLDM: D%d = %g\n", dest
, VFP_dval (dest
));
728 int dest
= (BITS (12, 15) << 1) | BIT (22);
732 VFP_uword (dest
) = ARMul_LoadWordN (state
, address
);
742 if (BITS (16, 19) == 13)
745 ARMword address
= state
->Reg
[13];
746 state
->Reg
[13] = address
+ (BITS (0, 7) << 2);
750 int dest
= (BIT (22) << 4) | BITS (12, 15);
751 int num
= BITS (0, 7) >> 1;
755 if (state
->bigendSig
)
757 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
);
758 VFP_dword (dest
) <<= 32;
759 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
+ 4);
763 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
764 VFP_dword (dest
) <<= 32;
765 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
769 fprintf (stderr
, " VFP: VPOP: D%d = %g\n", dest
, VFP_dval (dest
));
777 int sreg
= (BITS (12, 15) << 1) | BIT (22);
778 int num
= BITS (0, 7);
782 VFP_uword (sreg
) = ARMul_LoadWordN (state
, address
);
788 else if (BITS (9, 11) != 0x5)
793 int n
= BITS (16, 19);
794 int imm8
= BITS (0, 7);
795 ARMword address
= state
->Reg
[n
];
796 state
->Reg
[n
] += imm8
<< 2;
800 int dest
= (BIT (22) << 4) | BITS (12, 15);
805 if (state
->bigendSig
)
807 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
);
808 VFP_dword (dest
) <<= 32;
809 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
+ 4);
813 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
814 VFP_dword (dest
) <<= 32;
815 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
819 fprintf (stderr
, " VFP: VLDM: D%d = %g\n", dest
, VFP_dval (dest
));
827 int dest
= (BITS (12, 15) << 1) | BIT (22);
830 VFP_uword (dest
) = ARMul_LoadWordN (state
, address
);
844 ARMword imm32
= BITS (0, 7) << 2;
845 int base
= state
->Reg
[LHSReg
];
850 base
= (base
+ 3) & ~3;
852 address
= base
+ (BIT (23) ? imm32
: - imm32
);
856 dest
= (DESTReg
<< 1) + BIT (22);
858 VFP_uword (dest
) = ARMul_LoadWordN (state
, address
);
862 dest
= (BIT (22) << 4) + DESTReg
;
864 if (state
->bigendSig
)
866 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
);
867 VFP_dword (dest
) <<= 32;
868 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
+ 4);
872 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
873 VFP_dword (dest
) <<= 32;
874 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
878 fprintf (stderr
, " VFP: VLDR: D%d = %g\n", dest
, VFP_dval (dest
));
884 fprintf (stderr
, "SIM: VFP: Unimplemented: %0x\n", BITS (20, 24));
887 /* This function does the work of generating the addresses used in an
888 LDC instruction. The code here is always post-indexed, it's up to the
889 caller to get the input address correct and to handle base register
890 modification. It also handles the Busy-Waiting. */
893 ARMul_LDC (ARMul_State
* state
, ARMword instr
, ARMword address
)
898 if (CPNum
== 10 || CPNum
== 11)
900 handle_VFP_xfer (state
, instr
);
906 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
908 ARMul_UndefInstr (state
, instr
);
912 if (ADDREXCEPT (address
))
913 INTERNALABORT (address
);
915 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_FIRST
, instr
, 0);
916 while (cpab
== ARMul_BUSY
)
918 ARMul_Icycles (state
, 1, 0);
920 if (IntPending (state
))
922 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
926 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_BUSY
, instr
, 0);
928 if (cpab
== ARMul_CANT
)
934 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_TRANSFER
, instr
, 0);
935 data
= ARMul_LoadWordN (state
, address
);
939 LSBase
= state
->Base
;
940 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
942 while (cpab
== ARMul_INC
)
945 data
= ARMul_LoadWordN (state
, address
);
946 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
949 if (state
->abortSig
|| state
->Aborted
)
953 /* This function does the work of generating the addresses used in an
954 STC instruction. The code here is always post-indexed, it's up to the
955 caller to get the input address correct and to handle base register
956 modification. It also handles the Busy-Waiting. */
959 ARMul_STC (ARMul_State
* state
, ARMword instr
, ARMword address
)
964 if (CPNum
== 10 || CPNum
== 11)
966 handle_VFP_xfer (state
, instr
);
972 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
974 ARMul_UndefInstr (state
, instr
);
978 if (ADDREXCEPT (address
) || VECTORACCESS (address
))
979 INTERNALABORT (address
);
981 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_FIRST
, instr
, &data
);
982 while (cpab
== ARMul_BUSY
)
984 ARMul_Icycles (state
, 1, 0);
985 if (IntPending (state
))
987 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
991 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_BUSY
, instr
, &data
);
994 if (cpab
== ARMul_CANT
)
1000 if (ADDREXCEPT (address
) || VECTORACCESS (address
))
1001 INTERNALABORT (address
);
1005 LSBase
= state
->Base
;
1006 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_DATA
, instr
, &data
);
1007 ARMul_StoreWordN (state
, address
, data
);
1009 while (cpab
== ARMul_INC
)
1012 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_DATA
, instr
, &data
);
1013 ARMul_StoreWordN (state
, address
, data
);
1016 if (state
->abortSig
|| state
->Aborted
)
1020 /* This function does the Busy-Waiting for an MCR instruction. */
1023 ARMul_MCR (ARMul_State
* state
, ARMword instr
, ARMword source
)
1027 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
1029 ARMul_UndefInstr (state
, instr
);
1033 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_FIRST
, instr
, source
);
1035 while (cpab
== ARMul_BUSY
)
1037 ARMul_Icycles (state
, 1, 0);
1039 if (IntPending (state
))
1041 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
1045 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_BUSY
, instr
, source
);
1048 if (cpab
== ARMul_CANT
)
1049 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1053 ARMul_Ccycles (state
, 1, 0);
1057 /* This function does the Busy-Waiting for an MRC instruction. */
1060 ARMul_MRC (ARMul_State
* state
, ARMword instr
)
1065 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
1067 ARMul_UndefInstr (state
, instr
);
1071 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_FIRST
, instr
, &result
);
1072 while (cpab
== ARMul_BUSY
)
1074 ARMul_Icycles (state
, 1, 0);
1075 if (IntPending (state
))
1077 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
1081 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_BUSY
, instr
, &result
);
1083 if (cpab
== ARMul_CANT
)
1085 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1086 /* Parent will destroy the flags otherwise. */
1092 ARMul_Ccycles (state
, 1, 0);
1093 ARMul_Icycles (state
, 1, 0);
1100 handle_VFP_op (ARMul_State
* state
, ARMword instr
)
1106 if (BITS (9, 11) != 0x5 || BIT (4) != 0)
1108 fprintf (stderr
, "SIM: VFP: Unimplemented: Float op: %08x\n", BITS (0,31));
1114 dest
= BITS(12,15) + (BIT (22) << 4);
1115 srcN
= LHSReg
+ (BIT (7) << 4);
1116 srcM
= BITS (0,3) + (BIT (5) << 4);
1120 dest
= (BITS(12,15) << 1) + BIT (22);
1121 srcN
= (LHSReg
<< 1) + BIT (7);
1122 srcM
= (BITS (0,3) << 1) + BIT (5);
1125 switch (BITS (20, 27))
1132 ARMdval val
= VFP_dval (srcN
) * VFP_dval (srcM
);
1137 fprintf (stderr
, " VFP: VMLS: %g = %g - %g * %g\n",
1138 VFP_dval (dest
) - val
,
1139 VFP_dval (dest
), VFP_dval (srcN
), VFP_dval (srcM
));
1140 VFP_dval (dest
) -= val
;
1145 fprintf (stderr
, " VFP: VMLA: %g = %g + %g * %g\n",
1146 VFP_dval (dest
) + val
,
1147 VFP_dval (dest
), VFP_dval (srcN
), VFP_dval (srcM
));
1148 VFP_dval (dest
) += val
;
1153 ARMfval val
= VFP_fval (srcN
) * VFP_fval (srcM
);
1158 fprintf (stderr
, " VFP: VMLS: %g = %g - %g * %g\n",
1159 VFP_fval (dest
) - val
,
1160 VFP_fval (dest
), VFP_fval (srcN
), VFP_fval (srcM
));
1161 VFP_fval (dest
) -= val
;
1166 fprintf (stderr
, " VFP: VMLA: %g = %g + %g * %g\n",
1167 VFP_fval (dest
) + val
,
1168 VFP_fval (dest
), VFP_fval (srcN
), VFP_fval (srcM
));
1169 VFP_fval (dest
) += val
;
1178 ARMdval product
= VFP_dval (srcN
) * VFP_dval (srcM
);
1184 fprintf (stderr
, " VFP: VNMLA: %g = -(%g + (%g * %g))\n",
1185 -(VFP_dval (dest
) + product
),
1186 VFP_dval (dest
), VFP_dval (srcN
), VFP_dval (srcM
));
1187 VFP_dval (dest
) = -(product
+ VFP_dval (dest
));
1193 fprintf (stderr
, " VFP: VNMLS: %g = -(%g + (%g * %g))\n",
1194 -(VFP_dval (dest
) + product
),
1195 VFP_dval (dest
), VFP_dval (srcN
), VFP_dval (srcM
));
1196 VFP_dval (dest
) = product
- VFP_dval (dest
);
1201 ARMfval product
= VFP_fval (srcN
) * VFP_fval (srcM
);
1205 VFP_fval (dest
) = -(product
+ VFP_fval (dest
));
1208 VFP_fval (dest
) = product
- VFP_fval (dest
);
1216 ARMdval product
= VFP_dval (srcN
) * VFP_dval (srcM
);
1221 fprintf (stderr
, " VFP: VMUL: %g = %g * %g\n",
1222 - product
, VFP_dval (srcN
), VFP_dval (srcM
));
1224 VFP_dval (dest
) = - product
;
1229 fprintf (stderr
, " VFP: VMUL: %g = %g * %g\n",
1230 product
, VFP_dval (srcN
), VFP_dval (srcM
));
1232 VFP_dval (dest
) = product
;
1237 ARMfval product
= VFP_fval (srcN
) * VFP_fval (srcM
);
1242 fprintf (stderr
, " VFP: VNMUL: %g = %g * %g\n",
1243 - product
, VFP_fval (srcN
), VFP_fval (srcM
));
1245 VFP_fval (dest
) = - product
;
1250 fprintf (stderr
, " VFP: VMUL: %g = %g * %g\n",
1251 product
, VFP_fval (srcN
), VFP_fval (srcM
));
1253 VFP_fval (dest
) = product
;
1266 fprintf (stderr
, " VFP: VADD %g = %g + %g\n",
1267 VFP_dval (srcN
) + VFP_dval (srcM
),
1270 VFP_dval (dest
) = VFP_dval (srcN
) + VFP_dval (srcM
);
1273 VFP_fval (dest
) = VFP_fval (srcN
) + VFP_fval (srcM
);
1282 fprintf (stderr
, " VFP: VSUB %g = %g - %g\n",
1283 VFP_dval (srcN
) - VFP_dval (srcM
),
1286 VFP_dval (dest
) = VFP_dval (srcN
) - VFP_dval (srcM
);
1289 VFP_fval (dest
) = VFP_fval (srcN
) - VFP_fval (srcM
);
1301 ARMdval res
= VFP_dval (srcN
) / VFP_dval (srcM
);
1303 fprintf (stderr
, " VFP: VDIV (64bit): %g = %g / %g\n",
1304 res
, VFP_dval (srcN
), VFP_dval (srcM
));
1305 VFP_dval (dest
) = res
;
1310 fprintf (stderr
, " VFP: VDIV: %g = %g / %g\n",
1311 VFP_fval (srcN
) / VFP_fval (srcM
),
1312 VFP_fval (srcN
), VFP_fval (srcM
));
1314 VFP_fval (dest
) = VFP_fval (srcN
) / VFP_fval (srcM
);
1323 switch (BITS (16, 19))
1330 /* VMOV.F64 <Dd>, <Dm>. */
1331 VFP_dval (dest
) = VFP_dval (srcM
);
1333 fprintf (stderr
, " VFP: VMOV d%d, d%d: %g\n", dest
, srcM
, VFP_dval (srcM
));
1337 /* VMOV.F32 <Sd>, <Sm>. */
1338 VFP_fval (dest
) = VFP_fval (srcM
);
1340 fprintf (stderr
, " VFP: VMOV s%d, s%d: %g\n", dest
, srcM
, VFP_fval (srcM
));
1348 ARMdval src
= VFP_dval (srcM
);
1350 VFP_dval (dest
) = fabs (src
);
1352 fprintf (stderr
, " VFP: VABS (%g) = %g\n", src
, VFP_dval (dest
));
1356 ARMfval src
= VFP_fval (srcM
);
1358 VFP_fval (dest
) = fabsf (src
);
1360 fprintf (stderr
, " VFP: VABS (%g) = %g\n", src
, VFP_fval (dest
));
1370 VFP_dval (dest
) = - VFP_dval (srcM
);
1372 VFP_fval (dest
) = - VFP_fval (srcM
);
1380 fprintf (stderr
, " VFP: %g = root(%g)\n",
1381 sqrt (VFP_dval (srcM
)), VFP_dval (srcM
));
1383 VFP_dval (dest
) = sqrt (VFP_dval (srcM
));
1388 fprintf (stderr
, " VFP: %g = root(%g)\n",
1389 sqrtf (VFP_fval (srcM
)), VFP_fval (srcM
));
1391 VFP_fval (dest
) = sqrtf (VFP_fval (srcM
));
1401 ARMdval res
= VFP_dval (dest
);
1405 ARMdval src
= VFP_dval (srcM
);
1407 if (isinf (res
) && isinf (src
))
1409 if (res
> 0.0 && src
> 0.0)
1411 else if (res
< 0.0 && src
< 0.0)
1413 /* else leave res alone. */
1419 /* FIXME: Add handling of signalling NaNs and the E bit. */
1421 state
->FPSCR
&= 0x0FFFFFFF;
1423 state
->FPSCR
|= NBIT
;
1425 state
->FPSCR
|= CBIT
;
1427 state
->FPSCR
|= ZBIT
;
1429 state
->FPSCR
|= VBIT
;
1432 fprintf (stderr
, " VFP: VCMP (64bit) %g vs %g res %g, flags: %c%c%c%c\n",
1433 VFP_dval (dest
), BIT (16) ? 0.0 : VFP_dval (srcM
), res
,
1434 state
->FPSCR
& NBIT
? 'N' : '-',
1435 state
->FPSCR
& ZBIT
? 'Z' : '-',
1436 state
->FPSCR
& CBIT
? 'C' : '-',
1437 state
->FPSCR
& VBIT
? 'V' : '-');
1441 ARMfval res
= VFP_fval (dest
);
1445 ARMfval src
= VFP_fval (srcM
);
1447 if (isinf (res
) && isinf (src
))
1449 if (res
> 0.0 && src
> 0.0)
1451 else if (res
< 0.0 && src
< 0.0)
1453 /* else leave res alone. */
1459 /* FIXME: Add handling of signalling NaNs and the E bit. */
1461 state
->FPSCR
&= 0x0FFFFFFF;
1463 state
->FPSCR
|= NBIT
;
1465 state
->FPSCR
|= CBIT
;
1467 state
->FPSCR
|= ZBIT
;
1469 state
->FPSCR
|= VBIT
;
1472 fprintf (stderr
, " VFP: VCMP (32bit) %g vs %g res %g, flags: %c%c%c%c\n",
1473 VFP_fval (dest
), BIT (16) ? 0.0 : VFP_fval (srcM
), res
,
1474 state
->FPSCR
& NBIT
? 'N' : '-',
1475 state
->FPSCR
& ZBIT
? 'Z' : '-',
1476 state
->FPSCR
& CBIT
? 'C' : '-',
1477 state
->FPSCR
& VBIT
? 'V' : '-');
1484 dest
= (DESTReg
<< 1) + BIT (22);
1485 VFP_fval (dest
) = VFP_dval (srcM
);
1489 dest
= DESTReg
+ (BIT (22) << 4);
1490 VFP_dval (dest
) = VFP_fval (srcM
);
1497 /* VCVT integer <-> FP */
1503 dest
= (BITS(12,15) << 1) + BIT (22);
1505 VFP_sword (dest
) = VFP_dval (srcM
);
1507 VFP_uword (dest
) = VFP_dval (srcM
);
1512 VFP_sword (dest
) = VFP_fval (srcM
);
1514 VFP_uword (dest
) = VFP_fval (srcM
);
1522 srcM
= (BITS (0,3) << 1) + BIT (5);
1524 VFP_dval (dest
) = VFP_sword (srcM
);
1526 VFP_dval (dest
) = VFP_uword (srcM
);
1531 VFP_fval (dest
) = VFP_sword (srcM
);
1533 VFP_fval (dest
) = VFP_uword (srcM
);
1539 fprintf (stderr
, "SIM: VFP: Unimplemented: Float op3: %03x\n", BITS (16,27));
1543 fprintf (stderr
, "SIM: VFP: Unimplemented: Float op2: %02x\n", BITS (20, 27));
1547 /* This function does the Busy-Waiting for an CDP instruction. */
1550 ARMul_CDP (ARMul_State
* state
, ARMword instr
)
1554 if (CPNum
== 10 || CPNum
== 11)
1556 handle_VFP_op (state
, instr
);
1560 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
1562 ARMul_UndefInstr (state
, instr
);
1566 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_FIRST
, instr
);
1567 while (cpab
== ARMul_BUSY
)
1569 ARMul_Icycles (state
, 1, 0);
1570 if (IntPending (state
))
1572 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
);
1576 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_BUSY
, instr
);
1578 if (cpab
== ARMul_CANT
)
1579 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1584 /* This function handles Undefined instructions, as CP isntruction. */
1587 ARMul_UndefInstr (ARMul_State
* state
, ARMword instr ATTRIBUTE_UNUSED
)
1589 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1592 /* Return TRUE if an interrupt is pending, FALSE otherwise. */
1595 IntPending (ARMul_State
* state
)
1597 if (state
->Exception
)
1599 /* Any exceptions. */
1600 if (state
->NresetSig
== LOW
)
1602 ARMul_Abort (state
, ARMul_ResetV
);
1605 else if (!state
->NfiqSig
&& !FFLAG
)
1607 ARMul_Abort (state
, ARMul_FIQV
);
1610 else if (!state
->NirqSig
&& !IFLAG
)
1612 ARMul_Abort (state
, ARMul_IRQV
);
1620 /* Align a word access to a non word boundary. */
1623 ARMul_Align (ARMul_State
*state ATTRIBUTE_UNUSED
, ARMword address
, ARMword data
)
1625 /* This code assumes the address is really unaligned,
1626 as a shift by 32 is undefined in C. */
1628 address
= (address
& 3) << 3; /* Get the word address. */
1629 return ((data
>> address
) | (data
<< (32 - address
))); /* rot right */
1632 /* This routine is used to call another routine after a certain number of
1633 cycles have been executed. The first parameter is the number of cycles
1634 delay before the function is called, the second argument is a pointer
1635 to the function. A delay of zero doesn't work, just call the function. */
1638 ARMul_ScheduleEvent (ARMul_State
* state
, unsigned long delay
,
1639 unsigned (*what
) (ARMul_State
*))
1642 struct EventNode
*event
;
1644 if (state
->EventSet
++ == 0)
1645 state
->Now
= ARMul_Time (state
);
1646 when
= (state
->Now
+ delay
) % EVENTLISTSIZE
;
1647 event
= (struct EventNode
*) malloc (sizeof (struct EventNode
));
1649 event
->next
= *(state
->EventPtr
+ when
);
1650 *(state
->EventPtr
+ when
) = event
;
1653 /* This routine is called at the beginning of
1654 every cycle, to envoke scheduled events. */
1657 ARMul_EnvokeEvent (ARMul_State
* state
)
1659 static unsigned long then
;
1662 state
->Now
= ARMul_Time (state
) % EVENTLISTSIZE
;
1663 if (then
< state
->Now
)
1664 /* Schedule events. */
1665 EnvokeList (state
, then
, state
->Now
);
1666 else if (then
> state
->Now
)
1668 /* Need to wrap around the list. */
1669 EnvokeList (state
, then
, EVENTLISTSIZE
- 1L);
1670 EnvokeList (state
, 0L, state
->Now
);
1674 /* Envokes all the entries in a range. */
1677 EnvokeList (ARMul_State
* state
, unsigned long from
, unsigned long to
)
1679 for (; from
<= to
; from
++)
1681 struct EventNode
*anevent
;
1683 anevent
= *(state
->EventPtr
+ from
);
1686 (anevent
->func
) (state
);
1688 anevent
= anevent
->next
;
1690 *(state
->EventPtr
+ from
) = NULL
;
1694 /* This routine is returns the number of clock ticks since the last reset. */
1697 ARMul_Time (ARMul_State
* state
)
1699 return (state
->NumScycles
+ state
->NumNcycles
+
1700 state
->NumIcycles
+ state
->NumCcycles
+ state
->NumFcycles
);