< 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,1334 **** // 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. ! // Only support absolute value and square root. ! if (kind != Interpreter::java_lang_math_abs && kind != Interpreter::java_lang_math_sqrt) { ! return NULL; } ! BLOCK_COMMENT("math_entry {"); ! address math_entry = __ pc(); ! if (kind == Interpreter::java_lang_math_abs) { // Load operand from stack. __ mem2freg_opt(Z_FRET, Address(Z_esp, Interpreter::stackElementSize)); __ z_lpdbr(Z_FRET); } else { ! // sqrt ! // Can use memory operand directly. ! __ z_sqdb(Z_FRET, Interpreter::stackElementSize, Z_esp); } ! // Restore caller sp for c2i case. __ 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; } // 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. --- 1295,1394 ---- // Various method entries // Math function, frame manager must set up an interpreter state, etc. address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { ! // 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. ! } ! 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(); } ! // Use normal entry if neither instruction nor runtime call is used. ! if (!use_instruction && runtime_entry == NULL) return NULL; ! 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 { ! // 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. ! } ! ! // 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. __ z_br(Z_R14); ! 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 >