8171244: PPC64: Make interpreter's math entries consistent with C1 and C2 and support FMA
Reviewed-by: kvn, goetz
This commit is contained in:
parent
d652c70de6
commit
c44e860576
@ -51,19 +51,25 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) {
|
||||
return i;
|
||||
}
|
||||
|
||||
// Support abs and sqrt like in compiler.
|
||||
// For others we can use a normal (native) entry.
|
||||
bool AbstractInterpreter::math_entry_available(AbstractInterpreter::MethodKind kind) {
|
||||
if (!InlineIntrinsics) return false;
|
||||
|
||||
return ((kind==Interpreter::java_lang_math_sqrt && VM_Version::has_fsqrt()) ||
|
||||
(kind==Interpreter::java_lang_math_abs));
|
||||
}
|
||||
|
||||
// These should never be compiled since the interpreter will prefer
|
||||
// the compiled version to the intrinsic version.
|
||||
bool AbstractInterpreter::can_be_compiled(methodHandle m) {
|
||||
return !math_entry_available(method_kind(m));
|
||||
switch (method_kind(m)) {
|
||||
case Interpreter::java_lang_math_sin : // fall thru
|
||||
case Interpreter::java_lang_math_cos : // fall thru
|
||||
case Interpreter::java_lang_math_tan : // fall thru
|
||||
case Interpreter::java_lang_math_abs : // fall thru
|
||||
case Interpreter::java_lang_math_log : // fall thru
|
||||
case Interpreter::java_lang_math_log10 : // fall thru
|
||||
case Interpreter::java_lang_math_sqrt : // fall thru
|
||||
case Interpreter::java_lang_math_pow : // fall thru
|
||||
case Interpreter::java_lang_math_exp : // fall thru
|
||||
case Interpreter::java_lang_math_fmaD : // fall thru
|
||||
case Interpreter::java_lang_math_fmaF :
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// How much stack a method activation needs in stack slots.
|
||||
|
@ -460,16 +460,15 @@ class Assembler : public AbstractAssembler {
|
||||
FCTIWZ_OPCODE = (63u << OPCODE_SHIFT | 15u << 1),
|
||||
FRSP_OPCODE = (63u << OPCODE_SHIFT | 12u << 1),
|
||||
|
||||
// WARNING: using fmadd results in a non-compliant vm. Some floating
|
||||
// point tck tests will fail.
|
||||
FMADD_OPCODE = (59u << OPCODE_SHIFT | 29u << 1),
|
||||
DMADD_OPCODE = (63u << OPCODE_SHIFT | 29u << 1),
|
||||
FMSUB_OPCODE = (59u << OPCODE_SHIFT | 28u << 1),
|
||||
DMSUB_OPCODE = (63u << OPCODE_SHIFT | 28u << 1),
|
||||
FNMADD_OPCODE = (59u << OPCODE_SHIFT | 31u << 1),
|
||||
DNMADD_OPCODE = (63u << OPCODE_SHIFT | 31u << 1),
|
||||
FNMSUB_OPCODE = (59u << OPCODE_SHIFT | 30u << 1),
|
||||
DNMSUB_OPCODE = (63u << OPCODE_SHIFT | 30u << 1),
|
||||
// Fused multiply-accumulate instructions.
|
||||
FMADD_OPCODE = (63u << OPCODE_SHIFT | 29u << 1),
|
||||
FMADDS_OPCODE = (59u << OPCODE_SHIFT | 29u << 1),
|
||||
FMSUB_OPCODE = (63u << OPCODE_SHIFT | 28u << 1),
|
||||
FMSUBS_OPCODE = (59u << OPCODE_SHIFT | 28u << 1),
|
||||
FNMADD_OPCODE = (63u << OPCODE_SHIFT | 31u << 1),
|
||||
FNMADDS_OPCODE = (59u << OPCODE_SHIFT | 31u << 1),
|
||||
FNMSUB_OPCODE = (63u << OPCODE_SHIFT | 30u << 1),
|
||||
FNMSUBS_OPCODE = (59u << OPCODE_SHIFT | 30u << 1),
|
||||
|
||||
LFD_OPCODE = (50u << OPCODE_SHIFT | 00u << 1),
|
||||
LFDU_OPCODE = (51u << OPCODE_SHIFT | 00u << 1),
|
||||
@ -1939,6 +1938,26 @@ class Assembler : public AbstractAssembler {
|
||||
inline void fdivs( FloatRegister d, FloatRegister a, FloatRegister b);
|
||||
inline void fdivs_(FloatRegister d, FloatRegister a, FloatRegister b);
|
||||
|
||||
// Fused multiply-accumulate instructions.
|
||||
// WARNING: Use only when rounding between the 2 parts is not desired.
|
||||
// Some floating point tck tests will fail if used incorrectly.
|
||||
inline void fmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fmadds_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fmsubs_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fnmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fnmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fnmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fnmadds_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fnmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fnmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fnmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
inline void fnmsubs_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
|
||||
|
||||
// PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions
|
||||
inline void frsp( FloatRegister d, FloatRegister b);
|
||||
inline void fctid( FloatRegister d, FloatRegister b);
|
||||
|
@ -700,6 +700,26 @@ inline void Assembler::fdiv_( FloatRegister d, FloatRegister a, FloatRegister b)
|
||||
inline void Assembler::fdivs( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIVS_OPCODE | frt(d) | fra(a) | frb(b) | rc(0)); }
|
||||
inline void Assembler::fdivs_(FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIVS_OPCODE | frt(d) | fra(a) | frb(b) | rc(1)); }
|
||||
|
||||
// Fused multiply-accumulate instructions.
|
||||
// WARNING: Use only when rounding between the 2 parts is not desired.
|
||||
// Some floating point tck tests will fail if used incorrectly.
|
||||
inline void Assembler::fmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
|
||||
inline void Assembler::fmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
|
||||
inline void Assembler::fmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
|
||||
inline void Assembler::fmadds_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
|
||||
inline void Assembler::fmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
|
||||
inline void Assembler::fmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
|
||||
inline void Assembler::fmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
|
||||
inline void Assembler::fmsubs_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
|
||||
inline void Assembler::fnmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
|
||||
inline void Assembler::fnmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
|
||||
inline void Assembler::fnmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
|
||||
inline void Assembler::fnmadds_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
|
||||
inline void Assembler::fnmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
|
||||
inline void Assembler::fnmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
|
||||
inline void Assembler::fnmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
|
||||
inline void Assembler::fnmsubs_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
|
||||
|
||||
// PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions
|
||||
inline void Assembler::frsp( FloatRegister d, FloatRegister b) { emit_int32( FRSP_OPCODE | frt(d) | frb(b) | rc(0)); }
|
||||
inline void Assembler::fctid( FloatRegister d, FloatRegister b) { emit_int32( FCTID_OPCODE | frt(d) | frb(b) | rc(0)); }
|
||||
|
@ -292,28 +292,28 @@ void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo *info) {
|
||||
}
|
||||
|
||||
|
||||
void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
||||
const bool is_int = op->result_opr()->is_single_cpu();
|
||||
Register Rdividend = is_int ? op->in_opr1()->as_register() : op->in_opr1()->as_register_lo();
|
||||
void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) {
|
||||
const bool is_int = result->is_single_cpu();
|
||||
Register Rdividend = is_int ? left->as_register() : left->as_register_lo();
|
||||
Register Rdivisor = noreg;
|
||||
Register Rscratch = op->in_opr3()->as_register();
|
||||
Register Rresult = is_int ? op->result_opr()->as_register() : op->result_opr()->as_register_lo();
|
||||
Register Rscratch = temp->as_register();
|
||||
Register Rresult = is_int ? result->as_register() : result->as_register_lo();
|
||||
long divisor = -1;
|
||||
|
||||
if (op->in_opr2()->is_register()) {
|
||||
Rdivisor = is_int ? op->in_opr2()->as_register() : op->in_opr2()->as_register_lo();
|
||||
if (right->is_register()) {
|
||||
Rdivisor = is_int ? right->as_register() : right->as_register_lo();
|
||||
} else {
|
||||
divisor = is_int ? op->in_opr2()->as_constant_ptr()->as_jint()
|
||||
: op->in_opr2()->as_constant_ptr()->as_jlong();
|
||||
divisor = is_int ? right->as_constant_ptr()->as_jint()
|
||||
: right->as_constant_ptr()->as_jlong();
|
||||
}
|
||||
|
||||
assert(Rdividend != Rscratch, "");
|
||||
assert(Rdivisor != Rscratch, "");
|
||||
assert(op->code() == lir_idiv || op->code() == lir_irem, "Must be irem or idiv");
|
||||
assert(code == lir_idiv || code == lir_irem, "Must be irem or idiv");
|
||||
|
||||
if (Rdivisor == noreg) {
|
||||
if (divisor == 1) { // stupid, but can happen
|
||||
if (op->code() == lir_idiv) {
|
||||
if (code == lir_idiv) {
|
||||
__ mr_if_needed(Rresult, Rdividend);
|
||||
} else {
|
||||
__ li(Rresult, 0);
|
||||
@ -340,7 +340,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
||||
}
|
||||
__ add(Rscratch, Rdividend, Rscratch);
|
||||
|
||||
if (op->code() == lir_idiv) {
|
||||
if (code == lir_idiv) {
|
||||
if (is_int) {
|
||||
__ srawi(Rresult, Rscratch, log2);
|
||||
} else {
|
||||
@ -352,7 +352,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
||||
}
|
||||
|
||||
} else if (divisor == -1) {
|
||||
if (op->code() == lir_idiv) {
|
||||
if (code == lir_idiv) {
|
||||
__ neg(Rresult, Rdividend);
|
||||
} else {
|
||||
__ li(Rresult, 0);
|
||||
@ -360,7 +360,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
||||
|
||||
} else {
|
||||
__ load_const_optimized(Rscratch, divisor);
|
||||
if (op->code() == lir_idiv) {
|
||||
if (code == lir_idiv) {
|
||||
if (is_int) {
|
||||
__ divw(Rresult, Rdividend, Rscratch); // Can't divide minint/-1.
|
||||
} else {
|
||||
@ -389,7 +389,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
||||
__ cmpdi(CCR0, Rdivisor, -1);
|
||||
}
|
||||
__ bne(CCR0, regular);
|
||||
if (op->code() == lir_idiv) {
|
||||
if (code == lir_idiv) {
|
||||
__ neg(Rresult, Rdividend);
|
||||
__ b(done);
|
||||
__ bind(regular);
|
||||
@ -415,6 +415,26 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
||||
}
|
||||
|
||||
|
||||
void LIR_Assembler::emit_op3(LIR_Op3* op) {
|
||||
switch (op->code()) {
|
||||
case lir_idiv:
|
||||
case lir_irem:
|
||||
arithmetic_idiv(op->code(), op->in_opr1(), op->in_opr2(), op->in_opr3(),
|
||||
op->result_opr(), op->info());
|
||||
break;
|
||||
case lir_fmad:
|
||||
__ fmadd(op->result_opr()->as_double_reg(), op->in_opr1()->as_double_reg(),
|
||||
op->in_opr2()->as_double_reg(), op->in_opr3()->as_double_reg());
|
||||
break;
|
||||
case lir_fmaf:
|
||||
__ fmadds(op->result_opr()->as_float_reg(), op->in_opr1()->as_float_reg(),
|
||||
op->in_opr2()->as_float_reg(), op->in_opr3()->as_float_reg());
|
||||
break;
|
||||
default: ShouldNotReachHere(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) {
|
||||
#ifdef ASSERT
|
||||
assert(op->block() == NULL || op->block()->label() == op->label(), "wrong label");
|
||||
|
@ -1435,7 +1435,26 @@ void LIRGenerator::do_update_CRC32(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);
|
||||
|
||||
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) {
|
||||
|
@ -9569,6 +9569,117 @@ instruct roundFloat_nop(regF dst) %{
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
|
||||
// Multiply-Accumulate
|
||||
// src1 * src2 + src3
|
||||
instruct maddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
|
||||
match(Set dst (FmaF src3 (Binary src1 src2)));
|
||||
|
||||
format %{ "FMADDS $dst, $src1, $src2, $src3" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_fmadds);
|
||||
__ fmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// src1 * src2 + src3
|
||||
instruct maddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
|
||||
match(Set dst (FmaD src3 (Binary src1 src2)));
|
||||
|
||||
format %{ "FMADD $dst, $src1, $src2, $src3" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_fmadd);
|
||||
__ fmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// -src1 * src2 + src3 = -(src1*src2-src3)
|
||||
instruct mnsubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
|
||||
match(Set dst (FmaF src3 (Binary (NegF src1) src2)));
|
||||
match(Set dst (FmaF src3 (Binary src1 (NegF src2))));
|
||||
|
||||
format %{ "FNMSUBS $dst, $src1, $src2, $src3" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_fnmsubs);
|
||||
__ fnmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// -src1 * src2 + src3 = -(src1*src2-src3)
|
||||
instruct mnsubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
|
||||
match(Set dst (FmaD src3 (Binary (NegD src1) src2)));
|
||||
match(Set dst (FmaD src3 (Binary src1 (NegD src2))));
|
||||
|
||||
format %{ "FNMSUB $dst, $src1, $src2, $src3" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_fnmsub);
|
||||
__ fnmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// -src1 * src2 - src3 = -(src1*src2+src3)
|
||||
instruct mnaddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
|
||||
match(Set dst (FmaF (NegF src3) (Binary (NegF src1) src2)));
|
||||
match(Set dst (FmaF (NegF src3) (Binary src1 (NegF src2))));
|
||||
|
||||
format %{ "FNMADDS $dst, $src1, $src2, $src3" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_fnmadds);
|
||||
__ fnmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// -src1 * src2 - src3 = -(src1*src2+src3)
|
||||
instruct mnaddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
|
||||
match(Set dst (FmaD (NegD src3) (Binary (NegD src1) src2)));
|
||||
match(Set dst (FmaD (NegD src3) (Binary src1 (NegD src2))));
|
||||
|
||||
format %{ "FNMADD $dst, $src1, $src2, $src3" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_fnmadd);
|
||||
__ fnmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// src1 * src2 - src3
|
||||
instruct msubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
|
||||
match(Set dst (FmaF (NegF src3) (Binary src1 src2)));
|
||||
|
||||
format %{ "FMSUBS $dst, $src1, $src2, $src3" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_fmsubs);
|
||||
__ fmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// src1 * src2 - src3
|
||||
instruct msubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
|
||||
match(Set dst (FmaD (NegD src3) (Binary src1 src2)));
|
||||
|
||||
format %{ "FMSUB $dst, $src1, $src2, $src3" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_fmsub);
|
||||
__ fmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
|
||||
//----------Logical Instructions-----------------------------------------------
|
||||
|
||||
// And Instructions
|
||||
|
@ -1134,14 +1134,57 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist
|
||||
// End of helpers
|
||||
|
||||
address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
|
||||
if (!Interpreter::math_entry_available(kind)) {
|
||||
NOT_PRODUCT(__ should_not_reach_here();)
|
||||
return NULL;
|
||||
|
||||
// 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;
|
||||
|
||||
// PPC64 specific:
|
||||
switch (kind) {
|
||||
case Interpreter::java_lang_math_sqrt: use_instruction = VM_Version::has_fsqrt(); break;
|
||||
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.
|
||||
}
|
||||
|
||||
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); 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();
|
||||
}
|
||||
|
||||
// Use normal entry if neither instruction nor runtime call is used.
|
||||
if (!use_instruction && runtime_entry == NULL) return NULL;
|
||||
|
||||
address entry = __ pc();
|
||||
|
||||
__ lfd(F1_RET, Interpreter::stackElementSize, R15_esp);
|
||||
// Load arguments
|
||||
assert(num_args <= 13, "passed in registers");
|
||||
if (double_precision) {
|
||||
int offset = (2 * num_args - 1) * Interpreter::stackElementSize;
|
||||
for (int i = 0; i < num_args; ++i) {
|
||||
__ lfd(as_FloatRegister(F1_ARG1->encoding() + i), offset, R15_esp);
|
||||
offset -= 2 * Interpreter::stackElementSize;
|
||||
}
|
||||
} else {
|
||||
int offset = num_args * Interpreter::stackElementSize;
|
||||
for (int i = 0; i < num_args; ++i) {
|
||||
__ lfs(as_FloatRegister(F1_ARG1->encoding() + i), offset, R15_esp);
|
||||
offset -= Interpreter::stackElementSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Pop c2i arguments (if any) off when we return.
|
||||
#ifdef ASSERT
|
||||
@ -1152,15 +1195,30 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
|
||||
#endif // ASSERT
|
||||
__ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
|
||||
|
||||
if (kind == Interpreter::java_lang_math_sqrt) {
|
||||
__ fsqrt(F1_RET, F1_RET);
|
||||
} else if (kind == Interpreter::java_lang_math_abs) {
|
||||
__ fabs(F1_RET, F1_RET);
|
||||
if (use_instruction) {
|
||||
switch (kind) {
|
||||
case Interpreter::java_lang_math_sqrt: __ fsqrt(F1_RET, F1); break;
|
||||
case Interpreter::java_lang_math_abs: __ fabs(F1_RET, F1); break;
|
||||
case Interpreter::java_lang_math_fmaF: __ fmadds(F1_RET, F1, F2, F3); break;
|
||||
case Interpreter::java_lang_math_fmaD: __ fmadd(F1_RET, F1, F2, F3); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
// Comment: Can use tail call if the unextended frame is always C ABI compliant:
|
||||
//__ load_const_optimized(R12_scratch2, runtime_entry, R0);
|
||||
//__ call_c_and_return_to_caller(R12_scratch2);
|
||||
|
||||
// Push a new C frame and save LR.
|
||||
__ save_LR_CR(R0);
|
||||
__ push_frame_reg_args(0, R11_scratch1);
|
||||
|
||||
__ call_VM_leaf(runtime_entry);
|
||||
|
||||
// Pop the C frame and restore LR.
|
||||
__ pop_frame();
|
||||
__ restore_LR_CR(R0);
|
||||
}
|
||||
|
||||
// And we're done.
|
||||
__ blr();
|
||||
|
||||
__ flush();
|
||||
|
@ -230,9 +230,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);
|
||||
}
|
||||
|
||||
if (UseSHA) {
|
||||
|
@ -299,10 +299,6 @@ class AbstractInterpreter: AllStatic {
|
||||
}
|
||||
|
||||
static void initialize_method_handle_entries();
|
||||
|
||||
// PPC-only: Support abs and sqrt like in compiler.
|
||||
// For others we can use a normal (native) entry.
|
||||
static bool math_entry_available(MethodKind kind);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user