Index: src/mips64/constants-mips64.h |
diff --git a/src/mips64/constants-mips64.h b/src/mips64/constants-mips64.h |
index 76794688cf3da425ef3154755634dc51b03a5a21..2d78d2947f6eb37111a4772551617b6ce8ab0a4f 100644 |
--- a/src/mips64/constants-mips64.h |
+++ b/src/mips64/constants-mips64.h |
@@ -899,8 +899,7 @@ static constexpr uint64_t OpcodeToBitNumber(Opcode opcode) { |
return 1ULL << (static_cast<uint32_t>(opcode) >> kOpcodeShift); |
} |
- |
-class Instruction { |
+class InstructionBase { |
public: |
enum { |
kInstrSize = 4, |
@@ -910,6 +909,9 @@ class Instruction { |
kPCReadOffset = 0 |
}; |
+ // Instruction type. |
+ enum Type { kRegisterType, kImmediateType, kJumpType, kUnsupported = -1 }; |
+ |
// Get the raw instruction bits. |
inline Instr InstructionBits() const { |
return *reinterpret_cast<const Instr*>(this); |
@@ -930,14 +932,6 @@ class Instruction { |
return (InstructionBits() >> lo) & ((2U << (hi - lo)) - 1); |
} |
- // Instruction type. |
- enum Type { |
- kRegisterType, |
- kImmediateType, |
- kJumpType, |
- kUnsupported = -1 |
- }; |
- |
enum TypeChecks { NORMAL, EXTRA }; |
static constexpr uint64_t kOpcodeImmediateTypeMask = |
@@ -996,9 +990,6 @@ class Instruction { |
FunctionFieldToBitNumber(MOVCI) | FunctionFieldToBitNumber(SELEQZ_S) | |
FunctionFieldToBitNumber(SELNEZ_S) | FunctionFieldToBitNumber(SYNC); |
- // Get the encoding type of the instruction. |
- inline Type InstructionType(TypeChecks checks = NORMAL) const; |
- |
// Accessors for the different named fields used in the MIPS encoding. |
inline Opcode OpcodeValue() const { |
@@ -1006,118 +997,144 @@ class Instruction { |
Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift)); |
} |
+ inline int FunctionFieldRaw() const { |
+ return InstructionBits() & kFunctionFieldMask; |
+ } |
+ |
+ // Return the fields at their original place in the instruction encoding. |
+ inline Opcode OpcodeFieldRaw() const { |
+ return static_cast<Opcode>(InstructionBits() & kOpcodeMask); |
+ } |
+ |
+ // Safe to call within InstructionType(). |
+ inline int RsFieldRawNoAssert() const { |
+ return InstructionBits() & kRsFieldMask; |
+ } |
+ |
+ inline int SaFieldRaw() const { return InstructionBits() & kSaFieldMask; } |
+ |
+ // Get the encoding type of the instruction. |
+ inline Type InstructionType(TypeChecks checks = NORMAL) const; |
+ |
+ protected: |
+ InstructionBase() {} |
+}; |
+ |
+template <class T> |
+class InstructionGetters : public T { |
+ public: |
inline int RsValue() const { |
- DCHECK(InstructionType() == kRegisterType || |
- InstructionType() == kImmediateType); |
- return Bits(kRsShift + kRsBits - 1, kRsShift); |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType || |
+ this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->Bits(kRsShift + kRsBits - 1, kRsShift); |
} |
inline int RtValue() const { |
- DCHECK(InstructionType() == kRegisterType || |
- InstructionType() == kImmediateType); |
- return Bits(kRtShift + kRtBits - 1, kRtShift); |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType || |
+ this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->Bits(kRtShift + kRtBits - 1, kRtShift); |
} |
inline int RdValue() const { |
- DCHECK(InstructionType() == kRegisterType); |
- return Bits(kRdShift + kRdBits - 1, kRdShift); |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType); |
+ return this->Bits(kRdShift + kRdBits - 1, kRdShift); |
} |
inline int SaValue() const { |
- DCHECK(InstructionType() == kRegisterType); |
- return Bits(kSaShift + kSaBits - 1, kSaShift); |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType); |
+ return this->Bits(kSaShift + kSaBits - 1, kSaShift); |
} |
inline int LsaSaValue() const { |
- DCHECK(InstructionType() == kRegisterType); |
- return Bits(kSaShift + kLsaSaBits - 1, kSaShift); |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType); |
+ return this->Bits(kSaShift + kLsaSaBits - 1, kSaShift); |
} |
inline int FunctionValue() const { |
- DCHECK(InstructionType() == kRegisterType || |
- InstructionType() == kImmediateType); |
- return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift); |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType || |
+ this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift); |
} |
inline int FdValue() const { |
- return Bits(kFdShift + kFdBits - 1, kFdShift); |
+ return this->Bits(kFdShift + kFdBits - 1, kFdShift); |
} |
inline int FsValue() const { |
- return Bits(kFsShift + kFsBits - 1, kFsShift); |
+ return this->Bits(kFsShift + kFsBits - 1, kFsShift); |
} |
inline int FtValue() const { |
- return Bits(kFtShift + kFtBits - 1, kFtShift); |
+ return this->Bits(kFtShift + kFtBits - 1, kFtShift); |
} |
inline int FrValue() const { |
- return Bits(kFrShift + kFrBits -1, kFrShift); |
+ return this->Bits(kFrShift + kFrBits - 1, kFrShift); |
} |
inline int Bp2Value() const { |
- DCHECK(InstructionType() == kRegisterType); |
- return Bits(kBp2Shift + kBp2Bits - 1, kBp2Shift); |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType); |
+ return this->Bits(kBp2Shift + kBp2Bits - 1, kBp2Shift); |
} |
inline int Bp3Value() const { |
- DCHECK(InstructionType() == kRegisterType); |
- return Bits(kBp3Shift + kBp3Bits - 1, kBp3Shift); |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType); |
+ return this->Bits(kBp3Shift + kBp3Bits - 1, kBp3Shift); |
} |
// Float Compare condition code instruction bits. |
inline int FCccValue() const { |
- return Bits(kFCccShift + kFCccBits - 1, kFCccShift); |
+ return this->Bits(kFCccShift + kFCccBits - 1, kFCccShift); |
} |
// Float Branch condition code instruction bits. |
inline int FBccValue() const { |
- return Bits(kFBccShift + kFBccBits - 1, kFBccShift); |
+ return this->Bits(kFBccShift + kFBccBits - 1, kFBccShift); |
} |
// Float Branch true/false instruction bit. |
inline int FBtrueValue() const { |
- return Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift); |
+ return this->Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift); |
} |
// Return the fields at their original place in the instruction encoding. |
inline Opcode OpcodeFieldRaw() const { |
- return static_cast<Opcode>(InstructionBits() & kOpcodeMask); |
+ return static_cast<Opcode>(this->InstructionBits() & kOpcodeMask); |
} |
inline int RsFieldRaw() const { |
- DCHECK(InstructionType() == kRegisterType || |
- InstructionType() == kImmediateType); |
- return InstructionBits() & kRsFieldMask; |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType || |
+ this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->InstructionBits() & kRsFieldMask; |
} |
// Same as above function, but safe to call within InstructionType(). |
inline int RsFieldRawNoAssert() const { |
- return InstructionBits() & kRsFieldMask; |
+ return this->InstructionBits() & kRsFieldMask; |
} |
inline int RtFieldRaw() const { |
- DCHECK(InstructionType() == kRegisterType || |
- InstructionType() == kImmediateType); |
- return InstructionBits() & kRtFieldMask; |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType || |
+ this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->InstructionBits() & kRtFieldMask; |
} |
inline int RdFieldRaw() const { |
- DCHECK(InstructionType() == kRegisterType); |
- return InstructionBits() & kRdFieldMask; |
+ DCHECK(this->InstructionType() == InstructionBase::kRegisterType); |
+ return this->InstructionBits() & kRdFieldMask; |
} |
inline int SaFieldRaw() const { |
- return InstructionBits() & kSaFieldMask; |
+ return this->InstructionBits() & kSaFieldMask; |
} |
inline int FunctionFieldRaw() const { |
- return InstructionBits() & kFunctionFieldMask; |
+ return this->InstructionBits() & kFunctionFieldMask; |
} |
// Get the secondary field according to the opcode. |
inline int SecondaryValue() const { |
- Opcode op = OpcodeFieldRaw(); |
+ Opcode op = this->OpcodeFieldRaw(); |
switch (op) { |
case SPECIAL: |
case SPECIAL2: |
@@ -1132,34 +1149,34 @@ class Instruction { |
} |
inline int32_t ImmValue(int bits) const { |
- DCHECK(InstructionType() == kImmediateType); |
- return Bits(bits - 1, 0); |
+ DCHECK(this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->Bits(bits - 1, 0); |
} |
inline int32_t Imm16Value() const { |
- DCHECK(InstructionType() == kImmediateType); |
- return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift); |
+ DCHECK(this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift); |
} |
inline int32_t Imm18Value() const { |
- DCHECK(InstructionType() == kImmediateType); |
- return Bits(kImm18Shift + kImm18Bits - 1, kImm18Shift); |
+ DCHECK(this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->Bits(kImm18Shift + kImm18Bits - 1, kImm18Shift); |
} |
inline int32_t Imm19Value() const { |
- DCHECK(InstructionType() == kImmediateType); |
- return Bits(kImm19Shift + kImm19Bits - 1, kImm19Shift); |
+ DCHECK(this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->Bits(kImm19Shift + kImm19Bits - 1, kImm19Shift); |
} |
inline int32_t Imm21Value() const { |
- DCHECK(InstructionType() == kImmediateType); |
- return Bits(kImm21Shift + kImm21Bits - 1, kImm21Shift); |
+ DCHECK(this->InstructionType() == InstructionBase::kImmediateType); |
+ return this->Bits(kImm21Shift + kImm21Bits - 1, kImm21Shift); |
} |
inline int32_t Imm26Value() const { |
- DCHECK((InstructionType() == kJumpType) || |
- (InstructionType() == kImmediateType)); |
- return Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift); |
+ DCHECK((this->InstructionType() == InstructionBase::kJumpType) || |
+ (this->InstructionType() == InstructionBase::kImmediateType)); |
+ return this->Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift); |
} |
static bool IsForbiddenAfterBranchInstr(Instr instr); |
@@ -1167,14 +1184,21 @@ class Instruction { |
// Say if the instruction should not be used in a branch delay slot or |
// immediately after a compact branch. |
inline bool IsForbiddenAfterBranch() const { |
- return IsForbiddenAfterBranchInstr(InstructionBits()); |
+ return IsForbiddenAfterBranchInstr(this->InstructionBits()); |
+ } |
+ |
+ inline bool IsForbiddenInBranchDelay() const { |
+ return IsForbiddenAfterBranch(); |
} |
// Say if the instruction 'links'. e.g. jal, bal. |
bool IsLinkingInstruction() const; |
// Say if the instruction is a break or a trap. |
bool IsTrap() const; |
+}; |
+class Instruction : public InstructionGetters<InstructionBase> { |
+ public: |
// Instructions are read of out a code stream. The only way to get a |
// reference to an instruction is to convert a pointer. There is no way |
// to allocate or create instances of class Instruction. |
@@ -1202,8 +1226,8 @@ const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize * 2; |
const int kInvalidStackOffset = -1; |
const int kBranchReturnOffset = 2 * Instruction::kInstrSize; |
- |
-Instruction::Type Instruction::InstructionType(TypeChecks checks) const { |
+InstructionBase::Type InstructionBase::InstructionType( |
+ TypeChecks checks) const { |
if (checks == EXTRA) { |
if (OpcodeToBitNumber(OpcodeFieldRaw()) & kOpcodeImmediateTypeMask) { |
return kImmediateType; |
@@ -1306,9 +1330,119 @@ Instruction::Type Instruction::InstructionType(TypeChecks checks) const { |
} |
return kUnsupported; |
} |
- |
#undef OpcodeToBitNumber |
#undef FunctionFieldToBitNumber |
+ |
Ilija.Pavlovic1
2016/09/29 10:13:39
Why this code is transferred here from constants-m
balazs.kilvady
2016/09/29 10:57:41
Because of the template stuff. Template implementa
Ilija.Pavlovic1
2016/09/29 13:15:33
Acknowledged.
|
+// ----------------------------------------------------------------------------- |
+// Instructions. |
+ |
+template <class P> |
+bool InstructionGetters<P>::IsLinkingInstruction() const { |
+ switch (OpcodeFieldRaw()) { |
+ case JAL: |
+ return true; |
+ case POP76: |
+ if (RsFieldRawNoAssert() == JIALC) |
+ return true; // JIALC |
+ else |
+ return false; // BNEZC |
+ case REGIMM: |
+ switch (RtFieldRaw()) { |
+ case BGEZAL: |
+ case BLTZAL: |
+ return true; |
+ default: |
+ return false; |
+ } |
+ case SPECIAL: |
+ switch (FunctionFieldRaw()) { |
+ case JALR: |
+ return true; |
+ default: |
+ return false; |
+ } |
+ default: |
+ return false; |
+ } |
+} |
+ |
+template <class P> |
+bool InstructionGetters<P>::IsTrap() const { |
+ if (OpcodeFieldRaw() != SPECIAL) { |
+ return false; |
+ } else { |
+ switch (FunctionFieldRaw()) { |
+ case BREAK: |
+ case TGE: |
+ case TGEU: |
+ case TLT: |
+ case TLTU: |
+ case TEQ: |
+ case TNE: |
+ return true; |
+ default: |
+ return false; |
+ } |
+ } |
+} |
+ |
+// static |
+template <class T> |
+bool InstructionGetters<T>::IsForbiddenAfterBranchInstr(Instr instr) { |
+ Opcode opcode = static_cast<Opcode>(instr & kOpcodeMask); |
+ switch (opcode) { |
+ case J: |
+ case JAL: |
+ case BEQ: |
+ case BNE: |
+ case BLEZ: // POP06 bgeuc/bleuc, blezalc, bgezalc |
+ case BGTZ: // POP07 bltuc/bgtuc, bgtzalc, bltzalc |
+ case BEQL: |
+ case BNEL: |
+ case BLEZL: // POP26 bgezc, blezc, bgec/blec |
+ case BGTZL: // POP27 bgtzc, bltzc, bltc/bgtc |
+ case BC: |
+ case BALC: |
+ case POP10: // beqzalc, bovc, beqc |
+ case POP30: // bnezalc, bnvc, bnec |
+ case POP66: // beqzc, jic |
+ case POP76: // bnezc, jialc |
+ return true; |
+ case REGIMM: |
+ switch (instr & kRtFieldMask) { |
+ case BLTZ: |
+ case BGEZ: |
+ case BLTZAL: |
+ case BGEZAL: |
+ return true; |
+ default: |
+ return false; |
+ } |
+ break; |
+ case SPECIAL: |
+ switch (instr & kFunctionFieldMask) { |
+ case JR: |
+ case JALR: |
+ return true; |
+ default: |
+ return false; |
+ } |
+ break; |
+ case COP1: |
+ switch (instr & kRsFieldMask) { |
+ case BC1: |
+ case BC1EQZ: |
+ case BC1NEZ: |
+ return true; |
+ break; |
+ default: |
+ return false; |
+ } |
+ break; |
+ default: |
+ return false; |
+ } |
+} |
} // namespace internal |
} // namespace v8 |