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/>. */
21 /* Definitions for the support routines. */
23 static ARMword ModeToBank (ARMword);
24 static void EnvokeList (ARMul_State *, unsigned long, unsigned long);
27 { /* An event list node. */
28 unsigned (*func) (ARMul_State *); /* The function to call. */
29 struct EventNode *next;
32 /* This routine returns the value of a register from a mode. */
35 ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
38 if (mode != state->Mode)
39 return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
41 return (state->Reg[reg]);
44 /* This routine sets the value of a register for a mode. */
47 ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
50 if (mode != state->Mode)
51 state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
53 state->Reg[reg] = value;
56 /* This routine returns the value of the PC, mode independently. */
59 ARMul_GetPC (ARMul_State * state)
61 if (state->Mode > SVC26MODE)
62 return state->Reg[15];
67 /* This routine returns the value of the PC, mode independently. */
70 ARMul_GetNextPC (ARMul_State * state)
72 if (state->Mode > SVC26MODE)
73 return state->Reg[15] + isize;
75 return (state->Reg[15] + isize) & R15PCBITS;
78 /* This routine sets the value of the PC. */
81 ARMul_SetPC (ARMul_State * state, ARMword value)
84 state->Reg[15] = value & PCBITS;
86 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
90 /* This routine returns the value of register 15, mode independently. */
93 ARMul_GetR15 (ARMul_State * state)
95 if (state->Mode > SVC26MODE)
96 return (state->Reg[15]);
98 return (R15PC | ECC | ER15INT | EMODE);
101 /* This routine sets the value of Register 15. */
104 ARMul_SetR15 (ARMul_State * state, ARMword value)
107 state->Reg[15] = value & PCBITS;
110 state->Reg[15] = value;
111 ARMul_R15Altered (state);
116 /* This routine returns the value of the CPSR. */
119 ARMul_GetCPSR (ARMul_State * state)
121 return (CPSR | state->Cpsr);
124 /* This routine sets the value of the CPSR. */
127 ARMul_SetCPSR (ARMul_State * state, ARMword value)
130 ARMul_CPSRAltered (state);
133 /* This routine does all the nasty bits involved in a write to the CPSR,
134 including updating the register bank, given a MSR instruction. */
137 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
139 state->Cpsr = ARMul_GetCPSR (state);
141 if (state->Mode != USER26MODE
142 && state->Mode != USER32MODE)
144 /* In user mode, only write flags. */
146 SETPSR_C (state->Cpsr, rhs);
148 SETPSR_X (state->Cpsr, rhs);
150 SETPSR_S (state->Cpsr, rhs);
153 SETPSR_F (state->Cpsr, rhs);
154 ARMul_CPSRAltered (state);
157 /* Get an SPSR from the specified mode. */
160 ARMul_GetSPSR (ARMul_State * state, ARMword mode)
162 ARMword bank = ModeToBank (mode & MODEBITS);
164 if (! BANK_CAN_ACCESS_SPSR (bank))
165 return ARMul_GetCPSR (state);
167 return state->Spsr[bank];
170 /* This routine does a write to an SPSR. */
173 ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
175 ARMword bank = ModeToBank (mode & MODEBITS);
177 if (BANK_CAN_ACCESS_SPSR (bank))
178 state->Spsr[bank] = value;
181 /* This routine does a write to the current SPSR, given an MSR instruction. */
184 ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
186 if (BANK_CAN_ACCESS_SPSR (state->Bank))
189 SETPSR_C (state->Spsr[state->Bank], rhs);
191 SETPSR_X (state->Spsr[state->Bank], rhs);
193 SETPSR_S (state->Spsr[state->Bank], rhs);
195 SETPSR_F (state->Spsr[state->Bank], rhs);
199 /* This routine updates the state of the emulator after the Cpsr has been
200 changed. Both the processor flags and register bank are updated. */
203 ARMul_CPSRAltered (ARMul_State * state)
207 if (state->prog32Sig == LOW)
208 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
210 oldmode = state->Mode;
212 if (state->Mode != (state->Cpsr & MODEBITS))
215 ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
217 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
219 state->Cpsr &= ~MODEBITS;
221 ASSIGNINT (state->Cpsr & INTBITS);
222 state->Cpsr &= ~INTBITS;
223 ASSIGNN ((state->Cpsr & NBIT) != 0);
224 state->Cpsr &= ~NBIT;
225 ASSIGNZ ((state->Cpsr & ZBIT) != 0);
226 state->Cpsr &= ~ZBIT;
227 ASSIGNC ((state->Cpsr & CBIT) != 0);
228 state->Cpsr &= ~CBIT;
229 ASSIGNV ((state->Cpsr & VBIT) != 0);
230 state->Cpsr &= ~VBIT;
231 ASSIGNS ((state->Cpsr & SBIT) != 0);
232 state->Cpsr &= ~SBIT;
234 ASSIGNT ((state->Cpsr & TBIT) != 0);
235 state->Cpsr &= ~TBIT;
238 if (oldmode > SVC26MODE)
240 if (state->Mode <= SVC26MODE)
242 state->Emulate = CHANGEMODE;
243 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
248 if (state->Mode > SVC26MODE)
250 state->Emulate = CHANGEMODE;
251 state->Reg[15] = R15PC;
254 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
258 /* This routine updates the state of the emulator after register 15 has
259 been changed. Both the processor flags and register bank are updated.
260 This routine should only be called from a 26 bit mode. */
263 ARMul_R15Altered (ARMul_State * state)
265 if (state->Mode != R15MODE)
267 state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
268 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
271 if (state->Mode > SVC26MODE)
272 state->Emulate = CHANGEMODE;
274 ASSIGNR15INT (R15INT);
276 ASSIGNN ((state->Reg[15] & NBIT) != 0);
277 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
278 ASSIGNC ((state->Reg[15] & CBIT) != 0);
279 ASSIGNV ((state->Reg[15] & VBIT) != 0);
282 /* This routine controls the saving and restoring of registers across mode
283 changes. The regbank matrix is largely unused, only rows 13 and 14 are
284 used across all modes, 8 to 14 are used for FIQ, all others use the USER
285 column. It's easier this way. old and new parameter are modes numbers.
286 Notice the side effect of changing the Bank variable. */
289 ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
295 oldbank = ModeToBank (oldmode);
296 newbank = state->Bank = ModeToBank (newmode);
298 /* Do we really need to do it? */
299 if (oldbank != newbank)
301 /* Save away the old registers. */
309 if (newbank == FIQBANK)
310 for (i = 8; i < 13; i++)
311 state->RegBank[USERBANK][i] = state->Reg[i];
312 state->RegBank[oldbank][13] = state->Reg[13];
313 state->RegBank[oldbank][14] = state->Reg[14];
316 for (i = 8; i < 15; i++)
317 state->RegBank[FIQBANK][i] = state->Reg[i];
320 for (i = 8; i < 15; i++)
321 state->RegBank[DUMMYBANK][i] = 0;
327 /* Restore the new registers. */
335 if (oldbank == FIQBANK)
336 for (i = 8; i < 13; i++)
337 state->Reg[i] = state->RegBank[USERBANK][i];
338 state->Reg[13] = state->RegBank[newbank][13];
339 state->Reg[14] = state->RegBank[newbank][14];
342 for (i = 8; i < 15; i++)
343 state->Reg[i] = state->RegBank[FIQBANK][i];
346 for (i = 8; i < 15; i++)
357 /* Given a processor mode, this routine returns the
358 register bank that will be accessed in that mode. */
361 ModeToBank (ARMword mode)
363 static ARMword bankofmode[] =
365 USERBANK, FIQBANK, IRQBANK, SVCBANK,
366 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
367 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
368 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
369 USERBANK, FIQBANK, IRQBANK, SVCBANK,
370 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
371 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
372 DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
375 if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0])))
378 return bankofmode[mode];
381 /* Returns the register number of the nth register in a reg list. */
384 ARMul_NthReg (ARMword instr, unsigned number)
388 for (bit = 0, upto = 0; upto <= number; bit ++)
395 /* Assigns the N and Z flags depending on the value of result. */
398 ARMul_NegZero (ARMul_State * state, ARMword result)
405 else if (result == 0)
417 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
420 AddOverflow (ARMword a, ARMword b, ARMword result)
422 return ((NEG (a) && NEG (b) && POS (result))
423 || (POS (a) && POS (b) && NEG (result)));
426 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
429 SubOverflow (ARMword a, ARMword b, ARMword result)
431 return ((NEG (a) && POS (b) && POS (result))
432 || (POS (a) && NEG (b) && NEG (result)));
435 /* Assigns the C flag after an addition of a and b to give result. */
438 ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
440 ASSIGNC ((NEG (a) && NEG (b)) ||
441 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
444 /* Assigns the V flag after an addition of a and b to give result. */
447 ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
449 ASSIGNV (AddOverflow (a, b, result));
452 /* Assigns the C flag after an subtraction of a and b to give result. */
455 ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
457 ASSIGNC ((NEG (a) && POS (b)) ||
458 (NEG (a) && POS (result)) || (POS (b) && POS (result)));
461 /* Assigns the V flag after an subtraction of a and b to give result. */
464 ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
466 ASSIGNV (SubOverflow (a, b, result));
469 /* This function does the work of generating the addresses used in an
470 LDC instruction. The code here is always post-indexed, it's up to the
471 caller to get the input address correct and to handle base register
472 modification. It also handles the Busy-Waiting. */
475 ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
482 if (! CP_ACCESS_ALLOWED (state, CPNum))
484 ARMul_UndefInstr (state, instr);
488 if (ADDREXCEPT (address))
489 INTERNALABORT (address);
491 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
492 while (cpab == ARMul_BUSY)
494 ARMul_Icycles (state, 1, 0);
496 if (IntPending (state))
498 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
502 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
504 if (cpab == ARMul_CANT)
510 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
511 data = ARMul_LoadWordN (state, address);
515 LSBase = state->Base;
516 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
518 while (cpab == ARMul_INC)
521 data = ARMul_LoadWordN (state, address);
522 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
525 if (state->abortSig || state->Aborted)
529 /* This function does the work of generating the addresses used in an
530 STC instruction. The code here is always post-indexed, it's up to the
531 caller to get the input address correct and to handle base register
532 modification. It also handles the Busy-Waiting. */
535 ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
542 if (! CP_ACCESS_ALLOWED (state, CPNum))
544 ARMul_UndefInstr (state, instr);
548 if (ADDREXCEPT (address) || VECTORACCESS (address))
549 INTERNALABORT (address);
551 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
552 while (cpab == ARMul_BUSY)
554 ARMul_Icycles (state, 1, 0);
555 if (IntPending (state))
557 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
561 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
564 if (cpab == ARMul_CANT)
570 if (ADDREXCEPT (address) || VECTORACCESS (address))
571 INTERNALABORT (address);
575 LSBase = state->Base;
576 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
577 ARMul_StoreWordN (state, address, data);
579 while (cpab == ARMul_INC)
582 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
583 ARMul_StoreWordN (state, address, data);
586 if (state->abortSig || state->Aborted)
590 /* This function does the Busy-Waiting for an MCR instruction. */
593 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
597 if (! CP_ACCESS_ALLOWED (state, CPNum))
599 ARMul_UndefInstr (state, instr);
603 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
605 while (cpab == ARMul_BUSY)
607 ARMul_Icycles (state, 1, 0);
609 if (IntPending (state))
611 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
615 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
618 if (cpab == ARMul_CANT)
619 ARMul_Abort (state, ARMul_UndefinedInstrV);
623 ARMul_Ccycles (state, 1, 0);
627 /* This function does the Busy-Waiting for an MRC instruction. */
630 ARMul_MRC (ARMul_State * state, ARMword instr)
635 if (! CP_ACCESS_ALLOWED (state, CPNum))
637 ARMul_UndefInstr (state, instr);
641 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
642 while (cpab == ARMul_BUSY)
644 ARMul_Icycles (state, 1, 0);
645 if (IntPending (state))
647 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
651 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
653 if (cpab == ARMul_CANT)
655 ARMul_Abort (state, ARMul_UndefinedInstrV);
656 /* Parent will destroy the flags otherwise. */
662 ARMul_Ccycles (state, 1, 0);
663 ARMul_Icycles (state, 1, 0);
669 /* This function does the Busy-Waiting for an CDP instruction. */
672 ARMul_CDP (ARMul_State * state, ARMword instr)
676 if (! CP_ACCESS_ALLOWED (state, CPNum))
678 ARMul_UndefInstr (state, instr);
682 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
683 while (cpab == ARMul_BUSY)
685 ARMul_Icycles (state, 1, 0);
686 if (IntPending (state))
688 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
692 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
694 if (cpab == ARMul_CANT)
695 ARMul_Abort (state, ARMul_UndefinedInstrV);
700 /* This function handles Undefined instructions, as CP isntruction. */
703 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
705 ARMul_Abort (state, ARMul_UndefinedInstrV);
708 /* Return TRUE if an interrupt is pending, FALSE otherwise. */
711 IntPending (ARMul_State * state)
713 if (state->Exception)
715 /* Any exceptions. */
716 if (state->NresetSig == LOW)
718 ARMul_Abort (state, ARMul_ResetV);
721 else if (!state->NfiqSig && !FFLAG)
723 ARMul_Abort (state, ARMul_FIQV);
726 else if (!state->NirqSig && !IFLAG)
728 ARMul_Abort (state, ARMul_IRQV);
736 /* Align a word access to a non word boundary. */
739 ARMul_Align (state, address, data)
740 ARMul_State * state ATTRIBUTE_UNUSED;
744 /* This code assumes the address is really unaligned,
745 as a shift by 32 is undefined in C. */
747 address = (address & 3) << 3; /* Get the word address. */
748 return ((data >> address) | (data << (32 - address))); /* rot right */
751 /* This routine is used to call another routine after a certain number of
752 cycles have been executed. The first parameter is the number of cycles
753 delay before the function is called, the second argument is a pointer
754 to the function. A delay of zero doesn't work, just call the function. */
757 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
758 unsigned (*what) (ARMul_State *))
761 struct EventNode *event;
763 if (state->EventSet++ == 0)
764 state->Now = ARMul_Time (state);
765 when = (state->Now + delay) % EVENTLISTSIZE;
766 event = (struct EventNode *) malloc (sizeof (struct EventNode));
768 event->next = *(state->EventPtr + when);
769 *(state->EventPtr + when) = event;
772 /* This routine is called at the beginning of
773 every cycle, to envoke scheduled events. */
776 ARMul_EnvokeEvent (ARMul_State * state)
778 static unsigned long then;
781 state->Now = ARMul_Time (state) % EVENTLISTSIZE;
782 if (then < state->Now)
783 /* Schedule events. */
784 EnvokeList (state, then, state->Now);
785 else if (then > state->Now)
787 /* Need to wrap around the list. */
788 EnvokeList (state, then, EVENTLISTSIZE - 1L);
789 EnvokeList (state, 0L, state->Now);
793 /* Envokes all the entries in a range. */
796 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
798 for (; from <= to; from++)
800 struct EventNode *anevent;
802 anevent = *(state->EventPtr + from);
805 (anevent->func) (state);
807 anevent = anevent->next;
809 *(state->EventPtr + from) = NULL;
813 /* This routine is returns the number of clock ticks since the last reset. */
816 ARMul_Time (ARMul_State * state)
818 return (state->NumScycles + state->NumNcycles +
819 state->NumIcycles + state->NumCcycles + state->NumFcycles);