The beginnings of an instruction format to deal with block loads and stores. This takes advantage of microcode.
--HG-- extra : convert_revision : ac912df76c781f40fc462f314451148c5cdfaf43
This commit is contained in:
parent
b2d9c65db7
commit
6943c731ea
1 changed files with 370 additions and 0 deletions
370
src/arch/sparc/isa/formats/blockmem.isa
Normal file
370
src/arch/sparc/isa/formats/blockmem.isa
Normal file
|
@ -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)
|
||||
}};
|
Loading…
Reference in a new issue