Merging in a month of changes
src/arch/isa_parser.py:
Sign extend bit if you read int reg that is greater than default size
src/arch/mips/SConscript:
src/arch/mips/faults.cc:
src/arch/mips/faults.hh:
src/arch/mips/isa/base.isa:
src/arch/mips/isa/bitfields.isa:
src/arch/mips/isa/decoder.isa:
src/arch/mips/isa/formats/basic.isa:
src/arch/mips/isa/formats/branch.isa:
src/arch/mips/isa/formats/formats.isa:
src/arch/mips/isa/formats/fp.isa:
src/arch/mips/isa/formats/int.isa:
src/arch/mips/isa/formats/mem.isa:
src/arch/mips/isa/formats/noop.isa:
src/arch/mips/isa/formats/tlbop.isa:
src/arch/mips/isa/formats/trap.isa:
src/arch/mips/isa/formats/unimp.isa:
src/arch/mips/isa/formats/unknown.isa:
src/arch/mips/isa/formats/util.isa:
src/arch/mips/isa/includes.isa:
src/arch/mips/isa/main.isa:
src/arch/mips/isa/operands.isa:
src/arch/mips/isa_traits.cc:
src/arch/mips/linux/process.cc:
src/arch/mips/linux/process.hh:
src/arch/mips/process.cc:
src/arch/mips/process.hh:
src/arch/mips/regfile/float_regfile.hh:
src/arch/mips/utility.hh:
1 month of changes!
src/arch/mips/isa/formats/control.isa:
control formats
src/arch/mips/isa/formats/mt.isa:
mips mt format
src/arch/mips/utility.cc:
utility functions
--HG--
extra : convert_revision : c1332cb5ce08b464b99fbf04f4a5cac312898784
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Authors: Steve Reinhardt
|
||||
# Korey Sewell
|
||||
|
||||
import os
|
||||
import sys
|
||||
@@ -1181,6 +1182,11 @@ class IntRegOperand(Operand):
|
||||
if (self.size == self.dflt_size):
|
||||
return '%s = xc->readIntReg(this, %d);\n' % \
|
||||
(self.base_name, self.src_reg_idx)
|
||||
elif (self.size > self.dflt_size):
|
||||
int_reg_val = 'xc->readIntReg(this, %d)' % (self.src_reg_idx)
|
||||
if (self.is_signed):
|
||||
int_reg_val = 'sext<%d>(%s)' % (self.dflt_size, int_reg_val)
|
||||
return '%s = %s;\n' % (self.base_name, int_reg_val)
|
||||
else:
|
||||
return '%s = bits(xc->readIntReg(this, %d), %d, 0);\n' % \
|
||||
(self.base_name, self.src_reg_idx, self.size-1)
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#
|
||||
# Authors: Gabe Black
|
||||
# Steve Reinhardt
|
||||
# Korey Sewell
|
||||
|
||||
import os
|
||||
import sys
|
||||
@@ -46,6 +47,7 @@ Import('env')
|
||||
base_sources = Split('''
|
||||
faults.cc
|
||||
isa_traits.cc
|
||||
utility.cc
|
||||
''')
|
||||
|
||||
# Full-system sources
|
||||
|
||||
@@ -18,16 +18,6 @@ output header {{
|
||||
{
|
||||
protected:
|
||||
|
||||
/// Make MipsISA register dependence tags directly visible in
|
||||
/// this class and derived classes. Maybe these should really
|
||||
/// live here and not in the MipsISA namespace.
|
||||
/*enum DependenceTags {
|
||||
FP_Base_DepTag = MipsISA::FP_Base_DepTag,
|
||||
Fpcr_DepTag = MipsISA::Fpcr_DepTag,
|
||||
Uniq_DepTag = MipsISA::Uniq_DepTag,
|
||||
IPR_Base_DepTag = MipsISA::IPR_Base_DepTag
|
||||
};*/
|
||||
|
||||
// Constructor
|
||||
MipsStaticInst(const char *mnem, MachInst _machInst, OpClass __opClass)
|
||||
: StaticInst(mnem, _machInst, __opClass)
|
||||
@@ -67,12 +57,12 @@ output decoder {{
|
||||
}
|
||||
|
||||
if(_numSrcRegs > 0) {
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
}
|
||||
|
||||
if(_numSrcRegs > 1) {
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
printReg(ss, _srcRegIdx[1]);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,20 +17,19 @@ def bitfield FUNCTION < 5: 0>;
|
||||
def bitfield FUNCTION_HI < 5: 3>;
|
||||
def bitfield FUNCTION_LO < 2: 0>;
|
||||
|
||||
// Integer operate format
|
||||
def bitfield RT <20:16>;
|
||||
def bitfield RT_HI <20:19>;
|
||||
def bitfield RT_LO <18:16>;
|
||||
|
||||
def bitfield RS <25:21>;
|
||||
def bitfield RS_MSB <25:25>;
|
||||
def bitfield RS_HI <25:24>;
|
||||
def bitfield RS_LO <23:21>;
|
||||
def bitfield RS_SRL <25:22>;
|
||||
|
||||
def bitfield RS_SRL <25:22>;
|
||||
def bitfield RS_RT <25:16>;
|
||||
def bitfield RT <20:16>;
|
||||
def bitfield RT_HI <20:19>;
|
||||
def bitfield RT_LO <18:16>;
|
||||
def bitfield RT_RD <20:11>;
|
||||
def bitfield RD <15:11>;
|
||||
|
||||
def bitfield INTIMM <15: 0>; // integer immediate (literal)
|
||||
def bitfield INTIMM <15: 0>;
|
||||
|
||||
// Floating-point operate format
|
||||
def bitfield FMT <25:21>;
|
||||
@@ -67,5 +66,9 @@ def bitfield HINT <10: 6>;
|
||||
def bitfield SYSCALLCODE <25: 6>;
|
||||
def bitfield TRAPCODE <15:13>;
|
||||
|
||||
// EXT/INS instructions
|
||||
def bitfield MSB <15:11>;
|
||||
def bitfield LSB <10: 6>;
|
||||
|
||||
// M5 instructions
|
||||
def bitfield M5FUNC <7:0>;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,11 +12,11 @@ def template BasicDeclare {{
|
||||
*/
|
||||
class %(class_name)s : public %(base_class)s
|
||||
{
|
||||
public:
|
||||
public:
|
||||
/// Constructor.
|
||||
%(class_name)s(MachInst machInst);
|
||||
%(BasicExecDeclare)s
|
||||
};
|
||||
};
|
||||
}};
|
||||
|
||||
// Basic instruction class constructor template.
|
||||
@@ -27,6 +27,7 @@ def template BasicConstructor {{
|
||||
}
|
||||
}};
|
||||
|
||||
|
||||
// Basic instruction class execute method template.
|
||||
def template BasicExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
|
||||
|
||||
@@ -67,29 +67,6 @@ output header {{
|
||||
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for branch likely branches (PC-relative control transfers),
|
||||
*/
|
||||
class BranchLikely : public PCDependentDisassembly
|
||||
{
|
||||
protected:
|
||||
/// target address (signed) Displacement .
|
||||
int32_t disp;
|
||||
|
||||
/// Constructor.
|
||||
BranchLikely(const char *mnem, MachInst _machInst, OpClass __opClass)
|
||||
: PCDependentDisassembly(mnem, _machInst, __opClass),
|
||||
disp(OFFSET << 2)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Addr branchTarget(Addr branchPC) const;
|
||||
|
||||
std::string
|
||||
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for jumps (register-indirect control transfers). In
|
||||
* the Mips ISA, these are always unconditional.
|
||||
@@ -125,12 +102,6 @@ output decoder {{
|
||||
return branchPC + 4 + disp;
|
||||
}
|
||||
|
||||
Addr
|
||||
BranchLikely::branchTarget(Addr branchPC) const
|
||||
{
|
||||
return branchPC + 4 + disp;
|
||||
}
|
||||
|
||||
Addr
|
||||
Jump::branchTarget(ExecContext *xc) const
|
||||
{
|
||||
@@ -171,49 +142,12 @@ output decoder {{
|
||||
// unconditional branches)
|
||||
if (_numSrcRegs == 1) {
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
} else if(_numSrcRegs == 2) {
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
printReg(ss, _srcRegIdx[1]);
|
||||
ss << ",";
|
||||
}
|
||||
|
||||
Addr target = pc + 4 + disp;
|
||||
|
||||
std::string str;
|
||||
if (symtab && symtab->findSymbol(target, str))
|
||||
ss << str;
|
||||
else
|
||||
ccprintf(ss, "0x%x", target);
|
||||
|
||||
string inst_name = mnemonic;
|
||||
|
||||
if (inst_name.substr(inst_name.length()-2,inst_name.length()) == "al"){
|
||||
ccprintf(ss, " (r31=0x%x)",pc+8);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
BranchLikely::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ccprintf(ss, "%-10s ", mnemonic);
|
||||
|
||||
// There's only one register arg (RA), but it could be
|
||||
// either a source (the condition for conditional
|
||||
// branches) or a destination (the link reg for
|
||||
// unconditional branches)
|
||||
if (_numSrcRegs > 0) {
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
ss << ",";
|
||||
}
|
||||
else if (_numDestRegs > 0) {
|
||||
printReg(ss, _destRegIdx[0]);
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
}
|
||||
|
||||
Addr target = pc + 4 + disp;
|
||||
@@ -247,72 +181,64 @@ output decoder {{
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
} else if(_numSrcRegs == 2) {
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
printReg(ss, _srcRegIdx[1]);
|
||||
} else {
|
||||
panic(">= 3 Source Registers!!!");
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
}};
|
||||
|
||||
def format Branch(code,*flags) {{
|
||||
#Add Link Code if Link instruction
|
||||
strlen = len(name)
|
||||
if name[strlen-2:] == 'al':
|
||||
code += 'R31 = NNPC;\n'
|
||||
def format Branch(code,*opt_flags) {{
|
||||
not_taken_code = ' NNPC = NNPC;\n'
|
||||
not_taken_code += '} \n'
|
||||
|
||||
#Build Instruction Flags
|
||||
#Use Link & Likely Flags to Add Link/Condition Code
|
||||
inst_flags = ('IsDirectControl', )
|
||||
for x in opt_flags:
|
||||
if x == 'Link':
|
||||
code += 'R31 = NNPC;\n'
|
||||
elif x == 'Likely':
|
||||
not_taken_code = ' NPC = NNPC;\n'
|
||||
not_taken_code += ' NNPC = NNPC + 4;\n'
|
||||
not_taken_code += '} \n'
|
||||
inst_flags = ('IsCondDelaySlot', )
|
||||
else:
|
||||
inst_flags += (x, )
|
||||
|
||||
if 'cond == 1' in code:
|
||||
inst_flags += ('IsCondControl', )
|
||||
else:
|
||||
inst_flags += ('IsUncondControl', )
|
||||
|
||||
#Condition code
|
||||
code = 'bool cond;\n' + code
|
||||
code += 'if (cond) {\n'
|
||||
code += ' NNPC = NPC + disp;\n'
|
||||
code += '} else {\n'
|
||||
code += ' NNPC = NNPC;\n'
|
||||
code += '} \n'
|
||||
|
||||
iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
|
||||
('IsDirectControl', 'IsCondControl'))
|
||||
code += not_taken_code
|
||||
|
||||
iop = InstObjParams(name, Name, 'Branch', CodeBlock(code), inst_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
|
||||
def format BranchLikely(code,*flags) {{
|
||||
#Add Link Code if Link instruction
|
||||
strlen = len(name)
|
||||
if name[strlen-3:] == 'all':
|
||||
code += 'R31 = NNPC;\n'
|
||||
|
||||
#Condition code
|
||||
code = 'bool cond;\n' + code
|
||||
code += 'if (cond) {'
|
||||
code += 'NNPC = NPC + disp;\n'
|
||||
code += '} \n'
|
||||
|
||||
|
||||
iop = InstObjParams(name, Name, 'Branch', CodeBlock(code),
|
||||
('IsDirectControl', 'IsCondControl','IsCondDelaySlot'))
|
||||
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format Jump(code,*flags) {{
|
||||
#Add Link Code if Link instruction
|
||||
strlen = len(name)
|
||||
if strlen > 1 and name[1:] == 'al':
|
||||
def format Jump(code, *opt_flags) {{
|
||||
#Build Instruction Flags
|
||||
#Use Link Flag to Add Link Code
|
||||
inst_flags = ('IsIndirectControl', 'IsUncondControl')
|
||||
for x in opt_flags:
|
||||
if x == 'Link':
|
||||
code = 'R31 = NNPC;\n' + code
|
||||
elif x == 'ClearHazards':
|
||||
code += '/* Code Needed to Clear Execute & Inst Hazards */\n'
|
||||
else:
|
||||
inst_flags += (x, )
|
||||
|
||||
|
||||
iop = InstObjParams(name, Name, 'Jump', CodeBlock(code),\
|
||||
('IsIndirectControl', 'IsUncondControl'))
|
||||
|
||||
iop = InstObjParams(name, Name, 'Jump', CodeBlock(code), inst_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
|
||||
128
src/arch/mips/isa/formats/control.isa
Normal file
128
src/arch/mips/isa/formats/control.isa
Normal file
@@ -0,0 +1,128 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Integer operate instructions
|
||||
//
|
||||
|
||||
//Outputs to decoder.hh
|
||||
output header {{
|
||||
|
||||
class Control : public MipsStaticInst
|
||||
{
|
||||
protected:
|
||||
|
||||
/// Constructor
|
||||
Control(const char *mnem, MachInst _machInst, OpClass __opClass) :
|
||||
MipsStaticInst(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class CP0Control : public Control
|
||||
{
|
||||
protected:
|
||||
|
||||
/// Constructor
|
||||
CP0Control(const char *mnem, MachInst _machInst, OpClass __opClass) :
|
||||
Control(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class CP1Control : public Control
|
||||
{
|
||||
protected:
|
||||
|
||||
/// Constructor
|
||||
CP1Control(const char *mnem, MachInst _machInst, OpClass __opClass) :
|
||||
Control(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
}};
|
||||
|
||||
//Outputs to decoder.cc
|
||||
output decoder {{
|
||||
std::string Control::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ccprintf(ss, "%-10s ", mnemonic);
|
||||
|
||||
if (mnemonic == "mfc0" || mnemonic == "mtc0") {
|
||||
ccprintf(ss, "%-10s %d,%d,%d", mnemonic,RT,RD,SEL);
|
||||
} else {
|
||||
|
||||
// just print the first dest... if there's a second one,
|
||||
// it's generally implicit
|
||||
if (_numDestRegs > 0) {
|
||||
printReg(ss, _destRegIdx[0]);
|
||||
}
|
||||
|
||||
ss << ", ";
|
||||
|
||||
// just print the first two source regs... if there's
|
||||
// a third one, it's a read-modify-write dest (Rc),
|
||||
// e.g. for CMOVxx
|
||||
if (_numSrcRegs > 0) {
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
}
|
||||
|
||||
if (_numSrcRegs > 1) {
|
||||
ss << ", ";
|
||||
printReg(ss, _srcRegIdx[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string CP0Control::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ccprintf(ss, "%-10s r%d, r%d, %d", mnemonic, RT, RD, SEL);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string CP1Control::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ccprintf(ss, "%-10s r%d, f%d", mnemonic, RT, FS);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}};
|
||||
|
||||
def format System(code, *flags) {{
|
||||
iop = InstObjParams(name, Name, 'Control', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format CP0Control(code, *flags) {{
|
||||
iop = InstObjParams(name, Name, 'CP0Control', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format CP1Control(code, *flags) {{
|
||||
iop = InstObjParams(name, Name, 'CP1Control', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
//Include utility functions
|
||||
##include "util.isa"
|
||||
|
||||
//Include the cop0 formats
|
||||
##include "cop0.isa"
|
||||
//Include the control/cp0/cp1 formats
|
||||
##include "control.isa"
|
||||
|
||||
//Include the integer formats
|
||||
##include "int.isa"
|
||||
@@ -22,6 +22,9 @@
|
||||
//Include the mem format
|
||||
##include "mem.isa"
|
||||
|
||||
//Include the mem format
|
||||
##include "mt.isa"
|
||||
|
||||
//Include the trap format
|
||||
##include "trap.isa"
|
||||
|
||||
|
||||
@@ -18,49 +18,264 @@ output header {{
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
//std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
|
||||
//needs function to check for fpEnable or not
|
||||
};
|
||||
|
||||
class FPCompareOp : public FPOp
|
||||
{
|
||||
protected:
|
||||
FPCompareOp(const char *mnem, MachInst _machInst, OpClass __opClass) : FPOp(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
|
||||
};
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
std::string FPOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
std::string FPCompareOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
return "Disassembly of integer instruction\n";
|
||||
std::stringstream ss;
|
||||
|
||||
ccprintf(ss, "%-10s ", mnemonic);
|
||||
|
||||
ccprintf(ss,"%d",CC);
|
||||
|
||||
if(_numSrcRegs > 0) {
|
||||
ss << ", ";
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
}
|
||||
|
||||
if(_numSrcRegs > 1) {
|
||||
ss << ", ";
|
||||
printReg(ss, _srcRegIdx[1]);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
}};
|
||||
|
||||
output exec {{
|
||||
|
||||
// Primary format for float operate instructions:
|
||||
//If any operand is Nan return the appropriate QNaN
|
||||
template <class T>
|
||||
bool
|
||||
fpNanOperands(FPOp *inst, %(CPU_exec_context)s *xc, const T &src_type,
|
||||
Trace::InstRecord *traceData)
|
||||
{
|
||||
uint64_t mips_nan = 0;
|
||||
T src_op = 0;
|
||||
int size = sizeof(src_op) * 8;
|
||||
|
||||
for (int i = 0; i < inst->numSrcRegs(); i++) {
|
||||
uint64_t src_bits = xc->readFloatRegBits(inst, 0, size);
|
||||
|
||||
if (isNan(&src_bits, size) ) {
|
||||
if (isSnan(&src_bits, size)) {
|
||||
switch (size)
|
||||
{
|
||||
case 32: mips_nan = MIPS32_QNAN; break;
|
||||
case 64: mips_nan = MIPS64_QNAN; break;
|
||||
default: panic("Unsupported Floating Point Size (%d)", size);
|
||||
}
|
||||
} else {
|
||||
mips_nan = src_bits;
|
||||
}
|
||||
|
||||
xc->setFloatRegBits(inst, 0, mips_nan, size);
|
||||
if (traceData) { traceData->setData(mips_nan); }
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
fpInvalidOp(FPOp *inst, %(CPU_exec_context)s *xc, const T dest_val,
|
||||
Trace::InstRecord *traceData)
|
||||
{
|
||||
uint64_t mips_nan = 0;
|
||||
T src_op = dest_val;
|
||||
int size = sizeof(src_op) * 8;
|
||||
|
||||
if (isNan(&src_op, size)) {
|
||||
switch (size)
|
||||
{
|
||||
case 32: mips_nan = MIPS32_QNAN; break;
|
||||
case 64: mips_nan = MIPS64_QNAN; break;
|
||||
default: panic("Unsupported Floating Point Size (%d)", size);
|
||||
}
|
||||
|
||||
//Set value to QNAN
|
||||
xc->setFloatRegBits(inst, 0, mips_nan, size);
|
||||
|
||||
//Read FCSR from FloatRegFile
|
||||
uint32_t fcsr_bits = xc->cpuXC->readFloatRegBits(FCSR);
|
||||
|
||||
//Write FCSR from FloatRegFile
|
||||
xc->cpuXC->setFloatRegBits(FCSR, genInvalidVector(fcsr_bits));
|
||||
|
||||
if (traceData) { traceData->setData(mips_nan); }
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
fpResetCauseBits(%(CPU_exec_context)s *xc)
|
||||
{
|
||||
//Read FCSR from FloatRegFile
|
||||
uint32_t fcsr = xc->cpuXC->readFloatRegBits(FCSR);
|
||||
|
||||
fcsr = bits(fcsr, 31, 18) << 18 | bits(fcsr, 11, 0);
|
||||
|
||||
//Write FCSR from FloatRegFile
|
||||
xc->cpuXC->setFloatRegBits(FCSR, fcsr);
|
||||
}
|
||||
}};
|
||||
|
||||
def template FloatingPointExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
|
||||
{
|
||||
Fault fault = NoFault;
|
||||
|
||||
%(fp_enable_check)s;
|
||||
|
||||
//When is the right time to reset cause bits?
|
||||
//start of every instruction or every cycle?
|
||||
fpResetCauseBits(xc);
|
||||
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
|
||||
//Check if any FP operand is a NaN value
|
||||
if (!fpNanOperands((FPOp*)this, xc, Fd, traceData)) {
|
||||
%(code)s;
|
||||
|
||||
//Change this code for Full-System/Sycall Emulation
|
||||
//separation
|
||||
//----
|
||||
//Should Full System-Mode throw a fault here?
|
||||
//----
|
||||
//Check for IEEE 754 FP Exceptions
|
||||
//fault = fpNanOperands((FPOp*)this, xc, Fd, traceData);
|
||||
if (!fpInvalidOp((FPOp*)this, xc, Fd, traceData) &&
|
||||
fault == NoFault)
|
||||
{
|
||||
%(op_wb)s;
|
||||
}
|
||||
}
|
||||
|
||||
return fault;
|
||||
}
|
||||
}};
|
||||
|
||||
// Primary format for float point operate instructions:
|
||||
def format FloatOp(code, *flags) {{
|
||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||
iop = InstObjParams(name, Name, 'FPOp', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
exec_output = FloatingPointExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format FloatCompareOp(code, *flags) {{
|
||||
code = 'bool cond;\n' + code
|
||||
code += 'FCSR = makeCCVector(FCSR, CC,cond);\n'
|
||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
def format FloatCompareOp(cond_code, *flags) {{
|
||||
import sys
|
||||
|
||||
def format FloatCompareWithXcptOp(code, *flags) {{
|
||||
code = 'bool cond;\n' + code
|
||||
code += 'FCSR = makeCCVector(FCSR, CC,cond);\n'
|
||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
code = 'bool cond;\n'
|
||||
if '.sf' in cond_code or 'SinglePrecision' in flags:
|
||||
if 'QnanException' in flags:
|
||||
code += 'if (isQnan(&Fs.sf, 32) || isQnan(&Ft.sf, 32)) {\n'
|
||||
code += '\tFCSR = genInvalidVector(FCSR);\n'
|
||||
code += '\treturn NoFault;'
|
||||
code += '}\n else '
|
||||
code += 'if (isNan(&Fs.sf, 32) || isNan(&Ft.sf, 32)) {\n'
|
||||
elif '.df' in cond_code or 'DoublePrecision' in flags:
|
||||
if 'QnanException' in flags:
|
||||
code += 'if (isQnan(&Fs.df, 64) || isQnan(&Ft.df, 64)) {\n'
|
||||
code += '\tFCSR = genInvalidVector(FCSR);\n'
|
||||
code += '\treturn NoFault;'
|
||||
code += '}\n else '
|
||||
code += 'if (isNan(&Fs.df, 64) || isNan(&Ft.df, 64)) {\n'
|
||||
else:
|
||||
sys.exit('Decoder Failed: Can\'t Determine Operand Type\n')
|
||||
|
||||
if 'UnorderedTrue' in flags:
|
||||
code += 'cond = 1;\n'
|
||||
elif 'UnorderedFalse' in flags:
|
||||
code += 'cond = 0;\n'
|
||||
else:
|
||||
sys.exit('Decoder Failed: Float Compare Instruction Needs A Unordered Flag\n')
|
||||
|
||||
code += '} else {\n'
|
||||
code += cond_code + '}'
|
||||
code += 'FCSR = genCCVector(FCSR, CC, cond);\n'
|
||||
|
||||
iop = InstObjParams(name, Name, 'FPCompareOp', CodeBlock(code))
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format FloatConvertOp(code, *flags) {{
|
||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||
import sys
|
||||
|
||||
#Determine Source Type
|
||||
convert = 'fpConvert('
|
||||
if '.sf' in code:
|
||||
code = 'float ' + code + '\n'
|
||||
convert += 'SINGLE_TO_'
|
||||
elif '.df' in code:
|
||||
code = 'double ' + code + '\n'
|
||||
convert += 'DOUBLE_TO_'
|
||||
elif '.uw' in code:
|
||||
code = 'uint32_t ' + code + '\n'
|
||||
convert += 'WORD_TO_'
|
||||
elif '.ud' in code:
|
||||
code = 'uint64_t ' + code + '\n'
|
||||
convert += 'LONG_TO_'
|
||||
else:
|
||||
sys.exit("Error Determining Source Type for Conversion")
|
||||
|
||||
#Determine Destination Type
|
||||
if 'ToSingle' in flags:
|
||||
code += 'Fd.uw = ' + convert + 'SINGLE, '
|
||||
elif 'ToDouble' in flags:
|
||||
code += 'Fd.ud = ' + convert + 'DOUBLE, '
|
||||
elif 'ToWord' in flags:
|
||||
code += 'Fd.uw = ' + convert + 'WORD, '
|
||||
elif 'ToLong' in flags:
|
||||
code += 'Fd.ud = ' + convert + 'LONG, '
|
||||
else:
|
||||
sys.exit("Error Determining Destination Type for Conversion")
|
||||
|
||||
#Figure out how to round value
|
||||
if 'Ceil' in flags:
|
||||
code += 'ceil(val)); '
|
||||
elif 'Floor' in flags:
|
||||
code += 'floor(val)); '
|
||||
elif 'Round' in flags:
|
||||
code += 'roundFP(val, 0)); '
|
||||
elif 'Trunc' in flags:
|
||||
code += 'truncFP(val));'
|
||||
else:
|
||||
code += 'val); '
|
||||
|
||||
iop = InstObjParams(name, Name, 'FPOp', CodeBlock(code))
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format FloatAccOp(code, *flags) {{
|
||||
iop = InstObjParams(name, Name, 'FPOp', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
@@ -76,34 +291,51 @@ def format Float64Op(code, *flags) {{
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format Float64ConvertOp(code, *flags) {{
|
||||
code = 'bool cond;\n' + code
|
||||
code += 'FCSR = makeCCVector(FCSR, CC,cond);\n'
|
||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
def format FloatPSCompareOp(cond_code1, cond_code2, *flags) {{
|
||||
import sys
|
||||
|
||||
code = 'bool cond1, cond2;\n'
|
||||
code += 'bool code_block1, code_block2;\n'
|
||||
code += 'code_block1 = code_block2 = true;\n'
|
||||
|
||||
if 'QnanException' in flags:
|
||||
code += 'if (isQnan(&Fs1.sf, 32) || isQnan(&Ft1.sf, 32)) {\n'
|
||||
code += '\tFCSR = genInvalidVector(FCSR);\n'
|
||||
code += 'code_block1 = false;'
|
||||
code += '}\n'
|
||||
code += 'if (isQnan(&Fs2.sf, 32) || isQnan(&Ft2.sf, 32)) {\n'
|
||||
code += '\tFCSR = genInvalidVector(FCSR);\n'
|
||||
code += 'code_block2 = false;'
|
||||
code += '}\n'
|
||||
|
||||
code += 'if (code_block1) {'
|
||||
code += '\tif (isNan(&Fs1.sf, 32) || isNan(&Ft1.sf, 32)) {\n'
|
||||
if 'UnorderedTrue' in flags:
|
||||
code += 'cond1 = 1;\n'
|
||||
elif 'UnorderedFalse' in flags:
|
||||
code += 'cond1 = 0;\n'
|
||||
else:
|
||||
sys.exit('Decoder Failed: Float Compare Instruction Needs A Unordered Flag\n')
|
||||
code += '} else {\n'
|
||||
code += cond_code1
|
||||
code += 'FCSR = genCCVector(FCSR, CC, cond1);}\n}\n'
|
||||
|
||||
code += 'if (code_block2) {'
|
||||
code += '\tif (isNan(&Fs2.sf, 32) || isNan(&Ft2.sf, 32)) {\n'
|
||||
if 'UnorderedTrue' in flags:
|
||||
code += 'cond2 = 1;\n'
|
||||
elif 'UnorderedFalse' in flags:
|
||||
code += 'cond2 = 0;\n'
|
||||
else:
|
||||
sys.exit('Decoder Failed: Float Compare Instruction Needs A Unordered Flag\n')
|
||||
code += '} else {\n'
|
||||
code += cond_code2
|
||||
code += 'FCSR = genCCVector(FCSR, CC, cond2);}\n}'
|
||||
|
||||
iop = InstObjParams(name, Name, 'FPCompareOp', CodeBlock(code))
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format FloatPSCompareOp(code, *flags) {{
|
||||
code = 'bool cond1;\nbool cond2;\n' + code
|
||||
code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n'
|
||||
code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n'
|
||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format FloatPSCompareWithXcptOp(code, *flags) {{
|
||||
code = 'bool cond1;\nbool cond2;\n' + code
|
||||
code += 'FCSR = makeCCVector(FCSR, CC+1, cond1);\n'
|
||||
code += 'FCSR = makeCCVector(FCSR, CC, cond2);\n'
|
||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
//
|
||||
// Integer operate instructions
|
||||
//
|
||||
|
||||
//Outputs to decoder.hh
|
||||
output header {{
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
@@ -25,6 +23,34 @@ output header {{
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
|
||||
class HiLoOp: public IntOp
|
||||
{
|
||||
protected:
|
||||
|
||||
/// Constructor
|
||||
HiLoOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
|
||||
IntOp(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
class HiLoMiscOp: public HiLoOp
|
||||
{
|
||||
protected:
|
||||
|
||||
/// Constructor
|
||||
HiLoMiscOp(const char *mnem, MachInst _machInst, OpClass __opClass) :
|
||||
HiLoOp(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
|
||||
|
||||
class IntImmOp : public MipsStaticInst
|
||||
{
|
||||
protected:
|
||||
@@ -52,6 +78,33 @@ output header {{
|
||||
|
||||
}};
|
||||
|
||||
// HiLo<Misc> instruction class execute method template.
|
||||
// Mainly to get instruction trace data to print out
|
||||
// correctly
|
||||
def template HiLoExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
|
||||
{
|
||||
Fault fault = NoFault;
|
||||
|
||||
%(fp_enable_check)s;
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
%(code)s;
|
||||
|
||||
if(fault == NoFault)
|
||||
{
|
||||
%(op_wb)s;
|
||||
//If there are 2 Destination Registers then
|
||||
//concatenate the values for the traceData
|
||||
if(traceData && _numDestRegs == 2) {
|
||||
uint64_t hilo_final_val = (uint64_t)HI << 32 | LO;
|
||||
traceData->setData(hilo_final_val);
|
||||
}
|
||||
}
|
||||
return fault;
|
||||
}
|
||||
}};
|
||||
|
||||
//Outputs to decoder.cc
|
||||
output decoder {{
|
||||
std::string IntOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
@@ -64,7 +117,7 @@ output decoder {{
|
||||
// it's generally implicit
|
||||
if (_numDestRegs > 0) {
|
||||
printReg(ss, _destRegIdx[0]);
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
}
|
||||
|
||||
// just print the first two source regs... if there's
|
||||
@@ -75,13 +128,47 @@ output decoder {{
|
||||
}
|
||||
|
||||
if (_numSrcRegs > 1) {
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
printReg(ss, _srcRegIdx[1]);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string HiLoOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ccprintf(ss, "%-10s ", mnemonic);
|
||||
|
||||
//Destination Registers are implicit for HI/LO ops
|
||||
if (_numSrcRegs > 0) {
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
}
|
||||
|
||||
if (_numSrcRegs > 1) {
|
||||
ss << ", ";
|
||||
printReg(ss, _srcRegIdx[1]);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string HiLoMiscOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
ccprintf(ss, "%-10s ", mnemonic);
|
||||
|
||||
if (_numDestRegs > 0 && _destRegIdx[0] < 32) {
|
||||
printReg(ss, _destRegIdx[0]);
|
||||
} else if (_numSrcRegs > 0 && _srcRegIdx[0] < 32) {
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string IntImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
std::stringstream ss;
|
||||
@@ -92,15 +179,15 @@ output decoder {{
|
||||
printReg(ss, _destRegIdx[0]);
|
||||
}
|
||||
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
|
||||
if (_numSrcRegs > 0) {
|
||||
printReg(ss, _srcRegIdx[0]);
|
||||
ss << ",";
|
||||
ss << ", ";
|
||||
}
|
||||
|
||||
if( mnemonic == "lui")
|
||||
ccprintf(ss, "%08p ", sextImm);
|
||||
ccprintf(ss, "0x%x ", sextImm);
|
||||
else
|
||||
ss << (int) sextImm;
|
||||
|
||||
@@ -109,23 +196,47 @@ output decoder {{
|
||||
|
||||
}};
|
||||
|
||||
//Used by decoder.isa
|
||||
def format IntOp(code, *opt_flags) {{
|
||||
orig_code = code
|
||||
cblk = CodeBlock(code)
|
||||
iop = InstObjParams(name, Name, 'IntOp', CodeBlock(code), opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = OperateNopCheckDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
# Figure out if we are creating a IntImmOp or a IntOp
|
||||
# by looking at the instruction name
|
||||
iop = InstObjParams(name, Name, 'IntOp', cblk, opt_flags)
|
||||
strlen = len(name)
|
||||
if name[strlen-1] == 'i' or name[strlen-2:] == 'iu':
|
||||
iop = InstObjParams(name, Name, 'IntImmOp', cblk, opt_flags)
|
||||
def format IntImmOp(code, *opt_flags) {{
|
||||
iop = InstObjParams(name, Name, 'IntImmOp', CodeBlock(code), opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = OperateNopCheckDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = OperateNopCheckDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
def format HiLoOp(code, *opt_flags) {{
|
||||
if '.sd' in code:
|
||||
code = 'int64_t ' + code
|
||||
elif '.ud' in code:
|
||||
code = 'uint64_t ' + code
|
||||
|
||||
code += 'HI = val<63:32>;\n'
|
||||
code += 'LO = val<31:0>;\n'
|
||||
|
||||
iop = InstObjParams(name, Name, 'HiLoOp', CodeBlock(code), opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = OperateNopCheckDecode.subst(iop)
|
||||
exec_output = HiLoExecute.subst(iop)
|
||||
}};
|
||||
|
||||
def format HiLoMiscOp(code, *opt_flags) {{
|
||||
iop = InstObjParams(name, Name, 'HiLoMiscOp', CodeBlock(code), opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = OperateNopCheckDecode.subst(iop)
|
||||
exec_output = HiLoExecute.subst(iop)
|
||||
}};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -90,15 +90,6 @@ output decoder {{
|
||||
|
||||
}};
|
||||
|
||||
def format LoadAddress(code) {{
|
||||
iop = InstObjParams(name, Name, 'MemoryDisp32', CodeBlock(code))
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
|
||||
|
||||
def template LoadStoreDeclare {{
|
||||
/**
|
||||
* Static instruction class for "%(mnemonic)s".
|
||||
@@ -426,8 +417,70 @@ def template StoreCompleteAcc {{
|
||||
}
|
||||
}};
|
||||
|
||||
|
||||
def template MiscMemAccExecute {{
|
||||
Fault %(class_name)s::MemAcc::execute(%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = NoFault;
|
||||
|
||||
%(fp_enable_check)s;
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
EA = xc->getEA();
|
||||
|
||||
if (fault == NoFault) {
|
||||
%(code)s;
|
||||
}
|
||||
|
||||
return NoFault;
|
||||
}
|
||||
}};
|
||||
|
||||
def template MiscExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
Addr EA;
|
||||
Fault fault = NoFault;
|
||||
|
||||
%(fp_enable_check)s;
|
||||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
%(ea_code)s;
|
||||
|
||||
if (fault == NoFault) {
|
||||
%(memacc_code)s;
|
||||
}
|
||||
|
||||
return NoFault;
|
||||
}
|
||||
}};
|
||||
|
||||
def template MiscInitiateAcc {{
|
||||
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
panic("Misc instruction does not support split access method!");
|
||||
return NoFault;
|
||||
}
|
||||
}};
|
||||
|
||||
|
||||
def template MiscCompleteAcc {{
|
||||
Fault %(class_name)s::completeAcc(uint8_t *data,
|
||||
%(CPU_exec_context)s *xc,
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
panic("Misc instruction does not support split access method!");
|
||||
|
||||
return NoFault;
|
||||
}
|
||||
}};
|
||||
|
||||
// load instructions use Rt as dest, so check for
|
||||
// Rt == 31 to detect nops
|
||||
// Rt == 0 to detect nops
|
||||
def template LoadNopCheckDecode {{
|
||||
{
|
||||
MipsStaticInst *i = new %(class_name)s(machInst);
|
||||
@@ -446,7 +499,6 @@ def format LoadMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
|
||||
exec_template_base = 'Load')
|
||||
}};
|
||||
|
||||
|
||||
def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
|
||||
mem_flags = [], inst_flags = []) {{
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
@@ -454,26 +506,70 @@ def format StoreMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
|
||||
exec_template_base = 'Store')
|
||||
}};
|
||||
|
||||
//FP loads are offloaded to these formats for now ...
|
||||
def format LoadFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
|
||||
def format LoadIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
|
||||
mem_flags = [], inst_flags = []) {{
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||
decode_template = BasicDecode,
|
||||
decode_template = LoadNopCheckDecode,
|
||||
exec_template_base = 'Load')
|
||||
}};
|
||||
|
||||
|
||||
def format StoreFloatMemory(memacc_code, ea_code = {{ EA = Rs + disp; }},
|
||||
def format StoreIndexedMemory(memacc_code, ea_code = {{ EA = Rs + Rt; }},
|
||||
mem_flags = [], inst_flags = []) {{
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||
exec_template_base = 'Store')
|
||||
}};
|
||||
|
||||
def format LoadUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
|
||||
mem_flags = [], inst_flags = []) {{
|
||||
decl_code = 'uint32_t mem_word = Mem.uw;\n'
|
||||
decl_code += 'uint32_t unalign_addr = Rs + disp;\n'
|
||||
decl_code += 'uint32_t byte_offset = unalign_addr & 3;\n'
|
||||
decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
|
||||
decl_code += '\tbyte_offset ^= 3;\n'
|
||||
decl_code += '#endif\n'
|
||||
|
||||
def format UnalignedStore(memacc_code, postacc_code,
|
||||
ea_code = {{ EA = Rb + disp; }},
|
||||
memacc_code = decl_code + memacc_code
|
||||
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||
decode_template = LoadNopCheckDecode,
|
||||
exec_template_base = 'Load')
|
||||
}};
|
||||
|
||||
def format StoreUnalignedMemory(memacc_code, ea_code = {{ EA = (Rs + disp) & ~3; }},
|
||||
mem_flags = [], inst_flags = []) {{
|
||||
decl_code = 'uint32_t mem_word = 0;\n'
|
||||
decl_code += 'uint32_t unaligned_addr = Rs + disp;\n'
|
||||
decl_code += 'uint32_t byte_offset = unaligned_addr & 3;\n'
|
||||
decl_code += '#if BYTE_ORDER == BIG_ENDIAN\n'
|
||||
decl_code += '\tbyte_offset ^= 3;\n'
|
||||
decl_code += '#endif\n'
|
||||
decl_code += 'fault = xc->read(EA, (uint32_t&)mem_word, memAccessFlags);\n'
|
||||
memacc_code = decl_code + memacc_code + '\nMem = mem_word;\n'
|
||||
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||
decode_template = LoadNopCheckDecode,
|
||||
exec_template_base = 'Store')
|
||||
}};
|
||||
|
||||
def format Prefetch(ea_code = {{ EA = Rs + disp; }},
|
||||
mem_flags = [], pf_flags = [], inst_flags = []) {{
|
||||
pf_mem_flags = mem_flags + pf_flags + ['NO_FAULT']
|
||||
pf_inst_flags = inst_flags + ['IsMemRef', 'IsLoad',
|
||||
'IsDataPrefetch', 'MemReadOp']
|
||||
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
LoadStoreBase(name, Name, ea_code,
|
||||
'xc->prefetch(EA, memAccessFlags);',
|
||||
pf_mem_flags, pf_inst_flags, exec_template_base = 'Misc')
|
||||
|
||||
}};
|
||||
|
||||
def format StoreCond(memacc_code, postacc_code,
|
||||
ea_code = {{ EA = Rs + disp; }},
|
||||
mem_flags = [], inst_flags = []) {{
|
||||
(header_output, decoder_output, decode_block, exec_output) = \
|
||||
LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||
|
||||
53
src/arch/mips/isa/formats/mt.isa
Normal file
53
src/arch/mips/isa/formats/mt.isa
Normal file
@@ -0,0 +1,53 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// MT instructions
|
||||
//
|
||||
|
||||
output header {{
|
||||
/**
|
||||
* Base class for integer operations.
|
||||
*/
|
||||
class MT : public MipsStaticInst
|
||||
{
|
||||
protected:
|
||||
|
||||
/// Constructor
|
||||
MT(const char *mnem, MachInst _machInst, OpClass __opClass) : MipsStaticInst(mnem, _machInst, __opClass)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
//Edit This Template When MT is Implemented
|
||||
std::string MT::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
return "Disassembly of MT instruction\n";
|
||||
}
|
||||
}};
|
||||
|
||||
def template MTExecute {{
|
||||
//Edit This Template When MT is Implemented
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
|
||||
{
|
||||
//Write the resulting state to the execution context
|
||||
%(op_wb)s;
|
||||
|
||||
//Call into the trap handler with the appropriate fault
|
||||
return No_Fault;
|
||||
}
|
||||
}};
|
||||
|
||||
// Primary format for integer operate instructions:
|
||||
def format MipsMT() {{
|
||||
code = 'panic(\"Mips MT Is Currently Unimplemented.\");\n'
|
||||
iop = InstObjParams(name, Name, 'MT', CodeBlock(code))
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
decode_block = BasicDecode.subst(iop)
|
||||
exec_output = BasicExecute.subst(iop)
|
||||
}};
|
||||
@@ -36,11 +36,7 @@ output decoder {{
|
||||
std::string Nop::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
#ifdef SS_COMPATIBLE_DISASSEMBLY
|
||||
return originalDisassembly;
|
||||
#else
|
||||
return csprintf("%-10s (%s)", "nop", originalDisassembly);
|
||||
#endif
|
||||
return csprintf("%-10s %s", "nop", originalDisassembly);
|
||||
}
|
||||
|
||||
/// Helper function for decoding nops. Substitute Nop object
|
||||
@@ -89,6 +85,6 @@ def format BasicOperateWithNopCheck(code, *opt_args) {{
|
||||
}};
|
||||
|
||||
def format Nop() {{
|
||||
decode_block = 'return new Nop(\"sll r0,r0,0\",machInst);\n'
|
||||
decode_block = 'return new Nop(\"\",machInst);\n'
|
||||
}};
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TlbOp instructions
|
||||
@@ -30,13 +32,10 @@ output decoder {{
|
||||
def template TlbOpExecute {{
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
|
||||
{
|
||||
//Call into the trap handler with the appropriate fault
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
//Write the resulting state to the execution context
|
||||
%(op_wb)s;
|
||||
|
||||
//Call into the trap handler with the appropriate fault
|
||||
return No_Fault;
|
||||
}
|
||||
}};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Trap instructions
|
||||
@@ -23,27 +25,26 @@ output header {{
|
||||
output decoder {{
|
||||
std::string Trap::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
return "Disassembly of integer instruction\n";
|
||||
return "Disassembly of trap instruction\n";
|
||||
}
|
||||
}};
|
||||
|
||||
def template TrapExecute {{
|
||||
//Edit This Template When Traps Are Implemented
|
||||
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc, Trace::InstRecord *traceData) const
|
||||
{
|
||||
//Call into the trap handler with the appropriate fault
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
//Write the resulting state to the execution context
|
||||
%(op_wb)s;
|
||||
|
||||
//Call into the trap handler with the appropriate fault
|
||||
return No_Fault;
|
||||
}
|
||||
}};
|
||||
|
||||
// Primary format for integer operate instructions:
|
||||
def format Trap(code, *flags) {{
|
||||
code = 'bool cond;\n' + code;
|
||||
code = 'panic(\"'
|
||||
code += 'Trap Exception Handler Is Currently Not Implemented.'
|
||||
code += '\");'
|
||||
iop = InstObjParams(name, Name, 'MipsStaticInst', CodeBlock(code), flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
|
||||
@@ -25,13 +25,6 @@
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Authors: Korey Sewell
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Unimplemented instructions
|
||||
//
|
||||
|
||||
output header {{
|
||||
/**
|
||||
@@ -103,11 +96,7 @@ output decoder {{
|
||||
WarnUnimplemented::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
#ifdef SS_COMPATIBLE_DISASSEMBLY
|
||||
return csprintf("%-10s", mnemonic);
|
||||
#else
|
||||
return csprintf("%-10s (unimplemented)", mnemonic);
|
||||
#endif
|
||||
}
|
||||
}};
|
||||
|
||||
@@ -127,7 +116,7 @@ output exec {{
|
||||
Trace::InstRecord *traceData) const
|
||||
{
|
||||
if (!warned) {
|
||||
warn("instruction '%s' unimplemented\n", mnemonic);
|
||||
warn("\tinstruction '%s' unimplemented\n", mnemonic);
|
||||
warned = true;
|
||||
}
|
||||
|
||||
@@ -146,28 +135,3 @@ def format WarnUnimpl() {{
|
||||
decode_block = BasicDecodeWithMnemonic.subst(iop)
|
||||
}};
|
||||
|
||||
output header {{
|
||||
/**
|
||||
* Static instruction class for unknown (illegal) instructions.
|
||||
* These cause simulator termination if they are executed in a
|
||||
* non-speculative mode. This is a leaf class.
|
||||
*/
|
||||
class Unknown : public MipsStaticInst
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
Unknown(MachInst _machInst)
|
||||
: MipsStaticInst("unknown", _machInst, No_OpClass)
|
||||
{
|
||||
// don't call execute() (which panics) if we're on a
|
||||
// speculative path
|
||||
flags[IsNonSpeculative] = true;
|
||||
}
|
||||
|
||||
%(BasicExecDeclare)s
|
||||
|
||||
std::string
|
||||
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
}};
|
||||
|
||||
|
||||
@@ -34,28 +34,31 @@
|
||||
//
|
||||
|
||||
output header {{
|
||||
std::string inst2string(MachInst machInst);
|
||||
}};
|
||||
output decoder {{
|
||||
|
||||
std::string inst2string(MachInst machInst)
|
||||
{
|
||||
string str = "";
|
||||
uint32_t mask = 0x80000000;
|
||||
|
||||
for(int i=0; i < 32; i++) {
|
||||
if ((machInst & mask) == 0) {
|
||||
str += "0";
|
||||
} else {
|
||||
str += "1";
|
||||
/**
|
||||
* Static instruction class for unknown (illegal) instructions.
|
||||
* These cause simulator termination if they are executed in a
|
||||
* non-speculative mode. This is a leaf class.
|
||||
*/
|
||||
class Unknown : public MipsStaticInst
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
Unknown(MachInst _machInst)
|
||||
: MipsStaticInst("unknown", _machInst, No_OpClass)
|
||||
{
|
||||
// don't call execute() (which panics) if we're on a
|
||||
// speculative path
|
||||
flags[IsNonSpeculative] = true;
|
||||
}
|
||||
|
||||
mask = mask >> 1;
|
||||
}
|
||||
%(BasicExecDeclare)s
|
||||
|
||||
return str;
|
||||
}
|
||||
std::string
|
||||
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
|
||||
};
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
std::string
|
||||
Unknown::generateDisassembly(Addr pc, const SymbolTable *symtab) const
|
||||
{
|
||||
|
||||
@@ -90,7 +90,31 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags,
|
||||
+ completeAccTemplate.subst(completeacc_iop))
|
||||
}};
|
||||
|
||||
output header {{
|
||||
std::string inst2string(MachInst machInst);
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
|
||||
std::string inst2string(MachInst machInst)
|
||||
{
|
||||
string str = "";
|
||||
uint32_t mask = 0x80000000;
|
||||
|
||||
for(int i=0; i < 32; i++) {
|
||||
if ((machInst & mask) == 0) {
|
||||
str += "0";
|
||||
} else {
|
||||
str += "1";
|
||||
}
|
||||
|
||||
mask = mask >> 1;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
}};
|
||||
output exec {{
|
||||
|
||||
using namespace MipsISA;
|
||||
@@ -124,6 +148,7 @@ output exec {{
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}};
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Output include file directives.
|
||||
@@ -19,6 +21,7 @@ output decoder {{
|
||||
#include "cpu/exec_context.hh" // for Jump::branchTarget()
|
||||
#include "arch/mips/faults.hh"
|
||||
#include "arch/mips/isa_traits.hh"
|
||||
#include "arch/mips/utility.hh"
|
||||
|
||||
#include <math.h>
|
||||
#if defined(linux)
|
||||
@@ -31,6 +34,8 @@ using namespace MipsISA;
|
||||
output exec {{
|
||||
#include "arch/mips/faults.hh"
|
||||
#include "arch/mips/isa_traits.hh"
|
||||
#include "arch/mips/utility.hh"
|
||||
|
||||
#include <math.h>
|
||||
#if defined(linux)
|
||||
#include <fenv.h>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// -*- mode:c++ -*-
|
||||
|
||||
def operand_types {{
|
||||
'sb' : ('signed int', 8),
|
||||
'ub' : ('unsigned int', 8),
|
||||
|
||||
@@ -42,6 +42,7 @@ using namespace std;
|
||||
void
|
||||
MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||
{
|
||||
panic("Copy Regs Not Implemented Yet\n");
|
||||
/*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag);
|
||||
uniq = xc->readMiscReg(MipsISA::Uniq_DepTag);
|
||||
lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag);
|
||||
@@ -55,6 +56,7 @@ MipsISA::copyRegs(ThreadContext *src, ThreadContext *dest)
|
||||
void
|
||||
MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc)
|
||||
{
|
||||
panic("Copy Misc. Regs Not Implemented Yet\n");
|
||||
/*fpcr = xc->readMiscReg(MipsISA::Fpcr_DepTag);
|
||||
uniq = xc->readMiscReg(MipsISA::Uniq_DepTag);
|
||||
lock_flag = xc->readMiscReg(MipsISA::Lock_Flag_DepTag);
|
||||
@@ -63,77 +65,6 @@ MipsISA::MiscRegFile::copyMiscRegs(ThreadContext *tc)
|
||||
#endif*/
|
||||
}
|
||||
|
||||
uint64_t
|
||||
MipsISA::fpConvert(double fp_val, ConvertType cvt_type)
|
||||
{
|
||||
|
||||
switch (cvt_type)
|
||||
{
|
||||
case SINGLE_TO_DOUBLE:
|
||||
double sdouble_val = fp_val;
|
||||
void *sdouble_ptr = &sdouble_val;
|
||||
uint64_t sdp_bits = *(uint64_t *) sdouble_ptr;
|
||||
return sdp_bits;
|
||||
|
||||
case SINGLE_TO_WORD:
|
||||
int32_t sword_val = (int32_t) fp_val;
|
||||
void *sword_ptr = &sword_val;
|
||||
uint64_t sword_bits= *(uint32_t *) sword_ptr;
|
||||
return sword_bits;
|
||||
|
||||
case WORD_TO_SINGLE:
|
||||
float wfloat_val = fp_val;
|
||||
void *wfloat_ptr = &wfloat_val;
|
||||
uint64_t wfloat_bits = *(uint32_t *) wfloat_ptr;
|
||||
return wfloat_bits;
|
||||
|
||||
case WORD_TO_DOUBLE:
|
||||
double wdouble_val = fp_val;
|
||||
void *wdouble_ptr = &wdouble_val;
|
||||
uint64_t wdp_bits = *(uint64_t *) wdouble_ptr;
|
||||
return wdp_bits;
|
||||
|
||||
default:
|
||||
panic("Invalid Floating Point Conversion Type (%d). See \"types.hh\" for List of Conversions\n",cvt_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
MipsISA::roundFP(double val, int digits)
|
||||
{
|
||||
double digit_offset = pow(10.0,digits);
|
||||
val = val * digit_offset;
|
||||
val = val + 0.5;
|
||||
val = floor(val);
|
||||
val = val / digit_offset;
|
||||
return val;
|
||||
}
|
||||
|
||||
double
|
||||
MipsISA::truncFP(double val)
|
||||
{
|
||||
int trunc_val = (int) val;
|
||||
return (double) trunc_val;
|
||||
}
|
||||
|
||||
bool
|
||||
MipsISA::getFPConditionCode(uint32_t fcsr_reg, int cc)
|
||||
{
|
||||
//uint32_t cc_bits = xc->readFloatReg(35);
|
||||
return false;//regFile.floatRegfile.getConditionCode(cc);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MipsISA::makeCCVector(uint32_t fcsr, int num, bool val)
|
||||
{
|
||||
int shift = (num == 0) ? 22 : num + 23;
|
||||
|
||||
fcsr = fcsr | (val << shift);
|
||||
|
||||
return fcsr;
|
||||
}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
|
||||
static inline Addr
|
||||
|
||||
@@ -135,7 +135,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||
/* 14 */ SyscallDesc("mknod", unimplementedFunc),
|
||||
/* 15 */ SyscallDesc("chmod", chmodFunc<MipsLinux>),
|
||||
/* 16 */ SyscallDesc("lchown", chownFunc),
|
||||
/* 17 */ SyscallDesc("break", obreakFunc), /*obreak*/
|
||||
/* 17 */ SyscallDesc("break", obreakFunc),
|
||||
/* 18 */ SyscallDesc("unused#18", unimplementedFunc),
|
||||
/* 19 */ SyscallDesc("lseek", lseekFunc),
|
||||
/* 20 */ SyscallDesc("getpid", getpidFunc),
|
||||
@@ -163,7 +163,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||
/* 42 */ SyscallDesc("pipe", unimplementedFunc),
|
||||
/* 43 */ SyscallDesc("times", unimplementedFunc),
|
||||
/* 44 */ SyscallDesc("prof", unimplementedFunc),
|
||||
/* 45 */ SyscallDesc("brk", obreakFunc),/*openFunc<MipsLinux>*/
|
||||
/* 45 */ SyscallDesc("brk", obreakFunc),
|
||||
/* 46 */ SyscallDesc("setgid", unimplementedFunc),
|
||||
/* 47 */ SyscallDesc("getgid", getgidFunc),
|
||||
/* 48 */ SyscallDesc("signal", ignoreFunc),
|
||||
@@ -173,7 +173,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||
/* 52 */ SyscallDesc("umount2", unimplementedFunc),
|
||||
/* 53 */ SyscallDesc("lock", unimplementedFunc),
|
||||
/* 54 */ SyscallDesc("ioctl", ioctlFunc<MipsLinux>),
|
||||
/* 55 */ SyscallDesc("fcntl", unimplementedFunc),
|
||||
/* 55 */ SyscallDesc("fcntl", fcntlFunc),
|
||||
/* 56 */ SyscallDesc("mpx", unimplementedFunc),
|
||||
/* 57 */ SyscallDesc("setpgid", unimplementedFunc),
|
||||
/* 58 */ SyscallDesc("ulimit", unimplementedFunc),
|
||||
@@ -210,8 +210,8 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||
/* 89 */ SyscallDesc("readdir", unimplementedFunc),
|
||||
/* 90 */ SyscallDesc("mmap", mmapFunc<MipsLinux>),
|
||||
/* 91 */ SyscallDesc("munmap",munmapFunc),
|
||||
/* 92 */ SyscallDesc("truncate", fcntlFunc),
|
||||
/* 93 */ SyscallDesc("ftruncate", unimplementedFunc),
|
||||
/* 92 */ SyscallDesc("truncate", truncateFunc),
|
||||
/* 93 */ SyscallDesc("ftruncate", ftruncateFunc),
|
||||
/* 94 */ SyscallDesc("fchmod", unimplementedFunc),
|
||||
/* 95 */ SyscallDesc("fchown", unimplementedFunc),
|
||||
/* 96 */ SyscallDesc("getpriority", unimplementedFunc),
|
||||
@@ -262,7 +262,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||
/* 141 */ SyscallDesc("getdents", unimplementedFunc),
|
||||
/* 142 */ SyscallDesc("newselect", unimplementedFunc),
|
||||
/* 143 */ SyscallDesc("flock", unimplementedFunc),
|
||||
/* 144 */ SyscallDesc("msync", unimplementedFunc),/*getrlimitFunc<MipsLinux>*/
|
||||
/* 144 */ SyscallDesc("msync", unimplementedFunc),
|
||||
/* 145 */ SyscallDesc("readv", unimplementedFunc),
|
||||
/* 146 */ SyscallDesc("writev", writevFunc<MipsLinux>),
|
||||
/* 147 */ SyscallDesc("cacheflush", unimplementedFunc),
|
||||
@@ -338,7 +338,7 @@ SyscallDesc MipsLinuxProcess::syscallDescs[] = {
|
||||
/* 217 */ SyscallDesc("mincore", unimplementedFunc),
|
||||
/* 218 */ SyscallDesc("madvise", unimplementedFunc),
|
||||
/* 219 */ SyscallDesc("getdents64", unimplementedFunc),
|
||||
/* 220 */ SyscallDesc("fcntl64", fcntlFunc),
|
||||
/* 220 */ SyscallDesc("fcntl64", fcntl64Func),
|
||||
/* 221 */ SyscallDesc("reserved#221", unimplementedFunc),
|
||||
/* 222 */ SyscallDesc("gettid", unimplementedFunc),
|
||||
/* 223 */ SyscallDesc("readahead", unimplementedFunc),
|
||||
@@ -414,9 +414,7 @@ MipsLinuxProcess::MipsLinuxProcess(const std::string &name,
|
||||
: MipsLiveProcess(name, objFile, system, stdin_fd, stdout_fd, stderr_fd,
|
||||
argv, envp),
|
||||
Num_Syscall_Descs(sizeof(syscallDescs) / sizeof(SyscallDesc))
|
||||
{
|
||||
//init_regs->intRegFile[0] = 0;
|
||||
}
|
||||
{ }
|
||||
|
||||
SyscallDesc*
|
||||
MipsLinuxProcess::getDesc(int callnum)
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Korey Sewell
|
||||
*/
|
||||
|
||||
#ifndef __MIPS_LINUX_PROCESS_HH__
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
* Ali Saidi
|
||||
* Korey Sewell
|
||||
*/
|
||||
|
||||
#include "arch/mips/isa_traits.hh"
|
||||
@@ -56,7 +57,8 @@ MipsLiveProcess::create(const std::string &nm, System *system, int stdin_fd,
|
||||
|
||||
|
||||
if (objFile->getArch() != ObjectFile::Mips)
|
||||
fatal("Object file does not match architecture.");
|
||||
fatal("Object file does not match MIPS architecture.");
|
||||
|
||||
switch (objFile->getOpSys()) {
|
||||
case ObjectFile::Linux:
|
||||
process = new MipsLinuxProcess(nm, objFile, system,
|
||||
@@ -79,22 +81,19 @@ MipsLiveProcess::MipsLiveProcess(const std::string &nm, ObjectFile *objFile,
|
||||
: LiveProcess(nm, objFile, _system, stdin_fd, stdout_fd, stderr_fd,
|
||||
argv, envp)
|
||||
{
|
||||
|
||||
// XXX all the below need to be updated for SPARC - Ali
|
||||
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
|
||||
brk_point = roundUp(brk_point, VMPageSize);
|
||||
|
||||
// Set up stack. On Alpha, stack goes below text section. This
|
||||
// code should get moved to some architecture-specific spot.
|
||||
stack_base = objFile->textBase() - (409600+4096);
|
||||
|
||||
// Set up region for mmaps. Tru64 seems to start just above 0 and
|
||||
// grow up from there.
|
||||
mmap_start = mmap_end = 0x10000;
|
||||
// Set up stack. On MIPS, stack starts at the top of kuseg
|
||||
// user address space. MIPS stack grows down from here
|
||||
stack_base = 0x7FFFFFFF;
|
||||
|
||||
// Set pointer for next thread stack. Reserve 8M for main stack.
|
||||
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
|
||||
|
||||
// Set up break point (Top of Heap)
|
||||
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
|
||||
brk_point = roundUp(brk_point, VMPageSize);
|
||||
|
||||
// Set up region for mmaps. For now, start at bottom of kuseg space.
|
||||
mmap_start = mmap_end = 0x10000;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
* Ali Saidi
|
||||
* Korey Sewell
|
||||
*/
|
||||
|
||||
#ifndef __MIPS_PROCESS_HH__
|
||||
|
||||
@@ -62,13 +62,17 @@ namespace MipsISA
|
||||
switch(width)
|
||||
{
|
||||
case SingleWidth:
|
||||
void *float_ptr = ®s[floatReg];
|
||||
return *(float *) float_ptr;
|
||||
{
|
||||
void *float_ptr = ®s[floatReg];
|
||||
return *(float *) float_ptr;
|
||||
}
|
||||
|
||||
case DoubleWidth:
|
||||
uint64_t double_val = (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg];
|
||||
void *double_ptr = &double_val;
|
||||
return *(double *) double_ptr;
|
||||
{
|
||||
uint64_t double_val = (FloatReg64)regs[floatReg + 1] << 32 | regs[floatReg];
|
||||
void *double_ptr = &double_val;
|
||||
return *(double *) double_ptr;
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Attempted to read a %d bit floating point register!", width);
|
||||
@@ -99,21 +103,24 @@ namespace MipsISA
|
||||
|
||||
Fault setReg(int floatReg, const FloatReg &val, int width)
|
||||
{
|
||||
|
||||
switch(width)
|
||||
{
|
||||
case SingleWidth:
|
||||
float temp = val;
|
||||
void *float_ptr = &temp;
|
||||
regs[floatReg] = *(FloatReg32 *) float_ptr;
|
||||
break;
|
||||
{
|
||||
float temp = val;
|
||||
void *float_ptr = &temp;
|
||||
regs[floatReg] = *(FloatReg32 *) float_ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
case DoubleWidth:
|
||||
const void *double_ptr = &val;
|
||||
FloatReg64 temp_double = *(FloatReg64 *) double_ptr;
|
||||
regs[floatReg + 1] = temp_double >> 32;
|
||||
regs[floatReg] = temp_double;
|
||||
break;
|
||||
{
|
||||
const void *double_ptr = &val;
|
||||
FloatReg64 temp_double = *(FloatReg64 *) double_ptr;
|
||||
regs[floatReg + 1] = temp_double >> 32;
|
||||
regs[floatReg] = 0x0000FFFF & temp_double;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Attempted to read a %d bit floating point register!", width);
|
||||
@@ -148,14 +155,6 @@ namespace MipsISA
|
||||
void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
};
|
||||
|
||||
enum MiscFloatRegNums {
|
||||
FIR = NumFloatArchRegs,
|
||||
FCCR,
|
||||
FEXR,
|
||||
FENR,
|
||||
FCSR
|
||||
};
|
||||
|
||||
} // namespace MipsISA
|
||||
|
||||
#endif
|
||||
|
||||
200
src/arch/mips/utility.cc
Normal file
200
src/arch/mips/utility.cc
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "arch/mips/isa_traits.hh"
|
||||
#include "arch/mips/utility.hh"
|
||||
#include "config/full_system.hh"
|
||||
#include "cpu/static_inst.hh"
|
||||
#include "sim/serialize.hh"
|
||||
#include "base/bitfield.hh"
|
||||
|
||||
using namespace MipsISA;
|
||||
using namespace std;
|
||||
|
||||
uint64_t
|
||||
MipsISA::fpConvert(ConvertType cvt_type, double fp_val)
|
||||
{
|
||||
|
||||
switch (cvt_type)
|
||||
{
|
||||
case SINGLE_TO_DOUBLE:
|
||||
{
|
||||
double sdouble_val = fp_val;
|
||||
void *sdouble_ptr = &sdouble_val;
|
||||
uint64_t sdp_bits = *(uint64_t *) sdouble_ptr;
|
||||
return sdp_bits;
|
||||
}
|
||||
|
||||
case SINGLE_TO_WORD:
|
||||
{
|
||||
int32_t sword_val = (int32_t) fp_val;
|
||||
void *sword_ptr = &sword_val;
|
||||
uint64_t sword_bits= *(uint32_t *) sword_ptr;
|
||||
return sword_bits;
|
||||
}
|
||||
|
||||
case WORD_TO_SINGLE:
|
||||
{
|
||||
float wfloat_val = fp_val;
|
||||
void *wfloat_ptr = &wfloat_val;
|
||||
uint64_t wfloat_bits = *(uint32_t *) wfloat_ptr;
|
||||
return wfloat_bits;
|
||||
}
|
||||
|
||||
case WORD_TO_DOUBLE:
|
||||
{
|
||||
double wdouble_val = fp_val;
|
||||
void *wdouble_ptr = &wdouble_val;
|
||||
uint64_t wdp_bits = *(uint64_t *) wdouble_ptr;
|
||||
return wdp_bits;
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Invalid Floating Point Conversion Type (%d). See \"types.hh\" for List of Conversions\n",cvt_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
MipsISA::roundFP(double val, int digits)
|
||||
{
|
||||
double digit_offset = pow(10.0,digits);
|
||||
val = val * digit_offset;
|
||||
val = val + 0.5;
|
||||
val = floor(val);
|
||||
val = val / digit_offset;
|
||||
return val;
|
||||
}
|
||||
|
||||
double
|
||||
MipsISA::truncFP(double val)
|
||||
{
|
||||
int trunc_val = (int) val;
|
||||
return (double) trunc_val;
|
||||
}
|
||||
|
||||
bool
|
||||
MipsISA::getCondCode(uint32_t fcsr, int cc_idx)
|
||||
{
|
||||
int shift = (cc_idx == 0) ? 23 : cc_idx + 24;
|
||||
bool cc_val = (fcsr >> shift) & 0x00000001;
|
||||
return cc_val;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MipsISA::genCCVector(uint32_t fcsr, int cc_num, uint32_t cc_val)
|
||||
{
|
||||
int cc_idx = (cc_num == 0) ? 23 : cc_num + 24;
|
||||
|
||||
fcsr = bits(fcsr, 31, cc_idx + 1) << cc_idx + 1 |
|
||||
cc_val << cc_idx |
|
||||
bits(fcsr, cc_idx - 1, 0);
|
||||
|
||||
return fcsr;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MipsISA::genInvalidVector(uint32_t fcsr_bits)
|
||||
{
|
||||
//Set FCSR invalid in "flag" field
|
||||
int invalid_offset = Invalid + Flag_Field;
|
||||
fcsr_bits = fcsr_bits | (1 << invalid_offset);
|
||||
|
||||
//Set FCSR invalid in "cause" flag
|
||||
int cause_offset = Invalid + Cause_Field;
|
||||
fcsr_bits = fcsr_bits | (1 << cause_offset);
|
||||
|
||||
return fcsr_bits;
|
||||
}
|
||||
|
||||
bool
|
||||
MipsISA::isNan(void *val_ptr, int size)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 32:
|
||||
{
|
||||
uint32_t val_bits = *(uint32_t *) val_ptr;
|
||||
return (bits(val_bits, 30, 23) == 0xFF);
|
||||
}
|
||||
|
||||
case 64:
|
||||
{
|
||||
uint64_t val_bits = *(uint64_t *) val_ptr;
|
||||
return (bits(val_bits, 62, 52) == 0x7FF);
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Type unsupported. Size mismatch\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
MipsISA::isQnan(void *val_ptr, int size)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 32:
|
||||
{
|
||||
uint32_t val_bits = *(uint32_t *) val_ptr;
|
||||
return (bits(val_bits, 30, 22) == 0x1FE);
|
||||
}
|
||||
|
||||
case 64:
|
||||
{
|
||||
uint64_t val_bits = *(uint64_t *) val_ptr;
|
||||
return (bits(val_bits, 62, 51) == 0xFFE);
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Type unsupported. Size mismatch\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MipsISA::isSnan(void *val_ptr, int size)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 32:
|
||||
{
|
||||
uint32_t val_bits = *(uint32_t *) val_ptr;
|
||||
return (bits(val_bits, 30, 22) == 0x1FF);
|
||||
}
|
||||
|
||||
case 64:
|
||||
{
|
||||
uint64_t val_bits = *(uint64_t *) val_ptr;
|
||||
return (bits(val_bits, 62, 51) == 0xFFF);
|
||||
}
|
||||
|
||||
default:
|
||||
panic("Type unsupported. Size mismatch\n");
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,19 @@
|
||||
|
||||
namespace MipsISA {
|
||||
|
||||
//Floating Point Utility Functions
|
||||
uint64_t fpConvert(ConvertType cvt_type, double fp_val);
|
||||
double roundFP(double val, int digits);
|
||||
double truncFP(double val);
|
||||
|
||||
bool getCondCode(uint32_t fcsr, int cc);
|
||||
uint32_t genCCVector(uint32_t fcsr, int num, uint32_t cc_val);
|
||||
uint32_t genInvalidVector(uint32_t fcsr);
|
||||
|
||||
bool isNan(void *val_ptr, int size);
|
||||
bool isQnan(void *val_ptr, int size);
|
||||
bool isSnan(void *val_ptr, int size);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user