Index: src/mips/constants-mips.h |
diff --git a/src/mips/constants-mips.h b/src/mips/constants-mips.h |
index d0fdf88dbaf966928177c6f2f97ffefc62a01f6b..b20e9a284dff7ff713f4ee60f150f518482ebccb 100644 |
--- a/src/mips/constants-mips.h |
+++ b/src/mips/constants-mips.h |
@@ -28,15 +28,25 @@ |
#ifndef V8_MIPS_CONSTANTS_H_ |
#define V8_MIPS_CONSTANTS_H_ |
-#include "checks.h" |
- |
// UNIMPLEMENTED_ macro for MIPS. |
+#ifdef DEBUG |
#define UNIMPLEMENTED_MIPS() \ |
v8::internal::PrintF("%s, \tline %d: \tfunction %s not implemented. \n", \ |
__FILE__, __LINE__, __func__) |
+#else |
+#define UNIMPLEMENTED_MIPS() |
+#endif |
+ |
#define UNSUPPORTED_MIPS() v8::internal::PrintF("Unsupported instruction.\n") |
+#ifdef _MIPS_ARCH_MIPS32R2 |
+ #define mips32r2 1 |
+#else |
+ #define mips32r2 0 |
+#endif |
+ |
+ |
// Defines constants and accessor classes to assemble, disassemble and |
// simulate MIPS32 instructions. |
// |
@@ -44,8 +54,8 @@ |
// Volume II: The MIPS32 Instruction Set |
// Try www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol2.pdf. |
-namespace assembler { |
-namespace mips { |
+namespace v8 { |
+namespace internal { |
// ----------------------------------------------------------------------------- |
// Registers and FPURegister. |
@@ -61,9 +71,18 @@ static const int kNumSimuRegisters = 35; |
static const int kPCRegister = 34; |
// Number coprocessor registers. |
-static const int kNumFPURegister = 32; |
+static const int kNumFPURegisters = 32; |
static const int kInvalidFPURegister = -1; |
+// FPU (coprocessor 1) control registers. Currently only FCSR is implemented. |
+static const int kFCSRRegister = 31; |
+static const int kInvalidFPUControlRegister = -1; |
+static const uint32_t kFPUInvalidResult = (uint32_t) (1 << 31) - 1; |
+ |
+// FCSR constants. |
+static const uint32_t kFCSRFlagMask = (1 << 6) - 1; |
+static const uint32_t kFCSRFlagShift = 2; |
+ |
// Helper functions for converting between register numbers and names. |
class Registers { |
public: |
@@ -88,7 +107,7 @@ class Registers { |
}; |
// Helper functions for converting between register numbers and names. |
-class FPURegister { |
+class FPURegisters { |
public: |
// Return the name of the register. |
static const char* Name(int reg); |
@@ -103,7 +122,7 @@ class FPURegister { |
private: |
- static const char* names_[kNumFPURegister]; |
+ static const char* names_[kNumFPURegisters]; |
static const RegisterAlias aliases_[]; |
}; |
@@ -136,6 +155,7 @@ static const int kSaShift = 6; |
static const int kSaBits = 5; |
static const int kFunctionShift = 0; |
static const int kFunctionBits = 6; |
+static const int kLuiShift = 16; |
static const int kImm16Shift = 0; |
static const int kImm16Bits = 16; |
@@ -146,6 +166,14 @@ static const int kFsShift = 11; |
static const int kFsBits = 5; |
static const int kFtShift = 16; |
static const int kFtBits = 5; |
+static const int kFdShift = 6; |
+static const int kFdBits = 5; |
+static const int kFCccShift = 8; |
+static const int kFCccBits = 3; |
+static const int kFBccShift = 18; |
+static const int kFBccBits = 3; |
+static const int kFBtrueShift = 16; |
+static const int kFBtrueBits = 1; |
// ----- Miscellianous useful masks. |
// Instruction bit masks. |
@@ -159,9 +187,9 @@ static const int kSaFieldMask = ((1 << kSaBits) - 1) << kSaShift; |
static const int kFunctionFieldMask = |
((1 << kFunctionBits) - 1) << kFunctionShift; |
// Misc masks. |
-static const int HIMask = 0xffff << 16; |
-static const int LOMask = 0xffff; |
-static const int signMask = 0x80000000; |
+static const int kHiMask = 0xffff << 16; |
+static const int kLoMask = 0xffff; |
+static const int kSignMask = 0x80000000; |
// ----- MIPS Opcodes and Function Fields. |
@@ -194,12 +222,20 @@ enum Opcode { |
BGTZL = ((2 << 3) + 7) << kOpcodeShift, |
SPECIAL2 = ((3 << 3) + 4) << kOpcodeShift, |
+ SPECIAL3 = ((3 << 3) + 7) << kOpcodeShift, |
LB = ((4 << 3) + 0) << kOpcodeShift, |
+ LH = ((4 << 3) + 1) << kOpcodeShift, |
+ LWL = ((4 << 3) + 2) << kOpcodeShift, |
LW = ((4 << 3) + 3) << kOpcodeShift, |
LBU = ((4 << 3) + 4) << kOpcodeShift, |
+ LHU = ((4 << 3) + 5) << kOpcodeShift, |
+ LWR = ((4 << 3) + 6) << kOpcodeShift, |
SB = ((5 << 3) + 0) << kOpcodeShift, |
+ SH = ((5 << 3) + 1) << kOpcodeShift, |
+ SWL = ((5 << 3) + 2) << kOpcodeShift, |
SW = ((5 << 3) + 3) << kOpcodeShift, |
+ SWR = ((5 << 3) + 6) << kOpcodeShift, |
LWC1 = ((6 << 3) + 1) << kOpcodeShift, |
LDC1 = ((6 << 3) + 5) << kOpcodeShift, |
@@ -216,9 +252,12 @@ enum SecondaryField { |
SLLV = ((0 << 3) + 4), |
SRLV = ((0 << 3) + 6), |
SRAV = ((0 << 3) + 7), |
+ MOVCI = ((0 << 3) + 1), |
JR = ((1 << 3) + 0), |
JALR = ((1 << 3) + 1), |
+ MOVZ = ((1 << 3) + 2), |
+ MOVN = ((1 << 3) + 3), |
BREAK = ((1 << 3) + 5), |
MFHI = ((2 << 3) + 0), |
@@ -250,6 +289,12 @@ enum SecondaryField { |
// SPECIAL2 Encoding of Function Field. |
MUL = ((0 << 3) + 2), |
+ CLZ = ((4 << 3) + 0), |
+ CLO = ((4 << 3) + 1), |
+ |
+ // SPECIAL3 Encoding of Function Field. |
+ EXT = ((0 << 3) + 0), |
+ INS = ((0 << 3) + 4), |
// REGIMM encoding of rt Field. |
BLTZ = ((0 << 3) + 0) << 16, |
@@ -259,8 +304,10 @@ enum SecondaryField { |
// COP1 Encoding of rs Field. |
MFC1 = ((0 << 3) + 0) << 21, |
+ CFC1 = ((0 << 3) + 2) << 21, |
MFHC1 = ((0 << 3) + 3) << 21, |
MTC1 = ((0 << 3) + 4) << 21, |
+ CTC1 = ((0 << 3) + 6) << 21, |
MTHC1 = ((0 << 3) + 7) << 21, |
BC1 = ((1 << 3) + 0) << 21, |
S = ((2 << 3) + 0) << 21, |
@@ -269,14 +316,46 @@ enum SecondaryField { |
L = ((2 << 3) + 5) << 21, |
PS = ((2 << 3) + 6) << 21, |
// COP1 Encoding of Function Field When rs=S. |
+ ROUND_L_S = ((1 << 3) + 0), |
+ TRUNC_L_S = ((1 << 3) + 1), |
+ CEIL_L_S = ((1 << 3) + 2), |
+ FLOOR_L_S = ((1 << 3) + 3), |
+ ROUND_W_S = ((1 << 3) + 4), |
+ TRUNC_W_S = ((1 << 3) + 5), |
+ CEIL_W_S = ((1 << 3) + 6), |
+ FLOOR_W_S = ((1 << 3) + 7), |
CVT_D_S = ((4 << 3) + 1), |
CVT_W_S = ((4 << 3) + 4), |
CVT_L_S = ((4 << 3) + 5), |
CVT_PS_S = ((4 << 3) + 6), |
// COP1 Encoding of Function Field When rs=D. |
+ ADD_D = ((0 << 3) + 0), |
+ SUB_D = ((0 << 3) + 1), |
+ MUL_D = ((0 << 3) + 2), |
+ DIV_D = ((0 << 3) + 3), |
+ SQRT_D = ((0 << 3) + 4), |
+ ABS_D = ((0 << 3) + 5), |
+ MOV_D = ((0 << 3) + 6), |
+ NEG_D = ((0 << 3) + 7), |
+ ROUND_L_D = ((1 << 3) + 0), |
+ TRUNC_L_D = ((1 << 3) + 1), |
+ CEIL_L_D = ((1 << 3) + 2), |
+ FLOOR_L_D = ((1 << 3) + 3), |
+ ROUND_W_D = ((1 << 3) + 4), |
+ TRUNC_W_D = ((1 << 3) + 5), |
+ CEIL_W_D = ((1 << 3) + 6), |
+ FLOOR_W_D = ((1 << 3) + 7), |
CVT_S_D = ((4 << 3) + 0), |
CVT_W_D = ((4 << 3) + 4), |
CVT_L_D = ((4 << 3) + 5), |
+ C_F_D = ((6 << 3) + 0), |
+ C_UN_D = ((6 << 3) + 1), |
+ C_EQ_D = ((6 << 3) + 2), |
+ C_UEQ_D = ((6 << 3) + 3), |
+ C_OLT_D = ((6 << 3) + 4), |
+ C_ULT_D = ((6 << 3) + 5), |
+ C_OLE_D = ((6 << 3) + 6), |
+ C_ULE_D = ((6 << 3) + 7), |
// COP1 Encoding of Function Field When rs=W or L. |
CVT_S_W = ((4 << 3) + 0), |
CVT_D_W = ((4 << 3) + 1), |
@@ -293,7 +372,7 @@ enum SecondaryField { |
// the 'U' prefix is used to specify unsigned comparisons. |
enum Condition { |
// Any value < 0 is considered no_condition. |
- no_condition = -1, |
+ kNoCondition = -1, |
overflow = 0, |
no_overflow = 1, |
@@ -321,12 +400,59 @@ enum Condition { |
eq = equal, |
not_zero = not_equal, |
ne = not_equal, |
+ nz = not_equal, |
sign = negative, |
not_sign = positive, |
- |
- cc_default = no_condition |
+ mi = negative, |
+ pl = positive, |
+ hi = Ugreater, |
+ ls = Uless_equal, |
+ ge = greater_equal, |
+ lt = less, |
+ gt = greater, |
+ le = less_equal, |
+ hs = Ugreater_equal, |
+ lo = Uless, |
+ al = cc_always, |
+ |
+ cc_default = kNoCondition |
}; |
+ |
+// Returns the equivalent of !cc. |
+// Negation of the default kNoCondition (-1) results in a non-default |
+// no_condition value (-2). As long as tests for no_condition check |
+// for condition < 0, this will work as expected. |
+inline Condition NegateCondition(Condition cc) { |
+ ASSERT(cc != cc_always); |
+ return static_cast<Condition>(cc ^ 1); |
+} |
+ |
+ |
+inline Condition ReverseCondition(Condition cc) { |
+ switch (cc) { |
+ case Uless: |
+ return Ugreater; |
+ case Ugreater: |
+ return Uless; |
+ case Ugreater_equal: |
+ return Uless_equal; |
+ case Uless_equal: |
+ return Ugreater_equal; |
+ case less: |
+ return greater; |
+ case greater: |
+ return less; |
+ case greater_equal: |
+ return less_equal; |
+ case less_equal: |
+ return greater_equal; |
+ default: |
+ return cc; |
+ }; |
+} |
+ |
+ |
// ----- Coprocessor conditions. |
enum FPUCondition { |
F, // False |
@@ -340,6 +466,46 @@ enum FPUCondition { |
}; |
+// ----------------------------------------------------------------------------- |
+// Hints. |
+ |
+// Branch hints are not used on the MIPS. They are defined so that they can |
+// appear in shared function signatures, but will be ignored in MIPS |
+// implementations. |
+enum Hint { |
+ no_hint = 0 |
+}; |
+ |
+ |
+inline Hint NegateHint(Hint hint) { |
+ return no_hint; |
+} |
+ |
+ |
+// ----------------------------------------------------------------------------- |
+// Specific instructions, constants, and masks. |
+// These constants are declared in assembler-mips.cc, as they use named |
+// registers and other constants. |
+ |
+// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r) |
+// operations as post-increment of sp. |
+extern const Instr kPopInstruction; |
+// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp. |
+extern const Instr kPushInstruction; |
+// sw(r, MemOperand(sp, 0)) |
+extern const Instr kPushRegPattern; |
+// lw(r, MemOperand(sp, 0)) |
+extern const Instr kPopRegPattern; |
+extern const Instr kLwRegFpOffsetPattern; |
+extern const Instr kSwRegFpOffsetPattern; |
+extern const Instr kLwRegFpNegOffsetPattern; |
+extern const Instr kSwRegFpNegOffsetPattern; |
+// A mask for the Rt register for push, pop, lw, sw instructions. |
+extern const Instr kRtMask; |
+extern const Instr kLwSwInstrTypeMask; |
+extern const Instr kLwSwInstrArgumentMask; |
+extern const Instr kLwSwOffsetMask; |
+ |
// Break 0xfffff, reserved for redirected real time call. |
const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6; |
// A nop instruction. (Encoding of sll 0 0 0). |
@@ -348,10 +514,10 @@ const Instr nopInstr = 0; |
class Instruction { |
public: |
enum { |
- kInstructionSize = 4, |
- kInstructionSizeLog2 = 2, |
+ kInstrSize = 4, |
+ kInstrSizeLog2 = 2, |
// On MIPS PC cannot actually be directly accessed. We behave as if PC was |
- // always the value of the current instruction being exectued. |
+ // always the value of the current instruction being executed. |
kPCReadOffset = 0 |
}; |
@@ -388,45 +554,64 @@ class Instruction { |
// Accessors for the different named fields used in the MIPS encoding. |
- inline Opcode OpcodeField() const { |
+ inline Opcode OpcodeValue() const { |
return static_cast<Opcode>( |
Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift)); |
} |
- inline int RsField() const { |
+ inline int RsValue() const { |
ASSERT(InstructionType() == kRegisterType || |
InstructionType() == kImmediateType); |
return Bits(kRsShift + kRsBits - 1, kRsShift); |
} |
- inline int RtField() const { |
+ inline int RtValue() const { |
ASSERT(InstructionType() == kRegisterType || |
InstructionType() == kImmediateType); |
return Bits(kRtShift + kRtBits - 1, kRtShift); |
} |
- inline int RdField() const { |
+ inline int RdValue() const { |
ASSERT(InstructionType() == kRegisterType); |
return Bits(kRdShift + kRdBits - 1, kRdShift); |
} |
- inline int SaField() const { |
+ inline int SaValue() const { |
ASSERT(InstructionType() == kRegisterType); |
return Bits(kSaShift + kSaBits - 1, kSaShift); |
} |
- inline int FunctionField() const { |
+ inline int FunctionValue() const { |
ASSERT(InstructionType() == kRegisterType || |
InstructionType() == kImmediateType); |
return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift); |
} |
- inline int FsField() const { |
- return Bits(kFsShift + kRsBits - 1, kFsShift); |
+ inline int FdValue() const { |
+ return Bits(kFdShift + kFdBits - 1, kFdShift); |
+ } |
+ |
+ inline int FsValue() const { |
+ return Bits(kFsShift + kFsBits - 1, kFsShift); |
+ } |
+ |
+ inline int FtValue() const { |
+ return Bits(kFtShift + kFtBits - 1, kFtShift); |
} |
- inline int FtField() const { |
- return Bits(kFtShift + kRsBits - 1, kFtShift); |
+ // Float Compare condition code instruction bits. |
+ inline int FCccValue() const { |
+ return Bits(kFCccShift + kFCccBits - 1, kFCccShift); |
+ } |
+ |
+ // Float Branch condition code instruction bits. |
+ inline int FBccValue() const { |
+ return Bits(kFBccShift + kFBccBits - 1, kFBccShift); |
+ } |
+ |
+ // Float Branch true/false instruction bit. |
+ inline int FBtrueValue() const { |
+ return Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift); |
} |
// Return the fields at their original place in the instruction encoding. |
@@ -440,6 +625,11 @@ class Instruction { |
return InstructionBits() & kRsFieldMask; |
} |
+ // Same as above function, but safe to call within InstructionType(). |
+ inline int RsFieldRawNoAssert() const { |
+ return InstructionBits() & kRsFieldMask; |
+ } |
+ |
inline int RtFieldRaw() const { |
ASSERT(InstructionType() == kRegisterType || |
InstructionType() == kImmediateType); |
@@ -461,37 +651,37 @@ class Instruction { |
} |
// Get the secondary field according to the opcode. |
- inline int SecondaryField() const { |
+ inline int SecondaryValue() const { |
Opcode op = OpcodeFieldRaw(); |
switch (op) { |
case SPECIAL: |
case SPECIAL2: |
- return FunctionField(); |
+ return FunctionValue(); |
case COP1: |
- return RsField(); |
+ return RsValue(); |
case REGIMM: |
- return RtField(); |
+ return RtValue(); |
default: |
return NULLSF; |
} |
} |
- inline int32_t Imm16Field() const { |
+ inline int32_t Imm16Value() const { |
ASSERT(InstructionType() == kImmediateType); |
return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift); |
} |
- inline int32_t Imm26Field() const { |
+ inline int32_t Imm26Value() const { |
ASSERT(InstructionType() == kJumpType); |
return Bits(kImm16Shift + kImm26Bits - 1, kImm26Shift); |
} |
// Say if the instruction should not be used in a branch delay slot. |
- bool IsForbiddenInBranchDelay(); |
+ bool IsForbiddenInBranchDelay() const; |
// Say if the instruction 'links'. eg: jal, bal. |
- bool IsLinkingInstruction(); |
+ bool IsLinkingInstruction() const; |
// Say if the instruction is a break or a trap. |
- bool IsTrap(); |
+ bool IsTrap() const; |
// 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 |
@@ -510,16 +700,24 @@ class Instruction { |
// ----------------------------------------------------------------------------- |
// MIPS assembly various constants. |
-static const int kArgsSlotsSize = 4 * Instruction::kInstructionSize; |
+ |
+static const int kArgsSlotsSize = 4 * Instruction::kInstrSize; |
static const int kArgsSlotsNum = 4; |
+// C/C++ argument slots size. |
+static const int kCArgsSlotsSize = 4 * Instruction::kInstrSize; |
+// JS argument slots size. |
+static const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize; |
+// Assembly builtins argument slots size. |
+static const int kBArgsSlotsSize = 0 * Instruction::kInstrSize; |
-static const int kBranchReturnOffset = 2 * Instruction::kInstructionSize; |
+static const int kBranchReturnOffset = 2 * Instruction::kInstrSize; |
-static const int kDoubleAlignment = 2 * 8; |
-static const int kDoubleAlignmentMask = kDoubleAlignmentMask - 1; |
+static const int kDoubleAlignmentBits = 3; |
+static const int kDoubleAlignment = (1 << kDoubleAlignmentBits); |
+static const int kDoubleAlignmentMask = kDoubleAlignment - 1; |
-} } // namespace assembler::mips |
+} } // namespace v8::internal |
#endif // #ifndef V8_MIPS_CONSTANTS_H_ |