• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
81 namespace v8 {
82 namespace internal {
83 
84 class 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
91 class V8_EXPORT_PRIVATE Operand {
92  public:
93   // immediate
94   V8_INLINE explicit Operand(intptr_t immediate,
95                              RelocInfo::Mode rmode = RelocInfo::NO_INFO)
rmode_(rmode)96       : rmode_(rmode) {
97     value_.immediate = immediate;
98   }
Zero()99   V8_INLINE static Operand Zero() { return Operand(static_cast<intptr_t>(0)); }
Operand(const ExternalReference & f)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);
Operand(Smi value)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.
is_reg()116   V8_INLINE bool is_reg() const { return rm_.is_valid(); }
117 
118   bool must_output_reloc_info(const Assembler* assembler) const;
119 
immediate()120   inline intptr_t immediate() const {
121     DCHECK(!rm_.is_valid());
122     DCHECK(!is_heap_object_request());
123     return value_.immediate;
124   }
125 
heap_object_request()126   HeapObjectRequest heap_object_request() const {
127     DCHECK(is_heap_object_request());
128     return value_.heap_object_request;
129   }
130 
setBits(int n)131   inline void setBits(int n) {
132     value_.immediate =
133         (static_cast<uint32_t>(value_.immediate) << (32 - n)) >> (32 - n);
134   }
135 
rm()136   Register rm() const { return rm_; }
137 
is_heap_object_request()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 
rmode()146   RelocInfo::Mode rmode() const { return rmode_; }
147 
148  private:
149   Register rm_ = no_reg;
150   union Value {
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 
163 using 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
170 class 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 
offset()175   int32_t offset() const { return offset_; }
getDisplacement()176   uint32_t getDisplacement() const { return offset(); }
177 
178   // Base register
rb()179   Register rb() const {
180     DCHECK(baseRegister != no_reg);
181     return baseRegister;
182   }
183 
getBaseRegister()184   Register getBaseRegister() const { return rb(); }
185 
186   // Index Register
rx()187   Register rx() const {
188     DCHECK(indexRegister != no_reg);
189     return indexRegister;
190   }
getIndexRegister()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 
201 class DeferredRelocInfo {
202  public:
DeferredRelocInfo()203   DeferredRelocInfo() {}
DeferredRelocInfo(int position,RelocInfo::Mode rmode,intptr_t data)204   DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
205       : position_(position), rmode_(rmode), data_(data) {}
206 
position()207   int position() const { return position_; }
rmode()208   RelocInfo::Mode rmode() const { return rmode_; }
data()209   intptr_t data() const { return data_; }
210 
211  private:
212   int position_;
213   RelocInfo::Mode rmode_;
214   intptr_t data_;
215 };
216 
217 class 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 
~Assembler()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.
GetCode(Isolate * isolate,CodeDesc * desc)239   void GetCode(Isolate* isolate, CodeDesc* desc) {
240     GetCode(isolate, desc, kNoSafepointTable, kNoHandlerTable);
241   }
242 
243   // Unused on this architecture.
MaybeEmitOutOfLineConstantPool()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
branch_offset(Label * L)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 
GetScratchRegisterList()320   RegList* GetScratchRegisterList() { return &scratch_register_list_; }
321 
322   // ---------------------------------------------------------------------------
323   // Code generation
324 
325   template <class T, int size, int lo, int hi>
getfield(T value)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 
ril_format(Opcode opcode,int f1,int f2)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)
S390_RIL_B_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   }
S390_RR_OPCODE_LIST(DECLARE_S390_RR_INSTRUCTIONS)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   }
S390_RRD_OPCODE_LIST(DECLARE_S390_RRD_INSTRUCTIONS)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   }
S390_RRE_OPCODE_LIST(DECLARE_S390_RRE_INSTRUCTIONS)401   S390_RRE_OPCODE_LIST(DECLARE_S390_RRE_INSTRUCTIONS)
402   // Special format
403   void lzdr(DoubleRegister r1) { rre_format(LZDR, r1.code(), 0); }
lzer(DoubleRegister r1)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 
rx_format(Opcode opcode,int f1,int f2,int f3,int f4)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   }
S390_RX_A_OPCODE_LIST(DECLARE_S390_RX_INSTRUCTIONS)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   }
bc(Condition cond,Register x2,Register b2,const Operand & d2)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 
rxy_format(Opcode opcode,int f1,int f2,int f3,int f4)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   }
S390_RXY_A_OPCODE_LIST(DECLARE_S390_RXY_INSTRUCTIONS)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   }
pfd(Condition cond,Register x2,Register b2,const Operand & d2)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 
rsy_format(Opcode op,int f1,int f2,int f3,int f4)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   }
S390_RSY_B_OPCODE_LIST(DECLARE_S390_RSY_B_INSTRUCTIONS)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   }
S390_RS_B_OPCODE_LIST(DECLARE_S390_RS_B_INSTRUCTIONS)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   }
S390_RXE_OPCODE_LIST(DECLARE_S390_RXE_INSTRUCTIONS)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   }
S390_RI_B_OPCODE_LIST(DECLARE_S390_RI_B_INSTRUCTIONS)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   }
S390_RRF_B_OPCODE_LIST(DECLARE_S390_RRF_B_INSTRUCTIONS)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   }
S390_RSI_OPCODE_LIST(DECLARE_S390_RSI_INSTRUCTIONS)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   }
S390_RSL_B_OPCODE_LIST(DECLARE_S390_RSL_B_INSTRUCTIONS)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   }
S390_S_OPCODE_LIST(DECLARE_S390_S_INSTRUCTIONS)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   }
S390_SI_OPCODE_LIST(DECLARE_S390_SI_INSTRUCTIONS)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   }
S390_SIY_OPCODE_LIST(DECLARE_S390_SIY_INSTRUCTIONS)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   }
S390_RRS_OPCODE_LIST(DECLARE_S390_RRS_INSTRUCTIONS)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   }
S390_RIS_OPCODE_LIST(DECLARE_S390_RIS_INSTRUCTIONS)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   }
S390_SIL_OPCODE_LIST(DECLARE_S390_SIL_INSTRUCTIONS)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   }
S390_RIE_D_OPCODE_LIST(DECLARE_S390_RIE_D_INSTRUCTIONS)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   }
S390_RIE_E_OPCODE_LIST(DECLARE_S390_RIE_E_INSTRUCTIONS)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   }
S390_RIE_F_OPCODE_LIST(DECLARE_S390_RIE_F_INSTRUCTIONS)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   }
S390_SS_A_OPCODE_LIST(DECLARE_S390_SS_A_INSTRUCTIONS)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   }
bc_long(Condition cond,Label * l)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
b(Condition cond,Register r)980   void b(Condition cond, Register r) { bcr(cond, r); }
beq(Register r)981   void beq(Register r) { b(eq, r); }
bne(Register r)982   void bne(Register r) { b(ne, r); }
blt(Register r)983   void blt(Register r) { b(lt, r); }
ble(Register r)984   void ble(Register r) { b(le, r); }
bgt(Register r)985   void bgt(Register r) { b(gt, r); }
bge(Register r)986   void bge(Register r) { b(ge, r); }
b(Register r)987   void b(Register r) { b(al, r); }
jmp(Register r)988   void jmp(Register r) { b(al, r); }
bunordered(Register r)989   void bunordered(Register r) { b(unordered, r); }
bordered(Register r)990   void bordered(Register r) { b(ordered, r); }
991 
992   // wrappers around asm instr
brxh(Register dst,Register inc,Label * L)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 
brxhg(Register dst,Register inc,Label * L)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>
ledbr(R1 r1,R2 r2)1006   void ledbr(R1 r1, R2 r2) {
1007     ledbra(Condition(0), Condition(0), r1, r2);
1008   }
1009 
1010   template <class R1, class R2>
cdfbr(R1 r1,R2 r2)1011   void cdfbr(R1 r1, R2 r2) {
1012     cdfbra(Condition(0), Condition(0), r1, r2);
1013   }
1014 
1015   template <class R1, class R2>
cdgbr(R1 r1,R2 r2)1016   void cdgbr(R1 r1, R2 r2) {
1017     cdgbra(Condition(0), Condition(0), r1, r2);
1018   }
1019 
1020   template <class R1, class R2>
cegbr(R1 r1,R2 r2)1021   void cegbr(R1 r1, R2 r2) {
1022     cegbra(Condition(0), Condition(0), r1, r2);
1023   }
1024 
1025   template <class R1, class R2>
cgebr(Condition m3,R1 r1,R2 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>
cgdbr(Condition m3,R1 r1,R2 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>
cfdbr(Condition m3,R1 r1,R2 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>
cfebr(Condition m3,R1 r1,R2 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();
LoopHeaderAlign()1057   void LoopHeaderAlign() { CodeTargetAlign(); }
1058 
breakpoint(bool do_print)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   }
S390_VRR_C_OPCODE_LIST(DECLARE_VRR_C_INSTRUCTIONS)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   }
vfs(DoubleRegister v1,DoubleRegister v2,DoubleRegister v3)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   }
vfm(DoubleRegister v1,DoubleRegister v2,DoubleRegister v3)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   }
vfd(DoubleRegister v1,DoubleRegister v2,DoubleRegister v3)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.
SizeOfCodeGeneratedSince(Label * label)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
instr_at(int pos)1319   SixByteInstr instr_at(int pos) {
1320     return Instruction::InstructionBits(buffer_start_ + pos);
1321   }
1322   template <typename T>
instr_at_put(int pos,T instr)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
instr_length_at(int pos)1328   int32_t instr_length_at(int pos) {
1329     return Instruction::InstructionLength(buffer_start_ + pos);
1330   }
1331 
instr_at(byte * pc)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:
buffer_pos()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:
buffer_space()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
CheckBuffer()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
emit2bytes(uint16_t x)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
emit4bytes(uint32_t x)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
emit6bytes(uint64_t x)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 
1479 class EnsureSpace {
1480  public:
EnsureSpace(Assembler * assembler)1481   explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1482 };
1483 
1484 class 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.
CanAcquire()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