From: Sandipan Das Date: Thu, 7 Jun 2018 14:30:41 +0000 (+0530) Subject: arch-power: Fix branch instructions X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c9111802872744a62d99eb41b5ef181135b3b626;p=gem5.git arch-power: Fix branch instructions This fixes the following branch instructions in order to support 64-bit addressing: * Branch (b[l][a]) * Branch Conditional (bc[l][a]) * Branch Conditional to Link Register (bclr[l]) * Branch Conditional to Count Register (bcctr[l]) This also fixes disassembly generation for all of the above. Change-Id: I7cad4e1b3b2945ab06c4ffc8c79842f1453c85ec Signed-off-by: Sandipan Das --- diff --git a/src/arch/power/insts/branch.cc b/src/arch/power/insts/branch.cc index 3511b6b3c..fce3d3f64 100644 --- a/src/arch/power/insts/branch.cc +++ b/src/arch/power/insts/branch.cc @@ -52,21 +52,37 @@ 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 (aaSet) { + return disp; + } else { + return pc.pc() + disp; + } } + std::string -BranchPCRel::generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const +BranchOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; + Addr target; - ccprintf(ss, "%-10s ", mnemonic); + // Generate correct mnemonic + std::string myMnemonic(mnemonic); + + // Additional characters depending on isa bits being set + if (lkSet) myMnemonic = myMnemonic + "l"; + if (aaSet) myMnemonic = myMnemonic + "a"; + ccprintf(ss, "%-10s ", myMnemonic); - Addr target = pc + disp; + if (aaSet) { + target = disp; + } else { + target = pc + disp; + } Loader::SymbolTable::const_iterator it; if (symtab && (it = symtab->find(target)) != symtab->end()) @@ -77,46 +93,40 @@ BranchPCRel::generateDisassembly( return ss.str(); } -PowerISA::PCState -BranchNonPCRel::branchTarget(const PowerISA::PCState &pc) const -{ - return targetAddr; -} - -std::string -BranchNonPCRel::generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const -{ - std::stringstream ss; - - ccprintf(ss, "%-10s ", mnemonic); - - 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 -BranchPCRelCond::branchTarget(const PowerISA::PCState &pc) const +BranchDispCondOp::branchTarget(const PowerISA::PCState &pc) const { - return (uint32_t)(pc.pc() + disp); + if (aaSet) { + return disp; + } else { + return pc.pc() + disp; + } } + std::string -BranchPCRelCond::generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const +BranchDispCondOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; + Addr target; - ccprintf(ss, "%-10s ", mnemonic); + // Generate the correct mnemonic + std::string myMnemonic(mnemonic); - ss << bo << ", " << bi << ", "; + // Additional characters depending on isa bits being set + if (lkSet) myMnemonic = myMnemonic + "l"; + if (aaSet) myMnemonic = myMnemonic + "a"; + ccprintf(ss, "%-10s ", myMnemonic); - Addr target = pc + disp; + // Print BI and BO fields + ss << crBit << ", " << opts << ", "; + + if (aaSet) { + target = disp; + } else { + target = pc + disp; + } Loader::SymbolTable::const_iterator it; if (symtab && (it = symtab->find(target)) != symtab->end()) @@ -127,47 +137,29 @@ BranchPCRelCond::generateDisassembly( return ss.str(); } -PowerISA::PCState -BranchNonPCRelCond::branchTarget(const PowerISA::PCState &pc) const -{ - return targetAddr; -} - -std::string -BranchNonPCRelCond::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 +BranchRegCondOp::branchTarget(ThreadContext *tc) const { - uint32_t regVal = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1].index()); - return regVal & 0xfffffffc; + Addr addr = tc->readIntReg(_srcRegIdx[_numSrcRegs - 1].index()); + return addr & -4ULL; } + std::string -BranchRegCond::generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const +BranchRegCondOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; + // Generate the correct mnemonic + std::string myMnemonic(mnemonic); + + // Additional characters depending on isa bits being set + if (lkSet) myMnemonic = myMnemonic + "l"; ccprintf(ss, "%-10s ", mnemonic); - ss << bo << ", " << bi << ", "; + // Print the BI and BO fields + ss << crBit << ", " << opts; return ss.str(); } diff --git a/src/arch/power/insts/branch.hh b/src/arch/power/insts/branch.hh index 435b4fdff..1a0102210 100644 --- a/src/arch/power/insts/branch.hh +++ b/src/arch/power/insts/branch.hh @@ -63,55 +63,25 @@ class PCDependentDisassembly : public PowerStaticInst disassemble(Addr pc, const Loader::SymbolTable *symtab) const; }; -/** - * Base class for unconditional, PC-relative branches. - */ -class BranchPCRel : public PCDependentDisassembly -{ - protected: - - /// Displacement - uint32_t disp; - - /// Constructor. - BranchPCRel(const char *mnem, MachInst _machInst, OpClass __opClass) - : PCDependentDisassembly(mnem, _machInst, __opClass), - disp(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; - - /// Explicitly import the otherwise hidden branchTarget - using StaticInst::branchTarget; - - std::string generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const override; -}; /** - * Base class for unconditional, non PC-relative branches. + * Base class for unconditional, PC-relative or absolute address branches. */ -class BranchNonPCRel : public PCDependentDisassembly +class BranchOp : public PCDependentDisassembly { protected: - /// Target address - uint32_t targetAddr; + bool aaSet; + bool lkSet; + uint64_t disp; - /// Constructor. - BranchNonPCRel(const char *mnem, MachInst _machInst, OpClass __opClass) - : PCDependentDisassembly(mnem, _machInst, __opClass), - targetAddr(machInst.li << 2) + /// Constructor + BranchOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : PCDependentDisassembly(mnem, _machInst, __opClass), + aaSet(false), + lkSet(false), + disp(sext<26>(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; @@ -123,104 +93,74 @@ class BranchNonPCRel : public PCDependentDisassembly 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 lkSet; + uint32_t crBit; + uint32_t opts; - /// 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), + lkSet(false), + crBit(machInst.bi), + opts(machInst.bo) { } inline bool - ctrOk(uint32_t& ctr) const + checkCtr(uint64_t& ctr) const { - bool ctr_ok; - if (bo & 4) { - ctr_ok = true; + bool ctrOk; + if (opts & 0x4) { + ctrOk = true; } else { ctr--; if (ctr != 0) { - ctr_ok = ((bo & 2) == 0); + ctrOk = ((opts & 0x2) == 0); } else { - ctr_ok = ((bo & 2) != 0); + ctrOk = ((opts & 0x2) != 0); } } - return ctr_ok; + return ctrOk; } inline bool - condOk(uint32_t cr) const + checkCond(uint32_t cr) const { - bool cond_ok; - if (bo & 16) { - cond_ok = true; + bool condOk; + if (opts & 0x10) { + condOk = true; } else { - cond_ok = (((cr >> (31 - bi)) & 1) == ((bo >> 3) & 1)); + condOk = (((cr >> (31 - crBit)) & 0x1) == ((opts >> 3) & 0x1)); } - return cond_ok; + return condOk; } }; -/** - * Base class for conditional, PC-relative branches. - */ -class BranchPCRelCond : public BranchCond -{ - protected: - - /// Displacement - uint32_t disp; - - /// Constructor. - BranchPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) - : BranchCond(mnem, _machInst, __opClass), - disp(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; - - /// Explicitly import the otherwise hidden branchTarget - using StaticInst::branchTarget; - - std::string generateDisassembly( - Addr pc, const Loader::SymbolTable *symtab) const override; -}; /** - * Base class for conditional, non PC-relative branches. + * Base class for conditional, PC-relative or absolute address branches. */ -class BranchNonPCRelCond : public BranchCond +class BranchDispCondOp : public BranchCondOp { protected: - /// Target address - uint32_t targetAddr; + bool aaSet; + uint64_t disp; - /// Constructor. - BranchNonPCRelCond(const char *mnem, MachInst _machInst, OpClass __opClass) - : BranchCond(mnem, _machInst, __opClass), - targetAddr(machInst.bd << 2) + /// Constructor + BranchDispCondOp(const char *mnem, MachInst _machInst, OpClass __opClass) + : BranchCondOp(mnem, _machInst, __opClass), + aaSet(false), + disp(sext<14>(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; @@ -232,16 +172,22 @@ class BranchNonPCRelCond : public BranchCond Addr pc, const Loader::SymbolTable *symtab) const override; }; + /** - * Base class for conditional, register-based branches + * Base class for conditional, register-based branches. */ -class BranchRegCond : public BranchCond +class BranchRegCondOp : public BranchCondOp { protected: + // TODO: For now, the hint value (BH) is ignored and always considered + // to be zero. Instruction flags should vary depending on this. + uint32_t hint; + /// 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), + hint(machInst.bh) { } diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa index 7517c2818..69048ba8c 100644 --- a/src/arch/power/isa/decoder.isa +++ b/src/arch/power/isa/decoder.isa @@ -36,42 +36,26 @@ // decode PO default Unknown::unknown() { - 18: decode AA { - - // Unconditionally branch relative to PC. - format BranchPCRel { - 0: b({{ NIA = (uint32_t)(CIA + disp); }}); - } - - // Unconditionally branch to fixed address. - format BranchNonPCRel { - 1: ba({{ NIA = targetAddr; }}); - } + // Unconditionally branch to a PC-relative or absoulute address. + format BranchOp { + 18: b({{ NIA = CIA + disp; }}, + {{ NIA = disp; }}); } - 16: decode AA { - - // Conditionally branch relative to PC based on CR and CTR. - format BranchPCRelCondCtr { - 0: bc({{ NIA = (uint32_t)(CIA + disp); }}); - } - - // Conditionally branch to fixed address based on CR and CTR. - format BranchNonPCRelCondCtr { - 1: bca({{ NIA = targetAddr; }}); - } + // Conditionally branch to a PC-relative or absoulute address based + // on CR and CTR. + format BranchDispCondOp { + 16: bc({{ NIA = CIA + disp; }}, + {{ NIA = disp; }}); } 19: decode XL_XO { - // Conditionally branch to address in LR based on CR and CTR. - format BranchLrCondCtr { - 16: bclr({{ NIA = LR & 0xfffffffc; }}); - } - - // Conditionally branch to address in CTR based on CR. - format BranchCtrCond { - 528: bcctr({{ NIA = CTR & 0xfffffffc; }}); + // Conditionally branch to an address in a register based on + // either CR only or both CR and CTR. + format BranchRegCondOp { + 16: bclr({{ NIA = LR & -4ULL; }}, true, [ IsReturn ]); + 528: bcctr({{ NIA = CTR & -4ULL; }}); } // Condition register manipulation instructions. diff --git a/src/arch/power/isa/formats/branch.isa b/src/arch/power/isa/formats/branch.isa index 3481438bb..8b7ee5e01 100644 --- a/src/arch/power/isa/formats/branch.isa +++ b/src/arch/power/isa/formats/branch.isa @@ -39,68 +39,90 @@ // - Do not use bclrl 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 +// as calls, except bclrl (BranchRegCondOp format) which is flagged as // a return. -let {{ +// Instruction class constructor template when AA is set. +def template BranchAaConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + aaSet = true; + } +}}; -# Simple code to update link register (LR). -updateLrCode = 'LR = CIA + 4;' +// Instruction class constructor template when LK is set. +def template BranchLkConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + lkSet = true; + } }}; -// Instructions that unconditionally branch relative to the current PC. -def format BranchPCRel(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, 'BranchPCRel', basic_code, inst_flags, - CheckLkDecode, BasicConstructor) +// Instruction class constructor template when both AA and LK are set. +def template BranchAaLkConstructor {{ + %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) + { + %(constructor)s; + aaSet = true; + lkSet = true; + } +}}; + + +let {{ + +# Simple code to update link register (LR). +updateLrCode = 'LR = CIA + 4;' - # 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 }}; -// Instructions that unconditionally branch to a specific address. -def format BranchNonPCRel(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 - (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'BranchNonPCRel', basic_code, inst_flags, - CheckLkDecode, BasicConstructor) + # Setup the 4 code versions and add code to update LR if necessary + code_lk1 = code + updateLrCode + code_aa1_lk1 = code_aa1 + updateLrCode - # 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 + # Generate the classes + (header_output, decoder_output, decode_block, exec_output) = \ + 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, BranchAaConstructor) + (header_output_lk1, decoder_output_lk1, _, exec_output_lk1) = \ + GenAluOp(name, Name + 'LkSet', 'BranchOp', code_lk1, inst_flags, + CheckAaLkDecode, BranchLkConstructor) + (header_output_aa1_lk1, decoder_output_aa1_lk1, _, exec_output_aa1_lk1) = \ + GenAluOp(name, Name + 'AaSetLkSet', 'BranchOp', code_aa1_lk1, + inst_flags, CheckAaLkDecode, BranchAaLkConstructor) + + # 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 }}; + 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 (checkCond(CR)) {\n' cond_code += ' ' + br_code + '\n' cond_code += '} else {\n' cond_code += ' NIA = NIA;\n' @@ -109,12 +131,12 @@ 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 checkCtr 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 += 'bool ctrOk = checkCtr(ctr);\n' + cond_code += 'bool condOk = checkCond(CR);\n' + cond_code += 'if (ctrOk && condOk) {\n' cond_code += ' ' + br_code + '\n' cond_code += '} else {\n' cond_code += ' NIA = NIA;\n' @@ -124,97 +146,70 @@ 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 - (header_output, decoder_output, decode_block, exec_output) = \ - GenAluOp(name, Name, 'BranchNonPCRelCond', basic_code, inst_flags, - CheckLkDecode, BasicConstructor) + # 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' ] - # 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 -}}; - -// 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 + # Generate the classes (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 + 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, BranchAaConstructor) + (header_output_lk1, decoder_output_lk1, _, exec_output_lk1) = \ + GenAluOp(name, Name + 'LkSet', 'BranchDispCondOp', code_lk1, + inst_flags_lk1, CheckAaLkDecode, BranchLkConstructor) + (header_output_aa1_lk1, decoder_output_aa1_lk1, _, exec_output_aa1_lk1) = \ + GenAluOp(name, Name + 'AaSetLkSet', 'BranchDispCondOp', code_aa1_lk1, + inst_flags_lk1, CheckAaLkDecode, BranchAaLkConstructor) + + # 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 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 + if 'IsReturn' not in inst_flags: + inst_flags_lk1 += [ 'IsCall' ] + + # 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) - - # 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 + (header_output_lk1, decoder_output_lk1, _, exec_output_lk1) = \ + GenAluOp(name, Name + 'LkSet', 'BranchRegCondOp', code_lk1, + inst_flags_lk1, CheckLkDecode, BranchLkConstructor) + + # 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 1bb78e6ad..8b2e42515 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 {{ @@ -163,5 +190,3 @@ output decoder {{ } }}; - - diff --git a/src/arch/power/types.hh b/src/arch/power/types.hh index a805a4728..74cd7b43a 100644 --- a/src/arch/power/types.hh +++ b/src/arch/power/types.hh @@ -66,13 +66,17 @@ BitUnion32(ExtMachInst) // Special purpose register identifier Bitfield<20, 11> spr; - Bitfield<25, 2> li; - Bitfield<1> aa; Bitfield<25, 23> bf; + Bitfield<20, 18> bfa; + + // Branch instruction fields + Bitfield<1> aa; Bitfield<15, 2> bd; - Bitfield<25, 21> bo; Bitfield<20, 16> bi; - Bitfield<20, 18> bfa; + Bitfield<12, 11> bh; + Bitfield<25, 21> bo; + Bitfield<25, 2> li; + Bitfield<0> lk; // Record bits Bitfield<0> rc31;