diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index 58a17f23e..693cc6876 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -67,6 +67,26 @@ output header {{ OverflowSet=0x7 }; + enum FpCondTest + { + FAlways=0x8, + FNever=0x0, + FUnordered=0x7, + FGreater=0x6, + FUnorderedOrGreater=0x5, + FLess=0x4, + FUnorderedOrLess=0x3, + FLessOrGreater=0x2, + FNotEqual=0x1, + FEqual=0x9, + FUnorderedOrEqual=0xA, + FGreaterOrEqual=0xB, + FUnorderedOrGreaterOrEqual=0xC, + FLessOrEqual=0xD, + FUnorderedOrLessOrEqual=0xE, + FOrdered=0xF + }; + extern char * CondTestAbbrev[]; /** @@ -93,6 +113,8 @@ output header {{ const RegIndex indexArray[], int num) const; }; + bool passesFpCondition(uint32_t fcc, uint32_t condition); + bool passesCondition(uint32_t codes, uint32_t condition); inline int64_t sign_ext(uint64_t data, int origWidth) @@ -367,6 +389,51 @@ output decoder {{ return ss.str(); } + bool passesFpCondition(uint32_t fcc, uint32_t condition) + { + bool u = (fcc == 3); + bool g = (fcc == 2); + bool l = (fcc == 1); + bool e = (fcc == 0); + switch(condition) + { + case FAlways: + return 1; + case FNever: + return 0; + case FUnordered: + return u; + case FGreater: + return g; + case FUnorderedOrGreater: + return u || g; + case FLess: + return l; + case FUnorderedOrLess: + return u || l; + case FLessOrGreater: + return l || g; + case FNotEqual: + return l || g || u; + case FEqual: + return e; + case FUnorderedOrEqual: + return u || e; + case FGreaterOrEqual: + return g || e; + case FUnorderedOrGreaterOrEqual: + return u || g || e; + case FLessOrEqual: + return l || e; + case FUnorderedOrLessOrEqual: + return u || l || e; + case FOrdered: + return e || l || g; + } + panic("Tried testing condition nonexistant " + "condition code %d", condition); + } + bool passesCondition(uint32_t codes, uint32_t condition) { CondCodes condCodes; diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 9658578f2..8edb51546 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -62,8 +62,8 @@ decode OP default Unknown::unknown() NNPC = NNPC;//Don't do anything }}); 0x1: bpn(19, {{ - NPC = xc->readNextPC() + 4; - NNPC = NPC + 4; + NNPC = NPC + 8; + NPC = NPC + 4; }}, ',a'); } default: decode BPCC @@ -76,15 +76,9 @@ decode OP default Unknown::unknown() }}); 0x2: bpccx(19, {{ if(passesCondition(Ccr<7:4>, COND2)) - { - //warn("Took branch!\n"); NNPC = xc->readPC() + disp; - } else - { - //warn("Didn't take branch!\n"); handle_annul - } }}); } } @@ -109,8 +103,8 @@ decode OP default Unknown::unknown() NNPC = NNPC;//Don't do anything }}); 0x1: bn(22, {{ - NPC = xc->readNextPC() + 4; - NNPC = NPC + 4; + NNPC = NPC + 8; + NPC = NPC + 4; }}, ',a'); } default: bicc(22, {{ @@ -165,8 +159,92 @@ decode OP default Unknown::unknown() } //SETHI (or NOP if rd == 0 and imm == 0) 0x4: SetHi::sethi({{Rd.udw = imm;}}); - 0x5: FailUnimpl::fbpfcc(); - 0x6: FailUnimpl::fbfcc(); + //fbpfcc + 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'); + } + //Branch Never + 0x0: decode A + { + 0x0: fbpn(22, {{ + NNPC = NNPC;//Don't do anything + }}); + 0x1: fbpn(22, {{ + NNPC = NPC + 8; + NPC = NPC + 4; + }}, ',a'); + } + default: decode BPCC { + 0x0: fbpcc0(22, {{ + if(passesFpCondition(Fsr<11:10>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x1: fbpcc1(22, {{ + if(passesFpCondition(Fsr<33:32>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x2: fbpcc2(22, {{ + if(passesFpCondition(Fsr<35:34>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + 0x3: fbpcc3(22, {{ + if(passesFpCondition(Fsr<37:36>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + } + } + } + //fbfcc + 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'); + } + //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 + }}); + } + } } 0x1: BranchN::call(30, {{ if (Pstate<3:>) diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa index 59c6346d6..5cd3ab598 100644 --- a/src/arch/sparc/isa/formats/branch.isa +++ b/src/arch/sparc/isa/formats/branch.isa @@ -211,13 +211,13 @@ let {{ { if(A) { - NPC = xc->readNextNPC(); - NNPC = NPC + 4; + NNPC = NPC + 8; + NPC = NPC + 4; } else { - NPC = xc->readNextPC(); - NNPC = xc->readNextNPC(); + NPC = NPC; + NNPC = NNPC; } }''' }};