blob: 5e901cdfd8b7223d2fc5988a91553f03a4515eec [file] [log] [blame]
/*
* 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<Intrinsics>(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