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/>. */
22 /* Definitions for the support routines. */
24 static ARMword
ModeToBank (ARMword
);
25 static void EnvokeList (ARMul_State
*, unsigned long, unsigned long);
28 { /* An event list node. */
29 unsigned (*func
) (ARMul_State
*); /* The function to call. */
30 struct EventNode
*next
;
33 /* This routine returns the value of a register from a mode. */
36 ARMul_GetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
)
39 if (mode
!= state
->Mode
)
40 return (state
->RegBank
[ModeToBank ((ARMword
) mode
)][reg
]);
42 return (state
->Reg
[reg
]);
45 /* This routine sets the value of a register for a mode. */
48 ARMul_SetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
, ARMword value
)
51 if (mode
!= state
->Mode
)
52 state
->RegBank
[ModeToBank ((ARMword
) mode
)][reg
] = value
;
54 state
->Reg
[reg
] = value
;
57 /* This routine returns the value of the PC, mode independently. */
60 ARMul_GetPC (ARMul_State
* state
)
62 if (state
->Mode
> SVC26MODE
)
63 return state
->Reg
[15];
68 /* This routine returns the value of the PC, mode independently. */
71 ARMul_GetNextPC (ARMul_State
* state
)
73 if (state
->Mode
> SVC26MODE
)
74 return state
->Reg
[15] + isize
;
76 return (state
->Reg
[15] + isize
) & R15PCBITS
;
79 /* This routine sets the value of the PC. */
82 ARMul_SetPC (ARMul_State
* state
, ARMword value
)
85 state
->Reg
[15] = value
& PCBITS
;
87 state
->Reg
[15] = R15CCINTMODE
| (value
& R15PCBITS
);
91 /* This routine returns the value of register 15, mode independently. */
94 ARMul_GetR15 (ARMul_State
* state
)
96 if (state
->Mode
> SVC26MODE
)
97 return (state
->Reg
[15]);
99 return (R15PC
| ECC
| ER15INT
| EMODE
);
102 /* This routine sets the value of Register 15. */
105 ARMul_SetR15 (ARMul_State
* state
, ARMword value
)
108 state
->Reg
[15] = value
& PCBITS
;
111 state
->Reg
[15] = value
;
112 ARMul_R15Altered (state
);
117 /* This routine returns the value of the CPSR. */
120 ARMul_GetCPSR (ARMul_State
* state
)
122 return (CPSR
| state
->Cpsr
);
125 /* This routine sets the value of the CPSR. */
128 ARMul_SetCPSR (ARMul_State
* state
, ARMword value
)
131 ARMul_CPSRAltered (state
);
134 /* This routine does all the nasty bits involved in a write to the CPSR,
135 including updating the register bank, given a MSR instruction. */
138 ARMul_FixCPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
)
140 state
->Cpsr
= ARMul_GetCPSR (state
);
142 if (state
->Mode
!= USER26MODE
143 && state
->Mode
!= USER32MODE
)
145 /* In user mode, only write flags. */
147 SETPSR_C (state
->Cpsr
, rhs
);
149 SETPSR_X (state
->Cpsr
, rhs
);
151 SETPSR_S (state
->Cpsr
, rhs
);
154 SETPSR_F (state
->Cpsr
, rhs
);
155 ARMul_CPSRAltered (state
);
158 /* Get an SPSR from the specified mode. */
161 ARMul_GetSPSR (ARMul_State
* state
, ARMword mode
)
163 ARMword bank
= ModeToBank (mode
& MODEBITS
);
165 if (! BANK_CAN_ACCESS_SPSR (bank
))
166 return ARMul_GetCPSR (state
);
168 return state
->Spsr
[bank
];
171 /* This routine does a write to an SPSR. */
174 ARMul_SetSPSR (ARMul_State
* state
, ARMword mode
, ARMword value
)
176 ARMword bank
= ModeToBank (mode
& MODEBITS
);
178 if (BANK_CAN_ACCESS_SPSR (bank
))
179 state
->Spsr
[bank
] = value
;
182 /* This routine does a write to the current SPSR, given an MSR instruction. */
185 ARMul_FixSPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
)
187 if (BANK_CAN_ACCESS_SPSR (state
->Bank
))
190 SETPSR_C (state
->Spsr
[state
->Bank
], rhs
);
192 SETPSR_X (state
->Spsr
[state
->Bank
], rhs
);
194 SETPSR_S (state
->Spsr
[state
->Bank
], rhs
);
196 SETPSR_F (state
->Spsr
[state
->Bank
], rhs
);
200 /* This routine updates the state of the emulator after the Cpsr has been
201 changed. Both the processor flags and register bank are updated. */
204 ARMul_CPSRAltered (ARMul_State
* state
)
208 if (state
->prog32Sig
== LOW
)
209 state
->Cpsr
&= (CCBITS
| INTBITS
| R15MODEBITS
);
211 oldmode
= state
->Mode
;
213 if (state
->Mode
!= (state
->Cpsr
& MODEBITS
))
216 ARMul_SwitchMode (state
, state
->Mode
, state
->Cpsr
& MODEBITS
);
218 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
220 state
->Cpsr
&= ~MODEBITS
;
222 ASSIGNINT (state
->Cpsr
& INTBITS
);
223 state
->Cpsr
&= ~INTBITS
;
224 ASSIGNN ((state
->Cpsr
& NBIT
) != 0);
225 state
->Cpsr
&= ~NBIT
;
226 ASSIGNZ ((state
->Cpsr
& ZBIT
) != 0);
227 state
->Cpsr
&= ~ZBIT
;
228 ASSIGNC ((state
->Cpsr
& CBIT
) != 0);
229 state
->Cpsr
&= ~CBIT
;
230 ASSIGNV ((state
->Cpsr
& VBIT
) != 0);
231 state
->Cpsr
&= ~VBIT
;
232 ASSIGNS ((state
->Cpsr
& SBIT
) != 0);
233 state
->Cpsr
&= ~SBIT
;
235 ASSIGNT ((state
->Cpsr
& TBIT
) != 0);
236 state
->Cpsr
&= ~TBIT
;
239 if (oldmode
> SVC26MODE
)
241 if (state
->Mode
<= SVC26MODE
)
243 state
->Emulate
= CHANGEMODE
;
244 state
->Reg
[15] = ECC
| ER15INT
| EMODE
| R15PC
;
249 if (state
->Mode
> SVC26MODE
)
251 state
->Emulate
= CHANGEMODE
;
252 state
->Reg
[15] = R15PC
;
255 state
->Reg
[15] = ECC
| ER15INT
| EMODE
| R15PC
;
259 /* This routine updates the state of the emulator after register 15 has
260 been changed. Both the processor flags and register bank are updated.
261 This routine should only be called from a 26 bit mode. */
264 ARMul_R15Altered (ARMul_State
* state
)
266 if (state
->Mode
!= R15MODE
)
268 state
->Mode
= ARMul_SwitchMode (state
, state
->Mode
, R15MODE
);
269 state
->NtransSig
= (state
->Mode
& 3) ? HIGH
: LOW
;
272 if (state
->Mode
> SVC26MODE
)
273 state
->Emulate
= CHANGEMODE
;
275 ASSIGNR15INT (R15INT
);
277 ASSIGNN ((state
->Reg
[15] & NBIT
) != 0);
278 ASSIGNZ ((state
->Reg
[15] & ZBIT
) != 0);
279 ASSIGNC ((state
->Reg
[15] & CBIT
) != 0);
280 ASSIGNV ((state
->Reg
[15] & VBIT
) != 0);
283 /* This routine controls the saving and restoring of registers across mode
284 changes. The regbank matrix is largely unused, only rows 13 and 14 are
285 used across all modes, 8 to 14 are used for FIQ, all others use the USER
286 column. It's easier this way. old and new parameter are modes numbers.
287 Notice the side effect of changing the Bank variable. */
290 ARMul_SwitchMode (ARMul_State
* state
, ARMword oldmode
, ARMword newmode
)
296 oldbank
= ModeToBank (oldmode
);
297 newbank
= state
->Bank
= ModeToBank (newmode
);
299 /* Do we really need to do it? */
300 if (oldbank
!= newbank
)
302 /* Save away the old registers. */
310 if (newbank
== FIQBANK
)
311 for (i
= 8; i
< 13; i
++)
312 state
->RegBank
[USERBANK
][i
] = state
->Reg
[i
];
313 state
->RegBank
[oldbank
][13] = state
->Reg
[13];
314 state
->RegBank
[oldbank
][14] = state
->Reg
[14];
317 for (i
= 8; i
< 15; i
++)
318 state
->RegBank
[FIQBANK
][i
] = state
->Reg
[i
];
321 for (i
= 8; i
< 15; i
++)
322 state
->RegBank
[DUMMYBANK
][i
] = 0;
328 /* Restore the new registers. */
336 if (oldbank
== FIQBANK
)
337 for (i
= 8; i
< 13; i
++)
338 state
->Reg
[i
] = state
->RegBank
[USERBANK
][i
];
339 state
->Reg
[13] = state
->RegBank
[newbank
][13];
340 state
->Reg
[14] = state
->RegBank
[newbank
][14];
343 for (i
= 8; i
< 15; i
++)
344 state
->Reg
[i
] = state
->RegBank
[FIQBANK
][i
];
347 for (i
= 8; i
< 15; i
++)
358 /* Given a processor mode, this routine returns the
359 register bank that will be accessed in that mode. */
362 ModeToBank (ARMword mode
)
364 static ARMword bankofmode
[] =
366 USERBANK
, FIQBANK
, IRQBANK
, SVCBANK
,
367 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, DUMMYBANK
,
368 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, DUMMYBANK
,
369 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, DUMMYBANK
,
370 USERBANK
, FIQBANK
, IRQBANK
, SVCBANK
,
371 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, ABORTBANK
,
372 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, UNDEFBANK
,
373 DUMMYBANK
, DUMMYBANK
, DUMMYBANK
, SYSTEMBANK
376 if (mode
>= (sizeof (bankofmode
) / sizeof (bankofmode
[0])))
379 return bankofmode
[mode
];
382 /* Returns the register number of the nth register in a reg list. */
385 ARMul_NthReg (ARMword instr
, unsigned number
)
389 for (bit
= 0, upto
= 0; upto
<= number
; bit
++)
396 /* Assigns the N and Z flags depending on the value of result. */
399 ARMul_NegZero (ARMul_State
* state
, ARMword result
)
406 else if (result
== 0)
418 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
421 AddOverflow (ARMword a
, ARMword b
, ARMword result
)
423 return ((NEG (a
) && NEG (b
) && POS (result
))
424 || (POS (a
) && POS (b
) && NEG (result
)));
427 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
430 SubOverflow (ARMword a
, ARMword b
, ARMword result
)
432 return ((NEG (a
) && POS (b
) && POS (result
))
433 || (POS (a
) && NEG (b
) && NEG (result
)));
436 /* Assigns the C flag after an addition of a and b to give result. */
439 ARMul_AddCarry (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
441 ASSIGNC ((NEG (a
) && NEG (b
)) ||
442 (NEG (a
) && POS (result
)) || (NEG (b
) && POS (result
)));
445 /* Assigns the V flag after an addition of a and b to give result. */
448 ARMul_AddOverflow (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
450 ASSIGNV (AddOverflow (a
, b
, result
));
453 /* Assigns the C flag after an subtraction of a and b to give result. */
456 ARMul_SubCarry (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
458 ASSIGNC ((NEG (a
) && POS (b
)) ||
459 (NEG (a
) && POS (result
)) || (POS (b
) && POS (result
)));
462 /* Assigns the V flag after an subtraction of a and b to give result. */
465 ARMul_SubOverflow (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
467 ASSIGNV (SubOverflow (a
, b
, result
));
471 handle_VFP_xfer (ARMul_State
* state
, ARMword instr
)
473 if (TOPBITS (28) == NV
)
475 fprintf (stderr
, "SIM: UNDEFINED VFP instruction\n");
479 if (BITS (25, 27) != 0x6)
481 fprintf (stderr
, "SIM: ISE: VFP handler called incorrectly\n");
485 switch (BITS (20, 24))
490 /* VMOV double precision to/from two ARM registers. */
491 int vm
= BITS (0, 3);
492 int rt1
= BITS (12, 15);
493 int rt2
= BITS (16, 19);
495 /* FIXME: UNPREDICTABLE if rt1 == 15 or rt2 == 15. */
498 /* Transfer to ARM. */
499 /* FIXME: UPPREDICTABLE if rt1 == rt2. */
500 state
->Reg
[rt1
] = VFP_dword (vm
) & 0xffffffff;
501 state
->Reg
[rt2
] = VFP_dword (vm
) >> 32;
505 VFP_dword (vm
) = state
->Reg
[rt2
];
506 VFP_dword (vm
) <<= 32;
507 VFP_dword (vm
) |= (state
->Reg
[rt1
] & 0xffffffff);
517 /* VSTM with PUW=011 or PUW=010. */
518 int n
= BITS (16, 19);
519 int imm8
= BITS (0, 7);
521 ARMword address
= state
->Reg
[n
];
523 state
->Reg
[n
] = address
+ (imm8
<< 2);
527 int src
= (BIT (22) << 4) | BITS (12, 15);
531 if (state
->bigendSig
)
533 ARMul_StoreWordN (state
, address
, VFP_dword (src
) >> 32);
534 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
));
538 ARMul_StoreWordN (state
, address
, VFP_dword (src
));
539 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
) >> 32);
547 int src
= (BITS (12, 15) << 1) | BIT (22);
550 ARMul_StoreWordN (state
, address
, VFP_uword (src
));
564 ARMword imm32
= BITS (0, 7) << 2;
565 int base
= state
->Reg
[LHSReg
];
570 base
= (base
+ 3) & ~3;
572 address
= base
+ (BIT (23) ? imm32
: - imm32
);
576 dest
= (DESTReg
<< 1) + BIT (22);
578 ARMul_StoreWordN (state
, address
, VFP_uword (dest
));
582 dest
= (BIT (22) << 4) + DESTReg
;
584 if (state
->bigendSig
)
586 ARMul_StoreWordN (state
, address
, VFP_dword (dest
) >> 32);
587 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dest
));
591 ARMul_StoreWordN (state
, address
, VFP_dword (dest
));
592 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dest
) >> 32);
600 if (BITS (16, 19) == 13)
603 ARMword address
= state
->Reg
[13] - (BITS (0, 7) << 2);
604 state
->Reg
[13] = address
;
608 int dreg
= (BIT (22) << 4) | BITS (12, 15);
609 int num
= BITS (0, 7) >> 1;
612 if (state
->bigendSig
)
614 ARMul_StoreWordN (state
, address
, VFP_dword (dreg
) >> 32);
615 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dreg
));
619 ARMul_StoreWordN (state
, address
, VFP_dword (dreg
));
620 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dreg
) >> 32);
628 int sreg
= (BITS (12, 15) << 1) | BIT (22);
629 int num
= BITS (0, 7);
632 ARMul_StoreWordN (state
, address
, VFP_uword (sreg
));
638 else if (BITS (9, 11) != 0x5)
643 int n
= BITS (16, 19);
644 int imm8
= BITS (0, 7);
645 ARMword address
= state
->Reg
[n
] - (imm8
<< 2);
646 state
->Reg
[n
] = address
;
650 int src
= (BIT (22) << 4) | BITS (12, 15);
655 if (state
->bigendSig
)
657 ARMul_StoreWordN (state
, address
, VFP_dword (src
) >> 32);
658 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
));
662 ARMul_StoreWordN (state
, address
, VFP_dword (src
));
663 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
) >> 32);
671 int src
= (BITS (12, 15) << 1) | BIT (22);
675 ARMul_StoreWordN (state
, address
, VFP_uword (src
));
690 int n
= BITS (16, 19);
691 int imm8
= BITS (0, 7);
693 ARMword address
= state
->Reg
[n
];
695 address
-= imm8
<< 2;
697 state
->Reg
[n
] = BIT (23) ? address
+ (imm8
<< 2) : address
;
701 int dest
= (BIT (22) << 4) | BITS (12, 15);
705 if (state
->bigendSig
)
707 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
);
708 VFP_dword (dest
) <<= 32;
709 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
+ 4);
713 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
714 VFP_dword (dest
) <<= 32;
715 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
719 fprintf (stderr
, " VFP: VLDM: D%d = %g\n", dest
, VFP_dval (dest
));
727 int dest
= (BITS (12, 15) << 1) | BIT (22);
731 VFP_uword (dest
) = ARMul_LoadWordN (state
, address
);
741 if (BITS (16, 19) == 13)
744 ARMword address
= state
->Reg
[13];
745 state
->Reg
[13] = address
+ (BITS (0, 7) << 2);
749 int dest
= (BIT (22) << 4) | BITS (12, 15);
750 int num
= BITS (0, 7) >> 1;
754 if (state
->bigendSig
)
756 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
);
757 VFP_dword (dest
) <<= 32;
758 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
+ 4);
762 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
763 VFP_dword (dest
) <<= 32;
764 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
768 fprintf (stderr
, " VFP: VPOP: D%d = %g\n", dest
, VFP_dval (dest
));
776 int sreg
= (BITS (12, 15) << 1) | BIT (22);
777 int num
= BITS (0, 7);
781 VFP_uword (sreg
) = ARMul_LoadWordN (state
, address
);
787 else if (BITS (9, 11) != 0x5)
792 int n
= BITS (16, 19);
793 int imm8
= BITS (0, 7);
794 ARMword address
= state
->Reg
[n
];
795 state
->Reg
[n
] += imm8
<< 2;
799 int dest
= (BIT (22) << 4) | BITS (12, 15);
804 if (state
->bigendSig
)
806 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
);
807 VFP_dword (dest
) <<= 32;
808 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
+ 4);
812 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
813 VFP_dword (dest
) <<= 32;
814 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
818 fprintf (stderr
, " VFP: VLDM: D%d = %g\n", dest
, VFP_dval (dest
));
826 int dest
= (BITS (12, 15) << 1) | BIT (22);
829 VFP_uword (dest
) = ARMul_LoadWordN (state
, address
);
843 ARMword imm32
= BITS (0, 7) << 2;
844 int base
= state
->Reg
[LHSReg
];
849 base
= (base
+ 3) & ~3;
851 address
= base
+ (BIT (23) ? imm32
: - imm32
);
855 dest
= (DESTReg
<< 1) + BIT (22);
857 VFP_uword (dest
) = ARMul_LoadWordN (state
, address
);
861 dest
= (BIT (22) << 4) + DESTReg
;
863 if (state
->bigendSig
)
865 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
);
866 VFP_dword (dest
) <<= 32;
867 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
+ 4);
871 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
872 VFP_dword (dest
) <<= 32;
873 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
877 fprintf (stderr
, " VFP: VLDR: D%d = %g\n", dest
, VFP_dval (dest
));
883 fprintf (stderr
, "SIM: VFP: Unimplemented: %0x\n", BITS (20, 24));
886 /* This function does the work of generating the addresses used in an
887 LDC instruction. The code here is always post-indexed, it's up to the
888 caller to get the input address correct and to handle base register
889 modification. It also handles the Busy-Waiting. */
892 ARMul_LDC (ARMul_State
* state
, ARMword instr
, ARMword address
)
897 if (CPNum
== 10 || CPNum
== 11)
899 handle_VFP_xfer (state
, instr
);
905 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
907 ARMul_UndefInstr (state
, instr
);
911 if (ADDREXCEPT (address
))
912 INTERNALABORT (address
);
914 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_FIRST
, instr
, 0);
915 while (cpab
== ARMul_BUSY
)
917 ARMul_Icycles (state
, 1, 0);
919 if (IntPending (state
))
921 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
925 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_BUSY
, instr
, 0);
927 if (cpab
== ARMul_CANT
)
933 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_TRANSFER
, instr
, 0);
934 data
= ARMul_LoadWordN (state
, address
);
938 LSBase
= state
->Base
;
939 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
941 while (cpab
== ARMul_INC
)
944 data
= ARMul_LoadWordN (state
, address
);
945 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
948 if (state
->abortSig
|| state
->Aborted
)
952 /* This function does the work of generating the addresses used in an
953 STC instruction. The code here is always post-indexed, it's up to the
954 caller to get the input address correct and to handle base register
955 modification. It also handles the Busy-Waiting. */
958 ARMul_STC (ARMul_State
* state
, ARMword instr
, ARMword address
)
963 if (CPNum
== 10 || CPNum
== 11)
965 handle_VFP_xfer (state
, instr
);
971 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
973 ARMul_UndefInstr (state
, instr
);
977 if (ADDREXCEPT (address
) || VECTORACCESS (address
))
978 INTERNALABORT (address
);
980 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_FIRST
, instr
, &data
);
981 while (cpab
== ARMul_BUSY
)
983 ARMul_Icycles (state
, 1, 0);
984 if (IntPending (state
))
986 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
990 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_BUSY
, instr
, &data
);
993 if (cpab
== ARMul_CANT
)
999 if (ADDREXCEPT (address
) || VECTORACCESS (address
))
1000 INTERNALABORT (address
);
1004 LSBase
= state
->Base
;
1005 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_DATA
, instr
, &data
);
1006 ARMul_StoreWordN (state
, address
, data
);
1008 while (cpab
== ARMul_INC
)
1011 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_DATA
, instr
, &data
);
1012 ARMul_StoreWordN (state
, address
, data
);
1015 if (state
->abortSig
|| state
->Aborted
)
1019 /* This function does the Busy-Waiting for an MCR instruction. */
1022 ARMul_MCR (ARMul_State
* state
, ARMword instr
, ARMword source
)
1026 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
1028 ARMul_UndefInstr (state
, instr
);
1032 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_FIRST
, instr
, source
);
1034 while (cpab
== ARMul_BUSY
)
1036 ARMul_Icycles (state
, 1, 0);
1038 if (IntPending (state
))
1040 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
1044 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_BUSY
, instr
, source
);
1047 if (cpab
== ARMul_CANT
)
1048 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1052 ARMul_Ccycles (state
, 1, 0);
1056 /* This function does the Busy-Waiting for an MRC instruction. */
1059 ARMul_MRC (ARMul_State
* state
, ARMword instr
)
1064 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
1066 ARMul_UndefInstr (state
, instr
);
1070 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_FIRST
, instr
, &result
);
1071 while (cpab
== ARMul_BUSY
)
1073 ARMul_Icycles (state
, 1, 0);
1074 if (IntPending (state
))
1076 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
, 0);
1080 cpab
= (state
->MRC
[CPNum
]) (state
, ARMul_BUSY
, instr
, &result
);
1082 if (cpab
== ARMul_CANT
)
1084 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1085 /* Parent will destroy the flags otherwise. */
1091 ARMul_Ccycles (state
, 1, 0);
1092 ARMul_Icycles (state
, 1, 0);
1099 handle_VFP_op (ARMul_State
* state
, ARMword instr
)
1105 if (BITS (9, 11) != 0x5 || BIT (4) != 0)
1107 fprintf (stderr
, "SIM: VFP: Unimplemented: Float op: %08x\n", BITS (0,31));
1113 dest
= BITS(12,15) + (BIT (22) << 4);
1114 srcN
= LHSReg
+ (BIT (7) << 4);
1115 srcM
= BITS (0,3) + (BIT (5) << 4);
1119 dest
= (BITS(12,15) << 1) + BIT (22);
1120 srcN
= (LHSReg
<< 1) + BIT (7);
1121 srcM
= (BITS (0,3) << 1) + BIT (5);
1124 switch (BITS (20, 27))
1131 ARMdval val
= VFP_dval (srcN
) * VFP_dval (srcM
);
1136 fprintf (stderr
, " VFP: VMLS: %g = %g - %g * %g\n",
1137 VFP_dval (dest
) - val
,
1138 VFP_dval (dest
), VFP_dval (srcN
), VFP_dval (srcM
));
1139 VFP_dval (dest
) -= val
;
1144 fprintf (stderr
, " VFP: VMLA: %g = %g + %g * %g\n",
1145 VFP_dval (dest
) + val
,
1146 VFP_dval (dest
), VFP_dval (srcN
), VFP_dval (srcM
));
1147 VFP_dval (dest
) += val
;
1152 ARMfval val
= VFP_fval (srcN
) * VFP_fval (srcM
);
1157 fprintf (stderr
, " VFP: VMLS: %g = %g - %g * %g\n",
1158 VFP_fval (dest
) - val
,
1159 VFP_fval (dest
), VFP_fval (srcN
), VFP_fval (srcM
));
1160 VFP_fval (dest
) -= val
;
1165 fprintf (stderr
, " VFP: VMLA: %g = %g + %g * %g\n",
1166 VFP_fval (dest
) + val
,
1167 VFP_fval (dest
), VFP_fval (srcN
), VFP_fval (srcM
));
1168 VFP_fval (dest
) += val
;
1177 ARMdval product
= VFP_dval (srcN
) * VFP_dval (srcM
);
1183 fprintf (stderr
, " VFP: VNMLA: %g = -(%g + (%g * %g))\n",
1184 -(VFP_dval (dest
) + product
),
1185 VFP_dval (dest
), VFP_dval (srcN
), VFP_dval (srcM
));
1186 VFP_dval (dest
) = -(product
+ VFP_dval (dest
));
1192 fprintf (stderr
, " VFP: VNMLS: %g = -(%g + (%g * %g))\n",
1193 -(VFP_dval (dest
) + product
),
1194 VFP_dval (dest
), VFP_dval (srcN
), VFP_dval (srcM
));
1195 VFP_dval (dest
) = product
- VFP_dval (dest
);
1200 ARMfval product
= VFP_fval (srcN
) * VFP_fval (srcM
);
1204 VFP_fval (dest
) = -(product
+ VFP_fval (dest
));
1207 VFP_fval (dest
) = product
- VFP_fval (dest
);
1215 ARMdval product
= VFP_dval (srcN
) * VFP_dval (srcM
);
1220 fprintf (stderr
, " VFP: VMUL: %g = %g * %g\n",
1221 - product
, VFP_dval (srcN
), VFP_dval (srcM
));
1223 VFP_dval (dest
) = - product
;
1228 fprintf (stderr
, " VFP: VMUL: %g = %g * %g\n",
1229 product
, VFP_dval (srcN
), VFP_dval (srcM
));
1231 VFP_dval (dest
) = product
;
1236 ARMfval product
= VFP_fval (srcN
) * VFP_fval (srcM
);
1241 fprintf (stderr
, " VFP: VNMUL: %g = %g * %g\n",
1242 - product
, VFP_fval (srcN
), VFP_fval (srcM
));
1244 VFP_fval (dest
) = - product
;
1249 fprintf (stderr
, " VFP: VMUL: %g = %g * %g\n",
1250 product
, VFP_fval (srcN
), VFP_fval (srcM
));
1252 VFP_fval (dest
) = product
;
1265 fprintf (stderr
, " VFP: VADD %g = %g + %g\n",
1266 VFP_dval (srcN
) + VFP_dval (srcM
),
1269 VFP_dval (dest
) = VFP_dval (srcN
) + VFP_dval (srcM
);
1272 VFP_fval (dest
) = VFP_fval (srcN
) + VFP_fval (srcM
);
1281 fprintf (stderr
, " VFP: VSUB %g = %g - %g\n",
1282 VFP_dval (srcN
) - VFP_dval (srcM
),
1285 VFP_dval (dest
) = VFP_dval (srcN
) - VFP_dval (srcM
);
1288 VFP_fval (dest
) = VFP_fval (srcN
) - VFP_fval (srcM
);
1300 ARMdval res
= VFP_dval (srcN
) / VFP_dval (srcM
);
1302 fprintf (stderr
, " VFP: VDIV (64bit): %g = %g / %g\n",
1303 res
, VFP_dval (srcN
), VFP_dval (srcM
));
1304 VFP_dval (dest
) = res
;
1309 fprintf (stderr
, " VFP: VDIV: %g = %g / %g\n",
1310 VFP_fval (srcN
) / VFP_fval (srcM
),
1311 VFP_fval (srcN
), VFP_fval (srcM
));
1313 VFP_fval (dest
) = VFP_fval (srcN
) / VFP_fval (srcM
);
1322 switch (BITS (16, 19))
1329 /* VMOV.F64 <Dd>, <Dm>. */
1330 VFP_dval (dest
) = VFP_dval (srcM
);
1332 fprintf (stderr
, " VFP: VMOV d%d, d%d: %g\n", dest
, srcM
, VFP_dval (srcM
));
1336 /* VMOV.F32 <Sd>, <Sm>. */
1337 VFP_fval (dest
) = VFP_fval (srcM
);
1339 fprintf (stderr
, " VFP: VMOV s%d, s%d: %g\n", dest
, srcM
, VFP_fval (srcM
));
1347 ARMdval src
= VFP_dval (srcM
);
1349 VFP_dval (dest
) = fabs (src
);
1351 fprintf (stderr
, " VFP: VABS (%g) = %g\n", src
, VFP_dval (dest
));
1355 ARMfval src
= VFP_fval (srcM
);
1357 VFP_fval (dest
) = fabsf (src
);
1359 fprintf (stderr
, " VFP: VABS (%g) = %g\n", src
, VFP_fval (dest
));
1369 VFP_dval (dest
) = - VFP_dval (srcM
);
1371 VFP_fval (dest
) = - VFP_fval (srcM
);
1379 fprintf (stderr
, " VFP: %g = root(%g)\n",
1380 sqrt (VFP_dval (srcM
)), VFP_dval (srcM
));
1382 VFP_dval (dest
) = sqrt (VFP_dval (srcM
));
1387 fprintf (stderr
, " VFP: %g = root(%g)\n",
1388 sqrtf (VFP_fval (srcM
)), VFP_fval (srcM
));
1390 VFP_fval (dest
) = sqrtf (VFP_fval (srcM
));
1400 ARMdval res
= VFP_dval (dest
);
1404 ARMdval src
= VFP_dval (srcM
);
1406 if (isinf (res
) && isinf (src
))
1408 if (res
> 0.0 && src
> 0.0)
1410 else if (res
< 0.0 && src
< 0.0)
1412 /* else leave res alone. */
1418 /* FIXME: Add handling of signalling NaNs and the E bit. */
1420 state
->FPSCR
&= 0x0FFFFFFF;
1422 state
->FPSCR
|= NBIT
;
1424 state
->FPSCR
|= CBIT
;
1426 state
->FPSCR
|= ZBIT
;
1428 state
->FPSCR
|= VBIT
;
1431 fprintf (stderr
, " VFP: VCMP (64bit) %g vs %g res %g, flags: %c%c%c%c\n",
1432 VFP_dval (dest
), BIT (16) ? 0.0 : VFP_dval (srcM
), res
,
1433 state
->FPSCR
& NBIT
? 'N' : '-',
1434 state
->FPSCR
& ZBIT
? 'Z' : '-',
1435 state
->FPSCR
& CBIT
? 'C' : '-',
1436 state
->FPSCR
& VBIT
? 'V' : '-');
1440 ARMfval res
= VFP_fval (dest
);
1444 ARMfval src
= VFP_fval (srcM
);
1446 if (isinf (res
) && isinf (src
))
1448 if (res
> 0.0 && src
> 0.0)
1450 else if (res
< 0.0 && src
< 0.0)
1452 /* else leave res alone. */
1458 /* FIXME: Add handling of signalling NaNs and the E bit. */
1460 state
->FPSCR
&= 0x0FFFFFFF;
1462 state
->FPSCR
|= NBIT
;
1464 state
->FPSCR
|= CBIT
;
1466 state
->FPSCR
|= ZBIT
;
1468 state
->FPSCR
|= VBIT
;
1471 fprintf (stderr
, " VFP: VCMP (32bit) %g vs %g res %g, flags: %c%c%c%c\n",
1472 VFP_fval (dest
), BIT (16) ? 0.0 : VFP_fval (srcM
), res
,
1473 state
->FPSCR
& NBIT
? 'N' : '-',
1474 state
->FPSCR
& ZBIT
? 'Z' : '-',
1475 state
->FPSCR
& CBIT
? 'C' : '-',
1476 state
->FPSCR
& VBIT
? 'V' : '-');
1483 dest
= (DESTReg
<< 1) + BIT (22);
1484 VFP_fval (dest
) = VFP_dval (srcM
);
1488 dest
= DESTReg
+ (BIT (22) << 4);
1489 VFP_dval (dest
) = VFP_fval (srcM
);
1496 /* VCVT integer <-> FP */
1502 dest
= (BITS(12,15) << 1) + BIT (22);
1504 VFP_sword (dest
) = VFP_dval (srcM
);
1506 VFP_uword (dest
) = VFP_dval (srcM
);
1511 VFP_sword (dest
) = VFP_fval (srcM
);
1513 VFP_uword (dest
) = VFP_fval (srcM
);
1521 srcM
= (BITS (0,3) << 1) + BIT (5);
1523 VFP_dval (dest
) = VFP_sword (srcM
);
1525 VFP_dval (dest
) = VFP_uword (srcM
);
1530 VFP_fval (dest
) = VFP_sword (srcM
);
1532 VFP_fval (dest
) = VFP_uword (srcM
);
1538 fprintf (stderr
, "SIM: VFP: Unimplemented: Float op3: %03x\n", BITS (16,27));
1542 fprintf (stderr
, "SIM: VFP: Unimplemented: Float op2: %02x\n", BITS (20, 27));
1546 /* This function does the Busy-Waiting for an CDP instruction. */
1549 ARMul_CDP (ARMul_State
* state
, ARMword instr
)
1553 if (CPNum
== 10 || CPNum
== 11)
1555 handle_VFP_op (state
, instr
);
1559 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
1561 ARMul_UndefInstr (state
, instr
);
1565 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_FIRST
, instr
);
1566 while (cpab
== ARMul_BUSY
)
1568 ARMul_Icycles (state
, 1, 0);
1569 if (IntPending (state
))
1571 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_INTERRUPT
, instr
);
1575 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_BUSY
, instr
);
1577 if (cpab
== ARMul_CANT
)
1578 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1583 /* This function handles Undefined instructions, as CP isntruction. */
1586 ARMul_UndefInstr (ARMul_State
* state
, ARMword instr ATTRIBUTE_UNUSED
)
1588 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1591 /* Return TRUE if an interrupt is pending, FALSE otherwise. */
1594 IntPending (ARMul_State
* state
)
1596 if (state
->Exception
)
1598 /* Any exceptions. */
1599 if (state
->NresetSig
== LOW
)
1601 ARMul_Abort (state
, ARMul_ResetV
);
1604 else if (!state
->NfiqSig
&& !FFLAG
)
1606 ARMul_Abort (state
, ARMul_FIQV
);
1609 else if (!state
->NirqSig
&& !IFLAG
)
1611 ARMul_Abort (state
, ARMul_IRQV
);
1619 /* Align a word access to a non word boundary. */
1622 ARMul_Align (ARMul_State
*state ATTRIBUTE_UNUSED
, ARMword address
, ARMword data
)
1624 /* This code assumes the address is really unaligned,
1625 as a shift by 32 is undefined in C. */
1627 address
= (address
& 3) << 3; /* Get the word address. */
1628 return ((data
>> address
) | (data
<< (32 - address
))); /* rot right */
1631 /* This routine is used to call another routine after a certain number of
1632 cycles have been executed. The first parameter is the number of cycles
1633 delay before the function is called, the second argument is a pointer
1634 to the function. A delay of zero doesn't work, just call the function. */
1637 ARMul_ScheduleEvent (ARMul_State
* state
, unsigned long delay
,
1638 unsigned (*what
) (ARMul_State
*))
1641 struct EventNode
*event
;
1643 if (state
->EventSet
++ == 0)
1644 state
->Now
= ARMul_Time (state
);
1645 when
= (state
->Now
+ delay
) % EVENTLISTSIZE
;
1646 event
= (struct EventNode
*) malloc (sizeof (struct EventNode
));
1648 event
->next
= *(state
->EventPtr
+ when
);
1649 *(state
->EventPtr
+ when
) = event
;
1652 /* This routine is called at the beginning of
1653 every cycle, to envoke scheduled events. */
1656 ARMul_EnvokeEvent (ARMul_State
* state
)
1658 static unsigned long then
;
1661 state
->Now
= ARMul_Time (state
) % EVENTLISTSIZE
;
1662 if (then
< state
->Now
)
1663 /* Schedule events. */
1664 EnvokeList (state
, then
, state
->Now
);
1665 else if (then
> state
->Now
)
1667 /* Need to wrap around the list. */
1668 EnvokeList (state
, then
, EVENTLISTSIZE
- 1L);
1669 EnvokeList (state
, 0L, state
->Now
);
1673 /* Envokes all the entries in a range. */
1676 EnvokeList (ARMul_State
* state
, unsigned long from
, unsigned long to
)
1678 for (; from
<= to
; from
++)
1680 struct EventNode
*anevent
;
1682 anevent
= *(state
->EventPtr
+ from
);
1685 (anevent
->func
) (state
);
1687 anevent
= anevent
->next
;
1689 *(state
->EventPtr
+ from
) = NULL
;
1693 /* This routine is returns the number of clock ticks since the last reset. */
1696 ARMul_Time (ARMul_State
* state
)
1698 return (state
->NumScycles
+ state
->NumNcycles
+
1699 state
->NumIcycles
+ state
->NumCcycles
+ state
->NumFcycles
);