Home | History | Annotate | Download | only in mips64
      1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
      2 // All Rights Reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 // - Redistributions of source code must retain the above copyright notice,
      9 // this list of conditions and the following disclaimer.
     10 //
     11 // - Redistribution in binary form must reproduce the above copyright
     12 // notice, this list of conditions and the following disclaimer in the
     13 // documentation and/or other materials provided with the distribution.
     14 //
     15 // - Neither the name of Sun Microsystems or the names of contributors may
     16 // be used to endorse or promote products derived from this software without
     17 // specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 // The original source code covered by the above license above has been
     32 // modified significantly by Google Inc.
     33 // Copyright 2012 the V8 project authors. All rights reserved.
     34 
     35 
     36 #ifndef V8_MIPS_ASSEMBLER_MIPS_H_
     37 #define V8_MIPS_ASSEMBLER_MIPS_H_
     38 
     39 #include <stdio.h>
     40 #include "src/assembler.h"
     41 #include "src/mips64/constants-mips64.h"
     42 #include "src/serialize.h"
     43 
     44 namespace v8 {
     45 namespace internal {
     46 
     47 // CPU Registers.
     48 //
     49 // 1) We would prefer to use an enum, but enum values are assignment-
     50 // compatible with int, which has caused code-generation bugs.
     51 //
     52 // 2) We would prefer to use a class instead of a struct but we don't like
     53 // the register initialization to depend on the particular initialization
     54 // order (which appears to be different on OS X, Linux, and Windows for the
     55 // installed versions of C++ we tried). Using a struct permits C-style
     56 // "initialization". Also, the Register objects cannot be const as this
     57 // forces initialization stubs in MSVC, making us dependent on initialization
     58 // order.
     59 //
     60 // 3) By not using an enum, we are possibly preventing the compiler from
     61 // doing certain constant folds, which may significantly reduce the
     62 // code generated for some assembly instructions (because they boil down
     63 // to a few constants). If this is a problem, we could change the code
     64 // such that we use an enum in optimized mode, and the struct in debug
     65 // mode. This way we get the compile-time error checking in debug mode
     66 // and best performance in optimized code.
     67 
     68 
     69 // -----------------------------------------------------------------------------
     70 // Implementation of Register and FPURegister.
     71 
     72 // Core register.
     73 struct Register {
     74   static const int kNumRegisters = v8::internal::kNumRegisters;
     75   static const int kMaxNumAllocatableRegisters = 14;  // v0 through t6 and cp.
     76   static const int kSizeInBytes = 8;
     77   static const int kCpRegister = 23;  // cp (s7) is the 23rd register.
     78 
     79   inline static int NumAllocatableRegisters();
     80 
     81   static int ToAllocationIndex(Register reg) {
     82     DCHECK((reg.code() - 2) < (kMaxNumAllocatableRegisters - 1) ||
     83            reg.is(from_code(kCpRegister)));
     84     return reg.is(from_code(kCpRegister)) ?
     85            kMaxNumAllocatableRegisters - 1 :  // Return last index for 'cp'.
     86            reg.code() - 2;  // zero_reg and 'at' are skipped.
     87   }
     88 
     89   static Register FromAllocationIndex(int index) {
     90     DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
     91     return index == kMaxNumAllocatableRegisters - 1 ?
     92            from_code(kCpRegister) :  // Last index is always the 'cp' register.
     93            from_code(index + 2);  // zero_reg and 'at' are skipped.
     94   }
     95 
     96   static const char* AllocationIndexToString(int index) {
     97     DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
     98     const char* const names[] = {
     99       "v0",
    100       "v1",
    101       "a0",
    102       "a1",
    103       "a2",
    104       "a3",
    105       "a4",
    106       "a5",
    107       "a6",
    108       "a7",
    109       "t0",
    110       "t1",
    111       "t2",
    112       "s7",
    113     };
    114     return names[index];
    115   }
    116 
    117   static Register from_code(int code) {
    118     Register r = { code };
    119     return r;
    120   }
    121 
    122   bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
    123   bool is(Register reg) const { return code_ == reg.code_; }
    124   int code() const {
    125     DCHECK(is_valid());
    126     return code_;
    127   }
    128   int bit() const {
    129     DCHECK(is_valid());
    130     return 1 << code_;
    131   }
    132 
    133   // Unfortunately we can't make this private in a struct.
    134   int code_;
    135 };
    136 
    137 #define REGISTER(N, C) \
    138   const int kRegister_ ## N ## _Code = C; \
    139   const Register N = { C }
    140 
    141 REGISTER(no_reg, -1);
    142 // Always zero.
    143 REGISTER(zero_reg, 0);
    144 // at: Reserved for synthetic instructions.
    145 REGISTER(at, 1);
    146 // v0, v1: Used when returning multiple values from subroutines.
    147 REGISTER(v0, 2);
    148 REGISTER(v1, 3);
    149 // a0 - a4: Used to pass non-FP parameters.
    150 REGISTER(a0, 4);
    151 REGISTER(a1, 5);
    152 REGISTER(a2, 6);
    153 REGISTER(a3, 7);
    154 // a4 - a7 t0 - t3: Can be used without reservation, act as temporary registers
    155 // and are allowed to be destroyed by subroutines.
    156 REGISTER(a4, 8);
    157 REGISTER(a5, 9);
    158 REGISTER(a6, 10);
    159 REGISTER(a7, 11);
    160 REGISTER(t0, 12);
    161 REGISTER(t1, 13);
    162 REGISTER(t2, 14);
    163 REGISTER(t3, 15);
    164 // s0 - s7: Subroutine register variables. Subroutines that write to these
    165 // registers must restore their values before exiting so that the caller can
    166 // expect the values to be preserved.
    167 REGISTER(s0, 16);
    168 REGISTER(s1, 17);
    169 REGISTER(s2, 18);
    170 REGISTER(s3, 19);
    171 REGISTER(s4, 20);
    172 REGISTER(s5, 21);
    173 REGISTER(s6, 22);
    174 REGISTER(s7, 23);
    175 REGISTER(t8, 24);
    176 REGISTER(t9, 25);
    177 // k0, k1: Reserved for system calls and interrupt handlers.
    178 REGISTER(k0, 26);
    179 REGISTER(k1, 27);
    180 // gp: Reserved.
    181 REGISTER(gp, 28);
    182 // sp: Stack pointer.
    183 REGISTER(sp, 29);
    184 // fp: Frame pointer.
    185 REGISTER(fp, 30);
    186 // ra: Return address pointer.
    187 REGISTER(ra, 31);
    188 
    189 #undef REGISTER
    190 
    191 
    192 int ToNumber(Register reg);
    193 
    194 Register ToRegister(int num);
    195 
    196 // Coprocessor register.
    197 struct FPURegister {
    198   static const int kMaxNumRegisters = v8::internal::kNumFPURegisters;
    199 
    200   // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
    201   // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
    202   // number of Double regs (64-bit regs, or FPU-reg-pairs).
    203 
    204   // A few double registers are reserved: one as a scratch register and one to
    205   // hold 0.0.
    206   //  f28: 0.0
    207   //  f30: scratch register.
    208   static const int kNumReservedRegisters = 2;
    209   static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 -
    210       kNumReservedRegisters;
    211 
    212   inline static int NumRegisters();
    213   inline static int NumAllocatableRegisters();
    214   inline static int ToAllocationIndex(FPURegister reg);
    215   static const char* AllocationIndexToString(int index);
    216 
    217   static FPURegister FromAllocationIndex(int index) {
    218     DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
    219     return from_code(index * 2);
    220   }
    221 
    222   static FPURegister from_code(int code) {
    223     FPURegister r = { code };
    224     return r;
    225   }
    226 
    227   bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; }
    228   bool is(FPURegister creg) const { return code_ == creg.code_; }
    229   FPURegister low() const {
    230     // TODO(plind): Create DCHECK for FR=0 mode. This usage suspect for FR=1.
    231     // Find low reg of a Double-reg pair, which is the reg itself.
    232     DCHECK(code_ % 2 == 0);  // Specified Double reg must be even.
    233     FPURegister reg;
    234     reg.code_ = code_;
    235     DCHECK(reg.is_valid());
    236     return reg;
    237   }
    238   FPURegister high() const {
    239     // TODO(plind): Create DCHECK for FR=0 mode. This usage illegal in FR=1.
    240     // Find high reg of a Doubel-reg pair, which is reg + 1.
    241     DCHECK(code_ % 2 == 0);  // Specified Double reg must be even.
    242     FPURegister reg;
    243     reg.code_ = code_ + 1;
    244     DCHECK(reg.is_valid());
    245     return reg;
    246   }
    247 
    248   int code() const {
    249     DCHECK(is_valid());
    250     return code_;
    251   }
    252   int bit() const {
    253     DCHECK(is_valid());
    254     return 1 << code_;
    255   }
    256   void setcode(int f) {
    257     code_ = f;
    258     DCHECK(is_valid());
    259   }
    260   // Unfortunately we can't make this private in a struct.
    261   int code_;
    262 };
    263 
    264 // V8 now supports the O32 ABI, and the FPU Registers are organized as 32
    265 // 32-bit registers, f0 through f31. When used as 'double' they are used
    266 // in pairs, starting with the even numbered register. So a double operation
    267 // on f0 really uses f0 and f1.
    268 // (Modern mips hardware also supports 32 64-bit registers, via setting
    269 // (privileged) Status Register FR bit to 1. This is used by the N32 ABI,
    270 // but it is not in common use. Someday we will want to support this in v8.)
    271 
    272 // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
    273 typedef FPURegister DoubleRegister;
    274 typedef FPURegister FloatRegister;
    275 
    276 const FPURegister no_freg = { -1 };
    277 
    278 const FPURegister f0 = { 0 };  // Return value in hard float mode.
    279 const FPURegister f1 = { 1 };
    280 const FPURegister f2 = { 2 };
    281 const FPURegister f3 = { 3 };
    282 const FPURegister f4 = { 4 };
    283 const FPURegister f5 = { 5 };
    284 const FPURegister f6 = { 6 };
    285 const FPURegister f7 = { 7 };
    286 const FPURegister f8 = { 8 };
    287 const FPURegister f9 = { 9 };
    288 const FPURegister f10 = { 10 };
    289 const FPURegister f11 = { 11 };
    290 const FPURegister f12 = { 12 };  // Arg 0 in hard float mode.
    291 const FPURegister f13 = { 13 };
    292 const FPURegister f14 = { 14 };  // Arg 1 in hard float mode.
    293 const FPURegister f15 = { 15 };
    294 const FPURegister f16 = { 16 };
    295 const FPURegister f17 = { 17 };
    296 const FPURegister f18 = { 18 };
    297 const FPURegister f19 = { 19 };
    298 const FPURegister f20 = { 20 };
    299 const FPURegister f21 = { 21 };
    300 const FPURegister f22 = { 22 };
    301 const FPURegister f23 = { 23 };
    302 const FPURegister f24 = { 24 };
    303 const FPURegister f25 = { 25 };
    304 const FPURegister f26 = { 26 };
    305 const FPURegister f27 = { 27 };
    306 const FPURegister f28 = { 28 };
    307 const FPURegister f29 = { 29 };
    308 const FPURegister f30 = { 30 };
    309 const FPURegister f31 = { 31 };
    310 
    311 // Register aliases.
    312 // cp is assumed to be a callee saved register.
    313 // Defined using #define instead of "static const Register&" because Clang
    314 // complains otherwise when a compilation unit that includes this header
    315 // doesn't use the variables.
    316 #define kRootRegister s6
    317 #define cp s7
    318 #define kLithiumScratchReg s3
    319 #define kLithiumScratchReg2 s4
    320 #define kLithiumScratchDouble f30
    321 #define kDoubleRegZero f28
    322 
    323 // FPU (coprocessor 1) control registers.
    324 // Currently only FCSR (#31) is implemented.
    325 struct FPUControlRegister {
    326   bool is_valid() const { return code_ == kFCSRRegister; }
    327   bool is(FPUControlRegister creg) const { return code_ == creg.code_; }
    328   int code() const {
    329     DCHECK(is_valid());
    330     return code_;
    331   }
    332   int bit() const {
    333     DCHECK(is_valid());
    334     return 1 << code_;
    335   }
    336   void setcode(int f) {
    337     code_ = f;
    338     DCHECK(is_valid());
    339   }
    340   // Unfortunately we can't make this private in a struct.
    341   int code_;
    342 };
    343 
    344 const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
    345 const FPUControlRegister FCSR = { kFCSRRegister };
    346 
    347 
    348 // -----------------------------------------------------------------------------
    349 // Machine instruction Operands.
    350 const int kSmiShift = kSmiTagSize + kSmiShiftSize;
    351 const uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
    352 // Class Operand represents a shifter operand in data processing instructions.
    353 class Operand BASE_EMBEDDED {
    354  public:
    355   // Immediate.
    356   INLINE(explicit Operand(int64_t immediate,
    357          RelocInfo::Mode rmode = RelocInfo::NONE64));
    358   INLINE(explicit Operand(const ExternalReference& f));
    359   INLINE(explicit Operand(const char* s));
    360   INLINE(explicit Operand(Object** opp));
    361   INLINE(explicit Operand(Context** cpp));
    362   explicit Operand(Handle<Object> handle);
    363   INLINE(explicit Operand(Smi* value));
    364 
    365   // Register.
    366   INLINE(explicit Operand(Register rm));
    367 
    368   // Return true if this is a register operand.
    369   INLINE(bool is_reg() const);
    370 
    371   inline int64_t immediate() const {
    372     DCHECK(!is_reg());
    373     return imm64_;
    374   }
    375 
    376   Register rm() const { return rm_; }
    377 
    378  private:
    379   Register rm_;
    380   int64_t imm64_;  // Valid if rm_ == no_reg.
    381   RelocInfo::Mode rmode_;
    382 
    383   friend class Assembler;
    384   friend class MacroAssembler;
    385 };
    386 
    387 
    388 // On MIPS we have only one adressing mode with base_reg + offset.
    389 // Class MemOperand represents a memory operand in load and store instructions.
    390 class MemOperand : public Operand {
    391  public:
    392   // Immediate value attached to offset.
    393   enum OffsetAddend {
    394     offset_minus_one = -1,
    395     offset_zero = 0
    396   };
    397 
    398   explicit MemOperand(Register rn, int64_t offset = 0);
    399   explicit MemOperand(Register rn, int64_t unit, int64_t multiplier,
    400                       OffsetAddend offset_addend = offset_zero);
    401   int32_t offset() const { return offset_; }
    402 
    403   bool OffsetIsInt16Encodable() const {
    404     return is_int16(offset_);
    405   }
    406 
    407  private:
    408   int32_t offset_;
    409 
    410   friend class Assembler;
    411 };
    412 
    413 
    414 class Assembler : public AssemblerBase {
    415  public:
    416   // Create an assembler. Instructions and relocation information are emitted
    417   // into a buffer, with the instructions starting from the beginning and the
    418   // relocation information starting from the end of the buffer. See CodeDesc
    419   // for a detailed comment on the layout (globals.h).
    420   //
    421   // If the provided buffer is NULL, the assembler allocates and grows its own
    422   // buffer, and buffer_size determines the initial buffer size. The buffer is
    423   // owned by the assembler and deallocated upon destruction of the assembler.
    424   //
    425   // If the provided buffer is not NULL, the assembler uses the provided buffer
    426   // for code generation and assumes its size to be buffer_size. If the buffer
    427   // is too small, a fatal error occurs. No deallocation of the buffer is done
    428   // upon destruction of the assembler.
    429   Assembler(Isolate* isolate, void* buffer, int buffer_size);
    430   virtual ~Assembler() { }
    431 
    432   // GetCode emits any pending (non-emitted) code and fills the descriptor
    433   // desc. GetCode() is idempotent; it returns the same result if no other
    434   // Assembler functions are invoked in between GetCode() calls.
    435   void GetCode(CodeDesc* desc);
    436 
    437   // Label operations & relative jumps (PPUM Appendix D).
    438   //
    439   // Takes a branch opcode (cc) and a label (L) and generates
    440   // either a backward branch or a forward branch and links it
    441   // to the label fixup chain. Usage:
    442   //
    443   // Label L;    // unbound label
    444   // j(cc, &L);  // forward branch to unbound label
    445   // bind(&L);   // bind label to the current pc
    446   // j(cc, &L);  // backward branch to bound label
    447   // bind(&L);   // illegal: a label may be bound only once
    448   //
    449   // Note: The same Label can be used for forward and backward branches
    450   // but it may be bound only once.
    451   void bind(Label* L);  // Binds an unbound label L to current code position.
    452   // Determines if Label is bound and near enough so that branch instruction
    453   // can be used to reach it, instead of jump instruction.
    454   bool is_near(Label* L);
    455 
    456   // Returns the branch offset to the given label from the current code
    457   // position. Links the label to the current position if it is still unbound.
    458   // Manages the jump elimination optimization if the second parameter is true.
    459   int32_t branch_offset(Label* L, bool jump_elimination_allowed);
    460   int32_t branch_offset_compact(Label* L, bool jump_elimination_allowed);
    461   int32_t branch_offset21(Label* L, bool jump_elimination_allowed);
    462   int32_t branch_offset21_compact(Label* L, bool jump_elimination_allowed);
    463   int32_t shifted_branch_offset(Label* L, bool jump_elimination_allowed) {
    464     int32_t o = branch_offset(L, jump_elimination_allowed);
    465     DCHECK((o & 3) == 0);   // Assert the offset is aligned.
    466     return o >> 2;
    467   }
    468   int32_t shifted_branch_offset_compact(Label* L,
    469       bool jump_elimination_allowed) {
    470     int32_t o = branch_offset_compact(L, jump_elimination_allowed);
    471     DCHECK((o & 3) == 0);   // Assert the offset is aligned.
    472     return o >> 2;
    473   }
    474   uint64_t jump_address(Label* L);
    475 
    476   // Puts a labels target address at the given position.
    477   // The high 8 bits are set to zero.
    478   void label_at_put(Label* L, int at_offset);
    479 
    480   // Read/Modify the code target address in the branch/call instruction at pc.
    481   static Address target_address_at(Address pc);
    482   static void set_target_address_at(Address pc,
    483                                     Address target,
    484                                     ICacheFlushMode icache_flush_mode =
    485                                         FLUSH_ICACHE_IF_NEEDED);
    486   // On MIPS there is no Constant Pool so we skip that parameter.
    487   INLINE(static Address target_address_at(Address pc,
    488                                           ConstantPoolArray* constant_pool)) {
    489     return target_address_at(pc);
    490   }
    491   INLINE(static void set_target_address_at(Address pc,
    492                                            ConstantPoolArray* constant_pool,
    493                                            Address target,
    494                                            ICacheFlushMode icache_flush_mode =
    495                                                FLUSH_ICACHE_IF_NEEDED)) {
    496     set_target_address_at(pc, target, icache_flush_mode);
    497   }
    498   INLINE(static Address target_address_at(Address pc, Code* code)) {
    499     ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
    500     return target_address_at(pc, constant_pool);
    501   }
    502   INLINE(static void set_target_address_at(Address pc,
    503                                            Code* code,
    504                                            Address target,
    505                                            ICacheFlushMode icache_flush_mode =
    506                                                FLUSH_ICACHE_IF_NEEDED)) {
    507     ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
    508     set_target_address_at(pc, constant_pool, target, icache_flush_mode);
    509   }
    510 
    511   // Return the code target address at a call site from the return address
    512   // of that call in the instruction stream.
    513   inline static Address target_address_from_return_address(Address pc);
    514 
    515   // Return the code target address of the patch debug break slot
    516   inline static Address break_address_from_return_address(Address pc);
    517 
    518   static void JumpLabelToJumpRegister(Address pc);
    519 
    520   static void QuietNaN(HeapObject* nan);
    521 
    522   // This sets the branch destination (which gets loaded at the call address).
    523   // This is for calls and branches within generated code.  The serializer
    524   // has already deserialized the lui/ori instructions etc.
    525   inline static void deserialization_set_special_target_at(
    526       Address instruction_payload, Code* code, Address target) {
    527     set_target_address_at(
    528         instruction_payload - kInstructionsFor64BitConstant * kInstrSize,
    529         code,
    530         target);
    531   }
    532 
    533   // Size of an instruction.
    534   static const int kInstrSize = sizeof(Instr);
    535 
    536   // Difference between address of current opcode and target address offset.
    537   static const int kBranchPCOffset = 4;
    538 
    539   // Here we are patching the address in the LUI/ORI instruction pair.
    540   // These values are used in the serialization process and must be zero for
    541   // MIPS platform, as Code, Embedded Object or External-reference pointers
    542   // are split across two consecutive instructions and don't exist separately
    543   // in the code, so the serializer should not step forwards in memory after
    544   // a target is resolved and written.
    545   static const int kSpecialTargetSize = 0;
    546 
    547   // Number of consecutive instructions used to store 32bit/64bit constant.
    548   // Before jump-optimizations, this constant was used in
    549   // RelocInfo::target_address_address() function to tell serializer address of
    550   // the instruction that follows LUI/ORI instruction pair. Now, with new jump
    551   // optimization, where jump-through-register instruction that usually
    552   // follows LUI/ORI pair is substituted with J/JAL, this constant equals
    553   // to 3 instructions (LUI+ORI+J/JAL/JR/JALR).
    554   static const int kInstructionsFor32BitConstant = 3;
    555   static const int kInstructionsFor64BitConstant = 5;
    556 
    557   // Distance between the instruction referring to the address of the call
    558   // target and the return address.
    559   static const int kCallTargetAddressOffset = 6 * kInstrSize;
    560 
    561   // Distance between start of patched return sequence and the emitted address
    562   // to jump to.
    563   static const int kPatchReturnSequenceAddressOffset = 0;
    564 
    565   // Distance between start of patched debug break slot and the emitted address
    566   // to jump to.
    567   static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
    568 
    569   // Difference between address of current opcode and value read from pc
    570   // register.
    571   static const int kPcLoadDelta = 4;
    572 
    573   static const int kPatchDebugBreakSlotReturnOffset = 6 * kInstrSize;
    574 
    575   // Number of instructions used for the JS return sequence. The constant is
    576   // used by the debugger to patch the JS return sequence.
    577   static const int kJSReturnSequenceInstructions = 7;
    578   static const int kDebugBreakSlotInstructions = 6;
    579   static const int kDebugBreakSlotLength =
    580       kDebugBreakSlotInstructions * kInstrSize;
    581 
    582 
    583   // ---------------------------------------------------------------------------
    584   // Code generation.
    585 
    586   // Insert the smallest number of nop instructions
    587   // possible to align the pc offset to a multiple
    588   // of m. m must be a power of 2 (>= 4).
    589   void Align(int m);
    590   // Aligns code to something that's optimal for a jump target for the platform.
    591   void CodeTargetAlign();
    592 
    593   // Different nop operations are used by the code generator to detect certain
    594   // states of the generated code.
    595   enum NopMarkerTypes {
    596     NON_MARKING_NOP = 0,
    597     DEBUG_BREAK_NOP,
    598     // IC markers.
    599     PROPERTY_ACCESS_INLINED,
    600     PROPERTY_ACCESS_INLINED_CONTEXT,
    601     PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
    602     // Helper values.
    603     LAST_CODE_MARKER,
    604     FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED,
    605     // Code aging
    606     CODE_AGE_MARKER_NOP = 6,
    607     CODE_AGE_SEQUENCE_NOP
    608   };
    609 
    610   // Type == 0 is the default non-marking nop. For mips this is a
    611   // sll(zero_reg, zero_reg, 0). We use rt_reg == at for non-zero
    612   // marking, to avoid conflict with ssnop and ehb instructions.
    613   void nop(unsigned int type = 0) {
    614     DCHECK(type < 32);
    615     Register nop_rt_reg = (type == 0) ? zero_reg : at;
    616     sll(zero_reg, nop_rt_reg, type, true);
    617   }
    618 
    619 
    620   // --------Branch-and-jump-instructions----------
    621   // We don't use likely variant of instructions.
    622   void b(int16_t offset);
    623   void b(Label* L) { b(branch_offset(L, false)>>2); }
    624   void bal(int16_t offset);
    625   void bal(Label* L) { bal(branch_offset(L, false)>>2); }
    626 
    627   void beq(Register rs, Register rt, int16_t offset);
    628   void beq(Register rs, Register rt, Label* L) {
    629     beq(rs, rt, branch_offset(L, false) >> 2);
    630   }
    631   void bgez(Register rs, int16_t offset);
    632   void bgezc(Register rt, int16_t offset);
    633   void bgezc(Register rt, Label* L) {
    634     bgezc(rt, branch_offset_compact(L, false)>>2);
    635   }
    636   void bgeuc(Register rs, Register rt, int16_t offset);
    637   void bgeuc(Register rs, Register rt, Label* L) {
    638     bgeuc(rs, rt, branch_offset_compact(L, false)>>2);
    639   }
    640   void bgec(Register rs, Register rt, int16_t offset);
    641   void bgec(Register rs, Register rt, Label* L) {
    642     bgec(rs, rt, branch_offset_compact(L, false)>>2);
    643   }
    644   void bgezal(Register rs, int16_t offset);
    645   void bgezalc(Register rt, int16_t offset);
    646   void bgezalc(Register rt, Label* L) {
    647     bgezalc(rt, branch_offset_compact(L, false)>>2);
    648   }
    649   void bgezall(Register rs, int16_t offset);
    650   void bgezall(Register rs, Label* L) {
    651     bgezall(rs, branch_offset(L, false)>>2);
    652   }
    653   void bgtz(Register rs, int16_t offset);
    654   void bgtzc(Register rt, int16_t offset);
    655   void bgtzc(Register rt, Label* L) {
    656     bgtzc(rt, branch_offset_compact(L, false)>>2);
    657   }
    658   void blez(Register rs, int16_t offset);
    659   void blezc(Register rt, int16_t offset);
    660   void blezc(Register rt, Label* L) {
    661     blezc(rt, branch_offset_compact(L, false)>>2);
    662   }
    663   void bltz(Register rs, int16_t offset);
    664   void bltzc(Register rt, int16_t offset);
    665   void bltzc(Register rt, Label* L) {
    666     bltzc(rt, branch_offset_compact(L, false)>>2);
    667   }
    668   void bltuc(Register rs, Register rt, int16_t offset);
    669   void bltuc(Register rs, Register rt, Label* L) {
    670     bltuc(rs, rt, branch_offset_compact(L, false)>>2);
    671   }
    672   void bltc(Register rs, Register rt, int16_t offset);
    673   void bltc(Register rs, Register rt, Label* L) {
    674     bltc(rs, rt, branch_offset_compact(L, false)>>2);
    675   }
    676 
    677   void bltzal(Register rs, int16_t offset);
    678   void blezalc(Register rt, int16_t offset);
    679   void blezalc(Register rt, Label* L) {
    680     blezalc(rt, branch_offset_compact(L, false)>>2);
    681   }
    682   void bltzalc(Register rt, int16_t offset);
    683   void bltzalc(Register rt, Label* L) {
    684     bltzalc(rt, branch_offset_compact(L, false)>>2);
    685   }
    686   void bgtzalc(Register rt, int16_t offset);
    687   void bgtzalc(Register rt, Label* L) {
    688     bgtzalc(rt, branch_offset_compact(L, false)>>2);
    689   }
    690   void beqzalc(Register rt, int16_t offset);
    691   void beqzalc(Register rt, Label* L) {
    692     beqzalc(rt, branch_offset_compact(L, false)>>2);
    693   }
    694   void beqc(Register rs, Register rt, int16_t offset);
    695   void beqc(Register rs, Register rt, Label* L) {
    696     beqc(rs, rt, branch_offset_compact(L, false)>>2);
    697   }
    698   void beqzc(Register rs, int32_t offset);
    699   void beqzc(Register rs, Label* L) {
    700     beqzc(rs, branch_offset21_compact(L, false)>>2);
    701   }
    702   void bnezalc(Register rt, int16_t offset);
    703   void bnezalc(Register rt, Label* L) {
    704     bnezalc(rt, branch_offset_compact(L, false)>>2);
    705   }
    706   void bnec(Register rs, Register rt, int16_t offset);
    707   void bnec(Register rs, Register rt, Label* L) {
    708     bnec(rs, rt, branch_offset_compact(L, false)>>2);
    709   }
    710   void bnezc(Register rt, int32_t offset);
    711   void bnezc(Register rt, Label* L) {
    712     bnezc(rt, branch_offset21_compact(L, false)>>2);
    713   }
    714   void bne(Register rs, Register rt, int16_t offset);
    715   void bne(Register rs, Register rt, Label* L) {
    716     bne(rs, rt, branch_offset(L, false)>>2);
    717   }
    718   void bovc(Register rs, Register rt, int16_t offset);
    719   void bovc(Register rs, Register rt, Label* L) {
    720     bovc(rs, rt, branch_offset_compact(L, false)>>2);
    721   }
    722   void bnvc(Register rs, Register rt, int16_t offset);
    723   void bnvc(Register rs, Register rt, Label* L) {
    724     bnvc(rs, rt, branch_offset_compact(L, false)>>2);
    725   }
    726 
    727   // Never use the int16_t b(l)cond version with a branch offset
    728   // instead of using the Label* version.
    729 
    730   // Jump targets must be in the current 256 MB-aligned region. i.e. 28 bits.
    731   void j(int64_t target);
    732   void jal(int64_t target);
    733   void jalr(Register rs, Register rd = ra);
    734   void jr(Register target);
    735   void j_or_jr(int64_t target, Register rs);
    736   void jal_or_jalr(int64_t target, Register rs);
    737 
    738 
    739   // -------Data-processing-instructions---------
    740 
    741   // Arithmetic.
    742   void addu(Register rd, Register rs, Register rt);
    743   void subu(Register rd, Register rs, Register rt);
    744 
    745   void div(Register rs, Register rt);
    746   void divu(Register rs, Register rt);
    747   void ddiv(Register rs, Register rt);
    748   void ddivu(Register rs, Register rt);
    749   void div(Register rd, Register rs, Register rt);
    750   void divu(Register rd, Register rs, Register rt);
    751   void ddiv(Register rd, Register rs, Register rt);
    752   void ddivu(Register rd, Register rs, Register rt);
    753   void mod(Register rd, Register rs, Register rt);
    754   void modu(Register rd, Register rs, Register rt);
    755   void dmod(Register rd, Register rs, Register rt);
    756   void dmodu(Register rd, Register rs, Register rt);
    757 
    758   void mul(Register rd, Register rs, Register rt);
    759   void muh(Register rd, Register rs, Register rt);
    760   void mulu(Register rd, Register rs, Register rt);
    761   void muhu(Register rd, Register rs, Register rt);
    762   void mult(Register rs, Register rt);
    763   void multu(Register rs, Register rt);
    764   void dmul(Register rd, Register rs, Register rt);
    765   void dmuh(Register rd, Register rs, Register rt);
    766   void dmulu(Register rd, Register rs, Register rt);
    767   void dmuhu(Register rd, Register rs, Register rt);
    768   void daddu(Register rd, Register rs, Register rt);
    769   void dsubu(Register rd, Register rs, Register rt);
    770   void dmult(Register rs, Register rt);
    771   void dmultu(Register rs, Register rt);
    772 
    773   void addiu(Register rd, Register rs, int32_t j);
    774   void daddiu(Register rd, Register rs, int32_t j);
    775 
    776   // Logical.
    777   void and_(Register rd, Register rs, Register rt);
    778   void or_(Register rd, Register rs, Register rt);
    779   void xor_(Register rd, Register rs, Register rt);
    780   void nor(Register rd, Register rs, Register rt);
    781 
    782   void andi(Register rd, Register rs, int32_t j);
    783   void ori(Register rd, Register rs, int32_t j);
    784   void xori(Register rd, Register rs, int32_t j);
    785   void lui(Register rd, int32_t j);
    786   void aui(Register rs, Register rt, int32_t j);
    787   void daui(Register rs, Register rt, int32_t j);
    788   void dahi(Register rs, int32_t j);
    789   void dati(Register rs, int32_t j);
    790 
    791   // Shifts.
    792   // Please note: sll(zero_reg, zero_reg, x) instructions are reserved as nop
    793   // and may cause problems in normal code. coming_from_nop makes sure this
    794   // doesn't happen.
    795   void sll(Register rd, Register rt, uint16_t sa, bool coming_from_nop = false);
    796   void sllv(Register rd, Register rt, Register rs);
    797   void srl(Register rd, Register rt, uint16_t sa);
    798   void srlv(Register rd, Register rt, Register rs);
    799   void sra(Register rt, Register rd, uint16_t sa);
    800   void srav(Register rt, Register rd, Register rs);
    801   void rotr(Register rd, Register rt, uint16_t sa);
    802   void rotrv(Register rd, Register rt, Register rs);
    803   void dsll(Register rd, Register rt, uint16_t sa);
    804   void dsllv(Register rd, Register rt, Register rs);
    805   void dsrl(Register rd, Register rt, uint16_t sa);
    806   void dsrlv(Register rd, Register rt, Register rs);
    807   void drotr(Register rd, Register rt, uint16_t sa);
    808   void drotrv(Register rd, Register rt, Register rs);
    809   void dsra(Register rt, Register rd, uint16_t sa);
    810   void dsrav(Register rd, Register rt, Register rs);
    811   void dsll32(Register rt, Register rd, uint16_t sa);
    812   void dsrl32(Register rt, Register rd, uint16_t sa);
    813   void dsra32(Register rt, Register rd, uint16_t sa);
    814 
    815 
    816   // ------------Memory-instructions-------------
    817 
    818   void lb(Register rd, const MemOperand& rs);
    819   void lbu(Register rd, const MemOperand& rs);
    820   void lh(Register rd, const MemOperand& rs);
    821   void lhu(Register rd, const MemOperand& rs);
    822   void lw(Register rd, const MemOperand& rs);
    823   void lwu(Register rd, const MemOperand& rs);
    824   void lwl(Register rd, const MemOperand& rs);
    825   void lwr(Register rd, const MemOperand& rs);
    826   void sb(Register rd, const MemOperand& rs);
    827   void sh(Register rd, const MemOperand& rs);
    828   void sw(Register rd, const MemOperand& rs);
    829   void swl(Register rd, const MemOperand& rs);
    830   void swr(Register rd, const MemOperand& rs);
    831   void ldl(Register rd, const MemOperand& rs);
    832   void ldr(Register rd, const MemOperand& rs);
    833   void sdl(Register rd, const MemOperand& rs);
    834   void sdr(Register rd, const MemOperand& rs);
    835   void ld(Register rd, const MemOperand& rs);
    836   void sd(Register rd, const MemOperand& rs);
    837 
    838 
    839   // ----------------Prefetch--------------------
    840 
    841   void pref(int32_t hint, const MemOperand& rs);
    842 
    843 
    844   // -------------Misc-instructions--------------
    845 
    846   // Break / Trap instructions.
    847   void break_(uint32_t code, bool break_as_stop = false);
    848   void stop(const char* msg, uint32_t code = kMaxStopCode);
    849   void tge(Register rs, Register rt, uint16_t code);
    850   void tgeu(Register rs, Register rt, uint16_t code);
    851   void tlt(Register rs, Register rt, uint16_t code);
    852   void tltu(Register rs, Register rt, uint16_t code);
    853   void teq(Register rs, Register rt, uint16_t code);
    854   void tne(Register rs, Register rt, uint16_t code);
    855 
    856   // Move from HI/LO register.
    857   void mfhi(Register rd);
    858   void mflo(Register rd);
    859 
    860   // Set on less than.
    861   void slt(Register rd, Register rs, Register rt);
    862   void sltu(Register rd, Register rs, Register rt);
    863   void slti(Register rd, Register rs, int32_t j);
    864   void sltiu(Register rd, Register rs, int32_t j);
    865 
    866   // Conditional move.
    867   void movz(Register rd, Register rs, Register rt);
    868   void movn(Register rd, Register rs, Register rt);
    869   void movt(Register rd, Register rs, uint16_t cc = 0);
    870   void movf(Register rd, Register rs, uint16_t cc = 0);
    871 
    872   void sel(SecondaryField fmt, FPURegister fd, FPURegister ft,
    873       FPURegister fs, uint8_t sel);
    874   void seleqz(Register rs, Register rt, Register rd);
    875   void seleqz(SecondaryField fmt, FPURegister fd, FPURegister ft,
    876       FPURegister fs);
    877   void selnez(Register rs, Register rt, Register rd);
    878   void selnez(SecondaryField fmt, FPURegister fd, FPURegister ft,
    879       FPURegister fs);
    880 
    881   // Bit twiddling.
    882   void clz(Register rd, Register rs);
    883   void ins_(Register rt, Register rs, uint16_t pos, uint16_t size);
    884   void ext_(Register rt, Register rs, uint16_t pos, uint16_t size);
    885 
    886   // --------Coprocessor-instructions----------------
    887 
    888   // Load, store, and move.
    889   void lwc1(FPURegister fd, const MemOperand& src);
    890   void ldc1(FPURegister fd, const MemOperand& src);
    891 
    892   void swc1(FPURegister fs, const MemOperand& dst);
    893   void sdc1(FPURegister fs, const MemOperand& dst);
    894 
    895   void mtc1(Register rt, FPURegister fs);
    896   void mthc1(Register rt, FPURegister fs);
    897   void dmtc1(Register rt, FPURegister fs);
    898 
    899   void mfc1(Register rt, FPURegister fs);
    900   void mfhc1(Register rt, FPURegister fs);
    901   void dmfc1(Register rt, FPURegister fs);
    902 
    903   void ctc1(Register rt, FPUControlRegister fs);
    904   void cfc1(Register rt, FPUControlRegister fs);
    905 
    906   // Arithmetic.
    907   void add_d(FPURegister fd, FPURegister fs, FPURegister ft);
    908   void sub_d(FPURegister fd, FPURegister fs, FPURegister ft);
    909   void mul_d(FPURegister fd, FPURegister fs, FPURegister ft);
    910   void madd_d(FPURegister fd, FPURegister fr, FPURegister fs, FPURegister ft);
    911   void div_d(FPURegister fd, FPURegister fs, FPURegister ft);
    912   void abs_d(FPURegister fd, FPURegister fs);
    913   void mov_d(FPURegister fd, FPURegister fs);
    914   void neg_d(FPURegister fd, FPURegister fs);
    915   void sqrt_d(FPURegister fd, FPURegister fs);
    916 
    917   // Conversion.
    918   void cvt_w_s(FPURegister fd, FPURegister fs);
    919   void cvt_w_d(FPURegister fd, FPURegister fs);
    920   void trunc_w_s(FPURegister fd, FPURegister fs);
    921   void trunc_w_d(FPURegister fd, FPURegister fs);
    922   void round_w_s(FPURegister fd, FPURegister fs);
    923   void round_w_d(FPURegister fd, FPURegister fs);
    924   void floor_w_s(FPURegister fd, FPURegister fs);
    925   void floor_w_d(FPURegister fd, FPURegister fs);
    926   void ceil_w_s(FPURegister fd, FPURegister fs);
    927   void ceil_w_d(FPURegister fd, FPURegister fs);
    928 
    929   void cvt_l_s(FPURegister fd, FPURegister fs);
    930   void cvt_l_d(FPURegister fd, FPURegister fs);
    931   void trunc_l_s(FPURegister fd, FPURegister fs);
    932   void trunc_l_d(FPURegister fd, FPURegister fs);
    933   void round_l_s(FPURegister fd, FPURegister fs);
    934   void round_l_d(FPURegister fd, FPURegister fs);
    935   void floor_l_s(FPURegister fd, FPURegister fs);
    936   void floor_l_d(FPURegister fd, FPURegister fs);
    937   void ceil_l_s(FPURegister fd, FPURegister fs);
    938   void ceil_l_d(FPURegister fd, FPURegister fs);
    939 
    940   void min(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
    941   void mina(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
    942   void max(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
    943   void maxa(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs);
    944 
    945   void cvt_s_w(FPURegister fd, FPURegister fs);
    946   void cvt_s_l(FPURegister fd, FPURegister fs);
    947   void cvt_s_d(FPURegister fd, FPURegister fs);
    948 
    949   void cvt_d_w(FPURegister fd, FPURegister fs);
    950   void cvt_d_l(FPURegister fd, FPURegister fs);
    951   void cvt_d_s(FPURegister fd, FPURegister fs);
    952 
    953   // Conditions and branches for MIPSr6.
    954   void cmp(FPUCondition cond, SecondaryField fmt,
    955          FPURegister fd, FPURegister ft, FPURegister fs);
    956 
    957   void bc1eqz(int16_t offset, FPURegister ft);
    958   void bc1eqz(Label* L, FPURegister ft) {
    959     bc1eqz(branch_offset(L, false)>>2, ft);
    960   }
    961   void bc1nez(int16_t offset, FPURegister ft);
    962   void bc1nez(Label* L, FPURegister ft) {
    963     bc1nez(branch_offset(L, false)>>2, ft);
    964   }
    965 
    966   // Conditions and branches for non MIPSr6.
    967   void c(FPUCondition cond, SecondaryField fmt,
    968          FPURegister ft, FPURegister fs, uint16_t cc = 0);
    969 
    970   void bc1f(int16_t offset, uint16_t cc = 0);
    971   void bc1f(Label* L, uint16_t cc = 0) {
    972     bc1f(branch_offset(L, false)>>2, cc);
    973   }
    974   void bc1t(int16_t offset, uint16_t cc = 0);
    975   void bc1t(Label* L, uint16_t cc = 0) {
    976     bc1t(branch_offset(L, false)>>2, cc);
    977   }
    978   void fcmp(FPURegister src1, const double src2, FPUCondition cond);
    979 
    980   // Check the code size generated from label to here.
    981   int SizeOfCodeGeneratedSince(Label* label) {
    982     return pc_offset() - label->pos();
    983   }
    984 
    985   // Check the number of instructions generated from label to here.
    986   int InstructionsGeneratedSince(Label* label) {
    987     return SizeOfCodeGeneratedSince(label) / kInstrSize;
    988   }
    989 
    990   // Class for scoping postponing the trampoline pool generation.
    991   class BlockTrampolinePoolScope {
    992    public:
    993     explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
    994       assem_->StartBlockTrampolinePool();
    995     }
    996     ~BlockTrampolinePoolScope() {
    997       assem_->EndBlockTrampolinePool();
    998     }
    999 
   1000    private:
   1001     Assembler* assem_;
   1002 
   1003     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
   1004   };
   1005 
   1006   // Class for postponing the assembly buffer growth. Typically used for
   1007   // sequences of instructions that must be emitted as a unit, before
   1008   // buffer growth (and relocation) can occur.
   1009   // This blocking scope is not nestable.
   1010   class BlockGrowBufferScope {
   1011    public:
   1012     explicit BlockGrowBufferScope(Assembler* assem) : assem_(assem) {
   1013       assem_->StartBlockGrowBuffer();
   1014     }
   1015     ~BlockGrowBufferScope() {
   1016       assem_->EndBlockGrowBuffer();
   1017     }
   1018 
   1019    private:
   1020     Assembler* assem_;
   1021 
   1022     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockGrowBufferScope);
   1023   };
   1024 
   1025   // Debugging.
   1026 
   1027   // Mark address of the ExitJSFrame code.
   1028   void RecordJSReturn();
   1029 
   1030   // Mark address of a debug break slot.
   1031   void RecordDebugBreakSlot();
   1032 
   1033   // Record the AST id of the CallIC being compiled, so that it can be placed
   1034   // in the relocation information.
   1035   void SetRecordedAstId(TypeFeedbackId ast_id) {
   1036     DCHECK(recorded_ast_id_.IsNone());
   1037     recorded_ast_id_ = ast_id;
   1038   }
   1039 
   1040   TypeFeedbackId RecordedAstId() {
   1041     DCHECK(!recorded_ast_id_.IsNone());
   1042     return recorded_ast_id_;
   1043   }
   1044 
   1045   void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
   1046 
   1047   // Record a comment relocation entry that can be used by a disassembler.
   1048   // Use --code-comments to enable.
   1049   void RecordComment(const char* msg);
   1050 
   1051   static int RelocateInternalReference(byte* pc, intptr_t pc_delta);
   1052 
   1053   // Writes a single byte or word of data in the code stream.  Used for
   1054   // inline tables, e.g., jump-tables.
   1055   void db(uint8_t data);
   1056   void dd(uint32_t data);
   1057 
   1058   // Emits the address of the code stub's first instruction.
   1059   void emit_code_stub_address(Code* stub);
   1060 
   1061   PositionsRecorder* positions_recorder() { return &positions_recorder_; }
   1062 
   1063   // Postpone the generation of the trampoline pool for the specified number of
   1064   // instructions.
   1065   void BlockTrampolinePoolFor(int instructions);
   1066 
   1067   // Check if there is less than kGap bytes available in the buffer.
   1068   // If this is the case, we need to grow the buffer before emitting
   1069   // an instruction or relocation information.
   1070   inline bool overflow() const { return pc_ >= reloc_info_writer.pos() - kGap; }
   1071 
   1072   // Get the number of bytes available in the buffer.
   1073   inline int available_space() const { return reloc_info_writer.pos() - pc_; }
   1074 
   1075   // Read/patch instructions.
   1076   static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
   1077   static void instr_at_put(byte* pc, Instr instr) {
   1078     *reinterpret_cast<Instr*>(pc) = instr;
   1079   }
   1080   Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
   1081   void instr_at_put(int pos, Instr instr) {
   1082     *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
   1083   }
   1084 
   1085   // Check if an instruction is a branch of some kind.
   1086   static bool IsBranch(Instr instr);
   1087   static bool IsBeq(Instr instr);
   1088   static bool IsBne(Instr instr);
   1089 
   1090   static bool IsJump(Instr instr);
   1091   static bool IsJ(Instr instr);
   1092   static bool IsLui(Instr instr);
   1093   static bool IsOri(Instr instr);
   1094 
   1095   static bool IsJal(Instr instr);
   1096   static bool IsJr(Instr instr);
   1097   static bool IsJalr(Instr instr);
   1098 
   1099   static bool IsNop(Instr instr, unsigned int type);
   1100   static bool IsPop(Instr instr);
   1101   static bool IsPush(Instr instr);
   1102   static bool IsLwRegFpOffset(Instr instr);
   1103   static bool IsSwRegFpOffset(Instr instr);
   1104   static bool IsLwRegFpNegOffset(Instr instr);
   1105   static bool IsSwRegFpNegOffset(Instr instr);
   1106 
   1107   static Register GetRtReg(Instr instr);
   1108   static Register GetRsReg(Instr instr);
   1109   static Register GetRdReg(Instr instr);
   1110 
   1111   static uint32_t GetRt(Instr instr);
   1112   static uint32_t GetRtField(Instr instr);
   1113   static uint32_t GetRs(Instr instr);
   1114   static uint32_t GetRsField(Instr instr);
   1115   static uint32_t GetRd(Instr instr);
   1116   static uint32_t GetRdField(Instr instr);
   1117   static uint32_t GetSa(Instr instr);
   1118   static uint32_t GetSaField(Instr instr);
   1119   static uint32_t GetOpcodeField(Instr instr);
   1120   static uint32_t GetFunction(Instr instr);
   1121   static uint32_t GetFunctionField(Instr instr);
   1122   static uint32_t GetImmediate16(Instr instr);
   1123   static uint32_t GetLabelConst(Instr instr);
   1124 
   1125   static int32_t GetBranchOffset(Instr instr);
   1126   static bool IsLw(Instr instr);
   1127   static int16_t GetLwOffset(Instr instr);
   1128   static Instr SetLwOffset(Instr instr, int16_t offset);
   1129 
   1130   static bool IsSw(Instr instr);
   1131   static Instr SetSwOffset(Instr instr, int16_t offset);
   1132   static bool IsAddImmediate(Instr instr);
   1133   static Instr SetAddImmediateOffset(Instr instr, int16_t offset);
   1134 
   1135   static bool IsAndImmediate(Instr instr);
   1136   static bool IsEmittedConstant(Instr instr);
   1137 
   1138   void CheckTrampolinePool();
   1139 
   1140   // Allocate a constant pool of the correct size for the generated code.
   1141   Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
   1142 
   1143   // Generate the constant pool for the generated code.
   1144   void PopulateConstantPool(ConstantPoolArray* constant_pool);
   1145 
   1146  protected:
   1147   // Relocation for a type-recording IC has the AST id added to it.  This
   1148   // member variable is a way to pass the information from the call site to
   1149   // the relocation info.
   1150   TypeFeedbackId recorded_ast_id_;
   1151 
   1152   int64_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
   1153 
   1154   // Decode branch instruction at pos and return branch target pos.
   1155   int64_t target_at(int64_t pos);
   1156 
   1157   // Patch branch instruction at pos to branch to given branch target pos.
   1158   void target_at_put(int64_t pos, int64_t target_pos);
   1159 
   1160   // Say if we need to relocate with this mode.
   1161   bool MustUseReg(RelocInfo::Mode rmode);
   1162 
   1163   // Record reloc info for current pc_.
   1164   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
   1165 
   1166   // Block the emission of the trampoline pool before pc_offset.
   1167   void BlockTrampolinePoolBefore(int pc_offset) {
   1168     if (no_trampoline_pool_before_ < pc_offset)
   1169       no_trampoline_pool_before_ = pc_offset;
   1170   }
   1171 
   1172   void StartBlockTrampolinePool() {
   1173     trampoline_pool_blocked_nesting_++;
   1174   }
   1175 
   1176   void EndBlockTrampolinePool() {
   1177     trampoline_pool_blocked_nesting_--;
   1178   }
   1179 
   1180   bool is_trampoline_pool_blocked() const {
   1181     return trampoline_pool_blocked_nesting_ > 0;
   1182   }
   1183 
   1184   bool has_exception() const {
   1185     return internal_trampoline_exception_;
   1186   }
   1187 
   1188   void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi);
   1189 
   1190   bool is_trampoline_emitted() const {
   1191     return trampoline_emitted_;
   1192   }
   1193 
   1194   // Temporarily block automatic assembly buffer growth.
   1195   void StartBlockGrowBuffer() {
   1196     DCHECK(!block_buffer_growth_);
   1197     block_buffer_growth_ = true;
   1198   }
   1199 
   1200   void EndBlockGrowBuffer() {
   1201     DCHECK(block_buffer_growth_);
   1202     block_buffer_growth_ = false;
   1203   }
   1204 
   1205   bool is_buffer_growth_blocked() const {
   1206     return block_buffer_growth_;
   1207   }
   1208 
   1209  private:
   1210   // Buffer size and constant pool distance are checked together at regular
   1211   // intervals of kBufferCheckInterval emitted bytes.
   1212   static const int kBufferCheckInterval = 1*KB/2;
   1213 
   1214   // Code generation.
   1215   // The relocation writer's position is at least kGap bytes below the end of
   1216   // the generated instructions. This is so that multi-instruction sequences do
   1217   // not have to check for overflow. The same is true for writes of large
   1218   // relocation info entries.
   1219   static const int kGap = 32;
   1220 
   1221 
   1222   // Repeated checking whether the trampoline pool should be emitted is rather
   1223   // expensive. By default we only check again once a number of instructions
   1224   // has been generated.
   1225   static const int kCheckConstIntervalInst = 32;
   1226   static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
   1227 
   1228   int next_buffer_check_;  // pc offset of next buffer check.
   1229 
   1230   // Emission of the trampoline pool may be blocked in some code sequences.
   1231   int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
   1232   int no_trampoline_pool_before_;  // Block emission before this pc offset.
   1233 
   1234   // Keep track of the last emitted pool to guarantee a maximal distance.
   1235   int last_trampoline_pool_end_;  // pc offset of the end of the last pool.
   1236 
   1237   // Automatic growth of the assembly buffer may be blocked for some sequences.
   1238   bool block_buffer_growth_;  // Block growth when true.
   1239 
   1240   // Relocation information generation.
   1241   // Each relocation is encoded as a variable size value.
   1242   static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
   1243   RelocInfoWriter reloc_info_writer;
   1244 
   1245   // The bound position, before this we cannot do instruction elimination.
   1246   int last_bound_pos_;
   1247 
   1248   // Code emission.
   1249   inline void CheckBuffer();
   1250   void GrowBuffer();
   1251   inline void emit(Instr x);
   1252   inline void emit(uint64_t x);
   1253   inline void CheckTrampolinePoolQuick();
   1254 
   1255   // Instruction generation.
   1256   // We have 3 different kind of encoding layout on MIPS.
   1257   // However due to many different types of objects encoded in the same fields
   1258   // we have quite a few aliases for each mode.
   1259   // Using the same structure to refer to Register and FPURegister would spare a
   1260   // few aliases, but mixing both does not look clean to me.
   1261   // Anyway we could surely implement this differently.
   1262 
   1263   void GenInstrRegister(Opcode opcode,
   1264                         Register rs,
   1265                         Register rt,
   1266                         Register rd,
   1267                         uint16_t sa = 0,
   1268                         SecondaryField func = NULLSF);
   1269 
   1270   void GenInstrRegister(Opcode opcode,
   1271                         Register rs,
   1272                         Register rt,
   1273                         uint16_t msb,
   1274                         uint16_t lsb,
   1275                         SecondaryField func);
   1276 
   1277   void GenInstrRegister(Opcode opcode,
   1278                         SecondaryField fmt,
   1279                         FPURegister ft,
   1280                         FPURegister fs,
   1281                         FPURegister fd,
   1282                         SecondaryField func = NULLSF);
   1283 
   1284   void GenInstrRegister(Opcode opcode,
   1285                         FPURegister fr,
   1286                         FPURegister ft,
   1287                         FPURegister fs,
   1288                         FPURegister fd,
   1289                         SecondaryField func = NULLSF);
   1290 
   1291   void GenInstrRegister(Opcode opcode,
   1292                         SecondaryField fmt,
   1293                         Register rt,
   1294                         FPURegister fs,
   1295                         FPURegister fd,
   1296                         SecondaryField func = NULLSF);
   1297 
   1298   void GenInstrRegister(Opcode opcode,
   1299                         SecondaryField fmt,
   1300                         Register rt,
   1301                         FPUControlRegister fs,
   1302                         SecondaryField func = NULLSF);
   1303 
   1304 
   1305   void GenInstrImmediate(Opcode opcode,
   1306                          Register rs,
   1307                          Register rt,
   1308                          int32_t  j);
   1309   void GenInstrImmediate(Opcode opcode,
   1310                          Register rs,
   1311                          SecondaryField SF,
   1312                          int32_t  j);
   1313   void GenInstrImmediate(Opcode opcode,
   1314                          Register r1,
   1315                          FPURegister r2,
   1316                          int32_t  j);
   1317 
   1318 
   1319   void GenInstrJump(Opcode opcode,
   1320                      uint32_t address);
   1321 
   1322   // Helpers.
   1323   void LoadRegPlusOffsetToAt(const MemOperand& src);
   1324 
   1325   // Labels.
   1326   void print(Label* L);
   1327   void bind_to(Label* L, int pos);
   1328   void next(Label* L);
   1329 
   1330   // One trampoline consists of:
   1331   // - space for trampoline slots,
   1332   // - space for labels.
   1333   //
   1334   // Space for trampoline slots is equal to slot_count * 2 * kInstrSize.
   1335   // Space for trampoline slots preceeds space for labels. Each label is of one
   1336   // instruction size, so total amount for labels is equal to
   1337   // label_count *  kInstrSize.
   1338   class Trampoline {
   1339    public:
   1340     Trampoline() {
   1341       start_ = 0;
   1342       next_slot_ = 0;
   1343       free_slot_count_ = 0;
   1344       end_ = 0;
   1345     }
   1346     Trampoline(int start, int slot_count) {
   1347       start_ = start;
   1348       next_slot_ = start;
   1349       free_slot_count_ = slot_count;
   1350       end_ = start + slot_count * kTrampolineSlotsSize;
   1351     }
   1352     int start() {
   1353       return start_;
   1354     }
   1355     int end() {
   1356       return end_;
   1357     }
   1358     int take_slot() {
   1359       int trampoline_slot = kInvalidSlotPos;
   1360       if (free_slot_count_ <= 0) {
   1361         // We have run out of space on trampolines.
   1362         // Make sure we fail in debug mode, so we become aware of each case
   1363         // when this happens.
   1364         DCHECK(0);
   1365         // Internal exception will be caught.
   1366       } else {
   1367         trampoline_slot = next_slot_;
   1368         free_slot_count_--;
   1369         next_slot_ += kTrampolineSlotsSize;
   1370       }
   1371       return trampoline_slot;
   1372     }
   1373 
   1374    private:
   1375     int start_;
   1376     int end_;
   1377     int next_slot_;
   1378     int free_slot_count_;
   1379   };
   1380 
   1381   int32_t get_trampoline_entry(int32_t pos);
   1382   int unbound_labels_count_;
   1383   // If trampoline is emitted, generated code is becoming large. As this is
   1384   // already a slow case which can possibly break our code generation for the
   1385   // extreme case, we use this information to trigger different mode of
   1386   // branch instruction generation, where we use jump instructions rather
   1387   // than regular branch instructions.
   1388   bool trampoline_emitted_;
   1389   static const int kTrampolineSlotsSize = 6 * kInstrSize;
   1390   static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
   1391   static const int kInvalidSlotPos = -1;
   1392 
   1393   Trampoline trampoline_;
   1394   bool internal_trampoline_exception_;
   1395 
   1396   friend class RegExpMacroAssemblerMIPS;
   1397   friend class RelocInfo;
   1398   friend class CodePatcher;
   1399   friend class BlockTrampolinePoolScope;
   1400 
   1401   PositionsRecorder positions_recorder_;
   1402   friend class PositionsRecorder;
   1403   friend class EnsureSpace;
   1404 };
   1405 
   1406 
   1407 class EnsureSpace BASE_EMBEDDED {
   1408  public:
   1409   explicit EnsureSpace(Assembler* assembler) {
   1410     assembler->CheckBuffer();
   1411   }
   1412 };
   1413 
   1414 } }  // namespace v8::internal
   1415 
   1416 #endif  // V8_ARM_ASSEMBLER_MIPS_H_
   1417