V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
assembler-s390.h
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
6 // are 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
14 // distribution.
15 //
16 // - Neither the name of Sun Microsystems or the names of contributors may
17 // be used to endorse or promote products derived from this software without
18 // specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 // OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 // The original source code covered by the above license above has been
34 // modified significantly by Google Inc.
35 // Copyright 2014 the V8 project authors. All rights reserved.
36 
37 // A light-weight S390 Assembler
38 // Generates user mode instructions for z/Architecture
39 
40 #ifndef V8_S390_ASSEMBLER_S390_H_
41 #define V8_S390_ASSEMBLER_S390_H_
42 #include <stdio.h>
43 #if V8_HOST_ARCH_S390
44 // elf.h include is required for auxv check for STFLE facility used
45 // for hardware detection, which is sensible only on s390 hosts.
46 #include <elf.h>
47 #endif
48 
49 #include <fcntl.h>
50 #include <unistd.h>
51 #include <vector>
52 
53 #include "src/assembler.h"
54 #include "src/external-reference.h"
55 #include "src/label.h"
56 #include "src/objects/smi.h"
57 #include "src/s390/constants-s390.h"
58 
59 #define ABI_USES_FUNCTION_DESCRIPTORS 0
60 
61 #define ABI_PASSES_HANDLES_IN_REGS 1
62 
63 // ObjectPair is defined under runtime/runtime-util.h.
64 // On 31-bit, ObjectPair == uint64_t. ABI dictates long long
65 // be returned with the lower addressed half in r2
66 // and the higher addressed half in r3. (Returns in Regs)
67 // On 64-bit, ObjectPair is a Struct. ABI dictaes Structs be
68 // returned in a storage buffer allocated by the caller,
69 // with the address of this buffer passed as a hidden
70 // argument in r2. (Does NOT return in Regs)
71 // For x86 linux, ObjectPair is returned in registers.
72 #if V8_TARGET_ARCH_S390X
73 #define ABI_RETURNS_OBJECTPAIR_IN_REGS 0
74 #else
75 #define ABI_RETURNS_OBJECTPAIR_IN_REGS 1
76 #endif
77 
78 #define ABI_CALL_VIA_IP 1
79 
80 #define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC
81 
82 namespace v8 {
83 namespace internal {
84 
85 // clang-format off
86 #define GENERAL_REGISTERS(V) \
87  V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
88  V(r8) V(r9) V(r10) V(fp) V(ip) V(r13) V(r14) V(sp)
89 
90 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
91  V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
92  V(r8) V(r9) V(r13)
93 
94 #define DOUBLE_REGISTERS(V) \
95  V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
96  V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15)
97 
98 #define FLOAT_REGISTERS DOUBLE_REGISTERS
99 #define SIMD128_REGISTERS DOUBLE_REGISTERS
100 
101 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
102  V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
103  V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) V(d0)
104 
105 #define C_REGISTERS(V) \
106  V(cr0) V(cr1) V(cr2) V(cr3) V(cr4) V(cr5) V(cr6) V(cr7) \
107  V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15)
108 // clang-format on
109 
110 // Register list in load/store instructions
111 // Note that the bit values must match those used in actual instruction encoding
112 const int kNumRegs = 16;
113 
114 // Caller-saved/arguments registers
115 const RegList kJSCallerSaved = 1 << 1 | 1 << 2 | // r2 a1
116  1 << 3 | // r3 a2
117  1 << 4 | // r4 a3
118  1 << 5; // r5 a4
119 
120 const int kNumJSCallerSaved = 5;
121 
122 // Callee-saved registers preserved when switching from C to JavaScript
123 const RegList kCalleeSaved =
124  1 << 6 | // r6 (argument passing in CEntryStub)
125  // (HandleScope logic in MacroAssembler)
126  1 << 7 | // r7 (argument passing in CEntryStub)
127  // (HandleScope logic in MacroAssembler)
128  1 << 8 | // r8 (argument passing in CEntryStub)
129  // (HandleScope logic in MacroAssembler)
130  1 << 9 | // r9 (HandleScope logic in MacroAssembler)
131  1 << 10 | // r10 (Roots register in Javascript)
132  1 << 11 | // r11 (fp in Javascript)
133  1 << 12 | // r12 (ip in Javascript)
134  1 << 13; // r13 (cp in Javascript)
135 // 1 << 15; // r15 (sp in Javascript)
136 
137 const int kNumCalleeSaved = 8;
138 
139 #ifdef V8_TARGET_ARCH_S390X
140 
141 const RegList kCallerSavedDoubles = 1 << 0 | // d0
142  1 << 1 | // d1
143  1 << 2 | // d2
144  1 << 3 | // d3
145  1 << 4 | // d4
146  1 << 5 | // d5
147  1 << 6 | // d6
148  1 << 7; // d7
149 
150 const int kNumCallerSavedDoubles = 8;
151 
152 const RegList kCalleeSavedDoubles = 1 << 8 | // d8
153  1 << 9 | // d9
154  1 << 10 | // d10
155  1 << 11 | // d11
156  1 << 12 | // d12
157  1 << 13 | // d12
158  1 << 14 | // d12
159  1 << 15; // d13
160 
161 const int kNumCalleeSavedDoubles = 8;
162 
163 #else
164 
165 const RegList kCallerSavedDoubles = 1 << 14 | // d14
166  1 << 15 | // d15
167  1 << 0 | // d0
168  1 << 1 | // d1
169  1 << 2 | // d2
170  1 << 3 | // d3
171  1 << 5 | // d5
172  1 << 7 | // d7
173  1 << 8 | // d8
174  1 << 9 | // d9
175  1 << 10 | // d10
176  1 << 11 | // d10
177  1 << 12 | // d10
178  1 << 13; // d11
179 
180 const int kNumCallerSavedDoubles = 14;
181 
182 const RegList kCalleeSavedDoubles = 1 << 4 | // d4
183  1 << 6; // d6
184 
185 const int kNumCalleeSavedDoubles = 2;
186 
187 #endif
188 
189 // Number of registers for which space is reserved in safepoints. Must be a
190 // multiple of 8.
191 // TODO(regis): Only 8 registers may actually be sufficient. Revisit.
192 const int kNumSafepointRegisters = 16;
193 
194 // Define the list of registers actually saved at safepoints.
195 // Note that the number of saved registers may be smaller than the reserved
196 // space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
197 const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
198 const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
199 
200 // The following constants describe the stack frame linkage area as
201 // defined by the ABI.
202 
203 #if V8_TARGET_ARCH_S390X
204 // [0] Back Chain
205 // [1] Reserved for compiler use
206 // [2] GPR 2
207 // [3] GPR 3
208 // ...
209 // [15] GPR 15
210 // [16] FPR 0
211 // [17] FPR 2
212 // [18] FPR 4
213 // [19] FPR 6
214 const int kNumRequiredStackFrameSlots = 20;
215 const int kStackFrameRASlot = 14;
216 const int kStackFrameSPSlot = 15;
217 const int kStackFrameExtraParamSlot = 20;
218 #else
219 // [0] Back Chain
220 // [1] Reserved for compiler use
221 // [2] GPR 2
222 // [3] GPR 3
223 // ...
224 // [15] GPR 15
225 // [16..17] FPR 0
226 // [18..19] FPR 2
227 // [20..21] FPR 4
228 // [22..23] FPR 6
229 const int kNumRequiredStackFrameSlots = 24;
230 const int kStackFrameRASlot = 14;
231 const int kStackFrameSPSlot = 15;
232 const int kStackFrameExtraParamSlot = 24;
233 #endif
234 
235 // zLinux ABI requires caller frames to include sufficient space for
236 // callee preserved register save area.
237 #if V8_TARGET_ARCH_S390X
238 const int kCalleeRegisterSaveAreaSize = 160;
239 #elif V8_TARGET_ARCH_S390
240 const int kCalleeRegisterSaveAreaSize = 96;
241 #else
242 const int kCalleeRegisterSaveAreaSize = 0;
243 #endif
244 
245 enum RegisterCode {
246 #define REGISTER_CODE(R) kRegCode_##R,
247  GENERAL_REGISTERS(REGISTER_CODE)
248 #undef REGISTER_CODE
249  kRegAfterLast
250 };
251 
252 class Register : public RegisterBase<Register, kRegAfterLast> {
253  public:
254 #if V8_TARGET_LITTLE_ENDIAN
255  static constexpr int kMantissaOffset = 0;
256  static constexpr int kExponentOffset = 4;
257 #else
258  static constexpr int kMantissaOffset = 4;
259  static constexpr int kExponentOffset = 0;
260 #endif
261 
262  private:
263  friend class RegisterBase;
264  explicit constexpr Register(int code) : RegisterBase(code) {}
265 };
266 
267 ASSERT_TRIVIALLY_COPYABLE(Register);
268 static_assert(sizeof(Register) == sizeof(int),
269  "Register can efficiently be passed by value");
270 
271 #define DEFINE_REGISTER(R) \
272  constexpr Register R = Register::from_code<kRegCode_##R>();
273 GENERAL_REGISTERS(DEFINE_REGISTER)
274 #undef DEFINE_REGISTER
275 constexpr Register no_reg = Register::no_reg();
276 
277 // Register aliases
278 constexpr Register kRootRegister = r10; // Roots array pointer.
279 constexpr Register cp = r13; // JavaScript context pointer.
280 
281 constexpr bool kPadArguments = false;
282 constexpr bool kSimpleFPAliasing = true;
283 constexpr bool kSimdMaskRegisters = false;
284 
285 enum DoubleRegisterCode {
286 #define REGISTER_CODE(R) kDoubleCode_##R,
287  DOUBLE_REGISTERS(REGISTER_CODE)
288 #undef REGISTER_CODE
289  kDoubleAfterLast
290 };
291 
292 // Double word VFP register.
293 class DoubleRegister : public RegisterBase<DoubleRegister, kDoubleAfterLast> {
294  public:
295  // A few double registers are reserved: one as a scratch register and one to
296  // hold 0.0, that does not fit in the immediate field of vmov instructions.
297  // d14: 0.0
298  // d15: scratch register.
299  static constexpr int kSizeInBytes = 8;
300  inline static int NumRegisters();
301 
302  private:
303  friend class RegisterBase;
304 
305  explicit constexpr DoubleRegister(int code) : RegisterBase(code) {}
306 };
307 
308 ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
309 static_assert(sizeof(DoubleRegister) == sizeof(int),
310  "DoubleRegister can efficiently be passed by value");
311 
312 typedef DoubleRegister FloatRegister;
313 
314 // TODO(john.yan) Define SIMD registers.
315 typedef DoubleRegister Simd128Register;
316 
317 #define DEFINE_REGISTER(R) \
318  constexpr DoubleRegister R = DoubleRegister::from_code<kDoubleCode_##R>();
319 DOUBLE_REGISTERS(DEFINE_REGISTER)
320 #undef DEFINE_REGISTER
321 constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
322 
323 constexpr DoubleRegister kDoubleRegZero = d14;
324 constexpr DoubleRegister kScratchDoubleReg = d13;
325 
326 Register ToRegister(int num);
327 
328 enum CRegisterCode {
329 #define REGISTER_CODE(R) kCCode_##R,
330  C_REGISTERS(REGISTER_CODE)
331 #undef REGISTER_CODE
332  kCAfterLast
333 };
334 
335 // Coprocessor register
336 class CRegister : public RegisterBase<CRegister, kCAfterLast> {
337  friend class RegisterBase;
338  explicit constexpr CRegister(int code) : RegisterBase(code) {}
339 };
340 
341 constexpr CRegister no_creg = CRegister::no_reg();
342 #define DECLARE_C_REGISTER(R) \
343  constexpr CRegister R = CRegister::from_code<kCCode_##R>();
344 C_REGISTERS(DECLARE_C_REGISTER)
345 #undef DECLARE_C_REGISTER
346 
347 // -----------------------------------------------------------------------------
348 // Machine instruction Operands
349 
350 // Class Operand represents a shifter operand in data processing instructions
351 // defining immediate numbers and masks
352 class Operand {
353  public:
354  // immediate
355  V8_INLINE explicit Operand(intptr_t immediate,
356  RelocInfo::Mode rmode = RelocInfo::NONE)
357  : rmode_(rmode) {
358  value_.immediate = immediate;
359  }
360  V8_INLINE static Operand Zero() { return Operand(static_cast<intptr_t>(0)); }
361  V8_INLINE explicit Operand(const ExternalReference& f)
362  : rmode_(RelocInfo::EXTERNAL_REFERENCE) {
363  value_.immediate = static_cast<intptr_t>(f.address());
364  }
365  explicit Operand(Handle<HeapObject> handle);
366  V8_INLINE explicit Operand(Smi value) : rmode_(RelocInfo::NONE) {
367  value_.immediate = static_cast<intptr_t>(value.ptr());
368  }
369 
370  // rm
371  V8_INLINE explicit Operand(Register rm);
372 
373  static Operand EmbeddedNumber(double value); // Smi or HeapNumber
374  static Operand EmbeddedStringConstant(const StringConstantBase* str);
375 
376  // Return true if this is a register operand.
377  V8_INLINE bool is_reg() const { return rm_.is_valid(); }
378 
379  bool must_output_reloc_info(const Assembler* assembler) const;
380 
381  inline intptr_t immediate() const {
382  DCHECK(!rm_.is_valid());
383  DCHECK(!is_heap_object_request());
384  return value_.immediate;
385  }
386 
387  HeapObjectRequest heap_object_request() const {
388  DCHECK(is_heap_object_request());
389  return value_.heap_object_request;
390  }
391 
392  inline void setBits(int n) {
393  value_.immediate =
394  (static_cast<uint32_t>(value_.immediate) << (32 - n)) >> (32 - n);
395  }
396 
397  Register rm() const { return rm_; }
398 
399  bool is_heap_object_request() const {
400  DCHECK_IMPLIES(is_heap_object_request_, !rm_.is_valid());
401  DCHECK_IMPLIES(is_heap_object_request_,
402  rmode_ == RelocInfo::EMBEDDED_OBJECT ||
403  rmode_ == RelocInfo::CODE_TARGET);
404  return is_heap_object_request_;
405  }
406 
407  RelocInfo::Mode rmode() const { return rmode_; }
408 
409  private:
410  Register rm_ = no_reg;
411  union Value {
412  Value() {}
413  HeapObjectRequest heap_object_request; // if is_heap_object_request_
414  intptr_t immediate; // otherwise
415  } value_; // valid if rm_ == no_reg
416  bool is_heap_object_request_ = false;
417 
418  RelocInfo::Mode rmode_;
419 
420  friend class Assembler;
421  friend class MacroAssembler;
422 };
423 
424 typedef int32_t Disp;
425 
426 // Class MemOperand represents a memory operand in load and store instructions
427 // On S390, we have various flavours of memory operands:
428 // 1) a base register + 16 bit unsigned displacement
429 // 2) a base register + index register + 16 bit unsigned displacement
430 // 3) a base register + index register + 20 bit signed displacement
431 class MemOperand {
432  public:
433  explicit MemOperand(Register rx, Disp offset = 0);
434  explicit MemOperand(Register rx, Register rb, Disp offset = 0);
435 
436  int32_t offset() const { return offset_; }
437  uint32_t getDisplacement() const { return offset(); }
438 
439  // Base register
440  Register rb() const {
441  DCHECK(baseRegister != no_reg);
442  return baseRegister;
443  }
444 
445  Register getBaseRegister() const { return rb(); }
446 
447  // Index Register
448  Register rx() const {
449  DCHECK(indexRegister != no_reg);
450  return indexRegister;
451  }
452  Register getIndexRegister() const { return rx(); }
453 
454  private:
455  Register baseRegister; // base
456  Register indexRegister; // index
457  int32_t offset_; // offset
458 
459  friend class Assembler;
460 };
461 
462 class DeferredRelocInfo {
463  public:
464  DeferredRelocInfo() {}
465  DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
466  : position_(position), rmode_(rmode), data_(data) {}
467 
468  int position() const { return position_; }
469  RelocInfo::Mode rmode() const { return rmode_; }
470  intptr_t data() const { return data_; }
471 
472  private:
473  int position_;
474  RelocInfo::Mode rmode_;
475  intptr_t data_;
476 };
477 
478 class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
479  public:
480  // Create an assembler. Instructions and relocation information are emitted
481  // into a buffer, with the instructions starting from the beginning and the
482  // relocation information starting from the end of the buffer. See CodeDesc
483  // for a detailed comment on the layout (globals.h).
484  //
485  // If the provided buffer is nullptr, the assembler allocates and grows its
486  // own buffer, and buffer_size determines the initial buffer size. The buffer
487  // is owned by the assembler and deallocated upon destruction of the
488  // assembler.
489  //
490  // If the provided buffer is not nullptr, the assembler uses the provided
491  // buffer for code generation and assumes its size to be buffer_size. If the
492  // buffer is too small, a fatal error occurs. No deallocation of the buffer is
493  // done upon destruction of the assembler.
494  Assembler(const AssemblerOptions& options, void* buffer, int buffer_size);
495  virtual ~Assembler() {}
496 
497  // GetCode emits any pending (non-emitted) code and fills the descriptor
498  // desc. GetCode() is idempotent; it returns the same result if no other
499  // Assembler functions are invoked in between GetCode() calls.
500  void GetCode(Isolate* isolate, CodeDesc* desc);
501 
502  // Label operations & relative jumps (PPUM Appendix D)
503  //
504  // Takes a branch opcode (cc) and a label (L) and generates
505  // either a backward branch or a forward branch and links it
506  // to the label fixup chain. Usage:
507  //
508  // Label L; // unbound label
509  // j(cc, &L); // forward branch to unbound label
510  // bind(&L); // bind label to the current pc
511  // j(cc, &L); // backward branch to bound label
512  // bind(&L); // illegal: a label may be bound only once
513  //
514  // Note: The same Label can be used for forward and backward branches
515  // but it may be bound only once.
516 
517  void bind(Label* L); // binds an unbound label L to the current code position
518 
519  // Links a label at the current pc_offset(). If already bound, returns the
520  // bound position. If already linked, returns the position of the prior link.
521  // Otherwise, returns the current pc_offset().
522  int link(Label* L);
523 
524  // Determines if Label is bound and near enough so that a single
525  // branch instruction can be used to reach it.
526  bool is_near(Label* L, Condition cond);
527 
528  // Returns the branch offset to the given label from the current code position
529  // Links the label to the current position if it is still unbound
530  int branch_offset(Label* L) { return link(L) - pc_offset(); }
531 
532  // Puts a labels target address at the given position.
533  // The high 8 bits are set to zero.
534  void label_at_put(Label* L, int at_offset);
535  void load_label_offset(Register r1, Label* L);
536 
537  // Read/Modify the code target address in the branch/call instruction at pc.
538  // The isolate argument is unused (and may be nullptr) when skipping flushing.
539  V8_INLINE static Address target_address_at(Address pc, Address constant_pool);
540  V8_INLINE static void set_target_address_at(
541  Address pc, Address constant_pool, Address target,
542  ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
543 
544  // Return the code target address at a call site from the return address
545  // of that call in the instruction stream.
546  inline static Address target_address_from_return_address(Address pc);
547 
548  // Given the address of the beginning of a call, return the address
549  // in the instruction stream that the call will return to.
550  V8_INLINE static Address return_address_from_call_start(Address pc);
551 
552  inline Handle<Object> code_target_object_handle_at(Address pc);
553  // This sets the branch destination.
554  // This is for calls and branches within generated code.
555  inline static void deserialization_set_special_target_at(
556  Address instruction_payload, Code code, Address target);
557 
558  // Get the size of the special target encoded at 'instruction_payload'.
559  inline static int deserialization_special_target_size(
560  Address instruction_payload);
561 
562  // This sets the internal reference at the pc.
563  inline static void deserialization_set_target_internal_reference_at(
564  Address pc, Address target,
565  RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
566 
567  // Here we are patching the address in the IIHF/IILF instruction pair.
568  // These values are used in the serialization process and must be zero for
569  // S390 platform, as Code, Embedded Object or External-reference pointers
570  // are split across two consecutive instructions and don't exist separately
571  // in the code, so the serializer should not step forwards in memory after
572  // a target is resolved and written.
573  static constexpr int kSpecialTargetSize = 0;
574 
575 // Number of bytes for instructions used to store pointer sized constant.
576 #if V8_TARGET_ARCH_S390X
577  static constexpr int kBytesForPtrConstant = 12; // IIHF + IILF
578 #else
579  static constexpr int kBytesForPtrConstant = 6; // IILF
580 #endif
581 
582  // Distance between the instruction referring to the address of the call
583  // target and the return address.
584 
585  // Offset between call target address and return address
586  // for BRASL calls
587  // Patch will be appiled to other FIXED_SEQUENCE call
588  static constexpr int kCallTargetAddressOffset = 6;
589 
590 // The length of FIXED_SEQUENCE call
591 // iihf r8, <address_hi> // <64-bit only>
592 // iilf r8, <address_lo>
593 // basr r14, r8
594 #if V8_TARGET_ARCH_S390X
595  static constexpr int kCallSequenceLength = 14;
596 #else
597  static constexpr int kCallSequenceLength = 8;
598 #endif
599 
600  // ---------------------------------------------------------------------------
601  // Code generation
602 
603  template <class T, int size, int lo, int hi>
604  inline T getfield(T value) {
605  DCHECK(lo < hi);
606  DCHECK_GT(size, 0);
607  int mask = hi - lo;
608  int shift = size * 8 - hi;
609  uint32_t mask_value = (mask == 32) ? 0xffffffff : (1 << mask) - 1;
610  return (value & mask_value) << shift;
611  }
612 
613 #define DECLARE_S390_RIL_AB_INSTRUCTIONS(name, op_name, op_value) \
614  template <class R1> \
615  inline void name(R1 r1, const Operand& i2) { \
616  ril_format(op_name, r1.code(), i2.immediate()); \
617  }
618 #define DECLARE_S390_RIL_C_INSTRUCTIONS(name, op_name, op_value) \
619  inline void name(Condition m1, const Operand& i2) { \
620  ril_format(op_name, m1, i2.immediate()); \
621  }
622 
623  inline void ril_format(Opcode opcode, int f1, int f2) {
624  uint32_t op1 = opcode >> 4;
625  uint32_t op2 = opcode & 0xf;
626  emit6bytes(
627  getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
628  getfield<uint64_t, 6, 12, 16>(op2) | getfield<uint64_t, 6, 16, 48>(f2));
629  }
630  S390_RIL_A_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)
631  S390_RIL_B_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)
632  S390_RIL_C_OPCODE_LIST(DECLARE_S390_RIL_C_INSTRUCTIONS)
633 #undef DECLARE_S390_RIL_AB_INSTRUCTIONS
634 #undef DECLARE_S390_RIL_C_INSTRUCTIONS
635 
636 #define DECLARE_S390_RR_INSTRUCTIONS(name, op_name, op_value) \
637  inline void name(Register r1, Register r2) { \
638  rr_format(op_name, r1.code(), r2.code()); \
639  } \
640  inline void name(DoubleRegister r1, DoubleRegister r2) { \
641  rr_format(op_name, r1.code(), r2.code()); \
642  } \
643  inline void name(Condition m1, Register r2) { \
644  rr_format(op_name, m1, r2.code()); \
645  }
646 
647  inline void rr_format(Opcode opcode, int f1, int f2) {
648  emit2bytes(getfield<uint16_t, 2, 0, 8>(opcode) |
649  getfield<uint16_t, 2, 8, 12>(f1) |
650  getfield<uint16_t, 2, 12, 16>(f2));
651  }
652  S390_RR_OPCODE_LIST(DECLARE_S390_RR_INSTRUCTIONS)
653 #undef DECLARE_S390_RR_INSTRUCTIONS
654 
655 #define DECLARE_S390_RRD_INSTRUCTIONS(name, op_name, op_value) \
656  template <class R1, class R2, class R3> \
657  inline void name(R1 r1, R3 r3, R2 r2) { \
658  rrd_format(op_name, r1.code(), r3.code(), r2.code()); \
659  }
660  inline void rrd_format(Opcode opcode, int f1, int f2, int f3) {
661  emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) |
662  getfield<uint32_t, 4, 16, 20>(f1) |
663  getfield<uint32_t, 4, 24, 28>(f2) |
664  getfield<uint32_t, 4, 28, 32>(f3));
665  }
666  S390_RRD_OPCODE_LIST(DECLARE_S390_RRD_INSTRUCTIONS)
667 #undef DECLARE_S390_RRD_INSTRUCTIONS
668 
669 #define DECLARE_S390_RRE_INSTRUCTIONS(name, op_name, op_value) \
670  template <class R1, class R2> \
671  inline void name(R1 r1, R2 r2) { \
672  rre_format(op_name, r1.code(), r2.code()); \
673  }
674  inline void rre_format(Opcode opcode, int f1, int f2) {
675  emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) |
676  getfield<uint32_t, 4, 24, 28>(f1) |
677  getfield<uint32_t, 4, 28, 32>(f2));
678  }
679  S390_RRE_OPCODE_LIST(DECLARE_S390_RRE_INSTRUCTIONS)
680  // Special format
681  void lzdr(DoubleRegister r1) { rre_format(LZDR, r1.code(), 0); }
682 #undef DECLARE_S390_RRE_INSTRUCTIONS
683 
684 #define DECLARE_S390_RX_INSTRUCTIONS(name, op_name, op_value) \
685  template <class R1> \
686  inline void name(R1 r1, Register x2, Register b2, const Operand& d2) { \
687  rx_format(op_name, r1.code(), x2.code(), b2.code(), \
688  d2.immediate()); \
689  } \
690  template <class R1> \
691  inline void name(R1 r1, const MemOperand& opnd) { \
692  name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \
693  Operand(opnd.getDisplacement())); \
694  }
695 
696  inline void rx_format(Opcode opcode, int f1, int f2, int f3, int f4) {
697  DCHECK(is_uint8(opcode));
698  DCHECK(is_uint12(f4));
699  emit4bytes(getfield<uint32_t, 4, 0, 8>(opcode) |
700  getfield<uint32_t, 4, 8, 12>(f1) |
701  getfield<uint32_t, 4, 12, 16>(f2) |
702  getfield<uint32_t, 4, 16, 20>(f3) |
703  getfield<uint32_t, 4, 20, 32>(f4));
704  }
705  S390_RX_A_OPCODE_LIST(DECLARE_S390_RX_INSTRUCTIONS)
706 
707  void bc(Condition cond, const MemOperand& opnd) {
708  bc(cond, opnd.getIndexRegister(),
709  opnd.getBaseRegister(), Operand(opnd.getDisplacement()));
710  }
711  void bc(Condition cond, Register x2, Register b2, const Operand& d2) {
712  rx_format(BC, cond, x2.code(), b2.code(), d2.immediate());
713  }
714 #undef DECLARE_S390_RX_INSTRUCTIONS
715 
716 #define DECLARE_S390_RXY_INSTRUCTIONS(name, op_name, op_value) \
717  template <class R1, class R2> \
718  inline void name(R1 r1, R2 r2, Register b2, const Operand& d2) { \
719  rxy_format(op_name, r1.code(), r2.code(), b2.code(), d2.immediate()); \
720  } \
721  template <class R1> \
722  inline void name(R1 r1, const MemOperand& opnd) { \
723  name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \
724  Operand(opnd.getDisplacement())); \
725  }
726 
727  inline void rxy_format(Opcode opcode, int f1, int f2, int f3, int f4) {
728  DCHECK(is_uint16(opcode));
729  DCHECK(is_int20(f4));
730  emit6bytes(getfield<uint64_t, 6, 0, 8>(opcode >> 8) |
731  getfield<uint64_t, 6, 8, 12>(f1) |
732  getfield<uint64_t, 6, 12, 16>(f2) |
733  getfield<uint64_t, 6, 16, 20>(f3) |
734  getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
735  getfield<uint64_t, 6, 32, 40>(f4 >> 12) |
736  getfield<uint64_t, 6, 40, 48>(opcode & 0x00ff));
737  }
738  S390_RXY_A_OPCODE_LIST(DECLARE_S390_RXY_INSTRUCTIONS)
739 
740  void pfd(Condition cond, const MemOperand& opnd) {
741  pfd(cond, opnd.getIndexRegister(),
742  opnd.getBaseRegister(), Operand(opnd.getDisplacement()));
743  }
744  void pfd(Condition cond, Register x2, Register b2, const Operand& d2) {
745  rxy_format(PFD, cond, x2.code(), b2.code(), d2.immediate());
746  }
747 #undef DECLARE_S390_RXY_INSTRUCTIONS
748 
749 
750 inline void rsy_format(Opcode op, int f1, int f2, int f3, int f4) {
751  DCHECK(is_int20(f4));
752  DCHECK(is_uint16(op));
753  uint64_t code = (getfield<uint64_t, 6, 0, 8>(op >> 8) |
754  getfield<uint64_t, 6, 8, 12>(f1) |
755  getfield<uint64_t, 6, 12, 16>(f2) |
756  getfield<uint64_t, 6, 16, 20>(f3) |
757  getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
758  getfield<uint64_t, 6, 32, 40>(f4 >> 12) |
759  getfield<uint64_t, 6, 40, 48>(op & 0xff));
760  emit6bytes(code);
761 }
762 
763 #define DECLARE_S390_RSY_A_INSTRUCTIONS(name, op_name, op_value) \
764  void name(Register r1, Register r3, Register b2, \
765  const Operand& d2 = Operand::Zero()) { \
766  rsy_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate()); \
767  } \
768  void name(Register r1, Register r3, Operand d2) { \
769  name(r1, r3, r0, d2); \
770  } \
771  void name(Register r1, Register r3, const MemOperand& opnd) { \
772  name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
773  }
774  S390_RSY_A_OPCODE_LIST(DECLARE_S390_RSY_A_INSTRUCTIONS);
775 #undef DECLARE_S390_RSY_A_INSTRUCTIONS
776 
777 #define DECLARE_S390_RSY_B_INSTRUCTIONS(name, op_name, op_value) \
778  void name(Register r1, Condition m3, Register b2, const Operand& d2) { \
779  rsy_format(op_name, r1.code(), m3, b2.code(), d2.immediate()); \
780  } \
781  void name(Register r1, Condition m3, const MemOperand& opnd) { \
782  name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
783  }
784  S390_RSY_B_OPCODE_LIST(DECLARE_S390_RSY_B_INSTRUCTIONS);
785 #undef DECLARE_S390_RSY_B_INSTRUCTIONS
786 
787 
788 inline void rs_format(Opcode op, int f1, int f2, int f3, const int f4) {
789  uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
790  getfield<uint32_t, 4, 8, 12>(f1) |
791  getfield<uint32_t, 4, 12, 16>(f2) |
792  getfield<uint32_t, 4, 16, 20>(f3) |
793  getfield<uint32_t, 4, 20, 32>(f4);
794  emit4bytes(code);
795 }
796 
797 #define DECLARE_S390_RS_A_INSTRUCTIONS(name, op_name, op_value) \
798  void name(Register r1, Register r3, Register b2, const Operand& d2) { \
799  rs_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate()); \
800  } \
801  void name(Register r1, Register r3, const MemOperand& opnd) { \
802  name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
803  }
804  S390_RS_A_OPCODE_LIST(DECLARE_S390_RS_A_INSTRUCTIONS);
805 #undef DECLARE_S390_RS_A_INSTRUCTIONS
806 
807 #define DECLARE_S390_RS_B_INSTRUCTIONS(name, op_name, op_value) \
808  void name(Register r1, Condition m3, Register b2, const Operand& d2) { \
809  rs_format(op_name, r1.code(), m3, b2.code(), d2.immediate()); \
810  } \
811  void name(Register r1, Condition m3, const MemOperand& opnd) { \
812  name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
813  }
814  S390_RS_B_OPCODE_LIST(DECLARE_S390_RS_B_INSTRUCTIONS);
815 #undef DECLARE_S390_RS_B_INSTRUCTIONS
816 
817 #define DECLARE_S390_RS_SHIFT_FORMAT(name, opcode) \
818  void name(Register r1, Register r2, const Operand& opnd = \
819  Operand::Zero()) { \
820  DCHECK(r2 != r0); \
821  rs_format(opcode, r1.code(), r0.code(), r2.code(), opnd.immediate()); \
822  } \
823  void name(Register r1, const Operand& opnd) { \
824  rs_format(opcode, r1.code(), r0.code(), r0.code(), opnd.immediate()); \
825  }
826  DECLARE_S390_RS_SHIFT_FORMAT(sll, SLL)
827  DECLARE_S390_RS_SHIFT_FORMAT(srl, SRL)
828  DECLARE_S390_RS_SHIFT_FORMAT(sla, SLA)
829  DECLARE_S390_RS_SHIFT_FORMAT(sra, SRA)
830  DECLARE_S390_RS_SHIFT_FORMAT(sldl, SLDL)
831  DECLARE_S390_RS_SHIFT_FORMAT(srda, SRDA)
832  DECLARE_S390_RS_SHIFT_FORMAT(srdl, SRDL)
833 #undef DECLARE_S390_RS_SHIFT_FORMAT
834 
835 
836 inline void rxe_format(Opcode op, int f1, int f2, int f3, int f4, int f5 = 0) {
837  DCHECK(is_uint12(f4));
838  DCHECK(is_uint16(op));
839  uint64_t code = (getfield<uint64_t, 6, 0, 8>(op >> 8) |
840  getfield<uint64_t, 6, 8, 12>(f1) |
841  getfield<uint64_t, 6, 12, 16>(f2) |
842  getfield<uint64_t, 6, 16, 20>(f3) |
843  getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
844  getfield<uint64_t, 6, 32, 36>(f5) |
845  getfield<uint64_t, 6, 40, 48>(op & 0xff));
846  emit6bytes(code);
847 }
848 
849 #define DECLARE_S390_RXE_INSTRUCTIONS(name, op_name, op_value) \
850  void name(Register r1, Register x2, Register b2, const Operand& d2, \
851  Condition m3 = static_cast<Condition>(0)) { \
852  rxe_format(op_name, r1.code(), x2.code(), b2.code(), d2.immediate(), \
853  m3); \
854  } \
855  template<class _R1Type> \
856  void name(_R1Type r1, const MemOperand& opnd) { \
857  name(Register::from_code(r1.code()), opnd.rx(), opnd.rb(), \
858  Operand(opnd.offset())); \
859  }
860  S390_RXE_OPCODE_LIST(DECLARE_S390_RXE_INSTRUCTIONS);
861 #undef DECLARE_S390_RXE_INSTRUCTIONS
862 
863 
864 inline void ri_format(Opcode opcode, int f1, int f2) {
865  uint32_t op1 = opcode >> 4;
866  uint32_t op2 = opcode & 0xf;
867  emit4bytes(getfield<uint32_t, 4, 0, 8>(op1) |
868  getfield<uint32_t, 4, 8, 12>(f1) |
869  getfield<uint32_t, 4, 12, 16>(op2) |
870  getfield<uint32_t, 4, 16, 32>(f2));
871 }
872 
873 #define DECLARE_S390_RI_A_INSTRUCTIONS(name, op_name, op_value) \
874  void name(Register r, const Operand& i2) { \
875  DCHECK(is_uint12(op_name)); \
876  DCHECK(is_uint16(i2.immediate()) || is_int16(i2.immediate())); \
877  ri_format(op_name, r.code(), i2.immediate()); \
878  }
879  S390_RI_A_OPCODE_LIST(DECLARE_S390_RI_A_INSTRUCTIONS);
880 #undef DECLARE_S390_RI_A_INSTRUCTIONS
881 
882 #define DECLARE_S390_RI_B_INSTRUCTIONS(name, op_name, op_value) \
883  void name(Register r1, const Operand& imm) { \
884  /* 2nd argument encodes # of halfwords, so divide by 2. */ \
885  int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2; \
886  Operand halfwordOp = Operand(numHalfwords); \
887  halfwordOp.setBits(16); \
888  ri_format(op_name, r1.code(), halfwordOp.immediate()); \
889  }
890  S390_RI_B_OPCODE_LIST(DECLARE_S390_RI_B_INSTRUCTIONS);
891 #undef DECLARE_S390_RI_B_INSTRUCTIONS
892 
893 #define DECLARE_S390_RI_C_INSTRUCTIONS(name, op_name, op_value) \
894  void name(Condition m, const Operand& i2) { \
895  DCHECK(is_uint12(op_name)); \
896  DCHECK(is_uint4(m)); \
897  DCHECK(op_name == BRC ? \
898  is_int16(i2.immediate()) : is_uint16(i2.immediate())); \
899  ri_format(op_name, m, i2.immediate()); \
900  }
901  S390_RI_C_OPCODE_LIST(DECLARE_S390_RI_C_INSTRUCTIONS);
902 #undef DECLARE_S390_RI_C_INSTRUCTIONS
903 
904 
905 inline void rrf_format(Opcode op, int f1, int f2, int f3, int f4) {
906  uint32_t code = getfield<uint32_t, 4, 0, 16>(op) |
907  getfield<uint32_t, 4, 16, 20>(f1) |
908  getfield<uint32_t, 4, 20, 24>(f2) |
909  getfield<uint32_t, 4, 24, 28>(f3) |
910  getfield<uint32_t, 4, 28, 32>(f4);
911  emit4bytes(code);
912 }
913 
914 #define DECLARE_S390_RRF_A_INSTRUCTIONS(name, op_name, op_value) \
915  void name(Register r1, Condition m4, Register r2, Register r3) { \
916  rrf_format(op_name, r3.code(), m4, r1.code(), r2.code()); \
917  } \
918  void name(Register r1, Register r2, Register r3) { \
919  name(r1, Condition(0), r2, r3); \
920  }
921  S390_RRF_A_OPCODE_LIST(DECLARE_S390_RRF_A_INSTRUCTIONS);
922 #undef DECLARE_S390_RRF_A_INSTRUCTIONS
923 
924 
925 #define DECLARE_S390_RRF_B_INSTRUCTIONS(name, op_name, op_value) \
926  void name(Register r1, Condition m4, Register r2, Register r3) { \
927  rrf_format(op_name, r3.code(), m4, r1.code(), r2.code()); \
928  } \
929  void name(Register r1, Register r2, Register r3) { \
930  name(r1, Condition(0), r2, r3); \
931  }
932  S390_RRF_B_OPCODE_LIST(DECLARE_S390_RRF_B_INSTRUCTIONS);
933 #undef DECLARE_S390_RRF_B_INSTRUCTIONS
934 
935 
936 #define DECLARE_S390_RRF_C_INSTRUCTIONS(name, op_name, op_value) \
937  template <class R1, class R2> \
938  void name(Condition m3, Condition m4, R1 r1, R2 r2) { \
939  rrf_format(op_name, m3, m4, r1.code(), r2.code()); \
940  } \
941  template <class R1, class R2> \
942  void name(Condition m3, R1 r1, R2 r2) { \
943  name(m3, Condition(0), r1, r2); \
944  }
945  S390_RRF_C_OPCODE_LIST(DECLARE_S390_RRF_C_INSTRUCTIONS);
946 #undef DECLARE_S390_RRF_C_INSTRUCTIONS
947 
948 
949 #define DECLARE_S390_RRF_D_INSTRUCTIONS(name, op_name, op_value) \
950  template <class R1, class R2> \
951  void name(Condition m3, Condition m4, R1 r1, R2 r2) { \
952  rrf_format(op_name, m3, m4, r1.code(), r2.code()); \
953  } \
954  template <class R1, class R2> \
955  void name(Condition m3, R1 r1, R2 r2) { \
956  name(m3, Condition(0), r1, r2); \
957  }
958  S390_RRF_D_OPCODE_LIST(DECLARE_S390_RRF_D_INSTRUCTIONS);
959 #undef DECLARE_S390_RRF_D_INSTRUCTIONS
960 
961 
962 #define DECLARE_S390_RRF_E_INSTRUCTIONS(name, op_name, op_value) \
963  template <class M3, class M4, class R1, class R2> \
964  void name(M3 m3, M4 m4, R1 r1, R2 r2) { \
965  rrf_format(op_name, m3, m4, r1.code(), r2.code()); \
966  } \
967  template <class M3, class R1, class R2> \
968  void name(M3 m3, R1 r1, R2 r2) { \
969  name(m3, Condition(0), r1, r2); \
970  }
971  S390_RRF_E_OPCODE_LIST(DECLARE_S390_RRF_E_INSTRUCTIONS);
972 #undef DECLARE_S390_RRF_E_INSTRUCTIONS
973 
974 enum FIDBRA_FLAGS {
975  FIDBRA_CURRENT_ROUNDING_MODE = 0,
976  FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0 = 1,
977  // ...
978  FIDBRA_ROUND_TOWARD_0 = 5,
979  FIDBRA_ROUND_TOWARD_POS_INF = 6,
980  FIDBRA_ROUND_TOWARD_NEG_INF = 7
981 };
982 
983 
984 inline void rsi_format(Opcode op, int f1, int f2, int f3) {
985  DCHECK(is_uint8(op));
986  DCHECK(is_uint16(f3) || is_int16(f3));
987  uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
988  getfield<uint32_t, 4, 8, 12>(f1) |
989  getfield<uint32_t, 4, 12, 16>(f2) |
990  getfield<uint32_t, 4, 16, 32>(f3);
991  emit4bytes(code);
992 }
993 
994 #define DECLARE_S390_RSI_INSTRUCTIONS(name, op_name, op_value) \
995  void name(Register r1, Register r3, const Operand& i2) { \
996  rsi_format(op_name, r1.code(), r3.code(), i2.immediate()); \
997  }
998  S390_RSI_OPCODE_LIST(DECLARE_S390_RSI_INSTRUCTIONS);
999 #undef DECLARE_S390_RSI_INSTRUCTIONS
1000 
1001 
1002 inline void rsl_format(Opcode op, uint16_t f1, int f2, int f3, int f4,
1003  int f5) {
1004  DCHECK(is_uint16(op));
1005  uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1006  getfield<uint64_t, 6, 8, 16>(f1) |
1007  getfield<uint64_t, 6, 16, 20>(f2) |
1008  getfield<uint64_t, 6, 20, 32>(f3) |
1009  getfield<uint64_t, 6, 32, 36>(f4) |
1010  getfield<uint64_t, 6, 36, 40>(f5) |
1011  getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1012  emit6bytes(code);
1013 }
1014 
1015 #define DECLARE_S390_RSL_A_INSTRUCTIONS(name, op_name, op_value) \
1016  void name(const Operand& l1, Register b1, const Operand& d1) { \
1017  uint16_t L = static_cast<uint16_t>(l1.immediate() << 8); \
1018  rsl_format(op_name, L, b1.code(), d1.immediate(), 0, 0); \
1019  }
1020  S390_RSL_A_OPCODE_LIST(DECLARE_S390_RSL_A_INSTRUCTIONS);
1021 #undef DECLARE_S390_RSL_A_INSTRUCTIONS
1022 
1023 #define DECLARE_S390_RSL_B_INSTRUCTIONS(name, op_name, op_value) \
1024  void name(const Operand& l2, Register b2, const Operand& d2, \
1025  Register r1, Condition m3) { \
1026  uint16_t L = static_cast<uint16_t>(l2.immediate()); \
1027  rsl_format(op_name, L, b2.code(), d2.immediate(), r1.code(), m3); \
1028  }
1029  S390_RSL_B_OPCODE_LIST(DECLARE_S390_RSL_B_INSTRUCTIONS);
1030 #undef DECLARE_S390_RSL_B_INSTRUCTIONS
1031 
1032 
1033 inline void s_format(Opcode op, int f1, int f2) {
1034  DCHECK_NE(op & 0xff00, 0);
1035  DCHECK(is_uint12(f2));
1036  uint32_t code = getfield<uint32_t, 4, 0, 16>(op) |
1037  getfield<uint32_t, 4, 16, 20>(f1) |
1038  getfield<uint32_t, 4, 20, 32>(f2);
1039  emit4bytes(code);
1040 }
1041 
1042 #define DECLARE_S390_S_INSTRUCTIONS(name, op_name, op_value) \
1043  void name(Register b1, const Operand& d2) { \
1044  Opcode op = op_name; \
1045  if ((op & 0xFF00) == 0) { \
1046  op = (Opcode)(op << 8); \
1047  } \
1048  s_format(op, b1.code(), d2.immediate()); \
1049  } \
1050  void name(const MemOperand& opnd) { \
1051  Operand d2 = Operand(opnd.getDisplacement()); \
1052  name(opnd.getBaseRegister(), d2); \
1053  }
1054  S390_S_OPCODE_LIST(DECLARE_S390_S_INSTRUCTIONS);
1055 #undef DECLARE_S390_S_INSTRUCTIONS
1056 
1057 
1058 inline void si_format(Opcode op, int f1, int f2, int f3) {
1059  uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
1060  getfield<uint32_t, 4, 8, 16>(f1) |
1061  getfield<uint32_t, 4, 16, 20>(f2) |
1062  getfield<uint32_t, 4, 20, 32>(f3);
1063  emit4bytes(code);
1064 }
1065 
1066 #define DECLARE_S390_SI_INSTRUCTIONS(name, op_name, op_value) \
1067  void name(const Operand& i2, Register b1, const Operand& d1) { \
1068  si_format(op_name, i2.immediate(), b1.code(), d1.immediate()); \
1069  } \
1070  void name(const MemOperand& opnd, const Operand& i2) { \
1071  name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
1072  }
1073  S390_SI_OPCODE_LIST(DECLARE_S390_SI_INSTRUCTIONS);
1074 #undef DECLARE_S390_SI_INSTRUCTIONS
1075 
1076 
1077 inline void siy_format(Opcode op, int f1, int f2, int f3) {
1078  DCHECK(is_uint20(f3) || is_int20(f3));
1079  DCHECK(is_uint16(op));
1080  DCHECK(is_uint8(f1) || is_int8(f1));
1081  uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1082  getfield<uint64_t, 6, 8, 16>(f1) |
1083  getfield<uint64_t, 6, 16, 20>(f2) |
1084  getfield<uint64_t, 6, 20, 32>(f3) |
1085  getfield<uint64_t, 6, 32, 40>(f3 >> 12) |
1086  getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1087  emit6bytes(code);
1088 }
1089 
1090 #define DECLARE_S390_SIY_INSTRUCTIONS(name, op_name, op_value) \
1091  void name(const Operand& i2, Register b1, const Operand& d1) { \
1092  siy_format(op_name, i2.immediate(), b1.code(), d1.immediate()); \
1093  } \
1094  void name(const MemOperand& opnd, const Operand& i2) { \
1095  name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
1096  }
1097  S390_SIY_OPCODE_LIST(DECLARE_S390_SIY_INSTRUCTIONS);
1098 #undef DECLARE_S390_SIY_INSTRUCTIONS
1099 
1100 
1101 inline void rrs_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
1102  DCHECK(is_uint12(f4));
1103  DCHECK(is_uint16(op));
1104  uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1105  getfield<uint64_t, 6, 8, 12>(f1) |
1106  getfield<uint64_t, 6, 12, 16>(f2) |
1107  getfield<uint64_t, 6, 16, 20>(f3) |
1108  getfield<uint64_t, 6, 20, 32>(f4) |
1109  getfield<uint64_t, 6, 32, 36>(f5) |
1110  getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1111  emit6bytes(code);
1112 }
1113 
1114 #define DECLARE_S390_RRS_INSTRUCTIONS(name, op_name, op_value) \
1115  void name(Register r1, Register r2, Register b4, const Operand& d4, \
1116  Condition m3) { \
1117  rrs_format(op_name, r1.code(), r2.code(), b4.code(), d4.immediate(), \
1118  m3); \
1119  } \
1120  void name(Register r1, Register r2, Condition m3, \
1121  const MemOperand& opnd) { \
1122  name(r1, r2, opnd.getBaseRegister(), \
1123  Operand(opnd.getDisplacement()), m3); \
1124  }
1125  S390_RRS_OPCODE_LIST(DECLARE_S390_RRS_INSTRUCTIONS);
1126 #undef DECLARE_S390_RRS_INSTRUCTIONS
1127 
1128 
1129 inline void ris_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
1130  DCHECK(is_uint12(f3));
1131  DCHECK(is_uint16(op));
1132  DCHECK(is_uint8(f5));
1133  uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1134  getfield<uint64_t, 6, 8, 12>(f1) |
1135  getfield<uint64_t, 6, 12, 16>(f2) |
1136  getfield<uint64_t, 6, 16, 20>(f3) |
1137  getfield<uint64_t, 6, 20, 32>(f4) |
1138  getfield<uint64_t, 6, 32, 40>(f5) |
1139  getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1140  emit6bytes(code);
1141 }
1142 
1143 #define DECLARE_S390_RIS_INSTRUCTIONS(name, op_name, op_value) \
1144  void name(Register r1, Condition m3, Register b4, const Operand& d4, \
1145  const Operand& i2) { \
1146  ris_format(op_name, r1.code(), m3, b4.code(), d4.immediate(), \
1147  i2.immediate()); \
1148  } \
1149  void name(Register r1, const Operand& i2, Condition m3, \
1150  const MemOperand& opnd) { \
1151  name(r1, m3, opnd.getBaseRegister(), \
1152  Operand(opnd.getDisplacement()), i2); \
1153  }
1154  S390_RIS_OPCODE_LIST(DECLARE_S390_RIS_INSTRUCTIONS);
1155 #undef DECLARE_S390_RIS_INSTRUCTIONS
1156 
1157 
1158 inline void sil_format(Opcode op, int f1, int f2, int f3) {
1159  DCHECK(is_uint12(f2));
1160  DCHECK(is_uint16(op));
1161  DCHECK(is_uint16(f3));
1162  uint64_t code = getfield<uint64_t, 6, 0, 16>(op) |
1163  getfield<uint64_t, 6, 16, 20>(f1) |
1164  getfield<uint64_t, 6, 20, 32>(f2) |
1165  getfield<uint64_t, 6, 32, 48>(f3);
1166  emit6bytes(code);
1167 }
1168 
1169 #define DECLARE_S390_SIL_INSTRUCTIONS(name, op_name, op_value) \
1170  void name(Register b1, const Operand& d1, const Operand& i2) { \
1171  sil_format(op_name, b1.code(), d1.immediate(), i2.immediate()); \
1172  } \
1173  void name(const MemOperand& opnd, const Operand& i2) { \
1174  name(opnd.getBaseRegister(), Operand(opnd.getDisplacement()), i2); \
1175  }
1176  S390_SIL_OPCODE_LIST(DECLARE_S390_SIL_INSTRUCTIONS);
1177 #undef DECLARE_S390_SIL_INSTRUCTIONS
1178 
1179 
1180 inline void rie_d_format(Opcode opcode, int f1, int f2, int f3, int f4) {
1181  uint32_t op1 = opcode >> 8;
1182  uint32_t op2 = opcode & 0xff;
1183  uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
1184  getfield<uint64_t, 6, 8, 12>(f1) |
1185  getfield<uint64_t, 6, 12, 16>(f2) |
1186  getfield<uint64_t, 6, 16, 32>(f3) |
1187  getfield<uint64_t, 6, 32, 40>(f4) |
1188  getfield<uint64_t, 6, 40, 48>(op2);
1189  emit6bytes(code);
1190 }
1191 
1192 #define DECLARE_S390_RIE_D_INSTRUCTIONS(name, op_name, op_value) \
1193  void name(Register r1, Register r3, const Operand& i2) { \
1194  rie_d_format(op_name, r1.code(), r3.code(), i2.immediate(), 0); \
1195  }
1196  S390_RIE_D_OPCODE_LIST(DECLARE_S390_RIE_D_INSTRUCTIONS)
1197 #undef DECLARE_S390_RIE_D_INSTRUCTIONS
1198 
1199 
1200 inline void rie_e_format(Opcode opcode, int f1, int f2, int f3) {
1201  uint32_t op1 = opcode >> 8;
1202  uint32_t op2 = opcode & 0xff;
1203  uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
1204  getfield<uint64_t, 6, 8, 12>(f1) |
1205  getfield<uint64_t, 6, 12, 16>(f2) |
1206  getfield<uint64_t, 6, 16, 32>(f3) |
1207  getfield<uint64_t, 6, 40, 48>(op2);
1208  emit6bytes(code);
1209 }
1210 
1211 #define DECLARE_S390_RIE_E_INSTRUCTIONS(name, op_name, op_value) \
1212  void name(Register r1, Register r3, const Operand& i2) { \
1213  rie_e_format(op_name, r1.code(), r3.code(), i2.immediate()); \
1214  }
1215  S390_RIE_E_OPCODE_LIST(DECLARE_S390_RIE_E_INSTRUCTIONS)
1216 #undef DECLARE_S390_RIE_E_INSTRUCTIONS
1217 
1218 
1219 inline void rie_f_format(Opcode opcode, int f1, int f2, int f3, int f4,
1220  int f5) {
1221  uint32_t op1 = opcode >> 8;
1222  uint32_t op2 = opcode & 0xff;
1223  uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
1224  getfield<uint64_t, 6, 8, 12>(f1) |
1225  getfield<uint64_t, 6, 12, 16>(f2) |
1226  getfield<uint64_t, 6, 16, 24>(f3) |
1227  getfield<uint64_t, 6, 24, 32>(f4) |
1228  getfield<uint64_t, 6, 32, 40>(f5) |
1229  getfield<uint64_t, 6, 40, 48>(op2);
1230  emit6bytes(code);
1231 }
1232 
1233 #define DECLARE_S390_RIE_F_INSTRUCTIONS(name, op_name, op_value) \
1234  void name(Register dst, Register src, const Operand& startBit, \
1235  const Operand& endBit, const Operand& shiftAmt) { \
1236  DCHECK(is_uint8(startBit.immediate())); \
1237  DCHECK(is_uint8(endBit.immediate())); \
1238  DCHECK(is_uint8(shiftAmt.immediate())); \
1239  rie_f_format(op_name, dst.code(), src.code(), startBit.immediate(), \
1240  endBit.immediate(), shiftAmt.immediate()); \
1241  }
1242  S390_RIE_F_OPCODE_LIST(DECLARE_S390_RIE_F_INSTRUCTIONS)
1243 #undef DECLARE_S390_RIE_F_INSTRUCTIONS
1244 
1245 
1246 inline void ss_a_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
1247  DCHECK(is_uint12(f5));
1248  DCHECK(is_uint12(f3));
1249  DCHECK(is_uint8(f1));
1250  DCHECK(is_uint8(op));
1251  uint64_t code = getfield<uint64_t, 6, 0, 8>(op) |
1252  getfield<uint64_t, 6, 8, 16>(f1) |
1253  getfield<uint64_t, 6, 16, 20>(f2) |
1254  getfield<uint64_t, 6, 20, 32>(f3) |
1255  getfield<uint64_t, 6, 32, 36>(f4) |
1256  getfield<uint64_t, 6, 36, 48>(f5);
1257  emit6bytes(code);
1258 }
1259 
1260 #define DECLARE_S390_SS_A_INSTRUCTIONS(name, op_name, op_value) \
1261  void name(Register b1, const Operand& d1, Register b2, \
1262  const Operand& d2, const Operand& length) { \
1263  ss_a_format(op_name, length.immediate(), b1.code(), d1.immediate(), \
1264  b2.code(), d2.immediate()); \
1265  } \
1266  void name(const MemOperand& opnd1, const MemOperand& opnd2, \
1267  const Operand& length) { \
1268  ss_a_format(op_name, length.immediate(), \
1269  opnd1.getBaseRegister().code(), \
1270  opnd1.getDisplacement(), opnd2.getBaseRegister().code(), \
1271  opnd2.getDisplacement()); \
1272  }
1273  S390_SS_A_OPCODE_LIST(DECLARE_S390_SS_A_INSTRUCTIONS)
1274 #undef DECLARE_S390_SS_A_INSTRUCTIONS
1275 
1276 
1277  // Helper for unconditional branch to Label with update to save register
1278  void b(Register r, Label* l) {
1279  int32_t halfwords = branch_offset(l) / 2;
1280  brasl(r, Operand(halfwords));
1281  }
1282 
1283  // Conditional Branch Instruction - Generates either BRC / BRCL
1284  void branchOnCond(Condition c, int branch_offset, bool is_bound = false);
1285 
1286  // Helpers for conditional branch to Label
1287  void b(Condition cond, Label* l, Label::Distance dist = Label::kFar) {
1288  branchOnCond(cond, branch_offset(l),
1289  l->is_bound() || (dist == Label::kNear));
1290  }
1291 
1292  void bc_short(Condition cond, Label* l, Label::Distance dist = Label::kFar) {
1293  b(cond, l, Label::kNear);
1294  }
1295  // Helpers for conditional branch to Label
1296  void beq(Label* l, Label::Distance dist = Label::kFar) { b(eq, l, dist); }
1297  void bne(Label* l, Label::Distance dist = Label::kFar) { b(ne, l, dist); }
1298  void blt(Label* l, Label::Distance dist = Label::kFar) { b(lt, l, dist); }
1299  void ble(Label* l, Label::Distance dist = Label::kFar) { b(le, l, dist); }
1300  void bgt(Label* l, Label::Distance dist = Label::kFar) { b(gt, l, dist); }
1301  void bge(Label* l, Label::Distance dist = Label::kFar) { b(ge, l, dist); }
1302  void b(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); }
1303  void jmp(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); }
1304  void bunordered(Label* l, Label::Distance dist = Label::kFar) {
1305  b(unordered, l, dist);
1306  }
1307  void bordered(Label* l, Label::Distance dist = Label::kFar) {
1308  b(ordered, l, dist);
1309  }
1310 
1311  // Helpers for conditional indirect branch off register
1312  void b(Condition cond, Register r) { bcr(cond, r); }
1313  void beq(Register r) { b(eq, r); }
1314  void bne(Register r) { b(ne, r); }
1315  void blt(Register r) { b(lt, r); }
1316  void ble(Register r) { b(le, r); }
1317  void bgt(Register r) { b(gt, r); }
1318  void bge(Register r) { b(ge, r); }
1319  void b(Register r) { b(al, r); }
1320  void jmp(Register r) { b(al, r); }
1321  void bunordered(Register r) { b(unordered, r); }
1322  void bordered(Register r) { b(ordered, r); }
1323 
1324  // wrappers around asm instr
1325  void brxh(Register dst, Register inc, Label* L) {
1326  int offset_halfwords = branch_offset(L) / 2;
1327  CHECK(is_int16(offset_halfwords));
1328  brxh(dst, inc, Operand(offset_halfwords));
1329  }
1330 
1331  void brxhg(Register dst, Register inc, Label* L) {
1332  int offset_halfwords = branch_offset(L) / 2;
1333  CHECK(is_int16(offset_halfwords));
1334  brxhg(dst, inc, Operand(offset_halfwords));
1335  }
1336 
1337  template <class R1, class R2>
1338  void ledbr(R1 r1, R2 r2) {
1339  ledbra(Condition(0), Condition(0), r1, r2);
1340  }
1341 
1342  template <class R1, class R2>
1343  void cdfbr(R1 r1, R2 r2) {
1344  cdfbra(Condition(0), Condition(0), r1, r2);
1345  }
1346 
1347  template <class R1, class R2>
1348  void cdgbr(R1 r1, R2 r2) {
1349  cdgbra(Condition(0), Condition(0), r1, r2);
1350  }
1351 
1352  template <class R1, class R2>
1353  void cegbr(R1 r1, R2 r2) {
1354  cegbra(Condition(0), Condition(0), r1, r2);
1355  }
1356 
1357  template <class R1, class R2>
1358  void cgebr(Condition m3, R1 r1, R2 r2) {
1359  cgebra(m3, Condition(0), r1, r2);
1360  }
1361 
1362  template <class R1, class R2>
1363  void cgdbr(Condition m3, R1 r1, R2 r2) {
1364  cgdbra(m3, Condition(0), r1, r2);
1365  }
1366 
1367  template <class R1, class R2>
1368  void cfdbr(Condition m3, R1 r1, R2 r2) {
1369  cfdbra(m3, Condition(0), r1, r2);
1370  }
1371 
1372  template <class R1, class R2>
1373  void cfebr(Condition m3, R1 r1, R2 r2) {
1374  cfebra(m3, Condition(0), r1, r2);
1375  }
1376 
1377  // ---------------------------------------------------------------------------
1378  // Code generation
1379 
1380  // Insert the smallest number of nop instructions
1381  // possible to align the pc offset to a multiple
1382  // of m. m must be a power of 2 (>= 4).
1383  void Align(int m);
1384  // Insert the smallest number of zero bytes possible to align the pc offset
1385  // to a mulitple of m. m must be a power of 2 (>= 2).
1386  void DataAlign(int m);
1387  // Aligns code to something that's optimal for a jump target for the platform.
1388  void CodeTargetAlign();
1389 
1390  void breakpoint(bool do_print) {
1391  if (do_print) {
1392  PrintF("DebugBreak is inserted to %p\n", static_cast<void*>(pc_));
1393  }
1394 #if V8_HOST_ARCH_64_BIT
1395  int64_t value = reinterpret_cast<uint64_t>(&v8::base::OS::DebugBreak);
1396  int32_t hi_32 = static_cast<int64_t>(value) >> 32;
1397  int32_t lo_32 = static_cast<int32_t>(value);
1398 
1399  iihf(r1, Operand(hi_32));
1400  iilf(r1, Operand(lo_32));
1401 #else
1402  iilf(r1, Operand(reinterpret_cast<uint32_t>(&v8::base::OS::DebugBreak)));
1403 #endif
1404  basr(r14, r1);
1405  }
1406 
1407  void call(Handle<Code> target, RelocInfo::Mode rmode);
1408  void call(CodeStub* stub);
1409  void jump(Handle<Code> target, RelocInfo::Mode rmode, Condition cond);
1410 
1411 // S390 instruction generation
1412 #define DECLARE_VRR_A_INSTRUCTIONS(name, opcode_name, opcode_value) \
1413  void name(DoubleRegister v1, DoubleRegister v2, Condition m5, Condition m4, \
1414  Condition m3) { \
1415  uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
1416  (static_cast<uint64_t>(v1.code())) * B36 | \
1417  (static_cast<uint64_t>(v2.code())) * B32 | \
1418  (static_cast<uint64_t>(m5 & 0xF)) * B20 | \
1419  (static_cast<uint64_t>(m4 & 0xF)) * B16 | \
1420  (static_cast<uint64_t>(m3 & 0xF)) * B12 | \
1421  (static_cast<uint64_t>(opcode_value & 0x00FF)); \
1422  emit6bytes(code); \
1423  }
1424  S390_VRR_A_OPCODE_LIST(DECLARE_VRR_A_INSTRUCTIONS)
1425 #undef DECLARE_VRR_A_INSTRUCTIONS
1426 
1427 #define DECLARE_VRR_C_INSTRUCTIONS(name, opcode_name, opcode_value) \
1428  void name(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3, \
1429  Condition m6, Condition m5, Condition m4) { \
1430  uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
1431  (static_cast<uint64_t>(v1.code())) * B36 | \
1432  (static_cast<uint64_t>(v2.code())) * B32 | \
1433  (static_cast<uint64_t>(v3.code())) * B28 | \
1434  (static_cast<uint64_t>(m6 & 0xF)) * B20 | \
1435  (static_cast<uint64_t>(m5 & 0xF)) * B16 | \
1436  (static_cast<uint64_t>(m4 & 0xF)) * B12 | \
1437  (static_cast<uint64_t>(opcode_value & 0x00FF)); \
1438  emit6bytes(code); \
1439  }
1440  S390_VRR_C_OPCODE_LIST(DECLARE_VRR_C_INSTRUCTIONS)
1441 #undef DECLARE_VRR_C_INSTRUCTIONS
1442 
1443  // Single Element format
1444  void vfa(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1445  vfa(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1446  static_cast<Condition>(3));
1447  }
1448  void vfs(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1449  vfs(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1450  static_cast<Condition>(3));
1451  }
1452  void vfm(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1453  vfm(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1454  static_cast<Condition>(3));
1455  }
1456  void vfd(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1457  vfd(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1458  static_cast<Condition>(3));
1459  }
1460 
1461  // Load Address Instructions
1462  void larl(Register r, Label* l);
1463 
1464  // Exception-generating instructions and debugging support
1465  void stop(const char* msg, Condition cond = al,
1466  int32_t code = kDefaultStopCode, CRegister cr = cr7);
1467 
1468  void bkpt(uint32_t imm16); // v5 and above
1469 
1470  // Different nop operations are used by the code generator to detect certain
1471  // states of the generated code.
1472  enum NopMarkerTypes {
1473  NON_MARKING_NOP = 0,
1474  GROUP_ENDING_NOP,
1475  DEBUG_BREAK_NOP,
1476  // IC markers.
1477  PROPERTY_ACCESS_INLINED,
1478  PROPERTY_ACCESS_INLINED_CONTEXT,
1479  PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1480  // Helper values.
1481  LAST_CODE_MARKER,
1482  FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1483  };
1484 
1485  void nop(int type = 0); // 0 is the default non-marking type.
1486 
1487  void dumy(int r1, int x2, int b2, int d2);
1488 
1489  // Check the code size generated from label to here.
1490  int SizeOfCodeGeneratedSince(Label* label) {
1491  return pc_offset() - label->pos();
1492  }
1493 
1494  // Record a comment relocation entry that can be used by a disassembler.
1495  // Use --code-comments to enable.
1496  void RecordComment(const char* msg);
1497 
1498  // Record a deoptimization reason that can be used by a log or cpu profiler.
1499  // Use --trace-deopt to enable.
1500  void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
1501  int id);
1502 
1503  // Writes a single byte or word of data in the code stream. Used
1504  // for inline tables, e.g., jump-tables.
1505  void db(uint8_t data);
1506  void dd(uint32_t data);
1507  void dq(uint64_t data);
1508  void dp(uintptr_t data);
1509 
1510  // Read/patch instructions
1511  SixByteInstr instr_at(int pos) {
1512  return Instruction::InstructionBits(buffer_ + pos);
1513  }
1514  template <typename T>
1515  void instr_at_put(int pos, T instr) {
1516  Instruction::SetInstructionBits<T>(buffer_ + pos, instr);
1517  }
1518 
1519  // Decodes instruction at pos, and returns its length
1520  int32_t instr_length_at(int pos) {
1521  return Instruction::InstructionLength(buffer_ + pos);
1522  }
1523 
1524  static SixByteInstr instr_at(byte* pc) {
1525  return Instruction::InstructionBits(pc);
1526  }
1527 
1528  static Condition GetCondition(Instr instr);
1529 
1530  static bool IsBranch(Instr instr);
1531 #if V8_TARGET_ARCH_S390X
1532  static bool Is64BitLoadIntoIP(SixByteInstr instr1, SixByteInstr instr2);
1533 #else
1534  static bool Is32BitLoadIntoIP(SixByteInstr instr);
1535 #endif
1536 
1537  static bool IsCmpRegister(Instr instr);
1538  static bool IsCmpImmediate(Instr instr);
1539  static bool IsNop(SixByteInstr instr, int type = NON_MARKING_NOP);
1540 
1541  // The code currently calls CheckBuffer() too often. This has the side
1542  // effect of randomly growing the buffer in the middle of multi-instruction
1543  // sequences.
1544  //
1545  // This function allows outside callers to check and grow the buffer
1546  void EnsureSpaceFor(int space_needed);
1547 
1548  void EmitRelocations();
1549  void emit_label_addr(Label* label);
1550 
1551  public:
1552  byte* buffer_pos() const { return buffer_; }
1553 
1554  protected:
1555  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1556 
1557  // Decode instruction(s) at pos and return backchain to previous
1558  // label reference or kEndOfChain.
1559  int target_at(int pos);
1560 
1561  // Patch instruction(s) at pos to target target_pos (e.g. branch)
1562  void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
1563 
1564  // Record reloc info for current pc_
1565  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1566 
1567  private:
1568  // Avoid overflows for displacements etc.
1569  static const int kMaximalBufferSize = 512 * MB;
1570 
1571  // Code generation
1572  // The relocation writer's position is at least kGap bytes below the end of
1573  // the generated instructions. This is so that multi-instruction sequences do
1574  // not have to check for overflow. The same is true for writes of large
1575  // relocation info entries.
1576  static constexpr int kGap = 32;
1577 
1578  // Relocation info generation
1579  // Each relocation is encoded as a variable size value
1580  static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1581  RelocInfoWriter reloc_info_writer;
1582  std::vector<DeferredRelocInfo> relocations_;
1583 
1584  // The bound position, before this we cannot do instruction elimination.
1585  int last_bound_pos_;
1586 
1587  // Code emission
1588  void CheckBuffer() {
1589  if (buffer_space() <= kGap) {
1590  GrowBuffer();
1591  }
1592  }
1593  void GrowBuffer(int needed = 0);
1594  inline void TrackBranch();
1595  inline void UntrackBranch();
1596 
1597  // Helper to emit the binary encoding of a 2 byte instruction
1598  void emit2bytes(uint16_t x) {
1599  CheckBuffer();
1600 #if V8_TARGET_LITTLE_ENDIAN
1601  // We need to emit instructions in big endian format as disassembler /
1602  // simulator require the first byte of the instruction in order to decode
1603  // the instruction length. Swap the bytes.
1604  x = ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8);
1605 #endif
1606  *reinterpret_cast<uint16_t*>(pc_) = x;
1607  pc_ += 2;
1608  }
1609 
1610  // Helper to emit the binary encoding of a 4 byte instruction
1611  void emit4bytes(uint32_t x) {
1612  CheckBuffer();
1613 #if V8_TARGET_LITTLE_ENDIAN
1614  // We need to emit instructions in big endian format as disassembler /
1615  // simulator require the first byte of the instruction in order to decode
1616  // the instruction length. Swap the bytes.
1617  x = ((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) |
1618  ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24);
1619 #endif
1620  *reinterpret_cast<uint32_t*>(pc_) = x;
1621  pc_ += 4;
1622  }
1623 
1624  // Helper to emit the binary encoding of a 6 byte instruction
1625  void emit6bytes(uint64_t x) {
1626  CheckBuffer();
1627 #if V8_TARGET_LITTLE_ENDIAN
1628  // We need to emit instructions in big endian format as disassembler /
1629  // simulator require the first byte of the instruction in order to decode
1630  // the instruction length. Swap the bytes.
1631  x = (static_cast<uint64_t>(x & 0xFF) << 40) |
1632  (static_cast<uint64_t>((x >> 8) & 0xFF) << 32) |
1633  (static_cast<uint64_t>((x >> 16) & 0xFF) << 24) |
1634  (static_cast<uint64_t>((x >> 24) & 0xFF) << 16) |
1635  (static_cast<uint64_t>((x >> 32) & 0xFF) << 8) |
1636  (static_cast<uint64_t>((x >> 40) & 0xFF));
1637  x |= (*reinterpret_cast<uint64_t*>(pc_) >> 48) << 48;
1638 #else
1639  // We need to pad two bytes of zeros in order to get the 6-bytes
1640  // stored from low address.
1641  x = x << 16;
1642  x |= *reinterpret_cast<uint64_t*>(pc_) & 0xFFFF;
1643 #endif
1644  // It is safe to store 8-bytes, as CheckBuffer() guarantees we have kGap
1645  // space left over.
1646  *reinterpret_cast<uint64_t*>(pc_) = x;
1647  pc_ += 6;
1648  }
1649 
1650  // Labels
1651  void print(Label* L);
1652  int max_reach_from(int pos);
1653  void bind_to(Label* L, int pos);
1654  void next(Label* L);
1655 
1656  void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
1657 
1658  friend class RegExpMacroAssemblerS390;
1659  friend class RelocInfo;
1660  friend class EnsureSpace;
1661 };
1662 
1663 class EnsureSpace {
1664  public:
1665  explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1666 };
1667 
1668 // Define {RegisterName} methods for the register types.
1669 DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS);
1670 DEFINE_REGISTER_NAMES(DoubleRegister, DOUBLE_REGISTERS);
1671 
1672 
1673 } // namespace internal
1674 } // namespace v8
1675 
1676 #endif // V8_S390_ASSEMBLER_S390_H_
Definition: libplatform.h:13