diff options
author | Andreas Sandberg <andreas.sandberg@arm.com> | 2016-06-02 13:41:26 +0100 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2016-06-02 13:41:26 +0100 |
commit | 660fbd543f7c84dec81cd17bdb4ff08f954aec77 (patch) | |
tree | a03fb18c83b32031b5331767e3067a026d641775 /src/arch/arm/isa/insts/branch64.isa | |
parent | f48ad5b29d6f291b4f3679ff5fb7b5beae10d6fa (diff) | |
download | gem5-660fbd543f7c84dec81cd17bdb4ff08f954aec77.tar.xz |
arm: Rewrite ERET to behave according to the ARMv8 ARM
The ERET instruction doesn't set PSTATE correctly in some cases
(particularly when returning to aarch32 code). Among other things,
this breaks EL0 thumb code when using a 64-bit kernel. This changeset
updates the ERET implementation to match the ARM ARM.
Change-Id: I408e7c69a23cce437859313dfe84e68744b07c98
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Nathanael Premillieu <nathanael.premillieu@arm.com>
Diffstat (limited to 'src/arch/arm/isa/insts/branch64.isa')
-rw-r--r-- | src/arch/arm/isa/insts/branch64.isa | 95 |
1 files changed, 11 insertions, 84 deletions
diff --git a/src/arch/arm/isa/insts/branch64.isa b/src/arch/arm/isa/insts/branch64.isa index 265eee9b6..64457b8c0 100644 --- a/src/arch/arm/isa/insts/branch64.isa +++ b/src/arch/arm/isa/insts/branch64.isa @@ -1,6 +1,6 @@ // -*- mode:c++ -*- -// Copyright (c) 2011-2013 ARM Limited +// Copyright (c) 2011-2013, 2016 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall @@ -127,92 +127,19 @@ let {{ else newPc = newPc & ~mask(2); } - spsr.q = 0; - spsr.it1 = 0; - spsr.j = 0; - spsr.res0_23_22 = 0; - spsr.ge = 0; - spsr.it2 = 0; - spsr.t = 0; - - OperatingMode mode = (OperatingMode) (uint8_t) spsr.mode; - bool illegal = false; - ExceptionLevel target_el; - if (badMode(mode)) { - illegal = true; - } else { - target_el = opModeToEL(mode); - if (((target_el == EL2) && - !ArmSystem::haveVirtualization(xc->tcBase())) || - (target_el > curr_el) || - (spsr.width == 1)) { - illegal = true; - } else { - bool known = true; - bool from32 = (spsr.width == 1); - bool to32 = false; - if (false) { // TODO: !haveAArch32EL - to32 = false; - } else if (!ArmSystem::highestELIs64(xc->tcBase())) { - to32 = true; - } else { - bool scr_rw, hcr_rw; - if (ArmSystem::haveSecurity(xc->tcBase())) { - SCR scr = xc->tcBase()->readMiscReg(MISCREG_SCR_EL3); - scr_rw = scr.rw; - } else { - scr_rw = true; - } - - if (ArmSystem::haveVirtualization(xc->tcBase())) { - HCR hcr = xc->tcBase()->readMiscReg(MISCREG_HCR_EL2); - hcr_rw = hcr.rw; - } else { - hcr_rw = scr_rw; - } - - switch (target_el) { - case EL3: - to32 = false; - break; - case EL2: - to32 = !scr_rw; - break; - case EL1: - to32 = !scr_rw || !hcr_rw; - break; - case EL0: - if (curr_el == EL0) { - to32 = cpsr.width; - } else if (!scr_rw || !hcr_rw) { - // EL0 using AArch32 if EL1 using AArch32 - to32 = true; - } else { - known = false; - to32 = false; - } - } - } - if (known) - illegal = (from32 != to32); - } - } - if (illegal) { - uint8_t old_mode = cpsr.mode; - spsr.mode = old_mode; // Preserve old mode when invalid - spsr.il = 1; - } else { - if (cpsr.width != spsr.width) - panic("AArch32/AArch64 interprocessing not supported yet"); - } - Cpsr = spsr; + CPSR new_cpsr = getPSTATEFromPSR(xc->tcBase(), cpsr, spsr); - CondCodesNZ = spsr.nz; - CondCodesC = spsr.c; - CondCodesV = spsr.v; + Cpsr = new_cpsr; + CondCodesNZ = new_cpsr.nz; + CondCodesC = new_cpsr.c; + CondCodesV = new_cpsr.v; + + NextAArch64 = !new_cpsr.width; + NextItState = itState(new_cpsr); NPC = purifyTaggedAddr(newPc, xc->tcBase(), - opModeToEL((OperatingMode) (uint8_t) spsr.mode)); + opModeToEL((OperatingMode) (uint8_t) new_cpsr.mode)); + LLSCLock = 0; // Clear exclusive monitor SevMailbox = 1; //Set Event Register ''' |