8269516: AArch64: Assembler cleanups

Reviewed-by: ngasson, adinn
This commit is contained in:
Andrew Haley 2021-06-30 13:59:39 +00:00
parent a96012a7af
commit 1810b1c2ad
5 changed files with 145 additions and 138 deletions

@ -134,7 +134,16 @@ void Assembler::adrp(Register reg1, const Address &dest, uint64_t &byte_offset)
#undef __
#define starti Instruction_aarch64 do_not_use(this); set_current(&do_not_use)
#define starti Instruction_aarch64 current_insn(this);
#define f current_insn.f
#define sf current_insn.sf
#define rf current_insn.rf
#define srf current_insn.srf
#define zrf current_insn.zrf
#define prf current_insn.prf
#define pgrf current_insn.pgrf
#define fixed current_insn.fixed
void Assembler::adr(Register Rd, address adr) {
intptr_t offset = adr - pc();
@ -156,6 +165,53 @@ void Assembler::adrp(Register reg1, const Address &dest, uint64_t &byte_offset)
rf(Rd, 0);
}
// An "all-purpose" add/subtract immediate, per ARM documentation:
// A "programmer-friendly" assembler may accept a negative immediate
// between -(2^24 -1) and -1 inclusive, causing it to convert a
// requested ADD operation to a SUB, or vice versa, and then encode
// the absolute value of the immediate as for uimm24.
void Assembler::add_sub_immediate(Instruction_aarch64 &current_insn,
Register Rd, Register Rn, unsigned uimm, int op,
int negated_op) {
bool sets_flags = op & 1; // this op sets flags
union {
unsigned u;
int imm;
};
u = uimm;
bool shift = false;
bool neg = imm < 0;
if (neg) {
imm = -imm;
op = negated_op;
}
assert(Rd != sp || imm % 16 == 0, "misaligned stack");
if (imm >= (1 << 11)
&& ((imm >> 12) << 12 == imm)) {
imm >>= 12;
shift = true;
}
f(op, 31, 29), f(0b10001, 28, 24), f(shift, 23, 22), f(imm, 21, 10);
// add/subtract immediate ops with the S bit set treat r31 as zr;
// with S unset they use sp.
if (sets_flags)
zrf(Rd, 0);
else
srf(Rd, 0);
srf(Rn, 5);
}
#undef f
#undef sf
#undef rf
#undef srf
#undef zrf
#undef prf
#undef pgrf
#undef fixed
#undef starti
Address::Address(address target, relocInfo::relocType rtype) : _mode(literal){
@ -260,43 +316,6 @@ void Assembler::wrap_label(Label &L, prfop op, prefetch_insn insn) {
}
}
// An "all-purpose" add/subtract immediate, per ARM documentation:
// A "programmer-friendly" assembler may accept a negative immediate
// between -(2^24 -1) and -1 inclusive, causing it to convert a
// requested ADD operation to a SUB, or vice versa, and then encode
// the absolute value of the immediate as for uimm24.
void Assembler::add_sub_immediate(Register Rd, Register Rn, unsigned uimm, int op,
int negated_op) {
bool sets_flags = op & 1; // this op sets flags
union {
unsigned u;
int imm;
};
u = uimm;
bool shift = false;
bool neg = imm < 0;
if (neg) {
imm = -imm;
op = negated_op;
}
assert(Rd != sp || imm % 16 == 0, "misaligned stack");
if (imm >= (1 << 11)
&& ((imm >> 12) << 12 == imm)) {
imm >>= 12;
shift = true;
}
f(op, 31, 29), f(0b10001, 28, 24), f(shift, 23, 22), f(imm, 21, 10);
// add/subtract immediate ops with the S bit set treat r31 as zr;
// with S unset they use sp.
if (sets_flags)
zrf(Rd, 0);
else
srf(Rd, 0);
srf(Rn, 5);
}
bool Assembler::operand_valid_for_add_sub_immediate(int64_t imm) {
bool shift = false;
uint64_t uimm = (uint64_t)uabs((jlong)imm);

@ -247,12 +247,12 @@ public:
int nbits = msb - lsb + 1;
guarantee(val < (1ULL << nbits), "Field too big for insn");
assert_cond(msb >= lsb);
unsigned mask = checked_cast<unsigned>(right_n_bits(nbits));
val <<= lsb;
mask <<= lsb;
insn |= val;
assert_cond((bits & mask) == 0);
#ifdef ASSERT
unsigned mask = checked_cast<unsigned>(right_n_bits(nbits));
mask <<= lsb;
assert_cond((bits & mask) == 0);
bits |= mask;
#endif
}
@ -313,7 +313,7 @@ public:
}
};
#define starti Instruction_aarch64 do_not_use(this); set_current(&do_not_use)
#define starti Instruction_aarch64 current_insn(this);
class PrePost {
int _offset;
@ -694,46 +694,14 @@ public:
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);
}
void srf(Register reg, int lsb) {
current->srf(reg, lsb);
}
void zrf(Register reg, int lsb) {
current->zrf(reg, lsb);
}
void rf(FloatRegister reg, int lsb) {
current->rf(reg, lsb);
}
void prf(PRegister reg, int lsb) {
current->prf(reg, lsb);
}
void pgrf(PRegister reg, int lsb) {
current->pgrf(reg, lsb);
}
void fixed(unsigned value, unsigned mask) {
current->fixed(value, mask);
}
void emit() {
emit_long(current->get_insn());
assert_cond(current->get_bits() == 0xffffffff);
current = NULL;
}
#define f current_insn.f
#define sf current_insn.sf
#define rf current_insn.rf
#define srf current_insn.srf
#define zrf current_insn.zrf
#define prf current_insn.prf
#define pgrf current_insn.pgrf
#define fixed current_insn.fixed
typedef void (Assembler::* uncond_branch_insn)(address dest);
typedef void (Assembler::* compare_and_branch_insn)(Register Rt, address dest);
@ -764,8 +732,8 @@ public:
#undef INSN
void add_sub_immediate(Register Rd, Register Rn, unsigned uimm, int op,
int negated_op);
void add_sub_immediate(Instruction_aarch64 &current_insn, Register Rd, Register Rn,
unsigned uimm, int op, int negated_op);
// Add/subtract (immediate)
#define INSN(NAME, decode, negated) \
@ -777,7 +745,7 @@ public:
\
void NAME(Register Rd, Register Rn, unsigned imm) { \
starti; \
add_sub_immediate(Rd, Rn, imm, decode, negated); \
add_sub_immediate(current_insn, Rd, Rn, imm, decode, negated); \
}
INSN(addsw, 0b001, 0b011);
@ -790,7 +758,7 @@ public:
#define INSN(NAME, decode, negated) \
void NAME(Register Rd, Register Rn, unsigned imm) { \
starti; \
add_sub_immediate(Rd, Rn, imm, decode, negated); \
add_sub_immediate(current_insn, Rd, Rn, imm, decode, negated); \
}
INSN(addw, 0b000, 0b010);
@ -1092,7 +1060,7 @@ public:
}
void sys(int op1, int CRn, int CRm, int op2,
Register rt = (Register)0b11111) {
Register rt = as_Register(0b11111)) {
system(0b01, op1, CRn, CRm, op2, rt);
}
@ -1361,7 +1329,7 @@ public:
starti; \
f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \
sf(offset, 23, 5); \
rf((Register)Rt, 0); \
rf(as_Register(Rt), 0); \
}
INSN(ldrs, 0b00, 1);
@ -1375,7 +1343,7 @@ public:
starti; \
f(size, 31, 30), f(0b111100, 29, 24), f(opc, 23, 22), f(0, 21); \
f(0, 20, 12), f(0b01, 11, 10); \
rf(Rn, 5), rf((Register)Rt, 0); \
rf(Rn, 5), rf(as_Register(Rt), 0); \
}
INSN(ldrs, 0b10, 0b01);
@ -1408,9 +1376,9 @@ public:
f(opc, 31, 30), f(p1, 29, 27), f(V, 26), f(L, 22);
zrf(Rt2, 10), zrf(Rt1, 0);
if (no_allocate) {
adr.encode_nontemporal_pair(current);
adr.encode_nontemporal_pair(&current_insn);
} else {
adr.encode_pair(current);
adr.encode_pair(&current_insn);
}
}
@ -1436,7 +1404,8 @@ public:
#define INSN(NAME, size, p1, V, L, no_allocate) \
void NAME(FloatRegister Rt1, FloatRegister Rt2, Address adr) { \
ld_st1(size, p1, V, L, (Register)Rt1, (Register)Rt2, adr, no_allocate); \
ld_st1(size, p1, V, L, \
as_Register(Rt1), as_Register(Rt2), adr, no_allocate); \
}
INSN(stps, 0b00, 0b101, 1, 0, false);
@ -1471,7 +1440,7 @@ public:
f(size, 31, 30);
f(op, 23, 22); // str
adr.encode(current);
adr.encode(&current_insn);
}
#define INSN(NAME, size, op) \
@ -1499,7 +1468,7 @@ public:
#define INSN(NAME, size, op) \
void NAME(const Address &adr, prfop pfop = PLDL1KEEP) { \
ld_st2((Register)pfop, adr, size, op); \
ld_st2(as_Register(pfop), adr, size, op); \
}
INSN(prfm, 0b11, 0b10); // FIXME: PRFM should not be used with
@ -1510,7 +1479,7 @@ public:
#define INSN(NAME, size, op) \
void NAME(FloatRegister Rt, const Address &adr) { \
ld_st2((Register)Rt, adr, size, op, 1); \
ld_st2(as_Register(Rt), adr, size, op, 1); \
}
INSN(strd, 0b11, 0b00);
@ -1547,7 +1516,7 @@ public:
enum shift_kind { LSL, LSR, ASR, ROR };
void op_shifted_reg(unsigned decode,
void op_shifted_reg(Instruction_aarch64 &current_insn, unsigned decode,
enum shift_kind kind, unsigned shift,
unsigned size, unsigned op) {
f(size, 31);
@ -1558,14 +1527,14 @@ public:
}
// Logical (shifted register)
#define INSN(NAME, size, op, N) \
void NAME(Register Rd, Register Rn, Register Rm, \
enum shift_kind kind = LSL, unsigned shift = 0) { \
starti; \
guarantee(size == 1 || shift < 32, "incorrect shift"); \
f(N, 21); \
zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0); \
op_shifted_reg(0b01010, kind, shift, size, op); \
#define INSN(NAME, size, op, N) \
void NAME(Register Rd, Register Rn, Register Rm, \
enum shift_kind kind = LSL, unsigned shift = 0) { \
starti; \
guarantee(size == 1 || shift < 32, "incorrect shift"); \
f(N, 21); \
zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0); \
op_shifted_reg(current_insn, 0b01010, kind, shift, size, op); \
}
INSN(andr, 1, 0b00, 0);
@ -1585,7 +1554,7 @@ public:
starti; \
f(N, 21); \
zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0); \
op_shifted_reg(0b01010, kind, shift, size, op); \
op_shifted_reg(current_insn, 0b01010, kind, shift, size, op); \
} \
\
/* These instructions have no immediate form. Provide an overload so \
@ -1632,7 +1601,7 @@ void mvnw(Register Rd, Register Rm,
assert_cond(kind != ROR); \
guarantee(size == 1 || shift < 32, "incorrect shift");\
zrf(Rd, 0), zrf(Rn, 5), zrf(Rm, 16); \
op_shifted_reg(0b01011, kind, shift, size, op); \
op_shifted_reg(current_insn, 0b01011, kind, shift, size, op); \
}
INSN(add, 1, 0b000);
@ -1653,10 +1622,10 @@ void mvnw(Register Rd, Register Rm,
ext::operation option, int amount = 0) { \
starti; \
zrf(Rm, 16), srf(Rn, 5), srf(Rd, 0); \
add_sub_extended_reg(op, 0b01011, Rd, Rn, Rm, 0b00, option, amount); \
add_sub_extended_reg(current_insn, op, 0b01011, Rd, Rn, Rm, 0b00, option, amount); \
}
void add_sub_extended_reg(unsigned op, unsigned decode,
void add_sub_extended_reg(Instruction_aarch64 &current_insn, unsigned op, unsigned decode,
Register Rd, Register Rn, Register Rm,
unsigned opt, ext::operation option, unsigned imm) {
guarantee(imm <= 4, "shift amount must be <= 4");
@ -1676,7 +1645,7 @@ void mvnw(Register Rd, Register Rm,
ext::operation option, int amount = 0) { \
starti; \
zrf(Rm, 16), srf(Rn, 5), zrf(Rd, 0); \
add_sub_extended_reg(op, 0b01011, Rd, Rn, Rm, 0b00, option, amount); \
add_sub_extended_reg(current_insn, op, 0b01011, Rd, Rn, Rm, 0b00, option, amount); \
}
INSN(addsw, 0b001);
@ -1777,7 +1746,7 @@ void mvnw(Register Rd, Register Rm,
}
#define INSN(NAME, op, op2) \
void NAME(Register Rd, Register Rn, Register Rm, Condition cond) { \
void NAME(Register Rd, Register Rn, Register Rm, Condition cond) { \
conditional_select(op, op2, Rd, Rn, Rm, cond); \
}
@ -1793,7 +1762,7 @@ void mvnw(Register Rd, Register Rm,
#undef INSN
// Data processing
void data_processing(unsigned op29, unsigned opcode,
void data_processing(Instruction_aarch64 &current_insn, unsigned op29, unsigned opcode,
Register Rd, Register Rn) {
f(op29, 31, 29), f(0b11010110, 28, 21);
f(opcode, 15, 10);
@ -1801,11 +1770,11 @@ void mvnw(Register Rd, Register Rm,
}
// (1 source)
#define INSN(NAME, op29, opcode2, opcode) \
void NAME(Register Rd, Register Rn) { \
starti; \
f(opcode2, 20, 16); \
data_processing(op29, opcode, Rd, Rn); \
#define INSN(NAME, op29, opcode2, opcode) \
void NAME(Register Rd, Register Rn) { \
starti; \
f(opcode2, 20, 16); \
data_processing(current_insn, op29, opcode, Rd, Rn); \
}
INSN(rbitw, 0b010, 0b00000, 0b00000);
@ -1824,11 +1793,11 @@ void mvnw(Register Rd, Register Rm,
#undef INSN
// (2 sources)
#define INSN(NAME, op29, opcode) \
void NAME(Register Rd, Register Rn, Register Rm) { \
starti; \
rf(Rm, 16); \
data_processing(op29, opcode, Rd, Rn); \
#define INSN(NAME, op29, opcode) \
void NAME(Register Rd, Register Rn, Register Rm) { \
starti; \
rf(Rm, 16); \
data_processing(current_insn, op29, opcode, Rd, Rn); \
}
INSN(udivw, 0b000, 0b000010);
@ -1873,9 +1842,9 @@ void mvnw(Register Rd, Register Rm,
#undef INSN
#define INSN(NAME, op54, op31, o0) \
void NAME(Register Rd, Register Rn, Register Rm) { \
data_processing(op54, op31, o0, Rd, Rn, Rm, (Register)31); \
#define INSN(NAME, op54, op31, o0) \
void NAME(Register Rd, Register Rn, Register Rm) { \
data_processing(op54, op31, o0, Rd, Rn, Rm, as_Register(31)); \
}
INSN(smulh, 0b100, 0b010, 0);
@ -2054,7 +2023,7 @@ public:
#define INSN(NAME, op31, type, rmode, opcode) \
void NAME(Register Rd, FloatRegister Vn) { \
float_int_convert(op31, type, rmode, opcode, Rd, (Register)Vn); \
float_int_convert(op31, type, rmode, opcode, Rd, as_Register(Vn)); \
}
INSN(fcvtzsw, 0b000, 0b00, 0b11, 0b000);
@ -2071,7 +2040,7 @@ public:
#define INSN(NAME, op31, type, rmode, opcode) \
void NAME(FloatRegister Vd, Register Rn) { \
float_int_convert(op31, type, rmode, opcode, (Register)Vd, Rn); \
float_int_convert(op31, type, rmode, opcode, as_Register(Vd), Rn); \
}
INSN(fmovs, 0b000, 0b00, 0b00, 0b111);
@ -2126,7 +2095,7 @@ public:
// Floating-point compare
void float_compare(unsigned op31, unsigned type,
unsigned op, unsigned op2,
FloatRegister Vn, FloatRegister Vm = (FloatRegister)0) {
FloatRegister Vn, FloatRegister Vm = as_FloatRegister(0)) {
starti;
f(op31, 31, 29);
f(0b11110, 28, 24);
@ -2256,10 +2225,10 @@ private:
static short SIMD_Size_in_bytes[];
public:
#define INSN(NAME, op) \
void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) { \
ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \
} \
#define INSN(NAME, op) \
void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) { \
ld_st2(as_Register(Rt), adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \
}
INSN(ldr, 1);
INSN(str, 0);
@ -3265,9 +3234,19 @@ inline Assembler::Membar_mask_bits operator|(Assembler::Membar_mask_bits a,
}
Instruction_aarch64::~Instruction_aarch64() {
assem->emit();
assem->emit_int32(insn);
assert_cond(get_bits() == 0xffffffff);
}
#undef f
#undef sf
#undef rf
#undef srf
#undef zrf
#undef prf
#undef pgrf
#undef fixed
#undef starti
// Invert a condition

@ -45,17 +45,18 @@ bool ABIDescriptor::is_volatile_reg(FloatRegister reg) const {
const ABIDescriptor ForeignGlobals::parse_abi_descriptor_impl(jobject jabi) const {
oop abi_oop = JNIHandles::resolve_non_null(jabi);
ABIDescriptor abi;
const Register (*to_Register)(int) = as_Register;
objArrayOop inputStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.inputStorage_offset));
loadArray(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, as_Register);
loadArray(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, to_Register);
loadArray(inputStorage, VECTOR_TYPE, abi._vector_argument_registers, as_FloatRegister);
objArrayOop outputStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.outputStorage_offset));
loadArray(outputStorage, INTEGER_TYPE, abi._integer_return_registers, as_Register);
loadArray(outputStorage, INTEGER_TYPE, abi._integer_return_registers, to_Register);
loadArray(outputStorage, VECTOR_TYPE, abi._vector_return_registers, as_FloatRegister);
objArrayOop volatileStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.volatileStorage_offset));
loadArray(volatileStorage, INTEGER_TYPE, abi._integer_additional_volatile_registers, as_Register);
loadArray(volatileStorage, INTEGER_TYPE, abi._integer_additional_volatile_registers, to_Register);
loadArray(volatileStorage, VECTOR_TYPE, abi._vector_additional_volatile_registers, as_FloatRegister);
abi._stack_alignment_bytes = abi_oop->int_field(ABI.stackAlignment_offset);

@ -36,7 +36,7 @@ typedef VMRegImpl* VMReg;
class RegisterImpl;
typedef RegisterImpl* Register;
inline Register as_Register(int encoding) {
inline const Register as_Register(int encoding) {
return (Register)(intptr_t) encoding;
}
@ -53,7 +53,7 @@ class RegisterImpl: public AbstractRegisterImpl {
Register successor() const { return as_Register(encoding() + 1); }
// construction
inline friend Register as_Register(int encoding);
inline friend const Register as_Register(int encoding);
VMReg as_VMReg();
@ -420,4 +420,8 @@ inline FloatRegister AbstractRegSet<FloatRegister>::first() {
return first ? as_FloatRegister(exact_log2(first)) : fnoreg;
}
inline Register as_Register(FloatRegister reg) {
return as_Register(reg->encoding());
}
#endif // CPU_AARCH64_REGISTER_AARCH64_HPP

@ -222,7 +222,11 @@ class CodeSection {
set_end(curr);
}
void emit_int32(int32_t x) { *((int32_t*) end()) = x; set_end(end() + sizeof(int32_t)); }
void emit_int32(int32_t x) {
address curr = end();
*((int32_t*) curr) = x;
set_end(curr + sizeof(int32_t));
}
void emit_int32(int8_t x1, int8_t x2, int8_t x3, int8_t x4) {
address curr = end();
*((int8_t*) curr++) = x1;