/*
* 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