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. */
23 #include "libiberty.h"
26 /* Definitions for the support routines. */
28 static ARMword
ModeToBank (ARMword
);
29 static void EnvokeList (ARMul_State
*, unsigned long, unsigned long);
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. */
40 ARMul_GetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
)
43 if (mode
!= state
->Mode
)
44 return (state
->RegBank
[ModeToBank ((ARMword
) mode
)][reg
]);
46 return (state
->Reg
[reg
]);
49 /* This routine sets the value of a register for a mode. */
52 ARMul_SetReg (ARMul_State
* state
, unsigned mode
, unsigned reg
, ARMword value
)
55 if (mode
!= state
->Mode
)
56 state
->RegBank
[ModeToBank ((ARMword
) mode
)][reg
] = value
;
58 state
->Reg
[reg
] = value
;
61 /* This routine returns the value of the PC, mode independently. */
64 ARMul_GetPC (ARMul_State
* state
)
66 if (state
->Mode
> SVC26MODE
)
67 return state
->Reg
[15];
72 /* This routine returns the value of the PC, mode independently. */
75 ARMul_GetNextPC (ARMul_State
* state
)
77 if (state
->Mode
> SVC26MODE
)
78 return state
->Reg
[15] + isize
;
80 return (state
->Reg
[15] + isize
) & R15PCBITS
;
83 /* This routine sets the value of the PC. */
86 ARMul_SetPC (ARMul_State
* state
, ARMword value
)
89 state
->Reg
[15] = value
& PCBITS
;
91 state
->Reg
[15] = R15CCINTMODE
| (value
& R15PCBITS
);
95 /* This routine returns the value of register 15, mode independently. */
98 ARMul_GetR15 (ARMul_State
* state
)
100 if (state
->Mode
> SVC26MODE
)
101 return (state
->Reg
[15]);
103 return (R15PC
| ECC
| ER15INT
| EMODE
);
106 /* This routine sets the value of Register 15. */
109 ARMul_SetR15 (ARMul_State
* state
, ARMword value
)
112 state
->Reg
[15] = value
& PCBITS
;
115 state
->Reg
[15] = value
;
116 ARMul_R15Altered (state
);
121 /* This routine returns the value of the CPSR. */
124 ARMul_GetCPSR (ARMul_State
* state
)
126 return (CPSR
| state
->Cpsr
);
129 /* This routine sets the value of the CPSR. */
132 ARMul_SetCPSR (ARMul_State
* state
, ARMword 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. */
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. */
151 SETPSR_C (state
->Cpsr
, rhs
);
153 SETPSR_X (state
->Cpsr
, rhs
);
155 SETPSR_S (state
->Cpsr
, rhs
);
158 SETPSR_F (state
->Cpsr
, rhs
);
159 ARMul_CPSRAltered (state
);
162 /* Get an SPSR from the specified mode. */
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. */
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. */
189 ARMul_FixSPSR (ARMul_State
* state
, ARMword instr
, ARMword rhs
)
191 if (BANK_CAN_ACCESS_SPSR (state
->Bank
))
194 SETPSR_C (state
->Spsr
[state
->Bank
], rhs
);
196 SETPSR_X (state
->Spsr
[state
->Bank
], rhs
);
198 SETPSR_S (state
->Spsr
[state
->Bank
], rhs
);
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. */
208 ARMul_CPSRAltered (ARMul_State
* state
)
212 if (state
->prog32Sig
== LOW
)
213 state
->Cpsr
&= (CCBITS
| INTBITS
| R15MODEBITS
);
215 oldmode
= state
->Mode
;
217 if (state
->Mode
!= (state
->Cpsr
& MODEBITS
))
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
;
239 ASSIGNT ((state
->Cpsr
& TBIT
) != 0);
240 state
->Cpsr
&= ~TBIT
;
243 if (oldmode
> SVC26MODE
)
245 if (state
->Mode
<= SVC26MODE
)
247 state
->Emulate
= CHANGEMODE
;
248 state
->Reg
[15] = ECC
| ER15INT
| EMODE
| R15PC
;
253 if (state
->Mode
> SVC26MODE
)
255 state
->Emulate
= CHANGEMODE
;
256 state
->Reg
[15] = R15PC
;
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. */
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. */
294 ARMul_SwitchMode (ARMul_State
* state
, ARMword oldmode
, ARMword newmode
)
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. */
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];
321 for (i
= 8; i
< 15; i
++)
322 state
->RegBank
[FIQBANK
][i
] = state
->Reg
[i
];
325 for (i
= 8; i
< 15; i
++)
326 state
->RegBank
[DUMMYBANK
][i
] = 0;
332 /* Restore the new registers. */
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];
347 for (i
= 8; i
< 15; i
++)
348 state
->Reg
[i
] = state
->RegBank
[FIQBANK
][i
];
351 for (i
= 8; i
< 15; i
++)
362 /* Given a processor mode, this routine returns the
363 register bank that will be accessed in that mode. */
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
))
383 return bankofmode
[mode
];
386 /* Returns the register number of the nth register in a reg list. */
389 ARMul_NthReg (ARMword instr
, unsigned number
)
393 for (bit
= 0, up_to
= 0; up_to
<= number
; bit
++)
400 /* Assigns the N and Z flags depending on the value of result. */
403 ARMul_NegZero (ARMul_State
* state
, ARMword result
)
410 else if (result
== 0)
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. */
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. */
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. */
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. */
469 ARMul_SubOverflow (ARMul_State
* state
, ARMword a
, ARMword b
, ARMword result
)
471 ASSIGNV (SubOverflow (a
, b
, result
));
475 handle_VFP_xfer (ARMul_State
* state
, ARMword instr
)
477 if (TOPBITS (28) == NV
)
479 fprintf (stderr
, "SIM: UNDEFINED VFP instruction\n");
483 if (BITS (25, 27) != 0x6)
485 fprintf (stderr
, "SIM: ISE: VFP handler called incorrectly\n");
489 switch (BITS (20, 24))
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. */
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;
509 VFP_dword (vm
) = state
->Reg
[rt2
];
510 VFP_dword (vm
) <<= 32;
511 VFP_dword (vm
) |= (state
->Reg
[rt1
] & 0xffffffff);
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
];
527 state
->Reg
[n
] = address
+ (imm8
<< 2);
531 int src
= (BIT (22) << 4) | BITS (12, 15);
535 if (state
->bigendSig
)
537 ARMul_StoreWordN (state
, address
, VFP_dword (src
) >> 32);
538 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
));
542 ARMul_StoreWordN (state
, address
, VFP_dword (src
));
543 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
) >> 32);
551 int src
= (BITS (12, 15) << 1) | BIT (22);
554 ARMul_StoreWordN (state
, address
, VFP_uword (src
));
568 ARMword imm32
= BITS (0, 7) << 2;
569 int base
= state
->Reg
[LHSReg
];
574 base
= (base
+ 3) & ~3;
576 address
= base
+ (BIT (23) ? imm32
: - imm32
);
580 dest
= (DESTReg
<< 1) + BIT (22);
582 ARMul_StoreWordN (state
, address
, VFP_uword (dest
));
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
));
595 ARMul_StoreWordN (state
, address
, VFP_dword (dest
));
596 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dest
) >> 32);
604 if (BITS (16, 19) == 13)
607 ARMword address
= state
->Reg
[13] - (BITS (0, 7) << 2);
608 state
->Reg
[13] = address
;
612 int dreg
= (BIT (22) << 4) | BITS (12, 15);
613 int num
= BITS (0, 7) >> 1;
616 if (state
->bigendSig
)
618 ARMul_StoreWordN (state
, address
, VFP_dword (dreg
) >> 32);
619 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dreg
));
623 ARMul_StoreWordN (state
, address
, VFP_dword (dreg
));
624 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (dreg
) >> 32);
632 int sreg
= (BITS (12, 15) << 1) | BIT (22);
633 int num
= BITS (0, 7);
636 ARMul_StoreWordN (state
, address
, VFP_uword (sreg
));
642 else if (BITS (9, 11) != 0x5)
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
;
654 int src
= (BIT (22) << 4) | BITS (12, 15);
659 if (state
->bigendSig
)
661 ARMul_StoreWordN (state
, address
, VFP_dword (src
) >> 32);
662 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
));
666 ARMul_StoreWordN (state
, address
, VFP_dword (src
));
667 ARMul_StoreWordN (state
, address
+ 4, VFP_dword (src
) >> 32);
675 int src
= (BITS (12, 15) << 1) | BIT (22);
679 ARMul_StoreWordN (state
, address
, VFP_uword (src
));
694 int n
= BITS (16, 19);
695 int imm8
= BITS (0, 7);
697 ARMword address
= state
->Reg
[n
];
699 address
-= imm8
<< 2;
701 state
->Reg
[n
] = BIT (23) ? address
+ (imm8
<< 2) : address
;
705 int dest
= (BIT (22) << 4) | BITS (12, 15);
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);
717 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
718 VFP_dword (dest
) <<= 32;
719 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
723 fprintf (stderr
, " VFP: VLDM: D%d = %g\n", dest
, VFP_dval (dest
));
731 int dest
= (BITS (12, 15) << 1) | BIT (22);
735 VFP_uword (dest
) = ARMul_LoadWordN (state
, address
);
745 if (BITS (16, 19) == 13)
748 ARMword address
= state
->Reg
[13];
749 state
->Reg
[13] = address
+ (BITS (0, 7) << 2);
753 int dest
= (BIT (22) << 4) | BITS (12, 15);
754 int num
= BITS (0, 7) >> 1;
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);
766 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
767 VFP_dword (dest
) <<= 32;
768 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
772 fprintf (stderr
, " VFP: VPOP: D%d = %g\n", dest
, VFP_dval (dest
));
780 int sreg
= (BITS (12, 15) << 1) | BIT (22);
781 int num
= BITS (0, 7);
785 VFP_uword (sreg
) = ARMul_LoadWordN (state
, address
);
791 else if (BITS (9, 11) != 0x5)
796 int n
= BITS (16, 19);
797 int imm8
= BITS (0, 7);
798 ARMword address
= state
->Reg
[n
];
799 state
->Reg
[n
] += imm8
<< 2;
803 int dest
= (BIT (22) << 4) | BITS (12, 15);
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);
816 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
817 VFP_dword (dest
) <<= 32;
818 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
822 fprintf (stderr
, " VFP: VLDM: D%d = %g\n", dest
, VFP_dval (dest
));
830 int dest
= (BITS (12, 15) << 1) | BIT (22);
833 VFP_uword (dest
) = ARMul_LoadWordN (state
, address
);
847 ARMword imm32
= BITS (0, 7) << 2;
848 int base
= state
->Reg
[LHSReg
];
853 base
= (base
+ 3) & ~3;
855 address
= base
+ (BIT (23) ? imm32
: - imm32
);
859 dest
= (DESTReg
<< 1) + BIT (22);
861 VFP_uword (dest
) = ARMul_LoadWordN (state
, address
);
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);
875 VFP_dword (dest
) = ARMul_LoadWordN (state
, address
+ 4);
876 VFP_dword (dest
) <<= 32;
877 VFP_dword (dest
) |= ARMul_LoadWordN (state
, address
);
881 fprintf (stderr
, " VFP: VLDR: D%d = %g\n", dest
, VFP_dval (dest
));
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. */
896 ARMul_LDC (ARMul_State
* state
, ARMword instr
, ARMword address
)
901 if (CPNum
== 10 || CPNum
== 11)
903 handle_VFP_xfer (state
, instr
);
909 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
911 ARMul_UndefInstr (state
, instr
);
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);
929 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_BUSY
, instr
, 0);
931 if (cpab
== ARMul_CANT
)
937 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_TRANSFER
, instr
, 0);
938 data
= ARMul_LoadWordN (state
, address
);
942 LSBase
= state
->Base
;
943 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
945 while (cpab
== ARMul_INC
)
948 data
= ARMul_LoadWordN (state
, address
);
949 cpab
= (state
->LDC
[CPNum
]) (state
, ARMul_DATA
, instr
, data
);
952 if (state
->abortSig
|| state
->Aborted
)
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. */
962 ARMul_STC (ARMul_State
* state
, ARMword instr
, ARMword address
)
967 if (CPNum
== 10 || CPNum
== 11)
969 handle_VFP_xfer (state
, instr
);
975 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
977 ARMul_UndefInstr (state
, instr
);
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);
994 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_BUSY
, instr
, &data
);
997 if (cpab
== ARMul_CANT
)
1003 if (ADDREXCEPT (address
) || VECTORACCESS (address
))
1004 INTERNALABORT (address
);
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
)
1015 cpab
= (state
->STC
[CPNum
]) (state
, ARMul_DATA
, instr
, &data
);
1016 ARMul_StoreWordN (state
, address
, data
);
1019 if (state
->abortSig
|| state
->Aborted
)
1023 /* This function does the Busy-Waiting for an MCR instruction. */
1026 ARMul_MCR (ARMul_State
* state
, ARMword instr
, ARMword source
)
1030 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
1032 ARMul_UndefInstr (state
, instr
);
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);
1048 cpab
= (state
->MCR
[CPNum
]) (state
, ARMul_BUSY
, instr
, source
);
1051 if (cpab
== ARMul_CANT
)
1052 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1056 ARMul_Ccycles (state
, 1, 0);
1060 /* This function does the Busy-Waiting for an MRC instruction. */
1063 ARMul_MRC (ARMul_State
* state
, ARMword instr
)
1068 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
1070 ARMul_UndefInstr (state
, instr
);
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);
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. */
1095 ARMul_Ccycles (state
, 1, 0);
1096 ARMul_Icycles (state
, 1, 0);
1103 handle_VFP_op (ARMul_State
* state
, ARMword instr
)
1109 if (BITS (9, 11) != 0x5 || BIT (4) != 0)
1111 fprintf (stderr
, "SIM: VFP: Unimplemented: Float op: %08x\n", BITS (0,31));
1117 dest
= BITS(12,15) + (BIT (22) << 4);
1118 srcN
= LHSReg
+ (BIT (7) << 4);
1119 srcM
= BITS (0,3) + (BIT (5) << 4);
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))
1135 ARMdval val
= VFP_dval (srcN
) * VFP_dval (srcM
);
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
;
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
;
1156 ARMfval val
= VFP_fval (srcN
) * VFP_fval (srcM
);
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
;
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
;
1181 ARMdval product
= VFP_dval (srcN
) * VFP_dval (srcM
);
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
));
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
);
1204 ARMfval product
= VFP_fval (srcN
) * VFP_fval (srcM
);
1208 VFP_fval (dest
) = -(product
+ VFP_fval (dest
));
1211 VFP_fval (dest
) = product
- VFP_fval (dest
);
1219 ARMdval product
= VFP_dval (srcN
) * VFP_dval (srcM
);
1224 fprintf (stderr
, " VFP: VMUL: %g = %g * %g\n",
1225 - product
, VFP_dval (srcN
), VFP_dval (srcM
));
1227 VFP_dval (dest
) = - product
;
1232 fprintf (stderr
, " VFP: VMUL: %g = %g * %g\n",
1233 product
, VFP_dval (srcN
), VFP_dval (srcM
));
1235 VFP_dval (dest
) = product
;
1240 ARMfval product
= VFP_fval (srcN
) * VFP_fval (srcM
);
1245 fprintf (stderr
, " VFP: VNMUL: %g = %g * %g\n",
1246 - product
, VFP_fval (srcN
), VFP_fval (srcM
));
1248 VFP_fval (dest
) = - product
;
1253 fprintf (stderr
, " VFP: VMUL: %g = %g * %g\n",
1254 product
, VFP_fval (srcN
), VFP_fval (srcM
));
1256 VFP_fval (dest
) = product
;
1269 fprintf (stderr
, " VFP: VADD %g = %g + %g\n",
1270 VFP_dval (srcN
) + VFP_dval (srcM
),
1273 VFP_dval (dest
) = VFP_dval (srcN
) + VFP_dval (srcM
);
1276 VFP_fval (dest
) = VFP_fval (srcN
) + VFP_fval (srcM
);
1285 fprintf (stderr
, " VFP: VSUB %g = %g - %g\n",
1286 VFP_dval (srcN
) - VFP_dval (srcM
),
1289 VFP_dval (dest
) = VFP_dval (srcN
) - VFP_dval (srcM
);
1292 VFP_fval (dest
) = VFP_fval (srcN
) - VFP_fval (srcM
);
1304 ARMdval res
= VFP_dval (srcN
) / VFP_dval (srcM
);
1306 fprintf (stderr
, " VFP: VDIV (64bit): %g = %g / %g\n",
1307 res
, VFP_dval (srcN
), VFP_dval (srcM
));
1308 VFP_dval (dest
) = res
;
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
);
1326 switch (BITS (16, 19))
1333 /* VMOV.F64 <Dd>, <Dm>. */
1334 VFP_dval (dest
) = VFP_dval (srcM
);
1336 fprintf (stderr
, " VFP: VMOV d%d, d%d: %g\n", dest
, srcM
, VFP_dval (srcM
));
1340 /* VMOV.F32 <Sd>, <Sm>. */
1341 VFP_fval (dest
) = VFP_fval (srcM
);
1343 fprintf (stderr
, " VFP: VMOV s%d, s%d: %g\n", dest
, srcM
, VFP_fval (srcM
));
1351 ARMdval src
= VFP_dval (srcM
);
1353 VFP_dval (dest
) = fabs (src
);
1355 fprintf (stderr
, " VFP: VABS (%g) = %g\n", src
, VFP_dval (dest
));
1359 ARMfval src
= VFP_fval (srcM
);
1361 VFP_fval (dest
) = fabsf (src
);
1363 fprintf (stderr
, " VFP: VABS (%g) = %g\n", src
, VFP_fval (dest
));
1373 VFP_dval (dest
) = - VFP_dval (srcM
);
1375 VFP_fval (dest
) = - VFP_fval (srcM
);
1383 fprintf (stderr
, " VFP: %g = root(%g)\n",
1384 sqrt (VFP_dval (srcM
)), VFP_dval (srcM
));
1386 VFP_dval (dest
) = sqrt (VFP_dval (srcM
));
1391 fprintf (stderr
, " VFP: %g = root(%g)\n",
1392 sqrtf (VFP_fval (srcM
)), VFP_fval (srcM
));
1394 VFP_fval (dest
) = sqrtf (VFP_fval (srcM
));
1404 ARMdval res
= VFP_dval (dest
);
1408 ARMdval src
= VFP_dval (srcM
);
1410 if (isinf (res
) && isinf (src
))
1412 if (res
> 0.0 && src
> 0.0)
1414 else if (res
< 0.0 && src
< 0.0)
1416 /* else leave res alone. */
1422 /* FIXME: Add handling of signalling NaNs and the E bit. */
1424 state
->FPSCR
&= 0x0FFFFFFF;
1426 state
->FPSCR
|= NBIT
;
1428 state
->FPSCR
|= CBIT
;
1430 state
->FPSCR
|= ZBIT
;
1432 state
->FPSCR
|= VBIT
;
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' : '-');
1444 ARMfval res
= VFP_fval (dest
);
1448 ARMfval src
= VFP_fval (srcM
);
1450 if (isinf (res
) && isinf (src
))
1452 if (res
> 0.0 && src
> 0.0)
1454 else if (res
< 0.0 && src
< 0.0)
1456 /* else leave res alone. */
1462 /* FIXME: Add handling of signalling NaNs and the E bit. */
1464 state
->FPSCR
&= 0x0FFFFFFF;
1466 state
->FPSCR
|= NBIT
;
1468 state
->FPSCR
|= CBIT
;
1470 state
->FPSCR
|= ZBIT
;
1472 state
->FPSCR
|= VBIT
;
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' : '-');
1487 dest
= (DESTReg
<< 1) + BIT (22);
1488 VFP_fval (dest
) = VFP_dval (srcM
);
1492 dest
= DESTReg
+ (BIT (22) << 4);
1493 VFP_dval (dest
) = VFP_fval (srcM
);
1500 /* VCVT integer <-> FP */
1506 dest
= (BITS(12,15) << 1) + BIT (22);
1508 VFP_sword (dest
) = VFP_dval (srcM
);
1510 VFP_uword (dest
) = VFP_dval (srcM
);
1515 VFP_sword (dest
) = VFP_fval (srcM
);
1517 VFP_uword (dest
) = VFP_fval (srcM
);
1525 srcM
= (BITS (0,3) << 1) + BIT (5);
1527 VFP_dval (dest
) = VFP_sword (srcM
);
1529 VFP_dval (dest
) = VFP_uword (srcM
);
1534 VFP_fval (dest
) = VFP_sword (srcM
);
1536 VFP_fval (dest
) = VFP_uword (srcM
);
1542 fprintf (stderr
, "SIM: VFP: Unimplemented: Float op3: %03x\n", BITS (16,27));
1546 fprintf (stderr
, "SIM: VFP: Unimplemented: Float op2: %02x\n", BITS (20, 27));
1550 /* This function does the Busy-Waiting for an CDP instruction. */
1553 ARMul_CDP (ARMul_State
* state
, ARMword instr
)
1557 if (CPNum
== 10 || CPNum
== 11)
1559 handle_VFP_op (state
, instr
);
1563 if (! CP_ACCESS_ALLOWED (state
, CPNum
))
1565 ARMul_UndefInstr (state
, instr
);
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
);
1579 cpab
= (state
->CDP
[CPNum
]) (state
, ARMul_BUSY
, instr
);
1581 if (cpab
== ARMul_CANT
)
1582 ARMul_Abort (state
, ARMul_UndefinedInstrV
);
1587 /* This function handles Undefined instructions, as CP isntruction. */
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. */
1598 IntPending (ARMul_State
* state
)
1600 if (state
->Exception
)
1602 /* Any exceptions. */
1603 if (state
->NresetSig
== LOW
)
1605 ARMul_Abort (state
, ARMul_ResetV
);
1608 else if (!state
->NfiqSig
&& !FFLAG
)
1610 ARMul_Abort (state
, ARMul_FIQV
);
1613 else if (!state
->NirqSig
&& !IFLAG
)
1615 ARMul_Abort (state
, ARMul_IRQV
);
1623 /* Align a word access to a non word boundary. */
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. */
1641 ARMul_ScheduleEvent (ARMul_State
* state
, unsigned long delay
,
1642 unsigned (*what
) (ARMul_State
*))
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
));
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. */
1660 ARMul_EnvokeEvent (ARMul_State
* state
)
1662 static unsigned long then
;
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. */
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
);
1689 (anevent
->func
) (state
);
1691 anevent
= anevent
->next
;
1693 *(state
->EventPtr
+ from
) = NULL
;
1697 /* This routine is returns the number of clock ticks since the last reset. */
1700 ARMul_Time (ARMul_State
* state
)
1702 return (state
->NumScycles
+ state
->NumNcycles
+
1703 state
->NumIcycles
+ state
->NumCcycles
+ state
->NumFcycles
);