From 98b00d92fdf89d130630665327143f67ee16d0fe Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Thu, 12 Oct 2006 17:38:06 -0400 Subject: Some support for handling block loads and stores and ASIs properly. src/arch/sparc/isa/bitfields.isa: Added a field to retrieve the asi from the ExtMachInst src/arch/sparc/isa/decoder.isa: Fixed up how the size of memory operations where handled, and use the new EXT_ASI bit field. src/arch/sparc/isa/formats.isa: add includes for the new formats. src/arch/sparc/isa/formats/basic.isa: Add a template for BasicDecodeWithMnemonic which is needed by the unimp format. src/arch/sparc/isa/formats/mem.isa: Change around the memory format to figure out the memory access width on its own. src/arch/sparc/isa/operands.isa: Added support for the operands of block loads/stores which are offset from Frd. src/arch/sparc/utility.hh: Encoded the ASI into the ExtMachInst --HG-- extra : convert_revision : 5c6026a07e3a919e738d27f78beb0faf6b060643 --- src/arch/sparc/isa/bitfields.isa | 4 + src/arch/sparc/isa/decoder.isa | 201 ++++++++++++++++++++++++++--------- src/arch/sparc/isa/formats.isa | 9 ++ src/arch/sparc/isa/formats/basic.isa | 5 + src/arch/sparc/isa/formats/mem.isa | 112 +++++++++++++++---- src/arch/sparc/isa/operands.isa | 8 ++ src/arch/sparc/utility.hh | 13 ++- 7 files changed, 277 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/arch/sparc/isa/bitfields.isa b/src/arch/sparc/isa/bitfields.isa index 27f52fa29..372f5c4ef 100644 --- a/src/arch/sparc/isa/bitfields.isa +++ b/src/arch/sparc/isa/bitfields.isa @@ -76,3 +76,7 @@ def bitfield SIMM11 <10:0>; def bitfield SIMM13 <12:0>; def bitfield SW_TRAP <7:0>; def bitfield X <12>; + +// Extended bitfields which aren't part of the actual instruction. + +def bitfield EXT_ASI <39:32>; diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa index 1384b21a0..7c135a637 100644 --- a/src/arch/sparc/isa/decoder.isa +++ b/src/arch/sparc/isa/decoder.isa @@ -820,92 +820,189 @@ decode OP default Unknown::unknown() } 0x3: decode OP3 { format Load { - 0x00: lduw({{Rd = Mem;}}, {{32}}); - 0x01: ldub({{Rd = Mem;}}, {{8}}); - 0x02: lduh({{Rd = Mem;}}, {{16}}); + 0x00: lduw({{Rd = Mem.uw;}}); + 0x01: ldub({{Rd = Mem.ub;}}); + 0x02: lduh({{Rd = Mem.uhw;}}); 0x03: ldd({{ - uint64_t val = Mem; + uint64_t val = Mem.udw; RdLow = val<31:0>; RdHigh = val<63:32>; - }}, {{64}}); + }}); } format Store { - 0x04: stw({{Mem = Rd.sw;}}, {{32}}); - 0x05: stb({{Mem = Rd.sb;}}, {{8}}); - 0x06: sth({{Mem = Rd.shw;}}, {{16}}); - 0x07: std({{Mem = RdLow<31:0> | (RdHigh<31:0> << 32);}}, {{64}}); + 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);}}); } format Load { - 0x08: ldsw({{Rd = (int32_t)Mem;}}, {{32}}); - 0x09: ldsb({{Rd = (int8_t)Mem;}}, {{8}}); - 0x0A: ldsh({{Rd = (int16_t)Mem;}}, {{16}}); - 0x0B: ldx({{Rd = (int64_t)Mem;}}, {{64}}); + 0x08: ldsw({{Rd = (int32_t)Mem.sw;}}); + 0x09: ldsb({{Rd = (int8_t)Mem.sb;}}); + 0x0A: ldsh({{Rd = (int16_t)Mem.shw;}}); + 0x0B: ldx({{Rd = (int64_t)Mem.sdw;}}); 0x0D: ldstub({{ - Rd = Mem; - Mem = 0xFF; - }}, {{8}}); + Rd = Mem.ub; + Mem.ub = 0xFF; + }}); } - 0x0E: Store::stx({{Mem = Rd}}, {{64}}); + 0x0E: Store::stx({{Mem.udw = Rd}}); 0x0F: LoadStore::swap({{ uint32_t temp = Rd; - Rd = Mem; - Mem = temp; - }}, {{32}}); + Rd = Mem.uw; + Mem.uw = temp; + }}); format Load { - 0x10: lduwa({{Rd = Mem;}}, {{32}}); - 0x11: lduba({{Rd = Mem;}}, {{8}}); - 0x12: lduha({{Rd = Mem;}}, {{16}}); + 0x10: lduwa({{Rd = Mem.uw;}}); + 0x11: lduba({{Rd = Mem.ub;}}); + 0x12: lduha({{Rd = Mem.uhw;}}); 0x13: ldda({{ - uint64_t val = Mem; + uint64_t val = Mem.udw; RdLow = val<31:0>; RdHigh = val<63:32>; - }}, {{64}}); + }}); } format Store { - 0x14: stwa({{Mem = Rd;}}, {{32}}); - 0x15: stba({{Mem = Rd;}}, {{8}}); - 0x16: stha({{Mem = Rd;}}, {{16}}); - 0x17: stda({{Mem = RdLow<31:0> | RdHigh<31:0> << 32;}}, {{64}}); + 0x14: stwa({{Mem.uw = Rd;}}); + 0x15: stba({{Mem.ub = Rd;}}); + 0x16: stha({{Mem.uhw = Rd;}}); + 0x17: stda({{Mem.udw = RdLow<31:0> | RdHigh<31:0> << 32;}}); } format Load { - 0x18: ldswa({{Rd = (int32_t)Mem;}}, {{32}}); - 0x19: ldsba({{Rd = (int8_t)Mem;}}, {{8}}); - 0x1A: ldsha({{Rd = (int16_t)Mem;}}, {{16}}); - 0x1B: ldxa({{Rd = (int64_t)Mem;}}, {{64}}); + 0x18: ldswa({{Rd = (int32_t)Mem.sw;}}); + 0x19: ldsba({{Rd = (int8_t)Mem.sb;}}); + 0x1A: ldsha({{Rd = (int16_t)Mem.shw;}}); + 0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}); } 0x1D: LoadStore::ldstuba({{ - Rd = Mem; - Mem = 0xFF; - }}, {{8}}); - 0x1E: Store::stxa({{Mem = Rd}}, {{64}}); + Rd = Mem.ub; + Mem.ub = 0xFF; + }}); + 0x1E: Store::stxa({{Mem.udw = Rd}}); 0x1F: LoadStore::swapa({{ uint32_t temp = Rd; - Rd = Mem; - Mem = temp; - }}, {{32}}); + Rd = Mem.uw; + Mem.uw = temp; + }}); format Trap { - 0x20: Load::ldf({{Frd.uw = Mem;}}, {{32}}); + 0x20: Load::ldf({{Frd.uw = Mem.uw;}}); 0x21: decode X { - 0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}}); - 0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}}); + 0x0: Load::ldfsr({{Fsr = Mem.uw | Fsr<63:32>;}}); + 0x1: Load::ldxfsr({{Fsr = Mem.udw;}}); } 0x22: ldqf({{fault = new FpDisabled;}}); - 0x23: Load::lddf({{Frd.udw = Mem;}}, {{64}}); - 0x24: Store::stf({{Mem = Frd.uw;}}, {{32}}); + 0x23: Load::lddf({{Frd.udw = Mem.udw;}}); + 0x24: Store::stf({{Mem.uw = Frd.uw;}}); 0x25: decode X { - 0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}}); - 0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}}); + 0x0: Store::stfsr({{Mem.uw = Fsr<31:0>;}}); + 0x1: Store::stxfsr({{Mem.udw = Fsr;}}); } 0x26: stqf({{fault = new FpDisabled;}}); - 0x27: Store::stdf({{Mem = Frd.udw;}}, {{64}}); + 0x27: Store::stdf({{Mem.udw = Frd.udw;}}); 0x2D: Nop::prefetch({{ }}); - 0x30: Load::ldfa({{Frd.uw = Mem;}}, {{32}}); + 0x30: Load::ldfa({{Frd.uw = Mem.uw;}}); 0x32: ldqfa({{fault = new FpDisabled;}}); - 0x33: Load::lddfa({{Frd.udw = Mem;}}, {{64}}); - 0x34: Store::stfa({{Mem = Frd.uw;}}, {{32}}); + format LoadAlt { + 0x33: decode EXT_ASI { + //ASI_NUCLEUS + 0x04: FailUnimpl::lddfa_n(); + //ASI_NUCLEUS_LITTLE + 0x0C: FailUnimpl::lddfa_nl(); + //ASI_AS_IF_USER_PRIMARY + 0x10: FailUnimpl::lddfa_aiup(); + //ASI_AS_IF_USER_PRIMARY_LITTLE + 0x18: FailUnimpl::lddfa_aiupl(); + //ASI_AS_IF_USER_SECONDARY + 0x11: FailUnimpl::lddfa_aius(); + //ASI_AS_IF_USER_SECONDARY_LITTLE + 0x19: FailUnimpl::lddfa_aiusl(); + //ASI_REAL + 0x14: FailUnimpl::lddfa_real(); + //ASI_REAL_LITTLE + 0x1C: FailUnimpl::lddfa_real_l(); + //ASI_REAL_IO + 0x15: FailUnimpl::lddfa_real_io(); + //ASI_REAL_IO_LITTLE + 0x1D: FailUnimpl::lddfa_real_io_l(); + //ASI_PRIMARY + 0x80: FailUnimpl::lddfa_p(); + //ASI_PRIMARY_LITTLE + 0x88: FailUnimpl::lddfa_pl(); + //ASI_SECONDARY + 0x81: FailUnimpl::lddfa_s(); + //ASI_SECONDARY_LITTLE + 0x89: FailUnimpl::lddfa_sl(); + //ASI_PRIMARY_NO_FAULT + 0x82: FailUnimpl::lddfa_pnf(); + //ASI_PRIMARY_NO_FAULT_LITTLE + 0x8A: FailUnimpl::lddfa_pnfl(); + //ASI_SECONDARY_NO_FAULT + 0x83: FailUnimpl::lddfa_snf(); + //ASI_SECONDARY_NO_FAULT_LITTLE + 0x8B: FailUnimpl::lddfa_snfl(); + + format BlockLoad { + // LDBLOCKF + //ASI_BLOCK_AS_IF_USER_PRIMARY + 0x16: FailUnimpl::ldblockf_aiup(); + //ASI_BLOCK_AS_IF_USER_SECONDARY + 0x17: FailUnimpl::ldblockf_aius(); + //ASI_BLOCK_AS_IF_USER_PRIMARY_LITTLE + 0x1E: FailUnimpl::ldblockf_aiupl(); + //ASI_BLOCK_AS_IF_USER_SECONDARY_LITTLE + 0x1F: FailUnimpl::ldblockf_aiusl(); + //ASI_BLOCK_PRIMARY + 0xF0: ldblockf_p({{Frd_%(micro_pc)d = Mem.udw}}); + //ASI_BLOCK_SECONDARY + 0xF1: FailUnimpl::ldblockf_s(); + //ASI_BLOCK_PRIMARY_LITTLE + 0xF8: FailUnimpl::ldblockf_pl(); + //ASI_BLOCK_SECONDARY_LITTLE + 0xF9: FailUnimpl::ldblockf_sl(); + } + + //LDSHORTF + //ASI_FL8_PRIMARY + 0xD0: FailUnimpl::ldshortf_8p(); + //ASI_FL8_SECONDARY + 0xD1: FailUnimpl::ldshortf_8s(); + //ASI_FL8_PRIMARY_LITTLE + 0xD8: FailUnimpl::ldshortf_8pl(); + //ASI_FL8_SECONDARY_LITTLE + 0xD9: FailUnimpl::ldshortf_8sl(); + //ASI_FL16_PRIMARY + 0xD2: FailUnimpl::ldshortf_16p(); + //ASI_FL16_SECONDARY + 0xD3: FailUnimpl::ldshortf_16s(); + //ASI_FL16_PRIMARY_LITTLE + 0xDA: FailUnimpl::ldshortf_16pl(); + //ASI_FL16_SECONDARY_LITTLE + 0xDB: FailUnimpl::ldshortf_16sl(); + //Not an ASI which is legal with lddfa + default: Trap::lddfa_bad_asi({{fault = new DataAccessException;}}); + + //LoadAlt::lddfa({{ + //Do the actual loading + //if(fault == NoFault) + //{ + //if(AsiIsBlock(asi)) + //{ + //Do the block transfer + //} + //else + //{ + //uint64_t val = Mem; + //if(AsiIsLittle(asi)) + //val = gtole(val); + //Frd.udw = val; + //} + //} + //}}, {{64}});*/ + } + } + 0x34: Store::stfa({{Mem.uw = Frd.uw;}}); 0x36: stqfa({{fault = new FpDisabled;}}); //XXX need to work in the ASI thing - 0x37: Store::stdfa({{Mem = Frd.udw;}}, {{64}}); + 0x37: Store::stdfa({{Mem.udw = Frd.udw;}}); 0x3C: Cas::casa({{ uint64_t val = Mem.uw; if(Rs2.uw == val) diff --git a/src/arch/sparc/isa/formats.isa b/src/arch/sparc/isa/formats.isa index 17d68061b..e044aee1f 100644 --- a/src/arch/sparc/isa/formats.isa +++ b/src/arch/sparc/isa/formats.isa @@ -2,6 +2,9 @@ //Templates from this format are used later ##include "formats/basic.isa" +//Include base classes for microcoding instructions +##include "formats/micro.isa" + //Include the noop format ##include "formats/nop.isa" @@ -11,12 +14,18 @@ //Include the memory format ##include "formats/mem.isa" +//Include the block memory format +##include "formats/blockmem.isa" + //Include the compare and swap format ##include "formats/cas.isa" //Include the trap format ##include "formats/trap.isa" +//Include the unimplemented format +##include "formats/unimp.isa" + //Include the "unknown" format ##include "formats/unknown.isa" diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa index 0a47a7ffe..db77b1a15 100644 --- a/src/arch/sparc/isa/formats/basic.isa +++ b/src/arch/sparc/isa/formats/basic.isa @@ -80,6 +80,11 @@ def template BasicDecode {{ return new %(class_name)s(machInst); }}; +// Basic decode template, passing mnemonic in as string arg to constructor. +def template BasicDecodeWithMnemonic {{ + return new %(class_name)s("%(mnemonic)s", machInst); +}}; + // The most basic instruction format... used only for a few misc. insts def format BasicOperate(code, *flags) {{ iop = InstObjParams(name, Name, 'SparcStaticInst', diff --git a/src/arch/sparc/isa/formats/mem.isa b/src/arch/sparc/isa/formats/mem.isa index 9011c1fc6..88d39d890 100644 --- a/src/arch/sparc/isa/formats/mem.isa +++ b/src/arch/sparc/isa/formats/mem.isa @@ -32,7 +32,7 @@ output header {{ MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : Mem(mnem, _machInst, __opClass) { - imm = sign_ext(SIMM13, 13); + imm = sext<13>(SIMM13); } std::string generateDisassembly(Addr pc, @@ -97,9 +97,10 @@ output decoder {{ return response.str(); } + }}; -def template MemExecute {{ +def template LoadExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { @@ -107,14 +108,14 @@ def template MemExecute {{ Addr EA; %(op_decl)s; %(op_rd)s; + %(priv_check)s; %(ea_code)s; DPRINTF(Sparc, "The address is 0x%x\n", EA); - %(load)s; + xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); %(code)s; if(fault == NoFault) { - %(store)s; //Write the resulting state to the execution context %(op_wb)s; } @@ -123,49 +124,118 @@ def template MemExecute {{ } }}; -let {{ - # Leave memAccessFlags at 0 for now - loadString = "xc->read(EA, (uint%(width)s_t&)Mem, 0);" - storeString = "uint64_t write_result = 0; \ - xc->write((uint%(width)s_t)Mem, EA, 0, &write_result);" +def template StoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + uint64_t write_result = 0; + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(priv_check)s; + %(ea_code)s; + DPRINTF(Sparc, "The address is 0x%x\n", EA); + %(code)s; + + if(fault == NoFault) + { + xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); + //Write the resulting state to the execution context + %(op_wb)s; + } + + return fault; + } +}}; - def doMemFormat(code, load, store, name, Name, opt_flags): +def template LoadStoreExecute {{ + Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, + Trace::InstRecord *traceData) const + { + Fault fault = NoFault; + uint64_t write_result = 0; + Addr EA; + %(op_decl)s; + %(op_rd)s; + %(priv_check)s; + %(ea_code)s; + DPRINTF(Sparc, "The address is 0x%x\n", EA); + xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); + %(code)s; + + if(fault == NoFault) + { + xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); + //Write the resulting state to the execution context + %(op_wb)s; + } + + return fault; + } +}}; + +let {{ + # 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 + privilegedString = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0) + return new PrivilegedAction; + if(AsiIsAsIfUser(EXT_ASI) && !bits(Pstate,2,2)) + return new PrivilegedAction;''' + + def doMemFormat(code, execute, priv, name, Name, opt_flags): addrCalcReg = 'EA = Rs1 + Rs2;' addrCalcImm = 'EA = Rs1 + imm;' iop = InstObjParams(name, Name, 'Mem', code, opt_flags, ("ea_code", addrCalcReg), - ("load", load), ("store", store)) + ("priv_check", priv)) iop_imm = InstObjParams(name, Name + 'Imm', 'MemImm', code, opt_flags, ("ea_code", addrCalcImm), - ("load", load), ("store", store)) + ("priv_check", priv)) header_output = BasicDeclare.subst(iop) + BasicDeclare.subst(iop_imm) decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) - exec_output = MemExecute.subst(iop) + MemExecute.subst(iop_imm) + exec_output = execute.subst(iop) + execute.subst(iop_imm) return (header_output, decoder_output, exec_output, decode_block) }}; -def format Load(code, width, *opt_flags) {{ +def format LoadAlt(code, *opt_flags) {{ + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, LoadExecute, + privelegedString, name, Name, opt_flags) +}}; + +def format StoreAlt(code, *opt_flags) {{ + (header_output, + decoder_output, + exec_output, + decode_block) = doMemFormat(code, StoreExecute, + privilegedString, name, Name, opt_flags) +}}; + +def format Load(code, *opt_flags) {{ (header_output, decoder_output, exec_output, decode_block) = doMemFormat(code, - loadString % {"width":width}, '', name, Name, opt_flags) + LoadExecute, '', name, Name, opt_flags) }}; -def format Store(code, width, *opt_flags) {{ +def format Store(code, *opt_flags) {{ (header_output, decoder_output, exec_output, - decode_block) = doMemFormat(code, '', - storeString % {"width":width}, name, Name, opt_flags) + decode_block) = doMemFormat(code, + StoreExecute, '', name, Name, opt_flags) }}; -def format LoadStore(code, width, *opt_flags) {{ +def format LoadStore(code, *opt_flags) {{ (header_output, decoder_output, exec_output, decode_block) = doMemFormat(code, - loadString % {"width":width}, storeString % {"width":width}, - name, Name, opt_flags) + LoadStoreExecute, '', name, Name, opt_flags) }}; diff --git a/src/arch/sparc/isa/operands.isa b/src/arch/sparc/isa/operands.isa index 605816083..b01443d5b 100644 --- a/src/arch/sparc/isa/operands.isa +++ b/src/arch/sparc/isa/operands.isa @@ -52,6 +52,14 @@ def operands {{ 'Rs1': ('IntReg', 'udw', 'RS1', 'IsInteger', 4), 'Rs2': ('IntReg', 'udw', 'RS2', 'IsInteger', 5), 'Frd': ('FloatReg', 'df', 'RD', 'IsFloating', 10), + 'Frd_0': ('FloatReg', 'df', 'RD', 'IsFloating', 10), + 'Frd_1': ('FloatReg', 'df', 'RD + 1', 'IsFloating', 10), + 'Frd_2': ('FloatReg', 'df', 'RD + 2', 'IsFloating', 10), + 'Frd_3': ('FloatReg', 'df', 'RD + 3', 'IsFloating', 10), + 'Frd_4': ('FloatReg', 'df', 'RD + 4', 'IsFloating', 10), + 'Frd_5': ('FloatReg', 'df', 'RD + 5', 'IsFloating', 10), + 'Frd_6': ('FloatReg', 'df', 'RD + 6', 'IsFloating', 10), + 'Frd_7': ('FloatReg', 'df', 'RD + 7', 'IsFloating', 10), 'Frs1': ('FloatReg', 'df', 'RS1', 'IsFloating', 11), 'Frs2': ('FloatReg', 'df', 'RS2', 'IsFloating', 12), 'Mem': ('Mem', 'udw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 20), diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index f1c071148..796b6ba4c 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -33,12 +33,21 @@ #include "arch/sparc/isa_traits.hh" #include "base/misc.hh" +#include "cpu/thread_context.hh" namespace SparcISA { inline ExtMachInst - makeExtMI(MachInst inst, const Addr &pc) { - return ExtMachInst(inst); + makeExtMI(MachInst inst, ThreadContext * xc) { + ExtMachInst emi = (unsigned MachInst) inst; + //The I bit, bit 13, is used to figure out where the ASI + //should come from. Use that in the ExtMachInst. This is + //slightly redundant, but it removes the need to put a condition + //into all the execute functions + if(inst & (1 << 13)) + emi |= (static_cast(xc->readMiscReg(MISCREG_ASI)) + << (sizeof(MachInst) * 8)); + return emi; } inline bool isCallerSaveIntegerRegister(unsigned int reg) { -- cgit v1.2.3