mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 19:44:41 +02:00
8295270: RISC-V: Clean up and refactoring for assembler functions
Reviewed-by: fjiang, yadongwang, shade
This commit is contained in:
parent
be3b335452
commit
3d75e88eb2
12 changed files with 751 additions and 713 deletions
|
@ -719,7 +719,34 @@ void MacroAssembler::vfneg_v(VectorRegister vd, VectorRegister vs) {
|
|||
vfsgnjn_vv(vd, vs, vs);
|
||||
}
|
||||
|
||||
void MacroAssembler::la(Register Rd, const address &dest) {
|
||||
void MacroAssembler::baseOffset32(Register Rd, const Address &adr, int32_t &offset) {
|
||||
assert(Rd != noreg, "Rd must not be empty register!");
|
||||
guarantee(Rd != adr.base(), "should use different registers!");
|
||||
if (is_offset_in_range(adr.offset(), 32)) {
|
||||
int32_t imm = adr.offset();
|
||||
int32_t upper = imm, lower = imm;
|
||||
lower = (imm << 20) >> 20;
|
||||
upper -= lower;
|
||||
lui(Rd, upper);
|
||||
offset = lower;
|
||||
} else {
|
||||
offset = ((int32_t)adr.offset() << 20) >> 20;
|
||||
li(Rd, adr.offset() - offset);
|
||||
}
|
||||
add(Rd, Rd, adr.base());
|
||||
}
|
||||
|
||||
void MacroAssembler::baseOffset(Register Rd, const Address &adr, int32_t &offset) {
|
||||
if (is_offset_in_range(adr.offset(), 12)) {
|
||||
assert(Rd != noreg, "Rd must not be empty register!");
|
||||
addi(Rd, adr.base(), adr.offset());
|
||||
offset = 0;
|
||||
} else {
|
||||
baseOffset32(Rd, adr, offset);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::la(Register Rd, const address dest) {
|
||||
int64_t offset = dest - pc();
|
||||
if (is_offset_in_range(offset, 32)) {
|
||||
auipc(Rd, (int32_t)offset + 0x800); //0x800, Note:the 11th sign bit
|
||||
|
@ -757,8 +784,210 @@ void MacroAssembler::la(Register Rd, Label &label) {
|
|||
la(Rd, target(label));
|
||||
}
|
||||
|
||||
void MacroAssembler::li32(Register Rd, int32_t imm) {
|
||||
// int32_t is in range 0x8000 0000 ~ 0x7fff ffff, and imm[31] is the sign bit
|
||||
int64_t upper = imm, lower = imm;
|
||||
lower = (imm << 20) >> 20;
|
||||
upper -= lower;
|
||||
upper = (int32_t)upper;
|
||||
// lui Rd, imm[31:12] + imm[11]
|
||||
lui(Rd, upper);
|
||||
// use addiw to distinguish li32 to li64
|
||||
addiw(Rd, Rd, lower);
|
||||
}
|
||||
|
||||
void MacroAssembler::li64(Register Rd, int64_t imm) {
|
||||
// Load upper 32 bits. upper = imm[63:32], but if imm[31] == 1 or
|
||||
// (imm[31:20] == 0x7ff && imm[19] == 1), upper = imm[63:32] + 1.
|
||||
int64_t lower = imm & 0xffffffff;
|
||||
lower -= ((lower << 44) >> 44);
|
||||
int64_t tmp_imm = ((uint64_t)(imm & 0xffffffff00000000)) + (uint64_t)lower;
|
||||
int32_t upper = (tmp_imm - (int32_t)lower) >> 32;
|
||||
|
||||
// Load upper 32 bits
|
||||
int64_t up = upper, lo = upper;
|
||||
lo = (lo << 52) >> 52;
|
||||
up -= lo;
|
||||
up = (int32_t)up;
|
||||
lui(Rd, up);
|
||||
addi(Rd, Rd, lo);
|
||||
|
||||
// Load the rest 32 bits.
|
||||
slli(Rd, Rd, 12);
|
||||
addi(Rd, Rd, (int32_t)lower >> 20);
|
||||
slli(Rd, Rd, 12);
|
||||
lower = ((int32_t)imm << 12) >> 20;
|
||||
addi(Rd, Rd, lower);
|
||||
slli(Rd, Rd, 8);
|
||||
lower = imm & 0xff;
|
||||
addi(Rd, Rd, lower);
|
||||
}
|
||||
|
||||
void MacroAssembler::li(Register Rd, int64_t imm) {
|
||||
// int64_t is in range 0x8000 0000 0000 0000 ~ 0x7fff ffff ffff ffff
|
||||
// li -> c.li
|
||||
if (do_compress() && (is_imm_in_range(imm, 6, 0) && Rd != x0)) {
|
||||
c_li(Rd, imm);
|
||||
return;
|
||||
}
|
||||
|
||||
int shift = 12;
|
||||
int64_t upper = imm, lower = imm;
|
||||
// Split imm to a lower 12-bit sign-extended part and the remainder,
|
||||
// because addi will sign-extend the lower imm.
|
||||
lower = ((int32_t)imm << 20) >> 20;
|
||||
upper -= lower;
|
||||
|
||||
// Test whether imm is a 32-bit integer.
|
||||
if (!(((imm) & ~(int64_t)0x7fffffff) == 0 ||
|
||||
(((imm) & ~(int64_t)0x7fffffff) == ~(int64_t)0x7fffffff))) {
|
||||
while (((upper >> shift) & 1) == 0) { shift++; }
|
||||
upper >>= shift;
|
||||
li(Rd, upper);
|
||||
slli(Rd, Rd, shift);
|
||||
if (lower != 0) {
|
||||
addi(Rd, Rd, lower);
|
||||
}
|
||||
} else {
|
||||
// 32-bit integer
|
||||
Register hi_Rd = zr;
|
||||
if (upper != 0) {
|
||||
lui(Rd, (int32_t)upper);
|
||||
hi_Rd = Rd;
|
||||
}
|
||||
if (lower != 0 || hi_Rd == zr) {
|
||||
addiw(Rd, hi_Rd, lower);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define INSN(NAME, REGISTER) \
|
||||
void MacroAssembler::NAME(const address dest, Register temp) { \
|
||||
assert_cond(dest != NULL); \
|
||||
int64_t distance = dest - pc(); \
|
||||
if (is_imm_in_range(distance, 20, 1)) { \
|
||||
Assembler::jal(REGISTER, distance); \
|
||||
} else { \
|
||||
assert(temp != noreg, "temp must not be empty register!"); \
|
||||
int32_t offset = 0; \
|
||||
movptr(temp, dest, offset); \
|
||||
Assembler::jalr(REGISTER, temp, offset); \
|
||||
} \
|
||||
} \
|
||||
|
||||
INSN(j, x0);
|
||||
INSN(jal, x1);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, REGISTER) \
|
||||
void MacroAssembler::NAME(const Address &adr, Register temp) { \
|
||||
switch (adr.getMode()) { \
|
||||
case Address::literal: { \
|
||||
relocate(adr.rspec()); \
|
||||
NAME(adr.target(), temp); \
|
||||
break; \
|
||||
} \
|
||||
case Address::base_plus_offset: { \
|
||||
int32_t offset = 0; \
|
||||
baseOffset(temp, adr, offset); \
|
||||
Assembler::jalr(REGISTER, temp, offset); \
|
||||
break; \
|
||||
} \
|
||||
default: \
|
||||
ShouldNotReachHere(); \
|
||||
} \
|
||||
}
|
||||
|
||||
INSN(j, x0);
|
||||
INSN(jal, x1);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME) \
|
||||
void MacroAssembler::NAME(Register Rd, const address dest, Register temp) { \
|
||||
assert_cond(dest != NULL); \
|
||||
int64_t distance = dest - pc(); \
|
||||
if (is_imm_in_range(distance, 20, 1)) { \
|
||||
Assembler::NAME(Rd, distance); \
|
||||
} else { \
|
||||
assert_different_registers(Rd, temp); \
|
||||
int32_t offset = 0; \
|
||||
movptr(temp, dest, offset); \
|
||||
jalr(Rd, temp, offset); \
|
||||
} \
|
||||
} \
|
||||
void MacroAssembler::NAME(Register Rd, Label &L, Register temp) { \
|
||||
assert_different_registers(Rd, temp); \
|
||||
wrap_label(Rd, L, temp, &MacroAssembler::NAME); \
|
||||
}
|
||||
|
||||
INSN(jal);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, REGISTER) \
|
||||
void MacroAssembler::NAME(Label &l, Register temp) { \
|
||||
jal(REGISTER, l, temp); \
|
||||
} \
|
||||
|
||||
INSN(j, x0);
|
||||
INSN(jal, x1);
|
||||
|
||||
#undef INSN
|
||||
|
||||
void MacroAssembler::wrap_label(Register Rt, Label &L, Register tmp, load_insn_by_temp insn) {
|
||||
if (L.is_bound()) {
|
||||
(this->*insn)(Rt, target(L), tmp);
|
||||
} else {
|
||||
L.add_patch_at(code(), locator());
|
||||
(this->*insn)(Rt, pc(), tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::wrap_label(Register Rt, Label &L, jal_jalr_insn insn) {
|
||||
if (L.is_bound()) {
|
||||
(this->*insn)(Rt, target(L));
|
||||
} else {
|
||||
L.add_patch_at(code(), locator());
|
||||
(this->*insn)(Rt, pc());
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::wrap_label(Register r1, Register r2, Label &L,
|
||||
compare_and_branch_insn insn,
|
||||
compare_and_branch_label_insn neg_insn, bool is_far) {
|
||||
if (is_far) {
|
||||
Label done;
|
||||
(this->*neg_insn)(r1, r2, done, /* is_far */ false);
|
||||
j(L);
|
||||
bind(done);
|
||||
} else {
|
||||
if (L.is_bound()) {
|
||||
(this->*insn)(r1, r2, target(L));
|
||||
} else {
|
||||
L.add_patch_at(code(), locator());
|
||||
(this->*insn)(r1, r2, pc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define INSN(NAME, NEG_INSN) \
|
||||
void MacroAssembler::NAME(Register Rs1, Register Rs2, Label &L, bool is_far) { \
|
||||
wrap_label(Rs1, Rs2, L, &MacroAssembler::NAME, &MacroAssembler::NEG_INSN, is_far); \
|
||||
}
|
||||
|
||||
INSN(beq, bne);
|
||||
INSN(bne, beq);
|
||||
INSN(blt, bge);
|
||||
INSN(bge, blt);
|
||||
INSN(bltu, bgeu);
|
||||
INSN(bgeu, bltu);
|
||||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME) \
|
||||
void MacroAssembler::NAME##z(Register Rs, const address &dest) { \
|
||||
void MacroAssembler::NAME##z(Register Rs, const address dest) { \
|
||||
NAME(Rs, zr, dest); \
|
||||
} \
|
||||
void MacroAssembler::NAME##z(Register Rs, Label &l, bool is_far) { \
|
||||
|
@ -774,16 +1003,31 @@ void MacroAssembler::la(Register Rd, Label &label) {
|
|||
|
||||
#undef INSN
|
||||
|
||||
#define INSN(NAME, NEG_INSN) \
|
||||
void MacroAssembler::NAME(Register Rs, Register Rt, const address dest) { \
|
||||
NEG_INSN(Rt, Rs, dest); \
|
||||
} \
|
||||
void MacroAssembler::NAME(Register Rs, Register Rt, Label &l, bool is_far) { \
|
||||
NEG_INSN(Rt, Rs, l, is_far); \
|
||||
}
|
||||
|
||||
INSN(bgt, blt);
|
||||
INSN(ble, bge);
|
||||
INSN(bgtu, bltu);
|
||||
INSN(bleu, bgeu);
|
||||
|
||||
#undef INSN
|
||||
|
||||
// Float compare branch instructions
|
||||
|
||||
#define INSN(NAME, FLOATCMP, BRANCH) \
|
||||
void MacroAssembler::float_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \
|
||||
FLOATCMP##_s(t0, Rs1, Rs2); \
|
||||
BRANCH(t0, l, is_far); \
|
||||
} \
|
||||
void MacroAssembler::double_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \
|
||||
FLOATCMP##_d(t0, Rs1, Rs2); \
|
||||
BRANCH(t0, l, is_far); \
|
||||
#define INSN(NAME, FLOATCMP, BRANCH) \
|
||||
void MacroAssembler::float_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \
|
||||
FLOATCMP##_s(t0, Rs1, Rs2); \
|
||||
BRANCH(t0, l, is_far); \
|
||||
} \
|
||||
void MacroAssembler::double_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \
|
||||
FLOATCMP##_d(t0, Rs1, Rs2); \
|
||||
BRANCH(t0, l, is_far); \
|
||||
}
|
||||
|
||||
INSN(beq, feq, bnez);
|
||||
|
@ -928,7 +1172,7 @@ void MacroAssembler::push_reg(Register Rs)
|
|||
|
||||
void MacroAssembler::pop_reg(Register Rd)
|
||||
{
|
||||
ld(Rd, esp, 0);
|
||||
ld(Rd, Address(esp, 0));
|
||||
addi(esp, esp, wordSize);
|
||||
}
|
||||
|
||||
|
@ -1361,6 +1605,85 @@ void MacroAssembler::mv(Register Rd, RegisterOrConstant src) {
|
|||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::movptr(Register Rd, address addr, int32_t &offset) {
|
||||
int64_t imm64 = (int64_t)addr;
|
||||
#ifndef PRODUCT
|
||||
{
|
||||
char buffer[64];
|
||||
snprintf(buffer, sizeof(buffer), "0x%" PRIx64, imm64);
|
||||
block_comment(buffer);
|
||||
}
|
||||
#endif
|
||||
assert(is_unsigned_imm_in_range(imm64, 47, 0) || (imm64 == (int64_t)-1),
|
||||
"bit 47 overflows in address constant");
|
||||
// Load upper 31 bits
|
||||
int64_t imm = imm64 >> 17;
|
||||
int64_t upper = imm, lower = imm;
|
||||
lower = (lower << 52) >> 52;
|
||||
upper -= lower;
|
||||
upper = (int32_t)upper;
|
||||
lui(Rd, upper);
|
||||
addi(Rd, Rd, lower);
|
||||
|
||||
// Load the rest 17 bits.
|
||||
slli(Rd, Rd, 11);
|
||||
addi(Rd, Rd, (imm64 >> 6) & 0x7ff);
|
||||
slli(Rd, Rd, 6);
|
||||
|
||||
// This offset will be used by following jalr/ld.
|
||||
offset = imm64 & 0x3f;
|
||||
}
|
||||
|
||||
void MacroAssembler::movptr(Register Rd, uintptr_t imm64) {
|
||||
movptr(Rd, (address)imm64);
|
||||
}
|
||||
|
||||
void MacroAssembler::movptr(Register Rd, address addr) {
|
||||
int offset = 0;
|
||||
movptr(Rd, addr, offset);
|
||||
addi(Rd, Rd, offset);
|
||||
}
|
||||
|
||||
void MacroAssembler::add(Register Rd, Register Rn, int64_t increment, Register temp) {
|
||||
if (is_imm_in_range(increment, 12, 0)) {
|
||||
addi(Rd, Rn, increment);
|
||||
} else {
|
||||
assert_different_registers(Rn, temp);
|
||||
li(temp, increment);
|
||||
add(Rd, Rn, temp);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::addw(Register Rd, Register Rn, int32_t increment, Register temp) {
|
||||
if (is_imm_in_range(increment, 12, 0)) {
|
||||
addiw(Rd, Rn, increment);
|
||||
} else {
|
||||
assert_different_registers(Rn, temp);
|
||||
li(temp, increment);
|
||||
addw(Rd, Rn, temp);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::sub(Register Rd, Register Rn, int64_t decrement, Register temp) {
|
||||
if (is_imm_in_range(-decrement, 12, 0)) {
|
||||
addi(Rd, Rn, -decrement);
|
||||
} else {
|
||||
assert_different_registers(Rn, temp);
|
||||
li(temp, decrement);
|
||||
sub(Rd, Rn, temp);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::subw(Register Rd, Register Rn, int32_t decrement, Register temp) {
|
||||
if (is_imm_in_range(-decrement, 12, 0)) {
|
||||
addiw(Rd, Rn, -decrement);
|
||||
} else {
|
||||
assert_different_registers(Rn, temp);
|
||||
li(temp, decrement);
|
||||
subw(Rd, Rn, temp);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::andrw(Register Rd, Register Rs1, Register Rs2) {
|
||||
andr(Rd, Rs1, Rs2);
|
||||
// addw: The result is clipped to 32 bits, then the sign bit is extended,
|
||||
|
@ -3858,7 +4181,7 @@ void MacroAssembler::zero_memory(Register addr, Register len, Register tmp) {
|
|||
bind(loop);
|
||||
sub(len, len, unroll);
|
||||
for (int i = -unroll; i < 0; i++) {
|
||||
Assembler::sd(zr, Address(tmp, i * wordSize));
|
||||
sd(zr, Address(tmp, i * wordSize));
|
||||
}
|
||||
bind(entry);
|
||||
add(tmp, tmp, unroll * wordSize);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue