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