31,152d30
< ////////////////////////////////////////////////////////////////////
< //
< // Base class for sparc instructions, and some support functions
< //
<
< output header {{
<
< union CondCodes
< {
< struct
< {
< uint8_t c:1;
< uint8_t v:1;
< uint8_t z:1;
< uint8_t n:1;
< };
< uint32_t bits;
< };
<
< enum CondTest
< {
< Always=0x8,
< Never=0x0,
< NotEqual=0x9,
< Equal=0x1,
< Greater=0xA,
< LessOrEqual=0x2,
< GreaterOrEqual=0xB,
< Less=0x3,
< GreaterUnsigned=0xC,
< LessOrEqualUnsigned=0x4,
< CarryClear=0xD,
< CarrySet=0x5,
< Positive=0xE,
< Negative=0x6,
< OverflowClear=0xF,
< OverflowSet=0x7
< };
<
< 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.
< */
< class SparcStaticInst : public StaticInst
< {
< protected:
< // Constructor.
< SparcStaticInst(const char *mnem,
< ExtMachInst _machInst, OpClass __opClass)
< : StaticInst(mnem, _machInst, __opClass)
< {
< }
<
< std::string generateDisassembly(Addr pc,
< const SymbolTable *symtab) const;
<
< void printReg(std::ostream &os, RegId reg) const;
< void printSrcReg(std::ostream &os, int reg) const;
< void printDestReg(std::ostream &os, int reg) const;
<
< void printRegArray(std::ostream &os,
< const RegId 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)
< {
< int shiftAmount = 64 - origWidth;
< return (((int64_t)data) << shiftAmount) >> shiftAmount;
< }
< }};
<
< output decoder {{
<
< 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
< };
< }};
<
246,561d123
< output decoder {{
<
< inline void printMnemonic(std::ostream &os, const char * mnemonic)
< {
< ccprintf(os, "\t%s ", mnemonic);
< }
<
< void SparcStaticInst::printRegArray(std::ostream &os,
< const RegId indexArray[], int num) const
< {
< if (num <= 0)
< return;
< printReg(os, indexArray[0]);
< 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)
< printReg(os, _srcRegIdx[reg]);
< }
<
< void
< SparcStaticInst::printDestReg(std::ostream &os, int reg) const
< {
< if (_numDestRegs > reg)
< printReg(os, _destRegIdx[reg]);
< }
<
< void
< SparcStaticInst::printReg(std::ostream &os, RegId reg) const
< {
< const int MaxGlobal = 8;
< const int MaxOutput = 16;
< const int MaxLocal = 24;
< const int MaxInput = 32;
< const int MaxMicroReg = 40;
< RegIndex reg_idx = reg.index();
< if (reg.isIntReg()) {
< // If we used a register from the next or previous window,
< // take out the offset.
< while (reg_idx >= MaxMicroReg)
< reg_idx -= MaxMicroReg;
< if (reg_idx == FramePointerReg)
< ccprintf(os, "%%fp");
< else if (reg_idx == StackPointerReg)
< ccprintf(os, "%%sp");
< else if (reg_idx < MaxGlobal)
< ccprintf(os, "%%g%d", reg_idx);
< else if (reg_idx < MaxOutput)
< ccprintf(os, "%%o%d", reg_idx - MaxGlobal);
< else if (reg_idx < MaxLocal)
< ccprintf(os, "%%l%d", reg_idx - MaxOutput);
< else if (reg_idx < MaxInput)
< ccprintf(os, "%%i%d", reg_idx - MaxLocal);
< else if (reg_idx < MaxMicroReg)
< ccprintf(os, "%%u%d", reg_idx - MaxInput);
< // The fake int regs that are really control regs
< else {
< switch (reg_idx - 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.isFloatReg()) {
< ccprintf(os, "%%f%d", reg_idx);
< } else {
< switch (reg_idx) {
< 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_idx);
< }
< }
< }
<
< std::string
< SparcStaticInst::generateDisassembly(Addr pc,
< const SymbolTable *symtab) const
< {
< std::stringstream ss;
<
< printMnemonic(ss, mnemonic);
<
< // 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]);
< }
<
< // just print the first dest... if there's a second one,
< // it's generally implicit
< if (_numDestRegs > 0) {
< if (_numSrcRegs > 0)
< ss << ",";
< printReg(ss, _destRegIdx[0]);
< }
<
< return ss.str();
< }
<
< 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 = 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:
< return false;
< case NotEqual:
< return !condCodes.z;
< case Equal:
< return condCodes.z;
< case Greater:
< return !(condCodes.z | (condCodes.n ^ condCodes.v));
< case LessOrEqual:
< return condCodes.z | (condCodes.n ^ condCodes.v);
< case GreaterOrEqual:
< return !(condCodes.n ^ condCodes.v);
< case Less:
< return (condCodes.n ^ condCodes.v);
< case GreaterUnsigned:
< return !(condCodes.c | condCodes.z);
< case LessOrEqualUnsigned:
< return (condCodes.c | condCodes.z);
< case CarryClear:
< return !condCodes.c;
< case CarrySet:
< return condCodes.c;
< case Positive:
< return !condCodes.n;
< case Negative:
< return condCodes.n;
< case OverflowClear:
< return !condCodes.v;
< case OverflowSet:
< return condCodes.v;
< }
< panic("Tried testing condition nonexistant "
< "condition code %d", condition);
< }
< }};
<
580a143
>