< prev index next >

src/hotspot/cpu/aarch64/assembler_aarch64.hpp

Print this page
8248238: Adding Windows support to OpenJDK on AArch64

Summary: LP64 vs LLP64 changes to add Windows support

Contributed-by: Monica Beckwith <monica.beckwith@microsoft.com>, Ludovic Henry <luhenry@microsoft.com>
Reviewed-by:
8248238: Adding Windows support to OpenJDK on AArch64

Summary: Adding Windows support for AArch64

Contributed-by: Ludovic Henry <luhenry@microsoft.com>, Monica Beckwith <monica.beckwith@microsoft.com>
Reviewed-by:

*** 197,207 **** static inline int32_t sextract(uint32_t val, int msb, int lsb) { uint32_t uval = extract(val, msb, lsb); return extend(uval, msb - lsb); } ! static void patch(address a, int msb, int lsb, unsigned long val) { int nbits = msb - lsb + 1; guarantee(val < (1U << nbits), "Field too big for insn"); assert_cond(msb >= lsb); unsigned mask = (1U << nbits) - 1; val <<= lsb; --- 197,207 ---- static inline int32_t sextract(uint32_t val, int msb, int lsb) { uint32_t uval = extract(val, msb, lsb); return extend(uval, msb - lsb); } ! static void patch(address a, int msb, int lsb, uint64_t val) { int nbits = msb - lsb + 1; guarantee(val < (1U << nbits), "Field too big for insn"); assert_cond(msb >= lsb); unsigned mask = (1U << nbits) - 1; val <<= lsb;
*** 210,222 **** target &= ~mask; target |= val; *(unsigned *)a = target; } ! static void spatch(address a, int msb, int lsb, long val) { int nbits = msb - lsb + 1; ! long chk = val >> (nbits - 1); guarantee (chk == -1 || chk == 0, "Field too big for insn"); unsigned uval = val; unsigned mask = (1U << nbits) - 1; uval &= mask; uval <<= lsb; --- 210,222 ---- target &= ~mask; target |= val; *(unsigned *)a = target; } ! static void spatch(address a, int msb, int lsb, int64_t val) { int nbits = msb - lsb + 1; ! int64_t chk = val >> (nbits - 1); guarantee (chk == -1 || chk == 0, "Field too big for insn"); unsigned uval = val; unsigned mask = (1U << nbits) - 1; uval &= mask; uval <<= lsb;
*** 243,255 **** void f(unsigned val, int bit) { f(val, bit, bit); } ! void sf(long val, int msb, int lsb) { int nbits = msb - lsb + 1; ! long chk = val >> (nbits - 1); guarantee (chk == -1 || chk == 0, "Field too big for insn"); unsigned uval = val; unsigned mask = (1U << nbits) - 1; uval &= mask; f(uval, lsb + nbits - 1, lsb); --- 243,255 ---- void f(unsigned val, int bit) { f(val, bit, bit); } ! void sf(int64_t val, int msb, int lsb) { int nbits = msb - lsb + 1; ! int64_t chk = val >> (nbits - 1); guarantee (chk == -1 || chk == 0, "Field too big for insn"); unsigned uval = val; unsigned mask = (1U << nbits) - 1; uval &= mask; f(uval, lsb + nbits - 1, lsb);
*** 355,365 **** }; private: Register _base; Register _index; ! long _offset; enum mode _mode; extend _ext; RelocationHolder _rspec; --- 355,365 ---- }; private: Register _base; Register _index; ! int64_t _offset; enum mode _mode; extend _ext; RelocationHolder _rspec;
*** 378,390 **** : _mode(no_mode) { } Address(Register r) : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(0) { } Address(Register r, int o) : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } ! Address(Register r, long o) : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } ! Address(Register r, unsigned long o) : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } #ifdef ASSERT Address(Register r, ByteSize disp) : _base(r), _index(noreg), _offset(in_bytes(disp)), _mode(base_plus_offset), _target(0) { } #endif --- 378,390 ---- : _mode(no_mode) { } Address(Register r) : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(0) { } Address(Register r, int o) : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } ! Address(Register r, int64_t o) : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } ! Address(Register r, uint64_t o) : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(0) { } #ifdef ASSERT Address(Register r, ByteSize disp) : _base(r), _index(noreg), _offset(in_bytes(disp)), _mode(base_plus_offset), _target(0) { } #endif
*** 420,430 **** guarantee((_mode == base_plus_offset | _mode == base_plus_offset_reg | _mode == post | _mode == post_reg), "wrong mode"); return _base; } ! long offset() const { return _offset; } Register index() const { return _index; } --- 420,430 ---- guarantee((_mode == base_plus_offset | _mode == base_plus_offset_reg | _mode == post | _mode == post_reg), "wrong mode"); return _base; } ! int64_t offset() const { return _offset; } Register index() const { return _index; }
*** 552,562 **** "Bad addressing mode for non-temporal op"); } void lea(MacroAssembler *, Register) const; ! static bool offset_ok_for_immed(long offset, int shift) { unsigned mask = (1 << shift) - 1; if (offset < 0 || offset & mask) { return (uabs(offset) < (1 << (20 - 12))); // Unscaled offset } else { return ((offset >> shift) < (1 << (21 - 10 + 1))); // Scaled, unsigned offset --- 552,562 ---- "Bad addressing mode for non-temporal op"); } void lea(MacroAssembler *, Register) const; ! static bool offset_ok_for_immed(int64_t offset, int shift) { unsigned mask = (1 << shift) - 1; if (offset < 0 || offset & mask) { return (uabs(offset) < (1 << (20 - 12))); // Unscaled offset } else { return ((offset >> shift) < (1 << (21 - 10 + 1))); // Scaled, unsigned offset
*** 614,628 **** } prfop; class Assembler : public AbstractAssembler { #ifndef PRODUCT ! static const unsigned long asm_bp; void emit_long(jint x) { ! if ((unsigned long)pc() == asm_bp) asm volatile ("nop"); AbstractAssembler::emit_int32(x); } #else void emit_long(jint x) { AbstractAssembler::emit_int32(x); --- 614,634 ---- } prfop; class Assembler : public AbstractAssembler { #ifndef PRODUCT ! static const uint64_t asm_bp; void emit_long(jint x) { ! if ((uint64_t)pc() == asm_bp) { ! #ifdef _WIN64 ! // MSVC built-in: https://docs.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics?view=vs-2019#I ! __nop(); ! #else asm volatile ("nop"); + #endif + } AbstractAssembler::emit_int32(x); } #else void emit_long(jint x) { AbstractAssembler::emit_int32(x);
*** 658,678 **** Address post(Register base, Register idx) { return Address(Post(base, idx)); } Instruction_aarch64* current; void set_current(Instruction_aarch64* i) { current = i; } void f(unsigned val, int msb, int lsb) { current->f(val, msb, lsb); } void f(unsigned val, int msb) { current->f(val, msb, msb); } ! void sf(long val, int msb, int lsb) { current->sf(val, msb, lsb); } void rf(Register reg, int lsb) { current->rf(reg, lsb); } --- 664,686 ---- Address post(Register base, Register idx) { return Address(Post(base, idx)); } + static address locate_next_instruction(address inst); + Instruction_aarch64* current; void set_current(Instruction_aarch64* i) { current = i; } void f(unsigned val, int msb, int lsb) { current->f(val, msb, lsb); } void f(unsigned val, int msb) { current->f(val, msb, msb); } ! void sf(int64_t val, int msb, int lsb) { current->sf(val, msb, lsb); } void rf(Register reg, int lsb) { current->rf(reg, lsb); }
*** 718,728 **** } void _adrp(Register Rd, Label &L) { wrap_label(Rd, L, &Assembler::_adrp); } ! void adrp(Register Rd, const Address &dest, unsigned long &offset); #undef INSN void add_sub_immediate(Register Rd, Register Rn, unsigned uimm, int op, int negated_op); --- 726,736 ---- } void _adrp(Register Rd, Label &L) { wrap_label(Rd, L, &Assembler::_adrp); } ! void adrp(Register Rd, const Address &dest, uint64_t &offset); #undef INSN void add_sub_immediate(Register Rd, Register Rn, unsigned uimm, int op, int negated_op);
*** 844,864 **** // The maximum range of a branch is fixed for the AArch64 // architecture. In debug mode we shrink it in order to test // trampolines, but not so small that branches in the interpreter // are out of range. ! static const unsigned long branch_range = NOT_DEBUG(128 * M) DEBUG_ONLY(2 * M); static bool reachable_from_branch_at(address branch, address target) { return uabs(target - branch) < branch_range; } // Unconditional branch (immediate) #define INSN(NAME, opcode) \ void NAME(address dest) { \ starti; \ ! long offset = (dest - pc()) >> 2; \ DEBUG_ONLY(assert(reachable_from_branch_at(pc(), dest), "debug only")); \ f(opcode, 31), f(0b00101, 30, 26), sf(offset, 25, 0); \ } \ void NAME(Label &L) { \ wrap_label(L, &Assembler::NAME); \ --- 852,872 ---- // The maximum range of a branch is fixed for the AArch64 // architecture. In debug mode we shrink it in order to test // trampolines, but not so small that branches in the interpreter // are out of range. ! static const uint64_t branch_range = NOT_DEBUG(128 * M) DEBUG_ONLY(2 * M); static bool reachable_from_branch_at(address branch, address target) { return uabs(target - branch) < branch_range; } // Unconditional branch (immediate) #define INSN(NAME, opcode) \ void NAME(address dest) { \ starti; \ ! int64_t offset = (dest - pc()) >> 2; \ DEBUG_ONLY(assert(reachable_from_branch_at(pc(), dest), "debug only")); \ f(opcode, 31), f(0b00101, 30, 26), sf(offset, 25, 0); \ } \ void NAME(Label &L) { \ wrap_label(L, &Assembler::NAME); \
*** 871,881 **** #undef INSN // Compare & branch (immediate) #define INSN(NAME, opcode) \ void NAME(Register Rt, address dest) { \ ! long offset = (dest - pc()) >> 2; \ starti; \ f(opcode, 31, 24), sf(offset, 23, 5), rf(Rt, 0); \ } \ void NAME(Register Rt, Label &L) { \ wrap_label(Rt, L, &Assembler::NAME); \ --- 879,889 ---- #undef INSN // Compare & branch (immediate) #define INSN(NAME, opcode) \ void NAME(Register Rt, address dest) { \ ! int64_t offset = (dest - pc()) >> 2; \ starti; \ f(opcode, 31, 24), sf(offset, 23, 5), rf(Rt, 0); \ } \ void NAME(Register Rt, Label &L) { \ wrap_label(Rt, L, &Assembler::NAME); \
*** 889,899 **** #undef INSN // Test & branch (immediate) #define INSN(NAME, opcode) \ void NAME(Register Rt, int bitpos, address dest) { \ ! long offset = (dest - pc()) >> 2; \ int b5 = bitpos >> 5; \ bitpos &= 0x1f; \ starti; \ f(b5, 31), f(opcode, 30, 24), f(bitpos, 23, 19), sf(offset, 18, 5); \ rf(Rt, 0); \ --- 897,907 ---- #undef INSN // Test & branch (immediate) #define INSN(NAME, opcode) \ void NAME(Register Rt, int bitpos, address dest) { \ ! int64_t offset = (dest - pc()) >> 2; \ int b5 = bitpos >> 5; \ bitpos &= 0x1f; \ starti; \ f(b5, 31), f(opcode, 30, 24), f(bitpos, 23, 19), sf(offset, 18, 5); \ rf(Rt, 0); \
*** 910,920 **** // Conditional branch (immediate) enum Condition {EQ, NE, HS, CS=HS, LO, CC=LO, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV}; void br(Condition cond, address dest) { ! long offset = (dest - pc()) >> 2; starti; f(0b0101010, 31, 25), f(0, 24), sf(offset, 23, 5), f(0, 4), f(cond, 3, 0); } #define INSN(NAME, cond) \ --- 918,928 ---- // Conditional branch (immediate) enum Condition {EQ, NE, HS, CS=HS, LO, CC=LO, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV}; void br(Condition cond, address dest) { ! int64_t offset = (dest - pc()) >> 2; starti; f(0b0101010, 31, 25), f(0, 24), sf(offset, 23, 5), f(0, 4), f(cond, 3, 0); } #define INSN(NAME, cond) \
*** 1290,1300 **** #undef INSN // Load register (literal) #define INSN(NAME, opc, V) \ void NAME(Register Rt, address dest) { \ ! long offset = (dest - pc()) >> 2; \ starti; \ f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ sf(offset, 23, 5); \ rf(Rt, 0); \ } \ --- 1298,1308 ---- #undef INSN // Load register (literal) #define INSN(NAME, opc, V) \ void NAME(Register Rt, address dest) { \ ! int64_t offset = (dest - pc()) >> 2; \ starti; \ f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ sf(offset, 23, 5); \ rf(Rt, 0); \ } \
*** 1315,1325 **** #undef INSN #define INSN(NAME, opc, V) \ void NAME(FloatRegister Rt, address dest) { \ ! long offset = (dest - pc()) >> 2; \ starti; \ f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ sf(offset, 23, 5); \ rf((Register)Rt, 0); \ } --- 1323,1333 ---- #undef INSN #define INSN(NAME, opc, V) \ void NAME(FloatRegister Rt, address dest) { \ ! int64_t offset = (dest - pc()) >> 2; \ starti; \ f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ sf(offset, 23, 5); \ rf((Register)Rt, 0); \ }
*** 1330,1340 **** #undef INSN #define INSN(NAME, opc, V) \ void NAME(address dest, prfop op = PLDL1KEEP) { \ ! long offset = (dest - pc()) >> 2; \ starti; \ f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ sf(offset, 23, 5); \ f(op, 4, 0); \ } \ --- 1338,1348 ---- #undef INSN #define INSN(NAME, opc, V) \ void NAME(address dest, prfop op = PLDL1KEEP) { \ ! int64_t offset = (dest - pc()) >> 2; \ starti; \ f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \ sf(offset, 23, 5); \ f(op, 4, 0); \ } \
*** 1406,1416 **** // make it worth sharing. if (adr.getMode() == Address::literal) { assert(size == 0b10 || size == 0b11, "bad operand size in ldr"); assert(op == 0b01, "literal form can only be used with loads"); f(size & 0b01, 31, 30), f(0b011, 29, 27), f(0b00, 25, 24); ! long offset = (adr.target() - pc()) >> 2; sf(offset, 23, 5); code_section()->relocate(pc(), adr.rspec()); return; } --- 1414,1424 ---- // make it worth sharing. if (adr.getMode() == Address::literal) { assert(size == 0b10 || size == 0b11, "bad operand size in ldr"); assert(op == 0b01, "literal form can only be used with loads"); f(size & 0b01, 31, 30), f(0b011, 29, 27), f(0b00, 25, 24); ! int64_t offset = (adr.target() - pc()) >> 2; sf(offset, 23, 5); code_section()->relocate(pc(), adr.rspec()); return; }
*** 1527,1536 **** --- 1535,1549 ---- INSN(eonw, 0, 0b10, 1); INSN(bicsw, 0, 0b11, 1); #undef INSN + #ifdef _WIN64 + // In MSVC, `mvn` is defined as a macro and it screws up compilation + #undef mvn + #endif + // Aliases for short forms of orn void mvn(Register Rd, Register Rm, enum shift_kind kind = LSL, unsigned shift = 0) { orn(Rd, zr, Rm, kind, shift); }
*** 2681,2691 **** // Stack overflow checking virtual void bang_stack_with_offset(int offset); static bool operand_valid_for_logical_immediate(bool is32, uint64_t imm); ! static bool operand_valid_for_add_sub_immediate(long imm); static bool operand_valid_for_float_immediate(double imm); void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0); void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0); }; --- 2694,2704 ---- // Stack overflow checking virtual void bang_stack_with_offset(int offset); static bool operand_valid_for_logical_immediate(bool is32, uint64_t imm); ! static bool operand_valid_for_add_sub_immediate(int64_t imm); static bool operand_valid_for_float_immediate(double imm); void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0); void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0); };
< prev index next >