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