8204473: AARCH64: register post-index addressing mode is not supported directly
Reviewed-by: aph
This commit is contained in:
parent
8f5b71f3bb
commit
07e928c8ec
@ -58,6 +58,28 @@ extern "C" void entry(CodeBuffer *cb);
|
|||||||
|
|
||||||
static float unpack(unsigned value);
|
static float unpack(unsigned value);
|
||||||
|
|
||||||
|
short Assembler::SIMD_Size_in_bytes[] = {
|
||||||
|
// T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D, T1Q
|
||||||
|
8, 16, 8, 16, 8, 16, 8, 16, 16
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
static void asm_check(const unsigned int *insns, const unsigned int *insns1, size_t len) {
|
||||||
|
bool ok = true;
|
||||||
|
for (unsigned int i = 0; i < len; i++) {
|
||||||
|
if (insns[i] != insns1[i]) {
|
||||||
|
ok = false;
|
||||||
|
printf("Ours:\n");
|
||||||
|
Disassembler::decode((address)&insns1[i], (address)&insns1[i+1]);
|
||||||
|
printf("Theirs:\n");
|
||||||
|
Disassembler::decode((address)&insns[i], (address)&insns[i+1]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(ok, "Assembler smoke test failed");
|
||||||
|
}
|
||||||
|
#endif // ASSERT
|
||||||
|
|
||||||
void entry(CodeBuffer *cb) {
|
void entry(CodeBuffer *cb) {
|
||||||
|
|
||||||
// {
|
// {
|
||||||
@ -1155,31 +1177,24 @@ Disassembly of section .text:
|
|||||||
};
|
};
|
||||||
// END Generated code -- do not edit
|
// END Generated code -- do not edit
|
||||||
|
|
||||||
|
asm_check((unsigned int *)entry, insns, sizeof insns / sizeof insns[0]);
|
||||||
|
|
||||||
{
|
{
|
||||||
bool ok = true;
|
address PC = __ pc();
|
||||||
unsigned int *insns1 = (unsigned int *)entry;
|
__ ld1(v0, __ T16B, Address(r16)); // No offset
|
||||||
for (unsigned int i = 0; i < sizeof insns / sizeof insns[0]; i++) {
|
__ ld1(v0, __ T8H, __ post(r16, 16)); // Post-index
|
||||||
if (insns[i] != insns1[i]) {
|
__ ld2(v0, v1, __ T8H, __ post(r24, 16 * 2)); // Post-index
|
||||||
ok = false;
|
__ ld1(v0, __ T16B, __ post(r16, r17)); // Register post-index
|
||||||
printf("Ours:\n");
|
static const unsigned int vector_insns[] = {
|
||||||
Disassembler::decode((address)&insns1[i], (address)&insns1[i+1]);
|
0x4c407200, // ld1 {v0.16b}, [x16]
|
||||||
printf("Theirs:\n");
|
0x4cdf7600, // ld1 {v0.8h}, [x16], #16
|
||||||
Disassembler::decode((address)&insns[i], (address)&insns[i+1]);
|
0x4cdf8700, // ld2 {v0.8h, v1.8h}, [x24], #32
|
||||||
printf("\n");
|
0x4cd17200, // ld1 {v0.16b}, [x16], x17
|
||||||
}
|
};
|
||||||
}
|
asm_check((unsigned int *)PC, vector_insns,
|
||||||
assert(ok, "Assembler smoke test failed");
|
sizeof vector_insns / sizeof vector_insns[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
|
|
||||||
address PC = __ pc();
|
|
||||||
__ ld1(v0, __ T16B, Address(r16)); // No offset
|
|
||||||
__ ld1(v0, __ T16B, __ post(r16, 0)); // Post-index
|
|
||||||
__ ld1(v0, __ T16B, Address(r16, r17)); //
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PRODUCT
|
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,8 +305,11 @@ public:
|
|||||||
Pre(Register reg, int o) : PrePost(reg, o) { }
|
Pre(Register reg, int o) : PrePost(reg, o) { }
|
||||||
};
|
};
|
||||||
class Post : public PrePost {
|
class Post : public PrePost {
|
||||||
|
Register _idx;
|
||||||
public:
|
public:
|
||||||
Post(Register reg, int o) : PrePost(reg, o) { }
|
Post(Register reg, int o) : PrePost(reg, o) { _idx = NULL; }
|
||||||
|
Post(Register reg, Register idx) : PrePost(reg, 0) { _idx = idx; }
|
||||||
|
Register idx_reg() { return _idx; }
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ext
|
namespace ext
|
||||||
@ -341,7 +344,7 @@ static inline unsigned long uabs(int n) { return uabs((unsigned int)n); }
|
|||||||
class Address {
|
class Address {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum mode { no_mode, base_plus_offset, pre, post, pcrel,
|
enum mode { no_mode, base_plus_offset, pre, post, post_reg, pcrel,
|
||||||
base_plus_offset_reg, literal };
|
base_plus_offset_reg, literal };
|
||||||
|
|
||||||
// Shift and extend for base reg + reg offset addressing
|
// Shift and extend for base reg + reg offset addressing
|
||||||
@ -413,7 +416,8 @@ class Address {
|
|||||||
Address(Pre p)
|
Address(Pre p)
|
||||||
: _mode(pre), _base(p.reg()), _offset(p.offset()) { }
|
: _mode(pre), _base(p.reg()), _offset(p.offset()) { }
|
||||||
Address(Post p)
|
Address(Post p)
|
||||||
: _mode(post), _base(p.reg()), _offset(p.offset()), _target(0) { }
|
: _mode(p.idx_reg() == NULL ? post : post_reg), _base(p.reg()),
|
||||||
|
_offset(p.offset()), _target(0), _index(p.idx_reg()) { }
|
||||||
Address(address target, RelocationHolder const& rspec)
|
Address(address target, RelocationHolder const& rspec)
|
||||||
: _mode(literal),
|
: _mode(literal),
|
||||||
_rspec(rspec),
|
_rspec(rspec),
|
||||||
@ -436,7 +440,7 @@ class Address {
|
|||||||
|
|
||||||
Register base() const {
|
Register base() const {
|
||||||
guarantee((_mode == base_plus_offset | _mode == base_plus_offset_reg
|
guarantee((_mode == base_plus_offset | _mode == base_plus_offset_reg
|
||||||
| _mode == post),
|
| _mode == post | _mode == post_reg),
|
||||||
"wrong mode");
|
"wrong mode");
|
||||||
return _base;
|
return _base;
|
||||||
}
|
}
|
||||||
@ -660,10 +664,14 @@ public:
|
|||||||
return adjust(base, offset, true);
|
return adjust(base, offset, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Address post (Register base, int offset) {
|
Address post(Register base, int offset) {
|
||||||
return adjust(base, offset, false);
|
return adjust(base, offset, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Address post(Register base, Register idx) {
|
||||||
|
return Address(Post(base, idx));
|
||||||
|
}
|
||||||
|
|
||||||
Instruction_aarch64* current;
|
Instruction_aarch64* current;
|
||||||
|
|
||||||
void set_current(Instruction_aarch64* i) { current = i; }
|
void set_current(Instruction_aarch64* i) { current = i; }
|
||||||
@ -2032,6 +2040,10 @@ public:
|
|||||||
B, H, S, D, Q
|
B, H, S, D, Q
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static short SIMD_Size_in_bytes[];
|
||||||
|
|
||||||
|
public:
|
||||||
#define INSN(NAME, op) \
|
#define INSN(NAME, op) \
|
||||||
void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) { \
|
void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) { \
|
||||||
ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \
|
ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \
|
||||||
@ -2051,7 +2063,8 @@ public:
|
|||||||
f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0);
|
f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0);
|
||||||
}
|
}
|
||||||
void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn,
|
void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn,
|
||||||
int imm, int op1, int op2) {
|
int imm, int op1, int op2, int regs) {
|
||||||
|
guarantee(T <= T1Q && imm == SIMD_Size_in_bytes[T] * regs, "bad offset");
|
||||||
starti;
|
starti;
|
||||||
f(0,31), f((int)T & 1, 30);
|
f(0,31), f((int)T & 1, 30);
|
||||||
f(op1 | 0b100, 29, 21), f(0b11111, 20, 16), f(op2, 15, 12);
|
f(op1 | 0b100, 29, 21), f(0b11111, 20, 16), f(op2, 15, 12);
|
||||||
@ -2065,34 +2078,34 @@ public:
|
|||||||
f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0);
|
f((int)T >> 1, 11, 10), srf(Xn, 5), rf(Vt, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ld_st(FloatRegister Vt, SIMD_Arrangement T, Address a, int op1, int op2) {
|
void ld_st(FloatRegister Vt, SIMD_Arrangement T, Address a, int op1, int op2, int regs) {
|
||||||
switch (a.getMode()) {
|
switch (a.getMode()) {
|
||||||
case Address::base_plus_offset:
|
case Address::base_plus_offset:
|
||||||
guarantee(a.offset() == 0, "no offset allowed here");
|
guarantee(a.offset() == 0, "no offset allowed here");
|
||||||
ld_st(Vt, T, a.base(), op1, op2);
|
ld_st(Vt, T, a.base(), op1, op2);
|
||||||
break;
|
break;
|
||||||
case Address::post:
|
case Address::post:
|
||||||
ld_st(Vt, T, a.base(), a.offset(), op1, op2);
|
ld_st(Vt, T, a.base(), a.offset(), op1, op2, regs);
|
||||||
break;
|
break;
|
||||||
case Address::base_plus_offset_reg:
|
case Address::post_reg:
|
||||||
ld_st(Vt, T, a.base(), a.index(), op1, op2);
|
ld_st(Vt, T, a.base(), a.index(), op1, op2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#define INSN1(NAME, op1, op2) \
|
#define INSN1(NAME, op1, op2) \
|
||||||
void NAME(FloatRegister Vt, SIMD_Arrangement T, const Address &a) { \
|
void NAME(FloatRegister Vt, SIMD_Arrangement T, const Address &a) { \
|
||||||
ld_st(Vt, T, a, op1, op2); \
|
ld_st(Vt, T, a, op1, op2, 1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSN2(NAME, op1, op2) \
|
#define INSN2(NAME, op1, op2) \
|
||||||
void NAME(FloatRegister Vt, FloatRegister Vt2, SIMD_Arrangement T, const Address &a) { \
|
void NAME(FloatRegister Vt, FloatRegister Vt2, SIMD_Arrangement T, const Address &a) { \
|
||||||
assert(Vt->successor() == Vt2, "Registers must be ordered"); \
|
assert(Vt->successor() == Vt2, "Registers must be ordered"); \
|
||||||
ld_st(Vt, T, a, op1, op2); \
|
ld_st(Vt, T, a, op1, op2, 2); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSN3(NAME, op1, op2) \
|
#define INSN3(NAME, op1, op2) \
|
||||||
@ -2100,7 +2113,7 @@ public:
|
|||||||
SIMD_Arrangement T, const Address &a) { \
|
SIMD_Arrangement T, const Address &a) { \
|
||||||
assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3, \
|
assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3, \
|
||||||
"Registers must be ordered"); \
|
"Registers must be ordered"); \
|
||||||
ld_st(Vt, T, a, op1, op2); \
|
ld_st(Vt, T, a, op1, op2, 3); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSN4(NAME, op1, op2) \
|
#define INSN4(NAME, op1, op2) \
|
||||||
@ -2108,7 +2121,7 @@ public:
|
|||||||
FloatRegister Vt4, SIMD_Arrangement T, const Address &a) { \
|
FloatRegister Vt4, SIMD_Arrangement T, const Address &a) { \
|
||||||
assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3 && \
|
assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3 && \
|
||||||
Vt3->successor() == Vt4, "Registers must be ordered"); \
|
Vt3->successor() == Vt4, "Registers must be ordered"); \
|
||||||
ld_st(Vt, T, a, op1, op2); \
|
ld_st(Vt, T, a, op1, op2, 4); \
|
||||||
}
|
}
|
||||||
|
|
||||||
INSN1(ld1, 0b001100010, 0b0111);
|
INSN1(ld1, 0b001100010, 0b0111);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user