/* * Copyright (C) 2012 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. */ /*! \file LowerConst.cpp \brief This file lowers the following bytecodes: CONST_XXX Functions are called from the lowered native sequence: 1> const_string_resolve INPUT: const pool index in %eax OUTPUT: resolved string in %eax The only register that is still live after this function is ebx 2> class_resolve INPUT: const pool index in %eax OUTPUT: resolved class in %eax The only register that is still live after this function is ebx */ #include "libdex/DexOpcodes.h" #include "libdex/DexFile.h" #include "Lower.h" #include "NcgAot.h" #include "enc_wrapper.h" #define P_GPR_1 PhysicalReg_EBX #define P_GPR_2 PhysicalReg_ECX //! LOWER bytecode CONST_STRING without usage of helper function //! It calls const_string_resolve (%ebx is live across the call) //! Since the register allocator does not handle control flow within the lowered native sequence, //! we define an interface between the lowering module and register allocator: //! rememberState, gotoState, transferToState //! to make sure at the control flow merge point the state of registers is the same int const_string_common_nohelper(u4 tmp, u2 vA) { /* for trace-based JIT, the string is already resolved since this code has been executed */ void *strPtr = (void*) (currentMethod->clazz->pDvmDex->pResStrings[tmp]); assert(strPtr != NULL); set_VR_to_imm(vA, OpndSize_32, (int) strPtr ); return 0; } //! dispatcher to select either const_string_common_helper or const_string_common_nohelper //! int const_string_common(u4 tmp, u2 vA) { return const_string_common_nohelper(tmp, vA); } #undef P_GPR_1 #undef P_GPR_2 //! lower bytecode CONST_4 //! int op_const_4() { u2 vA = INST_A(inst); s4 tmp = (s4) (INST_B(inst) << 28) >> 28; set_VR_to_imm(vA, OpndSize_32, tmp); rPC += 1; return 1; } //! lower bytecode CONST_16 //! int op_const_16() { u2 BBBB = FETCH(1); u2 vA = INST_AA(inst); set_VR_to_imm(vA, OpndSize_32, (s2)BBBB); rPC += 2; return 1; } //! lower bytecode CONST //! int op_const() { u2 vA = INST_AA(inst); u4 tmp = FETCH(1); tmp |= (u4)FETCH(2) << 16; set_VR_to_imm(vA, OpndSize_32, (s4)tmp); rPC += 3; return 1; } //! lower bytecode CONST_HIGH16 //! int op_const_high16() { u2 vA = INST_AA(inst); u2 tmp = FETCH(1); set_VR_to_imm(vA, OpndSize_32, (s4)tmp<<16); //?? rPC += 2; return 1; } //! lower bytecode CONST_WIDE_16 //! int op_const_wide_16() { u2 vA = INST_AA(inst); u2 tmp = FETCH(1); set_VR_to_imm(vA, OpndSize_32, (s2)tmp); set_VR_to_imm(vA+1, OpndSize_32, (s2)tmp>>31); rPC += 2; return 2; } //! lower bytecode CONST_WIDE_32 //! int op_const_wide_32() { u2 vA = INST_AA(inst); u4 tmp = FETCH(1); tmp |= (u4)FETCH(2) << 16; set_VR_to_imm(vA, OpndSize_32, (s4)tmp); set_VR_to_imm(vA+1, OpndSize_32, (s4)tmp>>31); rPC += 3; return 2; } //! lower bytecode CONST_WIDE //! int op_const_wide() { u2 vA = INST_AA(inst); u4 tmp = FETCH(1); tmp |= (u8)FETCH(2) << 16; set_VR_to_imm(vA, OpndSize_32, (s4)tmp); tmp = (u8)FETCH(3); tmp |= (u8)FETCH(4) << 16; set_VR_to_imm(vA+1, OpndSize_32, (s4)tmp); rPC += 5; return 2; } //! lower bytecode CONST_WIDE_HIGH16 //! int op_const_wide_high16() { u2 vA = INST_AA(inst); u2 tmp = FETCH(1); set_VR_to_imm(vA, OpndSize_32, 0); set_VR_to_imm(vA+1, OpndSize_32, (s4)tmp<<16); rPC += 2; return 2; } //! lower bytecode CONST_STRING //! int op_const_string() { u2 vB = FETCH(1); u2 vA = INST_AA(inst); u4 tmp = vB; int retval = const_string_common(tmp, vA); rPC += 2; return retval; } //! lower bytecode CONST_STRING_JUMBO //! int op_const_string_jumbo() { u2 vA = INST_AA(inst); u4 tmp = FETCH(1); tmp |= (u4)FETCH(2) << 16; int retval = const_string_common(tmp, vA); rPC += 3; return retval; } #define P_GPR_1 PhysicalReg_EBX //! LOWER bytecode CONST_CLASS //! It calls class_resolve (%ebx is live across the call) //! Since the register allocator does not handle control flow within the lowered native sequence, //! we define an interface between the lowering module and register allocator: //! rememberState, gotoState, transferToState //! to make sure at the control flow merge point the state of registers is the same int op_const_class() { u2 vA = INST_AA(inst); u4 tmp = (u4)FETCH(1); /* for trace-based JIT, the class is already resolved since this code has been executed */ void *classPtr = (void*) (currentMethod->clazz->pDvmDex->pResClasses[tmp]); assert(classPtr != NULL); set_VR_to_imm(vA, OpndSize_32, (int) classPtr ); rPC += 2; return 0; } #undef P_GPR_1