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