mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-31 07:48:49 +00:00
8171398: s390x: Make interpreter's math entries consistent with C1 and C2 and support FMA
Reviewed-by: lucy, goetz
This commit is contained in:
parent
b06fa0ea3a
commit
27139d7529
@ -790,6 +790,16 @@ class Assembler : public AbstractAssembler {
|
||||
#define MDB_ZOPC (unsigned long)(237L << 40 | 28)
|
||||
#define MXDB_ZOPC (unsigned long)(237L << 40 | 7)
|
||||
|
||||
// Multiply-Add
|
||||
#define MAEBR_ZOPC (unsigned int)(179 << 24 | 14 << 16)
|
||||
#define MADBR_ZOPC (unsigned int)(179 << 24 | 30 << 16)
|
||||
#define MSEBR_ZOPC (unsigned int)(179 << 24 | 15 << 16)
|
||||
#define MSDBR_ZOPC (unsigned int)(179 << 24 | 31 << 16)
|
||||
#define MAEB_ZOPC (unsigned long)(237L << 40 | 14)
|
||||
#define MADB_ZOPC (unsigned long)(237L << 40 | 30)
|
||||
#define MSEB_ZOPC (unsigned long)(237L << 40 | 15)
|
||||
#define MSDB_ZOPC (unsigned long)(237L << 40 | 31)
|
||||
|
||||
// Divide
|
||||
// RR, signed
|
||||
#define DSGFR_ZOPC (unsigned int)(0xb91d << 16)
|
||||
@ -2205,6 +2215,20 @@ class Assembler : public AbstractAssembler {
|
||||
inline void z_meeb( FloatRegister f1, const Address& a);
|
||||
inline void z_mdb( FloatRegister f1, const Address& a);
|
||||
|
||||
// MUL-ADD
|
||||
inline void z_maebr(FloatRegister f1, FloatRegister f3, FloatRegister f2); // f1 = f3 * f2 + f1 ; float
|
||||
inline void z_madbr(FloatRegister f1, FloatRegister f3, FloatRegister f2); // f1 = f3 * f2 + f1 ; double
|
||||
inline void z_msebr(FloatRegister f1, FloatRegister f3, FloatRegister f2); // f1 = f3 * f2 - f1 ; float
|
||||
inline void z_msdbr(FloatRegister f1, FloatRegister f3, FloatRegister f2); // f1 = f3 * f2 - f1 ; double
|
||||
inline void z_maeb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2); // f1 = f3 * *(d2+x2+b2) + f1 ; float
|
||||
inline void z_madb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2); // f1 = f3 * *(d2+x2+b2) + f1 ; double
|
||||
inline void z_mseb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2); // f1 = f3 * *(d2+x2+b2) - f1 ; float
|
||||
inline void z_msdb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2); // f1 = f3 * *(d2+x2+b2) - f1 ; double
|
||||
inline void z_maeb(FloatRegister f1, FloatRegister f3, const Address& a);
|
||||
inline void z_madb(FloatRegister f1, FloatRegister f3, const Address& a);
|
||||
inline void z_mseb(FloatRegister f1, FloatRegister f3, const Address& a);
|
||||
inline void z_msdb(FloatRegister f1, FloatRegister f3, const Address& a);
|
||||
|
||||
// DIV
|
||||
inline void z_debr( FloatRegister f1, FloatRegister f2); // f1 = f1 / f2 ; float
|
||||
inline void z_ddbr( FloatRegister f1, FloatRegister f2); // f1 = f1 / f2 ; double
|
||||
|
||||
@ -777,6 +777,23 @@ inline void Assembler::z_meeb( FloatRegister r1, const Address& a)
|
||||
inline void Assembler::z_mdb( FloatRegister r1, const Address& a) { z_mdb( r1, a.disp(), a.indexOrR0(), a.baseOrR0()); }
|
||||
|
||||
|
||||
//---------------
|
||||
// MUL-ADD
|
||||
//---------------
|
||||
inline void Assembler::z_maebr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MAEBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );}
|
||||
inline void Assembler::z_madbr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MADBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );}
|
||||
inline void Assembler::z_msebr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MSEBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );}
|
||||
inline void Assembler::z_msdbr(FloatRegister f1, FloatRegister f3, FloatRegister f2) { emit_32( MSDBR_ZOPC | fregt(f1, 16, 32) | freg(f3, 24, 32) | freg(f2, 28, 32) );}
|
||||
inline void Assembler::z_maeb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MAEB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );}
|
||||
inline void Assembler::z_madb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MADB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );}
|
||||
inline void Assembler::z_mseb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MSEB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );}
|
||||
inline void Assembler::z_msdb(FloatRegister f1, FloatRegister f3, int64_t d2, Register x2, Register b2) { emit_48( MSDB_ZOPC | fregt(f1, 32, 48) | freg(f3, 8, 48) | uimm12(d2, 20, 48) | reg(x2, 12, 48) | regz(b2, 16, 48) );}
|
||||
inline void Assembler::z_maeb(FloatRegister f1, FloatRegister f3, const Address& a) { z_maeb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); }
|
||||
inline void Assembler::z_madb(FloatRegister f1, FloatRegister f3, const Address& a) { z_madb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); }
|
||||
inline void Assembler::z_mseb(FloatRegister f1, FloatRegister f3, const Address& a) { z_mseb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); }
|
||||
inline void Assembler::z_msdb(FloatRegister f1, FloatRegister f3, const Address& a) { z_msdb(f1, f3, a.disp(), a.indexOrR0(), a.baseOrR0()); }
|
||||
|
||||
|
||||
//---------------
|
||||
// DIV
|
||||
//---------------
|
||||
|
||||
@ -324,6 +324,22 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
||||
op->result_opr(),
|
||||
op->info());
|
||||
break;
|
||||
case lir_fmad: {
|
||||
const FloatRegister opr1 = op->in_opr1()->as_double_reg(),
|
||||
opr2 = op->in_opr2()->as_double_reg(),
|
||||
opr3 = op->in_opr3()->as_double_reg(),
|
||||
res = op->result_opr()->as_double_reg();
|
||||
__ z_madbr(opr3, opr1, opr2);
|
||||
if (res != opr3) { __ z_ldr(res, opr3); }
|
||||
} break;
|
||||
case lir_fmaf: {
|
||||
const FloatRegister opr1 = op->in_opr1()->as_float_reg(),
|
||||
opr2 = op->in_opr2()->as_float_reg(),
|
||||
opr3 = op->in_opr3()->as_float_reg(),
|
||||
res = op->result_opr()->as_float_reg();
|
||||
__ z_maebr(opr3, opr1, opr2);
|
||||
if (res != opr3) { __ z_ler(res, opr3); }
|
||||
} break;
|
||||
default: ShouldNotReachHere(); break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1237,7 +1237,28 @@ void LIRGenerator::do_update_CRC32C(Intrinsic* x) {
|
||||
}
|
||||
|
||||
void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
|
||||
fatal("FMA intrinsic is not implemented on this platform");
|
||||
assert(x->number_of_arguments() == 3, "wrong type");
|
||||
assert(UseFMA, "Needs FMA instructions support.");
|
||||
LIRItem value(x->argument_at(0), this);
|
||||
LIRItem value1(x->argument_at(1), this);
|
||||
LIRItem value2(x->argument_at(2), this);
|
||||
|
||||
value2.set_destroys_register();
|
||||
|
||||
value.load_item();
|
||||
value1.load_item();
|
||||
value2.load_item();
|
||||
|
||||
LIR_Opr calc_input = value.result();
|
||||
LIR_Opr calc_input1 = value1.result();
|
||||
LIR_Opr calc_input2 = value2.result();
|
||||
LIR_Opr calc_result = rlock_result(x);
|
||||
|
||||
switch (x->id()) {
|
||||
case vmIntrinsics::_fmaD: __ fmad(calc_input, calc_input1, calc_input2, calc_result); break;
|
||||
case vmIntrinsics::_fmaF: __ fmaf(calc_input, calc_input1, calc_input2, calc_result); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
|
||||
|
||||
@ -7249,6 +7249,171 @@ instruct mulD_reg_mem(regD dst, memoryRX src)%{
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// Multiply-Accumulate
|
||||
// src1 * src2 + dst
|
||||
instruct maddF_reg_reg(regF dst, regF src1, regF src2) %{
|
||||
match(Set dst (FmaF dst (Binary src1 src2)));
|
||||
// CC unchanged by MUL-ADD.
|
||||
ins_cost(ALU_REG_COST);
|
||||
size(4);
|
||||
format %{ "MAEBR $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_maebr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 + dst
|
||||
instruct maddD_reg_reg(regD dst, regD src1, regD src2) %{
|
||||
match(Set dst (FmaD dst (Binary src1 src2)));
|
||||
// CC unchanged by MUL-ADD.
|
||||
ins_cost(ALU_REG_COST);
|
||||
size(4);
|
||||
format %{ "MADBR $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_madbr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 - dst
|
||||
instruct msubF_reg_reg(regF dst, regF src1, regF src2) %{
|
||||
match(Set dst (FmaF (NegF dst) (Binary src1 src2)));
|
||||
// CC unchanged by MUL-SUB.
|
||||
ins_cost(ALU_REG_COST);
|
||||
size(4);
|
||||
format %{ "MSEBR $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_msebr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 - dst
|
||||
instruct msubD_reg_reg(regD dst, regD src1, regD src2) %{
|
||||
match(Set dst (FmaD (NegD dst) (Binary src1 src2)));
|
||||
// CC unchanged by MUL-SUB.
|
||||
ins_cost(ALU_REG_COST);
|
||||
size(4);
|
||||
format %{ "MSDBR $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_msdbr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 + dst
|
||||
instruct maddF_reg_mem(regF dst, regF src1, memoryRX src2) %{
|
||||
match(Set dst (FmaF dst (Binary src1 (LoadF src2))));
|
||||
// CC unchanged by MUL-ADD.
|
||||
ins_cost(ALU_MEMORY_COST);
|
||||
size(6);
|
||||
format %{ "MAEB $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_maeb($dst$$FloatRegister, $src1$$FloatRegister,
|
||||
Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 + dst
|
||||
instruct maddD_reg_mem(regD dst, regD src1, memoryRX src2) %{
|
||||
match(Set dst (FmaD dst (Binary src1 (LoadD src2))));
|
||||
// CC unchanged by MUL-ADD.
|
||||
ins_cost(ALU_MEMORY_COST);
|
||||
size(6);
|
||||
format %{ "MADB $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_madb($dst$$FloatRegister, $src1$$FloatRegister,
|
||||
Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 - dst
|
||||
instruct msubF_reg_mem(regF dst, regF src1, memoryRX src2) %{
|
||||
match(Set dst (FmaF (NegF dst) (Binary src1 (LoadF src2))));
|
||||
// CC unchanged by MUL-SUB.
|
||||
ins_cost(ALU_MEMORY_COST);
|
||||
size(6);
|
||||
format %{ "MSEB $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_mseb($dst$$FloatRegister, $src1$$FloatRegister,
|
||||
Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 - dst
|
||||
instruct msubD_reg_mem(regD dst, regD src1, memoryRX src2) %{
|
||||
match(Set dst (FmaD (NegD dst) (Binary src1 (LoadD src2))));
|
||||
// CC unchanged by MUL-SUB.
|
||||
ins_cost(ALU_MEMORY_COST);
|
||||
size(6);
|
||||
format %{ "MSDB $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_msdb($dst$$FloatRegister, $src1$$FloatRegister,
|
||||
Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 + dst
|
||||
instruct maddF_mem_reg(regF dst, memoryRX src1, regF src2) %{
|
||||
match(Set dst (FmaF dst (Binary (LoadF src1) src2)));
|
||||
// CC unchanged by MUL-ADD.
|
||||
ins_cost(ALU_MEMORY_COST);
|
||||
size(6);
|
||||
format %{ "MAEB $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_maeb($dst$$FloatRegister, $src2$$FloatRegister,
|
||||
Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 + dst
|
||||
instruct maddD_mem_reg(regD dst, memoryRX src1, regD src2) %{
|
||||
match(Set dst (FmaD dst (Binary (LoadD src1) src2)));
|
||||
// CC unchanged by MUL-ADD.
|
||||
ins_cost(ALU_MEMORY_COST);
|
||||
size(6);
|
||||
format %{ "MADB $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_madb($dst$$FloatRegister, $src2$$FloatRegister,
|
||||
Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 - dst
|
||||
instruct msubF_mem_reg(regF dst, memoryRX src1, regF src2) %{
|
||||
match(Set dst (FmaF (NegF dst) (Binary (LoadF src1) src2)));
|
||||
// CC unchanged by MUL-SUB.
|
||||
ins_cost(ALU_MEMORY_COST);
|
||||
size(6);
|
||||
format %{ "MSEB $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_mseb($dst$$FloatRegister, $src2$$FloatRegister,
|
||||
Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// src1 * src2 - dst
|
||||
instruct msubD_mem_reg(regD dst, memoryRX src1, regD src2) %{
|
||||
match(Set dst (FmaD (NegD dst) (Binary (LoadD src1) src2)));
|
||||
// CC unchanged by MUL-SUB.
|
||||
ins_cost(ALU_MEMORY_COST);
|
||||
size(6);
|
||||
format %{ "MSDB $dst, $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ z_msdb($dst$$FloatRegister, $src2$$FloatRegister,
|
||||
Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
|
||||
%}
|
||||
ins_pipe(pipe_class_dummy);
|
||||
%}
|
||||
|
||||
// DIV
|
||||
|
||||
// Div float single precision
|
||||
|
||||
@ -2038,15 +2038,15 @@ class StubGenerator: public StubCodeGenerator {
|
||||
generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, true);
|
||||
|
||||
// Prepare other registers for instruction.
|
||||
// __ z_lgr(src, from); // Not needed, registers are the same.
|
||||
// __ z_lgr(src, from); // Not needed, registers are the same.
|
||||
__ z_lgr(dst, to);
|
||||
__ z_lgr(srclen, msglen);
|
||||
__ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required.
|
||||
|
||||
__ kmc(dst, src); // Decipher the message.
|
||||
__ kmc(dst, src); // Decipher the message.
|
||||
|
||||
generate_pop_parmBlk(keylen, parmBlk, key, cv);
|
||||
|
||||
__ z_lgr(Z_RET, msglen);
|
||||
__ z_llgfr(Z_RET, msglen); // We pass the offsets as ints, not as longs as required.
|
||||
__ z_br(Z_R14);
|
||||
|
||||
return __ addr_at(start_off);
|
||||
|
||||
@ -1297,36 +1297,96 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
// Math function, frame manager must set up an interpreter state, etc.
|
||||
address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
|
||||
|
||||
if (!InlineIntrinsics) { return NULL; } // Generate a vanilla entry.
|
||||
// Decide what to do: Use same platform specific instructions and runtime calls as compilers.
|
||||
bool use_instruction = false;
|
||||
address runtime_entry = NULL;
|
||||
int num_args = 1;
|
||||
bool double_precision = true;
|
||||
|
||||
// Only support absolute value and square root.
|
||||
if (kind != Interpreter::java_lang_math_abs && kind != Interpreter::java_lang_math_sqrt) {
|
||||
return NULL;
|
||||
// s390 specific:
|
||||
switch (kind) {
|
||||
case Interpreter::java_lang_math_sqrt:
|
||||
case Interpreter::java_lang_math_abs: use_instruction = true; break;
|
||||
case Interpreter::java_lang_math_fmaF:
|
||||
case Interpreter::java_lang_math_fmaD: use_instruction = UseFMA; break;
|
||||
default: break; // Fall back to runtime call.
|
||||
}
|
||||
|
||||
BLOCK_COMMENT("math_entry {");
|
||||
switch (kind) {
|
||||
case Interpreter::java_lang_math_sin : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsin); break;
|
||||
case Interpreter::java_lang_math_cos : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dcos); break;
|
||||
case Interpreter::java_lang_math_tan : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dtan); break;
|
||||
case Interpreter::java_lang_math_abs : /* run interpreted */ break;
|
||||
case Interpreter::java_lang_math_sqrt : /* runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsqrt); not available */ break;
|
||||
case Interpreter::java_lang_math_log : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog); break;
|
||||
case Interpreter::java_lang_math_log10: runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10); break;
|
||||
case Interpreter::java_lang_math_pow : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dpow); num_args = 2; break;
|
||||
case Interpreter::java_lang_math_exp : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dexp); break;
|
||||
case Interpreter::java_lang_math_fmaF : /* run interpreted */ num_args = 3; double_precision = false; break;
|
||||
case Interpreter::java_lang_math_fmaD : /* run interpreted */ num_args = 3; break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
|
||||
address math_entry = __ pc();
|
||||
// Use normal entry if neither instruction nor runtime call is used.
|
||||
if (!use_instruction && runtime_entry == NULL) return NULL;
|
||||
|
||||
if (kind == Interpreter::java_lang_math_abs) {
|
||||
// Load operand from stack.
|
||||
__ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize));
|
||||
__ z_lpdbr(Z_FRET);
|
||||
address entry = __ pc();
|
||||
|
||||
if (use_instruction) {
|
||||
switch (kind) {
|
||||
case Interpreter::java_lang_math_sqrt:
|
||||
// Can use memory operand directly.
|
||||
__ z_sqdb(Z_FRET, Interpreter::stackElementSize, Z_esp);
|
||||
break;
|
||||
case Interpreter::java_lang_math_abs:
|
||||
// Load operand from stack.
|
||||
__ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize));
|
||||
__ z_lpdbr(Z_FRET);
|
||||
break;
|
||||
case Interpreter::java_lang_math_fmaF:
|
||||
__ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize)); // result reg = arg3
|
||||
__ mem2freg_opt(Z_FARG2, Address(Z_esp, 3 * Interpreter::stackElementSize)); // arg1
|
||||
__ z_maeb(Z_FRET, Z_FARG2, Address(Z_esp, 2 * Interpreter::stackElementSize));
|
||||
break;
|
||||
case Interpreter::java_lang_math_fmaD:
|
||||
__ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize)); // result reg = arg3
|
||||
__ mem2freg_opt(Z_FARG2, Address(Z_esp, 5 * Interpreter::stackElementSize)); // arg1
|
||||
__ z_madb(Z_FRET, Z_FARG2, Address(Z_esp, 3 * Interpreter::stackElementSize));
|
||||
break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
} else {
|
||||
// sqrt
|
||||
// Can use memory operand directly.
|
||||
__ z_sqdb(Z_FRET, Interpreter::stackElementSize, Z_esp);
|
||||
// Load arguments
|
||||
assert(num_args <= 4, "passed in registers");
|
||||
if (double_precision) {
|
||||
int offset = (2 * num_args - 1) * Interpreter::stackElementSize;
|
||||
for (int i = 0; i < num_args; ++i) {
|
||||
__ mem2freg_opt(as_FloatRegister(Z_FARG1->encoding() + 2 * i), Address(Z_esp, offset));
|
||||
offset -= 2 * Interpreter::stackElementSize;
|
||||
}
|
||||
} else {
|
||||
int offset = num_args * Interpreter::stackElementSize;
|
||||
for (int i = 0; i < num_args; ++i) {
|
||||
__ mem2freg_opt(as_FloatRegister(Z_FARG1->encoding() + 2 * i), Address(Z_esp, offset));
|
||||
offset -= Interpreter::stackElementSize;
|
||||
}
|
||||
}
|
||||
// Call runtime
|
||||
__ save_return_pc(); // Save Z_R14.
|
||||
__ push_frame_abi160(0); // Without new frame the RT call could overwrite the saved Z_R14.
|
||||
|
||||
__ call_VM_leaf(runtime_entry);
|
||||
|
||||
__ pop_frame();
|
||||
__ restore_return_pc(); // Restore Z_R14.
|
||||
}
|
||||
|
||||
// Restore caller sp for c2i case.
|
||||
// Pop c2i arguments (if any) off when we return.
|
||||
__ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started.
|
||||
|
||||
// We are done, return.
|
||||
__ z_br(Z_R14);
|
||||
|
||||
BLOCK_COMMENT("} math_entry");
|
||||
|
||||
return math_entry;
|
||||
return entry;
|
||||
}
|
||||
|
||||
// Interpreter stub for calling a native method. (asm interpreter).
|
||||
|
||||
@ -155,9 +155,8 @@ void VM_Version::initialize() {
|
||||
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
|
||||
}
|
||||
|
||||
if (UseFMA) {
|
||||
warning("FMA instructions are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseFMA, false);
|
||||
if (FLAG_IS_DEFAULT(UseFMA)) {
|
||||
FLAG_SET_DEFAULT(UseFMA, true);
|
||||
}
|
||||
|
||||
// On z/Architecture, we take UseSHA as the general switch to enable/disable the SHA intrinsics.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user