diff options
Diffstat (limited to 'arch/sparc/isa/base.isa')
-rw-r--r-- | arch/sparc/isa/base.isa | 141 |
1 files changed, 116 insertions, 25 deletions
diff --git a/arch/sparc/isa/base.isa b/arch/sparc/isa/base.isa index 992504369..cb370a3e7 100644 --- a/arch/sparc/isa/base.isa +++ b/arch/sparc/isa/base.isa @@ -5,15 +5,19 @@ output header {{ - struct condCodes + union CondCodes { - uint8_t c:1; - uint8_t v:1; - uint8_t z:1; - uint8_t n:1; - } + struct + { + uint8_t c:1; + uint8_t v:1; + uint8_t z:1; + uint8_t n:1; + }; + uint32_t bits; + }; - enum condTest + enum CondTest { Always=0x8, Never=0x0, @@ -31,7 +35,9 @@ output header {{ Negative=0x6, OverflowClear=0xF, OverflowSet=0x7 - } + }; + + extern char * CondTestAbbrev[]; /** * Base class for all SPARC static instructions. @@ -48,19 +54,100 @@ output header {{ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; + + void printReg(std::ostream &os, int reg) const; }; - bool passesCondition(condCodes codes, condTest condition); + bool passesCondition(uint32_t codes, uint32_t condition); + + inline int64_t sign_ext(uint64_t data, int origWidth) + { + int shiftAmount = 64 - origWidth; + return (((int64_t)data) << shiftAmount) >> shiftAmount; + } }}; output decoder {{ + char * CondTestAbbrev[] = + { + "nev", //Never + "e", //Equal + "le", //Less or Equal + "l", //Less + "leu", //Less or Equal Unsigned + "c", //Carry set + "n", //Negative + "o", //Overflow set + "a", //Always + "ne", //Not Equal + "g", //Greater + "ge", //Greater or Equal + "gu", //Greater Unsigned + "cc", //Carry clear + "p", //Positive + "oc" //Overflow Clear + }; +}}; + +def template ROrImmDecode {{ + { + return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst)) + : (SparcStaticInst *)(new %(class_name)s(machInst))); + } +}}; + +let {{ + def splitOutImm(code): + matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)') + rOrImmMatch = matcher.search(code) + if (rOrImmMatch == None): + return (False, code, '', '', '') + rString = rOrImmMatch.group("rNum") + iString = rOrImmMatch.group("iNum") + orig_code = code + code = matcher.sub('Rs' + rOrImmMatch.group("rNum"), orig_code) + imm_code = matcher.sub('imm', orig_code) + return (True, code, imm_code, rString, iString) +}}; + +output decoder {{ + + inline void printMnemonic(std::ostream &os, const char * mnemonic) + { + ccprintf(os, "\t%s ", mnemonic); + } + + void + SparcStaticInst::printReg(std::ostream &os, int reg) const + { + const int MaxGlobal = 8; + const int MaxOutput = 16; + const int MaxLocal = 24; + const int MaxInput = 32; + if (reg == FramePointerReg) + ccprintf(os, "%%fp"); + else if (reg == StackPointerReg) + ccprintf(os, "%%sp"); + else if(reg < MaxGlobal) + ccprintf(os, "%%g%d", reg); + else if(reg < MaxOutput) + ccprintf(os, "%%o%d", reg - MaxGlobal); + else if(reg < MaxLocal) + ccprintf(os, "%%l%d", reg - MaxOutput); + else if(reg < MaxInput) + ccprintf(os, "%%i%d", reg - MaxLocal); + else { + ccprintf(os, "%%f%d", reg - FP_Base_DepTag); + } + } + std::string SparcStaticInst::generateDisassembly(Addr pc, const SymbolTable *symtab) const { std::stringstream ss; - ccprintf(ss, "%-10s ", mnemonic); + printMnemonic(ss, mnemonic); // just print the first two source regs... if there's // a third one, it's a read-modify-write dest (Rc), @@ -87,8 +174,10 @@ output decoder {{ return ss.str(); } - bool passesCondition(condCodes codes, condTest condition) + bool passesCondition(uint32_t codes, uint32_t condition) { + CondCodes condCodes; + condCodes.bits = codes; switch(condition) { case Always: @@ -96,34 +185,36 @@ output decoder {{ case Never: return false; case NotEqual: - return !codes.z; + return !condCodes.z; case Equal: - return codes.z; + return condCodes.z; case Greater: - return !(codes.z | (codes.n ^ codes.v)); + return !(condCodes.z | (condCodes.n ^ condCodes.v)); case LessOrEqual: - return codes.z | (codes.n ^ codes.v); + return condCodes.z | (condCodes.n ^ condCodes.v); case GreaterOrEqual: - return !(codes.n ^ codes.v); + return !(condCodes.n ^ condCodes.v); case Less: - return (codes.n ^ codes.v); + return (condCodes.n ^ condCodes.v); case GreaterUnsigned: - return !(codes.c | codes.z); + return !(condCodes.c | condCodes.z); case LessOrEqualUnsigned: - return (codes.c | codes.z); + return (condCodes.c | condCodes.z); case CarryClear: - return !codes.c; + return !condCodes.c; case CarrySet: - return codes.c; + return condCodes.c; case Positive: - return !codes.n; + return !condCodes.n; case Negative: - return codes.n; + return condCodes.n; case OverflowClear: - return !codes.v; + return !condCodes.v; case OverflowSet: - return codes.v; + return condCodes.v; } + panic("Tried testing condition nonexistant " + "condition code %d", condition); } }}; |