diff options
Diffstat (limited to 'src/arch/sparc/isa')
-rw-r--r-- | src/arch/sparc/isa/base.isa | 10 | ||||
-rw-r--r-- | src/arch/sparc/isa/decoder.isa | 70 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/priv.isa | 140 | ||||
-rw-r--r-- | src/arch/sparc/isa/operands.isa | 1 |
4 files changed, 201 insertions, 20 deletions
diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa index a4c022411..aa24c75be 100644 --- a/src/arch/sparc/isa/base.isa +++ b/src/arch/sparc/isa/base.isa @@ -189,6 +189,7 @@ output decoder {{ const int MaxOutput = 16; const int MaxLocal = 24; const int MaxInput = 32; + const int MaxMicroReg = 33; if (reg == FramePointerReg) ccprintf(os, "%%fp"); else if (reg == StackPointerReg) @@ -201,6 +202,8 @@ output decoder {{ ccprintf(os, "%%l%d", reg - MaxOutput); else if(reg < MaxInput) ccprintf(os, "%%i%d", reg - MaxLocal); + else if(reg < MaxMicroReg) + ccprintf(os, "%%u%d", reg - MaxInput); else { ccprintf(os, "%%f%d", reg - FP_Base_DepTag); } @@ -241,7 +244,12 @@ output decoder {{ bool passesCondition(uint32_t codes, uint32_t condition) { CondCodes condCodes; - condCodes.bits = codes; + condCodes.bits = 0; + condCodes.c = codes & 0x1 ? 1 : 0; + condCodes.v = codes & 0x2 ? 1 : 0; + condCodes.z = codes & 0x4 ? 1 : 0; + condCodes.n = codes & 0x8 ? 1 : 0; + switch(condition) { case Always: diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 4f3ea7810..2c8e59a1d 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -41,15 +41,16 @@ decode OP default Unknown::unknown() 0x0: Trap::illtrap({{fault = new IllegalInstruction;}}); format BranchN { + //bpcc 0x1: decode COND2 { //Branch Always 0x8: decode A { - 0x0: b(19, {{ + 0x0: bpa(19, {{ NNPC = xc->readPC() + disp; }}); - 0x1: b(19, {{ + 0x1: bpa(19, {{ NPC = xc->readPC() + disp; NNPC = NPC + 4; }}, ',a'); @@ -57,10 +58,10 @@ decode OP default Unknown::unknown() //Branch Never 0x0: decode A { - 0x0: bn(19, {{ + 0x0: bpn(19, {{ NNPC = NNPC;//Don't do anything }}); - 0x1: bn(19, {{ + 0x1: bpn(19, {{ NPC = xc->readNextPC() + 4; NNPC = NPC + 4; }}, ',a'); @@ -81,12 +82,38 @@ decode OP default Unknown::unknown() }}); } } - 0x2: bicc(22, {{ - if(passesCondition(Ccr<3:0>, COND2)) - NNPC = xc->readPC() + disp; - else - handle_annul - }}); + //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'); + } + //Branch Never + 0x0: decode A + { + 0x0: bn(22, {{ + NNPC = NNPC;//Don't do anything + }}); + 0x1: bn(22, {{ + NPC = xc->readNextPC() + 4; + NNPC = NPC + 4; + }}, ',a'); + } + default: bicc(22, {{ + if(passesCondition(Ccr<3:0>, COND2)) + NNPC = xc->readPC() + disp; + else + handle_annul + }}); + } } 0x3: decode RCOND2 { @@ -380,7 +407,15 @@ decode OP default Unknown::unknown() 0x17: Priv::rdtick_cmpr({{Rd = TickCmpr;}}); 0x18: PrivCheck::rdstick({{Rd = Stick}}, {{Stick<63:>}}); 0x19: Priv::rdstick_cmpr({{Rd = StickCmpr;}}); - //0x1A-0x1F should cause an illegal instruction exception + 0x1A: Priv::rdstrand_sts_reg({{ + if(Pstate<2:> && !Hpstate<2:>) + Rd = StrandStsReg<0:>; + else + Rd = StrandStsReg; + }}); + //0x1A is supposed to be reserved, but it reads the strand + //status register. + //0x1B-0x1F should cause an illegal instruction exception } 0x29: decode RS1 { 0x00: HPriv::rdhprhpstate({{Rd = Hpstate;}}); @@ -515,7 +550,16 @@ decode OP default Unknown::unknown() Stick = Rs1 ^ Rs2_or_imm13; }}); 0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}}); - //0x1A-0x1F should cause an illegal instruction exception + 0x1A: Priv::wrstrand_sts_reg({{ + if(Pstate<2:> && !Hpstate<2:>) + StrandStsReg = StrandStsReg<63:1> | + (Rs1 ^ Rs2_or_imm13)<0:>; + else + StrandStsReg = Rs1 ^ Rs2_or_imm13; + }}); + //0x1A is supposed to be reserved, but it writes the strand + //status register. + //0x1B-0x1F should cause an illegal instruction exception } 0x31: decode FCN { 0x0: Priv::saved({{ @@ -527,7 +571,7 @@ decode OP default Unknown::unknown() else Otherwin = Otherwin - 1; }}); - 0x1: BasicOperate::restored({{ + 0x1: Priv::restored({{ assert(Cansave || Otherwin); assert(Canrestore < NWindows - 2); Canrestore = Canrestore + 1; diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa index 55bf968f4..94a68aebe 100644 --- a/src/arch/sparc/isa/formats/priv.isa +++ b/src/arch/sparc/isa/formats/priv.isa @@ -50,6 +50,42 @@ output header {{ const SymbolTable *symtab) const; }; + //This class is for instructions that explicitly read control + //registers. It provides a special generateDisassembly function. + class RdPriv : public Priv + { + protected: + //Constructor + RdPriv(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, char const * _regName) : + Priv(mnem, _machInst, __opClass), regName(_regName) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + char const * regName; + }; + + //This class is for instructions that explicitly write control + //registers. It provides a special generateDisassembly function. + class WrPriv : public Priv + { + protected: + //Constructor + WrPriv(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, char const * _regName) : + Priv(mnem, _machInst, __opClass), regName(_regName) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + char const * regName; + }; + /** * Base class for privelege mode operations with immediates. */ @@ -66,6 +102,23 @@ output header {{ int32_t imm; }; + //This class is for instructions that explicitly write control + //registers. It provides a special generateDisassembly function. + class WrPrivImm : public PrivImm + { + protected: + //Constructor + WrPrivImm(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, char const * _regName) : + PrivImm(mnem, _machInst, __opClass), regName(_regName) + { + } + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + char const * regName; + }; }}; output decoder {{ @@ -78,6 +131,58 @@ output decoder {{ return response.str(); } + + std::string RdPriv::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + + ccprintf(response, " %%%s, ", regName); + printDestReg(response, 0); + + return response.str(); + } + + std::string WrPriv::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + + ccprintf(response, " "); + printSrcReg(response, 0); + ccprintf(response, ", "); + printSrcReg(response, 1); + ccprintf(response, ", %%%s", regName); + + return response.str(); + } + + std::string WrPrivImm::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + + printMnemonic(response, mnemonic); + + ccprintf(response, " "); + printSrcReg(response, 0); + ccprintf(response, ", 0x%x, %%%s", imm, regName); + + return response.str(); + } +}}; + +def template ControlRegConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst, + %(op_class)s, "%(reg_name)s") + { + %(constructor)s; + } }}; def template PrivExecute {{ @@ -102,16 +207,39 @@ let {{ def doPrivFormat(code, checkCode, name, Name, opt_flags): (usesImm, code, immCode, rString, iString) = splitOutImm(code) - iop = InstObjParams(name, Name, 'Priv', code, - opt_flags, {"check": checkCode}) + #If these are rd, rdpr, rdhpr, wr, wrpr, or wrhpr instructions, + #cut any other info out of the mnemonic. Also pick a different + #base class. + regBase = 'Priv' + regName = '' + for mnem in ["rdhpr", "rdpr", "rd"]: + if name.startswith(mnem): + regName = name[len(mnem):] + name = mnem + regBase = 'RdPriv' + break + for mnem in ["wrhpr", "wrpr", "wr"]: + if name.startswith(mnem): + regName = name[len(mnem):] + name = mnem + regBase = 'WrPriv' + break + iop = InstObjParams(name, Name, regBase, code, + opt_flags, {"check": checkCode, "reg_name": regName}) header_output = BasicDeclare.subst(iop) - decoder_output = BasicConstructor.subst(iop) + if regName == '': + decoder_output = BasicConstructor.subst(iop) + else: + decoder_output = ControlRegConstructor.subst(iop) exec_output = PrivExecute.subst(iop) if usesImm: - imm_iop = InstObjParams(name, Name + 'Imm', 'PrivImm', - immCode, opt_flags, {"check": checkCode}) + imm_iop = InstObjParams(name, Name + 'Imm', regBase + 'Imm', + immCode, opt_flags, {"check": checkCode, "reg_name": regName}) header_output += BasicDeclare.subst(imm_iop) - decoder_output += BasicConstructor.subst(imm_iop) + if regName == '': + decoder_output += BasicConstructor.subst(imm_iop) + else: + decoder_output += ControlRegConstructor.subst(imm_iop) exec_output += PrivExecute.subst(imm_iop) decode_block = ROrImmDecode.subst(iop) else: diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index caee20b0c..2d200f568 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -123,6 +123,7 @@ def operands {{ 'Htba': ('ControlReg', 'udw', 'MISCREG_HTBA', None, 72), 'HstickCmpr': ('ControlReg', 'udw', 'MISCREG_HSTICK_CMPR', None, 73), 'Hver': ('ControlReg', 'udw', 'MISCREG_HVER', None, 74), + 'StrandStsReg': ('ControlReg', 'udw', 'MISCREG_STRAND_STS_REG', None, 75), 'Fsr': ('ControlReg', 'udw', 'MISCREG_FSR', None, 80), # Mem gets a large number so it's always last |