diff options
-rw-r--r-- | src/arch/sparc/isa/decoder.isa | 20 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/mem/blockmem.isa | 210 | ||||
-rw-r--r-- | src/arch/sparc/isa/formats/mem/util.isa | 6 | ||||
-rw-r--r-- | src/arch/sparc/isa/operands.isa | 3 | ||||
-rw-r--r-- | src/arch/sparc/system.hh | 6 |
5 files changed, 238 insertions, 7 deletions
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 5c69598d5..e8578291c 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -1009,7 +1009,7 @@ decode OP default Unknown::unknown() 0x00: lduw({{Rd = Mem.uw;}}); 0x01: ldub({{Rd = Mem.ub;}}); 0x02: lduh({{Rd = Mem.uhw;}}); - 0x03: ldd({{ + 0x03: ldtw({{ uint64_t val = Mem.udw; RdLow = val<31:0>; RdHigh = val<63:32>; @@ -1019,7 +1019,7 @@ decode OP default Unknown::unknown() 0x04: stw({{Mem.uw = Rd.sw;}}); 0x05: stb({{Mem.ub = Rd.sb;}}); 0x06: sth({{Mem.uhw = Rd.shw;}}); - 0x07: std({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}}); + 0x07: sttw({{Mem.udw = RdLow<31:0> | (RdHigh<31:0> << 32);}}); } format Load { 0x08: ldsw({{Rd = (int32_t)Mem.sw;}}); @@ -1039,7 +1039,7 @@ decode OP default Unknown::unknown() 0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}}); 0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}}); 0x12: lduha({{Rd = Mem.uhw;}}, {{EXT_ASI}}); - 0x13: ldda({{ + 0x13: ldtwa({{ uint64_t val = Mem.udw; RdLow = val<31:0>; RdHigh = val<63:32>; @@ -1049,7 +1049,7 @@ decode OP default Unknown::unknown() 0x14: stwa({{Mem.uw = Rd;}}, {{EXT_ASI}}); 0x15: stba({{Mem.ub = Rd;}}, {{EXT_ASI}}); 0x16: stha({{Mem.uhw = Rd;}}, {{EXT_ASI}}); - 0x17: stda({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}}); + 0x17: sttwa({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{EXT_ASI}}); } format LoadAlt { 0x18: ldswa({{Rd = (int32_t)Mem.sw;}}, {{EXT_ASI}}); @@ -1105,6 +1105,18 @@ decode OP default Unknown::unknown() 0x15: FailUnimpl::lddfa_real_io(); //ASI_REAL_IO_LITTLE 0x1D: FailUnimpl::lddfa_real_io_l(); + //ASI_LDTX_REAL + 0x26: TwinLoad::ldtx_real( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); + //ASI_LDTX_N + 0x27: TwinLoad::ldtx_n( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); + //ASI_LDTX_REAL_L + 0x2E: TwinLoad::ldtx_real_l( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); + //ASI_LDTX_N_L + 0x2F: TwinLoad::ldtx_n_l( + {{RdTwin.udw = Mem.udw}}, {{EXT_ASI}}); //ASI_PRIMARY 0x80: FailUnimpl::lddfa_p(); //ASI_PRIMARY_LITTLE diff --git a/src/arch/sparc/isa/formats/mem/blockmem.isa b/src/arch/sparc/isa/formats/mem/blockmem.isa index a0b235a61..25fffc02b 100644 --- a/src/arch/sparc/isa/formats/mem/blockmem.isa +++ b/src/arch/sparc/isa/formats/mem/blockmem.isa @@ -91,6 +91,65 @@ output header {{ }; }}; +output header {{ + + class TwinMem : public SparcMacroInst + { + protected: + + // Constructor + // We make the assumption that all block memory operations + // Will take 8 instructions to execute + TwinMem(const char *mnem, ExtMachInst _machInst) : + SparcMacroInst(mnem, _machInst, No_OpClass, 8) + {} + }; + + class TwinMemImm : public BlockMem + { + protected: + + // Constructor + TwinMemImm(const char *mnem, ExtMachInst _machInst) : + BlockMem(mnem, _machInst) + {} + }; + + class TwinMemMicro : public SparcMicroInst + { + protected: + + // Constructor + TwinMemMicro(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, int8_t _offset) : + SparcMicroInst(mnem, _machInst, __opClass), + offset(_offset) + {} + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + const int8_t offset; + }; + + class TwinMemImmMicro : public BlockMemMicro + { + protected: + + // Constructor + TwinMemImmMicro(const char *mnem, ExtMachInst _machInst, + OpClass __opClass, int8_t _offset) : + BlockMemMicro(mnem, _machInst, __opClass, _offset), + imm(sext<13>(SIMM13)) + {} + + std::string generateDisassembly(Addr pc, + const SymbolTable *symtab) const; + + const int32_t imm; + }; +}}; + output decoder {{ std::string BlockMemMicro::generateDisassembly(Addr pc, const SymbolTable *symtab) const @@ -149,6 +208,64 @@ output decoder {{ }}; +output decoder {{ + std::string TwinMemMicro::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + bool load = flags[IsLoad]; + bool save = flags[IsStore]; + + printMnemonic(response, mnemonic); + if(save) + { + printReg(response, _srcRegIdx[0]); + ccprintf(response, ", "); + } + ccprintf(response, "[ "); + printReg(response, _srcRegIdx[!save ? 0 : 1]); + ccprintf(response, " + "); + printReg(response, _srcRegIdx[!save ? 1 : 2]); + ccprintf(response, " ]"); + if(load) + { + ccprintf(response, ", "); + printReg(response, _destRegIdx[0]); + } + + return response.str(); + } + + std::string TwinMemImmMicro::generateDisassembly(Addr pc, + const SymbolTable *symtab) const + { + std::stringstream response; + bool load = flags[IsLoad]; + bool save = flags[IsStore]; + + printMnemonic(response, mnemonic); + if(save) + { + printReg(response, _srcRegIdx[1]); + ccprintf(response, ", "); + } + ccprintf(response, "[ "); + printReg(response, _srcRegIdx[0]); + if(imm >= 0) + ccprintf(response, " + 0x%x ]", imm); + else + ccprintf(response, " + -0x%x ]", -imm); + if(load) + { + ccprintf(response, ", "); + printReg(response, _destRegIdx[0]); + } + + return response.str(); + } + +}}; + def template BlockMemDeclare {{ /** * Static instruction class for a block memory operation @@ -242,6 +359,39 @@ def template BlockMemDeclare {{ }; }}; +def template TwinMemDeclare {{ + /** + * Static instruction class for a block memory operation + */ + class %(class_name)s : public %(base_class)s + { + public: + //Constructor + %(class_name)s(ExtMachInst machInst); + + protected: + class %(class_name)s_0 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_0(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + + class %(class_name)s_1 : public %(base_class)sMicro + { + public: + //Constructor + %(class_name)s_1(ExtMachInst machInst); + %(BasicExecDeclare)s + %(InitiateAccDeclare)s + %(CompleteAccDeclare)s + }; + }; +}}; + // Basic instruction class constructor template. def template BlockMemConstructor {{ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) @@ -259,6 +409,17 @@ def template BlockMemConstructor {{ } }}; +// Basic instruction class constructor template. +def template TwinMemConstructor {{ + inline %(class_name)s::%(class_name)s(ExtMachInst machInst) + : %(base_class)s("%(mnemonic)s", machInst) + { + %(constructor)s; + microOps[0] = new %(class_name)s_0(machInst); + microOps[1] = new %(class_name)s_1(machInst); + } +}}; + def template BlockMemMicroConstructor {{ inline %(class_name)s:: %(class_name)s_%(micro_pc)s:: @@ -312,6 +473,47 @@ let {{ asi, opt_flags); faultCode = '' return (header_output, decoder_output, exec_output, decode_block) + + + def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags): + addrCalcReg = 'EA = Rs1 + Rs2 + offset;' + addrCalcImm = 'EA = Rs1 + imm + offset;' + iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags) + iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags) + header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm) + decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm) + decode_block = ROrImmDecode.subst(iop) + matcher = re.compile(r'RdTwin') + exec_output = '' + for microPc in range(2): + flag_code = '' + pcedCode = '' + if (microPc == 1): + flag_code = "flags[IsLastMicroOp] = true;" + pcedCode = matcher.sub("RdHigh", code) + else: + flag_code = "flags[IsDelayedCommit] = true;" + pcedCode = matcher.sub("RdLow", code) + iop = InstObjParams(name, Name, 'TwinMem', pcedCode, + opt_flags, {"ea_code": addrCalcReg, + "fault_check": faultCode, "micro_pc": microPc, + "set_flags": flag_code}) + iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', pcedCode, + opt_flags, {"ea_code": addrCalcImm, + "fault_check": faultCode, "micro_pc": microPc, + "set_flags": flag_code}) + decoder_output += BlockMemMicroConstructor.subst(iop) + decoder_output += BlockMemMicroConstructor.subst(iop_imm) + exec_output += doDualSplitExecute( + pcedCode, addrCalcReg, addrCalcImm, LoadExecute, faultCode, + makeMicroName(name, microPc), + makeMicroName(name + "Imm", microPc), + makeMicroName(Name, microPc), + makeMicroName(Name + "Imm", microPc), + asi, opt_flags); + faultCode = '' + return (header_output, decoder_output, exec_output, decode_block) + }}; def format BlockLoad(code, asi, *opt_flags) {{ @@ -337,3 +539,11 @@ def format BlockStore(code, asi, *opt_flags) {{ decode_block) = doBlockMemFormat(code, faultCode, StoreFuncs, name, Name, asi, opt_flags) }}; + +def format TwinLoad(code, asi, *opt_flags) {{ + faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck + (header_output, + decoder_output, + exec_output, + decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags) +}}; diff --git a/src/arch/sparc/isa/formats/mem/util.isa b/src/arch/sparc/isa/formats/mem/util.isa index 03b08ae18..87a841270 100644 --- a/src/arch/sparc/isa/formats/mem/util.isa +++ b/src/arch/sparc/isa/formats/mem/util.isa @@ -295,6 +295,12 @@ let {{ else if(EA & 0x3f) fault = new MemAddressNotAligned; ''' + TwinAlignmentFaultCheck = ''' + if(RD & 0xe) + fault = new IllegalInstruction; + else if(EA & 0x1f) + fault = new MemAddressNotAligned; + ''' # XXX Need to take care of pstate.hpriv as well. The lower ASIs # are split into ones that are available in priv and hpriv, and # those that are only available in hpriv diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 256f2fa43..2d1c3d3b9 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -62,6 +62,9 @@ def operands {{ 'Rd_prev': ('IntReg', 'udw', 'RD + NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 2), # The Rd from the next window 'Rd_next': ('IntReg', 'udw', 'RD + 2 * NumIntArchRegs + NumMicroIntRegs', 'IsInteger', 3), + # For microcoded twin load instructions, RdTwin appears in the "code" + # for the instruction is replaced by RdLow or RdHigh by the format + # before it's processed by the iop. # The low (even) register of a two register pair 'RdLow': ('IntReg', 'udw', 'RD & (~1)', 'IsInteger', 4), # The high (odd) register of a two register pair diff --git a/src/arch/sparc/system.hh b/src/arch/sparc/system.hh index 5d50ea067..c81b093e8 100644 --- a/src/arch/sparc/system.hh +++ b/src/arch/sparc/system.hh @@ -133,21 +133,21 @@ class SparcSystem : public System /** Add a function-based event to reset binary. */ template <class T> - T *SparcSystem::addResetFuncEvent(const char *lbl) + T *addResetFuncEvent(const char *lbl) { return addFuncEvent<T>(resetSymtab, lbl); } /** Add a function-based event to the hypervisor. */ template <class T> - T *SparcSystem::addHypervisorFuncEvent(const char *lbl) + T *addHypervisorFuncEvent(const char *lbl) { return addFuncEvent<T>(hypervisorSymtab, lbl); } /** Add a function-based event to the openboot. */ template <class T> - T *SparcSystem::addOpenbootFuncEvent(const char *lbl) + T *addOpenbootFuncEvent(const char *lbl) { return addFuncEvent<T>(openbootSymtab, lbl); } |