diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm/insts/static_inst.cc | 111 | ||||
-rw-r--r-- | src/arch/arm/insts/static_inst.hh | 9 | ||||
-rw-r--r-- | src/arch/arm/isa/insts/branch64.isa | 95 | ||||
-rw-r--r-- | src/arch/arm/isa/operands.isa | 1 | ||||
-rw-r--r-- | src/arch/arm/miscregs.hh | 1 | ||||
-rw-r--r-- | src/arch/arm/utility.hh | 12 |
6 files changed, 144 insertions, 85 deletions
diff --git a/src/arch/arm/insts/static_inst.cc b/src/arch/arm/insts/static_inst.cc index d4ea1bcdf..3defc07c2 100644 --- a/src/arch/arm/insts/static_inst.cc +++ b/src/arch/arm/insts/static_inst.cc @@ -727,4 +727,115 @@ ArmStaticInst::checkAdvSIMDOrFPEnabled32(ThreadContext *tc, } +static uint8_t +getRestoredITBits(ThreadContext *tc, CPSR spsr) +{ + // See: shared/functions/system/RestoredITBits in the ARM ARM + + const ExceptionLevel el = opModeToEL((OperatingMode) (uint8_t)spsr.mode); + const uint8_t it = itState(spsr); + + if (!spsr.t || spsr.il) + return 0; + + // The IT bits are forced to zero when they are set to a reserved + // value. + if (bits(it, 7, 4) != 0 && bits(it, 3, 0) == 0) + return 0; + + const bool itd = el == EL2 ? + ((SCTLR)tc->readMiscReg(MISCREG_HSCTLR)).itd : + ((SCTLR)tc->readMiscReg(MISCREG_SCTLR)).itd; + + // The IT bits are forced to zero when returning to A32 state, or + // when returning to an EL with the ITD bit set to 1, and the IT + // bits are describing a multi-instruction block. + if (itd && bits(it, 2, 0) != 0) + return 0; + + return it; +} + +static bool +illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr) +{ + const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode; + if (badMode(mode)) + return true; + + const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode; + const ExceptionLevel target_el = opModeToEL(mode); + if (target_el > opModeToEL(cur_mode)) + return true; + + if (target_el == EL3 && !ArmSystem::haveSecurity(tc)) + return true; + + if (target_el == EL2 && !ArmSystem::haveVirtualization(tc)) + return true; + + if (!spsr.width) { + // aarch64 + if (!ArmSystem::highestELIs64(tc)) + return true; + + if (spsr & 0x2) + return true; + if (target_el == EL0 && spsr.sp) + return true; + if (target_el == EL2 && !((SCR)tc->readMiscReg(MISCREG_SCR_EL3)).ns) + return false; + } else { + return badMode32(mode); + } + + return false; +} + +CPSR +ArmStaticInst::getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const +{ + CPSR new_cpsr = 0; + + // gem5 doesn't implement single-stepping, so force the SS bit to + // 0. + new_cpsr.ss = 0; + + if (illegalExceptionReturn(tc, cpsr, spsr)) { + new_cpsr.il = 1; + } else { + new_cpsr.il = spsr.il; + if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) { + new_cpsr.il = 1; + } else if (spsr.width) { + new_cpsr.mode = spsr.mode; + } else { + new_cpsr.el = spsr.el; + new_cpsr.sp = spsr.sp; + } + } + + new_cpsr.nz = spsr.nz; + new_cpsr.c = spsr.c; + new_cpsr.v = spsr.v; + if (new_cpsr.width) { + // aarch32 + const ITSTATE it = getRestoredITBits(tc, spsr); + new_cpsr.q = spsr.q; + new_cpsr.ge = spsr.ge; + new_cpsr.e = spsr.e; + new_cpsr.aif = spsr.aif; + new_cpsr.t = spsr.t; + new_cpsr.it2 = it.top6; + new_cpsr.it1 = it.bottom2; + } else { + // aarch64 + new_cpsr.daif = spsr.daif; + } + + return new_cpsr; +} + + + } diff --git a/src/arch/arm/insts/static_inst.hh b/src/arch/arm/insts/static_inst.hh index 9ca64d1fe..55d16f69d 100644 --- a/src/arch/arm/insts/static_inst.hh +++ b/src/arch/arm/insts/static_inst.hh @@ -404,6 +404,15 @@ class ArmStaticInst : public StaticInst NSACR nsacr, FPEXC fpexc, bool fpexc_check, bool advsimd) const; + /** + * Get the new PSTATE from a SPSR register in preparation for an + * exception return. + * + * See shared/functions/system/SetPSTATEFromPSR in the ARM ARM + * psueodcode library. + */ + CPSR getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const; + public: virtual void annotateFault(ArmFault *fault) {} 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 ''' diff --git a/src/arch/arm/isa/operands.isa b/src/arch/arm/isa/operands.isa index 018c0956b..e48c154d4 100644 --- a/src/arch/arm/isa/operands.isa +++ b/src/arch/arm/isa/operands.isa @@ -440,6 +440,7 @@ def operands {{ 'NextJazelle': pcStateReg('nextJazelle', srtMode), 'NextItState': pcStateReg('nextItstate', srtMode), 'Itstate': pcStateReg('itstate', srtMode), + 'NextAArch64': pcStateReg('nextAArch64', srtMode), #Register operands depending on a field in the instruction encoding. These #should be avoided since they may not be portable across different diff --git a/src/arch/arm/miscregs.hh b/src/arch/arm/miscregs.hh index 025507673..84f0fe8d1 100644 --- a/src/arch/arm/miscregs.hh +++ b/src/arch/arm/miscregs.hh @@ -1376,6 +1376,7 @@ namespace ArmISA Bitfield<8> a; Bitfield<7> i; Bitfield<6> f; + Bitfield<8, 6> aif; Bitfield<9, 6> daif; // AArch64 Bitfield<5> t; Bitfield<4> width; // AArch64 diff --git a/src/arch/arm/utility.hh b/src/arch/arm/utility.hh index 8fb6558be..4b87dcc13 100644 --- a/src/arch/arm/utility.hh +++ b/src/arch/arm/utility.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2012-2013 ARM Limited + * Copyright (c) 2010, 2012-2013, 2016 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -161,6 +161,16 @@ bool ELIs64(ThreadContext *tc, ExceptionLevel el); bool isBigEndian64(ThreadContext *tc); +static inline uint8_t +itState(CPSR psr) +{ + ITSTATE it = 0; + it.top6 = psr.it2; + it.bottom2 = psr.it1; + + return (uint8_t)it; +} + /** * Removes the tag from tagged addresses if that mode is enabled. * @param addr The address to be purified. |