/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "interpreter/interpreter_common.h" #include "interpreter/interpreter_intrinsics.h" namespace art { namespace interpreter { #define BINARY_SIMPLE_INTRINSIC(name, op, get, set, offset) \ static ALWAYS_INLINE bool name(ShadowFrame* shadow_frame, \ const Instruction* inst, \ uint16_t inst_data, \ JValue* result_register) \ REQUIRES_SHARED(Locks::mutator_lock_) { \ uint32_t arg[Instruction::kMaxVarArgRegs] = {}; \ inst->GetVarArgs(arg, inst_data); \ result_register->set(op(shadow_frame->get(arg[0]), shadow_frame->get(arg[offset]))); \ return true; \ } #define UNARY_SIMPLE_INTRINSIC(name, op, get, set) \ static ALWAYS_INLINE bool name(ShadowFrame* shadow_frame, \ const Instruction* inst, \ uint16_t inst_data, \ JValue* result_register) \ REQUIRES_SHARED(Locks::mutator_lock_) { \ uint32_t arg[Instruction::kMaxVarArgRegs] = {}; \ inst->GetVarArgs(arg, inst_data); \ result_register->set(op(shadow_frame->get(arg[0]))); \ return true; \ } // java.lang.Math.min(II)I BINARY_SIMPLE_INTRINSIC(MterpMathMinIntInt, std::min, GetVReg, SetI, 1); // java.lang.Math.min(JJ)J BINARY_SIMPLE_INTRINSIC(MterpMathMinLongLong, std::min, GetVRegLong, SetJ, 2); // java.lang.Math.max(II)I BINARY_SIMPLE_INTRINSIC(MterpMathMaxIntInt, std::max, GetVReg, SetI, 1); // java.lang.Math.max(JJ)J BINARY_SIMPLE_INTRINSIC(MterpMathMaxLongLong, std::max, GetVRegLong, SetJ, 2); // java.lang.Math.abs(I)I UNARY_SIMPLE_INTRINSIC(MterpMathAbsInt, std::abs, GetVReg, SetI); // java.lang.Math.abs(J)J UNARY_SIMPLE_INTRINSIC(MterpMathAbsLong, std::abs, GetVRegLong, SetJ); // java.lang.Math.abs(F)F UNARY_SIMPLE_INTRINSIC(MterpMathAbsFloat, 0x7fffffff&, GetVReg, SetI); // java.lang.Math.abs(D)D UNARY_SIMPLE_INTRINSIC(MterpMathAbsDouble, INT64_C(0x7fffffffffffffff)&, GetVRegLong, SetJ); // java.lang.Math.sqrt(D)D UNARY_SIMPLE_INTRINSIC(MterpMathSqrt, std::sqrt, GetVRegDouble, SetD); // java.lang.Math.ceil(D)D UNARY_SIMPLE_INTRINSIC(MterpMathCeil, std::ceil, GetVRegDouble, SetD); // java.lang.Math.floor(D)D UNARY_SIMPLE_INTRINSIC(MterpMathFloor, std::floor, GetVRegDouble, SetD); // java.lang.Math.sin(D)D UNARY_SIMPLE_INTRINSIC(MterpMathSin, std::sin, GetVRegDouble, SetD); // java.lang.Math.cos(D)D UNARY_SIMPLE_INTRINSIC(MterpMathCos, std::cos, GetVRegDouble, SetD); // java.lang.Math.tan(D)D UNARY_SIMPLE_INTRINSIC(MterpMathTan, std::tan, GetVRegDouble, SetD); // java.lang.Math.asin(D)D UNARY_SIMPLE_INTRINSIC(MterpMathAsin, std::asin, GetVRegDouble, SetD); // java.lang.Math.acos(D)D UNARY_SIMPLE_INTRINSIC(MterpMathAcos, std::acos, GetVRegDouble, SetD); // java.lang.Math.atan(D)D UNARY_SIMPLE_INTRINSIC(MterpMathAtan, std::atan, GetVRegDouble, SetD); #define INTRINSIC_CASE(name) \ case Intrinsics::k##name: \ res = Mterp##name(shadow_frame, inst, inst_data, result_register); \ break; bool MterpHandleIntrinsic(ShadowFrame* shadow_frame, ArtMethod* const called_method, const Instruction* inst, uint16_t inst_data, JValue* result_register) REQUIRES_SHARED(Locks::mutator_lock_) { Intrinsics intrinsic = static_cast(called_method->GetIntrinsic()); bool res = false; // Assume failure switch (intrinsic) { INTRINSIC_CASE(MathMinIntInt) INTRINSIC_CASE(MathMinLongLong) INTRINSIC_CASE(MathMaxIntInt) INTRINSIC_CASE(MathMaxLongLong) INTRINSIC_CASE(MathAbsInt) INTRINSIC_CASE(MathAbsLong) INTRINSIC_CASE(MathAbsFloat) INTRINSIC_CASE(MathAbsDouble) INTRINSIC_CASE(MathSqrt) INTRINSIC_CASE(MathCeil) INTRINSIC_CASE(MathFloor) INTRINSIC_CASE(MathSin) INTRINSIC_CASE(MathCos) INTRINSIC_CASE(MathTan) INTRINSIC_CASE(MathAsin) INTRINSIC_CASE(MathAcos) INTRINSIC_CASE(MathAtan) default: res = false; // Punt break; } return res; } } // namespace interpreter } // namespace art