From ff44f8e352695045ac851ccde05bdc3d72247ff9 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 18 Oct 2001 12:20:49 +0000 Subject: [PATCH] Add support for XScale's coprocessor access check register. Fix formatting. --- sim/arm/ChangeLog | 19 + sim/arm/armcopro.c | 257 +++++++------ sim/arm/armemu.c | 881 ++++++++++++++++++++++----------------------- sim/arm/armemu.h | 411 +++++++++++---------- sim/arm/armsupp.c | 364 ++++++++----------- 5 files changed, 944 insertions(+), 988 deletions(-) diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog index 181f6f47bd2..546898a4e68 100644 --- a/sim/arm/ChangeLog +++ b/sim/arm/ChangeLog @@ -1,3 +1,22 @@ +2001-10-18 Nick Clifton + + * armemu.h (CP_ACCESS_ALLOWED): New macro. + Fix formatting. + * armcopro.c (read_cp14_reg): Make static. + (write_cp14_reg): Make static. + (check_cp13_access): Use CP_ACCESS_ALLOWED macro. + Fix formatting. + * armsupp.c (ARMul_LDC): Check CP_ACCESS_ALLOWED. + (ARMul_STC): Check CP_ACCESS_ALLOWED. + (ARMul_MCR): Check CP_ACCESS_ALLOWED. + (ARMul_MRC): Check CP_ACCESS_ALLOWED. + (ARMul_CDP): Check CP_ACCESS_ALLOWED. + Fix formatting. + * armemu.c (MCRR): Check CP_ACCESS_ALLOWED. Test Rd and Rn not + equal to 15. + (MRRC): Check CP_ACCESS_ALLOWED. Test Rd and Rn not equal to 15. + Fix formatting. + 2001-05-11 Nick Clifton * armemu.c (ARMul_Emulate32): Fix handling of XScale LDRD and STRD diff --git a/sim/arm/armcopro.c b/sim/arm/armcopro.c index 52b22d7b85a..75c6bfca62b 100644 --- a/sim/arm/armcopro.c +++ b/sim/arm/armcopro.c @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "armdefs.h" #include "armos.h" @@ -51,6 +51,8 @@ NoCoPro4W (ARMul_State * state ATTRIBUTE_UNUSED, /* The XScale Co-processors. */ /* Coprocessor 15: System Control. */ +static void write_cp14_reg (unsigned, ARMword); +static ARMword read_cp14_reg (unsigned); /* There are two sets of registers for copro 15. One set is available when opcode_2 is 0 and @@ -83,7 +85,7 @@ XScale_cp15_init (ARMul_State * state ATTRIBUTE_UNUSED) /* Initialise the ARM Control Register. */ XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078; - + } /* Check an access to a register. */ @@ -102,7 +104,7 @@ check_cp15_access (ARMul_State * state, /* Opcode_1should be zero. */ if (opcode_1 != 0) return ARMul_CANT; - + /* Different register have different access requirements. */ switch (reg) { @@ -149,7 +151,7 @@ check_cp15_access (ARMul_State * state, case 0: if ((CRm < 5) || (CRm > 7)) return ARMul_CANT; break; } break; - + case 8: /* Permissable combinations: Opcode_2 CRm @@ -205,14 +207,18 @@ check_cp15_access (ARMul_State * state, /* Should never happen. */ return ARMul_CANT; } - + return ARMul_DONE; } /* Store a value into one of coprocessor 15's registers. */ -void -write_cp15_reg (ARMul_State * state, unsigned reg, unsigned opcode_2, unsigned CRm, ARMword value) +static void +write_cp15_reg (ARMul_State * state, + unsigned reg, + unsigned opcode_2, + unsigned CRm, + ARMword value) { if (opcode_2) { @@ -226,11 +232,11 @@ write_cp15_reg (ARMul_State * state, unsigned reg, unsigned opcode_2, unsigned C /* Only BITS (5, 4) and BITS (1, 0) can be written. */ value &= 0x33; break; - + default: return; } - + XScale_cp15_opcode_2_is_not_0_Regs [reg] = value; } else @@ -261,11 +267,11 @@ write_cp15_reg (ARMul_State * state, unsigned reg, unsigned opcode_2, unsigned C /* Only BITS (31, 14) can be written. */ value &= 0xffffc000; break; - + case 3: /* Domain Access Control. */ /* All bits writable. */ break; - + case 5: /* Fault Status Register. */ /* BITS (10, 9) and BITS (7, 0) can be written. */ value &= 0x000006ff; @@ -319,18 +325,18 @@ write_cp15_reg (ARMul_State * state, unsigned reg, unsigned opcode_2, unsigned C /* Access is only valid if CRm == 1. */ if (CRm != 1) return; - + /* Only BITS (13, 0) may be written. */ value &= 0x00003fff; break; - + default: return; } XScale_cp15_opcode_2_is_0_Regs [reg] = value; } - + return; } @@ -356,7 +362,7 @@ read_cp15_reg (unsigned reg, unsigned opcode_2, unsigned CRm) break; } } - + return XScale_cp15_opcode_2_is_0_Regs [reg]; } else @@ -372,7 +378,7 @@ XScale_cp15_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data unsigned result; result = check_cp15_access (state, reg, 0, 0, 0); - + if (result == ARMul_DONE && type == ARMul_DATA) write_cp15_reg (state, reg, 0, 0, data); @@ -384,80 +390,79 @@ XScale_cp15_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * da { unsigned reg = BITS (12, 15); unsigned result; - + result = check_cp15_access (state, reg, 0, 0, 0); - + if (result == ARMul_DONE && type == ARMul_DATA) * data = read_cp15_reg (reg, 0, 0); - + return result; } static unsigned XScale_cp15_MRC (ARMul_State * state, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword * value) + unsigned type ATTRIBUTE_UNUSED, + ARMword instr, + ARMword * value) { unsigned opcode_2 = BITS (5, 7); unsigned CRm = BITS (0, 3); unsigned reg = BITS (16, 19); unsigned result; - + result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2); - + if (result == ARMul_DONE) * value = read_cp15_reg (reg, opcode_2, CRm); - + return result; } static unsigned XScale_cp15_MCR (ARMul_State * state, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword value) + unsigned type ATTRIBUTE_UNUSED, + ARMword instr, + ARMword value) { unsigned opcode_2 = BITS (5, 7); unsigned CRm = BITS (0, 3); unsigned reg = BITS (16, 19); unsigned result; - + result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2); - + if (result == ARMul_DONE) write_cp15_reg (state, reg, opcode_2, CRm, value); - + return result; } static unsigned XScale_cp15_read_reg (ARMul_State * state ATTRIBUTE_UNUSED, - unsigned reg, - ARMword * value) + unsigned reg, + ARMword * value) { /* FIXME: Not sure what to do about the alternative register set here. For now default to just accessing CRm == 0 registers. */ * value = read_cp15_reg (reg, 0, 0); - + return TRUE; } static unsigned XScale_cp15_write_reg (ARMul_State * state ATTRIBUTE_UNUSED, - unsigned reg, - ARMword value) + unsigned reg, + ARMword value) { /* FIXME: Not sure what to do about the alternative register set here. For now default to just accessing CRm == 0 registers. */ write_cp15_reg (state, reg, 0, 0, value); - + return TRUE; } -/***************************************************************************\ -* Check for special XScale memory access features * -\***************************************************************************/ +/* Check for special XScale memory access features. */ + void XScale_check_memacc (ARMul_State * state, ARMword * address, int store) { @@ -515,11 +520,10 @@ XScale_check_memacc (ARMul_State * state, ARMword * address, int store) } } -/***************************************************************************\ -* Check set -\***************************************************************************/ +/* Check set. */ + void -XScale_set_fsr_far(ARMul_State * state, ARMword fsr, ARMword far) +XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword far) { if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0) return; @@ -529,6 +533,7 @@ XScale_set_fsr_far(ARMul_State * state, ARMword fsr, ARMword far) } /* Set the XScale debug `method of entry' if it is enabled. */ + int XScale_debug_moe (ARMul_State * state, int moe) { @@ -589,12 +594,12 @@ check_cp13_access (ARMul_State * state, /* The opcodes should be zero. */ if ((opcode_1 != 0) || (opcode_2 != 0)) return ARMul_CANT; - - /* Do not allow access to these register if bit 13 of coprocessor - 15's register 15 is zero. */ - if ((XScale_cp15_opcode_2_is_0_Regs[15] & (1 << 13)) == 0) + + /* Do not allow access to these register if bit + 13 of coprocessor 15's register 15 is zero. */ + if (! CP_ACCESS_ALLOWED (state, 13)) return ARMul_CANT; - + /* Registers 0, 4 and 8 are defined when CRm == 0. Registers 0, 4, 5, 6, 7, 8 are defined when CRm == 1. For all other CRm values undefined behaviour results. */ @@ -626,21 +631,21 @@ write_cp13_reg (unsigned reg, unsigned CRm, ARMword value) /* Only BITS (3:0) can be written. */ value &= 0xf; break; - + case 4: /* INTSRC */ /* No bits may be written. */ return; - + case 8: /* INTSTR */ /* Only BITS (1:0) can be written. */ value &= 0x3; break; - + default: /* Should not happen. Ignore any writes to unimplemented registers. */ return; } - + XScale_cp13_CR0_Regs [reg] = value; break; @@ -653,7 +658,7 @@ write_cp13_reg (unsigned reg, unsigned CRm, ARMword value) value &= 0x7000000f; value |= XScale_cp13_CR1_Regs[0] & (1UL << 31); break; - + case 4: /* ELOG0 */ case 5: /* ELOG1 */ case 6: /* ECAR0 */ @@ -665,12 +670,12 @@ write_cp13_reg (unsigned reg, unsigned CRm, ARMword value) /* Only BITS (7:0) can be written. */ value &= 0xff; break; - + default: /* Should not happen. Ignore any writes to unimplemented registers. */ return; } - + XScale_cp13_CR1_Regs [reg] = value; break; @@ -678,7 +683,7 @@ write_cp13_reg (unsigned reg, unsigned CRm, ARMword value) /* Should not happen. */ break; } - + return; } @@ -700,9 +705,9 @@ XScale_cp13_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data { unsigned reg = BITS (12, 15); unsigned result; - + result = check_cp13_access (state, reg, 0, 0, 0); - + if (result == ARMul_DONE && type == ARMul_DATA) write_cp13_reg (reg, 0, data); @@ -714,78 +719,72 @@ XScale_cp13_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * da { unsigned reg = BITS (12, 15); unsigned result; - + result = check_cp13_access (state, reg, 0, 0, 0); - + if (result == ARMul_DONE && type == ARMul_DATA) * data = read_cp13_reg (reg, 0); - + return result; } static unsigned XScale_cp13_MRC (ARMul_State * state, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword * value) + unsigned type ATTRIBUTE_UNUSED, + ARMword instr, + ARMword * value) { unsigned CRm = BITS (0, 3); unsigned reg = BITS (16, 19); unsigned result; - + result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7)); - + if (result == ARMul_DONE) * value = read_cp13_reg (reg, CRm); - + return result; } static unsigned XScale_cp13_MCR (ARMul_State * state, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword value) + unsigned type ATTRIBUTE_UNUSED, + ARMword instr, + ARMword value) { unsigned CRm = BITS (0, 3); unsigned reg = BITS (16, 19); unsigned result; - + result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7)); - + if (result == ARMul_DONE) write_cp13_reg (reg, CRm, value); - + return result; } static unsigned -XScale_cp13_read_reg -( - ARMul_State * state ATTRIBUTE_UNUSED, - unsigned reg, - ARMword * value -) +XScale_cp13_read_reg (ARMul_State * state ATTRIBUTE_UNUSED, + unsigned reg, + ARMword * value) { /* FIXME: Not sure what to do about the alternative register set here. For now default to just accessing CRm == 0 registers. */ * value = read_cp13_reg (reg, 0); - + return TRUE; } static unsigned -XScale_cp13_write_reg -( - ARMul_State * state ATTRIBUTE_UNUSED, - unsigned reg, - ARMword value -) +XScale_cp13_write_reg (ARMul_State * state ATTRIBUTE_UNUSED, + unsigned reg, + ARMword value) { /* FIXME: Not sure what to do about the alternative register set here. For now default to just accessing CRm == 0 registers. */ write_cp13_reg (reg, 0, value); - + return TRUE; } @@ -823,7 +822,7 @@ check_cp14_access (ARMul_State * state, /* OPcodes should be zero. */ if (opcode1 != 0 || opcode2 != 0) return ARMul_CANT; - + /* Accessing registers 4 or 5 has unpredicatable results. */ if (reg >= 4 && reg <= 5) return ARMul_CANT; @@ -833,7 +832,7 @@ check_cp14_access (ARMul_State * state, /* Store a value into one of coprocessor 14's registers. */ -void +static void write_cp14_reg (unsigned reg, ARMword value) { switch (reg) @@ -853,7 +852,7 @@ write_cp14_reg (unsigned reg, ARMword value) can bypass the normal checks though, so it could happen. */ value = 0; break; - + case 6: /* CCLKCFG */ /* Only BITS (3:0) can be written. */ value &= 0xf; @@ -864,7 +863,7 @@ write_cp14_reg (unsigned reg, ARMword value) have the side effect of putting the processor to sleep. Thus in order for the register to be read again, it would have to go into ACTIVE mode, which means that any read will see these bits as zero. - + Rather than trying to implement complex reset-to-zero-upon-read logic we just override the write value with zero. */ value = 0; @@ -880,12 +879,12 @@ write_cp14_reg (unsigned reg, ARMword value) /* No writes are permitted. */ value = 0; break; - + case 14: /* TXRXCTRL */ /* Only BITS (31:30) can be written. */ value &= 0xc0000000; break; - + default: /* All bits can be written. */ break; @@ -908,9 +907,9 @@ XScale_cp14_LDC (ARMul_State * state, unsigned type, ARMword instr, ARMword data { unsigned reg = BITS (12, 15); unsigned result; - + result = check_cp14_access (state, reg, 0, 0, 0); - + if (result == ARMul_DONE && type == ARMul_DATA) write_cp14_reg (reg, data); @@ -922,12 +921,12 @@ XScale_cp14_STC (ARMul_State * state, unsigned type, ARMword instr, ARMword * da { unsigned reg = BITS (12, 15); unsigned result; - + result = check_cp14_access (state, reg, 0, 0, 0); - + if (result == ARMul_DONE && type == ARMul_DATA) * data = read_cp14_reg (reg); - + return result; } @@ -942,12 +941,12 @@ XScale_cp14_MRC { unsigned reg = BITS (16, 19); unsigned result; - + result = check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7)); - + if (result == ARMul_DONE) * value = read_cp14_reg (reg); - + return result; } @@ -962,12 +961,12 @@ XScale_cp14_MCR { unsigned reg = BITS (16, 19); unsigned result; - + result = check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7)); - + if (result == ARMul_DONE) write_cp14_reg (reg, value); - + return result; } @@ -980,7 +979,7 @@ XScale_cp14_read_reg ) { * value = read_cp14_reg (reg); - + return TRUE; } @@ -993,7 +992,7 @@ XScale_cp14_write_reg ) { write_cp14_reg (reg, value); - + return TRUE; } @@ -1052,7 +1051,7 @@ MMUMCR (ARMul_State * state, d = state->data32Sig; l = state->lateabtSig; b = state->bigendSig; - + state->prog32Sig = value >> 4 & 1; state->data32Sig = value >> 5 & 1; state->lateabtSig = value >> 6 & 1; @@ -1094,12 +1093,12 @@ MMUWrite (ARMul_State * state, unsigned reg, ARMword value) d = state->data32Sig; l = state->lateabtSig; b = state->bigendSig; - + state->prog32Sig = value >> 4 & 1; state->data32Sig = value >> 5 & 1; state->lateabtSig = value >> 6 & 1; state->bigendSig = value >> 7 & 1; - + if ( p != state->prog32Sig || d != state->data32Sig || l != state->lateabtSig @@ -1144,7 +1143,7 @@ ValLDC (ARMul_State * state ATTRIBUTE_UNUSED, if (words++ != 4) return ARMul_INC; } - + return ARMul_DONE; } @@ -1204,12 +1203,12 @@ ValCDP (ARMul_State * state, unsigned type, ARMword instr) if (type == ARMul_FIRST) { ARMword howlong; - + howlong = ValReg[BITS (0, 3)]; - + /* First cycle of a busy wait. */ finish = ARMul_Time (state) + howlong; - + return howlong == 0 ? ARMul_DONE : ARMul_BUSY; } else if (type == ARMul_BUSY) @@ -1219,7 +1218,7 @@ ValCDP (ARMul_State * state, unsigned type, ARMword instr) else return ARMul_BUSY; } - + return ARMul_CANT; } @@ -1265,42 +1264,40 @@ IntCDP (ARMul_State * state, unsigned type, ARMword instr) return ARMul_BUSY; } return ARMul_DONE; - + case 1: if (howlong == 0) ARMul_Abort (state, ARMul_FIQV); else ARMul_ScheduleEvent (state, howlong, DoAFIQ); return ARMul_DONE; - + case 2: if (howlong == 0) ARMul_Abort (state, ARMul_IRQV); else ARMul_ScheduleEvent (state, howlong, DoAIRQ); return ARMul_DONE; - + case 3: state->NfiqSig = HIGH; state->Exception--; return ARMul_DONE; - + case 4: state->NirqSig = HIGH; state->Exception--; return ARMul_DONE; - + case 5: ValReg[BITS (0, 3)] = ARMul_Time (state); return ARMul_DONE; } - + return ARMul_CANT; } -/***************************************************************************\ -* Install co-processor instruction handlers in this routine * -\***************************************************************************/ +/* Install co-processor instruction handlers in this routine. */ unsigned ARMul_CoProInit (ARMul_State * state) @@ -1332,12 +1329,12 @@ ARMul_CoProInit (ARMul_State * state) XScale_cp13_LDC, XScale_cp13_STC, XScale_cp13_MRC, XScale_cp13_MCR, NULL, XScale_cp13_read_reg, XScale_cp13_write_reg); - + ARMul_CoProAttach (state, 14, XScale_cp14_init, NULL, XScale_cp14_LDC, XScale_cp14_STC, XScale_cp14_MRC, XScale_cp14_MCR, NULL, XScale_cp14_read_reg, XScale_cp14_write_reg); - + ARMul_CoProAttach (state, 15, XScale_cp15_init, NULL, NULL, NULL, XScale_cp15_MRC, XScale_cp15_MCR, NULL, XScale_cp15_read_reg, XScale_cp15_write_reg); @@ -1352,9 +1349,7 @@ ARMul_CoProInit (ARMul_State * state) return TRUE; } -/***************************************************************************\ -* Install co-processor finalisation routines in this routine * -\***************************************************************************/ +/* Install co-processor finalisation routines in this routine. */ void ARMul_CoProExit (ARMul_State * state) @@ -1369,9 +1364,7 @@ ARMul_CoProExit (ARMul_State * state) ARMul_CoProDetach (state, i); } -/***************************************************************************\ -* Routines to hook Co-processors into ARMulator * -\***************************************************************************/ +/* Routines to hook Co-processors into ARMulator. */ void ARMul_CoProAttach (ARMul_State * state, diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c index 4edac6f4112..ebc6aed1f6d 100644 --- a/sim/arm/armemu.c +++ b/sim/arm/armemu.c @@ -14,45 +14,33 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "armdefs.h" #include "armemu.h" #include "armos.h" -static ARMword GetDPRegRHS (ARMul_State * state, ARMword instr); -static ARMword GetDPSRegRHS (ARMul_State * state, ARMword instr); -static void WriteR15 (ARMul_State * state, ARMword src); -static void WriteSR15 (ARMul_State * state, ARMword src); -static void WriteR15Branch (ARMul_State * state, ARMword src); -static ARMword GetLSRegRHS (ARMul_State * state, ARMword instr); -static ARMword GetLS7RHS (ARMul_State * state, ARMword instr); -static unsigned LoadWord (ARMul_State * state, ARMword instr, - ARMword address); -static unsigned LoadHalfWord (ARMul_State * state, ARMword instr, - ARMword address, int signextend); -static unsigned LoadByte (ARMul_State * state, ARMword instr, ARMword address, - int signextend); -static unsigned StoreWord (ARMul_State * state, ARMword instr, - ARMword address); -static unsigned StoreHalfWord (ARMul_State * state, ARMword instr, - ARMword address); -static unsigned StoreByte (ARMul_State * state, ARMword instr, - ARMword address); -static void LoadMult (ARMul_State * state, ARMword address, ARMword instr, - ARMword WBBase); -static void StoreMult (ARMul_State * state, ARMword address, ARMword instr, - ARMword WBBase); -static void LoadSMult (ARMul_State * state, ARMword address, ARMword instr, - ARMword WBBase); -static void StoreSMult (ARMul_State * state, ARMword address, ARMword instr, - ARMword WBBase); -static unsigned Multiply64 (ARMul_State * state, ARMword instr, - int signextend, int scc); -static unsigned MultiplyAdd64 (ARMul_State * state, ARMword instr, - int signextend, int scc); -static void Handle_Load_Double (ARMul_State * state, ARMword instr); -static void Handle_Store_Double (ARMul_State * state, ARMword instr); +static ARMword GetDPRegRHS (ARMul_State *, ARMword); +static ARMword GetDPSRegRHS (ARMul_State *, ARMword); +static void WriteR15 (ARMul_State *, ARMword); +static void WriteSR15 (ARMul_State *, ARMword); +static void WriteR15Branch (ARMul_State *, ARMword); +static ARMword GetLSRegRHS (ARMul_State *, ARMword); +static ARMword GetLS7RHS (ARMul_State *, ARMword); +static unsigned LoadWord (ARMul_State *, ARMword, ARMword); +static unsigned LoadHalfWord (ARMul_State *, ARMword, ARMword, int); +static unsigned LoadByte (ARMul_State *, ARMword, ARMword, int); +static unsigned StoreWord (ARMul_State *, ARMword, ARMword); +static unsigned StoreHalfWord (ARMul_State *, ARMword, ARMword); +static unsigned StoreByte (ARMul_State *, ARMword, ARMword); +static void LoadMult (ARMul_State *, ARMword, ARMword, ARMword); +static void StoreMult (ARMul_State *, ARMword, ARMword, ARMword); +static void LoadSMult (ARMul_State *, ARMword, ARMword, ARMword); +static void StoreSMult (ARMul_State *, ARMword, ARMword, ARMword); +static unsigned Multiply64 (ARMul_State *, ARMword, int, int); +static unsigned MultiplyAdd64 (ARMul_State *, ARMword, int, int); +static void Handle_Load_Double (ARMul_State *, ARMword); +static void Handle_Store_Double (ARMul_State *, ARMword); #define LUNSIGNED (0) /* unsigned operation */ #define LSIGNED (1) /* signed operation */ @@ -60,53 +48,51 @@ static void Handle_Store_Double (ARMul_State * state, ARMword instr); #define LSCC (1) /* set condition codes on result */ #ifdef NEED_UI_LOOP_HOOK -/* How often to run the ui_loop update, when in use */ +/* How often to run the ui_loop update, when in use. */ #define UI_LOOP_POLL_INTERVAL 0x32000 -/* Counter for the ui_loop_hook update */ +/* Counter for the ui_loop_hook update. */ static long ui_loop_hook_counter = UI_LOOP_POLL_INTERVAL; -/* Actual hook to call to run through gdb's gui event loop */ +/* Actual hook to call to run through gdb's gui event loop. */ extern int (*ui_loop_hook) (int); #endif /* NEED_UI_LOOP_HOOK */ extern int stop_simulator; -/***************************************************************************\ -* short-hand macros for LDR/STR * -\***************************************************************************/ +/* Short-hand macros for LDR/STR. */ -/* store post decrement writeback */ +/* Store post decrement writeback. */ #define SHDOWNWB() \ lhs = LHS ; \ - if (StoreHalfWord(state, instr, lhs)) \ - LSBase = lhs - GetLS7RHS(state, instr) ; + if (StoreHalfWord (state, instr, lhs)) \ + LSBase = lhs - GetLS7RHS (state, instr); -/* store post increment writeback */ +/* Store post increment writeback. */ #define SHUPWB() \ lhs = LHS ; \ - if (StoreHalfWord(state, instr, lhs)) \ - LSBase = lhs + GetLS7RHS(state, instr) ; + if (StoreHalfWord (state, instr, lhs)) \ + LSBase = lhs + GetLS7RHS (state, instr); -/* store pre decrement */ +/* Store pre decrement. */ #define SHPREDOWN() \ - (void)StoreHalfWord(state, instr, LHS - GetLS7RHS(state, instr)) ; + (void)StoreHalfWord (state, instr, LHS - GetLS7RHS (state, instr)); -/* store pre decrement writeback */ +/* Store pre decrement writeback. */ #define SHPREDOWNWB() \ - temp = LHS - GetLS7RHS(state, instr) ; \ - if (StoreHalfWord(state, instr, temp)) \ - LSBase = temp ; + temp = LHS - GetLS7RHS (state, instr); \ + if (StoreHalfWord (state, instr, temp)) \ + LSBase = temp; -/* store pre increment */ +/* Store pre increment. */ #define SHPREUP() \ - (void)StoreHalfWord(state, instr, LHS + GetLS7RHS(state, instr)) ; + (void)StoreHalfWord (state, instr, LHS + GetLS7RHS (state, instr)); -/* store pre increment writeback */ +/* Store pre increment writeback. */ #define SHPREUPWB() \ - temp = LHS + GetLS7RHS(state, instr) ; \ - if (StoreHalfWord(state, instr, temp)) \ - LSBase = temp ; + temp = LHS + GetLS7RHS (state, instr); \ + if (StoreHalfWord (state, instr, temp)) \ + LSBase = temp; /* Load post decrement writeback. */ #define LHPOSTDOWN() \ @@ -168,134 +154,143 @@ extern int stop_simulator; break; \ } - -/* load pre decrement */ -#define LHPREDOWN() \ -{ \ - int done = 1 ; \ - temp = LHS - GetLS7RHS(state,instr) ; \ - switch (BITS(5,6)) { \ - case 1: /* H */ \ - (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \ - break ; \ - case 2: /* SB */ \ - (void)LoadByte(state,instr,temp,LSIGNED) ; \ - break ; \ - case 3: /* SH */ \ - (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \ - break ; \ - case 0: /* SWP handled elsewhere */ \ - default: \ - done = 0 ; \ - break ; \ - } \ - if (done) \ - break ; \ +/* Load pre decrement. */ +#define LHPREDOWN() \ +{ \ + int done = 1; \ + \ + temp = LHS - GetLS7RHS (state, instr); \ + switch (BITS (5, 6)) \ + { \ + case 1: /* H */ \ + (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \ + break; \ + case 2: /* SB */ \ + (void) LoadByte (state, instr, temp, LSIGNED); \ + break; \ + case 3: /* SH */ \ + (void) LoadHalfWord (state, instr, temp, LSIGNED); \ + break; \ + case 0: \ + /* SWP handled elsewhere. */ \ + default: \ + done = 0; \ + break; \ + } \ + if (done) \ + break; \ } -/* load pre decrement writeback */ -#define LHPREDOWNWB() \ -{ \ - int done = 1 ; \ - temp = LHS - GetLS7RHS(state, instr) ; \ - switch (BITS(5,6)) { \ - case 1: /* H */ \ - if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \ - LSBase = temp ; \ - break ; \ - case 2: /* SB */ \ - if (LoadByte(state,instr,temp,LSIGNED)) \ - LSBase = temp ; \ - break ; \ - case 3: /* SH */ \ - if (LoadHalfWord(state,instr,temp,LSIGNED)) \ - LSBase = temp ; \ - break ; \ - case 0: /* SWP handled elsewhere */ \ - default: \ - done = 0 ; \ - break ; \ - } \ - if (done) \ - break ; \ +/* Load pre decrement writeback. */ +#define LHPREDOWNWB() \ +{ \ + int done = 1; \ + \ + temp = LHS - GetLS7RHS (state, instr); \ + switch (BITS (5, 6)) \ + { \ + case 1: /* H */ \ + if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \ + LSBase = temp; \ + break; \ + case 2: /* SB */ \ + if (LoadByte (state, instr, temp, LSIGNED)) \ + LSBase = temp; \ + break; \ + case 3: /* SH */ \ + if (LoadHalfWord (state, instr, temp, LSIGNED)) \ + LSBase = temp; \ + break; \ + case 0: \ + /* SWP handled elsewhere. */ \ + default: \ + done = 0; \ + break; \ + } \ + if (done) \ + break; \ } -/* load pre increment */ -#define LHPREUP() \ -{ \ - int done = 1 ; \ - temp = LHS + GetLS7RHS(state,instr) ; \ - switch (BITS(5,6)) { \ - case 1: /* H */ \ - (void)LoadHalfWord(state,instr,temp,LUNSIGNED) ; \ - break ; \ - case 2: /* SB */ \ - (void)LoadByte(state,instr,temp,LSIGNED) ; \ - break ; \ - case 3: /* SH */ \ - (void)LoadHalfWord(state,instr,temp,LSIGNED) ; \ - break ; \ - case 0: /* SWP handled elsewhere */ \ - default: \ - done = 0 ; \ - break ; \ - } \ - if (done) \ - break ; \ +/* Load pre increment. */ +#define LHPREUP() \ +{ \ + int done = 1; \ + \ + temp = LHS + GetLS7RHS (state, instr); \ + switch (BITS (5, 6)) \ + { \ + case 1: /* H */ \ + (void) LoadHalfWord (state, instr, temp, LUNSIGNED); \ + break; \ + case 2: /* SB */ \ + (void) LoadByte (state, instr, temp, LSIGNED); \ + break; \ + case 3: /* SH */ \ + (void) LoadHalfWord (state, instr, temp, LSIGNED); \ + break; \ + case 0: \ + /* SWP handled elsewhere. */ \ + default: \ + done = 0; \ + break; \ + } \ + if (done) \ + break; \ } -/* load pre increment writeback */ -#define LHPREUPWB() \ -{ \ - int done = 1 ; \ - temp = LHS + GetLS7RHS(state, instr) ; \ - switch (BITS(5,6)) { \ - case 1: /* H */ \ - if (LoadHalfWord(state,instr,temp,LUNSIGNED)) \ - LSBase = temp ; \ - break ; \ - case 2: /* SB */ \ - if (LoadByte(state,instr,temp,LSIGNED)) \ - LSBase = temp ; \ - break ; \ - case 3: /* SH */ \ - if (LoadHalfWord(state,instr,temp,LSIGNED)) \ - LSBase = temp ; \ - break ; \ - case 0: /* SWP handled elsewhere */ \ - default: \ - done = 0 ; \ - break ; \ - } \ - if (done) \ - break ; \ +/* Load pre increment writeback. */ +#define LHPREUPWB() \ +{ \ + int done = 1; \ + \ + temp = LHS + GetLS7RHS (state, instr); \ + switch (BITS (5, 6)) \ + { \ + case 1: /* H */ \ + if (LoadHalfWord (state, instr, temp, LUNSIGNED)) \ + LSBase = temp; \ + break; \ + case 2: /* SB */ \ + if (LoadByte (state, instr, temp, LSIGNED)) \ + LSBase = temp; \ + break; \ + case 3: /* SH */ \ + if (LoadHalfWord (state, instr, temp, LSIGNED)) \ + LSBase = temp; \ + break; \ + case 0: \ + /* SWP handled elsewhere. */ \ + default: \ + done = 0; \ + break; \ + } \ + if (done) \ + break; \ } -/***************************************************************************\ -* EMULATION of ARM6 * -\***************************************************************************/ +/* EMULATION of ARM6. */ -/* The PC pipeline value depends on whether ARM or Thumb instructions - are being executed: */ +/* The PC pipeline value depends on whether ARM + or Thumb instructions are being executed. */ ARMword isize; ARMword #ifdef MODE32 -ARMul_Emulate32 (register ARMul_State * state) +ARMul_Emulate32 (ARMul_State * state) #else -ARMul_Emulate26 (register ARMul_State * state) +ARMul_Emulate26 (ARMul_State * state) #endif { - register ARMword instr, /* the current instruction */ - dest = 0, /* almost the DestBus */ - temp, /* ubiquitous third hand */ - pc = 0; /* the address of the current instruction */ - ARMword lhs, rhs; /* almost the ABus and BBus */ - ARMword decoded = 0, loaded = 0; /* instruction pipeline */ + ARMword instr; /* The current instruction. */ + ARMword dest = 0; /* Almost the DestBus. */ + ARMword temp; /* Ubiquitous third hand. */ + ARMword pc = 0; /* The address of the current instruction. */ + ARMword lhs; /* Almost the ABus and BBus. */ + ARMword rhs; + ARMword decoded = 0; /* Instruction pipeline. */ + ARMword loaded = 0; -/***************************************************************************\ -* Execute the next instruction * -\***************************************************************************/ + /* Execute the next instruction. */ if (state->NextInstr < PRIMEPIPE) { @@ -305,12 +300,15 @@ ARMul_Emulate26 (register ARMul_State * state) } do - { /* just keep going */ + { + /* Just keep going. */ isize = INSN_SIZE; + switch (state->NextInstr) { case SEQ: - state->Reg[15] += isize; /* Advance the pipeline, and an S cycle */ + /* Advance the pipeline, and an S cycle. */ + state->Reg[15] += isize; pc += isize; instr = decoded; decoded = loaded; @@ -318,7 +316,8 @@ ARMul_Emulate26 (register ARMul_State * state) break; case NONSEQ: - state->Reg[15] += isize; /* Advance the pipeline, and an N cycle */ + /* Advance the pipeline, and an N cycle. */ + state->Reg[15] += isize; pc += isize; instr = decoded; decoded = loaded; @@ -327,7 +326,8 @@ ARMul_Emulate26 (register ARMul_State * state) break; case PCINCEDSEQ: - pc += isize; /* Program counter advanced, and an S cycle */ + /* Program counter advanced, and an S cycle. */ + pc += isize; instr = decoded; decoded = loaded; loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize); @@ -335,42 +335,45 @@ ARMul_Emulate26 (register ARMul_State * state) break; case PCINCEDNONSEQ: - pc += isize; /* Program counter advanced, and an N cycle */ + /* Program counter advanced, and an N cycle. */ + pc += isize; instr = decoded; decoded = loaded; loaded = ARMul_LoadInstrN (state, pc + (isize * 2), isize); NORMALCYCLE; break; - case RESUME: /* The program counter has been changed */ + case RESUME: + /* The program counter has been changed. */ pc = state->Reg[15]; #ifndef MODE32 pc = pc & R15PCBITS; #endif state->Reg[15] = pc + (isize * 2); state->Aborted = 0; - instr = ARMul_ReLoadInstr (state, pc, isize); + instr = ARMul_ReLoadInstr (state, pc, isize); decoded = ARMul_ReLoadInstr (state, pc + isize, isize); - loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize); + loaded = ARMul_ReLoadInstr (state, pc + isize * 2, isize); NORMALCYCLE; break; - default: /* The program counter has been changed */ + default: + /* The program counter has been changed. */ pc = state->Reg[15]; #ifndef MODE32 pc = pc & R15PCBITS; #endif state->Reg[15] = pc + (isize * 2); state->Aborted = 0; - instr = ARMul_LoadInstrN (state, pc, isize); + instr = ARMul_LoadInstrN (state, pc, isize); decoded = ARMul_LoadInstrS (state, pc + (isize), isize); - loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize); + loaded = ARMul_LoadInstrS (state, pc + (isize * 2), isize); NORMALCYCLE; break; } + if (state->EventSet) ARMul_EnvokeEvent (state); - #if 0 /* Enable this for a helpful bit of debugging when tracing is needed. */ fprintf (stderr, "pc: %x, instr: %x\n", pc & ~1, instr); @@ -379,7 +382,8 @@ ARMul_Emulate26 (register ARMul_State * state) #endif if (state->Exception) - { /* Any exceptions */ + { + /* Any exceptions ? */ if (state->NresetSig == LOW) { ARMul_Abort (state, ARMul_ResetV); @@ -427,34 +431,42 @@ ARMul_Emulate26 (register ARMul_State * state) instr variable, and letting the normal ARM simulator execute). There are some caveats to ensure that the correct pipelined PC value is used when executing Thumb code, and also for - dealing with the BL instruction. */ + dealing with the BL instruction. */ if (TFLAG) - { /* check if in Thumb mode */ + { ARMword new; + + /* Check if in Thumb mode. */ switch (ARMul_ThumbDecode (state, pc, instr, &new)) { case t_undefined: - ARMul_UndefInstr (state, instr); /* This is a Thumb instruction */ + /* This is a Thumb instruction. */ + ARMul_UndefInstr (state, instr); goto donext; - case t_branch: /* already processed */ + case t_branch: + /* Already processed. */ goto donext; - case t_decoded: /* ARM instruction available */ - instr = new; /* so continue instruction decoding */ + case t_decoded: + /* ARM instruction available. */ + instr = new; + /* So continue instruction decoding. */ + break; + default: break; } } #endif -/***************************************************************************\ -* Check the condition codes * -\***************************************************************************/ + /* Check the condition codes. */ if ((temp = TOPBITS (28)) == AL) - goto mainswitch; /* vile deed in the need for speed */ + /* Vile deed in the need for speed. */ + goto mainswitch; + /* Check the condition code. */ switch ((int) TOPBITS (28)) - { /* check the condition code */ + { case AL: temp = TRUE; break; @@ -566,7 +578,7 @@ check_PMUintr: cp14r1 = state->CPRead[14] (state, 1, 0); - /* coded like this for portability */ + /* Coded like this for portability. */ while (newcycles) { if (cp14r1 == 0xffffffff) @@ -602,12 +614,11 @@ check_PMUintr: } } -/***************************************************************************\ -* Actual execution of instructions begins here * -\***************************************************************************/ + /* Actual execution of instructions begins here. */ if (temp) - { /* if the condition codes don't match, stop here */ + { + /* If the condition codes don't match, stop here. */ mainswitch: if (state->is_XScale) @@ -670,16 +681,13 @@ check_PMUintr: switch ((int) BITS (20, 27)) { - -/***************************************************************************\ -* Data Processing Register RHS Instructions * -\***************************************************************************/ + /* Data Processing Register RHS Instructions. */ case 0x00: /* AND reg and MUL */ #ifdef MODET if (BITS (4, 11) == 0xB) { - /* STRH register offset, no write-back, down, post indexed */ + /* STRH register offset, no write-back, down, post indexed. */ SHDOWNWB (); break; } @@ -1461,9 +1469,9 @@ check_PMUintr: #ifdef MODET if ((BITS (4, 11) & 0xF9) == 0x9) { - /* LDR register offset, write-back, down, pre indexed */ + /* LDR register offset, write-back, down, pre indexed. */ LHPREDOWNWB (); - /* continue with remaining instruction decode */ + /* Continue with remaining instruction decode. */ } #endif if (DESTReg == 15) @@ -1543,7 +1551,7 @@ check_PMUintr: #ifdef MODET if (BITS (4, 7) == 0xB) { - /* STRH immediate offset, no write-back, down, pre indexed */ + /* STRH immediate offset, no write-back, down, pre indexed. */ SHPREDOWN (); break; } @@ -1914,9 +1922,8 @@ check_PMUintr: WRITESDEST (dest); break; -/***************************************************************************\ -* Data Processing Immediate RHS Instructions * -\***************************************************************************/ + + /* Data Processing Immediate RHS Instructions. */ case 0x20: /* AND immed */ dest = LHS & DPImmRHS; @@ -2250,9 +2257,7 @@ check_PMUintr: WRITESDEST (~rhs); break; -/***************************************************************************\ -* Single Data Transfer Immediate RHS Instructions * -\***************************************************************************/ + /* Single Data Transfer Immediate RHS Instructions. */ case 0x40: /* Store Word, No WriteBack, Post Dec, Immed */ lhs = LHS; @@ -2480,9 +2485,8 @@ check_PMUintr: LSBase = temp; break; -/***************************************************************************\ -* Single Data Transfer Register RHS Instructions * -\***************************************************************************/ + + /* Single Data Transfer Register RHS Instructions. */ case 0x60: /* Store Word, No WriteBack, Post Dec, Reg */ if (BIT (4)) @@ -2950,9 +2954,8 @@ check_PMUintr: LSBase = temp; break; -/***************************************************************************\ -* Multiple Data Transfer Instructions * -\***************************************************************************/ + + /* Multiple Data Transfer Instructions. */ case 0x80: /* Store, No WriteBack, Post Dec */ STOREMULT (instr, LSBase - LSMNumRegs + 4L, 0L); @@ -3098,10 +3101,8 @@ check_PMUintr: LOADSMULT (instr, temp + 4L, temp + LSMNumRegs); break; -/***************************************************************************\ -* Branch forward * -\***************************************************************************/ + /* Branch forward. */ case 0xa0: case 0xa1: case 0xa2: @@ -3114,10 +3115,8 @@ check_PMUintr: FLUSHPIPE; break; -/***************************************************************************\ -* Branch backward * -\***************************************************************************/ + /* Branch backward. */ case 0xa8: case 0xa9: case 0xaa: @@ -3130,10 +3129,8 @@ check_PMUintr: FLUSHPIPE; break; -/***************************************************************************\ -* Branch and Link forward * -\***************************************************************************/ + /* Branch and Link forward. */ case 0xb0: case 0xb1: case 0xb2: @@ -3142,19 +3139,18 @@ check_PMUintr: case 0xb5: case 0xb6: case 0xb7: + /* Put PC into Link. */ #ifdef MODE32 - state->Reg[14] = pc + 4; /* put PC into Link */ + state->Reg[14] = pc + 4; #else - state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; /* put PC into Link */ + state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; #endif state->Reg[15] = pc + 8 + POSBRANCH; FLUSHPIPE; break; -/***************************************************************************\ -* Branch and Link backward * -\***************************************************************************/ + /* Branch and Link backward. */ case 0xb8: case 0xb9: case 0xba: @@ -3163,36 +3159,48 @@ check_PMUintr: case 0xbd: case 0xbe: case 0xbf: + /* Put PC into Link. */ #ifdef MODE32 - state->Reg[14] = pc + 4; /* put PC into Link */ + state->Reg[14] = pc + 4; #else - state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; /* put PC into Link */ + state->Reg[14] = (pc + 4) | ECC | ER15INT | EMODE; #endif state->Reg[15] = pc + 8 + NEGBRANCH; FLUSHPIPE; break; -/***************************************************************************\ -* Co-Processor Data Transfers * -\***************************************************************************/ - + /* Co-Processor Data Transfers. */ case 0xc4: - if (state->is_XScale) + if (state->is_v5) { - if (BITS (4, 7) != 0x00) + /* Reading from R15 is UNPREDICTABLE. */ + if (BITS (12, 15) == 15 || BITS (16, 19) == 15) ARMul_UndefInstr (state, instr); - - if (BITS (8, 11) != 0x00) - ARMul_UndefInstr (state, instr); /* Not CP0. */ - - /* XScale MAR insn. Move two registers into accumulator. */ - if (BITS (0, 3) == 0x00) + /* Is access to coprocessor 0 allowed ? */ + else if (! CP_ACCESS_ALLOWED (state, CPNum)) + ARMul_UndefInstr (state, instr); + /* Special treatment for XScale coprocessors. */ + else if (state->is_XScale) { - state->Accumulator = state->Reg[BITS (12, 15)]; - state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32; - break; + /* Only opcode 0 is supported. */ + if (BITS (4, 7) != 0x00) + ARMul_UndefInstr (state, instr); + /* Only coporcessor 0 is supported. */ + else if (CPNum != 0x00) + ARMul_UndefInstr (state, instr); + /* Only accumulator 0 is supported. */ + else if (BITS (0, 3) != 0x00) + ARMul_UndefInstr (state, instr); + else + { + /* XScale MAR insn. Move two registers into accumulator. */ + state->Accumulator = state->Reg[BITS (12, 15)]; + state->Accumulator += (ARMdword) state->Reg[BITS (16, 19)] << 32; + } } - /* Access to any other acc is unpredicatable. */ + else + /* FIXME: Not sure what to do for other v5 processors. */ + ARMul_UndefInstr (state, instr); break; } /* Drop through. */ @@ -3202,27 +3210,42 @@ check_PMUintr: break; case 0xc5: - if (state->is_XScale) + if (state->is_v5) { - if (BITS (4, 7) != 0x00) + /* Writes to R15 are UNPREDICATABLE. */ + if (DESTReg == 15 || LHSReg == 15) ARMul_UndefInstr (state, instr); - - if (BITS (8, 11) != 0x00) - ARMul_UndefInstr (state, instr); /* Not CP0. */ - - /* XScale MRA insn. Move accumulator into two registers. */ - if (BITS (0, 3) == 0x00) + /* Is access to the coprocessor allowed ? */ + else if (! CP_ACCESS_ALLOWED (state, CPNum)) + ARMul_UndefInstr (state, instr); + /* Special handling for XScale coprcoessors. */ + else if (state->is_XScale) { - ARMword t1 = (state->Accumulator >> 32) & 255; + /* Only opcode 0 is supported. */ + if (BITS (4, 7) != 0x00) + ARMul_UndefInstr (state, instr); + /* Only coprocessor 0 is supported. */ + else if (CPNum != 0x00) + ARMul_UndefInstr (state, instr); + /* Only accumulator 0 is supported. */ + else if (BITS (0, 3) != 0x00) + ARMul_UndefInstr (state, instr); + else + { + /* XScale MRA insn. Move accumulator into two registers. */ + ARMword t1 = (state->Accumulator >> 32) & 255; - if (t1 & 128) - t1 -= 256; + if (t1 & 128) + t1 -= 256; - state->Reg[BITS (12, 15)] = state->Accumulator; - state->Reg[BITS (16, 19)] = t1; - break; + state->Reg[BITS (12, 15)] = state->Accumulator; + state->Reg[BITS (16, 19)] = t1; + break; + } } - /* Access to any other acc is unpredicatable. */ + else + /* FIXME: Not sure what to do for other v5 processors. */ + ARMul_UndefInstr (state, instr); break; } /* Drop through. */ @@ -3269,7 +3292,6 @@ check_PMUintr: ARMul_LDC (state, instr, LHS); break; - case 0xd0: case 0xd4: /* Store , No WriteBack , Pre Dec */ ARMul_STC (state, instr, LHS - LSCOff); @@ -3318,11 +3340,14 @@ check_PMUintr: ARMul_LDC (state, instr, lhs); break; -/***************************************************************************\ -* Co-Processor Register Transfers (MCR) and Data Ops * -\***************************************************************************/ + /* Co-Processor Register Transfers (MCR) and Data Ops. */ case 0xe2: + if (! CP_ACCESS_ALLOWED (state, CPNum)) + { + ARMul_UndefInstr (state, instr); + break; + } if (state->is_XScale) switch (BITS (18, 19)) { @@ -3431,10 +3456,8 @@ check_PMUintr: ARMul_CDP (state, instr); break; -/***************************************************************************\ -* Co-Processor Register Transfers (MRC) and Data Ops * -\***************************************************************************/ + /* Co-Processor Register Transfers (MRC) and Data Ops. */ case 0xe1: case 0xe3: case 0xe5: @@ -3460,10 +3483,8 @@ check_PMUintr: ARMul_CDP (state, instr); break; -/***************************************************************************\ -* SWI instruction * -\***************************************************************************/ + /* SWI instruction. */ case 0xf0: case 0xf1: case 0xf2: @@ -3489,12 +3510,11 @@ check_PMUintr: } if (!ARMul_OSHandleSWI (state, BITS (0, 23))) - { - ARMul_Abort (state, ARMul_SWIV); - } + ARMul_Abort (state, ARMul_SWIV); + break; - } /* 256 way main switch */ - } /* if temp */ + } + } #ifdef MODET donext: @@ -3516,21 +3536,18 @@ check_PMUintr: else if (state->Emulate != RUN) break; } - while (!stop_simulator); /* do loop */ + while (!stop_simulator); state->decoded = decoded; state->loaded = loaded; state->pc = pc; return pc; -} /* Emulate 26/32 in instruction based mode */ - +} -/***************************************************************************\ -* This routine evaluates most Data Processing register RHS's with the S * -* bit clear. It is intended to be called from the macro DPRegRHS, which * -* filters the common case of an unshifted register with in line code * -\***************************************************************************/ +/* This routine evaluates most Data Processing register RHS's with the S + bit clear. It is intended to be called from the macro DPRegRHS, which + filters the common case of an unshifted register with in line code. */ static ARMword GetDPRegRHS (ARMul_State * state, ARMword instr) @@ -3539,7 +3556,8 @@ GetDPRegRHS (ARMul_State * state, ARMword instr) base = RHSReg; if (BIT (4)) - { /* shift amount in a register */ + { + /* Shift amount in a register. */ UNDEF_Shift; INCPC; #ifndef MODE32 @@ -3582,7 +3600,8 @@ GetDPRegRHS (ARMul_State * state, ARMword instr) } } else - { /* shift amount is a constant */ + { + /* Shift amount is a constant. */ #ifndef MODE32 if (base == 15) base = ECC | ER15INT | R15PC | EMODE; @@ -3611,15 +3630,14 @@ GetDPRegRHS (ARMul_State * state, ARMword instr) return ((base << (32 - shamt)) | (base >> shamt)); } } - return (0); /* just to shut up lint */ + + return 0; } -/***************************************************************************\ -* This routine evaluates most Logical Data Processing register RHS's * -* with the S bit set. It is intended to be called from the macro * -* DPSRegRHS, which filters the common case of an unshifted register * -* with in line code * -\***************************************************************************/ +/* This routine evaluates most Logical Data Processing register RHS's + with the S bit set. It is intended to be called from the macro + DPSRegRHS, which filters the common case of an unshifted register + with in line code. */ static ARMword GetDPSRegRHS (ARMul_State * state, ARMword instr) @@ -3628,7 +3646,8 @@ GetDPSRegRHS (ARMul_State * state, ARMword instr) base = RHSReg; if (BIT (4)) - { /* shift amount in a register */ + { + /* Shift amount in a register. */ UNDEF_Shift; INCPC; #ifndef MODE32 @@ -3707,7 +3726,8 @@ GetDPSRegRHS (ARMul_State * state, ARMword instr) } } else - { /* shift amount is a constant */ + { + /* Shift amount is a constant. */ #ifndef MODE32 if (base == 15) base = ECC | ER15INT | R15PC | EMODE; @@ -3756,12 +3776,11 @@ GetDPSRegRHS (ARMul_State * state, ARMword instr) } } } - return (0); /* just to shut up lint */ + + return 0; } -/***************************************************************************\ -* This routine handles writes to register 15 when the S bit is not set. * -\***************************************************************************/ +/* This routine handles writes to register 15 when the S bit is not set. */ static void WriteR15 (ARMul_State * state, ARMword src) @@ -3786,9 +3805,7 @@ WriteR15 (ARMul_State * state, ARMword src) FLUSHPIPE; } -/***************************************************************************\ -* This routine handles writes to register 15 when the S bit is set. * -\***************************************************************************/ +/* This routine handles writes to register 15 when the S bit is set. */ static void WriteSR15 (ARMul_State * state, ARMword src) @@ -3823,14 +3840,15 @@ WriteSR15 (ARMul_State * state, ARMword src) } /* In machines capable of running in Thumb mode, BX, BLX, LDR and LDM - will switch to Thumb mode if the least significant bit is set. */ + will switch to Thumb mode if the least significant bit is set. */ static void WriteR15Branch (ARMul_State * state, ARMword src) { #ifdef MODET if (src & 1) - { /* Thumb bit */ + { + /* Thumb bit. */ SETT; state->Reg[15] = src & 0xfffffffe; } @@ -3845,11 +3863,9 @@ WriteR15Branch (ARMul_State * state, ARMword src) #endif } -/***************************************************************************\ -* This routine evaluates most Load and Store register RHS's. It is * -* intended to be called from the macro LSRegRHS, which filters the * -* common case of an unshifted register with in line code * -\***************************************************************************/ +/* This routine evaluates most Load and Store register RHS's. It is + intended to be called from the macro LSRegRHS, which filters the + common case of an unshifted register with in line code. */ static ARMword GetLSRegRHS (ARMul_State * state, ARMword instr) @@ -3859,7 +3875,7 @@ GetLSRegRHS (ARMul_State * state, ARMword instr) base = RHSReg; #ifndef MODE32 if (base == 15) - base = ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but .... */ + base = ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but .... */ else #endif base = state->Reg[base]; @@ -3884,33 +3900,32 @@ GetLSRegRHS (ARMul_State * state, ARMword instr) return ((base >> 1) | (CFLAG << 31)); else return ((base << (32 - shamt)) | (base >> shamt)); + default: + break; } - return (0); /* just to shut up lint */ + return 0; } -/***************************************************************************\ -* This routine evaluates the ARM7T halfword and signed transfer RHS's. * -\***************************************************************************/ +/* This routine evaluates the ARM7T halfword and signed transfer RHS's. */ static ARMword GetLS7RHS (ARMul_State * state, ARMword instr) { if (BIT (22) == 0) - { /* register */ + { + /* Register. */ #ifndef MODE32 if (RHSReg == 15) - return ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but ... */ + return ECC | ER15INT | R15PC | EMODE; /* Now forbidden, but ... */ #endif return state->Reg[RHSReg]; } - /* else immediate */ + /* Otherwise an immediate. */ return BITS (0, 3) | (BITS (8, 11) << 4); } -/***************************************************************************\ -* This function does the work of loading a word for a LDR instruction. * -\***************************************************************************/ +/* This function does the work of loading a word for a LDR instruction. */ static unsigned LoadWord (ARMul_State * state, ARMword instr, ARMword address) @@ -3920,11 +3935,11 @@ LoadWord (ARMul_State * state, ARMword instr, ARMword address) BUSUSEDINCPCS; #ifndef MODE32 if (ADDREXCEPT (address)) - { - INTERNALABORT (address); - } + INTERNALABORT (address); #endif + dest = ARMul_LoadWordN (state, address); + if (state->Aborted) { TAKEABORT; @@ -3939,9 +3954,7 @@ LoadWord (ARMul_State * state, ARMword instr, ARMword address) } #ifdef MODET -/***************************************************************************\ -* This function does the work of loading a halfword. * -\***************************************************************************/ +/* This function does the work of loading a halfword. */ static unsigned LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address, @@ -3975,9 +3988,7 @@ LoadHalfWord (ARMul_State * state, ARMword instr, ARMword address, #endif /* MODET */ -/***************************************************************************\ -* This function does the work of loading a byte for a LDRB instruction. * -\***************************************************************************/ +/* This function does the work of loading a byte for a LDRB instruction. */ static unsigned LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend) @@ -4008,9 +4019,7 @@ LoadByte (ARMul_State * state, ARMword instr, ARMword address, int signextend) return (DESTReg != LHSReg); } -/***************************************************************************\ -* This function does the work of loading two words for a LDRD instruction. * -\***************************************************************************/ +/* This function does the work of loading two words for a LDRD instruction. */ static void Handle_Load_Double (ARMul_State * state, ARMword instr) @@ -4117,9 +4126,7 @@ Handle_Load_Double (ARMul_State * state, ARMword instr) state->Reg[addr_reg] = addr; } -/***************************************************************************\ -* This function does the work of storing two words for a STRD instruction. * -\***************************************************************************/ +/* This function does the work of storing two words for a STRD instruction. */ static void Handle_Store_Double (ARMul_State * state, ARMword instr) @@ -4222,9 +4229,7 @@ Handle_Store_Double (ARMul_State * state, ARMword instr) state->Reg[addr_reg] = addr; } -/***************************************************************************\ -* This function does the work of storing a word from a STR instruction. * -\***************************************************************************/ +/* This function does the work of storing a word from a STR instruction. */ static unsigned StoreWord (ARMul_State * state, ARMword instr, ARMword address) @@ -4248,15 +4253,13 @@ StoreWord (ARMul_State * state, ARMword instr, ARMword address) if (state->Aborted) { TAKEABORT; - return (state->lateabtSig); + return state->lateabtSig; } - return (TRUE); + return TRUE; } #ifdef MODET -/***************************************************************************\ -* This function does the work of storing a byte for a STRH instruction. * -\***************************************************************************/ +/* This function does the work of storing a byte for a STRH instruction. */ static unsigned StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address) @@ -4283,17 +4286,15 @@ StoreHalfWord (ARMul_State * state, ARMword instr, ARMword address) if (state->Aborted) { TAKEABORT; - return (state->lateabtSig); + return state->lateabtSig; } - return (TRUE); + return TRUE; } #endif /* MODET */ -/***************************************************************************\ -* This function does the work of storing a byte for a STRB instruction. * -\***************************************************************************/ +/* This function does the work of storing a byte for a STRB instruction. */ static unsigned StoreByte (ARMul_State * state, ARMword instr, ARMword address) @@ -4320,15 +4321,13 @@ StoreByte (ARMul_State * state, ARMword instr, ARMword address) return (state->lateabtSig); } UNDEF_LSRBPC; - return (TRUE); + return TRUE; } -/***************************************************************************\ -* This function does the work of loading the registers listed in an LDM * -* instruction, when the S bit is clear. The code here is always increment * -* after, it's up to the caller to get the input address correct and to * -* handle base register modification. * -\***************************************************************************/ +/* This function does the work of loading the registers listed in an LDM + instruction, when the S bit is clear. The code here is always increment + after, it's up to the caller to get the input address correct and to + handle base register modification.a */ static void LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) @@ -4341,20 +4340,21 @@ LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) BUSUSEDINCPCS; #ifndef MODE32 if (ADDREXCEPT (address)) - { - INTERNALABORT (address); - } + INTERNALABORT (address); #endif if (BIT (21) && LHSReg != 15) LSBase = WBBase; - for (temp = 0; !BIT (temp); temp++); /* N cycle first */ + for (temp = 0; !BIT (temp); temp++) + ; /* N cycle first */ + dest = ARMul_LoadWordN (state, address); + if (!state->abortSig && !state->Aborted) state->Reg[temp++] = dest; else if (!state->Aborted) { - XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); + XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } @@ -4363,21 +4363,22 @@ LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) { /* load this register */ address += 4; dest = ARMul_LoadWordS (state, address); + if (!state->abortSig && !state->Aborted) state->Reg[temp] = dest; else if (!state->Aborted) { - XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); + XScale_set_fsr_far (state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } } if (BIT (15) && !state->Aborted) - { /* PC is in the reg list */ - WriteR15Branch(state, PC); - } + /* PC is in the reg list. */ + WriteR15Branch (state, PC); - ARMul_Icycles (state, 1, 0L); /* to write back the final register */ + /* To write back the final register. */ + ARMul_Icycles (state, 1, 0L); if (state->Aborted) { @@ -4387,12 +4388,10 @@ LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) } } -/***************************************************************************\ -* This function does the work of loading the registers listed in an LDM * -* instruction, when the S bit is set. The code here is always increment * -* after, it's up to the caller to get the input address correct and to * -* handle base register modification. * -\***************************************************************************/ +/* This function does the work of loading the registers listed in an LDM + instruction, when the S bit is set. The code here is always increment + after, it's up to the caller to get the input address correct and to + handle base register modification. */ static void LoadSMult (ARMul_State * state, @@ -4410,9 +4409,7 @@ LoadSMult (ARMul_State * state, #ifndef MODE32 if (ADDREXCEPT (address)) - { - INTERNALABORT (address); - } + INTERNALABORT (address); #endif if (BIT (21) && LHSReg != 15) @@ -4498,12 +4495,10 @@ LoadSMult (ARMul_State * state, } } -/***************************************************************************\ -* This function does the work of storing the registers listed in an STM * -* instruction, when the S bit is clear. The code here is always increment * -* after, it's up to the caller to get the input address correct and to * -* handle base register modification. * -\***************************************************************************/ +/* This function does the work of storing the registers listed in an STM + instruction, when the S bit is clear. The code here is always increment + after, it's up to the caller to get the input address correct and to + handle base register modification. */ static void StoreMult (ARMul_State * state, ARMword instr, @@ -4514,30 +4509,34 @@ StoreMult (ARMul_State * state, ARMword instr, UNDEF_LSMNoRegs; UNDEF_LSMPCBase; UNDEF_LSMBaseInListWb; + if (!TFLAG) - { - BUSUSEDINCPCN; /* N-cycle, increment the PC and update the NextInstr state */ - } + /* N-cycle, increment the PC and update the NextInstr state. */ + BUSUSEDINCPCN; #ifndef MODE32 if (VECTORACCESS (address) || ADDREXCEPT (address)) - { - INTERNALABORT (address); - } + INTERNALABORT (address); + if (BIT (15)) PATCHR15; #endif - for (temp = 0; !BIT (temp); temp++); /* N cycle first */ + for (temp = 0; !BIT (temp); temp++) + ; /* N cycle first. */ + #ifdef MODE32 ARMul_StoreWordN (state, address, state->Reg[temp++]); #else if (state->Aborted) { (void) ARMul_LoadWordN (state, address); - for (; temp < 16; temp++) /* Fake the Stores as Loads */ + + /* Fake the Stores as Loads. */ + for (; temp < 16; temp++) if (BIT (temp)) - { /* save this register */ + { + /* Save this register. */ address += 4; (void) ARMul_LoadWordS (state, address); } @@ -4561,7 +4560,8 @@ StoreMult (ARMul_State * state, ARMword instr, for (; temp < 16; temp++) /* S cycles from here on */ if (BIT (temp)) - { /* save this register */ + { + /* Save this register. */ address += 4; ARMul_StoreWordS (state, address, state->Reg[temp]); @@ -4574,17 +4574,13 @@ StoreMult (ARMul_State * state, ARMword instr, } if (state->Aborted) - { - TAKEABORT; - } + TAKEABORT; } -/***************************************************************************\ -* This function does the work of storing the registers listed in an STM * -* instruction when the S bit is set. The code here is always increment * -* after, it's up to the caller to get the input address correct and to * -* handle base register modification. * -\***************************************************************************/ +/* This function does the work of storing the registers listed in an STM + instruction when the S bit is set. The code here is always increment + after, it's up to the caller to get the input address correct and to + handle base register modification. */ static void StoreSMult (ARMul_State * state, @@ -4602,9 +4598,7 @@ StoreSMult (ARMul_State * state, #ifndef MODE32 if (VECTORACCESS (address) || ADDREXCEPT (address)) - { - INTERNALABORT (address); - } + INTERNALABORT (address); if (BIT (15)) PATCHR15; @@ -4678,15 +4672,11 @@ StoreSMult (ARMul_State * state, LSBase = WBBase; if (state->Aborted) - { - TAKEABORT; - } + TAKEABORT; } -/***************************************************************************\ -* This function does the work of adding two 32bit values together, and * -* calculating if a carry has occurred. * -\***************************************************************************/ +/* This function does the work of adding two 32bit values + together, and calculating if a carry has occurred. */ static ARMword Add32 (ARMword a1, ARMword a2, int *carry) @@ -4705,33 +4695,37 @@ Add32 (ARMword a1, ARMword a2, int *carry) return (result); } -/***************************************************************************\ -* This function does the work of multiplying two 32bit values to give a * -* 64bit result. * -\***************************************************************************/ +/* This function does the work of multiplying + two 32bit values to give a 64bit result. */ static unsigned Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) { - int nRdHi, nRdLo, nRs, nRm; /* operand register numbers */ + /* Operand register numbers. */ + int nRdHi, nRdLo, nRs, nRm; ARMword RdHi = 0, RdLo = 0, Rm; - int scount; /* cycle count */ + /* Cycle count. */ + int scount; nRdHi = BITS (16, 19); nRdLo = BITS (12, 15); nRs = BITS (8, 11); nRm = BITS (0, 3); - /* Needed to calculate the cycle count: */ + /* Needed to calculate the cycle count. */ Rm = state->Reg[nRm]; - /* Check for illegal operand combinations first: */ - if (nRdHi != 15 + /* Check for illegal operand combinations first. */ + if ( nRdHi != 15 && nRdLo != 15 - && nRs != 15 - && nRm != 15 && nRdHi != nRdLo && nRdHi != nRm && nRdLo != nRm) + && nRs != 15 + && nRm != 15 + && nRdHi != nRdLo + && nRdHi != nRm + && nRdLo != nRm) { - ARMword lo, mid1, mid2, hi; /* intermediate results */ + /* Intermediate results. */ + ARMword lo, mid1, mid2, hi; int carry; ARMword Rs = state->Reg[nRs]; int sign = 0; @@ -4749,15 +4743,15 @@ Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) Rs = -Rs; } - /* We can split the 32x32 into four 16x16 operations. This ensures - that we do not lose precision on 32bit only hosts: */ + /* We can split the 32x32 into four 16x16 operations. This + ensures that we do not lose precision on 32bit only hosts. */ lo = ((Rs & 0xFFFF) * (Rm & 0xFFFF)); mid1 = ((Rs & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); mid2 = (((Rs >> 16) & 0xFFFF) * (Rm & 0xFFFF)); hi = (((Rs >> 16) & 0xFFFF) * ((Rm >> 16) & 0xFFFF)); - /* We now need to add all of these results together, taking care - to propogate the carries from the additions: */ + /* We now need to add all of these results together, taking + care to propogate the carries from the additions. */ RdLo = Add32 (lo, (mid1 << 16), &carry); RdHi = carry; RdLo = Add32 (RdLo, (mid2 << 16), &carry); @@ -4778,24 +4772,26 @@ Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) else RdLo += 1; } + /* Else undefined result. */ state->Reg[nRdLo] = RdLo; state->Reg[nRdHi] = RdHi; - } /* else undefined result */ + } else fprintf (stderr, "sim: MULTIPLY64 - INVALID ARGUMENTS\n"); if (scc) { - /* Ensure that both RdHi and RdLo are used to compute Z, but - don't let RdLo's sign bit make it to N. */ + /* Ensure that both RdHi and RdLo are used to compute Z, + but don't let RdLo's sign bit make it to N. */ ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); } /* The cycle count depends on whether the instruction is a signed or - unsigned multiply, and what bits are clear in the multiplier: */ + unsigned multiply, and what bits are clear in the multiplier. */ if (msigned && (Rm & ((unsigned) 1 << 31))) - Rm = ~Rm; /* invert the bits to make the check against zero */ + /* Invert the bits to make the check against zero. */ + Rm = ~Rm; if ((Rm & 0xFFFFFF00) == 0) scount = 1; @@ -4809,10 +4805,8 @@ Multiply64 (ARMul_State * state, ARMword instr, int msigned, int scc) return 2 + scount; } -/***************************************************************************\ -* This function does the work of multiplying two 32bit values and adding * -* a 64bit value to give a 64bit result. * -\***************************************************************************/ +/* This function does the work of multiplying two 32bit + values and adding a 64bit value to give a 64bit result. */ static unsigned MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc) @@ -4837,11 +4831,10 @@ MultiplyAdd64 (ARMul_State * state, ARMword instr, int msigned, int scc) state->Reg[nRdHi] = RdHi; if (scc) - { - /* Ensure that both RdHi and RdLo are used to compute Z, but - don't let RdLo's sign bit make it to N. */ - ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); - } + /* Ensure that both RdHi and RdLo are used to compute Z, + but don't let RdLo's sign bit make it to N. */ + ARMul_NegZero (state, RdHi | (RdLo >> 16) | (RdLo & 0xFFFF)); - return scount + 1; /* extra cycle for addition */ + /* Extra cycle for addition. */ + return scount + 1; } diff --git a/sim/arm/armemu.h b/sim/arm/armemu.h index 009e9c8771a..ec20575b73d 100644 --- a/sim/arm/armemu.h +++ b/sim/arm/armemu.h @@ -17,10 +17,7 @@ extern ARMword isize; -/***************************************************************************\ -* Condition code values * -\***************************************************************************/ - +/* Condition code values. */ #define EQ 0 #define NE 1 #define CS 2 @@ -38,19 +35,13 @@ extern ARMword isize; #define AL 14 #define NV 15 -/***************************************************************************\ -* Shift Opcodes * -\***************************************************************************/ - +/* Shift Opcodes. */ #define LSL 0 #define LSR 1 #define ASR 2 #define ROR 3 -/***************************************************************************\ -* Macros to twiddle the status flags and mode * -\***************************************************************************/ - +/* Macros to twiddle the status flags and mode. */ #define NBIT ((unsigned)1L << 31) #define ZBIT (1L << 30) #define CBIT (1L << 29) @@ -66,7 +57,7 @@ extern ARMword isize; #define POS(i) ( (~(i)) >> 31 ) #define NEG(i) ( (i) >> 31 ) -#ifdef MODET /* Thumb support */ +#ifdef MODET /* Thumb support. */ /* ??? This bit is actually in the low order bit of the PC in the hardware. It isn't clear if the simulator needs to model that or not. */ #define TBIT (1L << 5) @@ -181,95 +172,130 @@ extern ARMword isize; #define SETPSR_S(d,s) d = ((d) & ~PSR_SBITS) | ((s) & PSR_SBITS) #define SETPSR_X(d,s) d = ((d) & ~PSR_XBITS) | ((s) & PSR_XBITS) #define SETPSR_C(d,s) d = ((d) & ~PSR_CBITS) | ((s) & PSR_CBITS) -#define SETR15PSR(s) if (state->Mode == USER26MODE) { \ - state->Reg[15] = ((s) & CCBITS) | R15PC | ER15INT | EMODE ; \ - ASSIGNN((state->Reg[15] & NBIT) != 0) ; \ - ASSIGNZ((state->Reg[15] & ZBIT) != 0) ; \ - ASSIGNC((state->Reg[15] & CBIT) != 0) ; \ - ASSIGNV((state->Reg[15] & VBIT) != 0) ; \ - } \ - else { \ - state->Reg[15] = R15PC | ((s) & (CCBITS | R15INTBITS | R15MODEBITS)) ; \ - ARMul_R15Altered (state) ; \ - } -#define SETABORT(i,m,d) do { \ - int SETABORT_mode = (m); \ - ARMul_SetSPSR (state, SETABORT_mode, ARMul_GetCPSR (state)); \ - ARMul_SetCPSR (state, ((ARMul_GetCPSR (state) & ~(EMODE | TBIT)) \ - | (i) | SETABORT_mode)); \ - state->Reg[14] = temp - (d); \ -} while (0) + +#define SETR15PSR(s) \ + do \ + { \ + if (state->Mode == USER26MODE) \ + { \ + state->Reg[15] = ((s) & CCBITS) | R15PC | ER15INT | EMODE; \ + ASSIGNN ((state->Reg[15] & NBIT) != 0); \ + ASSIGNZ ((state->Reg[15] & ZBIT) != 0); \ + ASSIGNC ((state->Reg[15] & CBIT) != 0); \ + ASSIGNV ((state->Reg[15] & VBIT) != 0); \ + } \ + else \ + { \ + state->Reg[15] = R15PC | ((s) & (CCBITS | R15INTBITS | R15MODEBITS)); \ + ARMul_R15Altered (state); \ + } \ + } \ + while (0) + +#define SETABORT(i, m, d) \ + do \ + { \ + int SETABORT_mode = (m); \ + \ + ARMul_SetSPSR (state, SETABORT_mode, ARMul_GetCPSR (state)); \ + ARMul_SetCPSR (state, ((ARMul_GetCPSR (state) & ~(EMODE | TBIT)) \ + | (i) | SETABORT_mode)); \ + state->Reg[14] = temp - (d); \ + } \ + while (0) #ifndef MODE32 #define VECTORS 0x20 #define LEGALADDR 0x03ffffff #define VECTORACCESS(address) (address < VECTORS && ARMul_MODE26BIT && state->prog32Sig) -#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig) +#define ADDREXCEPT(address) (address > LEGALADDR && !state->data32Sig) #endif -#define INTERNALABORT(address) if (address < VECTORS) \ - state->Aborted = ARMul_DataAbortV ; \ - else \ - state->Aborted = ARMul_AddrExceptnV ; +#define INTERNALABORT(address) \ + do \ + { \ + if (address < VECTORS) \ + state->Aborted = ARMul_DataAbortV; \ + else \ + state->Aborted = ARMul_AddrExceptnV; \ + } \ + while (0) #ifdef MODE32 -#define TAKEABORT ARMul_Abort(state,ARMul_DataAbortV) +#define TAKEABORT ARMul_Abort (state, ARMul_DataAbortV) #else -#define TAKEABORT if (state->Aborted == ARMul_AddrExceptnV) \ - ARMul_Abort(state,ARMul_AddrExceptnV) ; \ - else \ - ARMul_Abort(state,ARMul_DataAbortV) +#define TAKEABORT \ + do \ + { \ + if (state->Aborted == ARMul_AddrExceptnV) \ + ARMul_Abort (state, ARMul_AddrExceptnV); \ + else \ + ARMul_Abort (state, ARMul_DataAbortV); \ + } \ + while (0) #endif -#define CPTAKEABORT if (!state->Aborted) \ - ARMul_Abort(state,ARMul_UndefinedInstrV) ; \ - else if (state->Aborted == ARMul_AddrExceptnV) \ - ARMul_Abort(state,ARMul_AddrExceptnV) ; \ - else \ - ARMul_Abort(state,ARMul_DataAbortV) - - -/***************************************************************************\ -* Different ways to start the next instruction * -\***************************************************************************/ -#define SEQ 0 -#define NONSEQ 1 -#define PCINCEDSEQ 2 +#define CPTAKEABORT \ + do \ + { \ + if (!state->Aborted) \ + ARMul_Abort (state, ARMul_UndefinedInstrV); \ + else if (state->Aborted == ARMul_AddrExceptnV) \ + ARMul_Abort (state, ARMul_AddrExceptnV); \ + else \ + ARMul_Abort (state, ARMul_DataAbortV); \ + } \ + while (0); + + +/* Different ways to start the next instruction. */ +#define SEQ 0 +#define NONSEQ 1 +#define PCINCEDSEQ 2 #define PCINCEDNONSEQ 3 -#define PRIMEPIPE 4 -#define RESUME 8 +#define PRIMEPIPE 4 +#define RESUME 8 #define NORMALCYCLE state->NextInstr = 0 #define BUSUSEDN state->NextInstr |= 1 /* The next fetch will be an N cycle. */ -#define BUSUSEDINCPCS \ - do \ - { \ - if (! state->is_v4) \ - { \ - state->Reg[15] += isize ; /* A standard PC inc and an S cycle. */ \ - state->NextInstr = (state->NextInstr & 0xff) | 2; \ - } \ - } \ +#define BUSUSEDINCPCS \ + do \ + { \ + if (! state->is_v4) \ + { \ + /* A standard PC inc and an S cycle. */ \ + state->Reg[15] += isize; \ + state->NextInstr = (state->NextInstr & 0xff) | 2; \ + } \ + } \ while (0) -#define BUSUSEDINCPCN \ - do \ - { \ - if (state->is_v4) \ - BUSUSEDN; \ - else \ - { \ - state->Reg[15] += isize ; /* A standard PC inc and an N cycle. */ \ - state->NextInstr |= 3; \ - } \ - } \ + +#define BUSUSEDINCPCN \ + do \ + { \ + if (state->is_v4) \ + BUSUSEDN; \ + else \ + { \ + /* A standard PC inc and an N cycle. */ \ + state->Reg[15] += isize; \ + state->NextInstr |= 3; \ + } \ + } \ while (0) -#define INCPC state->Reg[15] += isize ; /* a standard PC inc */ \ - state->NextInstr |= 2 + +#define INCPC \ + do \ + { \ + /* A standard PC inc. */ \ + state->Reg[15] += isize; \ + state->NextInstr |= 2; \ + } \ + while (0) + #define FLUSHPIPE state->NextInstr |= PRIMEPIPE -/***************************************************************************\ -* Cycle based emulation * -\***************************************************************************/ +/* Cycle based emulation. */ #define OUTPUTCP(i,a,b) #define NCYCLE @@ -278,15 +304,7 @@ extern ARMword isize; #define CCYCLE #define NEXTCYCLE(c) -/***************************************************************************\ -* States of the cycle based state machine * -\***************************************************************************/ - - -/***************************************************************************\ -* Macros to extract parts of instructions * -\***************************************************************************/ - +/* Macros to extract parts of instructions. */ #define DESTReg (BITS(12,15)) #define LHSReg (BITS(16,19)) #define RHSReg (BITS(0,3)) @@ -300,77 +318,78 @@ extern ARMword isize; #define LHS (state->Reg[LHSReg]) #endif #else -#define LHS ((LHSReg == 15) ? R15PC : (state->Reg[LHSReg]) ) +#define LHS ((LHSReg == 15) ? R15PC : (state->Reg[LHSReg])) #endif -#define MULDESTReg (BITS(16,19)) -#define MULLHSReg (BITS(0,3)) -#define MULRHSReg (BITS(8,11)) -#define MULACCReg (BITS(12,15)) +#define MULDESTReg (BITS (16, 19)) +#define MULLHSReg (BITS ( 0, 3)) +#define MULRHSReg (BITS ( 8, 11)) +#define MULACCReg (BITS (12, 15)) -#define DPImmRHS (ARMul_ImmedTable[BITS(0,11)]) +#define DPImmRHS (ARMul_ImmedTable[BITS(0, 11)]) #define DPSImmRHS temp = BITS(0,11) ; \ rhs = ARMul_ImmedTable[temp] ; \ - if (temp > 255) /* there was a shift */ \ - ASSIGNC(rhs >> 31) ; + if (temp > 255) /* There was a shift. */ \ + ASSIGNC (rhs >> 31) ; #ifdef MODE32 -#define DPRegRHS ((BITS(4,11)==0) ? state->Reg[RHSReg] \ - : GetDPRegRHS(state, instr)) -#define DPSRegRHS ((BITS(4,11)==0) ? state->Reg[RHSReg] \ - : GetDPSRegRHS(state, instr)) +#define DPRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \ + : GetDPRegRHS (state, instr)) +#define DPSRegRHS ((BITS (4,11) == 0) ? state->Reg[RHSReg] \ + : GetDPSRegRHS (state, instr)) #else -#define DPRegRHS ((BITS(0,11)<15) ? state->Reg[RHSReg] \ - : GetDPRegRHS(state, instr)) -#define DPSRegRHS ((BITS(0,11)<15) ? state->Reg[RHSReg] \ - : GetDPSRegRHS(state, instr)) +#define DPRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \ + : GetDPRegRHS (state, instr)) +#define DPSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \ + : GetDPSRegRHS (state, instr)) #endif #define LSBase state->Reg[LHSReg] #define LSImmRHS (BITS(0,11)) #ifdef MODE32 -#define LSRegRHS ((BITS(4,11)==0) ? state->Reg[RHSReg] \ - : GetLSRegRHS(state, instr)) +#define LSRegRHS ((BITS (4, 11) == 0) ? state->Reg[RHSReg] \ + : GetLSRegRHS (state, instr)) #else -#define LSRegRHS ((BITS(0,11)<15) ? state->Reg[RHSReg] \ - : GetLSRegRHS(state, instr)) +#define LSRegRHS ((BITS (0, 11) < 15) ? state->Reg[RHSReg] \ + : GetLSRegRHS (state, instr)) #endif -#define LSMNumRegs ((ARMword)ARMul_BitList[BITS(0,7)] + \ - (ARMword)ARMul_BitList[BITS(8,15)] ) -#define LSMBaseFirst ((LHSReg == 0 && BIT(0)) || \ - (BIT(LHSReg) && BITS(0,LHSReg-1) == 0)) +#define LSMNumRegs ((ARMword) ARMul_BitList[BITS (0, 7)] + \ + (ARMword) ARMul_BitList[BITS (8, 15)] ) +#define LSMBaseFirst ((LHSReg == 0 && BIT (0)) || \ + (BIT (LHSReg) && BITS (0, LHSReg - 1) == 0)) #define SWAPSRC (state->Reg[RHSReg]) -#define LSCOff (BITS(0,7) << 2) -#define CPNum BITS(8,11) - -/***************************************************************************\ -* Macro to rotate n right by b bits * -\***************************************************************************/ +#define LSCOff (BITS (0, 7) << 2) +#define CPNum BITS (8, 11) -#define ROTATER(n,b) (((n)>>(b))|((n)<<(32-(b)))) +/* Determine if access to coprocessor CP is permitted. + The XScale has a register in CP15 which controls access to CP0 - CP13. */ +#define CP_ACCESS_ALLOWED(STATE, CP) \ + ( ((CP) >= 14) \ + || (! (STATE)->is_XScale) \ + || (read_cp15_reg (15, 0, 1) & (1 << (CP)))) -/***************************************************************************\ -* Macros to store results of instructions * -\***************************************************************************/ +/* Macro to rotate n right by b bits. */ +#define ROTATER(n, b) (((n) >> (b)) | ((n) << (32 - (b)))) -#define WRITEDEST(d) if (DESTReg==15) \ - WriteR15(state, d) ; \ +/* Macros to store results of instructions. */ +#define WRITEDEST(d) if (DESTReg == 15) \ + WriteR15 (state, d) ; \ else \ DEST = d #define WRITESDEST(d) if (DESTReg == 15) \ - WriteSR15(state, d) ; \ + WriteSR15 (state, d) ; \ else { \ DEST = d ; \ - ARMul_NegZero(state, d) ; \ + ARMul_NegZero (state, d) ; \ } #define WRITEDESTB(d) if (DESTReg == 15) \ - WriteR15Branch(state, d) ; \ + WriteR15Branch (state, d) ; \ else \ DEST = d @@ -378,87 +397,46 @@ extern ARMword isize; ((data & 0xff) << 8) | \ ((data & 0xff) << 16) | \ ((data & 0xff) << 24)) -#define BUSTOBYTE(address,data) \ + +#define BUSTOBYTE(address, data) \ if (state->bigendSig) \ temp = (data >> (((address ^ 3) & 3) << 3)) & 0xff ; \ else \ temp = (data >> ((address & 3) << 3)) & 0xff -#define LOADMULT(instr,address,wb) LoadMult(state,instr,address,wb) -#define LOADSMULT(instr,address,wb) LoadSMult(state,instr,address,wb) -#define STOREMULT(instr,address,wb) StoreMult(state,instr,address,wb) -#define STORESMULT(instr,address,wb) StoreSMult(state,instr,address,wb) +#define LOADMULT(instr, address, wb) LoadMult (state, instr, address, wb) +#define LOADSMULT(instr, address, wb) LoadSMult (state, instr, address, wb) +#define STOREMULT(instr, address, wb) StoreMult (state, instr, address, wb) +#define STORESMULT(instr, address, wb) StoreSMult (state, instr, address, wb) #define POSBRANCH ((instr & 0x7fffff) << 2) #define NEGBRANCH ((0xff000000 |(instr & 0xffffff)) << 2) -/***************************************************************************\ -* Values for Emulate * -\***************************************************************************/ +/* Values for Emulate. */ #define STOP 0 /* stop */ #define CHANGEMODE 1 /* change mode */ #define ONCE 2 /* execute just one interation */ #define RUN 3 /* continuous execution */ -/***************************************************************************\ -* Stuff that is shared across modes * -\***************************************************************************/ - -extern ARMword ARMul_Emulate26 (ARMul_State * state); -extern ARMword ARMul_Emulate32 (ARMul_State * state); -extern unsigned ARMul_MultTable[]; /* Number of I cycles for a mult */ -extern ARMword ARMul_ImmedTable[]; /* immediate DP LHS values */ -extern char ARMul_BitList[]; /* number of bits in a byte table */ -extern void ARMul_Abort26 (ARMul_State * state, ARMword); -extern void ARMul_Abort32 (ARMul_State * state, ARMword); -extern unsigned ARMul_NthReg (ARMword instr, unsigned number); -extern void ARMul_MSRCpsr (ARMul_State * state, ARMword instr, ARMword rhs); -extern void ARMul_NegZero (ARMul_State * state, ARMword result); -extern void ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, - ARMword result); -extern int AddOverflow (ARMword a, ARMword b, ARMword result); -extern int SubOverflow (ARMword a, ARMword b, ARMword result); -extern void ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, - ARMword result); -extern void ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, - ARMword result); -extern void ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, - ARMword result); -extern void ARMul_CPSRAltered (ARMul_State * state); -extern void ARMul_R15Altered (ARMul_State * state); -extern ARMword ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, - ARMword newmode); -extern unsigned ARMul_NthReg (ARMword instr, unsigned number); -extern void ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address); -extern void ARMul_STC (ARMul_State * state, ARMword instr, ARMword address); -extern void ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source); -extern ARMword ARMul_MRC (ARMul_State * state, ARMword instr); -extern void ARMul_CDP (ARMul_State * state, ARMword instr); -extern unsigned IntPending (ARMul_State * state); -extern ARMword ARMul_Align (ARMul_State * state, ARMword address, - ARMword data); -#define EVENTLISTSIZE 1024L +/* Stuff that is shared across modes. */ +extern unsigned ARMul_MultTable[]; /* Number of I cycles for a mult. */ +extern ARMword ARMul_ImmedTable[]; /* Immediate DP LHS values. */ +extern char ARMul_BitList[]; /* Number of bits in a byte table. */ -/* Thumb support: */ +#define EVENTLISTSIZE 1024L +/* Thumb support. */ typedef enum { - t_undefined, /* undefined Thumb instruction */ - t_decoded, /* instruction decoded to ARM equivalent */ - t_branch /* Thumb branch (already processed) */ + t_undefined, /* Undefined Thumb instruction. */ + t_decoded, /* Instruction decoded to ARM equivalent. */ + t_branch /* Thumb branch (already processed). */ } tdstate; -extern tdstate ARMul_ThumbDecode (ARMul_State * state, ARMword pc, - ARMword tinstr, ARMword * ainstr); - -/***************************************************************************\ -* Macros to scrutinize instructions * -\***************************************************************************/ - - +/* Macros to scrutinize instructions. */ #define UNDEF_Test #define UNDEF_Shift #define UNDEF_MSRPC @@ -484,13 +462,52 @@ extern tdstate ARMul_ThumbDecode (ARMul_State * state, ARMword pc, #define UNDEF_Prog32SigChange #define UNDEF_Data32SigChange +/* Prototypes for exported functions. */ +extern unsigned ARMul_NthReg (ARMword, unsigned); +extern int AddOverflow (ARMword, ARMword, ARMword); +extern int SubOverflow (ARMword, ARMword, ARMword); +extern ARMword ARMul_Emulate26 (ARMul_State *); +extern ARMword ARMul_Emulate32 (ARMul_State *); +extern unsigned IntPending (ARMul_State *); +extern void ARMul_CPSRAltered (ARMul_State *); +extern void ARMul_R15Altered (ARMul_State *); +extern ARMword ARMul_GetPC (ARMul_State *); +extern ARMword ARMul_GetNextPC (ARMul_State *); +extern ARMword ARMul_GetR15 (ARMul_State *); +extern ARMword ARMul_GetCPSR (ARMul_State *); +extern void ARMul_EnvokeEvent (ARMul_State *); +extern unsigned long ARMul_Time (ARMul_State *); +extern void ARMul_NegZero (ARMul_State *, ARMword); +extern void ARMul_SetPC (ARMul_State *, ARMword); +extern void ARMul_SetR15 (ARMul_State *, ARMword); +extern void ARMul_SetCPSR (ARMul_State *, ARMword); +extern ARMword ARMul_GetSPSR (ARMul_State *, ARMword); +extern void ARMul_Abort26 (ARMul_State *, ARMword); +extern void ARMul_Abort32 (ARMul_State *, ARMword); +extern ARMword ARMul_MRC (ARMul_State *, ARMword); +extern void ARMul_CDP (ARMul_State *, ARMword); +extern void ARMul_LDC (ARMul_State *, ARMword, ARMword); +extern void ARMul_STC (ARMul_State *, ARMword, ARMword); +extern void ARMul_MCR (ARMul_State *, ARMword, ARMword); +extern void ARMul_SetSPSR (ARMul_State *, ARMword, ARMword); +extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword); +extern ARMword ARMul_Align (ARMul_State *, ARMword, ARMword); +extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword); +extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword); +extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword); +extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword); +extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword); +extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword); +extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *); +extern ARMword ARMul_GetReg (ARMul_State *, unsigned, unsigned); +extern void ARMul_SetReg (ARMul_State *, unsigned, unsigned, ARMword); +extern void ARMul_ScheduleEvent (ARMul_State *, unsigned long, unsigned (*) (ARMul_State *)); /* Coprocessor support functions. */ -extern unsigned ARMul_CoProInit (ARMul_State *); -extern void ARMul_CoProExit (ARMul_State *); -extern void ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *, ARMul_CPExits *, - ARMul_LDCs *, ARMul_STCs *, ARMul_MRCs *, ARMul_MCRs *, - ARMul_CDPs *, ARMul_CPReads *, ARMul_CPWrites *); -extern void ARMul_CoProDetach (ARMul_State *, unsigned); -extern void write_cp15_reg (ARMul_State *, unsigned, unsigned, unsigned, ARMword); -extern void write_cp14_reg (unsigned, ARMword); -extern ARMword read_cp14_reg (unsigned); +extern unsigned ARMul_CoProInit (ARMul_State *); +extern void ARMul_CoProExit (ARMul_State *); +extern void ARMul_CoProAttach (ARMul_State *, unsigned, ARMul_CPInits *, ARMul_CPExits *, + ARMul_LDCs *, ARMul_STCs *, ARMul_MRCs *, ARMul_MCRs *, + ARMul_CDPs *, ARMul_CPReads *, ARMul_CPWrites *); +extern void ARMul_CoProDetach (ARMul_State *, unsigned); +extern ARMword read_cp15_reg (unsigned, unsigned, unsigned); + diff --git a/sim/arm/armsupp.c b/sim/arm/armsupp.c index 99b6099b3c3..027a9622134 100644 --- a/sim/arm/armsupp.c +++ b/sim/arm/armsupp.c @@ -19,68 +19,18 @@ #include "armemu.h" #include "ansidecl.h" -/***************************************************************************\ -* Definitions for the support routines * -\***************************************************************************/ - -ARMword ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg); -void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, - ARMword value); -ARMword ARMul_GetPC (ARMul_State * state); -ARMword ARMul_GetNextPC (ARMul_State * state); -void ARMul_SetPC (ARMul_State * state, ARMword value); -ARMword ARMul_GetR15 (ARMul_State * state); -void ARMul_SetR15 (ARMul_State * state, ARMword value); - -ARMword ARMul_GetCPSR (ARMul_State * state); -void ARMul_SetCPSR (ARMul_State * state, ARMword value); -ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode); -void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value); - -void ARMul_CPSRAltered (ARMul_State * state); -void ARMul_R15Altered (ARMul_State * state); - -ARMword ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, - ARMword newmode); -static ARMword ModeToBank (ARMword mode); - -unsigned ARMul_NthReg (ARMword instr, unsigned number); - -void ARMul_NegZero (ARMul_State * state, ARMword result); -void ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, - ARMword result); -void ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, - ARMword result); -void ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, - ARMword result); -void ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, - ARMword result); - -void ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address); -void ARMul_STC (ARMul_State * state, ARMword instr, ARMword address); -void ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source); -ARMword ARMul_MRC (ARMul_State * state, ARMword instr); -void ARMul_CDP (ARMul_State * state, ARMword instr); -unsigned IntPending (ARMul_State * state); - -ARMword ARMul_Align (ARMul_State * state, ARMword address, ARMword data); - -void ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay, - unsigned (*what) ()); -void ARMul_EnvokeEvent (ARMul_State * state); -unsigned long ARMul_Time (ARMul_State * state); -static void EnvokeList (ARMul_State * state, unsigned long from, - unsigned long to); +/* Definitions for the support routines. */ + +static ARMword ModeToBank (ARMword); +static void EnvokeList (ARMul_State *, unsigned long, unsigned long); struct EventNode -{ /* An event list node */ - unsigned (*func) (); /* The function to call */ +{ /* An event list node. */ + unsigned (*func) (ARMul_State *); /* The function to call. */ struct EventNode *next; }; -/***************************************************************************\ -* This routine returns the value of a register from a mode. * -\***************************************************************************/ +/* This routine returns the value of a register from a mode. */ ARMword ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg) @@ -92,9 +42,7 @@ ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg) return (state->Reg[reg]); } -/***************************************************************************\ -* This routine sets the value of a register for a mode. * -\***************************************************************************/ +/* This routine sets the value of a register for a mode. */ void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value) @@ -106,35 +54,29 @@ ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value) state->Reg[reg] = value; } -/***************************************************************************\ -* This routine returns the value of the PC, mode independently. * -\***************************************************************************/ +/* This routine returns the value of the PC, mode independently. */ ARMword ARMul_GetPC (ARMul_State * state) { if (state->Mode > SVC26MODE) - return (state->Reg[15]); + return state->Reg[15]; else - return (R15PC); + return R15PC; } -/***************************************************************************\ -* This routine returns the value of the PC, mode independently. * -\***************************************************************************/ +/* This routine returns the value of the PC, mode independently. */ ARMword ARMul_GetNextPC (ARMul_State * state) { if (state->Mode > SVC26MODE) - return (state->Reg[15] + isize); + return state->Reg[15] + isize; else - return ((state->Reg[15] + isize) & R15PCBITS); + return (state->Reg[15] + isize) & R15PCBITS; } -/***************************************************************************\ -* This routine sets the value of the PC. * -\***************************************************************************/ +/* This routine sets the value of the PC. */ void ARMul_SetPC (ARMul_State * state, ARMword value) @@ -146,9 +88,7 @@ ARMul_SetPC (ARMul_State * state, ARMword value) FLUSHPIPE; } -/***************************************************************************\ -* This routine returns the value of register 15, mode independently. * -\***************************************************************************/ +/* This routine returns the value of register 15, mode independently. */ ARMword ARMul_GetR15 (ARMul_State * state) @@ -159,9 +99,7 @@ ARMul_GetR15 (ARMul_State * state) return (R15PC | ECC | ER15INT | EMODE); } -/***************************************************************************\ -* This routine sets the value of Register 15. * -\***************************************************************************/ +/* This routine sets the value of Register 15. */ void ARMul_SetR15 (ARMul_State * state, ARMword value) @@ -176,9 +114,7 @@ ARMul_SetR15 (ARMul_State * state, ARMword value) FLUSHPIPE; } -/***************************************************************************\ -* This routine returns the value of the CPSR * -\***************************************************************************/ +/* This routine returns the value of the CPSR. */ ARMword ARMul_GetCPSR (ARMul_State * state) @@ -186,9 +122,7 @@ ARMul_GetCPSR (ARMul_State * state) return (CPSR | state->Cpsr); } -/***************************************************************************\ -* This routine sets the value of the CPSR * -\***************************************************************************/ +/* This routine sets the value of the CPSR. */ void ARMul_SetCPSR (ARMul_State * state, ARMword value) @@ -197,10 +131,8 @@ ARMul_SetCPSR (ARMul_State * state, ARMword value) ARMul_CPSRAltered (state); } -/***************************************************************************\ -* This routine does all the nasty bits involved in a write to the CPSR, * -* including updating the register bank, given a MSR instruction. * -\***************************************************************************/ +/* This routine does all the nasty bits involved in a write to the CPSR, + including updating the register bank, given a MSR instruction. */ void ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) @@ -208,7 +140,8 @@ ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) state->Cpsr = ARMul_GetCPSR (state); if (state->Mode != USER26MODE && state->Mode != USER32MODE) - { /* In user mode, only write flags */ + { + /* In user mode, only write flags. */ if (BIT (16)) SETPSR_C (state->Cpsr, rhs); if (BIT (17)) @@ -221,9 +154,7 @@ ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) ARMul_CPSRAltered (state); } -/***************************************************************************\ -* Get an SPSR from the specified mode * -\***************************************************************************/ +/* Get an SPSR from the specified mode. */ ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode) @@ -236,9 +167,7 @@ ARMul_GetSPSR (ARMul_State * state, ARMword mode) return state->Spsr[bank]; } -/***************************************************************************\ -* This routine does a write to an SPSR * -\***************************************************************************/ +/* This routine does a write to an SPSR. */ void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) @@ -249,9 +178,7 @@ ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) state->Spsr[bank] = value; } -/***************************************************************************\ -* This routine does a write to the current SPSR, given an MSR instruction * -\***************************************************************************/ +/* This routine does a write to the current SPSR, given an MSR instruction. */ void ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs) @@ -269,10 +196,8 @@ ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs) } } -/***************************************************************************\ -* This routine updates the state of the emulator after the Cpsr has been * -* changed. Both the processor flags and register bank are updated. * -\***************************************************************************/ +/* This routine updates the state of the emulator after the Cpsr has been + changed. Both the processor flags and register bank are updated. */ void ARMul_CPSRAltered (ARMul_State * state) @@ -330,11 +255,9 @@ ARMul_CPSRAltered (ARMul_State * state) } } -/***************************************************************************\ -* This routine updates the state of the emulator after register 15 has * -* been changed. Both the processor flags and register bank are updated. * -* This routine should only be called from a 26 bit mode. * -\***************************************************************************/ +/* This routine updates the state of the emulator after register 15 has + been changed. Both the processor flags and register bank are updated. + This routine should only be called from a 26 bit mode. */ void ARMul_R15Altered (ARMul_State * state) @@ -344,22 +267,23 @@ ARMul_R15Altered (ARMul_State * state) state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE); state->NtransSig = (state->Mode & 3) ? HIGH : LOW; } + if (state->Mode > SVC26MODE) state->Emulate = CHANGEMODE; + ASSIGNR15INT (R15INT); + ASSIGNN ((state->Reg[15] & NBIT) != 0); ASSIGNZ ((state->Reg[15] & ZBIT) != 0); ASSIGNC ((state->Reg[15] & CBIT) != 0); ASSIGNV ((state->Reg[15] & VBIT) != 0); } -/***************************************************************************\ -* This routine controls the saving and restoring of registers across mode * -* changes. The regbank matrix is largely unused, only rows 13 and 14 are * -* used across all modes, 8 to 14 are used for FIQ, all others use the USER * -* column. It's easier this way. old and new parameter are modes numbers. * -* Notice the side effect of changing the Bank variable. * -\***************************************************************************/ +/* This routine controls the saving and restoring of registers across mode + changes. The regbank matrix is largely unused, only rows 13 and 14 are + used across all modes, 8 to 14 are used for FIQ, all others use the USER + column. It's easier this way. old and new parameter are modes numbers. + Notice the side effect of changing the Bank variable. */ ARMword ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) @@ -371,10 +295,12 @@ ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) oldbank = ModeToBank (oldmode); newbank = state->Bank = ModeToBank (newmode); + /* Do we really need to do it? */ if (oldbank != newbank) - { /* really need to do it */ + { + /* Save away the old registers. */ switch (oldbank) - { /* save away the old registers */ + { case USERBANK: case IRQBANK: case SVCBANK: @@ -398,8 +324,9 @@ ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) abort (); } + /* Restore the new registers. */ switch (newbank) - { /* restore the new registers */ + { case USERBANK: case IRQBANK: case SVCBANK: @@ -421,16 +348,14 @@ ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) break; default: abort (); - } /* switch */ - } /* if */ + } + } return newmode; } -/***************************************************************************\ -* Given a processor mode, this routine returns the register bank that * -* will be accessed in that mode. * -\***************************************************************************/ +/* Given a processor mode, this routine returns the + register bank that will be accessed in that mode. */ static ARMword ModeToBank (ARMword mode) @@ -453,24 +378,21 @@ ModeToBank (ARMword mode) return bankofmode[mode]; } -/***************************************************************************\ -* Returns the register number of the nth register in a reg list. * -\***************************************************************************/ +/* Returns the register number of the nth register in a reg list. */ unsigned ARMul_NthReg (ARMword instr, unsigned number) { unsigned bit, upto; - for (bit = 0, upto = 0; upto <= number; bit++) + for (bit = 0, upto = 0; upto <= number; bit ++) if (BIT (bit)) - upto++; + upto ++; + return (bit - 1); } -/***************************************************************************\ -* Assigns the N and Z flags depending on the value of result * -\***************************************************************************/ +/* Assigns the N and Z flags depending on the value of result. */ void ARMul_NegZero (ARMul_State * state, ARMword result) @@ -489,10 +411,11 @@ ARMul_NegZero (ARMul_State * state, ARMword result) { CLEARN; CLEARZ; - }; + } } /* Compute whether an addition of A and B, giving RESULT, overflowed. */ + int AddOverflow (ARMword a, ARMword b, ARMword result) { @@ -501,6 +424,7 @@ AddOverflow (ARMword a, ARMword b, ARMword result) } /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */ + int SubOverflow (ARMword a, ARMword b, ARMword result) { @@ -508,9 +432,7 @@ SubOverflow (ARMword a, ARMword b, ARMword result) || (POS (a) && NEG (b) && NEG (result))); } -/***************************************************************************\ -* Assigns the C flag after an addition of a and b to give result * -\***************************************************************************/ +/* Assigns the C flag after an addition of a and b to give result. */ void ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) @@ -519,9 +441,7 @@ ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) (NEG (a) && POS (result)) || (NEG (b) && POS (result))); } -/***************************************************************************\ -* Assigns the V flag after an addition of a and b to give result * -\***************************************************************************/ +/* Assigns the V flag after an addition of a and b to give result. */ void ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) @@ -529,9 +449,7 @@ ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) ASSIGNV (AddOverflow (a, b, result)); } -/***************************************************************************\ -* Assigns the C flag after an subtraction of a and b to give result * -\***************************************************************************/ +/* Assigns the C flag after an subtraction of a and b to give result. */ void ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) @@ -540,9 +458,7 @@ ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) (NEG (a) && POS (result)) || (POS (b) && POS (result))); } -/***************************************************************************\ -* Assigns the V flag after an subtraction of a and b to give result * -\***************************************************************************/ +/* Assigns the V flag after an subtraction of a and b to give result. */ void ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) @@ -550,12 +466,10 @@ ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) ASSIGNV (SubOverflow (a, b, result)); } -/***************************************************************************\ -* This function does the work of generating the addresses used in an * -* LDC instruction. The code here is always post-indexed, it's up to the * -* caller to get the input address correct and to handle base register * -* modification. It also handles the Busy-Waiting. * -\***************************************************************************/ +/* This function does the work of generating the addresses used in an + LDC instruction. The code here is always post-indexed, it's up to the + caller to get the input address correct and to handle base register + modification. It also handles the Busy-Waiting. */ void ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address) @@ -564,14 +478,21 @@ ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address) ARMword data; UNDEF_LSCPCBaseWb; - if (ADDREXCEPT (address)) + + if (! CP_ACCESS_ALLOWED (state, CPNum)) { - INTERNALABORT (address); + ARMul_UndefInstr (state, instr); + return; } + + if (ADDREXCEPT (address)) + INTERNALABORT (address); + cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0); while (cpab == ARMul_BUSY) { ARMul_Icycles (state, 1, 0); + if (IntPending (state)) { cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0); @@ -585,30 +506,30 @@ ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address) CPTAKEABORT; return; } + cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0); data = ARMul_LoadWordN (state, address); BUSUSEDINCPCN; + if (BIT (21)) LSBase = state->Base; cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); + while (cpab == ARMul_INC) { address += 4; data = ARMul_LoadWordN (state, address); cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); } + if (state->abortSig || state->Aborted) - { - TAKEABORT; - } + TAKEABORT; } -/***************************************************************************\ -* This function does the work of generating the addresses used in an * -* STC instruction. The code here is always post-indexed, it's up to the * -* caller to get the input address correct and to handle base register * -* modification. It also handles the Busy-Waiting. * -\***************************************************************************/ +/* This function does the work of generating the addresses used in an + STC instruction. The code here is always post-indexed, it's up to the + caller to get the input address correct and to handle base register + modification. It also handles the Busy-Waiting. */ void ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) @@ -617,10 +538,16 @@ ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) ARMword data; UNDEF_LSCPCBaseWb; - if (ADDREXCEPT (address) || VECTORACCESS (address)) + + if (! CP_ACCESS_ALLOWED (state, CPNum)) { - INTERNALABORT (address); + ARMul_UndefInstr (state, instr); + return; } + + if (ADDREXCEPT (address) || VECTORACCESS (address)) + INTERNALABORT (address); + cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data); while (cpab == ARMul_BUSY) { @@ -633,6 +560,7 @@ ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) else cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data); } + if (cpab == ARMul_CANT) { CPTAKEABORT; @@ -640,36 +568,39 @@ ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) } #ifndef MODE32 if (ADDREXCEPT (address) || VECTORACCESS (address)) - { - INTERNALABORT (address); - } + INTERNALABORT (address); + #endif BUSUSEDINCPCN; if (BIT (21)) LSBase = state->Base; cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); ARMul_StoreWordN (state, address, data); + while (cpab == ARMul_INC) { address += 4; cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); ARMul_StoreWordN (state, address, data); } + if (state->abortSig || state->Aborted) - { - TAKEABORT; - } + TAKEABORT; } -/***************************************************************************\ -* This function does the Busy-Waiting for an MCR instruction. * -\***************************************************************************/ +/* This function does the Busy-Waiting for an MCR instruction. */ void ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) { unsigned cpab; + if (! CP_ACCESS_ALLOWED (state, CPNum)) + { + ARMul_UndefInstr (state, instr); + return; + } + cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); while (cpab == ARMul_BUSY) @@ -694,9 +625,7 @@ ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) } } -/***************************************************************************\ -* This function does the Busy-Waiting for an MRC instruction. * -\***************************************************************************/ +/* This function does the Busy-Waiting for an MRC instruction. */ ARMword ARMul_MRC (ARMul_State * state, ARMword instr) @@ -704,6 +633,12 @@ ARMul_MRC (ARMul_State * state, ARMword instr) unsigned cpab; ARMword result = 0; + if (! CP_ACCESS_ALLOWED (state, CPNum)) + { + ARMul_UndefInstr (state, instr); + return; + } + cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result); while (cpab == ARMul_BUSY) { @@ -719,7 +654,8 @@ ARMul_MRC (ARMul_State * state, ARMword instr) if (cpab == ARMul_CANT) { ARMul_Abort (state, ARMul_UndefinedInstrV); - result = ECC; /* Parent will destroy the flags otherwise */ + /* Parent will destroy the flags otherwise. */ + result = ECC; } else { @@ -727,18 +663,23 @@ ARMul_MRC (ARMul_State * state, ARMword instr) ARMul_Ccycles (state, 1, 0); ARMul_Icycles (state, 1, 0); } - return (result); + + return result; } -/***************************************************************************\ -* This function does the Busy-Waiting for an CDP instruction. * -\***************************************************************************/ +/* This function does the Busy-Waiting for an CDP instruction. */ void ARMul_CDP (ARMul_State * state, ARMword instr) { unsigned cpab; + if (! CP_ACCESS_ALLOWED (state, CPNum)) + { + ARMul_UndefInstr (state, instr); + return; + } + cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr); while (cpab == ARMul_BUSY) { @@ -757,9 +698,7 @@ ARMul_CDP (ARMul_State * state, ARMword instr) BUSUSEDN; } -/***************************************************************************\ -* This function handles Undefined instructions, as CP isntruction * -\***************************************************************************/ +/* This function handles Undefined instructions, as CP isntruction. */ void ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED) @@ -767,37 +706,35 @@ ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED) ARMul_Abort (state, ARMul_UndefinedInstrV); } -/***************************************************************************\ -* Return TRUE if an interrupt is pending, FALSE otherwise. * -\***************************************************************************/ +/* Return TRUE if an interrupt is pending, FALSE otherwise. */ unsigned IntPending (ARMul_State * state) { if (state->Exception) - { /* Any exceptions */ + { + /* Any exceptions. */ if (state->NresetSig == LOW) { ARMul_Abort (state, ARMul_ResetV); - return (TRUE); + return TRUE; } else if (!state->NfiqSig && !FFLAG) { ARMul_Abort (state, ARMul_FIQV); - return (TRUE); + return TRUE; } else if (!state->NirqSig && !IFLAG) { ARMul_Abort (state, ARMul_IRQV); - return (TRUE); + return TRUE; } } - return (FALSE); + + return FALSE; } -/***************************************************************************\ -* Align a word access to a non word boundary * -\***************************************************************************/ +/* Align a word access to a non word boundary. */ ARMword ARMul_Align (state, address, data) @@ -808,20 +745,18 @@ ARMul_Align (state, address, data) /* This code assumes the address is really unaligned, as a shift by 32 is undefined in C. */ - address = (address & 3) << 3; /* get the word address */ + address = (address & 3) << 3; /* Get the word address. */ return ((data >> address) | (data << (32 - address))); /* rot right */ } -/***************************************************************************\ -* This routine is used to call another routine after a certain number of * -* cycles have been executed. The first parameter is the number of cycles * -* delay before the function is called, the second argument is a pointer * -* to the function. A delay of zero doesn't work, just call the function. * -\***************************************************************************/ +/* This routine is used to call another routine after a certain number of + cycles have been executed. The first parameter is the number of cycles + delay before the function is called, the second argument is a pointer + to the function. A delay of zero doesn't work, just call the function. */ void ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay, - unsigned (*what) ()) + unsigned (*what) (ARMul_State *)) { unsigned long when; struct EventNode *event; @@ -835,10 +770,8 @@ ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay, *(state->EventPtr + when) = event; } -/***************************************************************************\ -* This routine is called at the beginning of every cycle, to envoke * -* scheduled events. * -\***************************************************************************/ +/* This routine is called at the beginning of + every cycle, to envoke scheduled events. */ void ARMul_EnvokeEvent (ARMul_State * state) @@ -847,23 +780,26 @@ ARMul_EnvokeEvent (ARMul_State * state) then = state->Now; state->Now = ARMul_Time (state) % EVENTLISTSIZE; - if (then < state->Now) /* schedule events */ + if (then < state->Now) + /* Schedule events. */ EnvokeList (state, then, state->Now); else if (then > state->Now) - { /* need to wrap around the list */ + { + /* Need to wrap around the list. */ EnvokeList (state, then, EVENTLISTSIZE - 1L); EnvokeList (state, 0L, state->Now); } } +/* Envokes all the entries in a range. */ + static void EnvokeList (ARMul_State * state, unsigned long from, unsigned long to) -/* envokes all the entries in a range */ { - struct EventNode *anevent; - for (; from <= to; from++) { + struct EventNode *anevent; + anevent = *(state->EventPtr + from); while (anevent) { @@ -875,9 +811,7 @@ EnvokeList (ARMul_State * state, unsigned long from, unsigned long to) } } -/***************************************************************************\ -* This routine is returns the number of clock ticks since the last reset. * -\***************************************************************************/ +/* This routine is returns the number of clock ticks since the last reset. */ unsigned long ARMul_Time (ARMul_State * state) -- 2.30.2