40 #ifndef V8_S390_ASSEMBLER_S390_H_ 41 #define V8_S390_ASSEMBLER_S390_H_ 53 #include "src/assembler.h" 54 #include "src/external-reference.h" 55 #include "src/label.h" 56 #include "src/objects/smi.h" 57 #include "src/s390/constants-s390.h" 59 #define ABI_USES_FUNCTION_DESCRIPTORS 0 61 #define ABI_PASSES_HANDLES_IN_REGS 1 72 #if V8_TARGET_ARCH_S390X 73 #define ABI_RETURNS_OBJECTPAIR_IN_REGS 0 75 #define ABI_RETURNS_OBJECTPAIR_IN_REGS 1 78 #define ABI_CALL_VIA_IP 1 80 #define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC 86 #define GENERAL_REGISTERS(V) \ 87 V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \ 88 V(r8) V(r9) V(r10) V(fp) V(ip) V(r13) V(r14) V(sp) 90 #define ALLOCATABLE_GENERAL_REGISTERS(V) \ 91 V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \ 94 #define DOUBLE_REGISTERS(V) \ 95 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ 96 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) 98 #define FLOAT_REGISTERS DOUBLE_REGISTERS 99 #define SIMD128_REGISTERS DOUBLE_REGISTERS 101 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \ 102 V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ 103 V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) V(d0) 105 #define C_REGISTERS(V) \ 106 V(cr0) V(cr1) V(cr2) V(cr3) V(cr4) V(cr5) V(cr6) V(cr7) \ 107 V(cr8) V(cr9) V(cr10) V(cr11) V(cr12) V(cr15) 112 const int kNumRegs = 16;
115 const RegList kJSCallerSaved = 1 << 1 | 1 << 2 |
120 const int kNumJSCallerSaved = 5;
123 const RegList kCalleeSaved =
137 const int kNumCalleeSaved = 8;
139 #ifdef V8_TARGET_ARCH_S390X 141 const RegList kCallerSavedDoubles = 1 << 0 |
150 const int kNumCallerSavedDoubles = 8;
152 const RegList kCalleeSavedDoubles = 1 << 8 |
161 const int kNumCalleeSavedDoubles = 8;
165 const RegList kCallerSavedDoubles = 1 << 14 |
180 const int kNumCallerSavedDoubles = 14;
182 const RegList kCalleeSavedDoubles = 1 << 4 |
185 const int kNumCalleeSavedDoubles = 2;
192 const int kNumSafepointRegisters = 16;
197 const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
198 const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
203 #if V8_TARGET_ARCH_S390X 214 const int kNumRequiredStackFrameSlots = 20;
215 const int kStackFrameRASlot = 14;
216 const int kStackFrameSPSlot = 15;
217 const int kStackFrameExtraParamSlot = 20;
229 const int kNumRequiredStackFrameSlots = 24;
230 const int kStackFrameRASlot = 14;
231 const int kStackFrameSPSlot = 15;
232 const int kStackFrameExtraParamSlot = 24;
237 #if V8_TARGET_ARCH_S390X 238 const int kCalleeRegisterSaveAreaSize = 160;
239 #elif V8_TARGET_ARCH_S390 240 const int kCalleeRegisterSaveAreaSize = 96;
242 const int kCalleeRegisterSaveAreaSize = 0;
246 #define REGISTER_CODE(R) kRegCode_##R, 247 GENERAL_REGISTERS(REGISTER_CODE)
252 class Register :
public RegisterBase<Register, kRegAfterLast> {
254 #if V8_TARGET_LITTLE_ENDIAN 255 static constexpr
int kMantissaOffset = 0;
256 static constexpr
int kExponentOffset = 4;
258 static constexpr
int kMantissaOffset = 4;
259 static constexpr
int kExponentOffset = 0;
263 friend class RegisterBase;
264 explicit constexpr Register(
int code) : RegisterBase(code) {}
267 ASSERT_TRIVIALLY_COPYABLE(Register);
268 static_assert(
sizeof(Register) ==
sizeof(
int),
269 "Register can efficiently be passed by value");
271 #define DEFINE_REGISTER(R) \ 272 constexpr Register R = Register::from_code<kRegCode_##R>(); 273 GENERAL_REGISTERS(DEFINE_REGISTER)
274 #undef DEFINE_REGISTER 275 constexpr Register no_reg = Register::no_reg();
278 constexpr Register kRootRegister = r10;
279 constexpr Register cp = r13;
281 constexpr
bool kPadArguments =
false;
282 constexpr
bool kSimpleFPAliasing =
true;
283 constexpr
bool kSimdMaskRegisters =
false;
285 enum DoubleRegisterCode {
286 #define REGISTER_CODE(R) kDoubleCode_##R, 287 DOUBLE_REGISTERS(REGISTER_CODE)
293 class DoubleRegister :
public RegisterBase<DoubleRegister, kDoubleAfterLast> {
299 static constexpr
int kSizeInBytes = 8;
300 inline static int NumRegisters();
303 friend class RegisterBase;
305 explicit constexpr DoubleRegister(
int code) : RegisterBase(code) {}
308 ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
309 static_assert(
sizeof(DoubleRegister) ==
sizeof(
int),
310 "DoubleRegister can efficiently be passed by value");
312 typedef DoubleRegister FloatRegister;
315 typedef DoubleRegister Simd128Register;
317 #define DEFINE_REGISTER(R) \ 318 constexpr DoubleRegister R = DoubleRegister::from_code<kDoubleCode_##R>(); 319 DOUBLE_REGISTERS(DEFINE_REGISTER)
320 #undef DEFINE_REGISTER 321 constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
323 constexpr DoubleRegister kDoubleRegZero = d14;
324 constexpr DoubleRegister kScratchDoubleReg = d13;
326 Register ToRegister(
int num);
329 #define REGISTER_CODE(R) kCCode_##R, 330 C_REGISTERS(REGISTER_CODE)
336 class CRegister :
public RegisterBase<CRegister, kCAfterLast> {
337 friend class RegisterBase;
338 explicit constexpr CRegister(
int code) : RegisterBase(code) {}
341 constexpr CRegister no_creg = CRegister::no_reg();
342 #define DECLARE_C_REGISTER(R) \ 343 constexpr CRegister R = CRegister::from_code<kCCode_##R>(); 344 C_REGISTERS(DECLARE_C_REGISTER)
345 #undef DECLARE_C_REGISTER 355 V8_INLINE
explicit Operand(intptr_t immediate,
356 RelocInfo::Mode rmode = RelocInfo::NONE)
358 value_.immediate = immediate;
360 V8_INLINE
static Operand Zero() {
return Operand(static_cast<intptr_t>(0)); }
361 V8_INLINE
explicit Operand(
const ExternalReference& f)
362 : rmode_(RelocInfo::EXTERNAL_REFERENCE) {
363 value_.immediate =
static_cast<intptr_t
>(f.address());
365 explicit Operand(Handle<HeapObject> handle);
366 V8_INLINE
explicit Operand(Smi value) : rmode_(RelocInfo::NONE) {
367 value_.immediate =
static_cast<intptr_t
>(value.ptr());
371 V8_INLINE
explicit Operand(Register rm);
373 static Operand EmbeddedNumber(
double value);
374 static Operand EmbeddedStringConstant(
const StringConstantBase* str);
377 V8_INLINE
bool is_reg()
const {
return rm_.is_valid(); }
379 bool must_output_reloc_info(
const Assembler* assembler)
const;
381 inline intptr_t immediate()
const {
382 DCHECK(!rm_.is_valid());
383 DCHECK(!is_heap_object_request());
384 return value_.immediate;
387 HeapObjectRequest heap_object_request()
const {
388 DCHECK(is_heap_object_request());
389 return value_.heap_object_request;
392 inline void setBits(
int n) {
394 (
static_cast<uint32_t>(value_.immediate) << (32 - n)) >> (32 - n);
397 Register rm()
const {
return rm_; }
399 bool is_heap_object_request()
const {
400 DCHECK_IMPLIES(is_heap_object_request_, !rm_.is_valid());
401 DCHECK_IMPLIES(is_heap_object_request_,
402 rmode_ == RelocInfo::EMBEDDED_OBJECT ||
403 rmode_ == RelocInfo::CODE_TARGET);
404 return is_heap_object_request_;
407 RelocInfo::Mode rmode()
const {
return rmode_; }
410 Register rm_ = no_reg;
413 HeapObjectRequest heap_object_request;
416 bool is_heap_object_request_ =
false;
418 RelocInfo::Mode rmode_;
420 friend class Assembler;
421 friend class MacroAssembler;
424 typedef int32_t Disp;
433 explicit MemOperand(Register rx, Disp offset = 0);
434 explicit MemOperand(Register rx, Register rb, Disp offset = 0);
436 int32_t offset()
const {
return offset_; }
437 uint32_t getDisplacement()
const {
return offset(); }
440 Register rb()
const {
441 DCHECK(baseRegister != no_reg);
445 Register getBaseRegister()
const {
return rb(); }
448 Register rx()
const {
449 DCHECK(indexRegister != no_reg);
450 return indexRegister;
452 Register getIndexRegister()
const {
return rx(); }
455 Register baseRegister;
456 Register indexRegister;
459 friend class Assembler;
462 class DeferredRelocInfo {
464 DeferredRelocInfo() {}
465 DeferredRelocInfo(
int position, RelocInfo::Mode rmode, intptr_t data)
466 : position_(position), rmode_(rmode), data_(data) {}
468 int position()
const {
return position_; }
469 RelocInfo::Mode rmode()
const {
return rmode_; }
470 intptr_t data()
const {
return data_; }
474 RelocInfo::Mode rmode_;
478 class V8_EXPORT_PRIVATE Assembler :
public AssemblerBase {
494 Assembler(
const AssemblerOptions& options,
void* buffer,
int buffer_size);
495 virtual ~Assembler() {}
500 void GetCode(Isolate* isolate, CodeDesc* desc);
526 bool is_near(Label* L, Condition cond);
530 int branch_offset(Label* L) {
return link(L) - pc_offset(); }
534 void label_at_put(Label* L,
int at_offset);
535 void load_label_offset(Register r1, Label* L);
539 V8_INLINE
static Address target_address_at(Address pc, Address constant_pool);
540 V8_INLINE
static void set_target_address_at(
541 Address pc, Address constant_pool, Address target,
542 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
546 inline static Address target_address_from_return_address(Address pc);
550 V8_INLINE
static Address return_address_from_call_start(Address pc);
552 inline Handle<Object> code_target_object_handle_at(Address pc);
555 inline static void deserialization_set_special_target_at(
556 Address instruction_payload, Code code, Address target);
559 inline static int deserialization_special_target_size(
560 Address instruction_payload);
563 inline static void deserialization_set_target_internal_reference_at(
564 Address pc, Address target,
565 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
573 static constexpr
int kSpecialTargetSize = 0;
576 #if V8_TARGET_ARCH_S390X 577 static constexpr
int kBytesForPtrConstant = 12;
579 static constexpr
int kBytesForPtrConstant = 6;
588 static constexpr
int kCallTargetAddressOffset = 6;
594 #if V8_TARGET_ARCH_S390X 595 static constexpr
int kCallSequenceLength = 14;
597 static constexpr
int kCallSequenceLength = 8;
603 template <
class T,
int size,
int lo,
int hi>
604 inline T getfield(T value) {
608 int shift = size * 8 - hi;
609 uint32_t mask_value = (mask == 32) ? 0xffffffff : (1 << mask) - 1;
610 return (value & mask_value) << shift;
613 #define DECLARE_S390_RIL_AB_INSTRUCTIONS(name, op_name, op_value) \ 614 template <class R1> \ 615 inline void name(R1 r1, const Operand& i2) { \ 616 ril_format(op_name, r1.code(), i2.immediate()); \ 618 #define DECLARE_S390_RIL_C_INSTRUCTIONS(name, op_name, op_value) \ 619 inline void name(Condition m1, const Operand& i2) { \ 620 ril_format(op_name, m1, i2.immediate()); \ 623 inline void ril_format(Opcode opcode,
int f1,
int f2) {
627 getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) |
628 getfield<uint64_t, 6, 12, 16>(op2) | getfield<uint64_t, 6, 16, 48>(f2));
630 S390_RIL_A_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)
631 S390_RIL_B_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)
632 S390_RIL_C_OPCODE_LIST(DECLARE_S390_RIL_C_INSTRUCTIONS)
633 #undef DECLARE_S390_RIL_AB_INSTRUCTIONS 634 #undef DECLARE_S390_RIL_C_INSTRUCTIONS 636 #define DECLARE_S390_RR_INSTRUCTIONS(name, op_name, op_value) \ 637 inline void name(Register r1, Register r2) { \ 638 rr_format(op_name, r1.code(), r2.code()); \ 640 inline void name(DoubleRegister r1, DoubleRegister r2) { \ 641 rr_format(op_name, r1.code(), r2.code()); \ 643 inline void name(Condition m1, Register r2) { \ 644 rr_format(op_name, m1, r2.code()); \ 647 inline void rr_format(Opcode opcode,
int f1,
int f2) {
648 emit2bytes(getfield<uint16_t, 2, 0, 8>(opcode) |
649 getfield<uint16_t, 2, 8, 12>(f1) |
650 getfield<uint16_t, 2, 12, 16>(f2));
652 S390_RR_OPCODE_LIST(DECLARE_S390_RR_INSTRUCTIONS)
653 #undef DECLARE_S390_RR_INSTRUCTIONS 655 #define DECLARE_S390_RRD_INSTRUCTIONS(name, op_name, op_value) \ 656 template <class R1, class R2, class R3> \ 657 inline void name(R1 r1, R3 r3, R2 r2) { \ 658 rrd_format(op_name, r1.code(), r3.code(), r2.code()); \ 660 inline void rrd_format(Opcode opcode,
int f1,
int f2,
int f3) {
661 emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) |
662 getfield<uint32_t, 4, 16, 20>(f1) |
663 getfield<uint32_t, 4, 24, 28>(f2) |
664 getfield<uint32_t, 4, 28, 32>(f3));
666 S390_RRD_OPCODE_LIST(DECLARE_S390_RRD_INSTRUCTIONS)
667 #undef DECLARE_S390_RRD_INSTRUCTIONS 669 #define DECLARE_S390_RRE_INSTRUCTIONS(name, op_name, op_value) \ 670 template <class R1, class R2> \ 671 inline void name(R1 r1, R2 r2) { \ 672 rre_format(op_name, r1.code(), r2.code()); \ 674 inline void rre_format(Opcode opcode,
int f1,
int f2) {
675 emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) |
676 getfield<uint32_t, 4, 24, 28>(f1) |
677 getfield<uint32_t, 4, 28, 32>(f2));
679 S390_RRE_OPCODE_LIST(DECLARE_S390_RRE_INSTRUCTIONS)
681 void lzdr(DoubleRegister r1) { rre_format(LZDR, r1.code(), 0); }
682 #undef DECLARE_S390_RRE_INSTRUCTIONS 684 #define DECLARE_S390_RX_INSTRUCTIONS(name, op_name, op_value) \ 685 template <class R1> \ 686 inline void name(R1 r1, Register x2, Register b2, const Operand& d2) { \ 687 rx_format(op_name, r1.code(), x2.code(), b2.code(), \ 690 template <class R1> \ 691 inline void name(R1 r1, const MemOperand& opnd) { \ 692 name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \ 693 Operand(opnd.getDisplacement())); \ 696 inline void rx_format(Opcode opcode,
int f1,
int f2,
int f3,
int f4) {
697 DCHECK(is_uint8(opcode));
698 DCHECK(is_uint12(f4));
699 emit4bytes(getfield<uint32_t, 4, 0, 8>(opcode) |
700 getfield<uint32_t, 4, 8, 12>(f1) |
701 getfield<uint32_t, 4, 12, 16>(f2) |
702 getfield<uint32_t, 4, 16, 20>(f3) |
703 getfield<uint32_t, 4, 20, 32>(f4));
705 S390_RX_A_OPCODE_LIST(DECLARE_S390_RX_INSTRUCTIONS)
707 void bc(Condition cond,
const MemOperand& opnd) {
708 bc(cond, opnd.getIndexRegister(),
709 opnd.getBaseRegister(), Operand(opnd.getDisplacement()));
711 void bc(Condition cond, Register x2, Register b2,
const Operand& d2) {
712 rx_format(BC, cond, x2.code(), b2.code(), d2.immediate());
714 #undef DECLARE_S390_RX_INSTRUCTIONS 716 #define DECLARE_S390_RXY_INSTRUCTIONS(name, op_name, op_value) \ 717 template <class R1, class R2> \ 718 inline void name(R1 r1, R2 r2, Register b2, const Operand& d2) { \ 719 rxy_format(op_name, r1.code(), r2.code(), b2.code(), d2.immediate()); \ 721 template <class R1> \ 722 inline void name(R1 r1, const MemOperand& opnd) { \ 723 name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \ 724 Operand(opnd.getDisplacement())); \ 727 inline void rxy_format(Opcode opcode,
int f1,
int f2,
int f3,
int f4) {
728 DCHECK(is_uint16(opcode));
729 DCHECK(is_int20(f4));
730 emit6bytes(getfield<uint64_t, 6, 0, 8>(opcode >> 8) |
731 getfield<uint64_t, 6, 8, 12>(f1) |
732 getfield<uint64_t, 6, 12, 16>(f2) |
733 getfield<uint64_t, 6, 16, 20>(f3) |
734 getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
735 getfield<uint64_t, 6, 32, 40>(f4 >> 12) |
736 getfield<uint64_t, 6, 40, 48>(opcode & 0x00ff));
738 S390_RXY_A_OPCODE_LIST(DECLARE_S390_RXY_INSTRUCTIONS)
740 void pfd(Condition cond,
const MemOperand& opnd) {
741 pfd(cond, opnd.getIndexRegister(),
742 opnd.getBaseRegister(), Operand(opnd.getDisplacement()));
744 void pfd(Condition cond, Register x2, Register b2,
const Operand& d2) {
745 rxy_format(PFD, cond, x2.code(), b2.code(), d2.immediate());
747 #undef DECLARE_S390_RXY_INSTRUCTIONS 750 inline void rsy_format(Opcode op,
int f1,
int f2,
int f3,
int f4) {
751 DCHECK(is_int20(f4));
752 DCHECK(is_uint16(op));
753 uint64_t code = (getfield<uint64_t, 6, 0, 8>(op >> 8) |
754 getfield<uint64_t, 6, 8, 12>(f1) |
755 getfield<uint64_t, 6, 12, 16>(f2) |
756 getfield<uint64_t, 6, 16, 20>(f3) |
757 getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
758 getfield<uint64_t, 6, 32, 40>(f4 >> 12) |
759 getfield<uint64_t, 6, 40, 48>(op & 0xff));
763 #define DECLARE_S390_RSY_A_INSTRUCTIONS(name, op_name, op_value) \ 764 void name(Register r1, Register r3, Register b2, \ 765 const Operand& d2 = Operand::Zero()) { \ 766 rsy_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate()); \ 768 void name(Register r1, Register r3, Operand d2) { \ 769 name(r1, r3, r0, d2); \ 771 void name(Register r1, Register r3, const MemOperand& opnd) { \ 772 name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \ 774 S390_RSY_A_OPCODE_LIST(DECLARE_S390_RSY_A_INSTRUCTIONS);
775 #undef DECLARE_S390_RSY_A_INSTRUCTIONS 777 #define DECLARE_S390_RSY_B_INSTRUCTIONS(name, op_name, op_value) \ 778 void name(Register r1, Condition m3, Register b2, const Operand& d2) { \ 779 rsy_format(op_name, r1.code(), m3, b2.code(), d2.immediate()); \ 781 void name(Register r1, Condition m3, const MemOperand& opnd) { \ 782 name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \ 784 S390_RSY_B_OPCODE_LIST(DECLARE_S390_RSY_B_INSTRUCTIONS);
785 #undef DECLARE_S390_RSY_B_INSTRUCTIONS 788 inline void rs_format(Opcode op,
int f1,
int f2,
int f3,
const int f4) {
789 uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
790 getfield<uint32_t, 4, 8, 12>(f1) |
791 getfield<uint32_t, 4, 12, 16>(f2) |
792 getfield<uint32_t, 4, 16, 20>(f3) |
793 getfield<uint32_t, 4, 20, 32>(f4);
797 #define DECLARE_S390_RS_A_INSTRUCTIONS(name, op_name, op_value) \ 798 void name(Register r1, Register r3, Register b2, const Operand& d2) { \ 799 rs_format(op_name, r1.code(), r3.code(), b2.code(), d2.immediate()); \ 801 void name(Register r1, Register r3, const MemOperand& opnd) { \ 802 name(r1, r3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \ 804 S390_RS_A_OPCODE_LIST(DECLARE_S390_RS_A_INSTRUCTIONS);
805 #undef DECLARE_S390_RS_A_INSTRUCTIONS 807 #define DECLARE_S390_RS_B_INSTRUCTIONS(name, op_name, op_value) \ 808 void name(Register r1, Condition m3, Register b2, const Operand& d2) { \ 809 rs_format(op_name, r1.code(), m3, b2.code(), d2.immediate()); \ 811 void name(Register r1, Condition m3, const MemOperand& opnd) { \ 812 name(r1, m3, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \ 814 S390_RS_B_OPCODE_LIST(DECLARE_S390_RS_B_INSTRUCTIONS);
815 #undef DECLARE_S390_RS_B_INSTRUCTIONS 817 #define DECLARE_S390_RS_SHIFT_FORMAT(name, opcode) \ 818 void name(Register r1, Register r2, const Operand& opnd = \ 821 rs_format(opcode, r1.code(), r0.code(), r2.code(), opnd.immediate()); \ 823 void name(Register r1, const Operand& opnd) { \ 824 rs_format(opcode, r1.code(), r0.code(), r0.code(), opnd.immediate()); \ 826 DECLARE_S390_RS_SHIFT_FORMAT(sll, SLL)
827 DECLARE_S390_RS_SHIFT_FORMAT(srl, SRL)
828 DECLARE_S390_RS_SHIFT_FORMAT(sla, SLA)
829 DECLARE_S390_RS_SHIFT_FORMAT(sra, SRA)
830 DECLARE_S390_RS_SHIFT_FORMAT(sldl, SLDL)
831 DECLARE_S390_RS_SHIFT_FORMAT(srda, SRDA)
832 DECLARE_S390_RS_SHIFT_FORMAT(srdl, SRDL)
833 #undef DECLARE_S390_RS_SHIFT_FORMAT 836 inline void rxe_format(Opcode op,
int f1,
int f2,
int f3,
int f4,
int f5 = 0) {
837 DCHECK(is_uint12(f4));
838 DCHECK(is_uint16(op));
839 uint64_t code = (getfield<uint64_t, 6, 0, 8>(op >> 8) |
840 getfield<uint64_t, 6, 8, 12>(f1) |
841 getfield<uint64_t, 6, 12, 16>(f2) |
842 getfield<uint64_t, 6, 16, 20>(f3) |
843 getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) |
844 getfield<uint64_t, 6, 32, 36>(f5) |
845 getfield<uint64_t, 6, 40, 48>(op & 0xff));
849 #define DECLARE_S390_RXE_INSTRUCTIONS(name, op_name, op_value) \ 850 void name(Register r1, Register x2, Register b2, const Operand& d2, \ 851 Condition m3 = static_cast<Condition>(0)) { \ 852 rxe_format(op_name, r1.code(), x2.code(), b2.code(), d2.immediate(), \ 855 template<class _R1Type> \ 856 void name(_R1Type r1, const MemOperand& opnd) { \ 857 name(Register::from_code(r1.code()), opnd.rx(), opnd.rb(), \ 858 Operand(opnd.offset())); \ 860 S390_RXE_OPCODE_LIST(DECLARE_S390_RXE_INSTRUCTIONS);
861 #undef DECLARE_S390_RXE_INSTRUCTIONS 864 inline void ri_format(Opcode opcode,
int f1,
int f2) {
867 emit4bytes(getfield<uint32_t, 4, 0, 8>(op1) |
868 getfield<uint32_t, 4, 8, 12>(f1) |
869 getfield<uint32_t, 4, 12, 16>(op2) |
870 getfield<uint32_t, 4, 16, 32>(f2));
873 #define DECLARE_S390_RI_A_INSTRUCTIONS(name, op_name, op_value) \ 874 void name(Register r, const Operand& i2) { \ 875 DCHECK(is_uint12(op_name)); \ 876 DCHECK(is_uint16(i2.immediate()) || is_int16(i2.immediate())); \ 877 ri_format(op_name, r.code(), i2.immediate()); \ 879 S390_RI_A_OPCODE_LIST(DECLARE_S390_RI_A_INSTRUCTIONS);
880 #undef DECLARE_S390_RI_A_INSTRUCTIONS 882 #define DECLARE_S390_RI_B_INSTRUCTIONS(name, op_name, op_value) \ 883 void name(Register r1, const Operand& imm) { \ 885 int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2; \ 886 Operand halfwordOp = Operand(numHalfwords); \ 887 halfwordOp.setBits(16); \ 888 ri_format(op_name, r1.code(), halfwordOp.immediate()); \ 890 S390_RI_B_OPCODE_LIST(DECLARE_S390_RI_B_INSTRUCTIONS);
891 #undef DECLARE_S390_RI_B_INSTRUCTIONS 893 #define DECLARE_S390_RI_C_INSTRUCTIONS(name, op_name, op_value) \ 894 void name(Condition m, const Operand& i2) { \ 895 DCHECK(is_uint12(op_name)); \ 896 DCHECK(is_uint4(m)); \ 897 DCHECK(op_name == BRC ? \ 898 is_int16(i2.immediate()) : is_uint16(i2.immediate())); \ 899 ri_format(op_name, m, i2.immediate()); \ 901 S390_RI_C_OPCODE_LIST(DECLARE_S390_RI_C_INSTRUCTIONS);
902 #undef DECLARE_S390_RI_C_INSTRUCTIONS 905 inline void rrf_format(Opcode op,
int f1,
int f2,
int f3,
int f4) {
906 uint32_t code = getfield<uint32_t, 4, 0, 16>(op) |
907 getfield<uint32_t, 4, 16, 20>(f1) |
908 getfield<uint32_t, 4, 20, 24>(f2) |
909 getfield<uint32_t, 4, 24, 28>(f3) |
910 getfield<uint32_t, 4, 28, 32>(f4);
914 #define DECLARE_S390_RRF_A_INSTRUCTIONS(name, op_name, op_value) \ 915 void name(Register r1, Condition m4, Register r2, Register r3) { \ 916 rrf_format(op_name, r3.code(), m4, r1.code(), r2.code()); \ 918 void name(Register r1, Register r2, Register r3) { \ 919 name(r1, Condition(0), r2, r3); \ 921 S390_RRF_A_OPCODE_LIST(DECLARE_S390_RRF_A_INSTRUCTIONS);
922 #undef DECLARE_S390_RRF_A_INSTRUCTIONS 925 #define DECLARE_S390_RRF_B_INSTRUCTIONS(name, op_name, op_value) \ 926 void name(Register r1, Condition m4, Register r2, Register r3) { \ 927 rrf_format(op_name, r3.code(), m4, r1.code(), r2.code()); \ 929 void name(Register r1, Register r2, Register r3) { \ 930 name(r1, Condition(0), r2, r3); \ 932 S390_RRF_B_OPCODE_LIST(DECLARE_S390_RRF_B_INSTRUCTIONS);
933 #undef DECLARE_S390_RRF_B_INSTRUCTIONS 936 #define DECLARE_S390_RRF_C_INSTRUCTIONS(name, op_name, op_value) \ 937 template <class R1, class R2> \ 938 void name(Condition m3, Condition m4, R1 r1, R2 r2) { \ 939 rrf_format(op_name, m3, m4, r1.code(), r2.code()); \ 941 template <class R1, class R2> \ 942 void name(Condition m3, R1 r1, R2 r2) { \ 943 name(m3, Condition(0), r1, r2); \ 945 S390_RRF_C_OPCODE_LIST(DECLARE_S390_RRF_C_INSTRUCTIONS);
946 #undef DECLARE_S390_RRF_C_INSTRUCTIONS 949 #define DECLARE_S390_RRF_D_INSTRUCTIONS(name, op_name, op_value) \ 950 template <class R1, class R2> \ 951 void name(Condition m3, Condition m4, R1 r1, R2 r2) { \ 952 rrf_format(op_name, m3, m4, r1.code(), r2.code()); \ 954 template <class R1, class R2> \ 955 void name(Condition m3, R1 r1, R2 r2) { \ 956 name(m3, Condition(0), r1, r2); \ 958 S390_RRF_D_OPCODE_LIST(DECLARE_S390_RRF_D_INSTRUCTIONS);
959 #undef DECLARE_S390_RRF_D_INSTRUCTIONS 962 #define DECLARE_S390_RRF_E_INSTRUCTIONS(name, op_name, op_value) \ 963 template <class M3, class M4, class R1, class R2> \ 964 void name(M3 m3, M4 m4, R1 r1, R2 r2) { \ 965 rrf_format(op_name, m3, m4, r1.code(), r2.code()); \ 967 template <class M3, class R1, class R2> \ 968 void name(M3 m3, R1 r1, R2 r2) { \ 969 name(m3, Condition(0), r1, r2); \ 971 S390_RRF_E_OPCODE_LIST(DECLARE_S390_RRF_E_INSTRUCTIONS);
972 #undef DECLARE_S390_RRF_E_INSTRUCTIONS 975 FIDBRA_CURRENT_ROUNDING_MODE = 0,
976 FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0 = 1,
978 FIDBRA_ROUND_TOWARD_0 = 5,
979 FIDBRA_ROUND_TOWARD_POS_INF = 6,
980 FIDBRA_ROUND_TOWARD_NEG_INF = 7
984 inline void rsi_format(Opcode op,
int f1,
int f2,
int f3) {
985 DCHECK(is_uint8(op));
986 DCHECK(is_uint16(f3) || is_int16(f3));
987 uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
988 getfield<uint32_t, 4, 8, 12>(f1) |
989 getfield<uint32_t, 4, 12, 16>(f2) |
990 getfield<uint32_t, 4, 16, 32>(f3);
994 #define DECLARE_S390_RSI_INSTRUCTIONS(name, op_name, op_value) \ 995 void name(Register r1, Register r3, const Operand& i2) { \ 996 rsi_format(op_name, r1.code(), r3.code(), i2.immediate()); \ 998 S390_RSI_OPCODE_LIST(DECLARE_S390_RSI_INSTRUCTIONS);
999 #undef DECLARE_S390_RSI_INSTRUCTIONS 1002 inline void rsl_format(Opcode op, uint16_t f1,
int f2,
int f3,
int f4,
1004 DCHECK(is_uint16(op));
1005 uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1006 getfield<uint64_t, 6, 8, 16>(f1) |
1007 getfield<uint64_t, 6, 16, 20>(f2) |
1008 getfield<uint64_t, 6, 20, 32>(f3) |
1009 getfield<uint64_t, 6, 32, 36>(f4) |
1010 getfield<uint64_t, 6, 36, 40>(f5) |
1011 getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1015 #define DECLARE_S390_RSL_A_INSTRUCTIONS(name, op_name, op_value) \ 1016 void name(const Operand& l1, Register b1, const Operand& d1) { \ 1017 uint16_t L = static_cast<uint16_t>(l1.immediate() << 8); \ 1018 rsl_format(op_name, L, b1.code(), d1.immediate(), 0, 0); \ 1020 S390_RSL_A_OPCODE_LIST(DECLARE_S390_RSL_A_INSTRUCTIONS);
1021 #undef DECLARE_S390_RSL_A_INSTRUCTIONS 1023 #define DECLARE_S390_RSL_B_INSTRUCTIONS(name, op_name, op_value) \ 1024 void name(const Operand& l2, Register b2, const Operand& d2, \ 1025 Register r1, Condition m3) { \ 1026 uint16_t L = static_cast<uint16_t>(l2.immediate()); \ 1027 rsl_format(op_name, L, b2.code(), d2.immediate(), r1.code(), m3); \ 1029 S390_RSL_B_OPCODE_LIST(DECLARE_S390_RSL_B_INSTRUCTIONS);
1030 #undef DECLARE_S390_RSL_B_INSTRUCTIONS 1033 inline void s_format(Opcode op,
int f1,
int f2) {
1034 DCHECK_NE(op & 0xff00, 0);
1035 DCHECK(is_uint12(f2));
1036 uint32_t code = getfield<uint32_t, 4, 0, 16>(op) |
1037 getfield<uint32_t, 4, 16, 20>(f1) |
1038 getfield<uint32_t, 4, 20, 32>(f2);
1042 #define DECLARE_S390_S_INSTRUCTIONS(name, op_name, op_value) \ 1043 void name(Register b1, const Operand& d2) { \ 1044 Opcode op = op_name; \ 1045 if ((op & 0xFF00) == 0) { \ 1046 op = (Opcode)(op << 8); \ 1048 s_format(op, b1.code(), d2.immediate()); \ 1050 void name(const MemOperand& opnd) { \ 1051 Operand d2 = Operand(opnd.getDisplacement()); \ 1052 name(opnd.getBaseRegister(), d2); \ 1054 S390_S_OPCODE_LIST(DECLARE_S390_S_INSTRUCTIONS);
1055 #undef DECLARE_S390_S_INSTRUCTIONS 1058 inline void si_format(Opcode op,
int f1,
int f2,
int f3) {
1059 uint32_t code = getfield<uint32_t, 4, 0, 8>(op) |
1060 getfield<uint32_t, 4, 8, 16>(f1) |
1061 getfield<uint32_t, 4, 16, 20>(f2) |
1062 getfield<uint32_t, 4, 20, 32>(f3);
1066 #define DECLARE_S390_SI_INSTRUCTIONS(name, op_name, op_value) \ 1067 void name(const Operand& i2, Register b1, const Operand& d1) { \ 1068 si_format(op_name, i2.immediate(), b1.code(), d1.immediate()); \ 1070 void name(const MemOperand& opnd, const Operand& i2) { \ 1071 name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \ 1073 S390_SI_OPCODE_LIST(DECLARE_S390_SI_INSTRUCTIONS);
1074 #undef DECLARE_S390_SI_INSTRUCTIONS 1077 inline void siy_format(Opcode op,
int f1,
int f2,
int f3) {
1078 DCHECK(is_uint20(f3) || is_int20(f3));
1079 DCHECK(is_uint16(op));
1080 DCHECK(is_uint8(f1) || is_int8(f1));
1081 uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1082 getfield<uint64_t, 6, 8, 16>(f1) |
1083 getfield<uint64_t, 6, 16, 20>(f2) |
1084 getfield<uint64_t, 6, 20, 32>(f3) |
1085 getfield<uint64_t, 6, 32, 40>(f3 >> 12) |
1086 getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1090 #define DECLARE_S390_SIY_INSTRUCTIONS(name, op_name, op_value) \ 1091 void name(const Operand& i2, Register b1, const Operand& d1) { \ 1092 siy_format(op_name, i2.immediate(), b1.code(), d1.immediate()); \ 1094 void name(const MemOperand& opnd, const Operand& i2) { \ 1095 name(i2, opnd.getBaseRegister(), Operand(opnd.getDisplacement())); \ 1097 S390_SIY_OPCODE_LIST(DECLARE_S390_SIY_INSTRUCTIONS);
1098 #undef DECLARE_S390_SIY_INSTRUCTIONS 1101 inline void rrs_format(Opcode op,
int f1,
int f2,
int f3,
int f4,
int f5) {
1102 DCHECK(is_uint12(f4));
1103 DCHECK(is_uint16(op));
1104 uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1105 getfield<uint64_t, 6, 8, 12>(f1) |
1106 getfield<uint64_t, 6, 12, 16>(f2) |
1107 getfield<uint64_t, 6, 16, 20>(f3) |
1108 getfield<uint64_t, 6, 20, 32>(f4) |
1109 getfield<uint64_t, 6, 32, 36>(f5) |
1110 getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1114 #define DECLARE_S390_RRS_INSTRUCTIONS(name, op_name, op_value) \ 1115 void name(Register r1, Register r2, Register b4, const Operand& d4, \ 1117 rrs_format(op_name, r1.code(), r2.code(), b4.code(), d4.immediate(), \ 1120 void name(Register r1, Register r2, Condition m3, \ 1121 const MemOperand& opnd) { \ 1122 name(r1, r2, opnd.getBaseRegister(), \ 1123 Operand(opnd.getDisplacement()), m3); \ 1125 S390_RRS_OPCODE_LIST(DECLARE_S390_RRS_INSTRUCTIONS);
1126 #undef DECLARE_S390_RRS_INSTRUCTIONS 1129 inline void ris_format(Opcode op,
int f1,
int f2,
int f3,
int f4,
int f5) {
1130 DCHECK(is_uint12(f3));
1131 DCHECK(is_uint16(op));
1132 DCHECK(is_uint8(f5));
1133 uint64_t code = getfield<uint64_t, 6, 0, 8>(op >> 8) |
1134 getfield<uint64_t, 6, 8, 12>(f1) |
1135 getfield<uint64_t, 6, 12, 16>(f2) |
1136 getfield<uint64_t, 6, 16, 20>(f3) |
1137 getfield<uint64_t, 6, 20, 32>(f4) |
1138 getfield<uint64_t, 6, 32, 40>(f5) |
1139 getfield<uint64_t, 6, 40, 48>(op & 0x00FF);
1143 #define DECLARE_S390_RIS_INSTRUCTIONS(name, op_name, op_value) \ 1144 void name(Register r1, Condition m3, Register b4, const Operand& d4, \ 1145 const Operand& i2) { \ 1146 ris_format(op_name, r1.code(), m3, b4.code(), d4.immediate(), \ 1149 void name(Register r1, const Operand& i2, Condition m3, \ 1150 const MemOperand& opnd) { \ 1151 name(r1, m3, opnd.getBaseRegister(), \ 1152 Operand(opnd.getDisplacement()), i2); \ 1154 S390_RIS_OPCODE_LIST(DECLARE_S390_RIS_INSTRUCTIONS);
1155 #undef DECLARE_S390_RIS_INSTRUCTIONS 1158 inline void sil_format(Opcode op,
int f1,
int f2,
int f3) {
1159 DCHECK(is_uint12(f2));
1160 DCHECK(is_uint16(op));
1161 DCHECK(is_uint16(f3));
1162 uint64_t code = getfield<uint64_t, 6, 0, 16>(op) |
1163 getfield<uint64_t, 6, 16, 20>(f1) |
1164 getfield<uint64_t, 6, 20, 32>(f2) |
1165 getfield<uint64_t, 6, 32, 48>(f3);
1169 #define DECLARE_S390_SIL_INSTRUCTIONS(name, op_name, op_value) \ 1170 void name(Register b1, const Operand& d1, const Operand& i2) { \ 1171 sil_format(op_name, b1.code(), d1.immediate(), i2.immediate()); \ 1173 void name(const MemOperand& opnd, const Operand& i2) { \ 1174 name(opnd.getBaseRegister(), Operand(opnd.getDisplacement()), i2); \ 1176 S390_SIL_OPCODE_LIST(DECLARE_S390_SIL_INSTRUCTIONS);
1177 #undef DECLARE_S390_SIL_INSTRUCTIONS 1180 inline void rie_d_format(Opcode opcode,
int f1,
int f2,
int f3,
int f4) {
1183 uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
1184 getfield<uint64_t, 6, 8, 12>(f1) |
1185 getfield<uint64_t, 6, 12, 16>(f2) |
1186 getfield<uint64_t, 6, 16, 32>(f3) |
1187 getfield<uint64_t, 6, 32, 40>(f4) |
1188 getfield<uint64_t, 6, 40, 48>(op2);
1192 #define DECLARE_S390_RIE_D_INSTRUCTIONS(name, op_name, op_value) \ 1193 void name(Register r1, Register r3, const Operand& i2) { \ 1194 rie_d_format(op_name, r1.code(), r3.code(), i2.immediate(), 0); \ 1196 S390_RIE_D_OPCODE_LIST(DECLARE_S390_RIE_D_INSTRUCTIONS)
1197 #undef DECLARE_S390_RIE_D_INSTRUCTIONS 1200 inline void rie_e_format(Opcode opcode,
int f1,
int f2,
int f3) {
1203 uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
1204 getfield<uint64_t, 6, 8, 12>(f1) |
1205 getfield<uint64_t, 6, 12, 16>(f2) |
1206 getfield<uint64_t, 6, 16, 32>(f3) |
1207 getfield<uint64_t, 6, 40, 48>(op2);
1211 #define DECLARE_S390_RIE_E_INSTRUCTIONS(name, op_name, op_value) \ 1212 void name(Register r1, Register r3, const Operand& i2) { \ 1213 rie_e_format(op_name, r1.code(), r3.code(), i2.immediate()); \ 1215 S390_RIE_E_OPCODE_LIST(DECLARE_S390_RIE_E_INSTRUCTIONS)
1216 #undef DECLARE_S390_RIE_E_INSTRUCTIONS 1219 inline void rie_f_format(Opcode opcode,
int f1,
int f2,
int f3,
int f4,
1223 uint64_t code = getfield<uint64_t, 6, 0, 8>(op1) |
1224 getfield<uint64_t, 6, 8, 12>(f1) |
1225 getfield<uint64_t, 6, 12, 16>(f2) |
1226 getfield<uint64_t, 6, 16, 24>(f3) |
1227 getfield<uint64_t, 6, 24, 32>(f4) |
1228 getfield<uint64_t, 6, 32, 40>(f5) |
1229 getfield<uint64_t, 6, 40, 48>(op2);
1233 #define DECLARE_S390_RIE_F_INSTRUCTIONS(name, op_name, op_value) \ 1234 void name(Register dst, Register src, const Operand& startBit, \ 1235 const Operand& endBit, const Operand& shiftAmt) { \ 1236 DCHECK(is_uint8(startBit.immediate())); \ 1237 DCHECK(is_uint8(endBit.immediate())); \ 1238 DCHECK(is_uint8(shiftAmt.immediate())); \ 1239 rie_f_format(op_name, dst.code(), src.code(), startBit.immediate(), \ 1240 endBit.immediate(), shiftAmt.immediate()); \ 1242 S390_RIE_F_OPCODE_LIST(DECLARE_S390_RIE_F_INSTRUCTIONS)
1243 #undef DECLARE_S390_RIE_F_INSTRUCTIONS 1246 inline void ss_a_format(Opcode op,
int f1,
int f2,
int f3,
int f4,
int f5) {
1247 DCHECK(is_uint12(f5));
1248 DCHECK(is_uint12(f3));
1249 DCHECK(is_uint8(f1));
1250 DCHECK(is_uint8(op));
1251 uint64_t code = getfield<uint64_t, 6, 0, 8>(op) |
1252 getfield<uint64_t, 6, 8, 16>(f1) |
1253 getfield<uint64_t, 6, 16, 20>(f2) |
1254 getfield<uint64_t, 6, 20, 32>(f3) |
1255 getfield<uint64_t, 6, 32, 36>(f4) |
1256 getfield<uint64_t, 6, 36, 48>(f5);
1260 #define DECLARE_S390_SS_A_INSTRUCTIONS(name, op_name, op_value) \ 1261 void name(Register b1, const Operand& d1, Register b2, \ 1262 const Operand& d2, const Operand& length) { \ 1263 ss_a_format(op_name, length.immediate(), b1.code(), d1.immediate(), \ 1264 b2.code(), d2.immediate()); \ 1266 void name(const MemOperand& opnd1, const MemOperand& opnd2, \ 1267 const Operand& length) { \ 1268 ss_a_format(op_name, length.immediate(), \ 1269 opnd1.getBaseRegister().code(), \ 1270 opnd1.getDisplacement(), opnd2.getBaseRegister().code(), \ 1271 opnd2.getDisplacement()); \ 1273 S390_SS_A_OPCODE_LIST(DECLARE_S390_SS_A_INSTRUCTIONS)
1274 #undef DECLARE_S390_SS_A_INSTRUCTIONS 1278 void b(Register r, Label* l) {
1279 int32_t halfwords = branch_offset(l) / 2;
1280 brasl(r, Operand(halfwords));
1284 void branchOnCond(Condition c,
int branch_offset,
bool is_bound =
false);
1287 void b(Condition cond, Label* l, Label::Distance dist = Label::kFar) {
1288 branchOnCond(cond, branch_offset(l),
1289 l->is_bound() || (dist == Label::kNear));
1292 void bc_short(Condition cond, Label* l, Label::Distance dist = Label::kFar) {
1293 b(cond, l, Label::kNear);
1296 void beq(Label* l, Label::Distance dist = Label::kFar) { b(eq, l, dist); }
1297 void bne(Label* l, Label::Distance dist = Label::kFar) { b(ne, l, dist); }
1298 void blt(Label* l, Label::Distance dist = Label::kFar) { b(lt, l, dist); }
1299 void ble(Label* l, Label::Distance dist = Label::kFar) { b(le, l, dist); }
1300 void bgt(Label* l, Label::Distance dist = Label::kFar) { b(gt, l, dist); }
1301 void bge(Label* l, Label::Distance dist = Label::kFar) { b(ge, l, dist); }
1302 void b(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); }
1303 void jmp(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); }
1304 void bunordered(Label* l, Label::Distance dist = Label::kFar) {
1305 b(unordered, l, dist);
1307 void bordered(Label* l, Label::Distance dist = Label::kFar) {
1308 b(ordered, l, dist);
1312 void b(Condition cond, Register r) { bcr(cond, r); }
1313 void beq(Register r) { b(eq, r); }
1314 void bne(Register r) { b(ne, r); }
1315 void blt(Register r) { b(lt, r); }
1316 void ble(Register r) { b(le, r); }
1317 void bgt(Register r) { b(gt, r); }
1318 void bge(Register r) { b(ge, r); }
1319 void b(Register r) { b(al, r); }
1320 void jmp(Register r) { b(al, r); }
1321 void bunordered(Register r) { b(unordered, r); }
1322 void bordered(Register r) { b(ordered, r); }
1325 void brxh(Register dst, Register inc, Label* L) {
1326 int offset_halfwords = branch_offset(L) / 2;
1327 CHECK(is_int16(offset_halfwords));
1328 brxh(dst, inc, Operand(offset_halfwords));
1331 void brxhg(Register dst, Register inc, Label* L) {
1332 int offset_halfwords = branch_offset(L) / 2;
1333 CHECK(is_int16(offset_halfwords));
1334 brxhg(dst, inc, Operand(offset_halfwords));
1337 template <
class R1,
class R2>
1338 void ledbr(R1 r1, R2 r2) {
1339 ledbra(Condition(0), Condition(0), r1, r2);
1342 template <
class R1,
class R2>
1343 void cdfbr(R1 r1, R2 r2) {
1344 cdfbra(Condition(0), Condition(0), r1, r2);
1347 template <
class R1,
class R2>
1348 void cdgbr(R1 r1, R2 r2) {
1349 cdgbra(Condition(0), Condition(0), r1, r2);
1352 template <
class R1,
class R2>
1353 void cegbr(R1 r1, R2 r2) {
1354 cegbra(Condition(0), Condition(0), r1, r2);
1357 template <
class R1,
class R2>
1358 void cgebr(Condition m3, R1 r1, R2 r2) {
1359 cgebra(m3, Condition(0), r1, r2);
1362 template <
class R1,
class R2>
1363 void cgdbr(Condition m3, R1 r1, R2 r2) {
1364 cgdbra(m3, Condition(0), r1, r2);
1367 template <
class R1,
class R2>
1368 void cfdbr(Condition m3, R1 r1, R2 r2) {
1369 cfdbra(m3, Condition(0), r1, r2);
1372 template <
class R1,
class R2>
1373 void cfebr(Condition m3, R1 r1, R2 r2) {
1374 cfebra(m3, Condition(0), r1, r2);
1386 void DataAlign(
int m);
1388 void CodeTargetAlign();
1390 void breakpoint(
bool do_print) {
1392 PrintF(
"DebugBreak is inserted to %p\n", static_cast<void*>(pc_));
1394 #if V8_HOST_ARCH_64_BIT 1395 int64_t value =
reinterpret_cast<uint64_t
>(&v8::base::OS::DebugBreak);
1396 int32_t hi_32 =
static_cast<int64_t>(value) >> 32;
1397 int32_t lo_32 =
static_cast<int32_t
>(value);
1399 iihf(r1, Operand(hi_32));
1400 iilf(r1, Operand(lo_32));
1402 iilf(r1, Operand(reinterpret_cast<uint32_t>(&v8::base::OS::DebugBreak)));
1407 void call(Handle<Code> target, RelocInfo::Mode rmode);
1408 void call(CodeStub* stub);
1409 void jump(Handle<Code> target, RelocInfo::Mode rmode, Condition cond);
1412 #define DECLARE_VRR_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 1413 void name(DoubleRegister v1, DoubleRegister v2, Condition m5, Condition m4, \ 1415 uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \ 1416 (static_cast<uint64_t>(v1.code())) * B36 | \ 1417 (static_cast<uint64_t>(v2.code())) * B32 | \ 1418 (static_cast<uint64_t>(m5 & 0xF)) * B20 | \ 1419 (static_cast<uint64_t>(m4 & 0xF)) * B16 | \ 1420 (static_cast<uint64_t>(m3 & 0xF)) * B12 | \ 1421 (static_cast<uint64_t>(opcode_value & 0x00FF)); \ 1424 S390_VRR_A_OPCODE_LIST(DECLARE_VRR_A_INSTRUCTIONS)
1425 #undef DECLARE_VRR_A_INSTRUCTIONS 1427 #define DECLARE_VRR_C_INSTRUCTIONS(name, opcode_name, opcode_value) \ 1428 void name(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3, \ 1429 Condition m6, Condition m5, Condition m4) { \ 1430 uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \ 1431 (static_cast<uint64_t>(v1.code())) * B36 | \ 1432 (static_cast<uint64_t>(v2.code())) * B32 | \ 1433 (static_cast<uint64_t>(v3.code())) * B28 | \ 1434 (static_cast<uint64_t>(m6 & 0xF)) * B20 | \ 1435 (static_cast<uint64_t>(m5 & 0xF)) * B16 | \ 1436 (static_cast<uint64_t>(m4 & 0xF)) * B12 | \ 1437 (static_cast<uint64_t>(opcode_value & 0x00FF)); \ 1440 S390_VRR_C_OPCODE_LIST(DECLARE_VRR_C_INSTRUCTIONS)
1441 #undef DECLARE_VRR_C_INSTRUCTIONS 1444 void vfa(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1445 vfa(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1446 static_cast<Condition>(3));
1448 void vfs(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1449 vfs(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1450 static_cast<Condition>(3));
1452 void vfm(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1453 vfm(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1454 static_cast<Condition>(3));
1456 void vfd(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) {
1457 vfd(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8),
1458 static_cast<Condition>(3));
1462 void larl(Register r, Label* l);
1465 void stop(
const char* msg, Condition cond = al,
1466 int32_t code = kDefaultStopCode, CRegister cr = cr7);
1472 enum NopMarkerTypes {
1473 NON_MARKING_NOP = 0,
1477 PROPERTY_ACCESS_INLINED,
1478 PROPERTY_ACCESS_INLINED_CONTEXT,
1479 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1482 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1485 void nop(
int type = 0);
1487 void dumy(
int r1,
int x2,
int b2,
int d2);
1490 int SizeOfCodeGeneratedSince(Label* label) {
1491 return pc_offset() - label->pos();
1496 void RecordComment(
const char* msg);
1500 void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
1505 void db(uint8_t data);
1507 void dq(uint64_t data);
1511 SixByteInstr instr_at(
int pos) {
1512 return Instruction::InstructionBits(buffer_ + pos);
1514 template <
typename T>
1515 void instr_at_put(
int pos, T instr) {
1516 Instruction::SetInstructionBits<T>(buffer_ + pos, instr);
1520 int32_t instr_length_at(
int pos) {
1521 return Instruction::InstructionLength(buffer_ + pos);
1524 static SixByteInstr instr_at(byte* pc) {
1525 return Instruction::InstructionBits(pc);
1528 static Condition GetCondition(Instr instr);
1530 static bool IsBranch(Instr instr);
1531 #if V8_TARGET_ARCH_S390X 1532 static bool Is64BitLoadIntoIP(SixByteInstr instr1, SixByteInstr instr2);
1534 static bool Is32BitLoadIntoIP(SixByteInstr instr);
1537 static bool IsCmpRegister(Instr instr);
1538 static bool IsCmpImmediate(Instr instr);
1539 static bool IsNop(SixByteInstr instr,
int type = NON_MARKING_NOP);
1546 void EnsureSpaceFor(
int space_needed);
1548 void EmitRelocations();
1549 void emit_label_addr(Label* label);
1552 byte* buffer_pos()
const {
return buffer_; }
1555 int buffer_space()
const {
return reloc_info_writer.pos() - pc_; }
1559 int target_at(
int pos);
1562 void target_at_put(
int pos,
int target_pos,
bool* is_branch =
nullptr);
1565 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1569 static const int kMaximalBufferSize = 512 * MB;
1576 static constexpr
int kGap = 32;
1580 static constexpr
int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1581 RelocInfoWriter reloc_info_writer;
1582 std::vector<DeferredRelocInfo> relocations_;
1585 int last_bound_pos_;
1588 void CheckBuffer() {
1589 if (buffer_space() <= kGap) {
1593 void GrowBuffer(
int needed = 0);
1594 inline void TrackBranch();
1595 inline void UntrackBranch();
1598 void emit2bytes(uint16_t x) {
1600 #if V8_TARGET_LITTLE_ENDIAN 1604 x = ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8);
1606 *
reinterpret_cast<uint16_t*
>(pc_) = x;
1613 #if V8_TARGET_LITTLE_ENDIAN 1617 x = ((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) |
1618 ((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24);
1620 *
reinterpret_cast<uint32_t*
>(pc_) = x;
1625 void emit6bytes(uint64_t x) {
1627 #if V8_TARGET_LITTLE_ENDIAN 1631 x = (
static_cast<uint64_t
>(x & 0xFF) << 40) |
1632 (
static_cast<uint64_t
>((x >> 8) & 0xFF) << 32) |
1633 (static_cast<uint64_t>((x >> 16) & 0xFF) << 24) |
1634 (
static_cast<uint64_t
>((x >> 24) & 0xFF) << 16) |
1635 (static_cast<uint64_t>((x >> 32) & 0xFF) << 8) |
1636 (
static_cast<uint64_t
>((x >> 40) & 0xFF));
1637 x |= (*
reinterpret_cast<uint64_t*
>(pc_) >> 48) << 48;
1642 x |= *
reinterpret_cast<uint64_t*
>(pc_) & 0xFFFF;
1646 *
reinterpret_cast<uint64_t*
>(pc_) = x;
1651 void print(Label* L);
1652 int max_reach_from(
int pos);
1653 void bind_to(Label* L,
int pos);
1654 void next(Label* L);
1656 void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
1658 friend class RegExpMacroAssemblerS390;
1659 friend class RelocInfo;
1660 friend class EnsureSpace;
1665 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1669 DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS);
1670 DEFINE_REGISTER_NAMES(DoubleRegister, DOUBLE_REGISTERS);
1676 #endif // V8_S390_ASSEMBLER_S390_H_