//////////////////////////////////////////////////////////////////// // // Mem instructions // output header {{ /** * Base class for memory operations. */ class Mem : public SparcStaticInst { protected: // Constructor Mem(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : SparcStaticInst(mnem, _machInst, __opClass) { } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; }; /** * Class for memory operations which use an immediate offset. */ class MemImm : public Mem { protected: // Constructor MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) : Mem(mnem, _machInst, __opClass) { imm = sext<13>(SIMM13); } std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; int32_t imm; }; }}; output decoder {{ std::string Mem::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 MemImm::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]); 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 LoadExecute {{ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const { Fault fault = NoFault; Addr EA; %(op_decl)s; %(op_rd)s; %(priv_check)s; %(ea_code)s; DPRINTF(Sparc, "The address is 0x%x\n", EA); fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); %(code)s; if(fault == NoFault) { //Write the resulting state to the execution context %(op_wb)s; } return fault; } Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { Fault fault = NoFault; Addr EA; uint%(mem_acc_size)s_t Mem; %(ea_decl)s; %(ea_rd)s; %(priv_check)s; %(ea_code)s; fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, 0); return fault; } Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { Fault fault = NoFault; %(code_decl)s; %(code_rd)s; Mem = pkt->get(); %(code)s; if(fault == NoFault) { %(code_wb)s; } return fault; } }}; 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) { fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); } if(fault == NoFault) { //Write the resulting state to the execution context %(op_wb)s; } return fault; } Fault %(class_name)s::initiateAcc(%(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) { fault = xc->write((uint%(mem_acc_size)s_t)Mem, EA, 0, &write_result); } if(fault == NoFault) { //Write the resulting state to the execution context %(op_wb)s; } return fault; } Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const { return NoFault; } }}; 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; } }}; def template MemDeclare {{ /** * Static instruction class for "%(mnemonic)s". */ class %(class_name)s : public %(base_class)s { public: /// Constructor. %(class_name)s(ExtMachInst machInst); %(BasicExecDeclare)s %(InitiateAccDeclare)s %(CompleteAccDeclare)s }; }}; def template InitiateAccDeclare {{ Fault initiateAcc(%(CPU_exec_context)s *, Trace::InstRecord *) const; }}; def template CompleteAccDeclare {{ Fault completeAcc(PacketPtr, %(CPU_exec_context)s *, Trace::InstRecord *) const; }}; 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;' ea_iop = InstObjParams(name, Name, 'Mem', addrCalcReg, opt_flags, {"priv_check": priv}) ea_iop_imm = InstObjParams(name, Name, 'MemImm', addrCalcImm, opt_flags, {"priv_check": priv}) code_iop = InstObjParams(name, Name, 'Mem', code, opt_flags) iop = InstObjParams(name, Name, 'Mem', code, opt_flags, {"ea_code": addrCalcReg, "priv_check": priv}) (iop.ea_decl, iop.ea_rd, iop.ea_wb) = (ea_iop.op_decl, ea_iop.op_rd, ea_iop.op_wb) (iop.code_decl, iop.code_rd, iop.code_wb) = (code_iop.op_decl, code_iop.op_rd, code_iop.op_wb) iop_imm = InstObjParams(name, Name + 'Imm', 'MemImm', code, opt_flags, {"ea_code": addrCalcImm, "priv_check": priv}) (iop_imm.ea_decl, iop_imm.ea_rd, iop_imm.ea_wb) = (ea_iop_imm.op_decl, ea_iop_imm.op_rd, ea_iop_imm.op_wb) (iop_imm.code_decl, iop_imm.code_rd, iop_imm.code_wb) = (code_iop.op_decl, code_iop.op_rd, code_iop.op_wb) header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm) decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm) decode_block = ROrImmDecode.subst(iop) exec_output = execute.subst(iop) + execute.subst(iop_imm) return (header_output, decoder_output, exec_output, decode_block) }}; 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, LoadExecute, '', name, Name, opt_flags) }}; def format Store(code, *opt_flags) {{ (header_output, decoder_output, exec_output, decode_block) = doMemFormat(code, StoreExecute, '', name, Name, opt_flags) }}; def format LoadStore(code, *opt_flags) {{ (header_output, decoder_output, exec_output, decode_block) = doMemFormat(code, LoadStoreExecute, '', name, Name, opt_flags) }};