mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-22 03:54:33 +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
|
@ -40,267 +40,6 @@ int AbstractAssembler::code_fill_byte() {
|
||||||
return 0;
|
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) {
|
Address::Address(address target, relocInfo::relocType rtype) : _base(noreg), _offset(0), _mode(literal) {
|
||||||
_target = target;
|
_target = target;
|
||||||
switch (rtype) {
|
switch (rtype) {
|
||||||
|
|
|
@ -171,6 +171,7 @@ class Address {
|
||||||
public:
|
public:
|
||||||
Address()
|
Address()
|
||||||
: _base(noreg), _index(noreg), _offset(0), _mode(no_mode), _target(NULL) { }
|
: _base(noreg), _index(noreg), _offset(0), _mode(no_mode), _target(NULL) { }
|
||||||
|
|
||||||
Address(Register r)
|
Address(Register r)
|
||||||
: _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(NULL) { }
|
: _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(NULL) { }
|
||||||
|
|
||||||
|
@ -180,6 +181,7 @@ class Address {
|
||||||
|
|
||||||
Address(Register r, ByteSize disp)
|
Address(Register r, ByteSize disp)
|
||||||
: Address(r, in_bytes(disp)) {}
|
: Address(r, in_bytes(disp)) {}
|
||||||
|
|
||||||
Address(address target, RelocationHolder const& rspec)
|
Address(address target, RelocationHolder const& rspec)
|
||||||
: _base(noreg),
|
: _base(noreg),
|
||||||
_index(noreg),
|
_index(noreg),
|
||||||
|
@ -187,6 +189,7 @@ class Address {
|
||||||
_mode(literal),
|
_mode(literal),
|
||||||
_rspec(rspec),
|
_rspec(rspec),
|
||||||
_target(target) { }
|
_target(target) { }
|
||||||
|
|
||||||
Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type);
|
Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type);
|
||||||
|
|
||||||
const Register base() const {
|
const Register base() const {
|
||||||
|
@ -291,48 +294,6 @@ public:
|
||||||
rdy = 0b111, // in instruction's rm field, selects dynamic rounding mode.In Rounding Mode register, Invalid.
|
rdy = 0b111, // in instruction's rm field, selects dynamic rounding mode.In Rounding Mode register, Invalid.
|
||||||
};
|
};
|
||||||
|
|
||||||
void 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 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 _li(Register Rd, int64_t imm); // optimized load immediate
|
|
||||||
void li32(Register Rd, int32_t imm);
|
|
||||||
void li64(Register Rd, int64_t imm);
|
|
||||||
void movptr(Register Rd, address addr);
|
|
||||||
void movptr(Register Rd, address addr, int32_t &offset);
|
|
||||||
void movptr(Register Rd, uintptr_t imm64);
|
|
||||||
void j(const address &dest, Register temp = t0);
|
|
||||||
void j(const Address &adr, Register temp = t0);
|
|
||||||
void j(Label &l, Register temp = t0);
|
|
||||||
void jal(Label &l, Register temp = t0);
|
|
||||||
void jal(const address &dest, Register temp = t0);
|
|
||||||
void jal(const Address &adr, Register temp = t0);
|
|
||||||
void jr(Register Rs);
|
|
||||||
void jalr(Register Rs);
|
|
||||||
|
|
||||||
static inline uint32_t extract(uint32_t val, unsigned msb, unsigned lsb) {
|
static inline uint32_t extract(uint32_t val, unsigned msb, unsigned lsb) {
|
||||||
assert_cond(msb >= lsb && msb <= 31);
|
assert_cond(msb >= lsb && msb <= 31);
|
||||||
unsigned nbits = msb - lsb + 1;
|
unsigned nbits = msb - lsb + 1;
|
||||||
|
@ -474,13 +435,7 @@ public:
|
||||||
|
|
||||||
#undef INSN
|
#undef INSN
|
||||||
|
|
||||||
#define INSN_ENTRY_RELOC(result_type, header) \
|
// Load/store register (all modes)
|
||||||
result_type header { \
|
|
||||||
guarantee(rtype == relocInfo::internal_word_type, \
|
|
||||||
"only internal_word_type relocs make sense here"); \
|
|
||||||
relocate(InternalAddress(dest).rspec());
|
|
||||||
|
|
||||||
// Load/store register (all modes)
|
|
||||||
#define INSN(NAME, op, funct3) \
|
#define INSN(NAME, op, funct3) \
|
||||||
void NAME(Register Rd, Register Rs, const int32_t offset) { \
|
void NAME(Register Rd, Register Rs, const int32_t offset) { \
|
||||||
guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \
|
guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \
|
||||||
|
@ -504,62 +459,6 @@ public:
|
||||||
|
|
||||||
#undef INSN
|
#undef INSN
|
||||||
|
|
||||||
#define INSN(NAME) \
|
|
||||||
void NAME(Register Rd, address dest) { \
|
|
||||||
assert_cond(dest != NULL); \
|
|
||||||
int64_t distance = (dest - pc()); \
|
|
||||||
if (is_offset_in_range(distance, 32)) { \
|
|
||||||
auipc(Rd, (int32_t)distance + 0x800); \
|
|
||||||
NAME(Rd, Rd, ((int32_t)distance << 20) >> 20); \
|
|
||||||
} else { \
|
|
||||||
int32_t offset = 0; \
|
|
||||||
movptr(Rd, dest, offset); \
|
|
||||||
NAME(Rd, Rd, offset); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
INSN_ENTRY_RELOC(void, NAME(Register Rd, address dest, relocInfo::relocType rtype)) \
|
|
||||||
NAME(Rd, dest); \
|
|
||||||
} \
|
|
||||||
void NAME(Register Rd, const Address &adr, Register temp = t0) { \
|
|
||||||
switch (adr.getMode()) { \
|
|
||||||
case Address::literal: { \
|
|
||||||
relocate(adr.rspec()); \
|
|
||||||
NAME(Rd, adr.target()); \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
case Address::base_plus_offset: { \
|
|
||||||
if (is_offset_in_range(adr.offset(), 12)) { \
|
|
||||||
NAME(Rd, adr.base(), adr.offset()); \
|
|
||||||
} else { \
|
|
||||||
int32_t offset = 0; \
|
|
||||||
if (Rd == adr.base()) { \
|
|
||||||
baseOffset32(temp, adr, offset); \
|
|
||||||
NAME(Rd, temp, offset); \
|
|
||||||
} else { \
|
|
||||||
baseOffset32(Rd, adr, offset); \
|
|
||||||
NAME(Rd, Rd, offset); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
default: \
|
|
||||||
ShouldNotReachHere(); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
void NAME(Register Rd, Label &L) { \
|
|
||||||
wrap_label(Rd, L, &Assembler::NAME); \
|
|
||||||
}
|
|
||||||
|
|
||||||
INSN(lb);
|
|
||||||
INSN(lbu);
|
|
||||||
INSN(lh);
|
|
||||||
INSN(lhu);
|
|
||||||
INSN(lw);
|
|
||||||
INSN(lwu);
|
|
||||||
INSN(ld);
|
|
||||||
|
|
||||||
#undef INSN
|
|
||||||
|
|
||||||
#define INSN(NAME, op, funct3) \
|
#define INSN(NAME, op, funct3) \
|
||||||
void NAME(FloatRegister Rd, Register Rs, const int32_t offset) { \
|
void NAME(FloatRegister Rd, Register Rs, const int32_t offset) { \
|
||||||
guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \
|
guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \
|
||||||
|
@ -578,48 +477,6 @@ public:
|
||||||
|
|
||||||
#undef INSN
|
#undef INSN
|
||||||
|
|
||||||
#define INSN(NAME) \
|
|
||||||
void NAME(FloatRegister Rd, address dest, Register temp = t0) { \
|
|
||||||
assert_cond(dest != NULL); \
|
|
||||||
int64_t distance = (dest - pc()); \
|
|
||||||
if (is_offset_in_range(distance, 32)) { \
|
|
||||||
auipc(temp, (int32_t)distance + 0x800); \
|
|
||||||
NAME(Rd, temp, ((int32_t)distance << 20) >> 20); \
|
|
||||||
} else { \
|
|
||||||
int32_t offset = 0; \
|
|
||||||
movptr(temp, dest, offset); \
|
|
||||||
NAME(Rd, temp, offset); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
INSN_ENTRY_RELOC(void, NAME(FloatRegister Rd, address dest, relocInfo::relocType rtype, Register temp = t0)) \
|
|
||||||
NAME(Rd, dest, temp); \
|
|
||||||
} \
|
|
||||||
void NAME(FloatRegister Rd, const Address &adr, Register temp = t0) { \
|
|
||||||
switch (adr.getMode()) { \
|
|
||||||
case Address::literal: { \
|
|
||||||
relocate(adr.rspec()); \
|
|
||||||
NAME(Rd, adr.target(), temp); \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
case Address::base_plus_offset: { \
|
|
||||||
if (is_offset_in_range(adr.offset(), 12)) { \
|
|
||||||
NAME(Rd, adr.base(), adr.offset()); \
|
|
||||||
} else { \
|
|
||||||
int32_t offset = 0; \
|
|
||||||
baseOffset32(temp, adr, offset); \
|
|
||||||
NAME(Rd, temp, offset); \
|
|
||||||
} \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
default: \
|
|
||||||
ShouldNotReachHere(); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
INSN(flw);
|
|
||||||
INSN(fld);
|
|
||||||
#undef INSN
|
|
||||||
|
|
||||||
#define INSN(NAME, op, funct3) \
|
#define INSN(NAME, op, funct3) \
|
||||||
void NAME(Register Rs1, Register Rs2, const int64_t offset) { \
|
void NAME(Register Rs1, Register Rs2, const int64_t offset) { \
|
||||||
guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid."); \
|
guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid."); \
|
||||||
|
@ -649,40 +506,6 @@ public:
|
||||||
|
|
||||||
#undef INSN
|
#undef INSN
|
||||||
|
|
||||||
#define INSN(NAME) \
|
|
||||||
void NAME(Register Rs1, Register Rs2, const address dest) { \
|
|
||||||
assert_cond(dest != NULL); \
|
|
||||||
int64_t offset = (dest - pc()); \
|
|
||||||
guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid."); \
|
|
||||||
NAME(Rs1, Rs2, offset); \
|
|
||||||
} \
|
|
||||||
INSN_ENTRY_RELOC(void, NAME(Register Rs1, Register Rs2, address dest, relocInfo::relocType rtype)) \
|
|
||||||
NAME(Rs1, Rs2, dest); \
|
|
||||||
}
|
|
||||||
|
|
||||||
INSN(beq);
|
|
||||||
INSN(bne);
|
|
||||||
INSN(bge);
|
|
||||||
INSN(bgeu);
|
|
||||||
INSN(blt);
|
|
||||||
INSN(bltu);
|
|
||||||
|
|
||||||
#undef INSN
|
|
||||||
|
|
||||||
#define INSN(NAME, NEG_INSN) \
|
|
||||||
void NAME(Register Rs1, Register Rs2, Label &L, bool is_far = false) { \
|
|
||||||
wrap_label(Rs1, Rs2, L, &Assembler::NAME, &Assembler::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, REGISTER, op, funct3) \
|
#define INSN(NAME, REGISTER, op, funct3) \
|
||||||
void NAME(REGISTER Rs1, Register Rs2, const int32_t offset) { \
|
void NAME(REGISTER Rs1, Register Rs2, const int32_t offset) { \
|
||||||
guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \
|
guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \
|
||||||
|
@ -708,105 +531,6 @@ public:
|
||||||
|
|
||||||
#undef INSN
|
#undef INSN
|
||||||
|
|
||||||
#define INSN(NAME, REGISTER) \
|
|
||||||
INSN_ENTRY_RELOC(void, NAME(REGISTER Rs, address dest, relocInfo::relocType rtype, Register temp = t0)) \
|
|
||||||
NAME(Rs, dest, temp); \
|
|
||||||
}
|
|
||||||
|
|
||||||
INSN(sb, Register);
|
|
||||||
INSN(sh, Register);
|
|
||||||
INSN(sw, Register);
|
|
||||||
INSN(sd, Register);
|
|
||||||
INSN(fsw, FloatRegister);
|
|
||||||
INSN(fsd, FloatRegister);
|
|
||||||
|
|
||||||
#undef INSN
|
|
||||||
|
|
||||||
#define INSN(NAME) \
|
|
||||||
void NAME(Register Rs, address dest, Register temp = t0) { \
|
|
||||||
assert_cond(dest != NULL); \
|
|
||||||
assert_different_registers(Rs, temp); \
|
|
||||||
int64_t distance = (dest - pc()); \
|
|
||||||
if (is_offset_in_range(distance, 32)) { \
|
|
||||||
auipc(temp, (int32_t)distance + 0x800); \
|
|
||||||
NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \
|
|
||||||
} else { \
|
|
||||||
int32_t offset = 0; \
|
|
||||||
movptr(temp, dest, offset); \
|
|
||||||
NAME(Rs, temp, offset); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
void NAME(Register Rs, const Address &adr, Register temp = t0) { \
|
|
||||||
switch (adr.getMode()) { \
|
|
||||||
case Address::literal: { \
|
|
||||||
assert_different_registers(Rs, temp); \
|
|
||||||
relocate(adr.rspec()); \
|
|
||||||
NAME(Rs, adr.target(), temp); \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
case Address::base_plus_offset: { \
|
|
||||||
if (is_offset_in_range(adr.offset(), 12)) { \
|
|
||||||
NAME(Rs, adr.base(), adr.offset()); \
|
|
||||||
} else { \
|
|
||||||
int32_t offset= 0; \
|
|
||||||
assert_different_registers(Rs, temp); \
|
|
||||||
baseOffset32(temp, adr, offset); \
|
|
||||||
NAME(Rs, temp, offset); \
|
|
||||||
} \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
default: \
|
|
||||||
ShouldNotReachHere(); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
INSN(sb);
|
|
||||||
INSN(sh);
|
|
||||||
INSN(sw);
|
|
||||||
INSN(sd);
|
|
||||||
|
|
||||||
#undef INSN
|
|
||||||
|
|
||||||
#define INSN(NAME) \
|
|
||||||
void NAME(FloatRegister Rs, address dest, Register temp = t0) { \
|
|
||||||
assert_cond(dest != NULL); \
|
|
||||||
int64_t distance = (dest - pc()); \
|
|
||||||
if (is_offset_in_range(distance, 32)) { \
|
|
||||||
auipc(temp, (int32_t)distance + 0x800); \
|
|
||||||
NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \
|
|
||||||
} else { \
|
|
||||||
int32_t offset = 0; \
|
|
||||||
movptr(temp, dest, offset); \
|
|
||||||
NAME(Rs, temp, offset); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
void NAME(FloatRegister Rs, const Address &adr, Register temp = t0) { \
|
|
||||||
switch (adr.getMode()) { \
|
|
||||||
case Address::literal: { \
|
|
||||||
relocate(adr.rspec()); \
|
|
||||||
NAME(Rs, adr.target(), temp); \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
case Address::base_plus_offset: { \
|
|
||||||
if (is_offset_in_range(adr.offset(), 12)) { \
|
|
||||||
NAME(Rs, adr.base(), adr.offset()); \
|
|
||||||
} else { \
|
|
||||||
int32_t offset = 0; \
|
|
||||||
baseOffset32(temp, adr, offset); \
|
|
||||||
NAME(Rs, temp, offset); \
|
|
||||||
} \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
default: \
|
|
||||||
ShouldNotReachHere(); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
INSN(fsw);
|
|
||||||
INSN(fsd);
|
|
||||||
|
|
||||||
#undef INSN
|
|
||||||
|
|
||||||
#define INSN(NAME, op, funct3) \
|
#define INSN(NAME, op, funct3) \
|
||||||
void NAME(Register Rd, const uint32_t csr, Register Rs1) { \
|
void NAME(Register Rd, const uint32_t csr, Register Rs1) { \
|
||||||
guarantee(is_unsigned_imm_in_range(csr, 12, 0), "csr is invalid"); \
|
guarantee(is_unsigned_imm_in_range(csr, 12, 0), "csr is invalid"); \
|
||||||
|
@ -862,30 +586,6 @@ public:
|
||||||
|
|
||||||
#undef INSN
|
#undef INSN
|
||||||
|
|
||||||
#define INSN(NAME) \
|
|
||||||
void NAME(Register Rd, const address dest, Register temp = t0) { \
|
|
||||||
assert_cond(dest != NULL); \
|
|
||||||
int64_t offset = dest - pc(); \
|
|
||||||
if (is_imm_in_range(offset, 20, 1)) { \
|
|
||||||
NAME(Rd, offset); \
|
|
||||||
} else { \
|
|
||||||
assert_different_registers(Rd, temp); \
|
|
||||||
int32_t off = 0; \
|
|
||||||
movptr(temp, dest, off); \
|
|
||||||
jalr(Rd, temp, off); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
void NAME(Register Rd, Label &L, Register temp = t0) { \
|
|
||||||
assert_different_registers(Rd, temp); \
|
|
||||||
wrap_label(Rd, L, temp, &Assembler::NAME); \
|
|
||||||
}
|
|
||||||
|
|
||||||
INSN(jal);
|
|
||||||
|
|
||||||
#undef INSN
|
|
||||||
|
|
||||||
#undef INSN_ENTRY_RELOC
|
|
||||||
|
|
||||||
#define INSN(NAME, op, funct) \
|
#define INSN(NAME, op, funct) \
|
||||||
void NAME(Register Rd, Register Rs, const int32_t offset) { \
|
void NAME(Register Rd, Register Rs, const int32_t offset) { \
|
||||||
guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \
|
guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \
|
||||||
|
@ -2676,10 +2376,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// some helper functions
|
// some helper functions
|
||||||
bool do_compress() const {
|
|
||||||
return UseRVC && in_compressible_region();
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FUNC(NAME, funct3, bits) \
|
#define FUNC(NAME, funct3, bits) \
|
||||||
bool NAME(Register rs1, Register rd_rs2, int32_t imm12, bool ld) { \
|
bool NAME(Register rs1, Register rd_rs2, int32_t imm12, bool ld) { \
|
||||||
return rs1 == sp && \
|
return rs1 == sp && \
|
||||||
|
@ -2719,6 +2415,10 @@ private:
|
||||||
#undef FUNC
|
#undef FUNC
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool do_compress() const {
|
||||||
|
return UseRVC && in_compressible_region();
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------
|
// --------------------------
|
||||||
// Load/store register
|
// Load/store register
|
||||||
// --------------------------
|
// --------------------------
|
||||||
|
@ -2882,21 +2582,6 @@ public:
|
||||||
|
|
||||||
// --------------------------
|
// --------------------------
|
||||||
// Immediate Instructions
|
// Immediate Instructions
|
||||||
// --------------------------
|
|
||||||
#define INSN(NAME) \
|
|
||||||
void NAME(Register Rd, int64_t imm) { \
|
|
||||||
/* li -> c.li */ \
|
|
||||||
if (do_compress() && (is_imm_in_range(imm, 6, 0) && Rd != x0)) { \
|
|
||||||
c_li(Rd, imm); \
|
|
||||||
return; \
|
|
||||||
} \
|
|
||||||
_li(Rd, imm); \
|
|
||||||
}
|
|
||||||
|
|
||||||
INSN(li);
|
|
||||||
|
|
||||||
#undef INSN
|
|
||||||
|
|
||||||
// --------------------------
|
// --------------------------
|
||||||
#define INSN(NAME) \
|
#define INSN(NAME) \
|
||||||
void NAME(Register Rd, Register Rs1, int32_t imm) { \
|
void NAME(Register Rd, Register Rs1, int32_t imm) { \
|
||||||
|
@ -3008,37 +2693,20 @@ public:
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void bgt(Register Rs, Register Rt, const address &dest);
|
#define INSN(NAME, REGISTER) \
|
||||||
void ble(Register Rs, Register Rt, const address &dest);
|
void NAME(Register Rs) { \
|
||||||
void bgtu(Register Rs, Register Rt, const address &dest);
|
jalr(REGISTER, Rs, 0); \
|
||||||
void bleu(Register Rs, Register Rt, const address &dest);
|
}
|
||||||
void bgt(Register Rs, Register Rt, Label &l, bool is_far = false);
|
|
||||||
void ble(Register Rs, Register Rt, Label &l, bool is_far = false);
|
|
||||||
void bgtu(Register Rs, Register Rt, Label &l, bool is_far = false);
|
|
||||||
void bleu(Register Rs, Register Rt, Label &l, bool is_far = false);
|
|
||||||
|
|
||||||
typedef void (Assembler::* jal_jalr_insn)(Register Rt, address dest);
|
INSN(jr, x0);
|
||||||
typedef void (Assembler::* load_insn_by_temp)(Register Rt, address dest, Register temp);
|
INSN(jalr, x1);
|
||||||
typedef void (Assembler::* compare_and_branch_insn)(Register Rs1, Register Rs2, const address dest);
|
|
||||||
typedef void (Assembler::* compare_and_branch_label_insn)(Register Rs1, Register Rs2, Label &L, bool is_far);
|
|
||||||
|
|
||||||
void wrap_label(Register r1, Register r2, Label &L, compare_and_branch_insn insn,
|
#undef INSN
|
||||||
compare_and_branch_label_insn neg_insn, bool is_far);
|
|
||||||
void wrap_label(Register r, Label &L, Register t, load_insn_by_temp insn);
|
|
||||||
void wrap_label(Register r, Label &L, jal_jalr_insn insn);
|
|
||||||
|
|
||||||
// Computational pseudo instructions
|
|
||||||
void add(Register Rd, Register Rn, int64_t increment, Register temp = t0);
|
|
||||||
void addw(Register Rd, Register Rn, int32_t increment, Register temp = t0);
|
|
||||||
|
|
||||||
void sub(Register Rd, Register Rn, int64_t decrement, Register temp = t0);
|
|
||||||
void subw(Register Rd, Register Rn, int32_t decrement, Register temp = t0);
|
|
||||||
|
|
||||||
// RVB pseudo instructions
|
// RVB pseudo instructions
|
||||||
// zero extend word
|
// zero extend word
|
||||||
void zext_w(Register Rd, Register Rs);
|
void zext_w(Register Rd, Register Rs) {
|
||||||
|
add_uw(Rd, Rs, zr);
|
||||||
Assembler(CodeBuffer* code) : AbstractAssembler(code), _in_compressible_region(false) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stack overflow checking
|
// Stack overflow checking
|
||||||
|
@ -3055,6 +2723,8 @@ public:
|
||||||
return uabs(target - branch) < branch_range;
|
return uabs(target - branch) < branch_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assembler(CodeBuffer* code) : AbstractAssembler(code), _in_compressible_region(false) {}
|
||||||
|
|
||||||
virtual ~Assembler() {}
|
virtual ~Assembler() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -543,44 +543,44 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi
|
||||||
assert(dest->is_address(), "should not call otherwise");
|
assert(dest->is_address(), "should not call otherwise");
|
||||||
LIR_Const* c = src->as_constant_ptr();
|
LIR_Const* c = src->as_constant_ptr();
|
||||||
LIR_Address* to_addr = dest->as_address_ptr();
|
LIR_Address* to_addr = dest->as_address_ptr();
|
||||||
void (Assembler::* insn)(Register Rt, const Address &adr, Register temp);
|
void (MacroAssembler::* insn)(Register Rt, const Address &adr, Register temp);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case T_ADDRESS:
|
case T_ADDRESS:
|
||||||
assert(c->as_jint() == 0, "should be");
|
assert(c->as_jint() == 0, "should be");
|
||||||
insn = &Assembler::sd; break;
|
insn = &MacroAssembler::sd; break;
|
||||||
case T_LONG:
|
case T_LONG:
|
||||||
assert(c->as_jlong() == 0, "should be");
|
assert(c->as_jlong() == 0, "should be");
|
||||||
insn = &Assembler::sd; break;
|
insn = &MacroAssembler::sd; break;
|
||||||
case T_DOUBLE:
|
case T_DOUBLE:
|
||||||
assert(c->as_jdouble() == 0.0, "should be");
|
assert(c->as_jdouble() == 0.0, "should be");
|
||||||
insn = &Assembler::sd; break;
|
insn = &MacroAssembler::sd; break;
|
||||||
case T_INT:
|
case T_INT:
|
||||||
assert(c->as_jint() == 0, "should be");
|
assert(c->as_jint() == 0, "should be");
|
||||||
insn = &Assembler::sw; break;
|
insn = &MacroAssembler::sw; break;
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
assert(c->as_jfloat() == 0.0f, "should be");
|
assert(c->as_jfloat() == 0.0f, "should be");
|
||||||
insn = &Assembler::sw; break;
|
insn = &MacroAssembler::sw; break;
|
||||||
case T_OBJECT: // fall through
|
case T_OBJECT: // fall through
|
||||||
case T_ARRAY:
|
case T_ARRAY:
|
||||||
assert(c->as_jobject() == 0, "should be");
|
assert(c->as_jobject() == 0, "should be");
|
||||||
if (UseCompressedOops && !wide) {
|
if (UseCompressedOops && !wide) {
|
||||||
insn = &Assembler::sw;
|
insn = &MacroAssembler::sw;
|
||||||
} else {
|
} else {
|
||||||
insn = &Assembler::sd;
|
insn = &MacroAssembler::sd;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case T_CHAR: // fall through
|
case T_CHAR: // fall through
|
||||||
case T_SHORT:
|
case T_SHORT:
|
||||||
assert(c->as_jint() == 0, "should be");
|
assert(c->as_jint() == 0, "should be");
|
||||||
insn = &Assembler::sh;
|
insn = &MacroAssembler::sh;
|
||||||
break;
|
break;
|
||||||
case T_BOOLEAN: // fall through
|
case T_BOOLEAN: // fall through
|
||||||
case T_BYTE:
|
case T_BYTE:
|
||||||
assert(c->as_jint() == 0, "should be");
|
assert(c->as_jint() == 0, "should be");
|
||||||
insn = &Assembler::sb; break;
|
insn = &MacroAssembler::sb; break;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
insn = &Assembler::sd; // unreachable
|
insn = &MacroAssembler::sd; // unreachable
|
||||||
}
|
}
|
||||||
if (info != NULL) {
|
if (info != NULL) {
|
||||||
add_debug_info_for_null_check_here(info);
|
add_debug_info_for_null_check_here(info);
|
||||||
|
|
|
@ -41,8 +41,7 @@
|
||||||
|
|
||||||
void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result,
|
void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result,
|
||||||
FloatRegister freg0, FloatRegister freg1,
|
FloatRegister freg0, FloatRegister freg1,
|
||||||
Register result)
|
Register result) {
|
||||||
{
|
|
||||||
if (is_float) {
|
if (is_float) {
|
||||||
float_compare(result, freg0, freg1, unordered_result);
|
float_compare(result, freg0, freg1, unordered_result);
|
||||||
} else {
|
} else {
|
||||||
|
@ -375,14 +374,14 @@ typedef void (C1_MacroAssembler::*c1_float_cond_branch_insn)(FloatRegister op1,
|
||||||
static c1_cond_branch_insn c1_cond_branch[] =
|
static c1_cond_branch_insn c1_cond_branch[] =
|
||||||
{
|
{
|
||||||
/* SHORT branches */
|
/* SHORT branches */
|
||||||
(c1_cond_branch_insn)&Assembler::beq,
|
(c1_cond_branch_insn)&MacroAssembler::beq,
|
||||||
(c1_cond_branch_insn)&Assembler::bne,
|
(c1_cond_branch_insn)&MacroAssembler::bne,
|
||||||
(c1_cond_branch_insn)&Assembler::blt,
|
(c1_cond_branch_insn)&MacroAssembler::blt,
|
||||||
(c1_cond_branch_insn)&Assembler::ble,
|
(c1_cond_branch_insn)&MacroAssembler::ble,
|
||||||
(c1_cond_branch_insn)&Assembler::bge,
|
(c1_cond_branch_insn)&MacroAssembler::bge,
|
||||||
(c1_cond_branch_insn)&Assembler::bgt,
|
(c1_cond_branch_insn)&MacroAssembler::bgt,
|
||||||
(c1_cond_branch_insn)&Assembler::bleu, // lir_cond_belowEqual
|
(c1_cond_branch_insn)&MacroAssembler::bleu, // lir_cond_belowEqual
|
||||||
(c1_cond_branch_insn)&Assembler::bgeu // lir_cond_aboveEqual
|
(c1_cond_branch_insn)&MacroAssembler::bgeu // lir_cond_aboveEqual
|
||||||
};
|
};
|
||||||
|
|
||||||
static c1_float_cond_branch_insn c1_float_cond_branch[] =
|
static c1_float_cond_branch_insn c1_float_cond_branch[] =
|
||||||
|
|
|
@ -1207,8 +1207,8 @@ void C2_MacroAssembler::string_equals(Register a1, Register a2,
|
||||||
andi(t0, cnt1, 1);
|
andi(t0, cnt1, 1);
|
||||||
beqz(t0, SAME);
|
beqz(t0, SAME);
|
||||||
{
|
{
|
||||||
lbu(tmp1, a1, 0);
|
lbu(tmp1, Address(a1, 0));
|
||||||
lbu(tmp2, a2, 0);
|
lbu(tmp2, Address(a2, 0));
|
||||||
bne(tmp1, tmp2, DONE);
|
bne(tmp1, tmp2, DONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1229,24 +1229,24 @@ typedef void (MacroAssembler::*float_conditional_branch_insn)(FloatRegister op1,
|
||||||
static conditional_branch_insn conditional_branches[] =
|
static conditional_branch_insn conditional_branches[] =
|
||||||
{
|
{
|
||||||
/* SHORT branches */
|
/* SHORT branches */
|
||||||
(conditional_branch_insn)&Assembler::beq,
|
(conditional_branch_insn)&MacroAssembler::beq,
|
||||||
(conditional_branch_insn)&Assembler::bgt,
|
(conditional_branch_insn)&MacroAssembler::bgt,
|
||||||
NULL, // BoolTest::overflow
|
NULL, // BoolTest::overflow
|
||||||
(conditional_branch_insn)&Assembler::blt,
|
(conditional_branch_insn)&MacroAssembler::blt,
|
||||||
(conditional_branch_insn)&Assembler::bne,
|
(conditional_branch_insn)&MacroAssembler::bne,
|
||||||
(conditional_branch_insn)&Assembler::ble,
|
(conditional_branch_insn)&MacroAssembler::ble,
|
||||||
NULL, // BoolTest::no_overflow
|
NULL, // BoolTest::no_overflow
|
||||||
(conditional_branch_insn)&Assembler::bge,
|
(conditional_branch_insn)&MacroAssembler::bge,
|
||||||
|
|
||||||
/* UNSIGNED branches */
|
/* UNSIGNED branches */
|
||||||
(conditional_branch_insn)&Assembler::beq,
|
(conditional_branch_insn)&MacroAssembler::beq,
|
||||||
(conditional_branch_insn)&Assembler::bgtu,
|
(conditional_branch_insn)&MacroAssembler::bgtu,
|
||||||
NULL,
|
NULL,
|
||||||
(conditional_branch_insn)&Assembler::bltu,
|
(conditional_branch_insn)&MacroAssembler::bltu,
|
||||||
(conditional_branch_insn)&Assembler::bne,
|
(conditional_branch_insn)&MacroAssembler::bne,
|
||||||
(conditional_branch_insn)&Assembler::bleu,
|
(conditional_branch_insn)&MacroAssembler::bleu,
|
||||||
NULL,
|
NULL,
|
||||||
(conditional_branch_insn)&Assembler::bgeu
|
(conditional_branch_insn)&MacroAssembler::bgeu
|
||||||
};
|
};
|
||||||
|
|
||||||
static float_conditional_branch_insn float_conditional_branches[] =
|
static float_conditional_branch_insn float_conditional_branches[] =
|
||||||
|
|
|
@ -368,12 +368,12 @@ void InterpreterMacroAssembler::push_l(Register r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterpreterMacroAssembler::pop_f(FloatRegister r) {
|
void InterpreterMacroAssembler::pop_f(FloatRegister r) {
|
||||||
flw(r, esp, 0);
|
flw(r, Address(esp, 0));
|
||||||
addi(esp, esp, wordSize);
|
addi(esp, esp, wordSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterpreterMacroAssembler::pop_d(FloatRegister r) {
|
void InterpreterMacroAssembler::pop_d(FloatRegister r) {
|
||||||
fld(r, esp, 0);
|
fld(r, Address(esp, 0));
|
||||||
addi(esp, esp, 2 * Interpreter::stackElementSize);
|
addi(esp, esp, 2 * Interpreter::stackElementSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -719,7 +719,34 @@ void MacroAssembler::vfneg_v(VectorRegister vd, VectorRegister vs) {
|
||||||
vfsgnjn_vv(vd, vs, 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();
|
int64_t offset = dest - pc();
|
||||||
if (is_offset_in_range(offset, 32)) {
|
if (is_offset_in_range(offset, 32)) {
|
||||||
auipc(Rd, (int32_t)offset + 0x800); //0x800, Note:the 11th sign bit
|
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));
|
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) \
|
#define INSN(NAME) \
|
||||||
void MacroAssembler::NAME##z(Register Rs, const address &dest) { \
|
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) { \
|
||||||
NAME(Rs, zr, dest); \
|
NAME(Rs, zr, dest); \
|
||||||
} \
|
} \
|
||||||
void MacroAssembler::NAME##z(Register Rs, Label &l, bool is_far) { \
|
void MacroAssembler::NAME##z(Register Rs, Label &l, bool is_far) { \
|
||||||
|
@ -774,6 +1003,21 @@ void MacroAssembler::la(Register Rd, Label &label) {
|
||||||
|
|
||||||
#undef INSN
|
#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
|
// Float compare branch instructions
|
||||||
|
|
||||||
#define INSN(NAME, FLOATCMP, BRANCH) \
|
#define INSN(NAME, FLOATCMP, BRANCH) \
|
||||||
|
@ -928,7 +1172,7 @@ void MacroAssembler::push_reg(Register Rs)
|
||||||
|
|
||||||
void MacroAssembler::pop_reg(Register Rd)
|
void MacroAssembler::pop_reg(Register Rd)
|
||||||
{
|
{
|
||||||
ld(Rd, esp, 0);
|
ld(Rd, Address(esp, 0));
|
||||||
addi(esp, esp, wordSize);
|
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) {
|
void MacroAssembler::andrw(Register Rd, Register Rs1, Register Rs2) {
|
||||||
andr(Rd, Rs1, Rs2);
|
andr(Rd, Rs1, Rs2);
|
||||||
// addw: The result is clipped to 32 bits, then the sign bit is extended,
|
// 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);
|
bind(loop);
|
||||||
sub(len, len, unroll);
|
sub(len, len, unroll);
|
||||||
for (int i = -unroll; i < 0; i++) {
|
for (int i = -unroll; i < 0; i++) {
|
||||||
Assembler::sd(zr, Address(tmp, i * wordSize));
|
sd(zr, Address(tmp, i * wordSize));
|
||||||
}
|
}
|
||||||
bind(entry);
|
bind(entry);
|
||||||
add(tmp, tmp, unroll * wordSize);
|
add(tmp, tmp, unroll * wordSize);
|
||||||
|
|
|
@ -42,14 +42,15 @@
|
||||||
class MacroAssembler: public Assembler {
|
class MacroAssembler: public Assembler {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MacroAssembler(CodeBuffer* code) : Assembler(code) {
|
MacroAssembler(CodeBuffer* code) : Assembler(code) {}
|
||||||
}
|
|
||||||
virtual ~MacroAssembler() {}
|
virtual ~MacroAssembler() {}
|
||||||
|
|
||||||
void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod);
|
void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod);
|
||||||
|
|
||||||
// Alignment
|
// Alignment
|
||||||
int align(int modulus, int extra_offset = 0);
|
int align(int modulus, int extra_offset = 0);
|
||||||
|
|
||||||
static inline void assert_alignment(address pc, int alignment = NativeInstruction::instruction_size) {
|
static inline void assert_alignment(address pc, int alignment = NativeInstruction::instruction_size) {
|
||||||
assert(is_aligned(pc, alignment), "bad alignment");
|
assert(is_aligned(pc, alignment), "bad alignment");
|
||||||
}
|
}
|
||||||
|
@ -401,7 +402,7 @@ class MacroAssembler: public Assembler {
|
||||||
void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg);
|
void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Standard pseudoinstruction
|
// Standard pseudo instructions
|
||||||
void nop();
|
void nop();
|
||||||
void mv(Register Rd, Register Rs);
|
void mv(Register Rd, Register Rs);
|
||||||
void notr(Register Rd, Register Rs);
|
void notr(Register Rd, Register Rs);
|
||||||
|
@ -414,17 +415,15 @@ class MacroAssembler: public Assembler {
|
||||||
void sltz(Register Rd, Register Rs); // set if < zero
|
void sltz(Register Rd, Register Rs); // set if < zero
|
||||||
void sgtz(Register Rd, Register Rs); // set if > zero
|
void sgtz(Register Rd, Register Rs); // set if > zero
|
||||||
|
|
||||||
// Float pseudoinstruction
|
// Floating-point data-processing pseudo instructions
|
||||||
void fmv_s(FloatRegister Rd, FloatRegister Rs);
|
void fmv_s(FloatRegister Rd, FloatRegister Rs);
|
||||||
void fabs_s(FloatRegister Rd, FloatRegister Rs); // single-precision absolute value
|
void fabs_s(FloatRegister Rd, FloatRegister Rs);
|
||||||
void fneg_s(FloatRegister Rd, FloatRegister Rs);
|
void fneg_s(FloatRegister Rd, FloatRegister Rs);
|
||||||
|
|
||||||
// Double pseudoinstruction
|
|
||||||
void fmv_d(FloatRegister Rd, FloatRegister Rs);
|
void fmv_d(FloatRegister Rd, FloatRegister Rs);
|
||||||
void fabs_d(FloatRegister Rd, FloatRegister Rs);
|
void fabs_d(FloatRegister Rd, FloatRegister Rs);
|
||||||
void fneg_d(FloatRegister Rd, FloatRegister Rs);
|
void fneg_d(FloatRegister Rd, FloatRegister Rs);
|
||||||
|
|
||||||
// Pseudoinstruction for control and status register
|
// Control and status pseudo instructions
|
||||||
void rdinstret(Register Rd); // read instruction-retired counter
|
void rdinstret(Register Rd); // read instruction-retired counter
|
||||||
void rdcycle(Register Rd); // read cycle counter
|
void rdcycle(Register Rd); // read cycle counter
|
||||||
void rdtime(Register Rd); // read time
|
void rdtime(Register Rd); // read time
|
||||||
|
@ -449,15 +448,23 @@ class MacroAssembler: public Assembler {
|
||||||
void fsflagsi(Register Rd, unsigned imm);
|
void fsflagsi(Register Rd, unsigned imm);
|
||||||
void fsflagsi(unsigned imm);
|
void fsflagsi(unsigned imm);
|
||||||
|
|
||||||
void beqz(Register Rs, const address &dest);
|
// Control transfer pseudo instructions
|
||||||
void bnez(Register Rs, const address &dest);
|
void beqz(Register Rs, const address dest);
|
||||||
void blez(Register Rs, const address &dest);
|
void bnez(Register Rs, const address dest);
|
||||||
void bgez(Register Rs, const address &dest);
|
void blez(Register Rs, const address dest);
|
||||||
void bltz(Register Rs, const address &dest);
|
void bgez(Register Rs, const address dest);
|
||||||
void bgtz(Register Rs, const address &dest);
|
void bltz(Register Rs, const address dest);
|
||||||
void la(Register Rd, Label &label);
|
void bgtz(Register Rs, const address dest);
|
||||||
void la(Register Rd, const address &dest);
|
|
||||||
void la(Register Rd, const Address &adr);
|
void j(Label &l, Register temp = t0);
|
||||||
|
void j(const address dest, Register temp = t0);
|
||||||
|
void j(const Address &adr, Register temp = t0);
|
||||||
|
void jal(Label &l, Register temp = t0);
|
||||||
|
void jal(const address dest, Register temp = t0);
|
||||||
|
void jal(const Address &adr, Register temp = t0);
|
||||||
|
void jal(Register Rd, Label &L, Register temp = t0);
|
||||||
|
void jal(Register Rd, const address dest, Register temp = t0);
|
||||||
|
|
||||||
//label
|
//label
|
||||||
void beqz(Register Rs, Label &l, bool is_far = false);
|
void beqz(Register Rs, Label &l, bool is_far = false);
|
||||||
void bnez(Register Rs, Label &l, bool is_far = false);
|
void bnez(Register Rs, Label &l, bool is_far = false);
|
||||||
|
@ -465,12 +472,59 @@ class MacroAssembler: public Assembler {
|
||||||
void bgez(Register Rs, Label &l, bool is_far = false);
|
void bgez(Register Rs, Label &l, bool is_far = false);
|
||||||
void bltz(Register Rs, Label &l, bool is_far = false);
|
void bltz(Register Rs, Label &l, bool is_far = false);
|
||||||
void bgtz(Register Rs, Label &l, bool is_far = false);
|
void bgtz(Register Rs, Label &l, bool is_far = false);
|
||||||
|
|
||||||
|
void beq (Register Rs1, Register Rs2, Label &L, bool is_far = false);
|
||||||
|
void bne (Register Rs1, Register Rs2, Label &L, bool is_far = false);
|
||||||
|
void blt (Register Rs1, Register Rs2, Label &L, bool is_far = false);
|
||||||
|
void bge (Register Rs1, Register Rs2, Label &L, bool is_far = false);
|
||||||
|
void bltu(Register Rs1, Register Rs2, Label &L, bool is_far = false);
|
||||||
|
void bgeu(Register Rs1, Register Rs2, Label &L, bool is_far = false);
|
||||||
|
|
||||||
|
void bgt (Register Rs, Register Rt, const address dest);
|
||||||
|
void ble (Register Rs, Register Rt, const address dest);
|
||||||
|
void bgtu(Register Rs, Register Rt, const address dest);
|
||||||
|
void bleu(Register Rs, Register Rt, const address dest);
|
||||||
|
|
||||||
|
void bgt (Register Rs, Register Rt, Label &l, bool is_far = false);
|
||||||
|
void ble (Register Rs, Register Rt, Label &l, bool is_far = false);
|
||||||
|
void bgtu(Register Rs, Register Rt, Label &l, bool is_far = false);
|
||||||
|
void bleu(Register Rs, Register Rt, Label &l, bool is_far = false);
|
||||||
|
|
||||||
|
#define INSN_ENTRY_RELOC(result_type, header) \
|
||||||
|
result_type header { \
|
||||||
|
guarantee(rtype == relocInfo::internal_word_type, \
|
||||||
|
"only internal_word_type relocs make sense here"); \
|
||||||
|
relocate(InternalAddress(dest).rspec());
|
||||||
|
|
||||||
|
#define INSN(NAME) \
|
||||||
|
void NAME(Register Rs1, Register Rs2, const address dest) { \
|
||||||
|
assert_cond(dest != NULL); \
|
||||||
|
int64_t offset = dest - pc(); \
|
||||||
|
guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid."); \
|
||||||
|
Assembler::NAME(Rs1, Rs2, offset); \
|
||||||
|
} \
|
||||||
|
INSN_ENTRY_RELOC(void, NAME(Register Rs1, Register Rs2, address dest, relocInfo::relocType rtype)) \
|
||||||
|
NAME(Rs1, Rs2, dest); \
|
||||||
|
}
|
||||||
|
|
||||||
|
INSN(beq);
|
||||||
|
INSN(bne);
|
||||||
|
INSN(bge);
|
||||||
|
INSN(bgeu);
|
||||||
|
INSN(blt);
|
||||||
|
INSN(bltu);
|
||||||
|
|
||||||
|
#undef INSN
|
||||||
|
|
||||||
|
#undef INSN_ENTRY_RELOC
|
||||||
|
|
||||||
void float_beq(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
void float_beq(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||||
void float_bne(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
void float_bne(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||||
void float_ble(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
void float_ble(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||||
void float_bge(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
void float_bge(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||||
void float_blt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
void float_blt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||||
void float_bgt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
void float_bgt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||||
|
|
||||||
void double_beq(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
void double_beq(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||||
void double_bne(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
void double_bne(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||||
void double_ble(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
void double_ble(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false);
|
||||||
|
@ -526,6 +580,28 @@ public:
|
||||||
code()->clear_last_insn();
|
code()->clear_last_insn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef void (MacroAssembler::* compare_and_branch_insn)(Register Rs1, Register Rs2, const address dest);
|
||||||
|
typedef void (MacroAssembler::* compare_and_branch_label_insn)(Register Rs1, Register Rs2, Label &L, bool is_far);
|
||||||
|
typedef void (MacroAssembler::* jal_jalr_insn)(Register Rt, address dest);
|
||||||
|
typedef void (MacroAssembler::* load_insn_by_temp)(Register Rt, address dest, Register temp);
|
||||||
|
|
||||||
|
void wrap_label(Register r, Label &L, Register t, load_insn_by_temp insn);
|
||||||
|
void wrap_label(Register r, Label &L, jal_jalr_insn insn);
|
||||||
|
void wrap_label(Register r1, Register r2, Label &L,
|
||||||
|
compare_and_branch_insn insn,
|
||||||
|
compare_and_branch_label_insn neg_insn, bool is_far = false);
|
||||||
|
|
||||||
|
void baseOffset(Register Rd, const Address &adr, int32_t &offset);
|
||||||
|
void baseOffset32(Register Rd, const Address &adr, int32_t &offset);
|
||||||
|
|
||||||
|
void la(Register Rd, Label &label);
|
||||||
|
void la(Register Rd, const address dest);
|
||||||
|
void la(Register Rd, const Address &adr);
|
||||||
|
|
||||||
|
void li32(Register Rd, int32_t imm);
|
||||||
|
void li64(Register Rd, int64_t imm);
|
||||||
|
void li(Register Rd, int64_t imm); // optimized load immediate
|
||||||
|
|
||||||
// mv
|
// mv
|
||||||
void mv(Register Rd, address addr) { li(Rd, (int64_t)addr); }
|
void mv(Register Rd, address addr) { li(Rd, (int64_t)addr); }
|
||||||
void mv(Register Rd, address addr, int32_t &offset) {
|
void mv(Register Rd, address addr, int32_t &offset) {
|
||||||
|
@ -543,6 +619,28 @@ public:
|
||||||
void mv(Register Rd, Address dest);
|
void mv(Register Rd, Address dest);
|
||||||
void mv(Register Rd, RegisterOrConstant src);
|
void mv(Register Rd, RegisterOrConstant src);
|
||||||
|
|
||||||
|
void movptr(Register Rd, address addr);
|
||||||
|
void movptr(Register Rd, address addr, int32_t &offset);
|
||||||
|
void movptr(Register Rd, uintptr_t imm64);
|
||||||
|
|
||||||
|
// arith
|
||||||
|
void add (Register Rd, Register Rn, int64_t increment, Register temp = t0);
|
||||||
|
void addw(Register Rd, Register Rn, int32_t increment, Register temp = t0);
|
||||||
|
void sub (Register Rd, Register Rn, int64_t decrement, Register temp = t0);
|
||||||
|
void subw(Register Rd, Register Rn, int32_t decrement, Register temp = t0);
|
||||||
|
|
||||||
|
#define INSN(NAME) \
|
||||||
|
inline void NAME(Register Rd, Register Rs1, Register Rs2) { \
|
||||||
|
Assembler::NAME(Rd, Rs1, Rs2); \
|
||||||
|
}
|
||||||
|
|
||||||
|
INSN(add);
|
||||||
|
INSN(addw);
|
||||||
|
INSN(sub);
|
||||||
|
INSN(subw);
|
||||||
|
|
||||||
|
#undef INSN
|
||||||
|
|
||||||
// logic
|
// logic
|
||||||
void andrw(Register Rd, Register Rs1, Register Rs2);
|
void andrw(Register Rd, Register Rs1, Register Rs2);
|
||||||
void orrw(Register Rd, Register Rs1, Register Rs2);
|
void orrw(Register Rd, Register Rs1, Register Rs2);
|
||||||
|
@ -562,6 +660,215 @@ public:
|
||||||
void andi(Register Rd, Register Rn, int64_t imm, Register tmp = t0);
|
void andi(Register Rd, Register Rn, int64_t imm, Register tmp = t0);
|
||||||
void orptr(Address adr, RegisterOrConstant src, Register tmp1 = t0, Register tmp2 = t1);
|
void orptr(Address adr, RegisterOrConstant src, Register tmp1 = t0, Register tmp2 = t1);
|
||||||
|
|
||||||
|
// Load and Store Instructions
|
||||||
|
#define INSN_ENTRY_RELOC(result_type, header) \
|
||||||
|
result_type header { \
|
||||||
|
guarantee(rtype == relocInfo::internal_word_type, \
|
||||||
|
"only internal_word_type relocs make sense here"); \
|
||||||
|
relocate(InternalAddress(dest).rspec());
|
||||||
|
|
||||||
|
#define INSN(NAME) \
|
||||||
|
void NAME(Register Rd, address dest) { \
|
||||||
|
assert_cond(dest != NULL); \
|
||||||
|
int64_t distance = dest - pc(); \
|
||||||
|
if (is_offset_in_range(distance, 32)) { \
|
||||||
|
auipc(Rd, (int32_t)distance + 0x800); \
|
||||||
|
Assembler::NAME(Rd, Rd, ((int32_t)distance << 20) >> 20); \
|
||||||
|
} else { \
|
||||||
|
int32_t offset = 0; \
|
||||||
|
movptr(Rd, dest, offset); \
|
||||||
|
Assembler::NAME(Rd, Rd, offset); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
INSN_ENTRY_RELOC(void, NAME(Register Rd, address dest, relocInfo::relocType rtype)) \
|
||||||
|
NAME(Rd, dest); \
|
||||||
|
} \
|
||||||
|
void NAME(Register Rd, const Address &adr, Register temp = t0) { \
|
||||||
|
switch (adr.getMode()) { \
|
||||||
|
case Address::literal: { \
|
||||||
|
relocate(adr.rspec()); \
|
||||||
|
NAME(Rd, adr.target()); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
case Address::base_plus_offset: { \
|
||||||
|
if (is_offset_in_range(adr.offset(), 12)) { \
|
||||||
|
Assembler::NAME(Rd, adr.base(), adr.offset()); \
|
||||||
|
} else { \
|
||||||
|
int32_t offset = 0; \
|
||||||
|
if (Rd == adr.base()) { \
|
||||||
|
baseOffset32(temp, adr, offset); \
|
||||||
|
Assembler::NAME(Rd, temp, offset); \
|
||||||
|
} else { \
|
||||||
|
baseOffset32(Rd, adr, offset); \
|
||||||
|
Assembler::NAME(Rd, Rd, offset); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
default: \
|
||||||
|
ShouldNotReachHere(); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
void NAME(Register Rd, Label &L) { \
|
||||||
|
wrap_label(Rd, L, &MacroAssembler::NAME); \
|
||||||
|
}
|
||||||
|
|
||||||
|
INSN(lb);
|
||||||
|
INSN(lbu);
|
||||||
|
INSN(lh);
|
||||||
|
INSN(lhu);
|
||||||
|
INSN(lw);
|
||||||
|
INSN(lwu);
|
||||||
|
INSN(ld);
|
||||||
|
|
||||||
|
#undef INSN
|
||||||
|
|
||||||
|
#define INSN(NAME) \
|
||||||
|
void NAME(FloatRegister Rd, address dest, Register temp = t0) { \
|
||||||
|
assert_cond(dest != NULL); \
|
||||||
|
int64_t distance = dest - pc(); \
|
||||||
|
if (is_offset_in_range(distance, 32)) { \
|
||||||
|
auipc(temp, (int32_t)distance + 0x800); \
|
||||||
|
Assembler::NAME(Rd, temp, ((int32_t)distance << 20) >> 20); \
|
||||||
|
} else { \
|
||||||
|
int32_t offset = 0; \
|
||||||
|
movptr(temp, dest, offset); \
|
||||||
|
Assembler::NAME(Rd, temp, offset); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
INSN_ENTRY_RELOC(void, NAME(FloatRegister Rd, address dest, \
|
||||||
|
relocInfo::relocType rtype, Register temp = t0)) \
|
||||||
|
NAME(Rd, dest, temp); \
|
||||||
|
} \
|
||||||
|
void NAME(FloatRegister Rd, const Address &adr, Register temp = t0) { \
|
||||||
|
switch (adr.getMode()) { \
|
||||||
|
case Address::literal: { \
|
||||||
|
relocate(adr.rspec()); \
|
||||||
|
NAME(Rd, adr.target(), temp); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
case Address::base_plus_offset: { \
|
||||||
|
if (is_offset_in_range(adr.offset(), 12)) { \
|
||||||
|
Assembler::NAME(Rd, adr.base(), adr.offset()); \
|
||||||
|
} else { \
|
||||||
|
int32_t offset = 0; \
|
||||||
|
baseOffset32(temp, adr, offset); \
|
||||||
|
Assembler::NAME(Rd, temp, offset); \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
default: \
|
||||||
|
ShouldNotReachHere(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
INSN(flw);
|
||||||
|
INSN(fld);
|
||||||
|
|
||||||
|
#undef INSN
|
||||||
|
|
||||||
|
#define INSN(NAME, REGISTER) \
|
||||||
|
INSN_ENTRY_RELOC(void, NAME(REGISTER Rs, address dest, \
|
||||||
|
relocInfo::relocType rtype, Register temp = t0)) \
|
||||||
|
NAME(Rs, dest, temp); \
|
||||||
|
}
|
||||||
|
|
||||||
|
INSN(sb, Register);
|
||||||
|
INSN(sh, Register);
|
||||||
|
INSN(sw, Register);
|
||||||
|
INSN(sd, Register);
|
||||||
|
INSN(fsw, FloatRegister);
|
||||||
|
INSN(fsd, FloatRegister);
|
||||||
|
|
||||||
|
#undef INSN
|
||||||
|
|
||||||
|
#define INSN(NAME) \
|
||||||
|
void NAME(Register Rs, address dest, Register temp = t0) { \
|
||||||
|
assert_cond(dest != NULL); \
|
||||||
|
assert_different_registers(Rs, temp); \
|
||||||
|
int64_t distance = dest - pc(); \
|
||||||
|
if (is_offset_in_range(distance, 32)) { \
|
||||||
|
auipc(temp, (int32_t)distance + 0x800); \
|
||||||
|
Assembler::NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \
|
||||||
|
} else { \
|
||||||
|
int32_t offset = 0; \
|
||||||
|
movptr(temp, dest, offset); \
|
||||||
|
Assembler::NAME(Rs, temp, offset); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
void NAME(Register Rs, const Address &adr, Register temp = t0) { \
|
||||||
|
switch (adr.getMode()) { \
|
||||||
|
case Address::literal: { \
|
||||||
|
assert_different_registers(Rs, temp); \
|
||||||
|
relocate(adr.rspec()); \
|
||||||
|
NAME(Rs, adr.target(), temp); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
case Address::base_plus_offset: { \
|
||||||
|
if (is_offset_in_range(adr.offset(), 12)) { \
|
||||||
|
Assembler::NAME(Rs, adr.base(), adr.offset()); \
|
||||||
|
} else { \
|
||||||
|
int32_t offset= 0; \
|
||||||
|
assert_different_registers(Rs, temp); \
|
||||||
|
baseOffset32(temp, adr, offset); \
|
||||||
|
Assembler::NAME(Rs, temp, offset); \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
default: \
|
||||||
|
ShouldNotReachHere(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
INSN(sb);
|
||||||
|
INSN(sh);
|
||||||
|
INSN(sw);
|
||||||
|
INSN(sd);
|
||||||
|
|
||||||
|
#undef INSN
|
||||||
|
|
||||||
|
#define INSN(NAME) \
|
||||||
|
void NAME(FloatRegister Rs, address dest, Register temp = t0) { \
|
||||||
|
assert_cond(dest != NULL); \
|
||||||
|
int64_t distance = dest - pc(); \
|
||||||
|
if (is_offset_in_range(distance, 32)) { \
|
||||||
|
auipc(temp, (int32_t)distance + 0x800); \
|
||||||
|
Assembler::NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \
|
||||||
|
} else { \
|
||||||
|
int32_t offset = 0; \
|
||||||
|
movptr(temp, dest, offset); \
|
||||||
|
Assembler::NAME(Rs, temp, offset); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
void NAME(FloatRegister Rs, const Address &adr, Register temp = t0) { \
|
||||||
|
switch (adr.getMode()) { \
|
||||||
|
case Address::literal: { \
|
||||||
|
relocate(adr.rspec()); \
|
||||||
|
NAME(Rs, adr.target(), temp); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
case Address::base_plus_offset: { \
|
||||||
|
if (is_offset_in_range(adr.offset(), 12)) { \
|
||||||
|
Assembler::NAME(Rs, adr.base(), adr.offset()); \
|
||||||
|
} else { \
|
||||||
|
int32_t offset = 0; \
|
||||||
|
baseOffset32(temp, adr, offset); \
|
||||||
|
Assembler::NAME(Rs, temp, offset); \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
default: \
|
||||||
|
ShouldNotReachHere(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
INSN(fsw);
|
||||||
|
INSN(fsd);
|
||||||
|
|
||||||
|
#undef INSN
|
||||||
|
|
||||||
|
#undef INSN_ENTRY_RELOC
|
||||||
|
|
||||||
void cmpxchg_obj_header(Register oldv, Register newv, Register obj, Register tmp, Label &succeed, Label *fail);
|
void cmpxchg_obj_header(Register oldv, Register newv, Register obj, Register tmp, Label &succeed, Label *fail);
|
||||||
void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp, Label &succeed, Label *fail);
|
void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp, Label &succeed, Label *fail);
|
||||||
void cmpxchg(Register addr, Register expected,
|
void cmpxchg(Register addr, Register expected,
|
||||||
|
|
|
@ -2173,8 +2173,8 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
size_of_deoptimized_frame_offset_in_bytes()));
|
size_of_deoptimized_frame_offset_in_bytes()));
|
||||||
__ sub(x12, x12, 2 * wordSize);
|
__ sub(x12, x12, 2 * wordSize);
|
||||||
__ add(sp, sp, x12);
|
__ add(sp, sp, x12);
|
||||||
__ ld(fp, sp, 0);
|
__ ld(fp, Address(sp, 0));
|
||||||
__ ld(ra, sp, wordSize);
|
__ ld(ra, Address(sp, wordSize));
|
||||||
__ addi(sp, sp, 2 * wordSize);
|
__ addi(sp, sp, 2 * wordSize);
|
||||||
// RA should now be the return address to the caller (3) frame
|
// RA should now be the return address to the caller (3) frame
|
||||||
|
|
||||||
|
|
|
@ -329,7 +329,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
__ beqz(c_rarg6, parameters_done);
|
__ beqz(c_rarg6, parameters_done);
|
||||||
|
|
||||||
address loop = __ pc();
|
address loop = __ pc();
|
||||||
__ ld(t0, c_rarg5, 0);
|
__ ld(t0, Address(c_rarg5, 0));
|
||||||
__ addi(c_rarg5, c_rarg5, wordSize);
|
__ addi(c_rarg5, c_rarg5, wordSize);
|
||||||
__ addi(c_rarg6, c_rarg6, -1);
|
__ addi(c_rarg6, c_rarg6, -1);
|
||||||
__ push_reg(t0);
|
__ push_reg(t0);
|
||||||
|
|
|
@ -1075,7 +1075,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
__ ld(x28, Address(xmethod, Method::native_function_offset()));
|
__ ld(x28, Address(xmethod, Method::native_function_offset()));
|
||||||
address unsatisfied = (SharedRuntime::native_method_throw_unsatisfied_link_error_entry());
|
address unsatisfied = (SharedRuntime::native_method_throw_unsatisfied_link_error_entry());
|
||||||
__ mv(t1, unsatisfied);
|
__ mv(t1, unsatisfied);
|
||||||
__ ld(t1, t1);
|
__ ld(t1, Address(t1, 0));
|
||||||
__ bne(x28, t1, L);
|
__ bne(x28, t1, L);
|
||||||
__ call_VM(noreg,
|
__ call_VM(noreg,
|
||||||
CAST_FROM_FN_PTR(address,
|
CAST_FROM_FN_PTR(address,
|
||||||
|
|
|
@ -244,10 +244,10 @@ void TemplateTable::fconst(int value) {
|
||||||
__ fmv_w_x(f10, zr);
|
__ fmv_w_x(f10, zr);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
__ flw(f10, t0, 0);
|
__ flw(f10, Address(t0, 0));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
__ flw(f10, t0, sizeof(float));
|
__ flw(f10, Address(t0, sizeof(float)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
|
@ -263,10 +263,10 @@ void TemplateTable::dconst(int value) {
|
||||||
__ fmv_d_x(f10, zr);
|
__ fmv_d_x(f10, zr);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
__ fld(f10, t0, 0);
|
__ fld(f10, Address(t0, 0));
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
__ fld(f10, t0, sizeof(double));
|
__ fld(f10, Address(t0, sizeof(double)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue