8353188: C1: Clean up x86 backend after 32-bit x86 removal

Reviewed-by: kvn, vlivanov
This commit is contained in:
Aleksey Shipilev 2025-04-07 07:39:17 +00:00
parent d1e91fcd62
commit d63b561fff
11 changed files with 45 additions and 1079 deletions

View File

@ -37,66 +37,12 @@
#define __ ce->masm()->
#ifndef _LP64
float ConversionStub::float_zero = 0.0;
double ConversionStub::double_zero = 0.0;
void ConversionStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
assert(bytecode() == Bytecodes::_f2i || bytecode() == Bytecodes::_d2i, "other conversions do not require stub");
if (input()->is_single_xmm()) {
__ comiss(input()->as_xmm_float_reg(),
ExternalAddress((address)&float_zero));
} else if (input()->is_double_xmm()) {
__ comisd(input()->as_xmm_double_reg(),
ExternalAddress((address)&double_zero));
} else {
__ push(rax);
__ ftst();
__ fnstsw_ax();
__ sahf();
__ pop(rax);
}
Label NaN, do_return;
__ jccb(Assembler::parity, NaN);
__ jccb(Assembler::below, do_return);
// input is > 0 -> return maxInt
// result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff
__ decrement(result()->as_register());
__ jmpb(do_return);
// input is NaN -> return 0
__ bind(NaN);
__ xorptr(result()->as_register(), result()->as_register());
__ bind(do_return);
__ jmp(_continuation);
}
#endif // !_LP64
void C1SafepointPollStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
InternalAddress safepoint_pc(ce->masm()->pc() - ce->masm()->offset() + safepoint_offset());
#ifdef _LP64
__ lea(rscratch1, safepoint_pc);
__ movptr(Address(r15_thread, JavaThread::saved_exception_pc_offset()), rscratch1);
#else
const Register tmp1 = rcx;
const Register tmp2 = rdx;
__ push(tmp1);
__ push(tmp2);
__ lea(tmp1, safepoint_pc);
__ get_thread(tmp2);
__ movptr(Address(tmp2, JavaThread::saved_exception_pc_offset()), tmp1);
__ pop(tmp2);
__ pop(tmp1);
#endif /* _LP64 */
assert(SharedRuntime::polling_page_return_handler_blob() != nullptr,
"polling page return stub not created yet");

View File

@ -33,15 +33,11 @@ enum {
// registers
enum {
pd_nof_cpu_regs_frame_map = NOT_LP64(8) LP64_ONLY(16), // number of registers used during code emission
pd_nof_cpu_regs_frame_map = 16, // number of registers used during code emission
pd_nof_fpu_regs_frame_map = FloatRegister::number_of_registers, // number of registers used during code emission
pd_nof_xmm_regs_frame_map = XMMRegister::number_of_registers, // number of registers used during code emission
#ifdef _LP64
#define UNALLOCATED 4 // rsp, rbp, r15, r10
#else
#define UNALLOCATED 2 // rsp, rbp
#endif // LP64
pd_nof_caller_save_cpu_regs_frame_map = pd_nof_cpu_regs_frame_map - UNALLOCATED, // number of registers killed by calls
pd_nof_caller_save_fpu_regs_frame_map = pd_nof_fpu_regs_frame_map, // number of registers killed by calls
@ -54,9 +50,9 @@ enum {
pd_nof_fpu_regs_linearscan = pd_nof_fpu_regs_frame_map, // number of registers visible to linear scan
pd_nof_xmm_regs_linearscan = pd_nof_xmm_regs_frame_map, // number of registers visible to linear scan
pd_first_cpu_reg = 0,
pd_last_cpu_reg = NOT_LP64(5) LP64_ONLY(11),
pd_first_byte_reg = NOT_LP64(2) LP64_ONLY(0),
pd_last_byte_reg = NOT_LP64(5) LP64_ONLY(11),
pd_last_cpu_reg = 11,
pd_first_byte_reg = 0,
pd_last_byte_reg = 11,
pd_first_fpu_reg = pd_nof_cpu_regs_frame_map,
pd_last_fpu_reg = pd_first_fpu_reg + 7,
pd_first_xmm_reg = pd_nof_cpu_regs_frame_map + pd_nof_fpu_regs_frame_map,

View File

@ -32,7 +32,6 @@ const int FrameMap::pd_c_runtime_reserved_arg_size = 0;
LIR_Opr FrameMap::map_to_opr(BasicType type, VMRegPair* reg, bool) {
LIR_Opr opr = LIR_OprFact::illegalOpr;
VMReg r_1 = reg->first();
VMReg r_2 = reg->second();
if (r_1->is_stack()) {
// Convert stack slot to an SP offset
// The calling convention does not count the SharedRuntime::out_preserve_stack_slots() value
@ -41,14 +40,8 @@ LIR_Opr FrameMap::map_to_opr(BasicType type, VMRegPair* reg, bool) {
opr = LIR_OprFact::address(new LIR_Address(rsp_opr, st_off, type));
} else if (r_1->is_Register()) {
Register reg = r_1->as_Register();
if (r_2->is_Register() && (type == T_LONG || type == T_DOUBLE)) {
Register reg2 = r_2->as_Register();
#ifdef _LP64
assert(reg2 == reg, "must be same register");
if (type == T_LONG || type == T_DOUBLE) {
opr = as_long_opr(reg);
#else
opr = as_long_opr(reg2, reg);
#endif // _LP64
} else if (is_reference_type(type)) {
opr = as_oop_opr(reg);
} else if (type == T_METADATA) {
@ -111,8 +104,6 @@ LIR_Opr FrameMap::long1_opr;
LIR_Opr FrameMap::xmm0_float_opr;
LIR_Opr FrameMap::xmm0_double_opr;
#ifdef _LP64
LIR_Opr FrameMap::r8_opr;
LIR_Opr FrameMap::r9_opr;
LIR_Opr FrameMap::r10_opr;
@ -137,7 +128,6 @@ LIR_Opr FrameMap::r11_metadata_opr;
LIR_Opr FrameMap::r12_metadata_opr;
LIR_Opr FrameMap::r13_metadata_opr;
LIR_Opr FrameMap::r14_metadata_opr;
#endif // _LP64
LIR_Opr FrameMap::_caller_save_cpu_regs[] = {};
LIR_Opr FrameMap::_caller_save_fpu_regs[] = {};
@ -157,23 +147,17 @@ XMMRegister FrameMap::nr2xmmreg(int rnr) {
void FrameMap::initialize() {
assert(!_init_done, "once");
assert(nof_cpu_regs == LP64_ONLY(16) NOT_LP64(8), "wrong number of CPU registers");
assert(nof_cpu_regs == 16, "wrong number of CPU registers");
map_register(0, rsi); rsi_opr = LIR_OprFact::single_cpu(0);
map_register(1, rdi); rdi_opr = LIR_OprFact::single_cpu(1);
map_register(2, rbx); rbx_opr = LIR_OprFact::single_cpu(2);
map_register(3, rax); rax_opr = LIR_OprFact::single_cpu(3);
map_register(4, rdx); rdx_opr = LIR_OprFact::single_cpu(4);
map_register(5, rcx); rcx_opr = LIR_OprFact::single_cpu(5);
#ifndef _LP64
// The unallocatable registers are at the end
map_register(6, rsp);
map_register(7, rbp);
#else
map_register( 6, r8); r8_opr = LIR_OprFact::single_cpu(6);
map_register( 7, r9); r9_opr = LIR_OprFact::single_cpu(7);
map_register( 8, r11); r11_opr = LIR_OprFact::single_cpu(8);
map_register( 9, r13); r13_opr = LIR_OprFact::single_cpu(9);
map_register(6, r8); r8_opr = LIR_OprFact::single_cpu(6);
map_register(7, r9); r9_opr = LIR_OprFact::single_cpu(7);
map_register(8, r11); r11_opr = LIR_OprFact::single_cpu(8);
map_register(9, r13); r13_opr = LIR_OprFact::single_cpu(9);
map_register(10, r14); r14_opr = LIR_OprFact::single_cpu(10);
// r12 is allocated conditionally. With compressed oops it holds
// the heapbase value and is not visible to the allocator.
@ -183,15 +167,9 @@ void FrameMap::initialize() {
map_register(13, r15); r15_opr = LIR_OprFact::single_cpu(13);
map_register(14, rsp);
map_register(15, rbp);
#endif // _LP64
#ifdef _LP64
long0_opr = LIR_OprFact::double_cpu(3 /*eax*/, 3 /*eax*/);
long1_opr = LIR_OprFact::double_cpu(2 /*ebx*/, 2 /*ebx*/);
#else
long0_opr = LIR_OprFact::double_cpu(3 /*eax*/, 4 /*edx*/);
long1_opr = LIR_OprFact::double_cpu(2 /*ebx*/, 5 /*ecx*/);
#endif // _LP64
xmm0_float_opr = LIR_OprFact::single_xmm(0);
xmm0_double_opr = LIR_OprFact::double_xmm(0);
@ -201,16 +179,12 @@ void FrameMap::initialize() {
_caller_save_cpu_regs[3] = rax_opr;
_caller_save_cpu_regs[4] = rdx_opr;
_caller_save_cpu_regs[5] = rcx_opr;
#ifdef _LP64
_caller_save_cpu_regs[6] = r8_opr;
_caller_save_cpu_regs[7] = r9_opr;
_caller_save_cpu_regs[8] = r11_opr;
_caller_save_cpu_regs[9] = r13_opr;
_caller_save_cpu_regs[10] = r14_opr;
_caller_save_cpu_regs[11] = r12_opr;
#endif // _LP64
_xmm_regs[0] = xmm0;
_xmm_regs[1] = xmm1;
@ -220,8 +194,6 @@ void FrameMap::initialize() {
_xmm_regs[5] = xmm5;
_xmm_regs[6] = xmm6;
_xmm_regs[7] = xmm7;
#ifdef _LP64
_xmm_regs[8] = xmm8;
_xmm_regs[9] = xmm9;
_xmm_regs[10] = xmm10;
@ -246,7 +218,6 @@ void FrameMap::initialize() {
_xmm_regs[29] = xmm29;
_xmm_regs[30] = xmm30;
_xmm_regs[31] = xmm31;
#endif // _LP64
for (int i = 0; i < 8; i++) {
_caller_save_fpu_regs[i] = LIR_OprFact::single_fpu(i);
@ -276,7 +247,6 @@ void FrameMap::initialize() {
rsp_opr = as_pointer_opr(rsp);
rbp_opr = as_pointer_opr(rbp);
#ifdef _LP64
r8_oop_opr = as_oop_opr(r8);
r9_oop_opr = as_oop_opr(r9);
r11_oop_opr = as_oop_opr(r11);
@ -290,7 +260,6 @@ void FrameMap::initialize() {
r12_metadata_opr = as_metadata_opr(r12);
r13_metadata_opr = as_metadata_opr(r13);
r14_metadata_opr = as_metadata_opr(r14);
#endif // _LP64
VMRegPair regs;
BasicType sig_bt = T_OBJECT;

View File

@ -41,13 +41,8 @@
nof_xmm_regs = pd_nof_xmm_regs_frame_map,
nof_caller_save_xmm_regs = pd_nof_caller_save_xmm_regs_frame_map,
first_available_sp_in_frame = 0,
#ifndef _LP64
frame_pad_in_bytes = 8,
nof_reg_args = 2
#else
frame_pad_in_bytes = 16,
nof_reg_args = 6
#endif // _LP64
};
private:
@ -81,8 +76,6 @@
static LIR_Opr rdx_metadata_opr;
static LIR_Opr rcx_metadata_opr;
#ifdef _LP64
static LIR_Opr r8_opr;
static LIR_Opr r9_opr;
static LIR_Opr r10_opr;
@ -108,28 +101,17 @@
static LIR_Opr r13_metadata_opr;
static LIR_Opr r14_metadata_opr;
#endif // _LP64
static LIR_Opr long0_opr;
static LIR_Opr long1_opr;
static LIR_Opr xmm0_float_opr;
static LIR_Opr xmm0_double_opr;
#ifdef _LP64
static LIR_Opr as_long_opr(Register r) {
return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r));
}
static LIR_Opr as_pointer_opr(Register r) {
return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r));
}
#else
static LIR_Opr as_long_opr(Register r, Register r2) {
return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r2));
}
static LIR_Opr as_pointer_opr(Register r) {
return LIR_OprFact::single_cpu(cpu_reg2rnr(r));
}
#endif // _LP64
// VMReg name for spilled physical FPU stack slot n
static VMReg fpu_regname (int n);

File diff suppressed because it is too large Load Diff

View File

@ -46,9 +46,9 @@
Register recv, Label* update_done);
enum {
_call_stub_size = NOT_LP64(15) LP64_ONLY(28),
_call_stub_size = 28,
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
_deopt_handler_size = NOT_LP64(10) LP64_ONLY(17)
_deopt_handler_size = 17
};
public:

View File

@ -142,7 +142,6 @@ bool LIRGenerator::can_inline_as_constant(LIR_Const* c) const {
LIR_Opr LIRGenerator::safepoint_poll_register() {
NOT_LP64( return new_register(T_ADDRESS); )
return LIR_OprFact::illegalOpr;
}
@ -152,7 +151,6 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index,
assert(base->is_register(), "must be");
if (index->is_constant()) {
LIR_Const *constant = index->as_constant_ptr();
#ifdef _LP64
jlong c;
if (constant->type() == T_INT) {
c = (jlong(index->as_jint()) << shift) + disp;
@ -167,11 +165,6 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index,
__ move(index, tmp);
return new LIR_Address(base, tmp, type);
}
#else
return new LIR_Address(base,
((intx)(constant->as_jint()) << shift) + disp,
type);
#endif
} else {
return new LIR_Address(base, index, (LIR_Address::Scale)shift, disp, type);
}
@ -185,7 +178,6 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o
LIR_Address* addr;
if (index_opr->is_constant()) {
int elem_size = type2aelembytes(type);
#ifdef _LP64
jint index = index_opr->as_jint();
jlong disp = offset_in_bytes + (jlong)(index) * elem_size;
if (disp > max_jint) {
@ -197,28 +189,12 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o
} else {
addr = new LIR_Address(array_opr, (intx)disp, type);
}
#else
// A displacement overflow can also occur for x86 but that is not a problem due to the 32-bit address range!
// Let's assume an array 'a' and an access with displacement 'disp'. When disp overflows, then "a + disp" will
// always be negative (i.e. underflows the 32-bit address range):
// Let N = 2^32: a + signed_overflow(disp) = a + disp - N.
// "a + disp" is always smaller than N. If an index was chosen which would point to an address beyond N, then
// range checks would catch that and throw an exception. Thus, a + disp < 0 holds which means that it always
// underflows the 32-bit address range:
// unsigned_underflow(a + signed_overflow(disp)) = unsigned_underflow(a + disp - N)
// = (a + disp - N) + N = a + disp
// This shows that we still end up at the correct address with a displacement overflow due to the 32-bit address
// range limitation. This overflow only needs to be handled if addresses can be larger as on 64-bit platforms.
addr = new LIR_Address(array_opr, offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type);
#endif // _LP64
} else {
#ifdef _LP64
if (index_opr->type() == T_INT) {
LIR_Opr tmp = new_register(T_LONG);
__ convert(Bytecodes::_i2l, index_opr, tmp);
index_opr = tmp;
}
#endif // _LP64
addr = new LIR_Address(array_opr,
index_opr,
LIR_Address::scale(type),
@ -358,34 +334,12 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
left.dont_load_item();
}
#ifndef _LP64
// do not load right operand if it is a constant. only 0 and 1 are
// loaded because there are special instructions for loading them
// without memory access (not needed for SSE2 instructions)
bool must_load_right = false;
if (right.is_constant()) {
LIR_Const* c = right.result()->as_constant_ptr();
assert(c != nullptr, "invalid constant");
assert(c->type() == T_FLOAT || c->type() == T_DOUBLE, "invalid type");
if (c->type() == T_FLOAT) {
must_load_right = UseSSE < 1 && (c->is_one_float() || c->is_zero_float());
} else {
must_load_right = UseSSE < 2 && (c->is_one_double() || c->is_zero_double());
}
}
#endif // !LP64
if (must_load_both) {
// frem and drem destroy also right operand, so move it to a new register
right.set_destroys_register();
right.load_item();
} else if (right.is_register()) {
right.load_item();
#ifndef _LP64
} else if (must_load_right) {
right.load_item();
#endif // !LP64
} else {
right.dont_load_item();
}
@ -395,7 +349,6 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
tmp = new_register(T_DOUBLE);
}
#ifdef _LP64
if (x->op() == Bytecodes::_frem || x->op() == Bytecodes::_drem) {
// frem and drem are implemented as a direct call into the runtime.
LIRItem left(x->x(), this);
@ -430,27 +383,6 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), tmp);
set_result(x, reg);
}
#else
if ((UseSSE >= 1 && x->op() == Bytecodes::_frem) || (UseSSE >= 2 && x->op() == Bytecodes::_drem)) {
// special handling for frem and drem: no SSE instruction, so must use FPU with temporary fpu stack slots
LIR_Opr fpu0, fpu1;
if (x->op() == Bytecodes::_frem) {
fpu0 = LIR_OprFact::single_fpu(0);
fpu1 = LIR_OprFact::single_fpu(1);
} else {
fpu0 = LIR_OprFact::double_fpu(0);
fpu1 = LIR_OprFact::double_fpu(1);
}
__ move(right.result(), fpu1); // order of left and right operand is important!
__ move(left.result(), fpu0);
__ rem (fpu0, fpu1, fpu0);
__ move(fpu0, reg);
} else {
arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), tmp);
}
set_result(x, reg);
#endif // _LP64
}
@ -740,7 +672,7 @@ LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value)
value.load_item();
// Because we want a 2-arg form of xchg and xadd
__ move(value.result(), result);
assert(type == T_INT || is_oop LP64_ONLY( || type == T_LONG ), "unexpected type");
assert(type == T_INT || is_oop || type == T_LONG, "unexpected type");
__ xchg(addr, result, result, LIR_OprFact::illegalOpr);
return result;
}
@ -750,7 +682,7 @@ LIR_Opr LIRGenerator::atomic_add(BasicType type, LIR_Opr addr, LIRItem& value) {
value.load_item();
// Because we want a 2-arg form of xchg and xadd
__ move(value.result(), result);
assert(type == T_INT LP64_ONLY( || type == T_LONG ), "unexpected type");
assert(type == T_INT || type == T_LONG, "unexpected type");
__ xadd(addr, result, result, LIR_OprFact::illegalOpr);
return result;
}
@ -788,10 +720,7 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
if (x->id() == vmIntrinsics::_dexp || x->id() == vmIntrinsics::_dlog ||
x->id() == vmIntrinsics::_dpow || x->id() == vmIntrinsics::_dcos ||
x->id() == vmIntrinsics::_dsin || x->id() == vmIntrinsics::_dtan ||
x->id() == vmIntrinsics::_dlog10
#ifdef _LP64
|| x->id() == vmIntrinsics::_dtanh
#endif
x->id() == vmIntrinsics::_dlog10 || x->id() == vmIntrinsics::_dtanh
) {
do_LibmIntrinsic(x);
return;
@ -799,12 +728,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
LIRItem value(x->argument_at(0), this);
bool use_fpu = false;
#ifndef _LP64
if (UseSSE < 2) {
value.set_destroys_register();
}
#endif // !LP64
value.load_item();
LIR_Opr calc_input = value.result();
@ -832,10 +755,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
default:
ShouldNotReachHere();
}
if (use_fpu) {
__ move(calc_result, x->operand());
}
}
void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) {
@ -956,20 +875,6 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
flags = 0;
}
#ifndef _LP64
src.load_item_force (FrameMap::rcx_oop_opr);
src_pos.load_item_force (FrameMap::rdx_opr);
dst.load_item_force (FrameMap::rax_oop_opr);
dst_pos.load_item_force (FrameMap::rbx_opr);
length.load_item_force (FrameMap::rdi_opr);
LIR_Opr tmp = (FrameMap::rsi_opr);
if (expected_type != nullptr && flags == 0) {
FrameMap* f = Compilation::current()->frame_map();
f->update_reserved_argument_area_size(3 * BytesPerWord);
}
#else
// The java calling convention will give us enough registers
// so that on the stub side the args will be perfect already.
// On the other slow/special case side we call C and the arg
@ -985,7 +890,6 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
length.load_item_force (FrameMap::as_opr(j_rarg4));
LIR_Opr tmp = FrameMap::as_opr(j_rarg5);
#endif // LP64
set_no_result(x);
@ -1027,18 +931,11 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
}
LIR_Opr base_op = buf.result();
#ifndef _LP64
if (!is_updateBytes) { // long b raw address
base_op = new_register(T_INT);
__ convert(Bytecodes::_l2i, buf.result(), base_op);
}
#else
if (index->is_valid()) {
LIR_Opr tmp = new_register(T_LONG);
__ convert(Bytecodes::_i2l, index, tmp);
index = tmp;
}
#endif
LIR_Address* a = new LIR_Address(base_op,
index,
@ -1172,14 +1069,6 @@ void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
}
LIR_Opr result_b = b.result();
#ifndef _LP64
result_a = new_register(T_INT);
__ convert(Bytecodes::_l2i, a.result(), result_a);
result_b = new_register(T_INT);
__ convert(Bytecodes::_l2i, b.result(), result_b);
#endif
LIR_Address* addr_a = new LIR_Address(result_a,
result_aOffset,
constant_aOffset,
@ -1214,7 +1103,6 @@ void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
}
void LIRGenerator::do_Convert(Convert* x) {
#ifdef _LP64
LIRItem value(x->value(), this);
value.load_item();
LIR_Opr input = value.result();
@ -1222,66 +1110,6 @@ void LIRGenerator::do_Convert(Convert* x) {
__ convert(x->op(), input, result);
assert(result->is_virtual(), "result must be virtual register");
set_result(x, result);
#else
// flags that vary for the different operations and different SSE-settings
bool fixed_input = false, fixed_result = false, round_result = false, needs_stub = false;
switch (x->op()) {
case Bytecodes::_i2l: // fall through
case Bytecodes::_l2i: // fall through
case Bytecodes::_i2b: // fall through
case Bytecodes::_i2c: // fall through
case Bytecodes::_i2s: fixed_input = false; fixed_result = false; round_result = false; needs_stub = false; break;
case Bytecodes::_f2d: fixed_input = UseSSE == 1; fixed_result = false; round_result = false; needs_stub = false; break;
case Bytecodes::_d2f: fixed_input = false; fixed_result = UseSSE == 1; round_result = UseSSE < 1; needs_stub = false; break;
case Bytecodes::_i2f: fixed_input = false; fixed_result = false; round_result = UseSSE < 1; needs_stub = false; break;
case Bytecodes::_i2d: fixed_input = false; fixed_result = false; round_result = false; needs_stub = false; break;
case Bytecodes::_f2i: fixed_input = false; fixed_result = false; round_result = false; needs_stub = true; break;
case Bytecodes::_d2i: fixed_input = false; fixed_result = false; round_result = false; needs_stub = true; break;
case Bytecodes::_l2f: fixed_input = false; fixed_result = UseSSE >= 1; round_result = UseSSE < 1; needs_stub = false; break;
case Bytecodes::_l2d: fixed_input = false; fixed_result = UseSSE >= 2; round_result = UseSSE < 2; needs_stub = false; break;
case Bytecodes::_f2l: fixed_input = true; fixed_result = true; round_result = false; needs_stub = false; break;
case Bytecodes::_d2l: fixed_input = true; fixed_result = true; round_result = false; needs_stub = false; break;
default: ShouldNotReachHere();
}
LIRItem value(x->value(), this);
value.load_item();
LIR_Opr input = value.result();
LIR_Opr result = rlock(x);
// arguments of lir_convert
LIR_Opr conv_input = input;
LIR_Opr conv_result = result;
ConversionStub* stub = nullptr;
if (fixed_input) {
conv_input = fixed_register_for(input->type());
__ move(input, conv_input);
}
assert(fixed_result == false || round_result == false, "cannot set both");
if (fixed_result) {
conv_result = fixed_register_for(result->type());
} else if (round_result) {
result = new_register(result->type());
set_vreg_flag(result, must_start_in_memory);
}
if (needs_stub) {
stub = new ConversionStub(x->op(), conv_input, conv_result);
}
__ convert(x->op(), conv_input, conv_result, stub);
if (result != conv_result) {
__ move(conv_result, result);
}
assert(result->is_virtual(), "result must be virtual register");
set_result(x, result);
#endif // _LP64
}
@ -1547,13 +1375,7 @@ void LIRGenerator::do_If(If* x) {
LIR_Opr LIRGenerator::getThreadPointer() {
#ifdef _LP64
return FrameMap::as_pointer_opr(r15_thread);
#else
LIR_Opr result = new_register(T_INT);
__ get_thread(result);
return result;
#endif //
}
void LIRGenerator::trace_block_entry(BlockBegin* block) {
@ -1598,12 +1420,6 @@ void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
LIR_Opr temp_double = new_register(T_DOUBLE);
__ volatile_move(LIR_OprFact::address(address), temp_double, T_LONG, info);
__ volatile_move(temp_double, result, T_LONG);
#ifndef _LP64
if (UseSSE < 2) {
// no spill slot needed in SSE2 mode because xmm->cpu register move is possible
set_vreg_flag(result, must_start_in_memory);
}
#endif // !LP64
} else {
__ load(address, result, info);
}

View File

@ -58,16 +58,9 @@ LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) {
#ifndef PRODUCT
void LIR_Address::verify() const {
#ifdef _LP64
assert(base()->is_cpu_register(), "wrong base operand");
assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand");
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA,
"wrong type for addresses");
#else
assert(base()->is_single_cpu(), "wrong base operand");
assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand");
assert(base()->type() == T_ADDRESS || base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA,
"wrong type for addresses");
#endif
}
#endif // PRODUCT

View File

@ -26,12 +26,6 @@
#define CPU_X86_C1_LINEARSCAN_X86_HPP
inline bool LinearScan::is_processed_reg_num(int reg_num) {
#ifndef _LP64
// rsp and rbp (numbers 6 ancd 7) are ignored
assert(FrameMap::rsp_opr->cpu_regnr() == 6, "wrong assumption below");
assert(FrameMap::rbp_opr->cpu_regnr() == 7, "wrong assumption below");
assert(reg_num >= 0, "invalid reg_num");
#else
// rsp and rbp, r10, r15 (numbers [12,15]) are ignored
// r12 (number 11) is conditional on compressed oops.
assert(FrameMap::r12_opr->cpu_regnr() == 11, "wrong assumption below");
@ -40,16 +34,10 @@ inline bool LinearScan::is_processed_reg_num(int reg_num) {
assert(FrameMap::rsp_opr->cpu_regnrLo() == 14, "wrong assumption below");
assert(FrameMap::rbp_opr->cpu_regnrLo() == 15, "wrong assumption below");
assert(reg_num >= 0, "invalid reg_num");
#endif // _LP64
return reg_num <= FrameMap::last_cpu_reg() || reg_num >= pd_nof_cpu_regs_frame_map;
}
inline int LinearScan::num_physical_regs(BasicType type) {
// Intel requires two cpu registers for long,
// but requires only one fpu register for double
if (LP64_ONLY(false &&) type == T_LONG) {
return 2;
}
return 1;
}

View File

@ -62,15 +62,8 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
}
if (LockingMode == LM_LIGHTWEIGHT) {
#ifdef _LP64
const Register thread = r15_thread;
lightweight_lock(disp_hdr, obj, hdr, thread, tmp, slow_case);
#else
// Implicit null check.
movptr(hdr, Address(obj, oopDesc::mark_offset_in_bytes()));
// Lacking registers and thread on x86_32. Always take slow path.
jmp(slow_case);
#endif
} else if (LockingMode == LM_LEGACY) {
Label done;
// Load object header
@ -135,12 +128,7 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_
verify_oop(obj);
if (LockingMode == LM_LIGHTWEIGHT) {
#ifdef _LP64
lightweight_unlock(obj, disp_hdr, r15_thread, hdr, slow_case);
#else
// Lacking registers and thread on x86_32. Always take slow path.
jmp(slow_case);
#endif
} else if (LockingMode == LM_LEGACY) {
// test if object header is pointing to the displaced header, and if so, restore
// the displaced header in the object - if the object header is not pointing to
@ -169,7 +157,6 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i
void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
assert_different_registers(obj, klass, len, t1, t2);
#ifdef _LP64
if (UseCompactObjectHeaders) {
movptr(t1, Address(klass, Klass::prototype_header_offset()));
movptr(Address(obj, oopDesc::mark_offset_in_bytes()), t1);
@ -178,16 +165,13 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
movptr(t1, klass);
encode_klass_not_null(t1, rscratch1);
movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1);
} else
#endif
{
} else {
movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast<int32_t>(markWord::prototype().value()));
movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
}
if (len->is_valid()) {
movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len);
#ifdef _LP64
int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt;
if (!is_aligned(base_offset, BytesPerWord)) {
assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned");
@ -195,14 +179,10 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
xorl(t1, t1);
movl(Address(obj, base_offset), t1);
}
#endif
}
#ifdef _LP64
else if (UseCompressedClassPointers && !UseCompactObjectHeaders) {
} else if (UseCompressedClassPointers && !UseCompactObjectHeaders) {
xorptr(t1, t1);
store_klass_gap(obj, t1);
}
#endif
}
@ -265,8 +245,6 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register
bind(loop);
movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - (1*BytesPerWord)),
t1_zero);
NOT_LP64(movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - (2*BytesPerWord)),
t1_zero);)
decrement(index);
jcc(Assembler::notZero, loop);
}

View File

@ -51,27 +51,18 @@
int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, int args_size) {
// setup registers
const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); // is callee-saved register (Visual C++ calling conventions)
const Register thread = r15_thread; // is callee-saved register (Visual C++ calling conventions)
assert(!(oop_result1->is_valid() || metadata_result->is_valid()) || oop_result1 != metadata_result, "registers must be different");
assert(oop_result1 != thread && metadata_result != thread, "registers must be different");
assert(args_size >= 0, "illegal args_size");
bool align_stack = false;
#ifdef _LP64
// At a method handle call, the stack may not be properly aligned
// when returning with an exception.
align_stack = (stub_id() == (int)C1StubId::handle_exception_from_callee_id);
#endif
#ifdef _LP64
mov(c_rarg0, thread);
set_num_rt_args(0); // Nothing on stack
#else
set_num_rt_args(1 + args_size);
// push java thread (becomes first argument of C function)
get_thread(thread);
push(thread);
#endif // _LP64
int call_offset = -1;
if (!align_stack) {
@ -104,9 +95,6 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre
#endif
reset_last_Java_frame(thread, true);
// discard thread and arguments
NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord));
// check for pending exceptions
{ Label L;
cmpptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD);
@ -144,17 +132,12 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre
int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1) {
#ifdef _LP64
mov(c_rarg1, arg1);
#else
push(arg1);
#endif // _LP64
return call_RT(oop_result1, metadata_result, entry, 1);
}
int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2) {
#ifdef _LP64
if (c_rarg1 == arg2) {
if (c_rarg2 == arg1) {
xchgq(arg1, arg2);
@ -166,16 +149,11 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre
mov(c_rarg1, arg1);
mov(c_rarg2, arg2);
}
#else
push(arg2);
push(arg1);
#endif // _LP64
return call_RT(oop_result1, metadata_result, entry, 2);
}
int StubAssembler::call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3) {
#ifdef _LP64
// if there is any conflict use the stack
if (arg1 == c_rarg2 || arg1 == c_rarg3 ||
arg2 == c_rarg1 || arg2 == c_rarg3 ||
@ -191,11 +169,6 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre
mov(c_rarg2, arg2);
mov(c_rarg3, arg3);
}
#else
push(arg3);
push(arg2);
push(arg1);
#endif // _LP64
return call_RT(oop_result1, metadata_result, entry, 3);
}
@ -262,20 +235,13 @@ const int xmm_regs_as_doubles_size_in_slots = FrameMap::nof_xmm_regs * 2;
// but the code in save_live_registers will take the argument count into
// account.
//
#ifdef _LP64
#define SLOT2(x) x,
#define SLOT_PER_WORD 2
#else
#define SLOT2(x)
#define SLOT_PER_WORD 1
#endif // _LP64
#define SLOT2(x) x,
#define SLOT_PER_WORD 2
enum reg_save_layout {
// 64bit needs to keep stack 16 byte aligned. So we add some alignment dummies to make that
// happen and will assert if the stack size we create is misaligned
#ifdef _LP64
align_dummy_0, align_dummy_1,
#endif // _LP64
#ifdef _WIN64
// Windows always allocates space for it's argument registers (see
// frame::arg_reg_save_area_bytes).
@ -291,7 +257,6 @@ enum reg_save_layout {
fpu_state_end_off = fpu_state_off + (FPUStateSizeInWords / SLOT_PER_WORD), // 352
marker = fpu_state_end_off, SLOT2(markerH) // 352, 356
extra_space_offset, // 360
#ifdef _LP64
r15_off = extra_space_offset, r15H_off, // 360, 364
r14_off, r14H_off, // 368, 372
r13_off, r13H_off, // 376, 380
@ -301,9 +266,6 @@ enum reg_save_layout {
r9_off, r9H_off, // 408, 412
r8_off, r8H_off, // 416, 420
rdi_off, rdiH_off, // 424, 428
#else
rdi_off = extra_space_offset,
#endif // _LP64
rsi_off, SLOT2(rsiH_off) // 432, 436
rbp_off, SLOT2(rbpH_off) // 440, 444
rsp_off, SLOT2(rspH_off) // 448, 452
@ -329,8 +291,8 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
bool save_fpu_registers = true) {
// In 64bit all the args are in regs so there are no additional stack slots
LP64_ONLY(num_rt_args = 0);
LP64_ONLY(assert((reg_save_frame_size * VMRegImpl::stack_slot_size) % 16 == 0, "must be 16 byte aligned");)
num_rt_args = 0;
assert((reg_save_frame_size * VMRegImpl::stack_slot_size) % 16 == 0, "must be 16 byte aligned");
int frame_size_in_slots = reg_save_frame_size + num_rt_args; // args + thread
sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word);
@ -343,7 +305,6 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
map->set_callee_saved(VMRegImpl::stack2reg(rbx_off + num_rt_args), rbx->as_VMReg());
map->set_callee_saved(VMRegImpl::stack2reg(rsi_off + num_rt_args), rsi->as_VMReg());
map->set_callee_saved(VMRegImpl::stack2reg(rdi_off + num_rt_args), rdi->as_VMReg());
#ifdef _LP64
map->set_callee_saved(VMRegImpl::stack2reg(r8_off + num_rt_args), r8->as_VMReg());
map->set_callee_saved(VMRegImpl::stack2reg(r9_off + num_rt_args), r9->as_VMReg());
map->set_callee_saved(VMRegImpl::stack2reg(r10_off + num_rt_args), r10->as_VMReg());
@ -369,37 +330,10 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
map->set_callee_saved(VMRegImpl::stack2reg(r13H_off + num_rt_args), r13->as_VMReg()->next());
map->set_callee_saved(VMRegImpl::stack2reg(r14H_off + num_rt_args), r14->as_VMReg()->next());
map->set_callee_saved(VMRegImpl::stack2reg(r15H_off + num_rt_args), r15->as_VMReg()->next());
#endif // _LP64
int xmm_bypass_limit = FrameMap::get_num_caller_save_xmms();
if (save_fpu_registers) {
#ifndef _LP64
if (UseSSE < 2) {
int fpu_off = float_regs_as_doubles_off;
for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
VMReg fpu_name_0 = FrameMap::fpu_regname(n);
map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + num_rt_args), fpu_name_0);
// %%% This is really a waste but we'll keep things as they were for now
if (true) {
map->set_callee_saved(VMRegImpl::stack2reg(fpu_off + 1 + num_rt_args), fpu_name_0->next());
}
fpu_off += 2;
}
assert(fpu_off == fpu_state_off, "incorrect number of fpu stack slots");
if (UseSSE == 1) {
int xmm_off = xmm_regs_as_doubles_off;
for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
xmm_off += 2;
}
assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
}
}
#endif // !LP64
if (UseSSE >= 2) {
int xmm_off = xmm_regs_as_doubles_off;
for (int n = 0; n < FrameMap::nof_xmm_regs; n++) {
@ -426,14 +360,7 @@ void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers)
__ block_comment("save_live_registers");
// Push CPU state in multiple of 16 bytes
#ifdef _LP64
__ save_legacy_gprs();
#else
__ pusha();
#endif
// assert(float_regs_as_doubles_off % 2 == 0, "misaligned offset");
// assert(xmm_regs_as_doubles_off % 2 == 0, "misaligned offset");
__ subptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size);
@ -442,46 +369,6 @@ void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers)
#endif
if (save_fpu_registers) {
#ifndef _LP64
if (UseSSE < 2) {
// save FPU stack
__ fnsave(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));
__ fwait();
#ifdef ASSERT
Label ok;
__ cmpw(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size), StubRoutines::x86::fpu_cntrl_wrd_std());
__ jccb(Assembler::equal, ok);
__ stop("corrupted control word detected");
__ bind(ok);
#endif
// Reset the control word to guard against exceptions being unmasked
// since fstp_d can cause FPU stack underflow exceptions. Write it
// into the on stack copy and then reload that to make sure that the
// current and future values are correct.
__ movw(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size), StubRoutines::x86::fpu_cntrl_wrd_std());
__ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));
// Save the FPU registers in de-opt-able form
int offset = 0;
for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
__ fstp_d(Address(rsp, float_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
offset += 8;
}
if (UseSSE == 1) {
// save XMM registers as float because double not supported without SSE2(num MMX == num fpu)
int offset = 0;
for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
__ movflt(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset), xmm_name);
offset += 8;
}
}
}
#endif // !_LP64
if (UseSSE >= 2) {
// save XMM registers
// XMM registers can contain float or double values, but this is not known here,
@ -497,16 +384,12 @@ void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers)
}
}
}
// FPU stack must be empty now
NOT_LP64( __ verify_FPU(0, "save_live_registers"); )
}
#undef __
#define __ sasm->
static void restore_fpu(C1_MacroAssembler* sasm, bool restore_fpu_registers) {
#ifdef _LP64
if (restore_fpu_registers) {
// restore XMM registers
int xmm_bypass_limit = FrameMap::get_num_caller_save_xmms();
@ -517,38 +400,6 @@ static void restore_fpu(C1_MacroAssembler* sasm, bool restore_fpu_registers) {
offset += 8;
}
}
#else
if (restore_fpu_registers) {
if (UseSSE >= 2) {
// restore XMM registers
int xmm_bypass_limit = FrameMap::nof_xmm_regs;
int offset = 0;
for (int n = 0; n < xmm_bypass_limit; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
__ movdbl(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
offset += 8;
}
} else if (UseSSE == 1) {
// restore XMM registers(num MMX == num fpu)
int offset = 0;
for (int n = 0; n < FrameMap::nof_fpu_regs; n++) {
XMMRegister xmm_name = as_XMMRegister(n);
__ movflt(xmm_name, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + offset));
offset += 8;
}
}
if (UseSSE < 2) {
__ frstor(Address(rsp, fpu_state_off * VMRegImpl::stack_slot_size));
} else {
// check that FPU stack is really empty
__ verify_FPU(0, "restore_live_registers");
}
} else {
// check that FPU stack is really empty
__ verify_FPU(0, "restore_live_registers");
}
#endif // _LP64
#ifdef ASSERT
{
@ -570,12 +421,7 @@ void C1_MacroAssembler::restore_live_registers(bool restore_fpu_registers) {
__ block_comment("restore_live_registers");
restore_fpu(this, restore_fpu_registers);
#ifdef _LP64
__ restore_legacy_gprs();
#else
__ popa();
#endif
}
@ -584,7 +430,6 @@ void C1_MacroAssembler::restore_live_registers_except_rax(bool restore_fpu_regis
restore_fpu(this, restore_fpu_registers);
#ifdef _LP64
__ movptr(r15, Address(rsp, 0));
__ movptr(r14, Address(rsp, wordSize));
__ movptr(r13, Address(rsp, 2 * wordSize));
@ -602,17 +447,6 @@ void C1_MacroAssembler::restore_live_registers_except_rax(bool restore_fpu_regis
__ movptr(rcx, Address(rsp, 14 * wordSize));
__ addptr(rsp, 16 * wordSize);
#else
__ pop(rdi);
__ pop(rsi);
__ pop(rbp);
__ pop(rbx); // skip this value
__ pop(rbx);
__ pop(rdx);
__ pop(rcx);
__ addptr(rsp, BytesPerWord);
#endif // _LP64
}
#undef __
@ -639,12 +473,7 @@ void Runtime1::initialize_pd() {
// return: offset in 64-bit words.
uint Runtime1::runtime_blob_current_thread_offset(frame f) {
#ifdef _LP64
return r15_off / 2; // rsp offsets are in halfwords
#else
Unimplemented();
return 0;
#endif
}
// Target: the entry point of the method that creates and posts the exception oop.
@ -664,15 +493,8 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe
// Load arguments for exception that are passed as arguments into the stub.
if (has_argument) {
#ifdef _LP64
__ movptr(c_rarg1, Address(rbp, 2*BytesPerWord));
__ movptr(c_rarg2, Address(rbp, 3*BytesPerWord));
#else
__ movptr(temp_reg, Address(rbp, 3*BytesPerWord));
__ push(temp_reg);
__ movptr(temp_reg, Address(rbp, 2*BytesPerWord));
__ push(temp_reg);
#endif // _LP64
}
int call_offset = __ call_RT(noreg, noreg, target, num_rt_args - 1);
@ -692,7 +514,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm)
const Register exception_oop = rax;
const Register exception_pc = rdx;
// other registers used in this stub
const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread);
const Register thread = r15_thread;
// Save registers, if required.
OopMapSet* oop_maps = new OopMapSet();
@ -725,7 +547,7 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm)
case C1StubId::handle_exception_from_callee_id: {
// At this point all registers except exception oop (RAX) and
// exception pc (RDX) are dead.
const int frame_size = 2 /*BP, return address*/ NOT_LP64(+ 1 /*thread*/) WIN64_ONLY(+ frame::arg_reg_save_area_bytes / BytesPerWord);
const int frame_size = 2 /*BP, return address*/ WIN64_ONLY(+ frame::arg_reg_save_area_bytes / BytesPerWord);
oop_map = new OopMap(frame_size * VMRegImpl::slots_per_word, 0);
sasm->set_frame_size(frame_size);
WIN64_ONLY(__ subq(rsp, frame::arg_reg_save_area_bytes));
@ -734,21 +556,11 @@ OopMapSet* Runtime1::generate_handle_exception(C1StubId id, StubAssembler *sasm)
default: ShouldNotReachHere();
}
#if !defined(_LP64) && defined(COMPILER2)
if (UseSSE < 2 && !CompilerConfig::is_c1_only_no_jvmci()) {
// C2 can leave the fpu stack dirty
__ empty_FPU_stack();
}
#endif // !_LP64 && COMPILER2
// verify that only rax, and rdx is valid at this time
__ invalidate_registers(false, true, true, false, true, true);
// verify that rax, contains a valid exception
__ verify_not_null_oop(exception_oop);
// load address of JavaThread object for thread-local data
NOT_LP64(__ get_thread(thread);)
#ifdef ASSERT
// check that fields in JavaThread for exception oop and issuing pc are
// empty before writing to them
@ -815,11 +627,11 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) {
// incoming parameters
const Register exception_oop = rax;
// callee-saved copy of exception_oop during runtime call
const Register exception_oop_callee_saved = NOT_LP64(rsi) LP64_ONLY(r14);
const Register exception_oop_callee_saved = r14;
// other registers used in this stub
const Register exception_pc = rdx;
const Register handler_addr = rbx;
const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread);
const Register thread = r15_thread;
if (AbortVMOnException) {
__ enter();
@ -834,7 +646,6 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) {
#ifdef ASSERT
// check that fields in JavaThread for exception oop and issuing pc are empty
NOT_LP64(__ get_thread(thread);)
Label oop_empty;
__ cmpptr(Address(thread, JavaThread::exception_oop_offset()), 0);
__ jcc(Assembler::equal, oop_empty);
@ -848,14 +659,10 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) {
__ bind(pc_empty);
#endif
// clear the FPU stack in case any FPU results are left behind
NOT_LP64( __ empty_FPU_stack(); )
// save exception_oop in callee-saved register to preserve it during runtime calls
__ verify_not_null_oop(exception_oop);
__ movptr(exception_oop_callee_saved, exception_oop);
NOT_LP64(__ get_thread(thread);)
// Get return address (is on top of stack after leave).
__ movptr(exception_pc, Address(rsp, 0));
@ -905,18 +712,10 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) {
OopMap* oop_map = save_live_registers(sasm, num_rt_args);
#ifdef _LP64
const Register thread = r15_thread;
// No need to worry about dummy
__ mov(c_rarg0, thread);
#else
__ push(rax); // push dummy
const Register thread = rdi; // is callee-saved register (Visual C++ calling conventions)
// push java thread (becomes first argument of C function)
__ get_thread(thread);
__ push(thread);
#endif // _LP64
__ set_last_Java_frame(thread, noreg, rbp, nullptr, rscratch1);
// do the call
__ call(RuntimeAddress(target));
@ -936,10 +735,6 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) {
__ pop(rax);
#endif
__ reset_last_Java_frame(thread, true);
#ifndef _LP64
__ pop(rcx); // discard thread arg
__ pop(rcx); // discard dummy
#endif // _LP64
// check for pending exceptions
{ Label L;
@ -1166,15 +961,8 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) {
// This is called via call_runtime so the arguments
// will be place in C abi locations
#ifdef _LP64
__ verify_oop(c_rarg0);
__ mov(rax, c_rarg0);
#else
// The object is passed on the stack and we haven't pushed a
// frame yet so it's one work away from top of stack.
__ movptr(rax, Address(rsp, 1 * BytesPerWord));
__ verify_oop(rax);
#endif // _LP64
// load the klass and check the has finalizer flag
Label register_finalizer;
@ -1467,9 +1255,8 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) {
// the live registers get saved.
save_live_registers(sasm, 1);
__ NOT_LP64(push(rax)) LP64_ONLY(mov(c_rarg0, rax));
__ mov(c_rarg0, rax);
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, static_cast<int (*)(oopDesc*)>(SharedRuntime::dtrace_object_alloc))));
NOT_LP64(__ pop(rax));
restore_live_registers(sasm);
}
@ -1477,7 +1264,6 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) {
case C1StubId::fpu2long_stub_id:
{
#ifdef _LP64
Label done;
__ cvttsd2siq(rax, Address(rsp, wordSize));
__ cmp64(rax, ExternalAddress((address) StubRoutines::x86::double_sign_flip()));
@ -1489,78 +1275,6 @@ OopMapSet* Runtime1::generate_code_for(C1StubId id, StubAssembler* sasm) {
__ pop(rax);
__ bind(done);
__ ret(0);
#else
// rax, and rdx are destroyed, but should be free since the result is returned there
// preserve rsi,ecx
__ push(rsi);
__ push(rcx);
// check for NaN
Label return0, do_return, return_min_jlong, do_convert;
Address value_high_word(rsp, wordSize + 4);
Address value_low_word(rsp, wordSize);
Address result_high_word(rsp, 3*wordSize + 4);
Address result_low_word(rsp, 3*wordSize);
__ subptr(rsp, 32); // more than enough on 32bit
__ fst_d(value_low_word);
__ movl(rax, value_high_word);
__ andl(rax, 0x7ff00000);
__ cmpl(rax, 0x7ff00000);
__ jcc(Assembler::notEqual, do_convert);
__ movl(rax, value_high_word);
__ andl(rax, 0xfffff);
__ orl(rax, value_low_word);
__ jcc(Assembler::notZero, return0);
__ bind(do_convert);
__ fnstcw(Address(rsp, 0));
__ movzwl(rax, Address(rsp, 0));
__ orl(rax, 0xc00);
__ movw(Address(rsp, 2), rax);
__ fldcw(Address(rsp, 2));
__ fwait();
__ fistp_d(result_low_word);
__ fldcw(Address(rsp, 0));
__ fwait();
// This gets the entire long in rax on 64bit
__ movptr(rax, result_low_word);
// testing of high bits
__ movl(rdx, result_high_word);
__ mov(rcx, rax);
// What the heck is the point of the next instruction???
__ xorl(rcx, 0x0);
__ movl(rsi, 0x80000000);
__ xorl(rsi, rdx);
__ orl(rcx, rsi);
__ jcc(Assembler::notEqual, do_return);
__ fldz();
__ fcomp_d(value_low_word);
__ fnstsw_ax();
__ sahf();
__ jcc(Assembler::above, return_min_jlong);
// return max_jlong
__ movl(rdx, 0x7fffffff);
__ movl(rax, 0xffffffff);
__ jmp(do_return);
__ bind(return_min_jlong);
__ movl(rdx, 0x80000000);
__ xorl(rax, rax);
__ jmp(do_return);
__ bind(return0);
__ fpop();
__ xorptr(rdx,rdx);
__ xorptr(rax,rax);
__ bind(do_return);
__ addptr(rsp, 32);
__ pop(rcx);
__ pop(rsi);
__ ret(0);
#endif // _LP64
}
break;