From 031f396c71e750fede19651ba3a14e262a87e117 Mon Sep 17 00:00:00 2001 From: Matt Horsnell Date: Thu, 17 Mar 2011 19:20:19 -0500 Subject: ARM: Fix RFE macrop. This changes the RFE macroop into 3 microops: URa = [sp]; URb = [sp+4]; // load CPSR,PC values from stack sp = sp + offset; // optionally auto-increment PC = URa; CPSR = URb; // write to the PC and CPSR. Importantly: - writing to PC is handled in the last micro-op. - loading occurs prior to state changes. --- src/arch/arm/isa/insts/ldr.isa | 25 +++++++++-------------- src/arch/arm/isa/insts/macromem.isa | 31 ++++++++++++++++++++++++++--- src/arch/arm/isa/insts/mem.isa | 25 +++++++++++++++++++---- src/arch/arm/isa/templates/macromem.isa | 35 +++++++++++++++++++++++++++++++++ src/arch/arm/isa/templates/mem.isa | 24 +++++++++++++--------- 5 files changed, 108 insertions(+), 32 deletions(-) (limited to 'src/arch/arm/isa') diff --git a/src/arch/arm/isa/insts/ldr.isa b/src/arch/arm/isa/insts/ldr.isa index c60a91a50..2e45f2875 100644 --- a/src/arch/arm/isa/insts/ldr.isa +++ b/src/arch/arm/isa/insts/ldr.isa @@ -67,7 +67,7 @@ let {{ self.memFlags = ["ArmISA::TLB::MustBeOne"] self.codeBlobs = {"postacc_code" : ""} - def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = []): + def emitHelper(self, base = 'Memory', wbDecl = None, instFlags = [], pcDecl = None): global header_output, decoder_output, exec_output @@ -76,7 +76,8 @@ let {{ (newHeader, newDecoder, newExec) = self.fillTemplates(self.name, self.Name, codeBlobs, - self.memFlags, instFlags, base, wbDecl) + self.memFlags, instFlags, base, + wbDecl, pcDecl) header_output += newHeader decoder_output += newDecoder @@ -104,26 +105,18 @@ let {{ wbDiff = 8 accCode = ''' CPSR cpsr = Cpsr; - SCTLR sctlr = Sctlr; - // Use the version of NPC that gets set before NextThumb - pNPC = cSwap(Mem.ud, cpsr.e); - uint32_t tempSpsr = cSwap(Mem.ud >> 32, cpsr.e); - uint32_t newCpsr = - cpsrWriteByInstr(cpsr | CondCodes, tempSpsr, - 0xF, true, sctlr.nmfi); - Cpsr = ~CondCodesMask & newCpsr; - NextThumb = ((CPSR)newCpsr).t; - NextJazelle = ((CPSR)newCpsr).j; - ForcedItState = ((((CPSR)tempSpsr).it2 << 2) & 0xFC) - | (((CPSR)tempSpsr).it1 & 0x3); - CondCodes = CondCodesMask & newCpsr; + URc = cpsr | CondCodes; + URa = cSwap(Mem.ud, cpsr.e); + URb = cSwap(Mem.ud >> 32, cpsr.e); ''' self.codeBlobs["memacc_code"] = accCode wbDecl = None + pcDecl = "MicroUopSetPCCPSR(machInst, INTREG_UREG0, INTREG_UREG1, INTREG_UREG2);" + if self.writeback: wbDecl = "MicroAddiUop(machInst, base, base, %d);" % wbDiff - self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"]) + self.emitHelper('RfeOp', wbDecl, ["IsSerializeAfter", "IsNonSpeculative"], pcDecl) class LoadImmInst(LoadInst): def __init__(self, *args, **kargs): diff --git a/src/arch/arm/isa/insts/macromem.isa b/src/arch/arm/isa/insts/macromem.isa index 0e3bcc648..d6c929353 100644 --- a/src/arch/arm/isa/insts/macromem.isa +++ b/src/arch/arm/isa/insts/macromem.isa @@ -608,23 +608,48 @@ let {{ 'predicate_test': predicateTest}, ['IsMicroop']) + setPCCPSRDecl = ''' + CPSR cpsrOrCondCodes = URc; + SCTLR sctlr = Sctlr; + pNPC = URa; + uint32_t newCpsr = + cpsrWriteByInstr(cpsrOrCondCodes, URb, + 0xF, true, sctlr.nmfi); + Cpsr = ~CondCodesMask & newCpsr; + NextThumb = ((CPSR)newCpsr).t; + NextJazelle = ((CPSR)newCpsr).j; + ForcedItState = ((((CPSR)URb).it2 << 2) & 0xFC) + | (((CPSR)URb).it1 & 0x3); + CondCodes = CondCodesMask & newCpsr; + ''' + + microUopSetPCCPSRIop = InstObjParams('uopSet_uop', 'MicroUopSetPCCPSR', + 'MicroSetPCCPSR', + {'code': setPCCPSRDecl, + 'predicate_test': predicateTest}, + ['IsMicroop']) + header_output = MicroIntImmDeclare.subst(microAddiUopIop) + \ MicroIntImmDeclare.subst(microSubiUopIop) + \ MicroIntRegDeclare.subst(microAddUopIop) + \ MicroIntRegDeclare.subst(microSubUopIop) + \ - MicroIntMovDeclare.subst(microUopRegMovIop) + MicroIntMovDeclare.subst(microUopRegMovIop) + \ + MicroSetPCCPSRDeclare.subst(microUopSetPCCPSRIop) decoder_output = MicroIntImmConstructor.subst(microAddiUopIop) + \ MicroIntImmConstructor.subst(microSubiUopIop) + \ MicroIntRegConstructor.subst(microAddUopIop) + \ MicroIntRegConstructor.subst(microSubUopIop) + \ - MicroIntMovConstructor.subst(microUopRegMovIop) + MicroIntMovConstructor.subst(microUopRegMovIop) + \ + MicroSetPCCPSRConstructor.subst(microUopSetPCCPSRIop) exec_output = PredOpExecute.subst(microAddiUopIop) + \ PredOpExecute.subst(microSubiUopIop) + \ PredOpExecute.subst(microAddUopIop) + \ PredOpExecute.subst(microSubUopIop) + \ - PredOpExecute.subst(microUopRegMovIop) + PredOpExecute.subst(microUopRegMovIop) + \ + PredOpExecute.subst(microUopSetPCCPSRIop) + }}; let {{ diff --git a/src/arch/arm/isa/insts/mem.isa b/src/arch/arm/isa/insts/mem.isa index 507f8cd4b..d0c0f0710 100644 --- a/src/arch/arm/isa/insts/mem.isa +++ b/src/arch/arm/isa/insts/mem.isa @@ -48,7 +48,7 @@ let {{ self.constructTemplate = eval(self.decConstBase + 'Constructor') def fillTemplates(self, name, Name, codeBlobs, memFlags, instFlags, - base = 'Memory', wbDecl = None): + base = 'Memory', wbDecl = None, pcDecl = None): # Make sure flags are in lists (convert to lists if not). memFlags = makeList(memFlags) instFlags = makeList(instFlags) @@ -65,12 +65,26 @@ let {{ macroName = Name instFlagsCopy = list(instFlags) codeBlobsCopy = dict(codeBlobs) - if wbDecl is not None: + + use_uops = 0 + if wbDecl is not None or pcDecl is not None: instFlagsCopy.append('IsMicroop') Name = Name + 'Acc' + use_uops = 1 + + use_wb = 0 + use_pc = 0 + if wbDecl is not None: + use_wb = 1 + if pcDecl is not None: + use_pc = 1 + codeBlobsCopy['acc_name'] = Name codeBlobsCopy['wb_decl'] = wbDecl + codeBlobsCopy['pc_decl'] = pcDecl codeBlobsCopy['use_uops'] = 0 + codeBlobsCopy['use_wb'] = 0 + codeBlobsCopy['use_pc'] = 0 iop = InstObjParams(name, Name, base, codeBlobsCopy, instFlagsCopy) @@ -81,11 +95,14 @@ let {{ self.initiateAccTemplate.subst(iop) + \ self.completeAccTemplate.subst(iop) - if wbDecl is not None: + if wbDecl is not None or pcDecl is not None: iop = InstObjParams(name, macroName, base, { "wb_decl" : wbDecl, + "pc_decl" : pcDecl, "acc_name" : Name, - "use_uops" : 1 }, + "use_uops" : use_uops, + "use_pc" : use_pc, + "use_wb" : use_wb }, ['IsMacroop']) header_output += self.declareTemplate.subst(iop) decoder_output += self.constructTemplate.subst(iop) diff --git a/src/arch/arm/isa/templates/macromem.isa b/src/arch/arm/isa/templates/macromem.isa index b7ca7fa48..a7f7f0da8 100644 --- a/src/arch/arm/isa/templates/macromem.isa +++ b/src/arch/arm/isa/templates/macromem.isa @@ -107,6 +107,41 @@ def template MicroNeonMemDeclare {{ }; }}; +//////////////////////////////////////////////////////////////////// +// +// PC = Integer(ura) +// CPSR = Integer(urb) +// + +def template MicroSetPCCPSRDeclare {{ + class %(class_name)s : public %(base_class)s + { + public: + %(class_name)s(ExtMachInst machInst, + IntRegIndex _ura, + IntRegIndex _urb, + IntRegIndex _urc); + %(BasicExecDeclare)s + }; +}}; + +def template MicroSetPCCPSRConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst, + IntRegIndex _ura, + IntRegIndex _urb, + IntRegIndex _urc) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + _ura, _urb, _urc) + { + %(constructor)s; + if (!(condCode == COND_AL || condCode == COND_UC)) { + for (int x = 0; x < _numDestRegs; x++) { + _srcRegIdx[_numSrcRegs++] = _destRegIdx[x]; + } + } + } +}}; + //////////////////////////////////////////////////////////////////// // // Integer = Integer op Integer microops diff --git a/src/arch/arm/isa/templates/mem.isa b/src/arch/arm/isa/templates/mem.isa index 3d073b322..dcfd47ace 100644 --- a/src/arch/arm/isa/templates/mem.isa +++ b/src/arch/arm/isa/templates/mem.isa @@ -917,9 +917,9 @@ def template CompleteAccDeclare {{ def template RfeConstructor {{ inline %(class_name)s::%(class_name)s(ExtMachInst machInst, - uint32_t _base, int _mode, bool _wb) - : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, - (IntRegIndex)_base, (AddrMode)_mode, _wb) + uint32_t _base, int _mode, bool _wb) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s, + (IntRegIndex)_base, (AddrMode)_mode, _wb) { %(constructor)s; if (!(condCode == COND_AL || condCode == COND_UC)) { @@ -928,12 +928,18 @@ def template RfeConstructor {{ } } #if %(use_uops)d - assert(numMicroops >= 2); - uops = new StaticInstPtr[numMicroops]; - uops[0] = new %(acc_name)s(machInst, _base, _mode, _wb); - uops[0]->setDelayedCommit(); - uops[1] = new %(wb_decl)s; - uops[1]->setLastMicroop(); + uops = new StaticInstPtr[1 + %(use_wb)d + %(use_pc)d]; + int uopIdx = 0; + uops[uopIdx] = new %(acc_name)s(machInst, _base, _mode, _wb); + uops[uopIdx]->setDelayedCommit(); +#if %(use_wb)d + uops[++uopIdx] = new %(wb_decl)s; + uops[uopIdx]->setDelayedCommit(); +#endif +#if %(use_pc)d + uops[++uopIdx] = new %(pc_decl)s; +#endif + uops[uopIdx]->setLastMicroop(); #endif } }}; -- cgit v1.2.3