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 2 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, write to the Free Software
16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
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));
470 /* This function does the work of generating the addresses used in an
471 LDC instruction. The code here is always post-indexed, it's up to the
472 caller to get the input address correct and to handle base register
473 modification. It also handles the Busy-Waiting. */
476 ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
483 if (! CP_ACCESS_ALLOWED (state, CPNum))
485 ARMul_UndefInstr (state, instr);
489 if (ADDREXCEPT (address))
490 INTERNALABORT (address);
492 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
493 while (cpab == ARMul_BUSY)
495 ARMul_Icycles (state, 1, 0);
497 if (IntPending (state))
499 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
503 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
505 if (cpab == ARMul_CANT)
511 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
512 data = ARMul_LoadWordN (state, address);
516 LSBase = state->Base;
517 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
519 while (cpab == ARMul_INC)
522 data = ARMul_LoadWordN (state, address);
523 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
526 if (state->abortSig || state->Aborted)
530 /* This function does the work of generating the addresses used in an
531 STC instruction. The code here is always post-indexed, it's up to the
532 caller to get the input address correct and to handle base register
533 modification. It also handles the Busy-Waiting. */
536 ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
543 if (! CP_ACCESS_ALLOWED (state, CPNum))
545 ARMul_UndefInstr (state, instr);
549 if (ADDREXCEPT (address) || VECTORACCESS (address))
550 INTERNALABORT (address);
552 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
553 while (cpab == ARMul_BUSY)
555 ARMul_Icycles (state, 1, 0);
556 if (IntPending (state))
558 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
562 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
565 if (cpab == ARMul_CANT)
571 if (ADDREXCEPT (address) || VECTORACCESS (address))
572 INTERNALABORT (address);
576 LSBase = state->Base;
577 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
578 ARMul_StoreWordN (state, address, data);
580 while (cpab == ARMul_INC)
583 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
584 ARMul_StoreWordN (state, address, data);
587 if (state->abortSig || state->Aborted)
591 /* This function does the Busy-Waiting for an MCR instruction. */
594 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
598 if (! CP_ACCESS_ALLOWED (state, CPNum))
600 ARMul_UndefInstr (state, instr);
604 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
606 while (cpab == ARMul_BUSY)
608 ARMul_Icycles (state, 1, 0);
610 if (IntPending (state))
612 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
616 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
619 if (cpab == ARMul_CANT)
620 ARMul_Abort (state, ARMul_UndefinedInstrV);
624 ARMul_Ccycles (state, 1, 0);
628 /* This function does the Busy-Waiting for an MRC instruction. */
631 ARMul_MRC (ARMul_State * state, ARMword instr)
636 if (! CP_ACCESS_ALLOWED (state, CPNum))
638 ARMul_UndefInstr (state, instr);
642 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
643 while (cpab == ARMul_BUSY)
645 ARMul_Icycles (state, 1, 0);
646 if (IntPending (state))
648 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
652 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
654 if (cpab == ARMul_CANT)
656 ARMul_Abort (state, ARMul_UndefinedInstrV);
657 /* Parent will destroy the flags otherwise. */
663 ARMul_Ccycles (state, 1, 0);
664 ARMul_Icycles (state, 1, 0);
670 /* This function does the Busy-Waiting for an CDP instruction. */
673 ARMul_CDP (ARMul_State * state, ARMword instr)
677 if (! CP_ACCESS_ALLOWED (state, CPNum))
679 ARMul_UndefInstr (state, instr);
683 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
684 while (cpab == ARMul_BUSY)
686 ARMul_Icycles (state, 1, 0);
687 if (IntPending (state))
689 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
693 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
695 if (cpab == ARMul_CANT)
696 ARMul_Abort (state, ARMul_UndefinedInstrV);
701 /* This function handles Undefined instructions, as CP isntruction. */
704 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
706 ARMul_Abort (state, ARMul_UndefinedInstrV);
709 /* Return TRUE if an interrupt is pending, FALSE otherwise. */
712 IntPending (ARMul_State * state)
714 if (state->Exception)
716 /* Any exceptions. */
717 if (state->NresetSig == LOW)
719 ARMul_Abort (state, ARMul_ResetV);
722 else if (!state->NfiqSig && !FFLAG)
724 ARMul_Abort (state, ARMul_FIQV);
727 else if (!state->NirqSig && !IFLAG)
729 ARMul_Abort (state, ARMul_IRQV);
737 /* Align a word access to a non word boundary. */
740 ARMul_Align (state, address, data)
741 ARMul_State * state ATTRIBUTE_UNUSED;
745 /* This code assumes the address is really unaligned,
746 as a shift by 32 is undefined in C. */
748 address = (address & 3) << 3; /* Get the word address. */
749 return ((data >> address) | (data << (32 - address))); /* rot right */
752 /* This routine is used to call another routine after a certain number of
753 cycles have been executed. The first parameter is the number of cycles
754 delay before the function is called, the second argument is a pointer
755 to the function. A delay of zero doesn't work, just call the function. */
758 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
759 unsigned (*what) (ARMul_State *))
762 struct EventNode *event;
764 if (state->EventSet++ == 0)
765 state->Now = ARMul_Time (state);
766 when = (state->Now + delay) % EVENTLISTSIZE;
767 event = (struct EventNode *) malloc (sizeof (struct EventNode));
769 event->next = *(state->EventPtr + when);
770 *(state->EventPtr + when) = event;
773 /* This routine is called at the beginning of
774 every cycle, to envoke scheduled events. */
777 ARMul_EnvokeEvent (ARMul_State * state)
779 static unsigned long then;
782 state->Now = ARMul_Time (state) % EVENTLISTSIZE;
783 if (then < state->Now)
784 /* Schedule events. */
785 EnvokeList (state, then, state->Now);
786 else if (then > state->Now)
788 /* Need to wrap around the list. */
789 EnvokeList (state, then, EVENTLISTSIZE - 1L);
790 EnvokeList (state, 0L, state->Now);
794 /* Envokes all the entries in a range. */
797 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
799 for (; from <= to; from++)
801 struct EventNode *anevent;
803 anevent = *(state->EventPtr + from);
806 (anevent->func) (state);
808 anevent = anevent->next;
810 *(state->EventPtr + from) = NULL;
814 /* This routine is returns the number of clock ticks since the last reset. */
817 ARMul_Time (ARMul_State * state)
819 return (state->NumScycles + state->NumNcycles +
820 state->NumIcycles + state->NumCcycles + state->NumFcycles);