Skip to content

Commit

Permalink
8295270: RISC-V: Clean up and refactoring for assembler functions
Browse files Browse the repository at this point in the history
Reviewed-by: fjiang, yadongwang, shade
  • Loading branch information
RealFYang committed Oct 14, 2022
1 parent be3b335 commit 3d75e88
Show file tree
Hide file tree
Showing 12 changed files with 751 additions and 713 deletions.
261 changes: 0 additions & 261 deletions src/hotspot/cpu/riscv/assembler_riscv.cpp
Expand Up @@ -40,267 +40,6 @@ int AbstractAssembler::code_fill_byte() {
return 0;
}

void Assembler::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 Assembler::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 Assembler::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 Assembler::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 Assembler::zext_w(Register Rd, Register Rs) {
add_uw(Rd, Rs, zr);
}

void Assembler::_li(Register Rd, int64_t imm) {
// int64_t is in range 0x8000 0000 0000 0000 ~ 0x7fff ffff ffff ffff
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);
}
}
}

void Assembler::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 Assembler::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);
}

#define INSN(NAME, REGISTER) \
void Assembler::NAME(const address &dest, Register temp) { \
assert_cond(dest != NULL); \
int64_t distance = dest - pc(); \
if (is_imm_in_range(distance, 20, 1)) { \
jal(REGISTER, distance); \
} else { \
assert(temp != noreg, "temp must not be empty register!"); \
int32_t offset = 0; \
movptr(temp, dest, offset); \
jalr(REGISTER, temp, offset); \
} \
} \
void Assembler::NAME(Label &l, Register temp) { \
jal(REGISTER, l, temp); \
} \

INSN(j, x0);
INSN(jal, x1);

#undef INSN

#define INSN(NAME, REGISTER) \
void Assembler::NAME(Register Rs) { \
jalr(REGISTER, Rs, 0); \
}

INSN(jr, x0);
INSN(jalr, x1);

#undef INSN

#define INSN(NAME, REGISTER) \
void Assembler::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); \
jalr(REGISTER, temp, offset); \
break; \
} \
default: \
ShouldNotReachHere(); \
} \
}

INSN(j, x0);
INSN(jal, x1);

#undef INSN

void Assembler::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());
}
}
}

void Assembler::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 Assembler::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 Assembler::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 Assembler::movptr(Register Rd, uintptr_t imm64) {
movptr(Rd, (address)imm64);
}

void Assembler::movptr(Register Rd, address addr) {
int offset = 0;
movptr(Rd, addr, offset);
addi(Rd, Rd, offset);
}

#define INSN(NAME, NEG_INSN) \
void Assembler::NAME(Register Rs, Register Rt, const address &dest) { \
NEG_INSN(Rt, Rs, dest); \
} \
void Assembler::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

#undef __

Address::Address(address target, relocInfo::relocType rtype) : _base(noreg), _offset(0), _mode(literal) {
_target = target;
switch (rtype) {
Expand Down

0 comments on commit 3d75e88

Please sign in to comment.