js/src/jit/mips/Assembler-mips.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef jit_mips_Assembler_mips_h
     8 #define jit_mips_Assembler_mips_h
    10 #include "mozilla/ArrayUtils.h"
    11 #include "mozilla/Attributes.h"
    12 #include "mozilla/MathAlgorithms.h"
    14 #include "jit/CompactBuffer.h"
    15 #include "jit/IonCode.h"
    16 #include "jit/IonSpewer.h"
    17 #include "jit/mips/Architecture-mips.h"
    18 #include "jit/shared/Assembler-shared.h"
    19 #include "jit/shared/IonAssemblerBuffer.h"
    21 namespace js {
    22 namespace jit {
    24 static MOZ_CONSTEXPR_VAR Register zero = { Registers::zero };
    25 static MOZ_CONSTEXPR_VAR Register at = { Registers::at };
    26 static MOZ_CONSTEXPR_VAR Register v0 = { Registers::v0 };
    27 static MOZ_CONSTEXPR_VAR Register v1 = { Registers::v1 };
    28 static MOZ_CONSTEXPR_VAR Register a0 = { Registers::a0 };
    29 static MOZ_CONSTEXPR_VAR Register a1 = { Registers::a1 };
    30 static MOZ_CONSTEXPR_VAR Register a2 = { Registers::a2 };
    31 static MOZ_CONSTEXPR_VAR Register a3 = { Registers::a3 };
    32 static MOZ_CONSTEXPR_VAR Register t0 = { Registers::t0 };
    33 static MOZ_CONSTEXPR_VAR Register t1 = { Registers::t1 };
    34 static MOZ_CONSTEXPR_VAR Register t2 = { Registers::t2 };
    35 static MOZ_CONSTEXPR_VAR Register t3 = { Registers::t3 };
    36 static MOZ_CONSTEXPR_VAR Register t4 = { Registers::t4 };
    37 static MOZ_CONSTEXPR_VAR Register t5 = { Registers::t5 };
    38 static MOZ_CONSTEXPR_VAR Register t6 = { Registers::t6 };
    39 static MOZ_CONSTEXPR_VAR Register t7 = { Registers::t7 };
    40 static MOZ_CONSTEXPR_VAR Register s0 = { Registers::s0 };
    41 static MOZ_CONSTEXPR_VAR Register s1 = { Registers::s1 };
    42 static MOZ_CONSTEXPR_VAR Register s2 = { Registers::s2 };
    43 static MOZ_CONSTEXPR_VAR Register s3 = { Registers::s3 };
    44 static MOZ_CONSTEXPR_VAR Register s4 = { Registers::s4 };
    45 static MOZ_CONSTEXPR_VAR Register s5 = { Registers::s5 };
    46 static MOZ_CONSTEXPR_VAR Register s6 = { Registers::s6 };
    47 static MOZ_CONSTEXPR_VAR Register s7 = { Registers::s7 };
    48 static MOZ_CONSTEXPR_VAR Register t8 = { Registers::t8 };
    49 static MOZ_CONSTEXPR_VAR Register t9 = { Registers::t9 };
    50 static MOZ_CONSTEXPR_VAR Register k0 = { Registers::k0 };
    51 static MOZ_CONSTEXPR_VAR Register k1 = { Registers::k1 };
    52 static MOZ_CONSTEXPR_VAR Register gp = { Registers::gp };
    53 static MOZ_CONSTEXPR_VAR Register sp = { Registers::sp };
    54 static MOZ_CONSTEXPR_VAR Register fp = { Registers::fp };
    55 static MOZ_CONSTEXPR_VAR Register ra = { Registers::ra };
    57 static MOZ_CONSTEXPR_VAR Register ScratchRegister = at;
    58 static MOZ_CONSTEXPR_VAR Register SecondScratchReg = t8;
    60 // Use arg reg from EnterJIT function as OsrFrameReg.
    61 static MOZ_CONSTEXPR_VAR Register OsrFrameReg = a3;
    62 static MOZ_CONSTEXPR_VAR Register ArgumentsRectifierReg = s3;
    63 static MOZ_CONSTEXPR_VAR Register CallTempReg0 = t0;
    64 static MOZ_CONSTEXPR_VAR Register CallTempReg1 = t1;
    65 static MOZ_CONSTEXPR_VAR Register CallTempReg2 = t2;
    66 static MOZ_CONSTEXPR_VAR Register CallTempReg3 = t3;
    67 static MOZ_CONSTEXPR_VAR Register CallTempReg4 = t4;
    68 static MOZ_CONSTEXPR_VAR Register CallTempReg5 = t5;
    70 static MOZ_CONSTEXPR_VAR Register IntArgReg0 = a0;
    71 static MOZ_CONSTEXPR_VAR Register IntArgReg1 = a1;
    72 static MOZ_CONSTEXPR_VAR Register IntArgReg2 = a2;
    73 static MOZ_CONSTEXPR_VAR Register IntArgReg3 = a3;
    74 static MOZ_CONSTEXPR_VAR Register GlobalReg = s6; // used by Odin
    75 static MOZ_CONSTEXPR_VAR Register HeapReg = s7; // used by Odin
    76 static MOZ_CONSTEXPR_VAR Register CallTempNonArgRegs[] = { t0, t1, t2, t3, t4 };
    77 static const uint32_t NumCallTempNonArgRegs = mozilla::ArrayLength(CallTempNonArgRegs);
    79 class ABIArgGenerator
    80 {
    81     unsigned usedArgSlots_;
    82     bool firstArgFloat;
    83     ABIArg current_;
    85   public:
    86     ABIArgGenerator();
    87     ABIArg next(MIRType argType);
    88     ABIArg &current() { return current_; }
    90     uint32_t stackBytesConsumedSoFar() const {
    91         if (usedArgSlots_ <= 4)
    92             return 4 * sizeof(intptr_t);
    94         return usedArgSlots_ * sizeof(intptr_t);
    95     }
    97     static const Register NonArgReturnVolatileReg0;
    98     static const Register NonArgReturnVolatileReg1;
    99 };
   101 static MOZ_CONSTEXPR_VAR Register PreBarrierReg = a1;
   103 static MOZ_CONSTEXPR_VAR Register InvalidReg = { Registers::invalid_reg };
   104 static MOZ_CONSTEXPR_VAR FloatRegister InvalidFloatReg = { FloatRegisters::invalid_freg };
   106 static MOZ_CONSTEXPR_VAR Register JSReturnReg_Type = v1;
   107 static MOZ_CONSTEXPR_VAR Register JSReturnReg_Data = v0;
   108 static MOZ_CONSTEXPR_VAR Register StackPointer = sp;
   109 static MOZ_CONSTEXPR_VAR Register FramePointer = fp;
   110 static MOZ_CONSTEXPR_VAR Register ReturnReg = v0;
   111 static MOZ_CONSTEXPR_VAR FloatRegister ReturnFloatReg = { FloatRegisters::f0 };
   112 static MOZ_CONSTEXPR_VAR FloatRegister ScratchFloatReg = { FloatRegisters::f18 };
   113 static MOZ_CONSTEXPR_VAR FloatRegister SecondScratchFloatReg = { FloatRegisters::f16 };
   115 static MOZ_CONSTEXPR_VAR FloatRegister NANReg = { FloatRegisters::f30 };
   117 static MOZ_CONSTEXPR_VAR FloatRegister f0  = {FloatRegisters::f0};
   118 static MOZ_CONSTEXPR_VAR FloatRegister f2  = {FloatRegisters::f2};
   119 static MOZ_CONSTEXPR_VAR FloatRegister f4  = {FloatRegisters::f4};
   120 static MOZ_CONSTEXPR_VAR FloatRegister f6  = {FloatRegisters::f6};
   121 static MOZ_CONSTEXPR_VAR FloatRegister f8  = {FloatRegisters::f8};
   122 static MOZ_CONSTEXPR_VAR FloatRegister f10 = {FloatRegisters::f10};
   123 static MOZ_CONSTEXPR_VAR FloatRegister f12 = {FloatRegisters::f12};
   124 static MOZ_CONSTEXPR_VAR FloatRegister f14 = {FloatRegisters::f14};
   125 static MOZ_CONSTEXPR_VAR FloatRegister f16 = {FloatRegisters::f16};
   126 static MOZ_CONSTEXPR_VAR FloatRegister f18 = {FloatRegisters::f18};
   127 static MOZ_CONSTEXPR_VAR FloatRegister f20 = {FloatRegisters::f20};
   128 static MOZ_CONSTEXPR_VAR FloatRegister f22 = {FloatRegisters::f22};
   129 static MOZ_CONSTEXPR_VAR FloatRegister f24 = {FloatRegisters::f24};
   130 static MOZ_CONSTEXPR_VAR FloatRegister f26 = {FloatRegisters::f26};
   131 static MOZ_CONSTEXPR_VAR FloatRegister f28 = {FloatRegisters::f28};
   132 static MOZ_CONSTEXPR_VAR FloatRegister f30 = {FloatRegisters::f30};
   134 // MIPS CPUs can only load multibyte data that is "naturally"
   135 // four-byte-aligned, sp register should be eight-byte-aligned.
   136 static const uint32_t StackAlignment = 8;
   137 static const uint32_t CodeAlignment = 4;
   138 static const bool StackKeptAligned = true;
   139 // NativeFrameSize is the size of return adress on stack in AsmJS functions.
   140 static const uint32_t NativeFrameSize = sizeof(void*);
   141 static const uint32_t AlignmentAtPrologue = 0;
   142 static const uint32_t AlignmentMidPrologue = NativeFrameSize;
   144 static const Scale ScalePointer = TimesFour;
   146 // MIPS instruction types
   147 //                +---------------------------------------------------------------+
   148 //                |    6      |    5    |    5    |    5    |    5    |    6      |
   149 //                +---------------------------------------------------------------+
   150 // Register type  |  Opcode   |    Rs   |    Rt   |    Rd   |    Sa   | Function  |
   151 //                +---------------------------------------------------------------+
   152 //                |    6      |    5    |    5    |               16              |
   153 //                +---------------------------------------------------------------+
   154 // Immediate type |  Opcode   |    Rs   |    Rt   |    2's complement constant    |
   155 //                +---------------------------------------------------------------+
   156 //                |    6      |                        26                         |
   157 //                +---------------------------------------------------------------+
   158 // Jump type      |  Opcode   |                    jump_target                    |
   159 //                +---------------------------------------------------------------+
   160 //                31 bit                                                      bit 0
   162 // MIPS instruction encoding constants.
   163 static const uint32_t OpcodeShift = 26;
   164 static const uint32_t OpcodeBits = 6;
   165 static const uint32_t RSShift = 21;
   166 static const uint32_t RSBits = 5;
   167 static const uint32_t RTShift = 16;
   168 static const uint32_t RTBits = 5;
   169 static const uint32_t RDShift = 11;
   170 static const uint32_t RDBits = 5;
   171 static const uint32_t SAShift = 6;
   172 static const uint32_t SABits = 5;
   173 static const uint32_t FunctionShift = 0;
   174 static const uint32_t FunctionBits = 5;
   175 static const uint32_t Imm16Shift = 0;
   176 static const uint32_t Imm16Bits = 16;
   177 static const uint32_t Imm26Shift = 0;
   178 static const uint32_t Imm26Bits = 26;
   179 static const uint32_t Imm28Shift = 0;
   180 static const uint32_t Imm28Bits = 28;
   181 static const uint32_t ImmFieldShift = 2;
   182 static const uint32_t FccMask = 0x7;
   183 static const uint32_t FccShift = 2;
   186 // MIPS instruction  field bit masks.
   187 static const uint32_t OpcodeMask = ((1 << OpcodeBits) - 1) << OpcodeShift;
   188 static const uint32_t Imm16Mask = ((1 << Imm16Bits) - 1) << Imm16Shift;
   189 static const uint32_t Imm26Mask = ((1 << Imm26Bits) - 1) << Imm26Shift;
   190 static const uint32_t Imm28Mask = ((1 << Imm28Bits) - 1) << Imm28Shift;
   191 static const uint32_t RSMask = ((1 << RSBits) - 1) << RSShift;
   192 static const uint32_t RTMask = ((1 << RTBits) - 1) << RTShift;
   193 static const uint32_t RDMask = ((1 << RDBits) - 1) << RDShift;
   194 static const uint32_t SAMask = ((1 << SABits) - 1) << SAShift;
   195 static const uint32_t FunctionMask = ((1 << FunctionBits) - 1) << FunctionShift;
   196 static const uint32_t RegMask = Registers::Total - 1;
   197 static const uint32_t StackAlignmentMask = StackAlignment - 1;
   199 static const int32_t MAX_BREAK_CODE = 1024 - 1;
   201 class Instruction;
   202 class InstReg;
   203 class InstImm;
   204 class InstJump;
   205 class BranchInstBlock;
   207 uint32_t RS(Register r);
   208 uint32_t RT(Register r);
   209 uint32_t RT(uint32_t regCode);
   210 uint32_t RT(FloatRegister r);
   211 uint32_t RD(Register r);
   212 uint32_t RD(FloatRegister r);
   213 uint32_t RD(uint32_t regCode);
   214 uint32_t SA(uint32_t value);
   215 uint32_t SA(FloatRegister r);
   217 Register toRS (Instruction &i);
   218 Register toRT (Instruction &i);
   219 Register toRD (Instruction &i);
   220 Register toR (Instruction &i);
   222 // MIPS enums for instruction fields
   223 enum Opcode {
   224     op_special  = 0 << OpcodeShift,
   225     op_regimm   = 1 << OpcodeShift,
   227     op_j        = 2 << OpcodeShift,
   228     op_jal      = 3 << OpcodeShift,
   229     op_beq      = 4 << OpcodeShift,
   230     op_bne      = 5 << OpcodeShift,
   231     op_blez     = 6 << OpcodeShift,
   232     op_bgtz     = 7 << OpcodeShift,
   234     op_addi     = 8 << OpcodeShift,
   235     op_addiu    = 9 << OpcodeShift,
   236     op_slti     = 10 << OpcodeShift,
   237     op_sltiu    = 11 << OpcodeShift,
   238     op_andi     = 12 << OpcodeShift,
   239     op_ori      = 13 << OpcodeShift,
   240     op_xori     = 14 << OpcodeShift,
   241     op_lui      = 15 << OpcodeShift,
   243     op_cop1     = 17 << OpcodeShift,
   244     op_cop1x    = 19 << OpcodeShift,
   246     op_beql     = 20 << OpcodeShift,
   247     op_bnel     = 21 << OpcodeShift,
   248     op_blezl    = 22 << OpcodeShift,
   249     op_bgtzl    = 23 << OpcodeShift,
   251     op_special2 = 28 << OpcodeShift,
   252     op_special3 = 31 << OpcodeShift,
   254     op_lb       = 32 << OpcodeShift,
   255     op_lh       = 33 << OpcodeShift,
   256     op_lwl      = 34 << OpcodeShift,
   257     op_lw       = 35 << OpcodeShift,
   258     op_lbu      = 36 << OpcodeShift,
   259     op_lhu      = 37 << OpcodeShift,
   260     op_lwr      = 38 << OpcodeShift,
   261     op_sb       = 40 << OpcodeShift,
   262     op_sh       = 41 << OpcodeShift,
   263     op_swl      = 42 << OpcodeShift,
   264     op_sw       = 43 << OpcodeShift,
   265     op_swr      = 46 << OpcodeShift,
   267     op_lwc1     = 49 << OpcodeShift,
   268     op_ldc1     = 53 << OpcodeShift,
   270     op_swc1     = 57 << OpcodeShift,
   271     op_sdc1     = 61 << OpcodeShift
   272 };
   274 enum RSField {
   275     rs_zero  = 0 << RSShift,
   276     // cop1 encoding of RS field.
   277     rs_mfc1  = 0 << RSShift,
   278     rs_one   = 1 << RSShift,
   279     rs_cfc1  = 2 << RSShift,
   280     rs_mfhc1 = 3 << RSShift,
   281     rs_mtc1  = 4 << RSShift,
   282     rs_ctc1  = 6 << RSShift,
   283     rs_mthc1 = 7 << RSShift,
   284     rs_bc1   = 8 << RSShift,
   285     rs_s     = 16 << RSShift,
   286     rs_d     = 17 << RSShift,
   287     rs_w     = 20 << RSShift,
   288     rs_ps    = 22 << RSShift
   289 };
   291 enum RTField {
   292     rt_zero   = 0 << RTShift,
   293     // regimm  encoding of RT field.
   294     rt_bltz   = 0 << RTShift,
   295     rt_bgez   = 1 << RTShift,
   296     rt_bltzal = 16 << RTShift,
   297     rt_bgezal = 17 << RTShift
   298 };
   300 enum FunctionField {
   301     // special encoding of function field.
   302     ff_sll         = 0,
   303     ff_movci       = 1,
   304     ff_srl         = 2,
   305     ff_sra         = 3,
   306     ff_sllv        = 4,
   307     ff_srlv        = 6,
   308     ff_srav        = 7,
   310     ff_jr          = 8,
   311     ff_jalr        = 9,
   312     ff_movz        = 10,
   313     ff_movn        = 11,
   314     ff_break       = 13,
   316     ff_mfhi        = 16,
   317     ff_mflo        = 18,
   319     ff_mult        = 24,
   320     ff_multu       = 25,
   321     ff_div         = 26,
   322     ff_divu        = 27,
   324     ff_add         = 32,
   325     ff_addu        = 33,
   326     ff_sub         = 34,
   327     ff_subu        = 35,
   328     ff_and         = 36,
   329     ff_or          = 37,
   330     ff_xor         = 38,
   331     ff_nor         = 39,
   333     ff_slt         = 42,
   334     ff_sltu        = 43,
   336     // special2 encoding of function field.
   337     ff_mul         = 2,
   338     ff_clz         = 32,
   339     ff_clo         = 33,
   341     // special3 encoding of function field.
   342     ff_ext         = 0,
   343     ff_ins         = 4,
   345     // cop1 encoding of function field.
   346     ff_add_fmt     = 0,
   347     ff_sub_fmt     = 1,
   348     ff_mul_fmt     = 2,
   349     ff_div_fmt     = 3,
   350     ff_sqrt_fmt    = 4,
   351     ff_abs_fmt     = 5,
   352     ff_mov_fmt     = 6,
   353     ff_neg_fmt     = 7,
   355     ff_round_w_fmt = 12,
   356     ff_trunc_w_fmt = 13,
   357     ff_ceil_w_fmt  = 14,
   358     ff_floor_w_fmt = 15,
   360     ff_cvt_s_fmt   = 32,
   361     ff_cvt_d_fmt   = 33,
   362     ff_cvt_w_fmt   = 36,
   364     ff_c_f_fmt     = 48,
   365     ff_c_un_fmt    = 49,
   366     ff_c_eq_fmt    = 50,
   367     ff_c_ueq_fmt   = 51,
   368     ff_c_olt_fmt   = 52,
   369     ff_c_ult_fmt   = 53,
   370     ff_c_ole_fmt   = 54,
   371     ff_c_ule_fmt   = 55,
   372 };
   374 class MacroAssemblerMIPS;
   375 class Operand;
   377 // A BOffImm16 is a 16 bit immediate that is used for branches.
   378 class BOffImm16
   379 {
   380     uint32_t data;
   382   public:
   383     uint32_t encode() {
   384         JS_ASSERT(!isInvalid());
   385         return data;
   386     }
   387     int32_t decode() {
   388         JS_ASSERT(!isInvalid());
   389         return (int32_t(data << 18) >> 16) + 4;
   390     }
   392     explicit BOffImm16(int offset)
   393       : data ((offset - 4) >> 2 & Imm16Mask)
   394     {
   395         JS_ASSERT((offset & 0x3) == 0);
   396         JS_ASSERT(isInRange(offset));
   397     }
   398     static bool isInRange(int offset) {
   399         if ((offset - 4) < (INT16_MIN << 2))
   400             return false;
   401         if ((offset - 4) > (INT16_MAX << 2))
   402             return false;
   403         return true;
   404     }
   405     static const uint32_t INVALID = 0x00020000;
   406     BOffImm16()
   407       : data(INVALID)
   408     { }
   410     bool isInvalid() {
   411         return data == INVALID;
   412     }
   413     Instruction *getDest(Instruction *src);
   415     BOffImm16(InstImm inst);
   416 };
   418 // A JOffImm26 is a 26 bit immediate that is used for unconditional jumps.
   419 class JOffImm26
   420 {
   421     uint32_t data;
   423   public:
   424     uint32_t encode() {
   425         JS_ASSERT(!isInvalid());
   426         return data;
   427     }
   428     int32_t decode() {
   429         JS_ASSERT(!isInvalid());
   430         return (int32_t(data << 8) >> 6) + 4;
   431     }
   433     explicit JOffImm26(int offset)
   434       : data ((offset - 4) >> 2 & Imm26Mask)
   435     {
   436         JS_ASSERT((offset & 0x3) == 0);
   437         JS_ASSERT(isInRange(offset));
   438     }
   439     static bool isInRange(int offset) {
   440         if ((offset - 4) < -536870912)
   441             return false;
   442         if ((offset - 4) > 536870908)
   443             return false;
   444         return true;
   445     }
   446     static const uint32_t INVALID = 0x20000000;
   447     JOffImm26()
   448       : data(INVALID)
   449     { }
   451     bool isInvalid() {
   452         return data == INVALID;
   453     }
   454     Instruction *getDest(Instruction *src);
   456 };
   458 class Imm16
   459 {
   460     uint16_t value;
   462   public:
   463     Imm16();
   464     Imm16(uint32_t imm)
   465       : value(imm)
   466     { }
   467     uint32_t encode() {
   468         return value;
   469     }
   470     int32_t decodeSigned() {
   471         return value;
   472     }
   473     uint32_t decodeUnsigned() {
   474         return value;
   475     }
   476     static bool isInSignedRange(int32_t imm) {
   477         return imm >= INT16_MIN  && imm <= INT16_MAX;
   478     }
   479     static bool isInUnsignedRange(uint32_t imm) {
   480         return imm <= UINT16_MAX ;
   481     }
   482     static Imm16 lower (Imm32 imm) {
   483         return Imm16(imm.value & 0xffff);
   484     }
   485     static Imm16 upper (Imm32 imm) {
   486         return Imm16((imm.value >> 16) & 0xffff);
   487     }
   488 };
   490 class Operand
   491 {
   492   public:
   493     enum Tag {
   494         REG,
   495         FREG,
   496         MEM
   497     };
   499   private:
   500     Tag tag : 3;
   501     uint32_t reg : 5;
   502     int32_t offset;
   504   public:
   505     Operand (Register reg_)
   506       : tag(REG), reg(reg_.code())
   507     { }
   509     Operand (FloatRegister freg)
   510       : tag(FREG), reg(freg.code())
   511     { }
   513     Operand (Register base, Imm32 off)
   514       : tag(MEM), reg(base.code()), offset(off.value)
   515     { }
   517     Operand (Register base, int32_t off)
   518       : tag(MEM), reg(base.code()), offset(off)
   519     { }
   521     Operand (const Address &addr)
   522       : tag(MEM), reg(addr.base.code()), offset(addr.offset)
   523     { }
   525     Tag getTag() const {
   526         return tag;
   527     }
   529     Register toReg() const {
   530         JS_ASSERT(tag == REG);
   531         return Register::FromCode(reg);
   532     }
   534     FloatRegister toFReg() const {
   535         JS_ASSERT(tag == FREG);
   536         return FloatRegister::FromCode(reg);
   537     }
   539     void toAddr(Register *r, Imm32 *dest) const {
   540         JS_ASSERT(tag == MEM);
   541         *r = Register::FromCode(reg);
   542         *dest = Imm32(offset);
   543     }
   544     Address toAddress() const {
   545         JS_ASSERT(tag == MEM);
   546         return Address(Register::FromCode(reg), offset);
   547     }
   548     int32_t disp() const {
   549         JS_ASSERT(tag == MEM);
   550         return offset;
   551     }
   553     int32_t base() const {
   554         JS_ASSERT(tag == MEM);
   555         return reg;
   556     }
   557     Register baseReg() const {
   558         JS_ASSERT(tag == MEM);
   559         return Register::FromCode(reg);
   560     }
   561 };
   563 void
   564 PatchJump(CodeLocationJump &jump_, CodeLocationLabel label);
   565 class Assembler;
   566 typedef js::jit::AssemblerBuffer<1024, Instruction> MIPSBuffer;
   568 class Assembler : public AssemblerShared
   569 {
   570   public:
   572     enum Condition {
   573         Equal,
   574         NotEqual,
   575         Above,
   576         AboveOrEqual,
   577         Below,
   578         BelowOrEqual,
   579         GreaterThan,
   580         GreaterThanOrEqual,
   581         LessThan,
   582         LessThanOrEqual,
   583         Overflow,
   584         Signed,
   585         NotSigned,
   586         Zero,
   587         NonZero,
   588         Always,
   589     };
   591     enum DoubleCondition {
   592         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
   593         DoubleOrdered,
   594         DoubleEqual,
   595         DoubleNotEqual,
   596         DoubleGreaterThan,
   597         DoubleGreaterThanOrEqual,
   598         DoubleLessThan,
   599         DoubleLessThanOrEqual,
   600         // If either operand is NaN, these conditions always evaluate to true.
   601         DoubleUnordered,
   602         DoubleEqualOrUnordered,
   603         DoubleNotEqualOrUnordered,
   604         DoubleGreaterThanOrUnordered,
   605         DoubleGreaterThanOrEqualOrUnordered,
   606         DoubleLessThanOrUnordered,
   607         DoubleLessThanOrEqualOrUnordered
   608     };
   610     enum FPConditionBit {
   611         FCC0 = 0,
   612         FCC1,
   613         FCC2,
   614         FCC3,
   615         FCC4,
   616         FCC5,
   617         FCC6,
   618         FCC7
   619     };
   621     enum FloatFormat {
   622         SingleFloat,
   623         DoubleFloat
   624     };
   626     enum JumpOrCall {
   627         BranchIsJump,
   628         BranchIsCall
   629     };
   631     enum FloatTestKind {
   632         TestForTrue,
   633         TestForFalse
   634     };
   636     // :( this should be protected, but since CodeGenerator
   637     // wants to use it, It needs to go out here :(
   639     BufferOffset nextOffset() {
   640         return m_buffer.nextOffset();
   641     }
   643   protected:
   644     Instruction * editSrc (BufferOffset bo) {
   645         return m_buffer.getInst(bo);
   646     }
   647   public:
   648     uint32_t actualOffset(uint32_t) const;
   649     uint32_t actualIndex(uint32_t) const;
   650     static uint8_t *PatchableJumpAddress(JitCode *code, uint32_t index);
   651   protected:
   653     // structure for fixing up pc-relative loads/jumps when a the machine code
   654     // gets moved (executable copy, gc, etc.)
   655     struct RelativePatch
   656     {
   657         // the offset within the code buffer where the value is loaded that
   658         // we want to fix-up
   659         BufferOffset offset;
   660         void *target;
   661         Relocation::Kind kind;
   663         RelativePatch(BufferOffset offset, void *target, Relocation::Kind kind)
   664           : offset(offset),
   665             target(target),
   666             kind(kind)
   667         { }
   668     };
   670     js::Vector<CodeLabel, 0, SystemAllocPolicy> codeLabels_;
   671     js::Vector<RelativePatch, 8, SystemAllocPolicy> jumps_;
   672     js::Vector<uint32_t, 8, SystemAllocPolicy> longJumps_;
   674     CompactBufferWriter jumpRelocations_;
   675     CompactBufferWriter dataRelocations_;
   676     CompactBufferWriter relocations_;
   677     CompactBufferWriter preBarriers_;
   679     bool enoughMemory_;
   681     MIPSBuffer m_buffer;
   683   public:
   684     Assembler()
   685       : enoughMemory_(true),
   686         m_buffer(),
   687         isFinished(false)
   688     { }
   690     static Condition InvertCondition(Condition cond);
   691     static DoubleCondition InvertCondition(DoubleCondition cond);
   693     // MacroAssemblers hold onto gcthings, so they are traced by the GC.
   694     void trace(JSTracer *trc);
   695     void writeRelocation(BufferOffset src) {
   696         jumpRelocations_.writeUnsigned(src.getOffset());
   697     }
   699     // As opposed to x86/x64 version, the data relocation has to be executed
   700     // before to recover the pointer, and not after.
   701     void writeDataRelocation(const ImmGCPtr &ptr) {
   702         if (ptr.value)
   703             dataRelocations_.writeUnsigned(nextOffset().getOffset());
   704     }
   705     void writePrebarrierOffset(CodeOffsetLabel label) {
   706         preBarriers_.writeUnsigned(label.offset());
   707     }
   709   public:
   710     static uintptr_t getPointer(uint8_t *);
   712     bool oom() const;
   714     void setPrinter(Sprinter *sp) {
   715     }
   717   private:
   718     bool isFinished;
   719   public:
   720     void finish();
   721     void executableCopy(void *buffer);
   722     void copyJumpRelocationTable(uint8_t *dest);
   723     void copyDataRelocationTable(uint8_t *dest);
   724     void copyPreBarrierTable(uint8_t *dest);
   726     bool addCodeLabel(CodeLabel label);
   727     size_t numCodeLabels() const {
   728         return codeLabels_.length();
   729     }
   730     CodeLabel codeLabel(size_t i) {
   731         return codeLabels_[i];
   732     }
   734     // Size of the instruction stream, in bytes.
   735     size_t size() const;
   736     // Size of the jump relocation table, in bytes.
   737     size_t jumpRelocationTableBytes() const;
   738     size_t dataRelocationTableBytes() const;
   739     size_t preBarrierTableBytes() const;
   741     // Size of the data table, in bytes.
   742     size_t bytesNeeded() const;
   744     // Write a blob of binary into the instruction stream *OR*
   745     // into a destination address. If dest is nullptr (the default), then the
   746     // instruction gets written into the instruction stream. If dest is not null
   747     // it is interpreted as a pointer to the location that we want the
   748     // instruction to be written.
   749     BufferOffset writeInst(uint32_t x, uint32_t *dest = nullptr);
   750     // A static variant for the cases where we don't want to have an assembler
   751     // object at all. Normally, you would use the dummy (nullptr) object.
   752     static void writeInstStatic(uint32_t x, uint32_t *dest);
   754   public:
   755     BufferOffset align(int alignment);
   756     BufferOffset as_nop();
   758     // Branch and jump instructions
   759     BufferOffset as_bal(BOffImm16 off);
   761     InstImm getBranchCode(JumpOrCall jumpOrCall);
   762     InstImm getBranchCode(Register s, Register t, Condition c);
   763     InstImm getBranchCode(Register s, Condition c);
   764     InstImm getBranchCode(FloatTestKind testKind, FPConditionBit fcc);
   766     BufferOffset as_j(JOffImm26 off);
   767     BufferOffset as_jal(JOffImm26 off);
   769     BufferOffset as_jr(Register rs);
   770     BufferOffset as_jalr(Register rs);
   772     // Arithmetic instructions
   773     BufferOffset as_addu(Register rd, Register rs, Register rt);
   774     BufferOffset as_addiu(Register rd, Register rs, int32_t j);
   775     BufferOffset as_subu(Register rd, Register rs, Register rt);
   776     BufferOffset as_mult(Register rs, Register rt);
   777     BufferOffset as_multu(Register rs, Register rt);
   778     BufferOffset as_div(Register rs, Register rt);
   779     BufferOffset as_divu(Register rs, Register rt);
   780     BufferOffset as_mul(Register rd, Register rs, Register rt);
   782     // Logical instructions
   783     BufferOffset as_and(Register rd, Register rs, Register rt);
   784     BufferOffset as_or(Register rd, Register rs, Register rt);
   785     BufferOffset as_xor(Register rd, Register rs, Register rt);
   786     BufferOffset as_nor(Register rd, Register rs, Register rt);
   788     BufferOffset as_andi(Register rd, Register rs, int32_t j);
   789     BufferOffset as_ori(Register rd, Register rs, int32_t j);
   790     BufferOffset as_xori(Register rd, Register rs, int32_t j);
   791     BufferOffset as_lui(Register rd, int32_t j);
   793     // Shift instructions
   794     // as_sll(zero, zero, x) instructions are reserved as nop
   795     BufferOffset as_sll(Register rd, Register rt, uint16_t sa);
   796     BufferOffset as_sllv(Register rd, Register rt, Register rs);
   797     BufferOffset as_srl(Register rd, Register rt, uint16_t sa);
   798     BufferOffset as_srlv(Register rd, Register rt, Register rs);
   799     BufferOffset as_sra(Register rd, Register rt, uint16_t sa);
   800     BufferOffset as_srav(Register rd, Register rt, Register rs);
   801     BufferOffset as_rotr(Register rd, Register rt, uint16_t sa);
   802     BufferOffset as_rotrv(Register rd, Register rt, Register rs);
   804     // Load and store instructions
   805     BufferOffset as_lb(Register rd, Register rs, int16_t off);
   806     BufferOffset as_lbu(Register rd, Register rs, int16_t off);
   807     BufferOffset as_lh(Register rd, Register rs, int16_t off);
   808     BufferOffset as_lhu(Register rd, Register rs, int16_t off);
   809     BufferOffset as_lw(Register rd, Register rs, int16_t off);
   810     BufferOffset as_lwl(Register rd, Register rs, int16_t off);
   811     BufferOffset as_lwr(Register rd, Register rs, int16_t off);
   812     BufferOffset as_sb(Register rd, Register rs, int16_t off);
   813     BufferOffset as_sh(Register rd, Register rs, int16_t off);
   814     BufferOffset as_sw(Register rd, Register rs, int16_t off);
   815     BufferOffset as_swl(Register rd, Register rs, int16_t off);
   816     BufferOffset as_swr(Register rd, Register rs, int16_t off);
   818     // Move from HI/LO register.
   819     BufferOffset as_mfhi(Register rd);
   820     BufferOffset as_mflo(Register rd);
   822     // Set on less than.
   823     BufferOffset as_slt(Register rd, Register rs, Register rt);
   824     BufferOffset as_sltu(Register rd, Register rs, Register rt);
   825     BufferOffset as_slti(Register rd, Register rs, int32_t j);
   826     BufferOffset as_sltiu(Register rd, Register rs, uint32_t j);
   828     // Conditional move.
   829     BufferOffset as_movz(Register rd, Register rs, Register rt);
   830     BufferOffset as_movn(Register rd, Register rs, Register rt);
   831     BufferOffset as_movt(Register rd, Register rs, uint16_t cc = 0);
   832     BufferOffset as_movf(Register rd, Register rs, uint16_t cc = 0);
   834     // Bit twiddling.
   835     BufferOffset as_clz(Register rd, Register rs, Register rt = Register::FromCode(0));
   836     BufferOffset as_ins(Register rt, Register rs, uint16_t pos, uint16_t size);
   837     BufferOffset as_ext(Register rt, Register rs, uint16_t pos, uint16_t size);
   839     // FP instructions
   841     // Use these two functions only when you are sure address is aligned.
   842     // Otherwise, use ma_ld and ma_sd.
   843     BufferOffset as_ld(FloatRegister fd, Register base, int32_t off);
   844     BufferOffset as_sd(FloatRegister fd, Register base, int32_t off);
   846     BufferOffset as_ls(FloatRegister fd, Register base, int32_t off);
   847     BufferOffset as_ss(FloatRegister fd, Register base, int32_t off);
   849     BufferOffset as_movs(FloatRegister fd, FloatRegister fs);
   850     BufferOffset as_movd(FloatRegister fd, FloatRegister fs);
   852     BufferOffset as_mtc1(Register rt, FloatRegister fs);
   853     BufferOffset as_mfc1(Register rt, FloatRegister fs);
   855   protected:
   856     // This is used to access the odd regiter form the pair of single
   857     // precision registers that make one double register.
   858     FloatRegister getOddPair(FloatRegister reg) {
   859         JS_ASSERT(reg.code() % 2 == 0);
   860         return FloatRegister::FromCode(reg.code() + 1);
   861     }
   863   public:
   864     // FP convert instructions
   865     BufferOffset as_ceilws(FloatRegister fd, FloatRegister fs);
   866     BufferOffset as_floorws(FloatRegister fd, FloatRegister fs);
   867     BufferOffset as_roundws(FloatRegister fd, FloatRegister fs);
   868     BufferOffset as_truncws(FloatRegister fd, FloatRegister fs);
   870     BufferOffset as_ceilwd(FloatRegister fd, FloatRegister fs);
   871     BufferOffset as_floorwd(FloatRegister fd, FloatRegister fs);
   872     BufferOffset as_roundwd(FloatRegister fd, FloatRegister fs);
   873     BufferOffset as_truncwd(FloatRegister fd, FloatRegister fs);
   875     BufferOffset as_cvtdl(FloatRegister fd, FloatRegister fs);
   876     BufferOffset as_cvtds(FloatRegister fd, FloatRegister fs);
   877     BufferOffset as_cvtdw(FloatRegister fd, FloatRegister fs);
   878     BufferOffset as_cvtld(FloatRegister fd, FloatRegister fs);
   879     BufferOffset as_cvtls(FloatRegister fd, FloatRegister fs);
   880     BufferOffset as_cvtsd(FloatRegister fd, FloatRegister fs);
   881     BufferOffset as_cvtsl(FloatRegister fd, FloatRegister fs);
   882     BufferOffset as_cvtsw(FloatRegister fd, FloatRegister fs);
   883     BufferOffset as_cvtwd(FloatRegister fd, FloatRegister fs);
   884     BufferOffset as_cvtws(FloatRegister fd, FloatRegister fs);
   886     // FP arithmetic instructions
   887     BufferOffset as_adds(FloatRegister fd, FloatRegister fs, FloatRegister ft);
   888     BufferOffset as_addd(FloatRegister fd, FloatRegister fs, FloatRegister ft);
   889     BufferOffset as_subs(FloatRegister fd, FloatRegister fs, FloatRegister ft);
   890     BufferOffset as_subd(FloatRegister fd, FloatRegister fs, FloatRegister ft);
   892     BufferOffset as_abss(FloatRegister fd, FloatRegister fs);
   893     BufferOffset as_absd(FloatRegister fd, FloatRegister fs);
   894     BufferOffset as_negd(FloatRegister fd, FloatRegister fs);
   896     BufferOffset as_muls(FloatRegister fd, FloatRegister fs, FloatRegister ft);
   897     BufferOffset as_muld(FloatRegister fd, FloatRegister fs, FloatRegister ft);
   898     BufferOffset as_divs(FloatRegister fd, FloatRegister fs, FloatRegister ft);
   899     BufferOffset as_divd(FloatRegister fd, FloatRegister fs, FloatRegister ft);
   900     BufferOffset as_sqrts(FloatRegister fd, FloatRegister fs);
   901     BufferOffset as_sqrtd(FloatRegister fd, FloatRegister fs);
   903     // FP compare instructions
   904     BufferOffset as_cf(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
   905                        FPConditionBit fcc = FCC0);
   906     BufferOffset as_cun(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
   907                         FPConditionBit fcc = FCC0);
   908     BufferOffset as_ceq(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
   909                         FPConditionBit fcc = FCC0);
   910     BufferOffset as_cueq(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
   911                          FPConditionBit fcc = FCC0);
   912     BufferOffset as_colt(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
   913                          FPConditionBit fcc = FCC0);
   914     BufferOffset as_cult(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
   915                          FPConditionBit fcc = FCC0);
   916     BufferOffset as_cole(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
   917                          FPConditionBit fcc = FCC0);
   918     BufferOffset as_cule(FloatFormat fmt, FloatRegister fs, FloatRegister ft,
   919                          FPConditionBit fcc = FCC0);
   921     // label operations
   922     void bind(Label *label, BufferOffset boff = BufferOffset());
   923     void bind(RepatchLabel *label);
   924     uint32_t currentOffset() {
   925         return nextOffset().getOffset();
   926     }
   927     void retarget(Label *label, Label *target);
   928     void Bind(uint8_t *rawCode, AbsoluteLabel *label, const void *address);
   930     // See Bind
   931     size_t labelOffsetToPatchOffset(size_t offset) {
   932         return actualOffset(offset);
   933     }
   935     void call(Label *label);
   936     void call(void *target);
   938     void as_break(uint32_t code);
   940   public:
   941     static void TraceJumpRelocations(JSTracer *trc, JitCode *code, CompactBufferReader &reader);
   942     static void TraceDataRelocations(JSTracer *trc, JitCode *code, CompactBufferReader &reader);
   944   protected:
   945     InstImm invertBranch(InstImm branch, BOffImm16 skipOffset);
   946     void bind(InstImm *inst, uint32_t branch, uint32_t target);
   947     void addPendingJump(BufferOffset src, ImmPtr target, Relocation::Kind kind) {
   948         enoughMemory_ &= jumps_.append(RelativePatch(src, target.value, kind));
   949         if (kind == Relocation::JITCODE)
   950             writeRelocation(src);
   951     }
   953     void addLongJump(BufferOffset src) {
   954         enoughMemory_ &= longJumps_.append(src.getOffset());
   955     }
   957   public:
   958     size_t numLongJumps() const {
   959         return longJumps_.length();
   960     }
   961     uint32_t longJump(size_t i) {
   962         return longJumps_[i];
   963     }
   965     // Copy the assembly code to the given buffer, and perform any pending
   966     // relocations relying on the target address.
   967     void executableCopy(uint8_t *buffer);
   969     void flushBuffer() {
   970     }
   972     static uint32_t patchWrite_NearCallSize();
   973     static uint32_t nopSize() { return 4; }
   975     static uint32_t extractLuiOriValue(Instruction *inst0, Instruction *inst1);
   976     static void updateLuiOriValue(Instruction *inst0, Instruction *inst1, uint32_t value);
   977     static void writeLuiOriInstructions(Instruction *inst, Instruction *inst1,
   978                                         Register reg, uint32_t value);
   980     static void patchWrite_NearCall(CodeLocationLabel start, CodeLocationLabel toCall);
   981     static void patchDataWithValueCheck(CodeLocationLabel label, PatchedImmPtr newValue,
   982                                         PatchedImmPtr expectedValue);
   983     static void patchDataWithValueCheck(CodeLocationLabel label, ImmPtr newValue,
   984                                         ImmPtr expectedValue);
   985     static void patchWrite_Imm32(CodeLocationLabel label, Imm32 imm);
   986     static uint32_t alignDoubleArg(uint32_t offset) {
   987         return (offset + 1U) &~ 1U;
   988     }
   990     static uint8_t *nextInstruction(uint8_t *instruction, uint32_t *count = nullptr);
   992     static void ToggleToJmp(CodeLocationLabel inst_);
   993     static void ToggleToCmp(CodeLocationLabel inst_);
   995     static void ToggleCall(CodeLocationLabel inst_, bool enabled);
   997     static void updateBoundsCheck(uint32_t logHeapSize, Instruction *inst);
   998     void processCodeLabels(uint8_t *rawCode);
  1000     bool bailed() {
  1001         return m_buffer.bail();
  1003 }; // Assembler
  1005 // An Instruction is a structure for both encoding and decoding any and all
  1006 // MIPS instructions.
  1007 class Instruction
  1009   protected:
  1010     // sll zero, zero, 0
  1011     static const uint32_t NopInst = 0x00000000;
  1013     uint32_t data;
  1015     // Standard constructor
  1016     Instruction (uint32_t data_) : data(data_) { }
  1018     // You should never create an instruction directly.  You should create a
  1019     // more specific instruction which will eventually call one of these
  1020     // constructors for you.
  1021   public:
  1022     uint32_t encode() const {
  1023         return data;
  1026     void makeNop() {
  1027         data = NopInst;
  1030     void setData(uint32_t data) {
  1031         this->data = data;
  1034     const Instruction & operator=(const Instruction &src) {
  1035         data = src.data;
  1036         return *this;
  1039     // Extract the one particular bit.
  1040     uint32_t extractBit(uint32_t bit) {
  1041         return (encode() >> bit) & 1;
  1043     // Extract a bit field out of the instruction
  1044     uint32_t extractBitField(uint32_t hi, uint32_t lo) {
  1045         return (encode() >> lo) & ((2 << (hi - lo)) - 1);
  1047     // Since all MIPS instructions have opcode, the opcode
  1048     // extractor resides in the base class.
  1049     uint32_t extractOpcode() {
  1050         return extractBitField(OpcodeShift + OpcodeBits - 1, OpcodeShift);
  1052     // Return the fields at their original place in the instruction encoding.
  1053     Opcode OpcodeFieldRaw() const {
  1054         return static_cast<Opcode>(encode() & OpcodeMask);
  1057     // Get the next instruction in the instruction stream.
  1058     // This does neat things like ignoreconstant pools and their guards.
  1059     Instruction *next();
  1061     // Sometimes, an api wants a uint32_t (or a pointer to it) rather than
  1062     // an instruction.  raw() just coerces this into a pointer to a uint32_t
  1063     const uint32_t *raw() const { return &data; }
  1064     uint32_t size() const { return 4; }
  1065 }; // Instruction
  1067 // make sure that it is the right size
  1068 static_assert(sizeof(Instruction) == 4, "Size of Instruction class has to be 4 bytes.");
  1070 class InstNOP : public Instruction
  1072   public:
  1073     InstNOP()
  1074       : Instruction(NopInst)
  1075     { }
  1077 };
  1079 // Class for register type instructions.
  1080 class InstReg : public Instruction
  1082   public:
  1083     InstReg(Opcode op, Register rd, FunctionField ff)
  1084       : Instruction(op | RD(rd) | ff)
  1085     { }
  1086     InstReg(Opcode op, Register rs, Register rt, FunctionField ff)
  1087       : Instruction(op | RS(rs) | RT(rt) | ff)
  1088     { }
  1089     InstReg(Opcode op, Register rs, Register rt, Register rd, FunctionField ff)
  1090       : Instruction(op | RS(rs) | RT(rt) | RD(rd) | ff)
  1091     { }
  1092     InstReg(Opcode op, Register rs, Register rt, Register rd, uint32_t sa, FunctionField ff)
  1093       : Instruction(op | RS(rs) | RT(rt) | RD(rd) | SA(sa) | ff)
  1094     { }
  1095     InstReg(Opcode op, RSField rs, Register rt, Register rd, uint32_t sa, FunctionField ff)
  1096       : Instruction(op | rs | RT(rt) | RD(rd) | SA(sa) | ff)
  1097     { }
  1098     InstReg(Opcode op, Register rs, RTField rt, Register rd, uint32_t sa, FunctionField ff)
  1099       : Instruction(op | RS(rs) | rt | RD(rd) | SA(sa) | ff)
  1100     { }
  1101     InstReg(Opcode op, Register rs, uint32_t cc, Register rd, uint32_t sa, FunctionField ff)
  1102       : Instruction(op | RS(rs) | cc | RD(rd) | SA(sa) | ff)
  1103     { }
  1104     InstReg(Opcode op, uint32_t code, FunctionField ff)
  1105       : Instruction(op | code | ff)
  1106     { }
  1107     // for float point
  1108     InstReg(Opcode op, RSField rs, Register rt, FloatRegister rd)
  1109       : Instruction(op | rs | RT(rt) | RD(rd))
  1110     { }
  1111     InstReg(Opcode op, RSField rs, Register rt, FloatRegister rd, uint32_t sa, FunctionField ff)
  1112       : Instruction(op | rs | RT(rt) | RD(rd) | SA(sa) | ff)
  1113     { }
  1114     InstReg(Opcode op, RSField rs, Register rt, FloatRegister fs, FloatRegister fd, FunctionField ff)
  1115       : Instruction(op | rs | RT(rt) | RD(fs) | SA(fd) | ff)
  1116     { }
  1117     InstReg(Opcode op, RSField rs, FloatRegister ft, FloatRegister fs, FloatRegister fd, FunctionField ff)
  1118       : Instruction(op | rs | RT(ft) | RD(fs) | SA(fd) | ff)
  1119     { }
  1120     InstReg(Opcode op, RSField rs, FloatRegister ft, FloatRegister fd, uint32_t sa, FunctionField ff)
  1121       : Instruction(op | rs | RT(ft) | RD(fd) | SA(sa) | ff)
  1122     { }
  1124     uint32_t extractRS () {
  1125         return extractBitField(RSShift + RSBits - 1, RSShift);
  1127     uint32_t extractRT () {
  1128         return extractBitField(RTShift + RTBits - 1, RTShift);
  1130     uint32_t extractRD () {
  1131         return extractBitField(RDShift + RDBits - 1, RDShift);
  1133     uint32_t extractSA () {
  1134         return extractBitField(SAShift + SABits - 1, SAShift);
  1136     uint32_t extractFunctionField () {
  1137         return extractBitField(FunctionShift + FunctionBits - 1, FunctionShift);
  1139 };
  1141 // Class for branch, load and store instructions with immediate offset.
  1142 class InstImm : public Instruction
  1144   public:
  1145     void extractImm16(BOffImm16 *dest);
  1147     InstImm(Opcode op, Register rs, Register rt, BOffImm16 off)
  1148       : Instruction(op | RS(rs) | RT(rt) | off.encode())
  1149     { }
  1150     InstImm(Opcode op, Register rs, RTField rt, BOffImm16 off)
  1151       : Instruction(op | RS(rs) | rt | off.encode())
  1152     { }
  1153     InstImm(Opcode op, RSField rs, uint32_t cc, BOffImm16 off)
  1154       : Instruction(op | rs | cc | off.encode())
  1155     { }
  1156     InstImm(Opcode op, Register rs, Register rt, Imm16 off)
  1157       : Instruction(op | RS(rs) | RT(rt) | off.encode())
  1158     { }
  1159     InstImm(uint32_t raw)
  1160       : Instruction(raw)
  1161     { }
  1162     // For floating-point loads and stores.
  1163     InstImm(Opcode op, Register rs, FloatRegister rt, Imm16 off)
  1164       : Instruction(op | RS(rs) | RT(rt) | off.encode())
  1165     { }
  1167     uint32_t extractOpcode() {
  1168         return extractBitField(OpcodeShift + OpcodeBits - 1, OpcodeShift);
  1170     void setOpcode(Opcode op) {
  1171         data = (data & ~OpcodeMask) | op;
  1173     uint32_t extractRS() {
  1174         return extractBitField(RSShift + RSBits - 1, RSShift);
  1176     uint32_t extractRT() {
  1177         return extractBitField(RTShift + RTBits - 1, RTShift);
  1179     void setRT(RTField rt) {
  1180         data = (data & ~RTMask) | rt;
  1182     uint32_t extractImm16Value() {
  1183         return extractBitField(Imm16Shift + Imm16Bits - 1, Imm16Shift);
  1185     void setBOffImm16(BOffImm16 off) {
  1186         // Reset immediate field and replace it
  1187         data = (data & ~Imm16Mask) | off.encode();
  1189     void setImm16(Imm16 off) {
  1190         // Reset immediate field and replace it
  1191         data = (data & ~Imm16Mask) | off.encode();
  1193 };
  1195 // Class for Jump type instructions.
  1196 class InstJump : public Instruction
  1198   public:
  1199     InstJump(Opcode op, JOffImm26 off)
  1200       : Instruction(op | off.encode())
  1201     { }
  1203     uint32_t extractImm26Value() {
  1204         return extractBitField(Imm26Shift + Imm26Bits - 1, Imm26Shift);
  1206 };
  1208 static const uint32_t NumIntArgRegs = 4;
  1210 static inline bool
  1211 GetIntArgReg(uint32_t usedArgSlots, Register *out)
  1213     if (usedArgSlots < NumIntArgRegs) {
  1214         *out = Register::FromCode(a0.code() + usedArgSlots);
  1215         return true;
  1217     return false;
  1220 // Get a register in which we plan to put a quantity that will be used as an
  1221 // integer argument. This differs from GetIntArgReg in that if we have no more
  1222 // actual argument registers to use we will fall back on using whatever
  1223 // CallTempReg* don't overlap the argument registers, and only fail once those
  1224 // run out too.
  1225 static inline bool
  1226 GetTempRegForIntArg(uint32_t usedIntArgs, uint32_t usedFloatArgs, Register *out)
  1228     // NOTE: We can't properly determine which regs are used if there are
  1229     // float arguments. If this is needed, we will have to guess.
  1230     JS_ASSERT(usedFloatArgs == 0);
  1232     if (GetIntArgReg(usedIntArgs, out))
  1233         return true;
  1234     // Unfortunately, we have to assume things about the point at which
  1235     // GetIntArgReg returns false, because we need to know how many registers it
  1236     // can allocate.
  1237     usedIntArgs -= NumIntArgRegs;
  1238     if (usedIntArgs >= NumCallTempNonArgRegs)
  1239         return false;
  1240     *out = CallTempNonArgRegs[usedIntArgs];
  1241     return true;
  1244 static inline uint32_t
  1245 GetArgStackDisp(uint32_t usedArgSlots)
  1247     JS_ASSERT(usedArgSlots >= NumIntArgRegs);
  1248     // Even register arguments have place reserved on stack.
  1249     return usedArgSlots * sizeof(intptr_t);
  1252 } // namespace jit
  1253 } // namespace js
  1255 #endif /* jit_mips_Assembler_mips_h */

mercurial