From 07f5053c1b75908f62533f8cea8e45425ecbdc4d Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Sat, 6 Feb 2021 17:16:39 +0530 Subject: [PATCH] arch-power: Refactor branch instructions This changes the base classes for branch instructions and switches to two high-level classes for unconditional and conditional branches. The conditional branches are further classified based on whether they use an immediate field or a register for determining the target address. Decoding has also been consolidated using formats that can generate code after determining if an instruction branches to an absolute address or a PC-relative address, or if it implicitly sets the return address by looking at the AA and LK bits. Change-Id: I5fa7db7b6693586b4ea3c71e5cad8a60753de29c Signed-off-by: Sandipan Das Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40886 Reviewed-by: Boris Shingarov Maintainer: Gabe Black Tested-by: kokoro --- src/arch/power/insts/branch.cc | 99 +++++------- src/arch/power/insts/branch.hh | 163 ++++++------------- src/arch/power/isa/decoder.isa | 27 ++-- src/arch/power/isa/formats/branch.isa | 222 +++++++++++--------------- src/arch/power/isa/formats/util.isa | 29 +++- src/arch/power/types.hh | 14 +- 6 files changed, 224 insertions(+), 330 deletions(-) diff --git a/src/arch/power/insts/branch.cc b/src/arch/power/insts/branch.cc index 84834f1ed6..1077f33004 100644 --- a/src/arch/power/insts/branch.cc +++ b/src/arch/power/insts/branch.cc @@ -49,21 +49,30 @@ PCDependentDisassembly::disassemble( return *cachedDisassembly; } + PowerISA::PCState -BranchPCRel::branchTarget(const PowerISA::PCState &pc) const +BranchOp::branchTarget(const PowerISA::PCState &pc) const { - return (uint32_t)(pc.pc() + disp); + if (aa) + return li; + else + return pc.pc() + li; } + std::string -BranchPCRel::generateDisassembly( +BranchOp::generateDisassembly( Addr pc, const Loader::SymbolTable *symtab) const { std::stringstream ss; + Addr target; ccprintf(ss, "%-10s ", mnemonic); - Addr target = pc + disp; + if (aa) + target = li; + else + target = pc + li; Loader::SymbolTable::const_iterator it; if (symtab && (it = symtab->find(target)) != symtab->end()) @@ -74,46 +83,34 @@ BranchPCRel::generateDisassembly( return ss.str(); } + PowerISA::PCState -BranchNonPCRel::branchTarget(const PowerISA::PCState &pc) const +BranchDispCondOp::branchTarget(const PowerISA::PCState &pc) const { - return targetAddr; + if (aa) { + return bd; + } else { + return pc.pc() + bd; + } } + std::string -BranchNonPCRel::generateDisassembly( +BranchDispCondOp::generateDisassembly( Addr pc, const Loader::SymbolTable *symtab) const { std::stringstream ss; + Addr target; ccprintf(ss, "%-10s ", mnemonic); - Loader::SymbolTable::const_iterator it; - if (symtab && (it = symtab->find(targetAddr)) != symtab->end()) - ss << it->name; + // Print BI and BO fields + ss << bi << ", " << bo << ", "; + + if (aa) + target = bd; else - ccprintf(ss, "%#x", targetAddr); - - return ss.str(); -} - -PowerISA::PCState -BranchPCRelCond::branchTarget(const PowerISA::PCState &pc) const -{ - return (uint32_t)(pc.pc() + disp); -} - -std::string -BranchPCRelCond::generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const -{ - std::stringstream ss; - - ccprintf(ss, "%-10s ", mnemonic); - - ss << bo << ", " << bi << ", "; - - Addr target = pc + disp; + target = pc + bd; Loader::SymbolTable::const_iterator it; if (symtab && (it = symtab->find(target)) != symtab->end()) @@ -124,47 +121,25 @@ BranchPCRelCond::generateDisassembly( return ss.str(); } + PowerISA::PCState -BranchNonPCRelCond::branchTarget(const PowerISA::PCState &pc) const +BranchRegCondOp::branchTarget(ThreadContext *tc) const { - return targetAddr; + Addr addr = tc->readIntReg(srcRegIdx(_numSrcRegs - 1).index()); + return addr & -4ULL; } + std::string -BranchNonPCRelCond::generateDisassembly( +BranchRegCondOp::generateDisassembly( Addr pc, const Loader::SymbolTable *symtab) const { std::stringstream ss; ccprintf(ss, "%-10s ", mnemonic); - ss << bo << ", " << bi << ", "; - - Loader::SymbolTable::const_iterator it; - if (symtab && (it = symtab->find(targetAddr)) != symtab->end()) - ss << it->name; - else - ccprintf(ss, "%#x", targetAddr); - - return ss.str(); -} - -PowerISA::PCState -BranchRegCond::branchTarget(ThreadContext *tc) const -{ - uint32_t regVal = tc->readIntReg(srcRegIdx(_numSrcRegs - 1).index()); - return regVal & 0xfffffffc; -} - -std::string -BranchRegCond::generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const -{ - std::stringstream ss; - - ccprintf(ss, "%-10s ", mnemonic); - - ss << bo << ", " << bi << ", "; + // Print the BI and BO fields + ss << bi << ", " << bo; return ss.str(); } diff --git a/src/arch/power/insts/branch.hh b/src/arch/power/insts/branch.hh index 435b4fdff2..532a4a2dab 100644 --- a/src/arch/power/insts/branch.hh +++ b/src/arch/power/insts/branch.hh @@ -63,25 +63,25 @@ class PCDependentDisassembly : public PowerStaticInst disassemble(Addr pc, const Loader::SymbolTable *symtab) const; }; + /** - * Base class for unconditional, PC-relative branches. + * Base class for unconditional, PC-relative or absolute address branches. */ -class BranchPCRel : public PCDependentDisassembly +class BranchOp : public PCDependentDisassembly { protected: - /// Displacement - uint32_t disp; + bool aa; + bool lk; + int64_t li; - /// Constructor. - BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass) - : PCDependentDisassembly(mnem, _machInst, __opClass), - disp(machInst.li << 2) + /// Constructor + BranchOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + aa(machInst.aa), + lk(machInst.lk), + li(sext<26>(machInst.li << 2)) { - // If bit 26 is 1 then sign extend - if (disp & 0x2000000) { - disp |= 0xfc000000; - } } PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override; @@ -93,104 +93,66 @@ class BranchPCRel : public PCDependentDisassembly Addr pc, const Loader::SymbolTable *symtab) const override; }; -/** - * Base class for unconditional, non PC-relative branches. - */ -class BranchNonPCRel : public PCDependentDisassembly -{ - protected: - - /// Target address - uint32_t targetAddr; - - /// Constructor. - BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass) - : PCDependentDisassembly(mnem, _machInst, __opClass), - targetAddr(machInst.li << 2) - { - // If bit 26 is 1 then sign extend - if (targetAddr & 0x2000000) { - targetAddr |= 0xfc000000; - } - } - - PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override; - - /// Explicitly import the otherwise hidden branchTarget - using StaticInst::branchTarget; - - std::string generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const override; -}; /** * Base class for conditional branches. */ -class BranchCond : public PCDependentDisassembly +class BranchCondOp : public PCDependentDisassembly { protected: - /// Fields needed for conditions - uint32_t bo; - uint32_t bi; + bool lk; + uint8_t bi; + uint8_t bo; - /// Constructor. - BranchCond(const char *mnem, MachInst _machInst, OpClass __opClass) - : PCDependentDisassembly(mnem, _machInst, __opClass), - bo(machInst.bo), - bi(machInst.bi) + /// Constructor + BranchCondOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + lk(machInst.lk), + bi(machInst.bi), + bo(machInst.bo) { } inline bool - ctrOk(uint32_t& ctr) const + ctrOk(uint64_t& ctr) const { - bool ctr_ok; - if (bo & 4) { - ctr_ok = true; - } else { - ctr--; - if (ctr != 0) { - ctr_ok = ((bo & 2) == 0); - } else { - ctr_ok = ((bo & 2) != 0); - } + if (bits(bo, 2)) { + return true; } - return ctr_ok; + + ctr--; + return !((ctr != 0) ^ (bits(bo, 1) == 0)); } inline bool condOk(uint32_t cr) const { - bool cond_ok; - if (bo & 16) { - cond_ok = true; - } else { - cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1)); + if (bits(bo, 4)) { + return true; } - return cond_ok; + + return bits(cr >> (31 - bi), 0) == bits(bo >> 3, 0); } }; + /** - * Base class for conditional, PC-relative branches. + * Base class for conditional, PC-relative or absolute address branches. */ -class BranchPCRelCond : public BranchCond +class BranchDispCondOp : public BranchCondOp { protected: - /// Displacement - uint32_t disp; + bool aa; + int64_t bd; - /// Constructor. - BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) - : BranchCond(mnem, _machInst, __opClass), - disp(machInst.bd << 2) + /// Constructor + BranchDispCondOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : BranchCondOp(mnem, _machInst, __opClass), + aa(machInst.aa), + bd(sext<16>(machInst.bd << 2)) { - // If bit 16 is 1 then sign extend - if (disp & 0x8000) { - disp |= 0xffff0000; - } } PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override; @@ -202,46 +164,21 @@ class BranchPCRelCond : public BranchCond Addr pc, const Loader::SymbolTable *symtab) const override; }; + /** - * Base class for conditional, non PC-relative branches. + * Base class for conditional, register-based branches. */ -class BranchNonPCRelCond : public BranchCond +class BranchRegCondOp : public BranchCondOp { protected: - /// Target address - uint32_t targetAddr; + /// TODO: Branch hints are currently ignored + uint8_t bh; /// Constructor. - BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) - : BranchCond(mnem, _machInst, __opClass), - targetAddr(machInst.bd << 2) - { - // If bit 16 is 1 then sign extend - if (targetAddr & 0x8000) { - targetAddr |= 0xffff0000; - } - } - - PowerISA::PCState branchTarget(const PowerISA::PCState &pc) const override; - - /// Explicitly import the otherwise hidden branchTarget - using StaticInst::branchTarget; - - std::string generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const override; -}; - -/** - * Base class for conditional, register-based branches - */ -class BranchRegCond : public BranchCond -{ - protected: - - /// Constructor. - BranchRegCond(const char *mnem, MachInst _machInst, OpClass __opClass) - : BranchCond(mnem, _machInst, __opClass) + BranchRegCondOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : BranchCondOp(mnem, _machInst, __opClass), + bh(machInst.bh) { } diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 8ffe007018..e4f57cadad 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -77,25 +77,16 @@ decode PO default Unknown::unknown() { {{ Rt = imm << 16; }}); } - 16: decode AA { - - // Conditionally branch relative to PC based on CR and CTR. - 0: BranchPCRelCondCtr::bc({{ NIA = (uint32_t)(CIA + disp); }}); - - // Conditionally branch to fixed address based on CR and CTR. - 1: BranchNonPCRelCondCtr::bca({{ NIA = targetAddr; }}); - } + // Conditionally branch to a PC-relative or absoulute address based + // on CR and CTR. + 16: BranchDispCondOp::bc({{ NIA = CIA + bd; }}, + {{ NIA = bd; }}); 17: IntOp::sc({{ return std::make_shared(); }}); - 18: decode AA { - - // Unconditionally branch relative to PC. - 0: BranchPCRel::b({{ NIA = (uint32_t)(CIA + disp); }}); - - // Unconditionally branch to fixed address. - 1: BranchNonPCRel::ba({{ NIA = targetAddr; }}); - } + // Unconditionally branch to a PC-relative or absoulute address. + 18: BranchOp::b({{ NIA = CIA + li; }}, + {{ NIA = li; }}); 19: decode XL_XO { @@ -105,7 +96,7 @@ decode PO default Unknown::unknown() { }}); // Conditionally branch to address in LR based on CR and CTR. - 16: BranchLrCondCtr::bclr({{ NIA = LR & 0xfffffffc; }}); + 16: BranchRegCondOp::bclr({{ NIA = LR & -4ULL; }}, true, [ IsReturn ]); format CondLogicOp { 33: crnor({{ @@ -162,7 +153,7 @@ decode PO default Unknown::unknown() { } // Conditionally branch to address in CTR based on CR. - 528: BranchCtrCond::bcctr({{ NIA = CTR & 0xfffffffc; }}); + 528: BranchRegCondOp::bcctr({{ NIA = CTR & -4ULL; }}); } format IntRotateOp { diff --git a/src/arch/power/isa/formats/branch.isa b/src/arch/power/isa/formats/branch.isa index 3481438bbe..2f506279e8 100644 --- a/src/arch/power/isa/formats/branch.isa +++ b/src/arch/power/isa/formats/branch.isa @@ -30,18 +30,17 @@ // // Control transfer instructions // -// From the Power ISA Book I v2.06, page 33, the following rules should +// From the Power ISA Book I v3.0B, page 35, the following rules should // be obeyed by programmers: // // - Use branch instructions where LK == 1 only as subroutine calls. // - Pair each subroutine call with a bclr instruction with BH == 00 -// that returns from the subroutine. -// - Do not use bclrl as a subroutine call. +// and LK == 0 that returns from the subroutine. +// - Do not use bclr with LK == 1 as a subroutine call. // -// Therefore, I've flagged all versions that update the link register (LR) -// as calls, except bclrl (BranchLrCtrCond format) which is flagged as -// a return. - +// Therefore, all versions that update the link register (LR) are flagged +// as calls, except bclr with LK == 1 (i.e. bclrl). The latter should not +// be tagged as a return either. let {{ @@ -50,57 +49,45 @@ updateLrCode = 'LR = CIA + 4;' }}; -// Instructions that unconditionally branch relative to the current PC. -def format BranchPCRel(br_code, inst_flags = []) {{ + +// Instructions that unconditionally branch either to an address relative +// to the current PC or an absolute address. +def format BranchOp(code, code_aa1, inst_flags = []) {{ inst_flags += ('IsUncondControl', 'IsDirectControl') - basic_code = br_code - # The version that does not update LR + # Setup the 4 code versions and add code to update LR if necessary + code_lk1 = code + updateLrCode + code_aa1_lk1 = code_aa1 + updateLrCode + + # Generate the classes (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'BranchPCRel', basic_code, inst_flags, - CheckLkDecode, BasicConstructor) + GenAluOp(name, Name, 'BranchOp', code, inst_flags, + CheckAaLkDecode, BasicConstructor) + (header_output_aa1, decoder_output_aa1, _, exec_output_aa1) = \ + GenAluOp(name, Name + 'AaSet', 'BranchOp', code_aa1, inst_flags, + CheckAaLkDecode, BasicConstructor) + (header_output_lk1, decoder_output_lk1, _, exec_output_lk1) = \ + GenAluOp(name, Name + 'LkSet', 'BranchOp', code_lk1, inst_flags, + CheckAaLkDecode, BasicConstructor) + (header_output_aa1_lk1, decoder_output_aa1_lk1, _, exec_output_aa1_lk1) = \ + GenAluOp(name, Name + 'AaSetLkSet', 'BranchOp', code_aa1_lk1, + inst_flags, CheckAaLkDecode, BasicConstructor) - # The version that does the update - update_code = basic_code + updateLrCode - update_flags = inst_flags + [ 'IsCall' ] - (header_output_up, decoder_output_up, _, exec_output_up) = \ - GenAluOp(name, Name + 'UpdateLr', 'BranchPCRel', update_code, - update_flags, CheckLkDecode, BasicConstructor) - - # Add the outputs together - header_output += header_output_up - decoder_output += decoder_output_up - exec_output += exec_output_up + # Finally, add to the other outputs + header_output += \ + header_output_aa1 + header_output_lk1 + header_output_aa1_lk1 + decoder_output += \ + decoder_output_aa1 + decoder_output_lk1 + decoder_output_aa1_lk1 + exec_output += \ + exec_output_aa1 + exec_output_lk1 + exec_output_aa1_lk1 }}; -// Instructions that unconditionally branch to a specific address. -def format BranchNonPCRel(br_code, inst_flags = []) {{ - inst_flags += ('IsUncondControl', 'IsDirectControl') - basic_code = br_code - - # The version that does not update LR - (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'BranchNonPCRel', basic_code, inst_flags, - CheckLkDecode, BasicConstructor) - - # The version that does the update - update_code = basic_code + updateLrCode - update_flags = inst_flags + [ 'IsCall' ] - (header_output_up, decoder_output_up, _, exec_output_up) = \ - GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRel', update_code, - update_flags, CheckLkDecode, BasicConstructor) - - # Add the outputs together - header_output += header_output_up - decoder_output += decoder_output_up - exec_output += exec_output_up -}}; let {{ # Check the condition register (CR) allows the branch to be taken. def GetCondCode(br_code): - cond_code = 'if(condOk(CR)) {\n' + cond_code = 'if (condOk(CR)) {\n' cond_code += ' ' + br_code + '\n' cond_code += '} else {\n' cond_code += ' NIA = NIA;\n' @@ -109,12 +96,10 @@ def GetCondCode(br_code): # Check the condition register (CR) and count register (CTR) allow the # branch to be taken. Also, in certain situations, decrement the count -# register too. This takes place in ctrOk within BranchCond classes. +# register too. This takes place in ctrOk within BranchCondOp classes. def GetCtrCondCode(br_code): - cond_code = 'uint32_t ctr = CTR;\n' - cond_code += 'bool ctr_ok = ctrOk(ctr);\n' - cond_code += 'bool cond_ok = condOk(CR);\n' - cond_code += 'if(ctr_ok && cond_ok) {\n' + cond_code = 'uint64_t ctr = CTR;\n' + cond_code += 'if (ctrOk(ctr) && condOk(CR)) {\n' cond_code += ' ' + br_code + '\n' cond_code += '} else {\n' cond_code += ' NIA = NIA;\n' @@ -124,97 +109,72 @@ def GetCtrCondCode(br_code): }}; -// Instructions that conditionally branch relative to the current PC based on -// the condition register (CR) and count register (CTR). -def format BranchPCRelCondCtr(br_code, inst_flags = []) {{ - inst_flags += ('IsCondControl', 'IsDirectControl') - basic_code = GetCtrCondCode(br_code) - # The version that does not update LR - (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'BranchPCRelCond', basic_code, inst_flags, - CheckLkDecode, BasicConstructor) - - # The version that does the update - update_code = basic_code + updateLrCode - update_flags = inst_flags + [ 'IsCall' ] - (header_output_up, decoder_output_up, _, exec_output_up) = \ - GenAluOp(name, Name + 'UpdateLr', 'BranchPCRelCond', update_code, - update_flags, CheckLkDecode, BasicConstructor) - - # Add the outputs together - header_output += header_output_up - decoder_output += decoder_output_up - exec_output += exec_output_up -}}; - -// Instructions that conditionally branch to a specific address based on the +// Instructions that conditionally branch either to an address relative +// to the current PC or an absolute address depending on the value of the // condition register (CR) and count register (CTR). -def format BranchNonPCRelCondCtr(br_code, inst_flags = []) {{ +def format BranchDispCondOp(code, code_aa1, inst_flags = []) {{ inst_flags += ('IsCondControl', 'IsDirectControl') - basic_code = GetCtrCondCode(br_code) - # The version that does not update LR + # Setup the 4 code versions and add code to update LR if necessary + code = GetCtrCondCode(code) + code_aa1 = GetCtrCondCode(code_aa1) + code_lk1 = code + updateLrCode + code_aa1_lk1 = code_aa1 + updateLrCode + inst_flags_lk1 = inst_flags + [ 'IsCall' ] + + # Generate the classes (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'BranchNonPCRelCond', basic_code, inst_flags, - CheckLkDecode, BasicConstructor) + GenAluOp(name, Name, 'BranchDispCondOp', code, inst_flags, + CheckAaLkDecode, BasicConstructor) + (header_output_aa1, decoder_output_aa1, _, exec_output_aa1) = \ + GenAluOp(name, Name + 'AaSet', 'BranchDispCondOp', code_aa1, + inst_flags, CheckAaLkDecode, BasicConstructor) + (header_output_lk1, decoder_output_lk1, _, exec_output_lk1) = \ + GenAluOp(name, Name + 'LkSet', 'BranchDispCondOp', code_lk1, + inst_flags_lk1, CheckAaLkDecode, BasicConstructor) + (header_output_aa1_lk1, decoder_output_aa1_lk1, _, exec_output_aa1_lk1) = \ + GenAluOp(name, Name + 'AaSetLkSet', 'BranchDispCondOp', code_aa1_lk1, + inst_flags_lk1, CheckAaLkDecode, BasicConstructor) - # The version that does the update - update_code = basic_code + updateLrCode - update_flags = inst_flags + [ 'IsCall' ] - (header_output_up, decoder_output_up, _, exec_output_up) = \ - GenAluOp(name, Name + 'UpdateLr', 'BranchNonPCRelCond', update_code, - update_flags, CheckLkDecode, BasicConstructor) - - # Add the outputs together - header_output += header_output_up - decoder_output += decoder_output_up - exec_output += exec_output_up + # Finally, add to the other outputs + header_output += \ + header_output_aa1 + header_output_lk1 + header_output_aa1_lk1 + decoder_output += \ + decoder_output_aa1 + decoder_output_lk1 + decoder_output_aa1_lk1 + exec_output += \ + exec_output_aa1 + exec_output_lk1 + exec_output_aa1_lk1 }}; -// Instructions that conditionally branch to the address in the link register -// (LR) based on the condition register (CR) and count register (CTR). -def format BranchLrCondCtr(br_code, inst_flags = []) {{ - inst_flags += ('IsCondControl', 'IsIndirectControl', 'IsReturn') - basic_code = GetCtrCondCode(br_code) - # The version that does not update LR - (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags, - CheckLkDecode, BasicConstructor) - - # The version that does the update - update_code = basic_code + updateLrCode - (header_output_up, decoder_output_up, _, exec_output_up) = \ - GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code, - inst_flags, CheckLkDecode, BasicConstructor) - - # Add the outputs together - header_output += header_output_up - decoder_output += decoder_output_up - exec_output += exec_output_up -}}; - -// Instructions that conditionally branch to the address in the count register -// (CTR) based on the condition register (CR). -def format BranchCtrCond(br_code, inst_flags = []) {{ +// Instructions that conditionally branch to an address in a register +// depending on the value of the condition register (CR) and count +// register (CTR). +def format BranchRegCondOp(code, checkCTR = 0, inst_flags = []) {{ inst_flags += ('IsCondControl', 'IsIndirectControl') - basic_code = GetCondCode(br_code) - # The version that does not update LR + # Setup the 2 code versions and add code to update LR if necessary + if checkCTR: + code = GetCtrCondCode(code) + else: + code = GetCondCode(code) + code_lk1 = code + updateLrCode + inst_flags_lk1 = inst_flags + [ 'IsCall' ] + + # When LK is set, this cannot be used to return to the callee + if 'IsReturn' in inst_flags: + inst_flags_lk1.remove('IsReturn') + + # Generate the classes (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'BranchRegCond', basic_code, inst_flags, + GenAluOp(name, Name, 'BranchRegCondOp', code, inst_flags, CheckLkDecode, BasicConstructor) + (header_output_lk1, decoder_output_lk1, _, exec_output_lk1) = \ + GenAluOp(name, Name + 'LkSet', 'BranchRegCondOp', code_lk1, + inst_flags_lk1, CheckLkDecode, BasicConstructor) - # The version that does the update - update_code = basic_code + updateLrCode - update_flags = inst_flags + [ 'IsCall' ] - (header_output_up, decoder_output_up, _, exec_output_up) = \ - GenAluOp(name, Name + 'UpdateLr', 'BranchRegCond', update_code, - update_flags, CheckLkDecode, BasicConstructor) - - # Add the outputs together - header_output += header_output_up - decoder_output += decoder_output_up - exec_output += exec_output_up + # Finally, add to the other outputs + header_output += header_output_lk1 + decoder_output += decoder_output_lk1 + exec_output += exec_output_lk1 }}; diff --git a/src/arch/power/isa/formats/util.isa b/src/arch/power/isa/formats/util.isa index 1bb78e6ad2..34bebb0ed4 100644 --- a/src/arch/power/isa/formats/util.isa +++ b/src/arch/power/isa/formats/util.isa @@ -78,11 +78,38 @@ def template CheckLkDecode {{ if (LK == 0) { return new %(class_name)s(machInst); } else { - return new %(class_name)sUpdateLr(machInst); + return new %(class_name)sLkSet(machInst); } } }}; +def template CheckAaDecode {{ + { + if (AA == 0) { + return new %(class_name)s(machInst); + } else { + return new %(class_name)sAaSet(machInst); + } + } +}}; + +def template CheckAaLkDecode {{ + { + if (AA == 0) { + if (LK == 0) { + return new %(class_name)s(machInst); + } else { + return new %(class_name)sLkSet(machInst); + } + } else { + if (LK == 0) { + return new %(class_name)sAaSet(machInst); + } else { + return new %(class_name)sAaSetLkSet(machInst); + } + } + } +}}; let {{ diff --git a/src/arch/power/types.hh b/src/arch/power/types.hh index 58751a9ec5..72dcd1e3b7 100644 --- a/src/arch/power/types.hh +++ b/src/arch/power/types.hh @@ -55,14 +55,18 @@ BitUnion32(ExtMachInst) // Special purpose register identifier Bitfield<20, 11> spr; - Bitfield<25, 2> li; - Bitfield<1> aa; Bitfield<25, 23> bf; - Bitfield<15, 2> bd; - Bitfield<25, 21> bo; - Bitfield<20, 16> bi; Bitfield<20, 18> bfa; + // Branch instruction fields + Bitfield<1> aa; + Bitfield<15, 2> bd; + Bitfield<20, 16> bi; + Bitfield<12, 11> bh; + Bitfield<25, 21> bo; + Bitfield<25, 2> li; + Bitfield<0> lk; + // Record bits Bitfield<0> rc31; Bitfield<10> oe;