summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/sparc/isa/formats/blockmem.isa370
1 files changed, 370 insertions, 0 deletions
diff --git a/src/arch/sparc/isa/formats/blockmem.isa b/src/arch/sparc/isa/formats/blockmem.isa
new file mode 100644
index 000000000..b3e99ed9a
--- /dev/null
+++ b/src/arch/sparc/isa/formats/blockmem.isa
@@ -0,0 +1,370 @@
+////////////////////////////////////////////////////////////////////
+//
+// Block Memory instructions
+//
+
+output header {{
+
+ class BlockMem : public SparcMacroInst
+ {
+ protected:
+
+ // Constructor
+ // We make the assumption that all block memory operations
+ // Will take 8 instructions to execute
+ BlockMem(const char *mnem,
+ ExtMachInst _machInst, OpClass __opClass) :
+ SparcMacroInst(mnem, _machInst, __opClass, 8)
+ {}
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+
+ class BlockMemImm : public BlockMem
+ {
+ protected:
+
+ // Constructor
+ BlockMemImm(const char *mnem,
+ ExtMachInst _machInst, OpClass __opClass) :
+ BlockMem(mnem, _machInst, __opClass),
+ imm(sext<13>(SIMM13))
+ {}
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ const int32_t imm;
+ };
+
+ class BlockMemMicro : public SparcDelayedMicroInst
+ {
+ protected:
+
+ // Constructor
+ BlockMemMicro(const char *mnem, ExtMachInst _machInst,
+ OpClass __opClass, int8_t _offset) :
+ SparcDelayedMicroInst(mnem, _machInst, __opClass),
+ offset(_offset)
+ {}
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+
+ const int8_t offset;
+ };
+
+ class BlockMemImmMicro : public BlockMemMicro
+ {
+ protected:
+
+ // Constructor
+ BlockMemImmMicro(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 BlockMem::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 BlockMemImm::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 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 BlockMemDeclare {{
+ /**
+ * Static instruction class for a block memory operation
+ */
+ class %(class_name)s : public %(base_class)s
+ {
+ public:
+ //Constructor
+ %(class_name)s(MachInst machInst);
+
+ class %(class_name)s_0 : public %(base_class)sMicro
+ {
+ //Constructor
+ %(class_name)s_0(MachInst machInst) :
+ %(base_class)sMicro("%(mnemonic)s[0]",
+ machInst, %(op_class)s, 0*8)
+ {;}
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_1 : public %(base_class)sMicro
+ {
+ //Constructor
+ %(class_name)s_1(MachInst machInst) :
+ %(base_class)sMicro("%(mnemonic)s[1]",
+ machInst, %(op_class)s, 1*8)
+ {;}
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_2 : public %(base_class)sMicro
+ {
+ //Constructor
+ %(class_name)s_2(MachInst machInst) :
+ %(base_class)sMicro("%(mnemonic)s[2]",
+ machInst, %(op_class)s, 2*8)
+ {;}
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_3 : public %(base_class)sMicro
+ {
+ //Constructor
+ %(class_name)s_3(MachInst machInst) :
+ %(base_class)sMicro("%(mnemonic)s[3]",
+ machInst, %(op_class)s, 3*8)
+ {;}
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_4 : public %(base_class)sMicro
+ {
+ //Constructor
+ %(class_name)s_4(MachInst machInst) :
+ %(base_class)sMicro("%(mnemonic)s[4]",
+ machInst, %(op_class)s, 4*8)
+ {;}
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_5 : public %(base_class)sMicro
+ {
+ //Constructor
+ %(class_name)s_5(MachInst machInst) :
+ %(base_class)sMicro("%(mnemonic)s[5]",
+ machInst, %(op_class)s, 5*8)
+ {;}
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_6 : public %(base_class)sMicro
+ {
+ //Constructor
+ %(class_name)s_6(MachInst machInst) :
+ %(base_class)sMicro("%(mnemonic)s[6]",
+ machInst, %(op_class)s, 6*8)
+ {;}
+ %(BasicExecDeclare)s
+ };
+
+ class %(class_name)s_7 : public %(base_class)sMicro
+ {
+ //Constructor
+ %(class_name)s_7(MachInst machInst) :
+ %(base_class)sMicro("%(mnemonic)s[7]",
+ machInst, %(op_class)s, 7*8)
+ {
+ flags[IsLastMicroOp] = true;
+ }
+ %(BasicExecDeclare)s
+ };
+ };
+}};
+
+// Basic instruction class constructor template.
+def template BlockMemConstructor {{
+ inline %(class_name)s::%(class_name)s(MachInst machInst)
+ : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s)
+ {
+ %(constructor)s;
+ microOps =
+ {new %(class_name)s_0(machInst),
+ new %(class_name)s_1(machInst),
+ new %(class_name)s_2(machInst),
+ new %(class_name)s_3(machInst),
+ new %(class_name)s_4(machInst),
+ new %(class_name)s_5(machInst),
+ new %(class_name)s_6(machInst),
+ new %(class_name)s_7(machInst)}
+ }
+}};
+
+def template MicroLoadExecute {{
+ Fault %(class_name)s_%(micro_pc)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ Fault fault = NoFault;
+ Addr EA;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(fault_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)
+ {
+ //Write the resulting state to the execution context
+ %(op_wb)s;
+ }
+
+ return fault;
+ }
+}};
+
+def template MicroStoreExecute {{
+ Fault %(class_name)s_%(micro_pc)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;
+ %(fault_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;
+ }
+}};
+
+let {{
+
+ def doBlockMemFormat(code, execute, name, Name, opt_flags):
+ # 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
+ faultCheck = '''if(bits(Pstate,2,2) == 0 && (EXT_ASI & 0x80) == 0)
+ return new PrivilegedAction;
+ if(AsiIsAsIfUser(EXT_ASI) && !bits(Pstate,2,2))
+ return new PrivilegedAction;
+ if(RD & 0xf)
+ return new IllegalInstruction;
+ if(EA & 0x3f)
+ return new MemAddressNotAligned;'''
+ addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
+ addrCalcImm = 'EA = Rs1 + imm + offset;'
+ iop = InstObjParams(name, Name, 'Mem', code, opt_flags)
+ iop_imm = InstObjParams(name, Name + 'Imm', 'MemImm', code, opt_flags)
+ header_output = BlockMemDeclare.subst(iop) + BlockMemDeclare.subst(iop_imm)
+ decoder_output = BlockMemConstructor.subst(iop) + BlockMemConstructor.subst(iop_imm)
+ decode_block = ROrImmDecode.subst(iop)
+ for microPC in range(8):
+ pcedCode = code % ("micro_pc", microPC)
+ iop = InstObjParams(name, Name, 'Mem', pcedCode,
+ opt_flags, ("ea_code", addrCalcReg),
+ ("fault_check", faultCheck), ("micro_pc", microPC))
+ iop_imm = InstObjParams(name, Name + 'Imm', 'MemImm', pcedCode,
+ opt_flags, ("ea_code", addrCalcImm),
+ ("fault_check", faultCheck), ("micro_pc", microPC))
+ exec_output += execute.subst(iop)
+ exec_output += execute.subst(iop_imm)
+ faultCheck = ''
+ return (header_output, decoder_output, exec_output, decode_block)
+}};
+
+def format BlockLoad(code, *opt_flags) {{
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doBlockMemFormat(code, MicroLoadExecute,
+ name, Name, opt_flags)
+}};
+
+def format BlockStore(code, *opt_flags) {{
+ (header_output,
+ decoder_output,
+ exec_output,
+ decode_block) = doBlockMemFormat(code, MicroStoreExecute,
+ name, Name, opt_flags)
+}};