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