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 <sandipan@linux.ibm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/40886
Reviewed-by: Boris Shingarov <shingarov@gmail.com>
Maintainer: Gabe Black <gabe.black@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Sandipan Das
2021-02-06 17:16:39 +05:30
committed by Boris Shingarov
parent e3d58b6132
commit 07f5053c1b
6 changed files with 224 additions and 330 deletions

View File

@@ -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();
}

View File

@@ -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)
{
}

View File

@@ -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<SESyscallFault>(); }});
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 {

View File

@@ -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
}};

View File

@@ -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 {{

View File

@@ -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;