< prev index next >
src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp
Print this page
rev 12410 : 8171398: s390x: Make interpreter's math entries consistent with C1 and C2 and support FMA
Reviewed-by:
@@ -1295,40 +1295,100 @@
// Various method entries
// 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;
+
+ // 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.
+ }
- // Only support absolute value and square root.
- if (kind != Interpreter::java_lang_math_abs && kind != Interpreter::java_lang_math_sqrt) {
- return NULL;
+ 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();
}
- BLOCK_COMMENT("math_entry {");
+ // Use normal entry if neither instruction nor runtime call is used.
+ if (!use_instruction && runtime_entry == NULL) return NULL;
- address math_entry = __ pc();
+ address entry = __ pc();
- if (kind == Interpreter::java_lang_math_abs) {
+ 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);
- // Restore caller sp for c2i case.
+ __ pop_frame();
+ __ restore_return_pc(); // Restore Z_R14.
+ }
+
+ // 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).
// This sets up a somewhat different looking stack for calling the
// native method than the typical interpreter frame setup.
< prev index next >