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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 /***************************************************************************\
23 * Definitions for the support routines *
24 \***************************************************************************/
26 ARMword ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg);
27 void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg,
29 ARMword ARMul_GetPC (ARMul_State * state);
30 ARMword ARMul_GetNextPC (ARMul_State * state);
31 void ARMul_SetPC (ARMul_State * state, ARMword value);
32 ARMword ARMul_GetR15 (ARMul_State * state);
33 void ARMul_SetR15 (ARMul_State * state, ARMword value);
35 ARMword ARMul_GetCPSR (ARMul_State * state);
36 void ARMul_SetCPSR (ARMul_State * state, ARMword value);
37 ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode);
38 void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value);
40 void ARMul_CPSRAltered (ARMul_State * state);
41 void ARMul_R15Altered (ARMul_State * state);
43 ARMword ARMul_SwitchMode (ARMul_State * state, ARMword oldmode,
45 static ARMword ModeToBank (ARMword mode);
47 unsigned ARMul_NthReg (ARMword instr, unsigned number);
49 void ARMul_NegZero (ARMul_State * state, ARMword result);
50 void ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b,
52 void ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b,
54 void ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b,
56 void ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b,
59 void ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address);
60 void ARMul_STC (ARMul_State * state, ARMword instr, ARMword address);
61 void ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source);
62 ARMword ARMul_MRC (ARMul_State * state, ARMword instr);
63 void ARMul_CDP (ARMul_State * state, ARMword instr);
64 unsigned IntPending (ARMul_State * state);
66 ARMword ARMul_Align (ARMul_State * state, ARMword address, ARMword data);
68 void ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
70 void ARMul_EnvokeEvent (ARMul_State * state);
71 unsigned long ARMul_Time (ARMul_State * state);
72 static void EnvokeList (ARMul_State * state, unsigned long from,
76 { /* An event list node */
77 unsigned (*func) (); /* The function to call */
78 struct EventNode *next;
81 /***************************************************************************\
82 * This routine returns the value of a register from a mode. *
83 \***************************************************************************/
86 ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg)
89 if (mode != state->Mode)
90 return (state->RegBank[ModeToBank ((ARMword) mode)][reg]);
92 return (state->Reg[reg]);
95 /***************************************************************************\
96 * This routine sets the value of a register for a mode. *
97 \***************************************************************************/
100 ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value)
103 if (mode != state->Mode)
104 state->RegBank[ModeToBank ((ARMword) mode)][reg] = value;
106 state->Reg[reg] = value;
109 /***************************************************************************\
110 * This routine returns the value of the PC, mode independently. *
111 \***************************************************************************/
114 ARMul_GetPC (ARMul_State * state)
116 if (state->Mode > SVC26MODE)
117 return (state->Reg[15]);
122 /***************************************************************************\
123 * This routine returns the value of the PC, mode independently. *
124 \***************************************************************************/
127 ARMul_GetNextPC (ARMul_State * state)
129 if (state->Mode > SVC26MODE)
130 return (state->Reg[15] + isize);
132 return ((state->Reg[15] + isize) & R15PCBITS);
135 /***************************************************************************\
136 * This routine sets the value of the PC. *
137 \***************************************************************************/
140 ARMul_SetPC (ARMul_State * state, ARMword value)
143 state->Reg[15] = value & PCBITS;
145 state->Reg[15] = R15CCINTMODE | (value & R15PCBITS);
149 /***************************************************************************\
150 * This routine returns the value of register 15, mode independently. *
151 \***************************************************************************/
154 ARMul_GetR15 (ARMul_State * state)
156 if (state->Mode > SVC26MODE)
157 return (state->Reg[15]);
159 return (R15PC | ECC | ER15INT | EMODE);
162 /***************************************************************************\
163 * This routine sets the value of Register 15. *
164 \***************************************************************************/
167 ARMul_SetR15 (ARMul_State * state, ARMword value)
170 state->Reg[15] = value & PCBITS;
173 state->Reg[15] = value;
174 ARMul_R15Altered (state);
179 /***************************************************************************\
180 * This routine returns the value of the CPSR *
181 \***************************************************************************/
184 ARMul_GetCPSR (ARMul_State * state)
186 return (CPSR | state->Cpsr);
189 /***************************************************************************\
190 * This routine sets the value of the CPSR *
191 \***************************************************************************/
194 ARMul_SetCPSR (ARMul_State * state, ARMword value)
197 ARMul_CPSRAltered (state);
200 /***************************************************************************\
201 * This routine does all the nasty bits involved in a write to the CPSR, *
202 * including updating the register bank, given a MSR instruction. *
203 \***************************************************************************/
206 ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs)
208 state->Cpsr = ARMul_GetCPSR (state);
209 if (state->Bank != USERBANK)
210 { /* In user mode, only write flags */
212 SETPSR_C (state->Cpsr, rhs);
214 SETPSR_X (state->Cpsr, rhs);
216 SETPSR_S (state->Cpsr, rhs);
219 SETPSR_F (state->Cpsr, rhs);
220 ARMul_CPSRAltered (state);
223 /***************************************************************************\
224 * Get an SPSR from the specified mode *
225 \***************************************************************************/
228 ARMul_GetSPSR (ARMul_State * state, ARMword mode)
230 ARMword bank = ModeToBank (mode & MODEBITS);
232 if (! BANK_CAN_ACCESS_SPSR (bank))
233 return ARMul_GetCPSR (state);
235 return state->Spsr[bank];
238 /***************************************************************************\
239 * This routine does a write to an SPSR *
240 \***************************************************************************/
243 ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value)
245 ARMword bank = ModeToBank (mode & MODEBITS);
247 if (BANK_CAN_ACCESS_SPSR (bank))
248 state->Spsr[bank] = value;
251 /***************************************************************************\
252 * This routine does a write to the current SPSR, given an MSR instruction *
253 \***************************************************************************/
256 ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs)
258 if (BANK_CAN_ACCESS_SPSR (state->Bank))
261 SETPSR_C (state->Spsr[state->Bank], rhs);
263 SETPSR_X (state->Spsr[state->Bank], rhs);
265 SETPSR_S (state->Spsr[state->Bank], rhs);
267 SETPSR_F (state->Spsr[state->Bank], rhs);
271 /***************************************************************************\
272 * This routine updates the state of the emulator after the Cpsr has been *
273 * changed. Both the processor flags and register bank are updated. *
274 \***************************************************************************/
277 ARMul_CPSRAltered (ARMul_State * state)
281 if (state->prog32Sig == LOW)
282 state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS);
284 oldmode = state->Mode;
286 if (state->Mode != (state->Cpsr & MODEBITS))
289 ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS);
291 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
293 state->Cpsr &= ~MODEBITS;
295 ASSIGNINT (state->Cpsr & INTBITS);
296 state->Cpsr &= ~INTBITS;
297 ASSIGNN ((state->Cpsr & NBIT) != 0);
298 state->Cpsr &= ~NBIT;
299 ASSIGNZ ((state->Cpsr & ZBIT) != 0);
300 state->Cpsr &= ~ZBIT;
301 ASSIGNC ((state->Cpsr & CBIT) != 0);
302 state->Cpsr &= ~CBIT;
303 ASSIGNV ((state->Cpsr & VBIT) != 0);
304 state->Cpsr &= ~VBIT;
306 ASSIGNT ((state->Cpsr & TBIT) != 0);
307 state->Cpsr &= ~TBIT;
310 if (oldmode > SVC26MODE)
312 if (state->Mode <= SVC26MODE)
314 state->Emulate = CHANGEMODE;
315 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
320 if (state->Mode > SVC26MODE)
322 state->Emulate = CHANGEMODE;
323 state->Reg[15] = R15PC;
326 state->Reg[15] = ECC | ER15INT | EMODE | R15PC;
330 /***************************************************************************\
331 * This routine updates the state of the emulator after register 15 has *
332 * been changed. Both the processor flags and register bank are updated. *
333 * This routine should only be called from a 26 bit mode. *
334 \***************************************************************************/
337 ARMul_R15Altered (ARMul_State * state)
339 if (state->Mode != R15MODE)
341 state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE);
342 state->NtransSig = (state->Mode & 3) ? HIGH : LOW;
344 if (state->Mode > SVC26MODE)
345 state->Emulate = CHANGEMODE;
346 ASSIGNR15INT (R15INT);
347 ASSIGNN ((state->Reg[15] & NBIT) != 0);
348 ASSIGNZ ((state->Reg[15] & ZBIT) != 0);
349 ASSIGNC ((state->Reg[15] & CBIT) != 0);
350 ASSIGNV ((state->Reg[15] & VBIT) != 0);
353 /***************************************************************************\
354 * This routine controls the saving and restoring of registers across mode *
355 * changes. The regbank matrix is largely unused, only rows 13 and 14 are *
356 * used across all modes, 8 to 14 are used for FIQ, all others use the USER *
357 * column. It's easier this way. old and new parameter are modes numbers. *
358 * Notice the side effect of changing the Bank variable. *
359 \***************************************************************************/
362 ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode)
368 oldbank = ModeToBank (oldmode);
369 newbank = state->Bank = ModeToBank (newmode);
371 if (oldbank != newbank)
372 { /* really need to do it */
374 { /* save away the old registers */
380 if (newbank == FIQBANK)
381 for (i = 8; i < 13; i++)
382 state->RegBank[USERBANK][i] = state->Reg[i];
383 state->RegBank[oldbank][13] = state->Reg[13];
384 state->RegBank[oldbank][14] = state->Reg[14];
387 for (i = 8; i < 15; i++)
388 state->RegBank[FIQBANK][i] = state->Reg[i];
391 for (i = 8; i < 15; i++)
392 state->RegBank[DUMMYBANK][i] = 0;
399 { /* restore the new registers */
405 if (oldbank == FIQBANK)
406 for (i = 8; i < 13; i++)
407 state->Reg[i] = state->RegBank[USERBANK][i];
408 state->Reg[13] = state->RegBank[newbank][13];
409 state->Reg[14] = state->RegBank[newbank][14];
412 for (i = 8; i < 15; i++)
413 state->Reg[i] = state->RegBank[FIQBANK][i];
416 for (i = 8; i < 15; i++)
427 /***************************************************************************\
428 * Given a processor mode, this routine returns the register bank that *
429 * will be accessed in that mode. *
430 \***************************************************************************/
433 ModeToBank (ARMword mode)
435 static ARMword bankofmode[] =
437 USERBANK, FIQBANK, IRQBANK, SVCBANK,
438 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
439 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
440 DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK,
441 USERBANK, FIQBANK, IRQBANK, SVCBANK,
442 DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK,
443 DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK,
444 DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK
447 if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0])))
450 return bankofmode[mode];
453 /***************************************************************************\
454 * Returns the register number of the nth register in a reg list. *
455 \***************************************************************************/
458 ARMul_NthReg (ARMword instr, unsigned number)
462 for (bit = 0, upto = 0; upto <= number; bit++)
468 /***************************************************************************\
469 * Assigns the N and Z flags depending on the value of result *
470 \***************************************************************************/
473 ARMul_NegZero (ARMul_State * state, ARMword result)
480 else if (result == 0)
492 /* Compute whether an addition of A and B, giving RESULT, overflowed. */
494 AddOverflow (ARMword a, ARMword b, ARMword result)
496 return ((NEG (a) && NEG (b) && POS (result))
497 || (POS (a) && POS (b) && NEG (result)));
500 /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */
502 SubOverflow (ARMword a, ARMword b, ARMword result)
504 return ((NEG (a) && POS (b) && POS (result))
505 || (POS (a) && NEG (b) && NEG (result)));
508 /***************************************************************************\
509 * Assigns the C flag after an addition of a and b to give result *
510 \***************************************************************************/
513 ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
515 ASSIGNC ((NEG (a) && NEG (b)) ||
516 (NEG (a) && POS (result)) || (NEG (b) && POS (result)));
519 /***************************************************************************\
520 * Assigns the V flag after an addition of a and b to give result *
521 \***************************************************************************/
524 ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
526 ASSIGNV (AddOverflow (a, b, result));
529 /***************************************************************************\
530 * Assigns the C flag after an subtraction of a and b to give result *
531 \***************************************************************************/
534 ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
536 ASSIGNC ((NEG (a) && POS (b)) ||
537 (NEG (a) && POS (result)) || (POS (b) && POS (result)));
540 /***************************************************************************\
541 * Assigns the V flag after an subtraction of a and b to give result *
542 \***************************************************************************/
545 ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
547 ASSIGNV (SubOverflow (a, b, result));
550 /***************************************************************************\
551 * This function does the work of generating the addresses used in an *
552 * LDC instruction. The code here is always post-indexed, it's up to the *
553 * caller to get the input address correct and to handle base register *
554 * modification. It also handles the Busy-Waiting. *
555 \***************************************************************************/
558 ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
564 if (ADDREXCEPT (address))
566 INTERNALABORT (address);
568 cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
569 while (cpab == ARMul_BUSY)
571 ARMul_Icycles (state, 1, 0);
572 if (IntPending (state))
574 cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
578 cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
580 if (cpab == ARMul_CANT)
585 cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
586 data = ARMul_LoadWordN (state, address);
589 LSBase = state->Base;
590 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
591 while (cpab == ARMul_INC)
594 data = ARMul_LoadWordN (state, address);
595 cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
597 if (state->abortSig || state->Aborted)
603 /***************************************************************************\
604 * This function does the work of generating the addresses used in an *
605 * STC instruction. The code here is always post-indexed, it's up to the *
606 * caller to get the input address correct and to handle base register *
607 * modification. It also handles the Busy-Waiting. *
608 \***************************************************************************/
611 ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
617 if (ADDREXCEPT (address) || VECTORACCESS (address))
619 INTERNALABORT (address);
621 cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
622 while (cpab == ARMul_BUSY)
624 ARMul_Icycles (state, 1, 0);
625 if (IntPending (state))
627 cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
631 cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
633 if (cpab == ARMul_CANT)
639 if (ADDREXCEPT (address) || VECTORACCESS (address))
641 INTERNALABORT (address);
646 LSBase = state->Base;
647 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
648 ARMul_StoreWordN (state, address, data);
649 while (cpab == ARMul_INC)
652 cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
653 ARMul_StoreWordN (state, address, data);
655 if (state->abortSig || state->Aborted)
661 /***************************************************************************\
662 * This function does the Busy-Waiting for an MCR instruction. *
663 \***************************************************************************/
666 ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
670 cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
672 while (cpab == ARMul_BUSY)
674 ARMul_Icycles (state, 1, 0);
676 if (IntPending (state))
678 cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
682 cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
685 if (cpab == ARMul_CANT)
686 ARMul_Abort (state, ARMul_UndefinedInstrV);
690 ARMul_Ccycles (state, 1, 0);
694 /***************************************************************************\
695 * This function does the Busy-Waiting for an MRC instruction. *
696 \***************************************************************************/
699 ARMul_MRC (ARMul_State * state, ARMword instr)
704 cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
705 while (cpab == ARMul_BUSY)
707 ARMul_Icycles (state, 1, 0);
708 if (IntPending (state))
710 cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
714 cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
716 if (cpab == ARMul_CANT)
718 ARMul_Abort (state, ARMul_UndefinedInstrV);
719 result = ECC; /* Parent will destroy the flags otherwise */
724 ARMul_Ccycles (state, 1, 0);
725 ARMul_Icycles (state, 1, 0);
730 /***************************************************************************\
731 * This function does the Busy-Waiting for an CDP instruction. *
732 \***************************************************************************/
735 ARMul_CDP (ARMul_State * state, ARMword instr)
739 cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
740 while (cpab == ARMul_BUSY)
742 ARMul_Icycles (state, 1, 0);
743 if (IntPending (state))
745 cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
749 cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
751 if (cpab == ARMul_CANT)
752 ARMul_Abort (state, ARMul_UndefinedInstrV);
757 /***************************************************************************\
758 * This function handles Undefined instructions, as CP isntruction *
759 \***************************************************************************/
762 ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
764 ARMul_Abort (state, ARMul_UndefinedInstrV);
767 /***************************************************************************\
768 * Return TRUE if an interrupt is pending, FALSE otherwise. *
769 \***************************************************************************/
772 IntPending (ARMul_State * state)
774 if (state->Exception)
775 { /* Any exceptions */
776 if (state->NresetSig == LOW)
778 ARMul_Abort (state, ARMul_ResetV);
781 else if (!state->NfiqSig && !FFLAG)
783 ARMul_Abort (state, ARMul_FIQV);
786 else if (!state->NirqSig && !IFLAG)
788 ARMul_Abort (state, ARMul_IRQV);
795 /***************************************************************************\
796 * Align a word access to a non word boundary *
797 \***************************************************************************/
800 ARMul_Align (state, address, data)
801 ARMul_State * state ATTRIBUTE_UNUSED;
805 /* This code assumes the address is really unaligned,
806 as a shift by 32 is undefined in C. */
808 address = (address & 3) << 3; /* get the word address */
809 return ((data >> address) | (data << (32 - address))); /* rot right */
812 /***************************************************************************\
813 * This routine is used to call another routine after a certain number of *
814 * cycles have been executed. The first parameter is the number of cycles *
815 * delay before the function is called, the second argument is a pointer *
816 * to the function. A delay of zero doesn't work, just call the function. *
817 \***************************************************************************/
820 ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
824 struct EventNode *event;
826 if (state->EventSet++ == 0)
827 state->Now = ARMul_Time (state);
828 when = (state->Now + delay) % EVENTLISTSIZE;
829 event = (struct EventNode *) malloc (sizeof (struct EventNode));
831 event->next = *(state->EventPtr + when);
832 *(state->EventPtr + when) = event;
835 /***************************************************************************\
836 * This routine is called at the beginning of every cycle, to envoke *
837 * scheduled events. *
838 \***************************************************************************/
841 ARMul_EnvokeEvent (ARMul_State * state)
843 static unsigned long then;
846 state->Now = ARMul_Time (state) % EVENTLISTSIZE;
847 if (then < state->Now) /* schedule events */
848 EnvokeList (state, then, state->Now);
849 else if (then > state->Now)
850 { /* need to wrap around the list */
851 EnvokeList (state, then, EVENTLISTSIZE - 1L);
852 EnvokeList (state, 0L, state->Now);
857 EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
858 /* envokes all the entries in a range */
860 struct EventNode *anevent;
862 for (; from <= to; from++)
864 anevent = *(state->EventPtr + from);
867 (anevent->func) (state);
869 anevent = anevent->next;
871 *(state->EventPtr + from) = NULL;
875 /***************************************************************************\
876 * This routine is returns the number of clock ticks since the last reset. *
877 \***************************************************************************/
880 ARMul_Time (ARMul_State * state)
882 return (state->NumScycles + state->NumNcycles +
883 state->NumIcycles + state->NumCcycles + state->NumFcycles);