-// Copyright (c) 2006 The Regents of The University of Michigan
+// Copyright (c) 2006-2007 The Regents of The University of Michigan
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
OverflowSet=0x7
};
- extern char * CondTestAbbrev[];
+ enum FpCondTest
+ {
+ FAlways=0x8,
+ FNever=0x0,
+ FUnordered=0x7,
+ FGreater=0x6,
+ FUnorderedOrGreater=0x5,
+ FLess=0x4,
+ FUnorderedOrLess=0x3,
+ FLessOrGreater=0x2,
+ FNotEqual=0x1,
+ FEqual=0x9,
+ FUnorderedOrEqual=0xA,
+ FGreaterOrEqual=0xB,
+ FUnorderedOrGreaterOrEqual=0xC,
+ FLessOrEqual=0xD,
+ FUnorderedOrLessOrEqual=0xE,
+ FOrdered=0xF
+ };
+
+ extern const char *CondTestAbbrev[];
/**
* Base class for all SPARC static instructions.
void printRegArray(std::ostream &os,
const RegIndex indexArray[], int num) const;
+
+ void advancePC(SparcISA::PCState &pcState) const;
};
+ bool passesFpCondition(uint32_t fcc, uint32_t condition);
+
bool passesCondition(uint32_t codes, uint32_t condition);
- inline int64_t sign_ext(uint64_t data, int origWidth)
+ inline int64_t
+ sign_ext(uint64_t data, int origWidth)
{
int shiftAmount = 64 - origWidth;
return (((int64_t)data) << shiftAmount) >> shiftAmount;
output decoder {{
- char * CondTestAbbrev[] =
+ const char *CondTestAbbrev[] =
{
- "nev", //Never
- "e", //Equal
- "le", //Less or Equal
- "l", //Less
- "leu", //Less or Equal Unsigned
- "c", //Carry set
- "n", //Negative
- "o", //Overflow set
- "a", //Always
- "ne", //Not Equal
- "g", //Greater
- "ge", //Greater or Equal
- "gu", //Greater Unsigned
- "cc", //Carry clear
- "p", //Positive
- "oc" //Overflow Clear
+ "nev", // Never
+ "e", // Equal
+ "le", // Less or Equal
+ "l", // Less
+ "leu", // Less or Equal Unsigned
+ "c", // Carry set
+ "n", // Negative
+ "o", // Overflow set
+ "a", // Always
+ "ne", // Not Equal
+ "g", // Greater
+ "ge", // Greater or Equal
+ "gu", // Greater Unsigned
+ "cc", // Carry clear
+ "p", // Positive
+ "oc" // Overflow Clear
};
}};
}
}};
+output header {{
+ union DoubleSingle
+ {
+ double d;
+ uint64_t ui;
+ uint32_t s[2];
+ DoubleSingle(double _d) : d(_d)
+ {}
+ DoubleSingle(uint64_t _ui) : ui(_ui)
+ {}
+ DoubleSingle(uint32_t _s0, uint32_t _s1)
+ {
+ s[0] = _s0;
+ s[1] = _s1;
+ }
+ };
+}};
+
+let {{
+ def filterDoubles(code):
+ assignRE = re.compile(r'\s*=(?!=)', re.MULTILINE)
+ for opName in ("Frd", "Frs1", "Frs2", "Frd_N"):
+ next_pos = 0
+ operandsREString = (r'''
+ (?<!\w) # neg. lookbehind assertion: prevent partial matches
+ ((%s)(?:_([^\W_]+))?) # match: operand with optional '.' then suffix
+ (?!\w) # neg. lookahead assertion: prevent partial matches
+ ''' % opName)
+ operandsRE = re.compile(operandsREString, re.MULTILINE|re.VERBOSE)
+ is_src = False
+ is_dest = False
+ extension = None
+ foundOne = False
+ while 1:
+ match = operandsRE.search(code, next_pos)
+ if not match:
+ break
+ foundOne = True
+ op = match.groups()
+ (op_full, op_base, op_ext) = op
+ is_dest_local = (assignRE.match(code, match.end()) != None)
+ is_dest = is_dest or is_dest_local
+ is_src = is_src or not is_dest_local
+ if extension and extension != op_ext:
+ raise Exception, "Inconsistent extensions in double filter."
+ extension = op_ext
+ next_pos = match.end()
+ if foundOne:
+ # Get rid of any unwanted extension
+ code = operandsRE.sub(op_base, code)
+ is_int = False
+ member = "d"
+ if extension in ("sb", "ub", "shw", "uhw", "sw", "uw", "sdw", "udw"):
+ is_int = True
+ member = "ui"
+ if is_src:
+ code = ("%s = DoubleSingle(%s_high, %s_low).%s;" % \
+ (opName, opName, opName, member)) + code
+ if is_dest:
+ code += '''
+ %s_low = DoubleSingle(%s).s[1];
+ %s_high = DoubleSingle(%s).s[0];''' % \
+ (opName, opName, opName, opName)
+ if is_int:
+ code = ("uint64_t %s;" % opName) + code
+ else:
+ code = ("double %s;" % opName) + code
+ return code
+}};
+
let {{
def splitOutImm(code):
- matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>\.\w+)?')
+ matcher = re.compile(r'Rs(?P<rNum>\d)_or_imm(?P<iNum>\d+)(?P<typeQual>_[^\W_]+)?')
rOrImmMatch = matcher.search(code)
if (rOrImmMatch == None):
return (False, code, '', '', '')
void SparcStaticInst::printRegArray(std::ostream &os,
const RegIndex indexArray[], int num) const
{
- if(num <= 0)
+ if (num <= 0)
return;
printReg(os, indexArray[0]);
- for(int x = 1; x < num; x++)
- {
+ for (int x = 1; x < num; x++) {
os << ", ";
printReg(os, indexArray[x]);
}
}
+ void
+ SparcStaticInst::advancePC(SparcISA::PCState &pcState) const
+ {
+ pcState.advance();
+ }
+
void
SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
{
- if(_numSrcRegs > reg)
+ if (_numSrcRegs > reg)
printReg(os, _srcRegIdx[reg]);
}
void
SparcStaticInst::printDestReg(std::ostream &os, int reg) const
{
- if(_numDestRegs > reg)
+ if (_numDestRegs > reg)
printReg(os, _destRegIdx[reg]);
}
const int MaxOutput = 16;
const int MaxLocal = 24;
const int MaxInput = 32;
- const int MaxMicroReg = 33;
- if (reg == FramePointerReg)
- ccprintf(os, "%%fp");
- else if (reg == StackPointerReg)
- ccprintf(os, "%%sp");
- else if(reg < MaxGlobal)
- ccprintf(os, "%%g%d", reg);
- else if(reg < MaxOutput)
- ccprintf(os, "%%o%d", reg - MaxGlobal);
- else if(reg < MaxLocal)
- ccprintf(os, "%%l%d", reg - MaxOutput);
- else if(reg < MaxInput)
- ccprintf(os, "%%i%d", reg - MaxLocal);
- else if(reg < MaxMicroReg)
- ccprintf(os, "%%u%d", reg - MaxInput);
- else {
- ccprintf(os, "%%f%d", reg - FP_Base_DepTag);
+ const int MaxMicroReg = 40;
+ if (reg < FP_Reg_Base) {
+ // If we used a register from the next or previous window,
+ // take out the offset.
+ while (reg >= MaxMicroReg)
+ reg -= MaxMicroReg;
+ if (reg == FramePointerReg)
+ ccprintf(os, "%%fp");
+ else if (reg == StackPointerReg)
+ ccprintf(os, "%%sp");
+ else if (reg < MaxGlobal)
+ ccprintf(os, "%%g%d", reg);
+ else if (reg < MaxOutput)
+ ccprintf(os, "%%o%d", reg - MaxGlobal);
+ else if (reg < MaxLocal)
+ ccprintf(os, "%%l%d", reg - MaxOutput);
+ else if (reg < MaxInput)
+ ccprintf(os, "%%i%d", reg - MaxLocal);
+ else if (reg < MaxMicroReg)
+ ccprintf(os, "%%u%d", reg - MaxInput);
+ // The fake int regs that are really control regs
+ else {
+ switch (reg - MaxMicroReg) {
+ case 1:
+ ccprintf(os, "%%y");
+ break;
+ case 2:
+ ccprintf(os, "%%ccr");
+ break;
+ case 3:
+ ccprintf(os, "%%cansave");
+ break;
+ case 4:
+ ccprintf(os, "%%canrestore");
+ break;
+ case 5:
+ ccprintf(os, "%%cleanwin");
+ break;
+ case 6:
+ ccprintf(os, "%%otherwin");
+ break;
+ case 7:
+ ccprintf(os, "%%wstate");
+ break;
+ }
+ }
+ } else if (reg < Misc_Reg_Base) {
+ ccprintf(os, "%%f%d", reg - FP_Reg_Base);
+ } else {
+ switch (reg - Misc_Reg_Base) {
+ case MISCREG_ASI:
+ ccprintf(os, "%%asi");
+ break;
+ case MISCREG_FPRS:
+ ccprintf(os, "%%fprs");
+ break;
+ case MISCREG_PCR:
+ ccprintf(os, "%%pcr");
+ break;
+ case MISCREG_PIC:
+ ccprintf(os, "%%pic");
+ break;
+ case MISCREG_GSR:
+ ccprintf(os, "%%gsr");
+ break;
+ case MISCREG_SOFTINT:
+ ccprintf(os, "%%softint");
+ break;
+ case MISCREG_SOFTINT_SET:
+ ccprintf(os, "%%softint_set");
+ break;
+ case MISCREG_SOFTINT_CLR:
+ ccprintf(os, "%%softint_clr");
+ break;
+ case MISCREG_TICK_CMPR:
+ ccprintf(os, "%%tick_cmpr");
+ break;
+ case MISCREG_STICK:
+ ccprintf(os, "%%stick");
+ break;
+ case MISCREG_STICK_CMPR:
+ ccprintf(os, "%%stick_cmpr");
+ break;
+ case MISCREG_TPC:
+ ccprintf(os, "%%tpc");
+ break;
+ case MISCREG_TNPC:
+ ccprintf(os, "%%tnpc");
+ break;
+ case MISCREG_TSTATE:
+ ccprintf(os, "%%tstate");
+ break;
+ case MISCREG_TT:
+ ccprintf(os, "%%tt");
+ break;
+ case MISCREG_TICK:
+ ccprintf(os, "%%tick");
+ break;
+ case MISCREG_TBA:
+ ccprintf(os, "%%tba");
+ break;
+ case MISCREG_PSTATE:
+ ccprintf(os, "%%pstate");
+ break;
+ case MISCREG_TL:
+ ccprintf(os, "%%tl");
+ break;
+ case MISCREG_PIL:
+ ccprintf(os, "%%pil");
+ break;
+ case MISCREG_CWP:
+ ccprintf(os, "%%cwp");
+ break;
+ case MISCREG_GL:
+ ccprintf(os, "%%gl");
+ break;
+ case MISCREG_HPSTATE:
+ ccprintf(os, "%%hpstate");
+ break;
+ case MISCREG_HTSTATE:
+ ccprintf(os, "%%htstate");
+ break;
+ case MISCREG_HINTP:
+ ccprintf(os, "%%hintp");
+ break;
+ case MISCREG_HTBA:
+ ccprintf(os, "%%htba");
+ break;
+ case MISCREG_HSTICK_CMPR:
+ ccprintf(os, "%%hstick_cmpr");
+ break;
+ case MISCREG_HVER:
+ ccprintf(os, "%%hver");
+ break;
+ case MISCREG_STRAND_STS_REG:
+ ccprintf(os, "%%strand_sts_reg");
+ break;
+ case MISCREG_FSR:
+ ccprintf(os, "%%fsr");
+ break;
+ default:
+ ccprintf(os, "%%ctrl%d", reg - Misc_Reg_Base);
+ }
}
}
- std::string SparcStaticInst::generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
+ std::string
+ SparcStaticInst::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
{
std::stringstream 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)
- {
+ if (_numSrcRegs > 0)
printReg(ss, _srcRegIdx[0]);
- }
- if(_numSrcRegs > 1)
- {
+ if (_numSrcRegs > 1) {
ss << ",";
printReg(ss, _srcRegIdx[1]);
}
// just print the first dest... if there's a second one,
// it's generally implicit
- if(_numDestRegs > 0)
- {
- if(_numSrcRegs > 0)
+ if (_numDestRegs > 0) {
+ if (_numSrcRegs > 0)
ss << ",";
printReg(ss, _destRegIdx[0]);
}
return ss.str();
}
- bool passesCondition(uint32_t codes, uint32_t condition)
+ bool
+ passesFpCondition(uint32_t fcc, uint32_t condition)
+ {
+ bool u = (fcc == 3);
+ bool g = (fcc == 2);
+ bool l = (fcc == 1);
+ bool e = (fcc == 0);
+ switch (condition) {
+ case FAlways:
+ return 1;
+ case FNever:
+ return 0;
+ case FUnordered:
+ return u;
+ case FGreater:
+ return g;
+ case FUnorderedOrGreater:
+ return u || g;
+ case FLess:
+ return l;
+ case FUnorderedOrLess:
+ return u || l;
+ case FLessOrGreater:
+ return l || g;
+ case FNotEqual:
+ return l || g || u;
+ case FEqual:
+ return e;
+ case FUnorderedOrEqual:
+ return u || e;
+ case FGreaterOrEqual:
+ return g || e;
+ case FUnorderedOrGreaterOrEqual:
+ return u || g || e;
+ case FLessOrEqual:
+ return l || e;
+ case FUnorderedOrLessOrEqual:
+ return u || l || e;
+ case FOrdered:
+ return e || l || g;
+ }
+ panic("Tried testing condition nonexistant "
+ "condition code %d", condition);
+ }
+
+ bool
+ passesCondition(uint32_t codes, uint32_t condition)
{
CondCodes condCodes;
- condCodes.bits = codes;
- switch(condition)
- {
+ condCodes.bits = 0;
+ condCodes.c = codes & 0x1 ? 1 : 0;
+ condCodes.v = codes & 0x2 ? 1 : 0;
+ condCodes.z = codes & 0x4 ? 1 : 0;
+ condCodes.n = codes & 0x8 ? 1 : 0;
+
+ switch (condition) {
case Always:
return true;
case Never:
}
}};
+output exec {{
+ /// Check "FP enabled" machine status bit. Called when executing any FP
+ /// instruction.
+ /// @retval Full-system mode: NoFault if FP is enabled, FpDisabled
+ /// if not. Non-full-system mode: always returns NoFault.
+ static inline Fault
+ checkFpEnableFault(CPU_EXEC_CONTEXT *xc)
+ {
+ if (FullSystem) {
+ PSTATE pstate = xc->readMiscReg(MISCREG_PSTATE);
+ if (pstate.pef && xc->readMiscReg(MISCREG_FPRS) & 0x4) {
+ return NoFault;
+ } else {
+ return new FpDisabled;
+ }
+ } else {
+ return NoFault;
+ }
+ }
+}};
+
+