SPARC: Clean up the branch instructions a bit.
--HG-- extra : convert_revision : 93d5cc68e4a327ee0492eeed7f3b56e98d2d83bb
This commit is contained in:
@@ -45,116 +45,49 @@ decode OP default Unknown::unknown()
|
||||
0x1: decode COND2
|
||||
{
|
||||
//Branch Always
|
||||
0x8: decode A
|
||||
{
|
||||
0x0: bpa(19, {{
|
||||
NNPC = xc->readPC() + disp;
|
||||
}});
|
||||
0x1: bpa(19, {{
|
||||
NPC = xc->readPC() + disp;
|
||||
NNPC = NPC + 4;
|
||||
}}, ',a');
|
||||
}
|
||||
0x8: bpa(19, annul_code={{
|
||||
NPC = xc->readPC() + disp;
|
||||
NNPC = NPC + 4;
|
||||
}});
|
||||
//Branch Never
|
||||
0x0: decode A
|
||||
{
|
||||
0x0: bpn(19, {{
|
||||
NNPC = NNPC;//Don't do anything
|
||||
}});
|
||||
0x1: bpn(19, {{
|
||||
NNPC = NPC + 8;
|
||||
NPC = NPC + 4;
|
||||
}}, ',a');
|
||||
}
|
||||
0x0: bpn(19, {{;}},
|
||||
annul_code={{
|
||||
NNPC = NPC + 8;
|
||||
NPC = NPC + 4;
|
||||
}});
|
||||
default: decode BPCC
|
||||
{
|
||||
0x0: bpcci(19, {{
|
||||
if(passesCondition(Ccr<3:0>, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x2: bpccx(19, {{
|
||||
if(passesCondition(Ccr<7:4>, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x0: bpcci(19, test={{passesCondition(Ccr<3:0>, COND2)}});
|
||||
0x2: bpccx(19, test={{passesCondition(Ccr<7:4>, COND2)}});
|
||||
}
|
||||
}
|
||||
//bicc
|
||||
0x2: decode COND2
|
||||
{
|
||||
//Branch Always
|
||||
0x8: decode A
|
||||
{
|
||||
0x0: ba(22, {{
|
||||
NNPC = xc->readPC() + disp;
|
||||
}});
|
||||
0x1: ba(22, {{
|
||||
NPC = xc->readPC() + disp;
|
||||
NNPC = NPC + 4;
|
||||
}}, ',a');
|
||||
}
|
||||
0x8: ba(22, annul_code={{
|
||||
NPC = xc->readPC() + disp;
|
||||
NNPC = NPC + 4;
|
||||
}});
|
||||
//Branch Never
|
||||
0x0: decode A
|
||||
{
|
||||
0x0: bn(22, {{
|
||||
NNPC = NNPC;//Don't do anything
|
||||
}});
|
||||
0x1: bn(22, {{
|
||||
NNPC = NPC + 8;
|
||||
NPC = NPC + 4;
|
||||
}}, ',a');
|
||||
}
|
||||
default: bicc(22, {{
|
||||
if(passesCondition(Ccr<3:0>, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x0: bn(22, {{;}},
|
||||
annul_code={{
|
||||
NNPC = NPC + 8;
|
||||
NPC = NPC + 4;
|
||||
}});
|
||||
default: bicc(22, test={{passesCondition(Ccr<3:0>, COND2)}});
|
||||
}
|
||||
}
|
||||
0x3: decode RCOND2
|
||||
{
|
||||
format BranchSplit
|
||||
{
|
||||
0x1: bpreq({{
|
||||
if(Rs1.sdw == 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x2: bprle({{
|
||||
if(Rs1.sdw <= 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x3: bprl({{
|
||||
if(Rs1.sdw < 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x5: bprne({{
|
||||
if(Rs1.sdw != 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x6: bprg({{
|
||||
if(Rs1.sdw > 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x7: bprge({{
|
||||
if(Rs1.sdw >= 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x1: bpreq(test={{Rs1.sdw == 0}});
|
||||
0x2: bprle(test={{Rs1.sdw <= 0}});
|
||||
0x3: bprl(test={{Rs1.sdw < 0}});
|
||||
0x5: bprne(test={{Rs1.sdw != 0}});
|
||||
0x6: bprg(test={{Rs1.sdw > 0}});
|
||||
0x7: bprge(test={{Rs1.sdw >= 0}});
|
||||
}
|
||||
}
|
||||
//SETHI (or NOP if rd == 0 and imm == 0)
|
||||
@@ -163,52 +96,25 @@ decode OP default Unknown::unknown()
|
||||
0x5: decode COND2 {
|
||||
format BranchN {
|
||||
//Branch Always
|
||||
0x8: decode A
|
||||
{
|
||||
0x0: fbpa(22, {{
|
||||
NNPC = xc->readPC() + disp;
|
||||
}});
|
||||
0x1: fbpa(22, {{
|
||||
NPC = xc->readPC() + disp;
|
||||
NNPC = NPC + 4;
|
||||
}}, ',a');
|
||||
}
|
||||
0x8: fbpa(22, annul_code={{
|
||||
NPC = xc->readPC() + disp;
|
||||
NNPC = NPC + 4;
|
||||
}});
|
||||
//Branch Never
|
||||
0x0: decode A
|
||||
{
|
||||
0x0: fbpn(22, {{
|
||||
NNPC = NNPC;//Don't do anything
|
||||
}});
|
||||
0x1: fbpn(22, {{
|
||||
NNPC = NPC + 8;
|
||||
NPC = NPC + 4;
|
||||
}}, ',a');
|
||||
}
|
||||
0x0: fbpn(22, {{;}},
|
||||
annul_code={{
|
||||
NNPC = NPC + 8;
|
||||
NPC = NPC + 4;
|
||||
}});
|
||||
default: decode BPCC {
|
||||
0x0: fbpfcc0(19, {{
|
||||
if(passesFpCondition(Fsr<11:10>, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x1: fbpfcc1(19, {{
|
||||
if(passesFpCondition(Fsr<33:32>, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x2: fbpfcc2(19, {{
|
||||
if(passesFpCondition(Fsr<35:34>, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x3: fbpfcc3(19, {{
|
||||
if(passesFpCondition(Fsr<37:36>, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x0: fbpfcc0(19, test=
|
||||
{{passesFpCondition(Fsr<11:10>, COND2)}});
|
||||
0x1: fbpfcc1(19, test=
|
||||
{{passesFpCondition(Fsr<33:32>, COND2)}});
|
||||
0x2: fbpfcc2(19, test=
|
||||
{{passesFpCondition(Fsr<35:34>, COND2)}});
|
||||
0x3: fbpfcc3(19, test=
|
||||
{{passesFpCondition(Fsr<37:36>, COND2)}});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,33 +122,18 @@ decode OP default Unknown::unknown()
|
||||
0x6: decode COND2 {
|
||||
format BranchN {
|
||||
//Branch Always
|
||||
0x8: decode A
|
||||
{
|
||||
0x0: fba(22, {{
|
||||
NNPC = xc->readPC() + disp;
|
||||
}});
|
||||
0x1: fba(22, {{
|
||||
NPC = xc->readPC() + disp;
|
||||
NNPC = NPC + 4;
|
||||
}}, ',a');
|
||||
}
|
||||
0x8: fba(22, annul_code={{
|
||||
NPC = xc->readPC() + disp;
|
||||
NNPC = NPC + 4;
|
||||
}});
|
||||
//Branch Never
|
||||
0x0: decode A
|
||||
{
|
||||
0x0: fbn(22, {{
|
||||
NNPC = NNPC;//Don't do anything
|
||||
}});
|
||||
0x1: fbn(22, {{
|
||||
NNPC = NPC + 8;
|
||||
NPC = NPC + 4;
|
||||
}}, ',a');
|
||||
}
|
||||
default: fbfcc(22, {{
|
||||
if(passesFpCondition(Fsr<11:10>, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x0: fbn(22, {{;}},
|
||||
annul_code={{
|
||||
NNPC = NPC + 8;
|
||||
NPC = NPC + 4;
|
||||
}});
|
||||
default: fbfcc(22, test=
|
||||
{{passesFpCondition(Fsr<11:10>, COND2)}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,20 @@ def template BasicDeclare {{
|
||||
};
|
||||
}};
|
||||
|
||||
// Basic instruction class declaration template.
|
||||
def template BasicDeclareWithMnemonic {{
|
||||
/**
|
||||
* Static instruction class for "%(mnemonic)s".
|
||||
*/
|
||||
class %(class_name)s : public %(base_class)s
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
%(class_name)s(const char * mnemonic, ExtMachInst machInst);
|
||||
%(BasicExecDeclare)s
|
||||
};
|
||||
}};
|
||||
|
||||
// Basic instruction class constructor template.
|
||||
def template BasicConstructor {{
|
||||
inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
||||
@@ -65,6 +79,16 @@ def template BasicConstructor {{
|
||||
}
|
||||
}};
|
||||
|
||||
// Basic instruction class constructor template.
|
||||
def template BasicConstructorWithMnemonic {{
|
||||
inline %(class_name)s::%(class_name)s(const char * mnemonic,
|
||||
ExtMachInst machInst)
|
||||
: %(base_class)s(mnemonic, machInst, %(op_class)s)
|
||||
{
|
||||
%(constructor)s;
|
||||
}
|
||||
}};
|
||||
|
||||
// Basic instruction class execute method template.
|
||||
def template BasicExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
||||
|
||||
@@ -183,7 +183,7 @@ output decoder {{
|
||||
}
|
||||
}};
|
||||
|
||||
def template BranchExecute {{
|
||||
def template JumpExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
@@ -206,65 +206,135 @@ def template BranchExecute {{
|
||||
}
|
||||
}};
|
||||
|
||||
let {{
|
||||
handle_annul = '''
|
||||
{
|
||||
if(A)
|
||||
def template BranchExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
NNPC = NPC + 8;
|
||||
NPC = NPC + 4;
|
||||
//Attempt to execute the instruction
|
||||
Fault fault = NoFault;
|
||||
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
|
||||
if (%(cond)s) {
|
||||
%(code)s;
|
||||
} else {
|
||||
%(fail)s;
|
||||
}
|
||||
|
||||
if(fault == NoFault)
|
||||
{
|
||||
//Write the resulting state to the execution context
|
||||
%(op_wb)s;
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
else
|
||||
{
|
||||
NPC = NPC;
|
||||
NNPC = NNPC;
|
||||
}
|
||||
}'''
|
||||
}};
|
||||
|
||||
def template BranchDecode {{
|
||||
if (A)
|
||||
return new %(class_name)sAnnul("%(mnemonic)s,a", machInst);
|
||||
else
|
||||
return new %(class_name)s("%(mnemonic)s", machInst);
|
||||
}};
|
||||
|
||||
// Primary format for branch instructions:
|
||||
def format Branch(code, *opt_flags) {{
|
||||
(usesImm, code, immCode,
|
||||
rString, iString) = splitOutImm(code)
|
||||
iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
(usesImm, code, immCode,
|
||||
rString, iString) = splitOutImm(code)
|
||||
iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
exec_output = JumpExecute.subst(iop)
|
||||
if usesImm:
|
||||
imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
|
||||
immCode, opt_flags)
|
||||
header_output += BasicDeclare.subst(imm_iop)
|
||||
decoder_output += BasicConstructor.subst(imm_iop)
|
||||
exec_output += JumpExecute.subst(imm_iop)
|
||||
decode_block = ROrImmDecode.subst(iop)
|
||||
else:
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
}};
|
||||
|
||||
let {{
|
||||
def doBranch(name, Name, base, cond,
|
||||
code, annul_code, fail, annul_fail, opt_flags):
|
||||
iop = InstObjParams(name, Name, base,
|
||||
{"code": code,
|
||||
"fail": fail,
|
||||
"cond": cond
|
||||
},
|
||||
opt_flags)
|
||||
header_output = BasicDeclareWithMnemonic.subst(iop)
|
||||
decoder_output = BasicConstructorWithMnemonic.subst(iop)
|
||||
exec_output = BranchExecute.subst(iop)
|
||||
if usesImm:
|
||||
imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
|
||||
immCode, opt_flags)
|
||||
header_output += BasicDeclare.subst(imm_iop)
|
||||
decoder_output += BasicConstructor.subst(imm_iop)
|
||||
exec_output += BranchExecute.subst(imm_iop)
|
||||
decode_block = ROrImmDecode.subst(iop)
|
||||
if annul_code == "None":
|
||||
decode_block = BasicDecodeWithMnemonic.subst(iop)
|
||||
else:
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
decode_block = BranchDecode.subst(iop)
|
||||
|
||||
if annul_code != "None":
|
||||
iop = InstObjParams(name + ',a', Name + 'Annul', base,
|
||||
{"code": annul_code,
|
||||
"fail": annul_fail,
|
||||
"cond": cond
|
||||
},
|
||||
opt_flags)
|
||||
header_output += BasicDeclareWithMnemonic.subst(iop)
|
||||
decoder_output += BasicConstructorWithMnemonic.subst(iop)
|
||||
exec_output += BranchExecute.subst(iop)
|
||||
return (header_output, decoder_output, exec_output, decode_block)
|
||||
|
||||
def doCondBranch(name, Name, base, cond, code, opt_flags):
|
||||
return doBranch(name, Name, base, cond, code, code,
|
||||
'NPC = NPC; NNPC = NNPC;',
|
||||
'NNPC = NPC + 8; NPC = NPC + 4',
|
||||
opt_flags)
|
||||
|
||||
def doUncondBranch(name, Name, base, code, annul_code, opt_flags):
|
||||
return doBranch(name, Name, base, "true", code, annul_code,
|
||||
";", ";", opt_flags)
|
||||
|
||||
default_branch_code = "NNPC = xc->readPC() + disp;"
|
||||
}};
|
||||
|
||||
// Primary format for branch instructions:
|
||||
def format BranchN(bits, code, *opt_flags) {{
|
||||
code = re.sub(r'handle_annul', handle_annul, code)
|
||||
new_opt_flags = []
|
||||
for flag in opt_flags:
|
||||
if flag == ',a':
|
||||
name += ',a'
|
||||
Name += 'Annul'
|
||||
else:
|
||||
new_opt_flags += flag
|
||||
iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, code, new_opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
exec_output = BranchExecute.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
// Format for branch instructions with n bit displacements:
|
||||
def format BranchN(bits, code=default_branch_code,
|
||||
test=None, annul_code=None, *opt_flags) {{
|
||||
if code == "default_branch_code":
|
||||
code = default_branch_code
|
||||
if test != "None":
|
||||
(header_output,
|
||||
decoder_output,
|
||||
exec_output,
|
||||
decode_block) = doCondBranch(name, Name,
|
||||
"BranchNBits<%d>" % bits, test, code, opt_flags)
|
||||
else:
|
||||
(header_output,
|
||||
decoder_output,
|
||||
exec_output,
|
||||
decode_block) = doUncondBranch(name, Name,
|
||||
"BranchNBits<%d>" % bits, code, annul_code, opt_flags)
|
||||
}};
|
||||
|
||||
// Primary format for branch instructions:
|
||||
def format BranchSplit(code, *opt_flags) {{
|
||||
code = re.sub(r'handle_annul', handle_annul, code)
|
||||
iop = InstObjParams(name, Name, 'BranchSplit', code, opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
exec_output = BranchExecute.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
// Format for branch instructions with split displacements:
|
||||
def format BranchSplit(code=default_branch_code,
|
||||
test=None, annul_code=None, *opt_flags) {{
|
||||
if code == "default_branch_code":
|
||||
code = default_branch_code
|
||||
if test != "None":
|
||||
(header_output,
|
||||
decoder_output,
|
||||
exec_output,
|
||||
decode_block) = doCondBranch(name, Name,
|
||||
"BranchSplit", test, code, opt_flags)
|
||||
else:
|
||||
(header_output,
|
||||
decoder_output,
|
||||
exec_output,
|
||||
decode_block) = doUncondBranch(name, Name,
|
||||
"BranchSplit", code, annul_code, opt_flags)
|
||||
}};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user