Home | History | Annotate | Download | only in mips
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef  V8_MIPS_CONSTANTS_H_
      6 #define  V8_MIPS_CONSTANTS_H_
      7 
      8 // UNIMPLEMENTED_ macro for MIPS.
      9 #ifdef DEBUG
     10 #define UNIMPLEMENTED_MIPS()                                                  \
     11   v8::internal::PrintF("%s, \tline %d: \tfunction %s not implemented. \n",    \
     12                        __FILE__, __LINE__, __func__)
     13 #else
     14 #define UNIMPLEMENTED_MIPS()
     15 #endif
     16 
     17 #define UNSUPPORTED_MIPS() v8::internal::PrintF("Unsupported instruction.\n")
     18 
     19 enum ArchVariants {
     20   kMips32r2,
     21   kMips32r1,
     22   kLoongson
     23 };
     24 
     25 #ifdef _MIPS_ARCH_MIPS32R2
     26   static const ArchVariants kArchVariant = kMips32r2;
     27 #elif _MIPS_ARCH_LOONGSON
     28 // The loongson flag refers to the LOONGSON architectures based on MIPS-III,
     29 // which predates (and is a subset of) the mips32r2 and r1 architectures.
     30   static const ArchVariants kArchVariant = kLoongson;
     31 #else
     32   static const ArchVariants kArchVariant = kMips32r1;
     33 #endif
     34 
     35 enum Endianness {
     36   kLittle,
     37   kBig
     38 };
     39 
     40 #if defined(V8_TARGET_LITTLE_ENDIAN)
     41   static const Endianness kArchEndian = kLittle;
     42 #elif defined(V8_TARGET_BIG_ENDIAN)
     43   static const Endianness kArchEndian = kBig;
     44 #else
     45 #error Unknown endianness
     46 #endif
     47 
     48 #if(defined(__mips_hard_float) && __mips_hard_float != 0)
     49 // Use floating-point coprocessor instructions. This flag is raised when
     50 // -mhard-float is passed to the compiler.
     51 const bool IsMipsSoftFloatABI = false;
     52 #elif(defined(__mips_soft_float) && __mips_soft_float != 0)
     53 // This flag is raised when -msoft-float is passed to the compiler.
     54 // Although FPU is a base requirement for v8, soft-float ABI is used
     55 // on soft-float systems with FPU kernel emulation.
     56 const bool IsMipsSoftFloatABI = true;
     57 #else
     58 const bool IsMipsSoftFloatABI = true;
     59 #endif
     60 
     61 #if defined(V8_TARGET_LITTLE_ENDIAN)
     62 const uint32_t kHoleNanUpper32Offset = 4;
     63 const uint32_t kHoleNanLower32Offset = 0;
     64 #elif defined(V8_TARGET_BIG_ENDIAN)
     65 const uint32_t kHoleNanUpper32Offset = 0;
     66 const uint32_t kHoleNanLower32Offset = 4;
     67 #else
     68 #error Unknown endianness
     69 #endif
     70 
     71 // Defines constants and accessor classes to assemble, disassemble and
     72 // simulate MIPS32 instructions.
     73 //
     74 // See: MIPS32 Architecture For Programmers
     75 //      Volume II: The MIPS32 Instruction Set
     76 // Try www.cs.cornell.edu/courses/cs3410/2008fa/MIPS_Vol2.pdf.
     77 
     78 namespace v8 {
     79 namespace internal {
     80 
     81 // -----------------------------------------------------------------------------
     82 // Registers and FPURegisters.
     83 
     84 // Number of general purpose registers.
     85 const int kNumRegisters = 32;
     86 const int kInvalidRegister = -1;
     87 
     88 // Number of registers with HI, LO, and pc.
     89 const int kNumSimuRegisters = 35;
     90 
     91 // In the simulator, the PC register is simulated as the 34th register.
     92 const int kPCRegister = 34;
     93 
     94 // Number coprocessor registers.
     95 const int kNumFPURegisters = 32;
     96 const int kInvalidFPURegister = -1;
     97 
     98 // FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
     99 const int kFCSRRegister = 31;
    100 const int kInvalidFPUControlRegister = -1;
    101 const uint32_t kFPUInvalidResult = static_cast<uint32_t>(1 << 31) - 1;
    102 
    103 // FCSR constants.
    104 const uint32_t kFCSRInexactFlagBit = 2;
    105 const uint32_t kFCSRUnderflowFlagBit = 3;
    106 const uint32_t kFCSROverflowFlagBit = 4;
    107 const uint32_t kFCSRDivideByZeroFlagBit = 5;
    108 const uint32_t kFCSRInvalidOpFlagBit = 6;
    109 
    110 const uint32_t kFCSRInexactFlagMask = 1 << kFCSRInexactFlagBit;
    111 const uint32_t kFCSRUnderflowFlagMask = 1 << kFCSRUnderflowFlagBit;
    112 const uint32_t kFCSROverflowFlagMask = 1 << kFCSROverflowFlagBit;
    113 const uint32_t kFCSRDivideByZeroFlagMask = 1 << kFCSRDivideByZeroFlagBit;
    114 const uint32_t kFCSRInvalidOpFlagMask = 1 << kFCSRInvalidOpFlagBit;
    115 
    116 const uint32_t kFCSRFlagMask =
    117     kFCSRInexactFlagMask |
    118     kFCSRUnderflowFlagMask |
    119     kFCSROverflowFlagMask |
    120     kFCSRDivideByZeroFlagMask |
    121     kFCSRInvalidOpFlagMask;
    122 
    123 const uint32_t kFCSRExceptionFlagMask = kFCSRFlagMask ^ kFCSRInexactFlagMask;
    124 
    125 // 'pref' instruction hints
    126 const int32_t kPrefHintLoad = 0;
    127 const int32_t kPrefHintStore = 1;
    128 const int32_t kPrefHintLoadStreamed = 4;
    129 const int32_t kPrefHintStoreStreamed = 5;
    130 const int32_t kPrefHintLoadRetained = 6;
    131 const int32_t kPrefHintStoreRetained = 7;
    132 const int32_t kPrefHintWritebackInvalidate = 25;
    133 const int32_t kPrefHintPrepareForStore = 30;
    134 
    135 // Helper functions for converting between register numbers and names.
    136 class Registers {
    137  public:
    138   // Return the name of the register.
    139   static const char* Name(int reg);
    140 
    141   // Lookup the register number for the name provided.
    142   static int Number(const char* name);
    143 
    144   struct RegisterAlias {
    145     int reg;
    146     const char* name;
    147   };
    148 
    149   static const int32_t kMaxValue = 0x7fffffff;
    150   static const int32_t kMinValue = 0x80000000;
    151 
    152  private:
    153   static const char* names_[kNumSimuRegisters];
    154   static const RegisterAlias aliases_[];
    155 };
    156 
    157 // Helper functions for converting between register numbers and names.
    158 class FPURegisters {
    159  public:
    160   // Return the name of the register.
    161   static const char* Name(int reg);
    162 
    163   // Lookup the register number for the name provided.
    164   static int Number(const char* name);
    165 
    166   struct RegisterAlias {
    167     int creg;
    168     const char* name;
    169   };
    170 
    171  private:
    172   static const char* names_[kNumFPURegisters];
    173   static const RegisterAlias aliases_[];
    174 };
    175 
    176 
    177 // -----------------------------------------------------------------------------
    178 // Instructions encoding constants.
    179 
    180 // On MIPS all instructions are 32 bits.
    181 typedef int32_t Instr;
    182 
    183 // Special Software Interrupt codes when used in the presence of the MIPS
    184 // simulator.
    185 enum SoftwareInterruptCodes {
    186   // Transition to C code.
    187   call_rt_redirected = 0xfffff
    188 };
    189 
    190 // On MIPS Simulator breakpoints can have different codes:
    191 // - Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints,
    192 //   the simulator will run through them and print the registers.
    193 // - Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop()
    194 //   instructions (see Assembler::stop()).
    195 // - Breaks larger than kMaxStopCode are simple breaks, dropping you into the
    196 //   debugger.
    197 const uint32_t kMaxWatchpointCode = 31;
    198 const uint32_t kMaxStopCode = 127;
    199 STATIC_ASSERT(kMaxWatchpointCode < kMaxStopCode);
    200 
    201 
    202 // ----- Fields offset and length.
    203 const int kOpcodeShift   = 26;
    204 const int kOpcodeBits    = 6;
    205 const int kRsShift       = 21;
    206 const int kRsBits        = 5;
    207 const int kRtShift       = 16;
    208 const int kRtBits        = 5;
    209 const int kRdShift       = 11;
    210 const int kRdBits        = 5;
    211 const int kSaShift       = 6;
    212 const int kSaBits        = 5;
    213 const int kFunctionShift = 0;
    214 const int kFunctionBits  = 6;
    215 const int kLuiShift      = 16;
    216 
    217 const int kImm16Shift = 0;
    218 const int kImm16Bits  = 16;
    219 const int kImm26Shift = 0;
    220 const int kImm26Bits  = 26;
    221 const int kImm28Shift = 0;
    222 const int kImm28Bits  = 28;
    223 
    224 // In branches and jumps immediate fields point to words, not bytes,
    225 // and are therefore shifted by 2.
    226 const int kImmFieldShift = 2;
    227 
    228 const int kFrBits        = 5;
    229 const int kFrShift       = 21;
    230 const int kFsShift       = 11;
    231 const int kFsBits        = 5;
    232 const int kFtShift       = 16;
    233 const int kFtBits        = 5;
    234 const int kFdShift       = 6;
    235 const int kFdBits        = 5;
    236 const int kFCccShift     = 8;
    237 const int kFCccBits      = 3;
    238 const int kFBccShift     = 18;
    239 const int kFBccBits      = 3;
    240 const int kFBtrueShift   = 16;
    241 const int kFBtrueBits    = 1;
    242 
    243 // ----- Miscellaneous useful masks.
    244 // Instruction bit masks.
    245 const int  kOpcodeMask   = ((1 << kOpcodeBits) - 1) << kOpcodeShift;
    246 const int  kImm16Mask    = ((1 << kImm16Bits) - 1) << kImm16Shift;
    247 const int  kImm26Mask    = ((1 << kImm26Bits) - 1) << kImm26Shift;
    248 const int  kImm28Mask    = ((1 << kImm28Bits) - 1) << kImm28Shift;
    249 const int  kRsFieldMask  = ((1 << kRsBits) - 1) << kRsShift;
    250 const int  kRtFieldMask  = ((1 << kRtBits) - 1) << kRtShift;
    251 const int  kRdFieldMask  = ((1 << kRdBits) - 1) << kRdShift;
    252 const int  kSaFieldMask  = ((1 << kSaBits) - 1) << kSaShift;
    253 const int  kFunctionFieldMask = ((1 << kFunctionBits) - 1) << kFunctionShift;
    254 // Misc masks.
    255 const int  kHiMask       =   0xffff << 16;
    256 const int  kLoMask       =   0xffff;
    257 const int  kSignMask     =   0x80000000;
    258 const int  kJumpAddrMask = (1 << (kImm26Bits + kImmFieldShift)) - 1;
    259 
    260 // ----- MIPS Opcodes and Function Fields.
    261 // We use this presentation to stay close to the table representation in
    262 // MIPS32 Architecture For Programmers, Volume II: The MIPS32 Instruction Set.
    263 enum Opcode {
    264   SPECIAL   =   0 << kOpcodeShift,
    265   REGIMM    =   1 << kOpcodeShift,
    266 
    267   J         =   ((0 << 3) + 2) << kOpcodeShift,
    268   JAL       =   ((0 << 3) + 3) << kOpcodeShift,
    269   BEQ       =   ((0 << 3) + 4) << kOpcodeShift,
    270   BNE       =   ((0 << 3) + 5) << kOpcodeShift,
    271   BLEZ      =   ((0 << 3) + 6) << kOpcodeShift,
    272   BGTZ      =   ((0 << 3) + 7) << kOpcodeShift,
    273 
    274   ADDI      =   ((1 << 3) + 0) << kOpcodeShift,
    275   ADDIU     =   ((1 << 3) + 1) << kOpcodeShift,
    276   SLTI      =   ((1 << 3) + 2) << kOpcodeShift,
    277   SLTIU     =   ((1 << 3) + 3) << kOpcodeShift,
    278   ANDI      =   ((1 << 3) + 4) << kOpcodeShift,
    279   ORI       =   ((1 << 3) + 5) << kOpcodeShift,
    280   XORI      =   ((1 << 3) + 6) << kOpcodeShift,
    281   LUI       =   ((1 << 3) + 7) << kOpcodeShift,
    282 
    283   COP1      =   ((2 << 3) + 1) << kOpcodeShift,  // Coprocessor 1 class.
    284   BEQL      =   ((2 << 3) + 4) << kOpcodeShift,
    285   BNEL      =   ((2 << 3) + 5) << kOpcodeShift,
    286   BLEZL     =   ((2 << 3) + 6) << kOpcodeShift,
    287   BGTZL     =   ((2 << 3) + 7) << kOpcodeShift,
    288 
    289   SPECIAL2  =   ((3 << 3) + 4) << kOpcodeShift,
    290   SPECIAL3  =   ((3 << 3) + 7) << kOpcodeShift,
    291 
    292   LB        =   ((4 << 3) + 0) << kOpcodeShift,
    293   LH        =   ((4 << 3) + 1) << kOpcodeShift,
    294   LWL       =   ((4 << 3) + 2) << kOpcodeShift,
    295   LW        =   ((4 << 3) + 3) << kOpcodeShift,
    296   LBU       =   ((4 << 3) + 4) << kOpcodeShift,
    297   LHU       =   ((4 << 3) + 5) << kOpcodeShift,
    298   LWR       =   ((4 << 3) + 6) << kOpcodeShift,
    299   SB        =   ((5 << 3) + 0) << kOpcodeShift,
    300   SH        =   ((5 << 3) + 1) << kOpcodeShift,
    301   SWL       =   ((5 << 3) + 2) << kOpcodeShift,
    302   SW        =   ((5 << 3) + 3) << kOpcodeShift,
    303   SWR       =   ((5 << 3) + 6) << kOpcodeShift,
    304 
    305   LWC1      =   ((6 << 3) + 1) << kOpcodeShift,
    306   LDC1      =   ((6 << 3) + 5) << kOpcodeShift,
    307 
    308   PREF      =   ((6 << 3) + 3) << kOpcodeShift,
    309 
    310   SWC1      =   ((7 << 3) + 1) << kOpcodeShift,
    311   SDC1      =   ((7 << 3) + 5) << kOpcodeShift,
    312 
    313   COP1X     =   ((1 << 4) + 3) << kOpcodeShift
    314 };
    315 
    316 enum SecondaryField {
    317   // SPECIAL Encoding of Function Field.
    318   SLL       =   ((0 << 3) + 0),
    319   MOVCI     =   ((0 << 3) + 1),
    320   SRL       =   ((0 << 3) + 2),
    321   SRA       =   ((0 << 3) + 3),
    322   SLLV      =   ((0 << 3) + 4),
    323   SRLV      =   ((0 << 3) + 6),
    324   SRAV      =   ((0 << 3) + 7),
    325 
    326   JR        =   ((1 << 3) + 0),
    327   JALR      =   ((1 << 3) + 1),
    328   MOVZ      =   ((1 << 3) + 2),
    329   MOVN      =   ((1 << 3) + 3),
    330   BREAK     =   ((1 << 3) + 5),
    331 
    332   MFHI      =   ((2 << 3) + 0),
    333   MFLO      =   ((2 << 3) + 2),
    334 
    335   MULT      =   ((3 << 3) + 0),
    336   MULTU     =   ((3 << 3) + 1),
    337   DIV       =   ((3 << 3) + 2),
    338   DIVU      =   ((3 << 3) + 3),
    339 
    340   ADD       =   ((4 << 3) + 0),
    341   ADDU      =   ((4 << 3) + 1),
    342   SUB       =   ((4 << 3) + 2),
    343   SUBU      =   ((4 << 3) + 3),
    344   AND       =   ((4 << 3) + 4),
    345   OR        =   ((4 << 3) + 5),
    346   XOR       =   ((4 << 3) + 6),
    347   NOR       =   ((4 << 3) + 7),
    348 
    349   SLT       =   ((5 << 3) + 2),
    350   SLTU      =   ((5 << 3) + 3),
    351 
    352   TGE       =   ((6 << 3) + 0),
    353   TGEU      =   ((6 << 3) + 1),
    354   TLT       =   ((6 << 3) + 2),
    355   TLTU      =   ((6 << 3) + 3),
    356   TEQ       =   ((6 << 3) + 4),
    357   TNE       =   ((6 << 3) + 6),
    358 
    359   // SPECIAL2 Encoding of Function Field.
    360   MUL       =   ((0 << 3) + 2),
    361   CLZ       =   ((4 << 3) + 0),
    362   CLO       =   ((4 << 3) + 1),
    363 
    364   // SPECIAL3 Encoding of Function Field.
    365   EXT       =   ((0 << 3) + 0),
    366   INS       =   ((0 << 3) + 4),
    367 
    368   // REGIMM  encoding of rt Field.
    369   BLTZ      =   ((0 << 3) + 0) << 16,
    370   BGEZ      =   ((0 << 3) + 1) << 16,
    371   BLTZAL    =   ((2 << 3) + 0) << 16,
    372   BGEZAL    =   ((2 << 3) + 1) << 16,
    373 
    374   // COP1 Encoding of rs Field.
    375   MFC1      =   ((0 << 3) + 0) << 21,
    376   CFC1      =   ((0 << 3) + 2) << 21,
    377   MFHC1     =   ((0 << 3) + 3) << 21,
    378   MTC1      =   ((0 << 3) + 4) << 21,
    379   CTC1      =   ((0 << 3) + 6) << 21,
    380   MTHC1     =   ((0 << 3) + 7) << 21,
    381   BC1       =   ((1 << 3) + 0) << 21,
    382   S         =   ((2 << 3) + 0) << 21,
    383   D         =   ((2 << 3) + 1) << 21,
    384   W         =   ((2 << 3) + 4) << 21,
    385   L         =   ((2 << 3) + 5) << 21,
    386   PS        =   ((2 << 3) + 6) << 21,
    387   // COP1 Encoding of Function Field When rs=S.
    388   ROUND_L_S =   ((1 << 3) + 0),
    389   TRUNC_L_S =   ((1 << 3) + 1),
    390   CEIL_L_S  =   ((1 << 3) + 2),
    391   FLOOR_L_S =   ((1 << 3) + 3),
    392   ROUND_W_S =   ((1 << 3) + 4),
    393   TRUNC_W_S =   ((1 << 3) + 5),
    394   CEIL_W_S  =   ((1 << 3) + 6),
    395   FLOOR_W_S =   ((1 << 3) + 7),
    396   CVT_D_S   =   ((4 << 3) + 1),
    397   CVT_W_S   =   ((4 << 3) + 4),
    398   CVT_L_S   =   ((4 << 3) + 5),
    399   CVT_PS_S  =   ((4 << 3) + 6),
    400   // COP1 Encoding of Function Field When rs=D.
    401   ADD_D     =   ((0 << 3) + 0),
    402   SUB_D     =   ((0 << 3) + 1),
    403   MUL_D     =   ((0 << 3) + 2),
    404   DIV_D     =   ((0 << 3) + 3),
    405   SQRT_D    =   ((0 << 3) + 4),
    406   ABS_D     =   ((0 << 3) + 5),
    407   MOV_D     =   ((0 << 3) + 6),
    408   NEG_D     =   ((0 << 3) + 7),
    409   ROUND_L_D =   ((1 << 3) + 0),
    410   TRUNC_L_D =   ((1 << 3) + 1),
    411   CEIL_L_D  =   ((1 << 3) + 2),
    412   FLOOR_L_D =   ((1 << 3) + 3),
    413   ROUND_W_D =   ((1 << 3) + 4),
    414   TRUNC_W_D =   ((1 << 3) + 5),
    415   CEIL_W_D  =   ((1 << 3) + 6),
    416   FLOOR_W_D =   ((1 << 3) + 7),
    417   CVT_S_D   =   ((4 << 3) + 0),
    418   CVT_W_D   =   ((4 << 3) + 4),
    419   CVT_L_D   =   ((4 << 3) + 5),
    420   C_F_D     =   ((6 << 3) + 0),
    421   C_UN_D    =   ((6 << 3) + 1),
    422   C_EQ_D    =   ((6 << 3) + 2),
    423   C_UEQ_D   =   ((6 << 3) + 3),
    424   C_OLT_D   =   ((6 << 3) + 4),
    425   C_ULT_D   =   ((6 << 3) + 5),
    426   C_OLE_D   =   ((6 << 3) + 6),
    427   C_ULE_D   =   ((6 << 3) + 7),
    428   // COP1 Encoding of Function Field When rs=W or L.
    429   CVT_S_W   =   ((4 << 3) + 0),
    430   CVT_D_W   =   ((4 << 3) + 1),
    431   CVT_S_L   =   ((4 << 3) + 0),
    432   CVT_D_L   =   ((4 << 3) + 1),
    433   // COP1 Encoding of Function Field When rs=PS.
    434   // COP1X Encoding of Function Field.
    435   MADD_D    =   ((4 << 3) + 1),
    436 
    437   NULLSF    =   0
    438 };
    439 
    440 
    441 // ----- Emulated conditions.
    442 // On MIPS we use this enum to abstract from conditionnal branch instructions.
    443 // The 'U' prefix is used to specify unsigned comparisons.
    444 // Oppposite conditions must be paired as odd/even numbers
    445 // because 'NegateCondition' function flips LSB to negate condition.
    446 enum Condition {
    447   // Any value < 0 is considered no_condition.
    448   kNoCondition  = -1,
    449 
    450   overflow      =  0,
    451   no_overflow   =  1,
    452   Uless         =  2,
    453   Ugreater_equal=  3,
    454   equal         =  4,
    455   not_equal     =  5,
    456   Uless_equal   =  6,
    457   Ugreater      =  7,
    458   negative      =  8,
    459   positive      =  9,
    460   parity_even   = 10,
    461   parity_odd    = 11,
    462   less          = 12,
    463   greater_equal = 13,
    464   less_equal    = 14,
    465   greater       = 15,
    466   ueq           = 16,  // Unordered or Equal.
    467   nue           = 17,  // Not (Unordered or Equal).
    468 
    469   cc_always     = 18,
    470 
    471   // Aliases.
    472   carry         = Uless,
    473   not_carry     = Ugreater_equal,
    474   zero          = equal,
    475   eq            = equal,
    476   not_zero      = not_equal,
    477   ne            = not_equal,
    478   nz            = not_equal,
    479   sign          = negative,
    480   not_sign      = positive,
    481   mi            = negative,
    482   pl            = positive,
    483   hi            = Ugreater,
    484   ls            = Uless_equal,
    485   ge            = greater_equal,
    486   lt            = less,
    487   gt            = greater,
    488   le            = less_equal,
    489   hs            = Ugreater_equal,
    490   lo            = Uless,
    491   al            = cc_always,
    492 
    493   cc_default    = kNoCondition
    494 };
    495 
    496 
    497 // Returns the equivalent of !cc.
    498 // Negation of the default kNoCondition (-1) results in a non-default
    499 // no_condition value (-2). As long as tests for no_condition check
    500 // for condition < 0, this will work as expected.
    501 inline Condition NegateCondition(Condition cc) {
    502   ASSERT(cc != cc_always);
    503   return static_cast<Condition>(cc ^ 1);
    504 }
    505 
    506 
    507 // Commute a condition such that {a cond b == b cond' a}.
    508 inline Condition CommuteCondition(Condition cc) {
    509   switch (cc) {
    510     case Uless:
    511       return Ugreater;
    512     case Ugreater:
    513       return Uless;
    514     case Ugreater_equal:
    515       return Uless_equal;
    516     case Uless_equal:
    517       return Ugreater_equal;
    518     case less:
    519       return greater;
    520     case greater:
    521       return less;
    522     case greater_equal:
    523       return less_equal;
    524     case less_equal:
    525       return greater_equal;
    526     default:
    527       return cc;
    528   }
    529 }
    530 
    531 
    532 // ----- Coprocessor conditions.
    533 enum FPUCondition {
    534   kNoFPUCondition = -1,
    535 
    536   F     = 0,  // False.
    537   UN    = 1,  // Unordered.
    538   EQ    = 2,  // Equal.
    539   UEQ   = 3,  // Unordered or Equal.
    540   OLT   = 4,  // Ordered or Less Than.
    541   ULT   = 5,  // Unordered or Less Than.
    542   OLE   = 6,  // Ordered or Less Than or Equal.
    543   ULE   = 7   // Unordered or Less Than or Equal.
    544 };
    545 
    546 
    547 // FPU rounding modes.
    548 enum FPURoundingMode {
    549   RN = 0 << 0,  // Round to Nearest.
    550   RZ = 1 << 0,  // Round towards zero.
    551   RP = 2 << 0,  // Round towards Plus Infinity.
    552   RM = 3 << 0,  // Round towards Minus Infinity.
    553 
    554   // Aliases.
    555   kRoundToNearest = RN,
    556   kRoundToZero = RZ,
    557   kRoundToPlusInf = RP,
    558   kRoundToMinusInf = RM
    559 };
    560 
    561 const uint32_t kFPURoundingModeMask = 3 << 0;
    562 
    563 enum CheckForInexactConversion {
    564   kCheckForInexactConversion,
    565   kDontCheckForInexactConversion
    566 };
    567 
    568 
    569 // -----------------------------------------------------------------------------
    570 // Hints.
    571 
    572 // Branch hints are not used on the MIPS.  They are defined so that they can
    573 // appear in shared function signatures, but will be ignored in MIPS
    574 // implementations.
    575 enum Hint {
    576   no_hint = 0
    577 };
    578 
    579 
    580 inline Hint NegateHint(Hint hint) {
    581   return no_hint;
    582 }
    583 
    584 
    585 // -----------------------------------------------------------------------------
    586 // Specific instructions, constants, and masks.
    587 // These constants are declared in assembler-mips.cc, as they use named
    588 // registers and other constants.
    589 
    590 // addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
    591 // operations as post-increment of sp.
    592 extern const Instr kPopInstruction;
    593 // addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
    594 extern const Instr kPushInstruction;
    595 // sw(r, MemOperand(sp, 0))
    596 extern const Instr kPushRegPattern;
    597 // lw(r, MemOperand(sp, 0))
    598 extern const Instr kPopRegPattern;
    599 extern const Instr kLwRegFpOffsetPattern;
    600 extern const Instr kSwRegFpOffsetPattern;
    601 extern const Instr kLwRegFpNegOffsetPattern;
    602 extern const Instr kSwRegFpNegOffsetPattern;
    603 // A mask for the Rt register for push, pop, lw, sw instructions.
    604 extern const Instr kRtMask;
    605 extern const Instr kLwSwInstrTypeMask;
    606 extern const Instr kLwSwInstrArgumentMask;
    607 extern const Instr kLwSwOffsetMask;
    608 
    609 // Break 0xfffff, reserved for redirected real time call.
    610 const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6;
    611 // A nop instruction. (Encoding of sll 0 0 0).
    612 const Instr nopInstr = 0;
    613 
    614 class Instruction {
    615  public:
    616   enum {
    617     kInstrSize = 4,
    618     kInstrSizeLog2 = 2,
    619     // On MIPS PC cannot actually be directly accessed. We behave as if PC was
    620     // always the value of the current instruction being executed.
    621     kPCReadOffset = 0
    622   };
    623 
    624   // Get the raw instruction bits.
    625   inline Instr InstructionBits() const {
    626     return *reinterpret_cast<const Instr*>(this);
    627   }
    628 
    629   // Set the raw instruction bits to value.
    630   inline void SetInstructionBits(Instr value) {
    631     *reinterpret_cast<Instr*>(this) = value;
    632   }
    633 
    634   // Read one particular bit out of the instruction bits.
    635   inline int Bit(int nr) const {
    636     return (InstructionBits() >> nr) & 1;
    637   }
    638 
    639   // Read a bit field out of the instruction bits.
    640   inline int Bits(int hi, int lo) const {
    641     return (InstructionBits() >> lo) & ((2 << (hi - lo)) - 1);
    642   }
    643 
    644   // Instruction type.
    645   enum Type {
    646     kRegisterType,
    647     kImmediateType,
    648     kJumpType,
    649     kUnsupported = -1
    650   };
    651 
    652   // Get the encoding type of the instruction.
    653   Type InstructionType() const;
    654 
    655 
    656   // Accessors for the different named fields used in the MIPS encoding.
    657   inline Opcode OpcodeValue() const {
    658     return static_cast<Opcode>(
    659         Bits(kOpcodeShift + kOpcodeBits - 1, kOpcodeShift));
    660   }
    661 
    662   inline int RsValue() const {
    663     ASSERT(InstructionType() == kRegisterType ||
    664            InstructionType() == kImmediateType);
    665     return Bits(kRsShift + kRsBits - 1, kRsShift);
    666   }
    667 
    668   inline int RtValue() const {
    669     ASSERT(InstructionType() == kRegisterType ||
    670            InstructionType() == kImmediateType);
    671     return Bits(kRtShift + kRtBits - 1, kRtShift);
    672   }
    673 
    674   inline int RdValue() const {
    675     ASSERT(InstructionType() == kRegisterType);
    676     return Bits(kRdShift + kRdBits - 1, kRdShift);
    677   }
    678 
    679   inline int SaValue() const {
    680     ASSERT(InstructionType() == kRegisterType);
    681     return Bits(kSaShift + kSaBits - 1, kSaShift);
    682   }
    683 
    684   inline int FunctionValue() const {
    685     ASSERT(InstructionType() == kRegisterType ||
    686            InstructionType() == kImmediateType);
    687     return Bits(kFunctionShift + kFunctionBits - 1, kFunctionShift);
    688   }
    689 
    690   inline int FdValue() const {
    691     return Bits(kFdShift + kFdBits - 1, kFdShift);
    692   }
    693 
    694   inline int FsValue() const {
    695     return Bits(kFsShift + kFsBits - 1, kFsShift);
    696   }
    697 
    698   inline int FtValue() const {
    699     return Bits(kFtShift + kFtBits - 1, kFtShift);
    700   }
    701 
    702   inline int FrValue() const {
    703     return Bits(kFrShift + kFrBits -1, kFrShift);
    704   }
    705 
    706   // Float Compare condition code instruction bits.
    707   inline int FCccValue() const {
    708     return Bits(kFCccShift + kFCccBits - 1, kFCccShift);
    709   }
    710 
    711   // Float Branch condition code instruction bits.
    712   inline int FBccValue() const {
    713     return Bits(kFBccShift + kFBccBits - 1, kFBccShift);
    714   }
    715 
    716   // Float Branch true/false instruction bit.
    717   inline int FBtrueValue() const {
    718     return Bits(kFBtrueShift + kFBtrueBits - 1, kFBtrueShift);
    719   }
    720 
    721   // Return the fields at their original place in the instruction encoding.
    722   inline Opcode OpcodeFieldRaw() const {
    723     return static_cast<Opcode>(InstructionBits() & kOpcodeMask);
    724   }
    725 
    726   inline int RsFieldRaw() const {
    727     ASSERT(InstructionType() == kRegisterType ||
    728            InstructionType() == kImmediateType);
    729     return InstructionBits() & kRsFieldMask;
    730   }
    731 
    732   // Same as above function, but safe to call within InstructionType().
    733   inline int RsFieldRawNoAssert() const {
    734     return InstructionBits() & kRsFieldMask;
    735   }
    736 
    737   inline int RtFieldRaw() const {
    738     ASSERT(InstructionType() == kRegisterType ||
    739            InstructionType() == kImmediateType);
    740     return InstructionBits() & kRtFieldMask;
    741   }
    742 
    743   inline int RdFieldRaw() const {
    744     ASSERT(InstructionType() == kRegisterType);
    745     return InstructionBits() & kRdFieldMask;
    746   }
    747 
    748   inline int SaFieldRaw() const {
    749     ASSERT(InstructionType() == kRegisterType);
    750     return InstructionBits() & kSaFieldMask;
    751   }
    752 
    753   inline int FunctionFieldRaw() const {
    754     return InstructionBits() & kFunctionFieldMask;
    755   }
    756 
    757   // Get the secondary field according to the opcode.
    758   inline int SecondaryValue() const {
    759     Opcode op = OpcodeFieldRaw();
    760     switch (op) {
    761       case SPECIAL:
    762       case SPECIAL2:
    763         return FunctionValue();
    764       case COP1:
    765         return RsValue();
    766       case REGIMM:
    767         return RtValue();
    768       default:
    769         return NULLSF;
    770     }
    771   }
    772 
    773   inline int32_t Imm16Value() const {
    774     ASSERT(InstructionType() == kImmediateType);
    775     return Bits(kImm16Shift + kImm16Bits - 1, kImm16Shift);
    776   }
    777 
    778   inline int32_t Imm26Value() const {
    779     ASSERT(InstructionType() == kJumpType);
    780     return Bits(kImm26Shift + kImm26Bits - 1, kImm26Shift);
    781   }
    782 
    783   // Say if the instruction should not be used in a branch delay slot.
    784   bool IsForbiddenInBranchDelay() const;
    785   // Say if the instruction 'links'. e.g. jal, bal.
    786   bool IsLinkingInstruction() const;
    787   // Say if the instruction is a break or a trap.
    788   bool IsTrap() const;
    789 
    790   // Instructions are read of out a code stream. The only way to get a
    791   // reference to an instruction is to convert a pointer. There is no way
    792   // to allocate or create instances of class Instruction.
    793   // Use the At(pc) function to create references to Instruction.
    794   static Instruction* At(byte* pc) {
    795     return reinterpret_cast<Instruction*>(pc);
    796   }
    797 
    798  private:
    799   // We need to prevent the creation of instances of class Instruction.
    800   DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
    801 };
    802 
    803 
    804 // -----------------------------------------------------------------------------
    805 // MIPS assembly various constants.
    806 
    807 // C/C++ argument slots size.
    808 const int kCArgSlotCount = 4;
    809 const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize;
    810 // JS argument slots size.
    811 const int kJSArgsSlotsSize = 0 * Instruction::kInstrSize;
    812 // Assembly builtins argument slots size.
    813 const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
    814 
    815 const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
    816 
    817 } }   // namespace v8::internal
    818 
    819 #endif    // #ifndef V8_MIPS_CONSTANTS_H_
    820