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_CODEGEN_S390_ASSEMBLER_S390_H_
41#define V8_CODEGEN_S390_ASSEMBLER_S390_H_
42#include <stdio.h>
43#include <memory>
44#if V8_HOST_ARCH_S390
45// elf.h include is required for auxv check for STFLE facility used
46// for hardware detection, which is sensible only on s390 hosts.
47#include <elf.h>
48#endif
49
50#include <fcntl.h>
51#include <unistd.h>
52
53#include "src/codegen/assembler.h"
54#include "src/codegen/external-reference.h"
55#include "src/codegen/label.h"
56#include "src/codegen/s390/constants-s390.h"
57#include "src/codegen/s390/register-s390.h"
58#include "src/objects/smi.h"
59
60#define ABI_USES_FUNCTION_DESCRIPTORS 0
61
62#define ABI_PASSES_HANDLES_IN_REGS 1
63
64// ObjectPair is defined under runtime/runtime-util.h.
65// On 31-bit, ObjectPair == uint64_t.  ABI dictates long long
66//            be returned with the lower addressed half in r2
67//            and the higher addressed half in r3. (Returns in Regs)
68// On 64-bit, ObjectPair is a Struct.  ABI dictaes Structs be
69//            returned in a storage buffer allocated by the caller,
70//            with the address of this buffer passed as a hidden
71//            argument in r2. (Does NOT return in Regs)
72// For x86 linux, ObjectPair is returned in registers.
73#if V8_TARGET_ARCH_S390X
74#define ABI_RETURNS_OBJECTPAIR_IN_REGS 0
75#else
76#define ABI_RETURNS_OBJECTPAIR_IN_REGS 1
77#endif
78
79#define ABI_CALL_VIA_IP 1
80
81namespace v8 {
82namespace internal {
83
84class SafepointTableBuilder;
85
86// -----------------------------------------------------------------------------
87// Machine instruction Operands
88
89// Class Operand represents a shifter operand in data processing instructions
90// defining immediate numbers and masks
91class V8_EXPORT_PRIVATE Operand {
92 public:
93  // immediate
94  V8_INLINE explicit Operand(intptr_t immediate,
95                             RelocInfo::Mode rmode = RelocInfo::NO_INFO)
96      : rmode_(rmode) {
97    value_.immediate = immediate;
98  }
99  V8_INLINE static Operand Zero() { return Operand(static_cast<intptr_t>(0)); }
100  V8_INLINE explicit Operand(const ExternalReference& f)
101      : rmode_(RelocInfo::EXTERNAL_REFERENCE) {
102    value_.immediate = static_cast<intptr_t>(f.address());
103  }
104  explicit Operand(Handle<HeapObject> handle);
105  V8_INLINE explicit Operand(Smi value) : rmode_(RelocInfo::NO_INFO) {
106    value_.immediate = static_cast<intptr_t>(value.ptr());
107  }
108
109  // rm
110  V8_INLINE explicit Operand(Register rm);
111
112  static Operand EmbeddedNumber(double value);  // Smi or HeapNumber
113  static Operand EmbeddedStringConstant(const StringConstantBase* str);
114
115  // Return true if this is a register operand.
116  V8_INLINE bool is_reg() const { return rm_.is_valid(); }
117
118  bool must_output_reloc_info(const Assembler* assembler) const;
119
120  inline intptr_t immediate() const {
121    DCHECK(!rm_.is_valid());
122    DCHECK(!is_heap_object_request());
123    return value_.immediate;
124  }
125
126  HeapObjectRequest heap_object_request() const {
127    DCHECK(is_heap_object_request());
128    return value_.heap_object_request;
129  }
130
131  inline void setBits(int n) {
132    value_.immediate =
133        (static_cast<uint32_t>(value_.immediate) << (32 - n)) >> (32 - n);
134  }
135
136  Register rm() const { return rm_; }
137
138  bool is_heap_object_request() const {
139    DCHECK_IMPLIES(is_heap_object_request_, !rm_.is_valid());
140    DCHECK_IMPLIES(is_heap_object_request_,
141                   rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT ||
142                       rmode_ == RelocInfo::CODE_TARGET);
143    return is_heap_object_request_;
144  }
145
146  RelocInfo::Mode rmode() const { return rmode_; }
147
148 private:
149  Register rm_ = no_reg;
150  union Value {
151    Value() {}
152    HeapObjectRequest heap_object_request;  // if is_heap_object_request_
153    intptr_t immediate;                     // otherwise
154  } value_;                                 // valid if rm_ == no_reg
155  bool is_heap_object_request_ = false;
156
157  RelocInfo::Mode rmode_;
158
159  friend class Assembler;
160  friend class MacroAssembler;
161};
162
163using Disp = int32_t;
164
165// Class MemOperand represents a memory operand in load and store instructions
166// On S390, we have various flavours of memory operands:
167//   1) a base register + 16 bit unsigned displacement
168//   2) a base register + index register + 16 bit unsigned displacement
169//   3) a base register + index register + 20 bit signed displacement
170class V8_EXPORT_PRIVATE MemOperand {
171 public:
172  explicit MemOperand(Register rx, Disp offset = 0);
173  explicit MemOperand(Register rx, Register rb, Disp offset = 0);
174
175  int32_t offset() const { return offset_; }
176  uint32_t getDisplacement() const { return offset(); }
177
178  // Base register
179  Register rb() const {
180    DCHECK(baseRegister != no_reg);
181    return baseRegister;
182  }
183
184  Register getBaseRegister() const { return rb(); }
185
186  // Index Register
187  Register rx() const {
188    DCHECK(indexRegister != no_reg);
189    return indexRegister;
190  }
191  Register getIndexRegister() const { return rx(); }
192
193 private:
194  Register baseRegister;   // base
195  Register indexRegister;  // index
196  int32_t offset_;         // offset
197
198  friend class Assembler;
199};
200
201class DeferredRelocInfo {
202 public:
203  DeferredRelocInfo() {}
204  DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
205      : position_(position), rmode_(rmode), data_(data) {}
206
207  int position() const { return position_; }
208  RelocInfo::Mode rmode() const { return rmode_; }
209  intptr_t data() const { return data_; }
210
211 private:
212  int position_;
213  RelocInfo::Mode rmode_;
214  intptr_t data_;
215};
216
217class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
218 public:
219  // Create an assembler. Instructions and relocation information are emitted
220  // into a buffer, with the instructions starting from the beginning and the
221  // relocation information starting from the end of the buffer. See CodeDesc
222  // for a detailed comment on the layout (globals.h).
223  //
224  // If the provided buffer is nullptr, the assembler allocates and grows its
225  // own buffer. Otherwise it takes ownership of the provided buffer.
226  explicit Assembler(const AssemblerOptions&,
227                     std::unique_ptr<AssemblerBuffer> = {});
228
229  virtual ~Assembler() {}
230
231  // GetCode emits any pending (non-emitted) code and fills the descriptor desc.
232  static constexpr int kNoHandlerTable = 0;
233  static constexpr SafepointTableBuilder* kNoSafepointTable = nullptr;
234  void GetCode(Isolate* isolate, CodeDesc* desc,
235               SafepointTableBuilder* safepoint_table_builder,
236               int handler_table_offset);
237
238  // Convenience wrapper for code without safepoint or handler tables.
239  void GetCode(Isolate* isolate, CodeDesc* desc) {
240    GetCode(isolate, desc, kNoSafepointTable, kNoHandlerTable);
241  }
242
243  // Unused on this architecture.
244  void MaybeEmitOutOfLineConstantPool() {}
245
246  // Label operations & relative jumps (PPUM Appendix D)
247  //
248  // Takes a branch opcode (cc) and a label (L) and generates
249  // either a backward branch or a forward branch and links it
250  // to the label fixup chain. Usage:
251  //
252  // Label L;    // unbound label
253  // j(cc, &L);  // forward branch to unbound label
254  // bind(&L);   // bind label to the current pc
255  // j(cc, &L);  // backward branch to bound label
256  // bind(&L);   // illegal: a label may be bound only once
257  //
258  // Note: The same Label can be used for forward and backward branches
259  // but it may be bound only once.
260
261  void bind(Label* L);  // binds an unbound label L to the current code position
262
263  // Links a label at the current pc_offset().  If already bound, returns the
264  // bound position.  If already linked, returns the position of the prior link.
265  // Otherwise, returns the current pc_offset().
266  int link(Label* L);
267
268  // Returns the branch offset to the given label from the current code position
269  // Links the label to the current position if it is still unbound
270  int branch_offset(Label* L) { return link(L) - pc_offset(); }
271
272  void load_label_offset(Register r1, Label* L);
273
274  // Read/Modify the code target address in the branch/call instruction at pc.
275  // The isolate argument is unused (and may be nullptr) when skipping flushing.
276  V8_INLINE static Address target_address_at(Address pc, Address constant_pool);
277
278  // Read/Modify the code target address in the branch/call instruction at pc.
279  inline static Tagged_t target_compressed_address_at(Address pc,
280                                                      Address constant_pool);
281  V8_INLINE static void set_target_address_at(
282      Address pc, Address constant_pool, Address target,
283      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
284
285  inline static void set_target_compressed_address_at(
286      Address pc, Address constant_pool, Tagged_t target,
287      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
288
289  inline Handle<Object> code_target_object_handle_at(Address pc);
290  inline Handle<HeapObject> compressed_embedded_object_handle_at(
291      Address pc, Address constant_pool);
292  // This sets the branch destination.
293  // This is for calls and branches within generated code.
294  inline static void deserialization_set_special_target_at(
295      Address instruction_payload, Code code, Address target);
296
297  // Get the size of the special target encoded at 'instruction_payload'.
298  inline static int deserialization_special_target_size(
299      Address instruction_payload);
300
301  // This sets the internal reference at the pc.
302  inline static void deserialization_set_target_internal_reference_at(
303      Address pc, Address target,
304      RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
305
306  // Here we are patching the address in the IIHF/IILF instruction pair.
307  // These values are used in the serialization process and must be zero for
308  // S390 platform, as Code, Embedded Object or External-reference pointers
309  // are split across two consecutive instructions and don't exist separately
310  // in the code, so the serializer should not step forwards in memory after
311  // a target is resolved and written.
312  static constexpr int kSpecialTargetSize = 0;
313// Number of bytes for instructions used to store pointer sized constant.
314#if V8_TARGET_ARCH_S390X
315  static constexpr int kBytesForPtrConstant = 12;  // IIHF + IILF
316#else
317  static constexpr int kBytesForPtrConstant = 6;  // IILF
318#endif
319
320  RegList* GetScratchRegisterList() { return &scratch_register_list_; }
321
322  // ---------------------------------------------------------------------------
323  // Code generation
324
325  template <class T, int size, int lo, int hi>
326  inline T getfield(T value) {
327    DCHECK(lo < hi);
328    DCHECK_GT(size, 0);
329    int mask = hi - lo;
330    int shift = size * 8 - hi;
331    uint32_t mask_value = (mask == 32) ? 0xffffffff : (1 << mask) - 1;
332    return (value & mask_value) << shift;
333  }
334
335#define DECLARE_S390_RIL_AB_INSTRUCTIONS(name, op_name, op_value) \
336  template <class R1>                                             \
337  inline void name(R1 r1, const Operand& i2) {                    \
338    ril_format(op_name, r1.code(), i2.immediate());               \
339  }
340#define DECLARE_S390_RIL_C_INSTRUCTIONS(name, op_name, op_value) \
341  inline void name(Condition m1, const Operand& i2) {            \
342    ril_format(op_name, m1, i2.immediate());                     \
343  }
344
345  inline void ril_format(Opcode opcode, int f1, int f2) {
346    uint32_t op1 = opcode >> 4;
347    uint32_t op2 = opcode & 0xf;
348    emit6bytes(
349        getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
350        getfield<uint64_t, 6, 12, 16>(op2) | getfield<uint64_t, 6, 16, 48>(f2));
351  }
352  S390_RIL_A_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)
353  S390_RIL_B_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)
354  S390_RIL_C_OPCODE_LIST(DECLARE_S390_RIL_C_INSTRUCTIONS)
355#undef DECLARE_S390_RIL_AB_INSTRUCTIONS
356#undef DECLARE_S390_RIL_C_INSTRUCTIONS
357
358#define DECLARE_S390_RR_INSTRUCTIONS(name, op_name, op_value) \
359  inline void name(Register r1, Register r2) {                \
360    rr_format(op_name, r1.code(), r2.code());                 \
361  }                                                           \
362  inline void name(DoubleRegister r1, DoubleRegister r2) {    \
363    rr_format(op_name, r1.code(), r2.code());                 \
364  }                                                           \
365  inline void name(Condition m1, Register r2) {               \
366    rr_format(op_name, m1, r2.code());                        \
367  }
368
369  inline void rr_format(Opcode opcode, int f1, int f2) {
370    emit2bytes(getfield<uint16_t, 2, 0, 8>(opcode) |
371               getfield<uint16_t, 2, 8, 12>(f1) |
372               getfield<uint16_t, 2, 12, 16>(f2));
373  }
374  S390_RR_OPCODE_LIST(DECLARE_S390_RR_INSTRUCTIONS)
375#undef DECLARE_S390_RR_INSTRUCTIONS
376
377#define DECLARE_S390_RRD_INSTRUCTIONS(name, op_name, op_value) \
378  template <class R1, class R2, class R3>                      \
379  inline void name(R1 r1, R3 r3, R2 r2) {                      \
380    rrd_format(op_name, r1.code(), r3.code(), r2.code());      \
381  }
382  inline void rrd_format(Opcode opcode, int f1, int f2, int f3) {
383    emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) |
384               getfield<uint32_t, 4, 16, 20>(f1) |
385               getfield<uint32_t, 4, 24, 28>(f2) |
386               getfield<uint32_t, 4, 28, 32>(f3));
387  }
388  S390_RRD_OPCODE_LIST(DECLARE_S390_RRD_INSTRUCTIONS)
389#undef DECLARE_S390_RRD_INSTRUCTIONS
390
391#define DECLARE_S390_RRE_INSTRUCTIONS(name, op_name, op_value) \
392  template <class R1, class R2>                                \
393  inline void name(R1 r1, R2 r2) {                             \
394    rre_format(op_name, r1.code(), r2.code());                 \
395  }
396  inline void rre_format(Opcode opcode, int f1, int f2) {
397    emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) |
398               getfield<uint32_t, 4, 24, 28>(f1) |
399               getfield<uint32_t, 4, 28, 32>(f2));
400  }
401  S390_RRE_OPCODE_LIST(DECLARE_S390_RRE_INSTRUCTIONS)
402  // Special format
403  void lzdr(DoubleRegister r1) { rre_format(LZDR, r1.code(), 0); }
404  void lzer(DoubleRegister r1) { rre_format(LZER, r1.code(), 0); }
405#undef DECLARE_S390_RRE_INSTRUCTIONS
406
407#define DECLARE_S390_RX_INSTRUCTIONS(name, op_name, op_value)            \
408  template <class R1>                                                    \
409  inline void name(R1 r1, Register x2, Register b2, const Operand& d2) { \
410    rx_format(op_name, r1.code(), x2.code(), b2.code(), d2.immediate()); \
411  }                                                                      \
412  template <class R1>                                                    \
413  inline void name(R1 r1, const MemOperand& opnd) {                      \
414    name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(),            \
415         Operand(opnd.getDisplacement()));                               \
416  }
417
418  inline void rx_format(Opcode opcode, int f1, int f2, int f3, int f4) {
419    DCHECK(is_uint8(opcode));
420    DCHECK(is_uint12(f4));
421    emit4bytes(
422        getfield<uint32_t, 4, 0, 8>(opcode) | getfield<uint32_t, 4, 8, 12>(f1) |
423        getfield<uint32_t, 4, 12, 16>(f2) | getfield<uint32_t, 4, 16, 20>(f3) |
424        getfield<uint32_t, 4, 20, 32>(f4));
425  }
426  S390_RX_A_OPCODE_LIST(DECLARE_S390_RX_INSTRUCTIONS)
427
428  void bc(Condition cond, const MemOperand& opnd) {
429    bc(cond, opnd.getIndexRegister(), opnd.getBaseRegister(),
430       Operand(opnd.getDisplacement()));
431  }
432  void bc(Condition cond, Register x2, Register b2, const Operand& d2) {
433    rx_format(BC, cond, x2.code(), b2.code(), d2.immediate());
434  }
435#undef DECLARE_S390_RX_INSTRUCTIONS
436
437#define DECLARE_S390_RXY_INSTRUCTIONS(name, op_name, op_value)            \
438  template <class R1, class R2>                                           \
439  inline void name(R1 r1, R2 r2, Register b2, const Operand& d2) {        \
440    rxy_format(op_name, r1.code(), r2.code(), b2.code(), d2.immediate()); \
441  }                                                                       \
442  template <class R1>                                                     \
443  inline void name(R1 r1, const MemOperand& opnd) {                       \
444    name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(),             \
445         Operand(opnd.getDisplacement()));                                \
446  }
447
448  inline void rxy_format(Opcode opcode, int f1, int f2, int f3, int f4) {
449    DCHECK(is_uint16(opcode));
450    DCHECK(is_int20(f4));
451    emit6bytes(getfield<uint64_t, 6, 0, 8>(opcode >> 8) |
452               getfield<uint64_t, 6, 8, 12>(f1) |
453               getfield<uint64_t, 6, 12, 16>(f2) |
454               getfield<uint64_t, 6, 16, 20>(f3) |
455               getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
456               getfield<uint64_t, 6, 32, 40>(f4 >> 12) |
457               getfield<uint64_t, 6, 40, 48>(opcode & 0x00ff));
458  }
459  S390_RXY_A_OPCODE_LIST(DECLARE_S390_RXY_INSTRUCTIONS)
460
461  void pfd(Condition cond, const MemOperand& opnd) {
462    pfd(cond, opnd.getIndexRegister(), opnd.getBaseRegister(),
463        Operand(opnd.getDisplacement()));
464  }
465  void pfd(Condition cond, Register x2, Register b2, const Operand& d2) {
466    rxy_format(PFD, cond, x2.code(), b2.code(), d2.immediate());
467  }
468#undef DECLARE_S390_RXY_INSTRUCTIONS
469
470  inline void rsy_format(Opcode op, int f1, int f2, int f3, int f4) {
471    DCHECK(is_int20(f4));
472    DCHECK(is_uint16(op));
473    uint64_t code =
474        (getfield<uint64_t, 6, 0, 8>(op >> 8) |
475         getfield<uint64_t, 6, 8, 12>(f1) | getfield<uint64_t, 6, 12, 16>(f2) |
476         getfield<uint64_t, 6, 16, 20>(f3) |
477         getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
478         getfield<uint64_t, 6, 32, 40>(f4 >> 12) |
479         getfield<uint64_t, 6, 40, 48>(op & 0xff));
480    emit6bytes(code);
481  }
482
483#define DECLARE_S390_RSY_A_INSTRUCTIONS(name, op_name, op_value)            \
484  void name(Register r1, Register r3, Register b2,                          \
485            const Operand& d2 = Operand::Zero()) {                          \
486    rsy_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate());   \
487  }                                                                         \
488  void name(Register r1, Register r3, Operand d2) { name(r1, r3, r0, d2); } \
489  void name(Register r1, Register r3, const MemOperand& opnd) {             \
490    name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement()));  \
491  }
492  S390_RSY_A_OPCODE_LIST(DECLARE_S390_RSY_A_INSTRUCTIONS)
493#undef DECLARE_S390_RSY_A_INSTRUCTIONS
494
495#define DECLARE_S390_RSY_B_INSTRUCTIONS(name, op_name, op_value)           \
496  void name(Register r1, Condition m3, Register b2, const Operand& d2) {   \
497    rsy_format(op_name, r1.code(), m3, b2.code(), d2.immediate());         \
498  }                                                                        \
499  void name(Register r1, Condition m3, const MemOperand& opnd) {           \
500    name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
501  }
502  S390_RSY_B_OPCODE_LIST(DECLARE_S390_RSY_B_INSTRUCTIONS)
503#undef DECLARE_S390_RSY_B_INSTRUCTIONS
504
505  inline void rs_format(Opcode op, int f1, int f2, int f3, const int f4) {
506    uint32_t code =
507        getfield<uint32_t, 4, 0, 8>(op) | getfield<uint32_t, 4, 8, 12>(f1) |
508        getfield<uint32_t, 4, 12, 16>(f2) | getfield<uint32_t, 4, 16, 20>(f3) |
509        getfield<uint32_t, 4, 20, 32>(f4);
510    emit4bytes(code);
511  }
512
513#define DECLARE_S390_RS_A_INSTRUCTIONS(name, op_name, op_value)            \
514  void name(Register r1, Register r3, Register b2, const Operand& d2) {    \
515    rs_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate());   \
516  }                                                                        \
517  void name(Register r1, Register r3, const MemOperand& opnd) {            \
518    name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
519  }
520  S390_RS_A_OPCODE_LIST(DECLARE_S390_RS_A_INSTRUCTIONS)
521#undef DECLARE_S390_RS_A_INSTRUCTIONS
522
523#define DECLARE_S390_RS_B_INSTRUCTIONS(name, op_name, op_value)            \
524  void name(Register r1, Condition m3, Register b2, const Operand& d2) {   \
525    rs_format(op_name, r1.code(), m3, b2.code(), d2.immediate());          \
526  }                                                                        \
527  void name(Register r1, Condition m3, const MemOperand& opnd) {           \
528    name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
529  }
530  S390_RS_B_OPCODE_LIST(DECLARE_S390_RS_B_INSTRUCTIONS)
531#undef DECLARE_S390_RS_B_INSTRUCTIONS
532
533#define DECLARE_S390_RS_SHIFT_FORMAT(name, opcode)                             \
534  void name(Register r1, Register r2, const Operand& opnd = Operand::Zero()) { \
535    rs_format(opcode, r1.code(), r0.code(), r2.code(), opnd.immediate());      \
536  }                                                                            \
537  void name(Register r1, const Operand& opnd) {                                \
538    rs_format(opcode, r1.code(), r0.code(), r0.code(), opnd.immediate());      \
539  }
540  DECLARE_S390_RS_SHIFT_FORMAT(sll, SLL)
541  DECLARE_S390_RS_SHIFT_FORMAT(srl, SRL)
542  DECLARE_S390_RS_SHIFT_FORMAT(sla, SLA)
543  DECLARE_S390_RS_SHIFT_FORMAT(sra, SRA)
544  DECLARE_S390_RS_SHIFT_FORMAT(sldl, SLDL)
545  DECLARE_S390_RS_SHIFT_FORMAT(srda, SRDA)
546  DECLARE_S390_RS_SHIFT_FORMAT(srdl, SRDL)
547#undef DECLARE_S390_RS_SHIFT_FORMAT
548
549  inline void rxe_format(Opcode op, int f1, int f2, int f3, int f4,
550                         int f5 = 0) {
551    DCHECK(is_uint12(f4));
552    DCHECK(is_uint16(op));
553    uint64_t code =
554        (getfield<uint64_t, 6, 0, 8>(op >> 8) |
555         getfield<uint64_t, 6, 8, 12>(f1) | getfield<uint64_t, 6, 12, 16>(f2) |
556         getfield<uint64_t, 6, 16, 20>(f3) |
557         getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
558         getfield<uint64_t, 6, 32, 36>(f5) |
559         getfield<uint64_t, 6, 40, 48>(op & 0xff));
560    emit6bytes(code);
561  }
562
563#define DECLARE_S390_RXE_INSTRUCTIONS(name, op_name, op_value)                \
564  void name(Register r1, Register x2, Register b2, const Operand& d2,         \
565            Condition m3 = static_cast<Condition>(0)) {                       \
566    rxe_format(op_name, r1.code(), x2.code(), b2.code(), d2.immediate(), m3); \
567  }                                                                           \
568  template <class _R1Type>                                                    \
569  void name(_R1Type r1, const MemOperand& opnd) {                             \
570    name(Register::from_code(r1.code()), opnd.rx(), opnd.rb(),                \
571         Operand(opnd.offset()));                                             \
572  }
573  S390_RXE_OPCODE_LIST(DECLARE_S390_RXE_INSTRUCTIONS)
574#undef DECLARE_S390_RXE_INSTRUCTIONS
575
576  inline void ri_format(Opcode opcode, int f1, int f2) {
577    uint32_t op1 = opcode >> 4;
578    uint32_t op2 = opcode & 0xf;
579    emit4bytes(
580        getfield<uint32_t, 4, 0, 8>(op1) | getfield<uint32_t, 4, 8, 12>(f1) |
581        getfield<uint32_t, 4, 12, 16>(op2) | getfield<uint32_t, 4, 16, 32>(f2));
582  }
583
584#define DECLARE_S390_RI_A_INSTRUCTIONS(name, op_name, op_value)    \
585  void name(Register r, const Operand& i2) {                       \
586    DCHECK(is_uint12(op_name));                                    \
587    DCHECK(is_uint16(i2.immediate()) || is_int16(i2.immediate())); \
588    ri_format(op_name, r.code(), i2.immediate());                  \
589  }
590  S390_RI_A_OPCODE_LIST(DECLARE_S390_RI_A_INSTRUCTIONS)
591#undef DECLARE_S390_RI_A_INSTRUCTIONS
592
593#define DECLARE_S390_RI_B_INSTRUCTIONS(name, op_name, op_value)       \
594  void name(Register r1, const Operand& imm) {                        \
595    /* 2nd argument encodes # of halfwords, so divide by 2. */        \
596    int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2; \
597    Operand halfwordOp = Operand(numHalfwords);                       \
598    halfwordOp.setBits(16);                                           \
599    ri_format(op_name, r1.code(), halfwordOp.immediate());            \
600  }
601  S390_RI_B_OPCODE_LIST(DECLARE_S390_RI_B_INSTRUCTIONS)
602#undef DECLARE_S390_RI_B_INSTRUCTIONS
603
604#define DECLARE_S390_RI_C_INSTRUCTIONS(name, op_name, op_value) \
605  void name(Condition m, const Operand& i2) {                   \
606    DCHECK(is_uint12(op_name));                                 \
607    DCHECK(is_uint4(m));                                        \
608    DCHECK(op_name == BRC ? is_int16(i2.immediate())            \
609                          : is_uint16(i2.immediate()));         \
610    ri_format(op_name, m, i2.immediate());                      \
611  }
612  S390_RI_C_OPCODE_LIST(DECLARE_S390_RI_C_INSTRUCTIONS)
613#undef DECLARE_S390_RI_C_INSTRUCTIONS
614
615  inline void rrf_format(Opcode op, int f1, int f2, int f3, int f4) {
616    uint32_t code =
617        getfield<uint32_t, 4, 0, 16>(op) | getfield<uint32_t, 4, 16, 20>(f1) |
618        getfield<uint32_t, 4, 20, 24>(f2) | getfield<uint32_t, 4, 24, 28>(f3) |
619        getfield<uint32_t, 4, 28, 32>(f4);
620    emit4bytes(code);
621  }
622
623#define DECLARE_S390_RRF_A_INSTRUCTIONS(name, op_name, op_value)   \
624  void name(Register r1, Condition m4, Register r2, Register r3) { \
625    rrf_format(op_name, r3.code(), m4, r1.code(), r2.code());      \
626  }                                                                \
627  void name(Register r1, Register r2, Register r3) {               \
628    name(r1, Condition(0), r2, r3);                                \
629  }
630  S390_RRF_A_OPCODE_LIST(DECLARE_S390_RRF_A_INSTRUCTIONS)
631#undef DECLARE_S390_RRF_A_INSTRUCTIONS
632
633#define DECLARE_S390_RRF_B_INSTRUCTIONS(name, op_name, op_value)   \
634  void name(Register r1, Condition m4, Register r2, Register r3) { \
635    rrf_format(op_name, r3.code(), m4, r1.code(), r2.code());      \
636  }                                                                \
637  void name(Register r1, Register r2, Register r3) {               \
638    name(r1, Condition(0), r2, r3);                                \
639  }
640  S390_RRF_B_OPCODE_LIST(DECLARE_S390_RRF_B_INSTRUCTIONS)
641#undef DECLARE_S390_RRF_B_INSTRUCTIONS
642
643#define DECLARE_S390_RRF_C_INSTRUCTIONS(name, op_name, op_value) \
644  template <class R1, class R2>                                  \
645  void name(Condition m3, Condition m4, R1 r1, R2 r2) {          \
646    rrf_format(op_name, m3, m4, r1.code(), r2.code());           \
647  }                                                              \
648  template <class R1, class R2>                                  \
649  void name(Condition m3, R1 r1, R2 r2) {                        \
650    name(m3, Condition(0), r1, r2);                              \
651  }
652  S390_RRF_C_OPCODE_LIST(DECLARE_S390_RRF_C_INSTRUCTIONS)
653#undef DECLARE_S390_RRF_C_INSTRUCTIONS
654
655#define DECLARE_S390_RRF_D_INSTRUCTIONS(name, op_name, op_value) \
656  template <class R1, class R2>                                  \
657  void name(Condition m3, Condition m4, R1 r1, R2 r2) {          \
658    rrf_format(op_name, m3, m4, r1.code(), r2.code());           \
659  }                                                              \
660  template <class R1, class R2>                                  \
661  void name(Condition m3, R1 r1, R2 r2) {                        \
662    name(m3, Condition(0), r1, r2);                              \
663  }
664  S390_RRF_D_OPCODE_LIST(DECLARE_S390_RRF_D_INSTRUCTIONS)
665#undef DECLARE_S390_RRF_D_INSTRUCTIONS
666
667#define DECLARE_S390_RRF_E_INSTRUCTIONS(name, op_name, op_value) \
668  template <class M3, class M4, class R1, class R2>              \
669  void name(M3 m3, M4 m4, R1 r1, R2 r2) {                        \
670    rrf_format(op_name, m3, m4, r1.code(), r2.code());           \
671  }                                                              \
672  template <class M3, class R1, class R2>                        \
673  void name(M3 m3, R1 r1, R2 r2) {                               \
674    name(m3, Condition(0), r1, r2);                              \
675  }
676  S390_RRF_E_OPCODE_LIST(DECLARE_S390_RRF_E_INSTRUCTIONS)
677#undef DECLARE_S390_RRF_E_INSTRUCTIONS
678
679  inline void rsi_format(Opcode op, int f1, int f2, int f3) {
680    DCHECK(is_uint8(op));
681    DCHECK(is_uint16(f3) || is_int16(f3));
682    uint32_t code =
683        getfield<uint32_t, 4, 0, 8>(op) | getfield<uint32_t, 4, 8, 12>(f1) |
684        getfield<uint32_t, 4, 12, 16>(f2) | getfield<uint32_t, 4, 16, 32>(f3);
685    emit4bytes(code);
686  }
687
688#define DECLARE_S390_RSI_INSTRUCTIONS(name, op_name, op_value) \
689  void name(Register r1, Register r3, const Operand& i2) {     \
690    rsi_format(op_name, r1.code(), r3.code(), i2.immediate()); \
691  }
692  S390_RSI_OPCODE_LIST(DECLARE_S390_RSI_INSTRUCTIONS)
693#undef DECLARE_S390_RSI_INSTRUCTIONS
694
695  inline void rsl_format(Opcode op, uint16_t f1, int f2, int f3, int f4,
696                         int f5) {
697    DCHECK(is_uint16(op));
698    uint64_t code =
699        getfield<uint64_t, 6, 0, 8>(op >> 8) |
700        getfield<uint64_t, 6, 8, 16>(f1) | getfield<uint64_t, 6, 16, 20>(f2) |
701        getfield<uint64_t, 6, 20, 32>(f3) | getfield<uint64_t, 6, 32, 36>(f4) |
702        getfield<uint64_t, 6, 36, 40>(f5) |
703        getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
704    emit6bytes(code);
705  }
706
707#define DECLARE_S390_RSL_A_INSTRUCTIONS(name, op_name, op_value) \
708  void name(const Operand& l1, Register b1, const Operand& d1) { \
709    uint16_t L = static_cast<uint16_t>(l1.immediate() << 8);     \
710    rsl_format(op_name, L, b1.code(), d1.immediate(), 0, 0);     \
711  }
712  S390_RSL_A_OPCODE_LIST(DECLARE_S390_RSL_A_INSTRUCTIONS)
713#undef DECLARE_S390_RSL_A_INSTRUCTIONS
714
715#define DECLARE_S390_RSL_B_INSTRUCTIONS(name, op_name, op_value)            \
716  void name(const Operand& l2, Register b2, const Operand& d2, Register r1, \
717            Condition m3) {                                                 \
718    uint16_t L = static_cast<uint16_t>(l2.immediate());                     \
719    rsl_format(op_name, L, b2.code(), d2.immediate(), r1.code(), m3);       \
720  }
721  S390_RSL_B_OPCODE_LIST(DECLARE_S390_RSL_B_INSTRUCTIONS)
722#undef DECLARE_S390_RSL_B_INSTRUCTIONS
723
724  inline void s_format(Opcode op, int f1, int f2) {
725    DCHECK_NE(op & 0xff00, 0);
726    DCHECK(is_uint12(f2));
727    uint32_t code = getfield<uint32_t, 4, 0, 16>(op) |
728                    getfield<uint32_t, 4, 16, 20>(f1) |
729                    getfield<uint32_t, 4, 20, 32>(f2);
730    emit4bytes(code);
731  }
732
733#define DECLARE_S390_S_INSTRUCTIONS(name, op_name, op_value) \
734  void name(Register b1, const Operand& d2) {                \
735    Opcode op = op_name;                                     \
736    if ((op & 0xFF00) == 0) {                                \
737      op = (Opcode)(op << 8);                                \
738    }                                                        \
739    s_format(op, b1.code(), d2.immediate());                 \
740  }                                                          \
741  void name(const MemOperand& opnd) {                        \
742    Operand d2 = Operand(opnd.getDisplacement());            \
743    name(opnd.getBaseRegister(), d2);                        \
744  }
745  S390_S_OPCODE_LIST(DECLARE_S390_S_INSTRUCTIONS)
746#undef DECLARE_S390_S_INSTRUCTIONS
747
748  inline void si_format(Opcode op, int f1, int f2, int f3) {
749    uint32_t code =
750        getfield<uint32_t, 4, 0, 8>(op) | getfield<uint32_t, 4, 8, 16>(f1) |
751        getfield<uint32_t, 4, 16, 20>(f2) | getfield<uint32_t, 4, 20, 32>(f3);
752    emit4bytes(code);
753  }
754
755#define DECLARE_S390_SI_INSTRUCTIONS(name, op_name, op_value)          \
756  void name(const Operand& i2, Register b1, const Operand& d1) {       \
757    si_format(op_name, i2.immediate(), b1.code(), d1.immediate());     \
758  }                                                                    \
759  void name(const MemOperand& opnd, const Operand& i2) {               \
760    name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
761  }
762  S390_SI_OPCODE_LIST(DECLARE_S390_SI_INSTRUCTIONS)
763#undef DECLARE_S390_SI_INSTRUCTIONS
764
765  inline void siy_format(Opcode op, int f1, int f2, int f3) {
766    DCHECK(is_uint20(f3) || is_int20(f3));
767    DCHECK(is_uint16(op));
768    DCHECK(is_uint8(f1) || is_int8(f1));
769    uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
770                    getfield<uint64_t, 6, 8, 16>(f1) |
771                    getfield<uint64_t, 6, 16, 20>(f2) |
772                    getfield<uint64_t, 6, 20, 32>(f3) |
773                    getfield<uint64_t, 6, 32, 40>(f3 >> 12) |
774                    getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
775    emit6bytes(code);
776  }
777
778#define DECLARE_S390_SIY_INSTRUCTIONS(name, op_name, op_value)         \
779  void name(const Operand& i2, Register b1, const Operand& d1) {       \
780    siy_format(op_name, i2.immediate(), b1.code(), d1.immediate());    \
781  }                                                                    \
782  void name(const MemOperand& opnd, const Operand& i2) {               \
783    name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \
784  }
785  S390_SIY_OPCODE_LIST(DECLARE_S390_SIY_INSTRUCTIONS)
786#undef DECLARE_S390_SIY_INSTRUCTIONS
787
788  inline void rrs_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
789    DCHECK(is_uint12(f4));
790    DCHECK(is_uint16(op));
791    uint64_t code =
792        getfield<uint64_t, 6, 0, 8>(op >> 8) |
793        getfield<uint64_t, 6, 8, 12>(f1) | getfield<uint64_t, 6, 12, 16>(f2) |
794        getfield<uint64_t, 6, 16, 20>(f3) | getfield<uint64_t, 6, 20, 32>(f4) |
795        getfield<uint64_t, 6, 32, 36>(f5) |
796        getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
797    emit6bytes(code);
798  }
799
800#define DECLARE_S390_RRS_INSTRUCTIONS(name, op_name, op_value)                 \
801  void name(Register r1, Register r2, Register b4, const Operand& d4,          \
802            Condition m3) {                                                    \
803    rrs_format(op_name, r1.code(), r2.code(), b4.code(), d4.immediate(), m3);  \
804  }                                                                            \
805  void name(Register r1, Register r2, Condition m3, const MemOperand& opnd) {  \
806    name(r1, r2, opnd.getBaseRegister(), Operand(opnd.getDisplacement()), m3); \
807  }
808  S390_RRS_OPCODE_LIST(DECLARE_S390_RRS_INSTRUCTIONS)
809#undef DECLARE_S390_RRS_INSTRUCTIONS
810
811  inline void ris_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
812    DCHECK(is_uint12(f3));
813    DCHECK(is_uint16(op));
814    DCHECK(is_uint8(f5));
815    uint64_t code =
816        getfield<uint64_t, 6, 0, 8>(op >> 8) |
817        getfield<uint64_t, 6, 8, 12>(f1) | getfield<uint64_t, 6, 12, 16>(f2) |
818        getfield<uint64_t, 6, 16, 20>(f3) | getfield<uint64_t, 6, 20, 32>(f4) |
819        getfield<uint64_t, 6, 32, 40>(f5) |
820        getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
821    emit6bytes(code);
822  }
823
824#define DECLARE_S390_RIS_INSTRUCTIONS(name, op_name, op_value)                 \
825  void name(Register r1, Condition m3, Register b4, const Operand& d4,         \
826            const Operand& i2) {                                               \
827    ris_format(op_name, r1.code(), m3, b4.code(), d4.immediate(),              \
828               i2.immediate());                                                \
829  }                                                                            \
830  void name(Register r1, const Operand& i2, Condition m3,                      \
831            const MemOperand& opnd) {                                          \
832    name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement()), i2); \
833  }
834  S390_RIS_OPCODE_LIST(DECLARE_S390_RIS_INSTRUCTIONS)
835#undef DECLARE_S390_RIS_INSTRUCTIONS
836
837  inline void sil_format(Opcode op, int f1, int f2, int f3) {
838    DCHECK(is_uint12(f2));
839    DCHECK(is_uint16(op));
840    DCHECK(is_uint16(f3));
841    uint64_t code =
842        getfield<uint64_t, 6, 0, 16>(op) | getfield<uint64_t, 6, 16, 20>(f1) |
843        getfield<uint64_t, 6, 20, 32>(f2) | getfield<uint64_t, 6, 32, 48>(f3);
844    emit6bytes(code);
845  }
846
847#define DECLARE_S390_SIL_INSTRUCTIONS(name, op_name, op_value)         \
848  void name(Register b1, const Operand& d1, const Operand& i2) {       \
849    sil_format(op_name, b1.code(), d1.immediate(), i2.immediate());    \
850  }                                                                    \
851  void name(const MemOperand& opnd, const Operand& i2) {               \
852    name(opnd.getBaseRegister(), Operand(opnd.getDisplacement()), i2); \
853  }
854  S390_SIL_OPCODE_LIST(DECLARE_S390_SIL_INSTRUCTIONS)
855#undef DECLARE_S390_SIL_INSTRUCTIONS
856
857  inline void rie_d_format(Opcode opcode, int f1, int f2, int f3, int f4) {
858    uint32_t op1 = opcode >> 8;
859    uint32_t op2 = opcode & 0xff;
860    uint64_t code =
861        getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
862        getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 32>(f3) |
863        getfield<uint64_t, 6, 32, 40>(f4) | getfield<uint64_t, 6, 40, 48>(op2);
864    emit6bytes(code);
865  }
866
867#define DECLARE_S390_RIE_D_INSTRUCTIONS(name, op_name, op_value)    \
868  void name(Register r1, Register r3, const Operand& i2) {          \
869    rie_d_format(op_name, r1.code(), r3.code(), i2.immediate(), 0); \
870  }
871  S390_RIE_D_OPCODE_LIST(DECLARE_S390_RIE_D_INSTRUCTIONS)
872#undef DECLARE_S390_RIE_D_INSTRUCTIONS
873
874  inline void rie_e_format(Opcode opcode, int f1, int f2, int f3) {
875    uint32_t op1 = opcode >> 8;
876    uint32_t op2 = opcode & 0xff;
877    uint64_t code =
878        getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
879        getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 32>(f3) |
880        getfield<uint64_t, 6, 40, 48>(op2);
881    emit6bytes(code);
882  }
883
884#define DECLARE_S390_RIE_E_INSTRUCTIONS(name, op_name, op_value) \
885  void name(Register r1, Register r3, const Operand& i2) {       \
886    rie_e_format(op_name, r1.code(), r3.code(), i2.immediate()); \
887  }
888  S390_RIE_E_OPCODE_LIST(DECLARE_S390_RIE_E_INSTRUCTIONS)
889#undef DECLARE_S390_RIE_E_INSTRUCTIONS
890
891  inline void rie_f_format(Opcode opcode, int f1, int f2, int f3, int f4,
892                           int f5) {
893    uint32_t op1 = opcode >> 8;
894    uint32_t op2 = opcode & 0xff;
895    uint64_t code =
896        getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
897        getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 24>(f3) |
898        getfield<uint64_t, 6, 24, 32>(f4) | getfield<uint64_t, 6, 32, 40>(f5) |
899        getfield<uint64_t, 6, 40, 48>(op2);
900    emit6bytes(code);
901  }
902
903#define DECLARE_S390_RIE_F_INSTRUCTIONS(name, op_name, op_value)        \
904  void name(Register dst, Register src, const Operand& startBit,        \
905            const Operand& endBit, const Operand& shiftAmt) {           \
906    DCHECK(is_uint8(startBit.immediate()));                             \
907    DCHECK(is_uint8(endBit.immediate()));                               \
908    DCHECK(is_uint8(shiftAmt.immediate()));                             \
909    rie_f_format(op_name, dst.code(), src.code(), startBit.immediate(), \
910                 endBit.immediate(), shiftAmt.immediate());             \
911  }
912  S390_RIE_F_OPCODE_LIST(DECLARE_S390_RIE_F_INSTRUCTIONS)
913#undef DECLARE_S390_RIE_F_INSTRUCTIONS
914
915  inline void ss_a_format(Opcode op, int f1, int f2, int f3, int f4, int f5) {
916    DCHECK(is_uint12(f5));
917    DCHECK(is_uint12(f3));
918    DCHECK(is_uint8(f1));
919    DCHECK(is_uint8(op));
920    uint64_t code =
921        getfield<uint64_t, 6, 0, 8>(op) | getfield<uint64_t, 6, 8, 16>(f1) |
922        getfield<uint64_t, 6, 16, 20>(f2) | getfield<uint64_t, 6, 20, 32>(f3) |
923        getfield<uint64_t, 6, 32, 36>(f4) | getfield<uint64_t, 6, 36, 48>(f5);
924    emit6bytes(code);
925  }
926
927#define DECLARE_S390_SS_A_INSTRUCTIONS(name, op_name, op_value)              \
928  void name(Register b1, const Operand& d1, Register b2, const Operand& d2,  \
929            const Operand& length) {                                         \
930    ss_a_format(op_name, length.immediate(), b1.code(), d1.immediate(),      \
931                b2.code(), d2.immediate());                                  \
932  }                                                                          \
933  void name(const MemOperand& opnd1, const MemOperand& opnd2,                \
934            const Operand& length) {                                         \
935    ss_a_format(op_name, length.immediate(), opnd1.getBaseRegister().code(), \
936                opnd1.getDisplacement(), opnd2.getBaseRegister().code(),     \
937                opnd2.getDisplacement());                                    \
938  }
939  S390_SS_A_OPCODE_LIST(DECLARE_S390_SS_A_INSTRUCTIONS)
940#undef DECLARE_S390_SS_A_INSTRUCTIONS
941
942  // Helper for unconditional branch to Label with update to save register
943  void b(Register r, Label* l) {
944    int32_t halfwords = branch_offset(l) / 2;
945    brasl(r, Operand(halfwords));
946  }
947
948  // Conditional Branch Instruction - Generates either BRC / BRCL
949  void branchOnCond(Condition c, int branch_offset, bool is_bound = false,
950                    bool force_long_branch = false);
951
952  // Helpers for conditional branch to Label
953  void b(Condition cond, Label* l, Label::Distance dist = Label::kFar,
954         bool force_long_branch = false) {
955    branchOnCond(cond, branch_offset(l),
956                 l->is_bound() || (dist == Label::kNear), force_long_branch);
957  }
958
959  void bc_short(Condition cond, Label* l, Label::Distance dist = Label::kFar) {
960    b(cond, l, Label::kNear);
961  }
962  void bc_long(Condition cond, Label* l) { b(cond, l, Label::kFar, true); }
963  // Helpers for conditional branch to Label
964  void beq(Label* l, Label::Distance dist = Label::kFar) { b(eq, l, dist); }
965  void bne(Label* l, Label::Distance dist = Label::kFar) { b(ne, l, dist); }
966  void blt(Label* l, Label::Distance dist = Label::kFar) { b(lt, l, dist); }
967  void ble(Label* l, Label::Distance dist = Label::kFar) { b(le, l, dist); }
968  void bgt(Label* l, Label::Distance dist = Label::kFar) { b(gt, l, dist); }
969  void bge(Label* l, Label::Distance dist = Label::kFar) { b(ge, l, dist); }
970  void b(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); }
971  void jmp(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); }
972  void bunordered(Label* l, Label::Distance dist = Label::kFar) {
973    b(unordered, l, dist);
974  }
975  void bordered(Label* l, Label::Distance dist = Label::kFar) {
976    b(ordered, l, dist);
977  }
978
979  // Helpers for conditional indirect branch off register
980  void b(Condition cond, Register r) { bcr(cond, r); }
981  void beq(Register r) { b(eq, r); }
982  void bne(Register r) { b(ne, r); }
983  void blt(Register r) { b(lt, r); }
984  void ble(Register r) { b(le, r); }
985  void bgt(Register r) { b(gt, r); }
986  void bge(Register r) { b(ge, r); }
987  void b(Register r) { b(al, r); }
988  void jmp(Register r) { b(al, r); }
989  void bunordered(Register r) { b(unordered, r); }
990  void bordered(Register r) { b(ordered, r); }
991
992  // wrappers around asm instr
993  void brxh(Register dst, Register inc, Label* L) {
994    int offset_halfwords = branch_offset(L) / 2;
995    CHECK(is_int16(offset_halfwords));
996    brxh(dst, inc, Operand(offset_halfwords));
997  }
998
999  void brxhg(Register dst, Register inc, Label* L) {
1000    int offset_halfwords = branch_offset(L) / 2;
1001    CHECK(is_int16(offset_halfwords));
1002    brxhg(dst, inc, Operand(offset_halfwords));
1003  }
1004
1005  template <class R1, class R2>
1006  void ledbr(R1 r1, R2 r2) {
1007    ledbra(Condition(0), Condition(0), r1, r2);
1008  }
1009
1010  template <class R1, class R2>
1011  void cdfbr(R1 r1, R2 r2) {
1012    cdfbra(Condition(0), Condition(0), r1, r2);
1013  }
1014
1015  template <class R1, class R2>
1016  void cdgbr(R1 r1, R2 r2) {
1017    cdgbra(Condition(0), Condition(0), r1, r2);
1018  }
1019
1020  template <class R1, class R2>
1021  void cegbr(R1 r1, R2 r2) {
1022    cegbra(Condition(0), Condition(0), r1, r2);
1023  }
1024
1025  template <class R1, class R2>
1026  void cgebr(Condition m3, R1 r1, R2 r2) {
1027    cgebra(m3, Condition(0), r1, r2);
1028  }
1029
1030  template <class R1, class R2>
1031  void cgdbr(Condition m3, R1 r1, R2 r2) {
1032    cgdbra(m3, Condition(0), r1, r2);
1033  }
1034
1035  template <class R1, class R2>
1036  void cfdbr(Condition m3, R1 r1, R2 r2) {
1037    cfdbra(m3, Condition(0), r1, r2);
1038  }
1039
1040  template <class R1, class R2>
1041  void cfebr(Condition m3, R1 r1, R2 r2) {
1042    cfebra(m3, Condition(0), r1, r2);
1043  }
1044
1045  // ---------------------------------------------------------------------------
1046  // Code generation
1047
1048  // Insert the smallest number of nop instructions
1049  // possible to align the pc offset to a multiple
1050  // of m. m must be a power of 2 (>= 4).
1051  void Align(int m);
1052  // Insert the smallest number of zero bytes possible to align the pc offset
1053  // to a mulitple of m. m must be a power of 2 (>= 2).
1054  void DataAlign(int m);
1055  // Aligns code to something that's optimal for a jump target for the platform.
1056  void CodeTargetAlign();
1057  void LoopHeaderAlign() { CodeTargetAlign(); }
1058
1059  void breakpoint(bool do_print) {
1060    if (do_print) {
1061      PrintF("DebugBreak is inserted to %p\n", static_cast<void*>(pc_));
1062    }
1063#if V8_HOST_ARCH_64_BIT
1064    int64_t value = reinterpret_cast<uint64_t>(&v8::base::OS::DebugBreak);
1065    int32_t hi_32 = static_cast<int64_t>(value) >> 32;
1066    int32_t lo_32 = static_cast<int32_t>(value);
1067
1068    iihf(r1, Operand(hi_32));
1069    iilf(r1, Operand(lo_32));
1070#else
1071    iilf(r1, Operand(reinterpret_cast<uint32_t>(&v8::base::OS::DebugBreak)));
1072#endif
1073    basr(r14, r1);
1074  }
1075
1076  void call(Handle<Code> target, RelocInfo::Mode rmode);
1077  void jump(Handle<Code> target, RelocInfo::Mode rmode, Condition cond);
1078
1079// S390 instruction generation
1080#define DECLARE_VRR_A_INSTRUCTIONS(name, opcode_name, opcode_value)           \
1081  void name(DoubleRegister v1, DoubleRegister v2, Condition m5, Condition m4, \
1082            Condition m3) {                                                   \
1083    uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 |    \
1084                    (static_cast<uint64_t>(v1.code())) * B36 |                \
1085                    (static_cast<uint64_t>(v2.code())) * B32 |                \
1086                    (static_cast<uint64_t>(m5 & 0xF)) * B20 |                 \
1087                    (static_cast<uint64_t>(m4 & 0xF)) * B16 |                 \
1088                    (static_cast<uint64_t>(m3 & 0xF)) * B12 |                 \
1089                    (static_cast<uint64_t>(0)) * B8 |                         \
1090                    (static_cast<uint64_t>(opcode_value & 0x00FF));           \
1091    emit6bytes(code);                                                         \
1092  }
1093  S390_VRR_A_OPCODE_LIST(DECLARE_VRR_A_INSTRUCTIONS)
1094#undef DECLARE_VRR_A_INSTRUCTIONS
1095
1096#define DECLARE_VRR_C_INSTRUCTIONS(name, opcode_name, opcode_value)        \
1097  void name(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3,       \
1098            Condition m6, Condition m5, Condition m4) {                    \
1099    uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
1100                    (static_cast<uint64_t>(v1.code())) * B36 |             \
1101                    (static_cast<uint64_t>(v2.code())) * B32 |             \
1102                    (static_cast<uint64_t>(v3.code())) * B28 |             \
1103                    (static_cast<uint64_t>(m6 & 0xF)) * B20 |              \
1104                    (static_cast<uint64_t>(m5 & 0xF)) * B16 |              \
1105                    (static_cast<uint64_t>(m4 & 0xF)) * B12 |              \
1106                    (static_cast<uint64_t>(0)) * B8 |                      \
1107                    (static_cast<uint64_t>(opcode_value & 0x00FF));        \
1108    emit6bytes(code);                                                      \
1109  }
1110  S390_VRR_C_OPCODE_LIST(DECLARE_VRR_C_INSTRUCTIONS)
1111#undef DECLARE_VRR_C_INSTRUCTIONS
1112
1113#define DECLARE_VRR_B_INSTRUCTIONS(name, opcode_name, opcode_value)        \
1114  void name(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3,       \
1115            Condition m5, Condition m4) {                                  \
1116    uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
1117                    (static_cast<uint64_t>(v1.code())) * B36 |             \
1118                    (static_cast<uint64_t>(v2.code())) * B32 |             \
1119                    (static_cast<uint64_t>(v3.code())) * B28 |             \
1120                    (static_cast<uint64_t>(m5 & 0xF)) * B20 |              \
1121                    (static_cast<uint64_t>(m4 & 0xF)) * B12 |              \
1122                    (static_cast<uint64_t>(0)) * B8 |                      \
1123                    (static_cast<uint64_t>(opcode_value & 0x00FF));        \
1124    emit6bytes(code);                                                      \
1125  }
1126  S390_VRR_B_OPCODE_LIST(DECLARE_VRR_B_INSTRUCTIONS)
1127#undef DECLARE_VRR_B_INSTRUCTIONS
1128
1129#define DECLARE_VRR_E_INSTRUCTIONS(name, opcode_name, opcode_value)        \
1130  void name(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3,       \
1131            DoubleRegister v4, Condition m6, Condition m5) {               \
1132    uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
1133                    (static_cast<uint64_t>(v1.code())) * B36 |             \
1134                    (static_cast<uint64_t>(v2.code())) * B32 |             \
1135                    (static_cast<uint64_t>(v3.code())) * B28 |             \
1136                    (static_cast<uint64_t>(m6 & 0xF)) * B24 |              \
1137                    (static_cast<uint64_t>(m5 & 0xF)) * B16 |              \
1138                    (static_cast<uint64_t>(v4.code())) * B12 |             \
1139                    (static_cast<uint64_t>(0)) * B8 |                      \
1140                    (static_cast<uint64_t>(opcode_value & 0x00FF));        \
1141    emit6bytes(code);                                                      \
1142  }
1143  S390_VRR_E_OPCODE_LIST(DECLARE_VRR_E_INSTRUCTIONS)
1144#undef DECLARE_VRR_E_INSTRUCTIONS
1145
1146#define DECLARE_VRR_F_INSTRUCTIONS(name, opcode_name, opcode_value)        \
1147  void name(DoubleRegister v1, Register r1, Register r2) {                 \
1148    uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
1149                    (static_cast<uint64_t>(v1.code())) * B36 |             \
1150                    (static_cast<uint64_t>(r1.code())) * B32 |             \
1151                    (static_cast<uint64_t>(r2.code())) * B28 |             \
1152                    (static_cast<uint64_t>(0)) * B8 |                      \
1153                    (static_cast<uint64_t>(opcode_value & 0x00FF));        \
1154    emit6bytes(code);                                                      \
1155  }
1156  S390_VRR_F_OPCODE_LIST(DECLARE_VRR_F_INSTRUCTIONS)
1157#undef DECLARE_VRR_E_INSTRUCTIONS
1158
1159#define DECLARE_VRX_INSTRUCTIONS(name, opcode_name, opcode_value)       \
1160  void name(DoubleRegister v1, const MemOperand& opnd, Condition m3) {  \
1161    uint64_t code =                                                     \
1162        (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 |          \
1163        (static_cast<uint64_t>(v1.code())) * B36 |                      \
1164        (static_cast<uint64_t>(opnd.getIndexRegister().code())) * B32 | \
1165        (static_cast<uint64_t>(opnd.getBaseRegister().code())) * B28 |  \
1166        (static_cast<uint64_t>(opnd.getDisplacement())) * B16 |         \
1167        (static_cast<uint64_t>(m3 & 0xF)) * B12 |                       \
1168        (static_cast<uint64_t>(0)) * B8 |                               \
1169        (static_cast<uint64_t>(opcode_value & 0x00FF));                 \
1170    emit6bytes(code);                                                   \
1171  }
1172  S390_VRX_OPCODE_LIST(DECLARE_VRX_INSTRUCTIONS)
1173#undef DECLARE_VRX_INSTRUCTIONS
1174
1175#define DECLARE_VRS_A_INSTRUCTIONS(name, opcode_name, opcode_value)       \
1176  void name(DoubleRegister v1, DoubleRegister v2, const MemOperand& opnd, \
1177            Condition m4 = Condition(0)) {                                \
1178    uint64_t code =                                                       \
1179        (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 |            \
1180        (static_cast<uint64_t>(v1.code())) * B36 |                        \
1181        (static_cast<uint64_t>(v2.code())) * B32 |                        \
1182        (static_cast<uint64_t>(opnd.getBaseRegister().code())) * B28 |    \
1183        (static_cast<uint64_t>(opnd.getDisplacement())) * B16 |           \
1184        (static_cast<uint64_t>(m4 & 0xF)) * B12 |                         \
1185        (static_cast<uint64_t>(0)) * B8 |                                 \
1186        (static_cast<uint64_t>(opcode_value & 0x00FF));                   \
1187    emit6bytes(code);                                                     \
1188  }
1189  S390_VRS_A_OPCODE_LIST(DECLARE_VRS_A_INSTRUCTIONS)
1190#undef DECLARE_VRS_A_INSTRUCTIONS
1191
1192#define DECLARE_VRS_B_INSTRUCTIONS(name, opcode_name, opcode_value)    \
1193  void name(DoubleRegister v1, Register r1, const MemOperand& opnd,    \
1194            Condition m4 = Condition(0)) {                             \
1195    uint64_t code =                                                    \
1196        (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 |         \
1197        (static_cast<uint64_t>(v1.code())) * B36 |                     \
1198        (static_cast<uint64_t>(r1.code())) * B32 |                     \
1199        (static_cast<uint64_t>(opnd.getBaseRegister().code())) * B28 | \
1200        (static_cast<uint64_t>(opnd.getDisplacement())) * B16 |        \
1201        (static_cast<uint64_t>(m4 & 0xF)) * B12 |                      \
1202        (static_cast<uint64_t>(0)) * B8 |                              \
1203        (static_cast<uint64_t>(opcode_value & 0x00FF));                \
1204    emit6bytes(code);                                                  \
1205  }
1206  S390_VRS_B_OPCODE_LIST(DECLARE_VRS_B_INSTRUCTIONS)
1207#undef DECLARE_VRS_B_INSTRUCTIONS
1208
1209#define DECLARE_VRS_C_INSTRUCTIONS(name, opcode_name, opcode_value)    \
1210  void name(Register r1, DoubleRegister v1, const MemOperand& opnd,    \
1211            Condition m4 = Condition(0)) {                             \
1212    uint64_t code =                                                    \
1213        (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 |         \
1214        (static_cast<uint64_t>(r1.code())) * B36 |                     \
1215        (static_cast<uint64_t>(v1.code())) * B32 |                     \
1216        (static_cast<uint64_t>(opnd.getBaseRegister().code())) * B28 | \
1217        (static_cast<uint64_t>(opnd.getDisplacement())) * B16 |        \
1218        (static_cast<uint64_t>(m4 & 0xF)) * B12 |                      \
1219        (static_cast<uint64_t>(0)) * B8 |                              \
1220        (static_cast<uint64_t>(opcode_value & 0x00FF));                \
1221    emit6bytes(code);                                                  \
1222  }
1223  S390_VRS_C_OPCODE_LIST(DECLARE_VRS_C_INSTRUCTIONS)
1224#undef DECLARE_VRS_C_INSTRUCTIONS
1225
1226#define DECLARE_VRI_A_INSTRUCTIONS(name, opcode_name, opcode_value)        \
1227  void name(DoubleRegister v1, const Operand& i2, Condition m3) {          \
1228    uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
1229                    (static_cast<uint64_t>(v1.code())) * B36 |             \
1230                    (static_cast<uint32_t>(i2.immediate())) * B16 |        \
1231                    (static_cast<uint64_t>(m3 & 0xF)) * B12 |              \
1232                    (static_cast<uint64_t>(0)) * B8 |                      \
1233                    (static_cast<uint64_t>(opcode_value & 0x00FF));        \
1234    emit6bytes(code);                                                      \
1235  }
1236  S390_VRI_A_OPCODE_LIST(DECLARE_VRI_A_INSTRUCTIONS)
1237#undef DECLARE_VRI_A_INSTRUCTIONS
1238
1239#define DECLARE_VRI_C_INSTRUCTIONS(name, opcode_name, opcode_value)        \
1240  void name(DoubleRegister v1, DoubleRegister v2, const Operand& i2,       \
1241            Condition m4) {                                                \
1242    uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \
1243                    (static_cast<uint64_t>(v1.code())) * B36 |             \
1244                    (static_cast<uint64_t>(v2.code())) * B32 |             \
1245                    (static_cast<uint16_t>(i2.immediate())) * B16 |        \
1246                    (static_cast<uint64_t>(m4 & 0xF)) * B12 |              \
1247                    (static_cast<uint64_t>(0)) * B8 |                      \
1248                    (static_cast<uint64_t>(opcode_value & 0x00FF));        \
1249    emit6bytes(code);                                                      \
1250  }
1251  S390_VRI_C_OPCODE_LIST(DECLARE_VRI_C_INSTRUCTIONS)
1252#undef DECLARE_VRI_C_INSTRUCTIONS
1253
1254  // Single Element format
1255  void vfa(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1256    vfa(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1257        static_cast<Condition>(3));
1258  }
1259  void vfs(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1260    vfs(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1261        static_cast<Condition>(3));
1262  }
1263  void vfm(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1264    vfm(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1265        static_cast<Condition>(3));
1266  }
1267  void vfd(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1268    vfd(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1269        static_cast<Condition>(3));
1270  }
1271
1272  // Load Address Instructions
1273  void larl(Register r, Label* l);
1274  void lgrl(Register r, Label* l);
1275
1276  // Exception-generating instructions and debugging support
1277  void stop(Condition cond = al, int32_t code = kDefaultStopCode,
1278            CRegister cr = cr7);
1279
1280  void bkpt(uint32_t imm16);  // v5 and above
1281
1282  // Different nop operations are used by the code generator to detect certain
1283  // states of the generated code.
1284  enum NopMarkerTypes {
1285    NON_MARKING_NOP = 0,
1286    GROUP_ENDING_NOP,
1287    DEBUG_BREAK_NOP,
1288    // IC markers.
1289    PROPERTY_ACCESS_INLINED,
1290    PROPERTY_ACCESS_INLINED_CONTEXT,
1291    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1292    // Helper values.
1293    LAST_CODE_MARKER,
1294    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1295  };
1296
1297  void nop(int type = 0);  // 0 is the default non-marking type.
1298
1299  void dumy(int r1, int x2, int b2, int d2);
1300
1301  // Check the code size generated from label to here.
1302  int SizeOfCodeGeneratedSince(Label* label) {
1303    return pc_offset() - label->pos();
1304  }
1305
1306  // Record a deoptimization reason that can be used by a log or cpu profiler.
1307  // Use --trace-deopt to enable.
1308  void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
1309                         SourcePosition position, int id);
1310
1311  // Writes a single byte or word of data in the code stream.  Used
1312  // for inline tables, e.g., jump-tables.
1313  void db(uint8_t data);
1314  void dd(uint32_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO);
1315  void dq(uint64_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO);
1316  void dp(uintptr_t data, RelocInfo::Mode rmode = RelocInfo::NO_INFO);
1317
1318  // Read/patch instructions
1319  SixByteInstr instr_at(int pos) {
1320    return Instruction::InstructionBits(buffer_start_ + pos);
1321  }
1322  template <typename T>
1323  void instr_at_put(int pos, T instr) {
1324    Instruction::SetInstructionBits<T>(buffer_start_ + pos, instr);
1325  }
1326
1327  // Decodes instruction at pos, and returns its length
1328  int32_t instr_length_at(int pos) {
1329    return Instruction::InstructionLength(buffer_start_ + pos);
1330  }
1331
1332  static SixByteInstr instr_at(byte* pc) {
1333    return Instruction::InstructionBits(pc);
1334  }
1335
1336  static Condition GetCondition(Instr instr);
1337
1338  static bool IsBranch(Instr instr);
1339#if V8_TARGET_ARCH_S390X
1340  static bool Is64BitLoadIntoIP(SixByteInstr instr1, SixByteInstr instr2);
1341#else
1342  static bool Is32BitLoadIntoIP(SixByteInstr instr);
1343#endif
1344
1345  static bool IsCmpRegister(Instr instr);
1346  static bool IsCmpImmediate(Instr instr);
1347  static bool IsNop(SixByteInstr instr, int type = NON_MARKING_NOP);
1348
1349  // The code currently calls CheckBuffer() too often. This has the side
1350  // effect of randomly growing the buffer in the middle of multi-instruction
1351  // sequences.
1352  //
1353  // This function allows outside callers to check and grow the buffer
1354  void EnsureSpaceFor(int space_needed);
1355
1356  void EmitRelocations();
1357  void emit_label_addr(Label* label);
1358
1359 public:
1360  byte* buffer_pos() const { return buffer_start_; }
1361
1362
1363  // Code generation
1364  // The relocation writer's position is at least kGap bytes below the end of
1365  // the generated instructions. This is so that multi-instruction sequences do
1366  // not have to check for overflow. The same is true for writes of large
1367  // relocation info entries.
1368  static constexpr int kGap = 32;
1369  STATIC_ASSERT(AssemblerBase::kMinimalBufferSize >= 2 * kGap);
1370
1371 protected:
1372  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1373
1374  // Decode instruction(s) at pos and return backchain to previous
1375  // label reference or kEndOfChain.
1376  int target_at(int pos);
1377
1378  // Patch instruction(s) at pos to target target_pos (e.g. branch)
1379  void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
1380
1381  // Record reloc info for current pc_
1382  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1383
1384 private:
1385  // Avoid overflows for displacements etc.
1386  static const int kMaximalBufferSize = 512 * MB;
1387
1388  // Relocation info generation
1389  // Each relocation is encoded as a variable size value
1390  static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1391  RelocInfoWriter reloc_info_writer;
1392  std::vector<DeferredRelocInfo> relocations_;
1393
1394  // Scratch registers available for use by the Assembler.
1395  RegList scratch_register_list_;
1396
1397  // The bound position, before this we cannot do instruction elimination.
1398  int last_bound_pos_;
1399
1400  // Code emission
1401  void CheckBuffer() {
1402    if (buffer_space() <= kGap) {
1403      GrowBuffer();
1404    }
1405  }
1406  void GrowBuffer(int needed = 0);
1407  inline void TrackBranch();
1408  inline void UntrackBranch();
1409
1410  // Helper to emit the binary encoding of a 2 byte instruction
1411  void emit2bytes(uint16_t x) {
1412    CheckBuffer();
1413#if V8_TARGET_LITTLE_ENDIAN
1414    // We need to emit instructions in big endian format as disassembler /
1415    // simulator require the first byte of the instruction in order to decode
1416    // the instruction length.  Swap the bytes.
1417    x = ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8);
1418#endif
1419    *reinterpret_cast<uint16_t*>(pc_) = x;
1420    pc_ += 2;
1421  }
1422
1423  // Helper to emit the binary encoding of a 4 byte instruction
1424  void emit4bytes(uint32_t x) {
1425    CheckBuffer();
1426#if V8_TARGET_LITTLE_ENDIAN
1427    // We need to emit instructions in big endian format as disassembler /
1428    // simulator require the first byte of the instruction in order to decode
1429    // the instruction length.  Swap the bytes.
1430    x = ((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) |
1431        ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24);
1432#endif
1433    *reinterpret_cast<uint32_t*>(pc_) = x;
1434    pc_ += 4;
1435  }
1436
1437  // Helper to emit the binary encoding of a 6 byte instruction
1438  void emit6bytes(uint64_t x) {
1439    CheckBuffer();
1440#if V8_TARGET_LITTLE_ENDIAN
1441    // We need to emit instructions in big endian format as disassembler /
1442    // simulator require the first byte of the instruction in order to decode
1443    // the instruction length.  Swap the bytes.
1444    x = (static_cast<uint64_t>(x & 0xFF) << 40) |
1445        (static_cast<uint64_t>((x >> 8) & 0xFF) << 32) |
1446        (static_cast<uint64_t>((x >> 16) & 0xFF) << 24) |
1447        (static_cast<uint64_t>((x >> 24) & 0xFF) << 16) |
1448        (static_cast<uint64_t>((x >> 32) & 0xFF) << 8) |
1449        (static_cast<uint64_t>((x >> 40) & 0xFF));
1450    x |= (*reinterpret_cast<uint64_t*>(pc_) >> 48) << 48;
1451#else
1452    // We need to pad two bytes of zeros in order to get the 6-bytes
1453    // stored from low address.
1454    x = x << 16;
1455    x |= *reinterpret_cast<uint64_t*>(pc_) & 0xFFFF;
1456#endif
1457    // It is safe to store 8-bytes, as CheckBuffer() guarantees we have kGap
1458    // space left over.
1459    *reinterpret_cast<uint64_t*>(pc_) = x;
1460    pc_ += 6;
1461  }
1462
1463  // Labels
1464  void print(Label* L);
1465  int max_reach_from(int pos);
1466  void bind_to(Label* L, int pos);
1467  void next(Label* L);
1468
1469  void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
1470
1471  int WriteCodeComments();
1472
1473  friend class RegExpMacroAssemblerS390;
1474  friend class RelocInfo;
1475  friend class EnsureSpace;
1476  friend class UseScratchRegisterScope;
1477};
1478
1479class EnsureSpace {
1480 public:
1481  explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1482};
1483
1484class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope {
1485 public:
1486  explicit UseScratchRegisterScope(Assembler* assembler);
1487  ~UseScratchRegisterScope();
1488
1489  Register Acquire();
1490
1491  // Check if we have registers available to acquire.
1492  bool CanAcquire() const {
1493    return !assembler_->GetScratchRegisterList()->is_empty();
1494  }
1495
1496 private:
1497  friend class Assembler;
1498  friend class TurboAssembler;
1499
1500  Assembler* assembler_;
1501  RegList old_available_;
1502};
1503
1504}  // namespace internal
1505}  // namespace v8
1506
1507#endif  // V8_CODEGEN_S390_ASSEMBLER_S390_H_
1508