| /* |
| * 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 BytecodeVisitor.cpp |
| \brief This file implements visitors of the bytecode |
| */ |
| #include "libdex/DexOpcodes.h" |
| #include "libdex/DexFile.h" |
| #include "Lower.h" |
| #include "AnalysisO1.h" |
| |
| //! Returns size of the current bytecode in u2 unit |
| |
| //! |
| int getByteCodeSize() { //uses inst, unit in u2 |
| switch (INST_INST(inst)) { |
| case OP_NOP: |
| return 1; |
| case OP_MOVE: |
| case OP_MOVE_OBJECT: |
| return 1; |
| case OP_MOVE_FROM16: |
| case OP_MOVE_OBJECT_FROM16: |
| return 2; |
| case OP_MOVE_16: |
| case OP_MOVE_OBJECT_16: |
| return 3; |
| case OP_MOVE_WIDE: |
| return 1; |
| case OP_MOVE_WIDE_FROM16: |
| return 2; |
| case OP_MOVE_WIDE_16: |
| return 3; |
| case OP_MOVE_RESULT: |
| case OP_MOVE_RESULT_OBJECT: |
| return 1; |
| case OP_MOVE_RESULT_WIDE: |
| return 1; |
| case OP_MOVE_EXCEPTION: |
| return 1; |
| case OP_RETURN_VOID: |
| case OP_RETURN_VOID_BARRIER: |
| return 1; |
| case OP_RETURN: |
| case OP_RETURN_OBJECT: |
| return 1; |
| case OP_RETURN_WIDE: |
| return 1; |
| case OP_CONST_4: |
| return 1; |
| case OP_CONST_16: |
| return 2; |
| case OP_CONST: |
| return 3; |
| case OP_CONST_HIGH16: |
| return 2; |
| case OP_CONST_WIDE_16: |
| return 2; |
| case OP_CONST_WIDE_32: |
| return 3; |
| case OP_CONST_WIDE: |
| return 5; |
| case OP_CONST_WIDE_HIGH16: |
| return 2; |
| case OP_CONST_STRING: |
| return 2; |
| case OP_CONST_STRING_JUMBO: |
| return 3; |
| case OP_CONST_CLASS: |
| return 2; |
| case OP_MONITOR_ENTER: |
| return 1; |
| case OP_MONITOR_EXIT: |
| return 1; |
| case OP_CHECK_CAST: |
| return 2; |
| case OP_INSTANCE_OF: |
| return 2; |
| case OP_ARRAY_LENGTH: |
| return 1; |
| case OP_NEW_INSTANCE: |
| return 2; |
| case OP_NEW_ARRAY: |
| return 2; |
| case OP_FILLED_NEW_ARRAY: |
| return 3; |
| case OP_FILLED_NEW_ARRAY_RANGE: |
| return 3; |
| case OP_FILL_ARRAY_DATA: |
| return 3; |
| case OP_THROW: |
| return 1; |
| case OP_THROW_VERIFICATION_ERROR: |
| return 2; |
| case OP_GOTO: |
| return 1; |
| case OP_GOTO_16: |
| return 2; |
| case OP_GOTO_32: |
| return 3; |
| case OP_PACKED_SWITCH: |
| return 3; |
| case OP_SPARSE_SWITCH: |
| return 3; |
| case OP_CMPL_FLOAT: |
| return 2; |
| case OP_CMPG_FLOAT: |
| return 2; |
| case OP_CMPL_DOUBLE: |
| return 2; |
| case OP_CMPG_DOUBLE: |
| return 2; |
| case OP_CMP_LONG: |
| return 2; |
| case OP_IF_EQ: |
| return 2; |
| case OP_IF_NE: |
| return 2; |
| case OP_IF_LT: |
| return 2; |
| case OP_IF_GE: |
| return 2; |
| case OP_IF_GT: |
| return 2; |
| case OP_IF_LE: |
| return 2; |
| case OP_IF_EQZ: |
| return 2; |
| case OP_IF_NEZ: |
| return 2; |
| case OP_IF_LTZ: |
| return 2; |
| case OP_IF_GEZ: |
| return 2; |
| case OP_IF_GTZ: |
| return 2; |
| case OP_IF_LEZ: |
| return 2; |
| case OP_AGET: |
| return 2; |
| case OP_AGET_WIDE: |
| return 2; |
| case OP_AGET_OBJECT: |
| return 2; |
| case OP_AGET_BOOLEAN: |
| return 2; |
| case OP_AGET_BYTE: |
| return 2; |
| case OP_AGET_CHAR: |
| return 2; |
| case OP_AGET_SHORT: |
| return 2; |
| case OP_APUT: |
| return 2; |
| case OP_APUT_WIDE: |
| return 2; |
| case OP_APUT_OBJECT: |
| return 2; |
| case OP_APUT_BOOLEAN: |
| return 2; |
| case OP_APUT_BYTE: |
| return 2; |
| case OP_APUT_CHAR: |
| return 2; |
| case OP_APUT_SHORT: |
| return 2; |
| case OP_IGET: |
| case OP_IGET_WIDE: |
| case OP_IGET_OBJECT: |
| case OP_IGET_VOLATILE: |
| case OP_IGET_WIDE_VOLATILE: |
| case OP_IGET_OBJECT_VOLATILE: |
| case OP_IGET_BOOLEAN: |
| case OP_IGET_BYTE: |
| case OP_IGET_CHAR: |
| case OP_IGET_SHORT: |
| case OP_IPUT: |
| case OP_IPUT_WIDE: |
| case OP_IPUT_OBJECT: |
| case OP_IPUT_VOLATILE: |
| case OP_IPUT_WIDE_VOLATILE: |
| case OP_IPUT_OBJECT_VOLATILE: |
| case OP_IPUT_BOOLEAN: |
| case OP_IPUT_BYTE: |
| case OP_IPUT_CHAR: |
| case OP_IPUT_SHORT: |
| return 2; |
| case OP_SGET: |
| case OP_SGET_WIDE: |
| case OP_SGET_OBJECT: |
| case OP_SGET_VOLATILE: |
| case OP_SGET_WIDE_VOLATILE: |
| case OP_SGET_OBJECT_VOLATILE: |
| case OP_SGET_BOOLEAN: |
| case OP_SGET_BYTE: |
| case OP_SGET_CHAR: |
| case OP_SGET_SHORT: |
| case OP_SPUT: |
| case OP_SPUT_WIDE: |
| case OP_SPUT_OBJECT: |
| case OP_SPUT_VOLATILE: |
| case OP_SPUT_WIDE_VOLATILE: |
| case OP_SPUT_OBJECT_VOLATILE: |
| case OP_SPUT_BOOLEAN: |
| case OP_SPUT_BYTE: |
| case OP_SPUT_CHAR: |
| case OP_SPUT_SHORT: |
| return 2; |
| case OP_INVOKE_VIRTUAL: |
| case OP_INVOKE_SUPER: |
| case OP_INVOKE_DIRECT: |
| case OP_INVOKE_STATIC: |
| case OP_INVOKE_INTERFACE: |
| case OP_INVOKE_VIRTUAL_RANGE: |
| case OP_INVOKE_SUPER_RANGE: |
| case OP_INVOKE_DIRECT_RANGE: |
| case OP_INVOKE_STATIC_RANGE: |
| case OP_INVOKE_INTERFACE_RANGE: |
| return 3; |
| |
| case OP_NEG_INT: |
| case OP_NOT_INT: |
| case OP_NEG_LONG: |
| case OP_NOT_LONG: |
| case OP_NEG_FLOAT: |
| case OP_NEG_DOUBLE: |
| case OP_INT_TO_LONG: |
| case OP_INT_TO_FLOAT: |
| case OP_INT_TO_DOUBLE: |
| case OP_LONG_TO_INT: |
| case OP_LONG_TO_FLOAT: |
| case OP_LONG_TO_DOUBLE: |
| case OP_FLOAT_TO_INT: |
| case OP_FLOAT_TO_LONG: |
| case OP_FLOAT_TO_DOUBLE: |
| case OP_DOUBLE_TO_INT: |
| case OP_DOUBLE_TO_LONG: |
| case OP_DOUBLE_TO_FLOAT: |
| case OP_INT_TO_BYTE: |
| case OP_INT_TO_CHAR: |
| case OP_INT_TO_SHORT: |
| return 1; |
| |
| case OP_ADD_INT: |
| case OP_SUB_INT: |
| case OP_MUL_INT: |
| case OP_DIV_INT: |
| case OP_REM_INT: |
| case OP_AND_INT: |
| case OP_OR_INT: |
| case OP_XOR_INT: |
| case OP_SHL_INT: |
| case OP_SHR_INT: |
| case OP_USHR_INT: |
| case OP_ADD_LONG: |
| case OP_SUB_LONG: |
| case OP_MUL_LONG: |
| case OP_DIV_LONG: |
| case OP_REM_LONG: |
| case OP_AND_LONG: |
| case OP_OR_LONG: |
| case OP_XOR_LONG: |
| case OP_SHL_LONG: |
| case OP_SHR_LONG: |
| case OP_USHR_LONG: |
| case OP_ADD_FLOAT: |
| case OP_SUB_FLOAT: |
| case OP_MUL_FLOAT: |
| case OP_DIV_FLOAT: |
| case OP_REM_FLOAT: |
| case OP_ADD_DOUBLE: |
| case OP_SUB_DOUBLE: |
| case OP_MUL_DOUBLE: |
| case OP_DIV_DOUBLE: |
| case OP_REM_DOUBLE: |
| return 2; |
| |
| case OP_ADD_INT_2ADDR: |
| case OP_SUB_INT_2ADDR: |
| case OP_MUL_INT_2ADDR: |
| case OP_DIV_INT_2ADDR: |
| case OP_REM_INT_2ADDR: |
| case OP_AND_INT_2ADDR: |
| case OP_OR_INT_2ADDR: |
| case OP_XOR_INT_2ADDR: |
| case OP_SHL_INT_2ADDR: |
| case OP_SHR_INT_2ADDR: |
| case OP_USHR_INT_2ADDR: |
| case OP_ADD_LONG_2ADDR: |
| case OP_SUB_LONG_2ADDR: |
| case OP_MUL_LONG_2ADDR: |
| case OP_DIV_LONG_2ADDR: |
| case OP_REM_LONG_2ADDR: |
| case OP_AND_LONG_2ADDR: |
| case OP_OR_LONG_2ADDR: |
| case OP_XOR_LONG_2ADDR: |
| case OP_SHL_LONG_2ADDR: |
| case OP_SHR_LONG_2ADDR: |
| case OP_USHR_LONG_2ADDR: |
| case OP_ADD_FLOAT_2ADDR: |
| case OP_SUB_FLOAT_2ADDR: |
| case OP_MUL_FLOAT_2ADDR: |
| case OP_DIV_FLOAT_2ADDR: |
| case OP_REM_FLOAT_2ADDR: |
| case OP_ADD_DOUBLE_2ADDR: |
| case OP_SUB_DOUBLE_2ADDR: |
| case OP_MUL_DOUBLE_2ADDR: |
| case OP_DIV_DOUBLE_2ADDR: |
| case OP_REM_DOUBLE_2ADDR: |
| return 1; |
| |
| case OP_ADD_INT_LIT16: |
| case OP_RSUB_INT: |
| case OP_MUL_INT_LIT16: |
| case OP_DIV_INT_LIT16: |
| case OP_REM_INT_LIT16: |
| case OP_AND_INT_LIT16: |
| case OP_OR_INT_LIT16: |
| case OP_XOR_INT_LIT16: |
| return 2; |
| |
| case OP_ADD_INT_LIT8: |
| case OP_RSUB_INT_LIT8: |
| case OP_MUL_INT_LIT8: |
| case OP_DIV_INT_LIT8: |
| case OP_REM_INT_LIT8: |
| case OP_AND_INT_LIT8: |
| case OP_OR_INT_LIT8: |
| case OP_XOR_INT_LIT8: |
| case OP_SHL_INT_LIT8: |
| case OP_SHR_INT_LIT8: |
| case OP_USHR_INT_LIT8: |
| return 2; |
| |
| case OP_EXECUTE_INLINE: |
| case OP_EXECUTE_INLINE_RANGE: |
| return 3; |
| #if FIXME |
| case OP_INVOKE_OBJECT_INIT_RANGE: |
| return 3; |
| #endif |
| |
| case OP_IGET_QUICK: |
| case OP_IGET_WIDE_QUICK: |
| case OP_IGET_OBJECT_QUICK: |
| case OP_IPUT_QUICK: |
| case OP_IPUT_WIDE_QUICK: |
| case OP_IPUT_OBJECT_QUICK: |
| return 2; |
| |
| case OP_INVOKE_VIRTUAL_QUICK: |
| case OP_INVOKE_VIRTUAL_QUICK_RANGE: |
| case OP_INVOKE_SUPER_QUICK: |
| case OP_INVOKE_SUPER_QUICK_RANGE: |
| return 3; |
| #ifdef SUPPORT_HLO |
| case kExtInstruction: |
| switch(inst) { |
| case OP_X_AGET_QUICK: |
| case OP_X_AGET_WIDE_QUICK: |
| case OP_X_AGET_OBJECT_QUICK: |
| case OP_X_AGET_BOOLEAN_QUICK: |
| case OP_X_AGET_BYTE_QUICK: |
| case OP_X_AGET_CHAR_QUICK: |
| case OP_X_AGET_SHORT_QUICK: |
| case OP_X_APUT_QUICK: |
| case OP_X_APUT_WIDE_QUICK: |
| case OP_X_APUT_OBJECT_QUICK: |
| case OP_X_APUT_BOOLEAN_QUICK: |
| case OP_X_APUT_BYTE_QUICK: |
| case OP_X_APUT_CHAR_QUICK: |
| case OP_X_APUT_SHORT_QUICK: |
| return 3; |
| case OP_X_DEREF_GET: |
| case OP_X_DEREF_GET_OBJECT: |
| case OP_X_DEREF_GET_WIDE: |
| case OP_X_DEREF_GET_BOOLEAN: |
| case OP_X_DEREF_GET_BYTE: |
| case OP_X_DEREF_GET_CHAR: |
| case OP_X_DEREF_GET_SHORT: |
| case OP_X_DEREF_PUT: |
| case OP_X_DEREF_PUT_WIDE: |
| case OP_X_DEREF_PUT_OBJECT: |
| case OP_X_DEREF_PUT_BOOLEAN: |
| case OP_X_DEREF_PUT_BYTE: |
| case OP_X_DEREF_PUT_CHAR: |
| case OP_X_DEREF_PUT_SHORT: |
| return 2; |
| case OP_X_ARRAY_CHECKS: |
| case OP_X_ARRAY_OBJECT_CHECKS: |
| return 3; |
| case OP_X_CHECK_BOUNDS: |
| case OP_X_CHECK_NULL: |
| case OP_X_CHECK_TYPE: |
| return 2; |
| } |
| #endif |
| } |
| return -1; |
| } |
| //! reduces refCount of a virtual register |
| |
| //! |
| void touchOneVR(u2 vA, LowOpndRegType type) { |
| int index = searchCompileTable(LowOpndRegType_virtual | type, vA); |
| if(index < 0) { |
| ALOGE("virtual reg %d type %d not found in touchOneVR", vA, type); |
| return; |
| } |
| compileTable[index].refCount--; |
| } |
| //! reduces refCount of two virtual registers |
| |
| //! |
| void touchTwoVRs(u2 vA, u2 vB, LowOpndRegType type) { |
| int index = searchCompileTable(LowOpndRegType_virtual | type, vA); |
| if(index < 0) { |
| ALOGE("virtual reg vA %d type %d not found in touchTwoVRs", vA, type); |
| return; |
| } |
| compileTable[index].refCount--; |
| index = searchCompileTable(LowOpndRegType_virtual | type, vB); |
| if(index < 0) { |
| ALOGE("virtual reg vB %d type %d not found in touchTwoVRs", vB, type); |
| return; |
| } |
| compileTable[index].refCount--; |
| } |
| int num_const_worklist; |
| //! worklist to update constVRTable later |
| int constWorklist[10]; |
| |
| int num_const_vr; //in a basic block |
| //! table to store the constant information for virtual registers |
| ConstVRInfo constVRTable[MAX_CONST_REG]; |
| //! update constVRTable for a given virtual register |
| |
| //! set "isConst" to false |
| void setVRToNonConst(int regNum, OpndSize size) { |
| int k; |
| int indexL = -1; |
| int indexH = -1; |
| for(k = 0; k < num_const_vr; k++) { |
| if(constVRTable[k].regNum == regNum) { |
| indexL = k; |
| continue; |
| } |
| if(constVRTable[k].regNum == regNum + 1 && size == OpndSize_64) { |
| indexH = k; |
| continue; |
| } |
| } |
| if(indexL >= 0) { |
| //remove this entry?? |
| constVRTable[indexL].isConst = false; |
| } |
| if(size == OpndSize_64 && indexH >= 0) { |
| constVRTable[indexH].isConst = false; |
| } |
| } |
| //! update constVRTable for a given virtual register |
| |
| //! set "isConst" to true |
| void setVRToConst(int regNum, OpndSize size, int* tmpValue) { |
| int k; |
| int indexL = -1; |
| int indexH = -1; |
| for(k = 0; k < num_const_vr; k++) { |
| if(constVRTable[k].regNum == regNum) { |
| indexL = k; |
| continue; |
| } |
| if(constVRTable[k].regNum == regNum + 1 && size == OpndSize_64) { |
| indexH = k; |
| continue; |
| } |
| } |
| if(indexL < 0) { |
| indexL = num_const_vr; |
| constVRTable[indexL].regNum = regNum; |
| num_const_vr++; |
| } |
| constVRTable[indexL].isConst = true; |
| constVRTable[indexL].value = tmpValue[0]; |
| if(size == OpndSize_64) { |
| if(indexH < 0) { |
| indexH = num_const_vr; |
| constVRTable[indexH].regNum = regNum+1; |
| num_const_vr++; |
| } |
| constVRTable[indexH].isConst = true; |
| constVRTable[indexH].value = tmpValue[1]; |
| } |
| if(num_const_vr > MAX_CONST_REG) ALOGE("constVRTable overflows"); |
| invalidateVRDueToConst(regNum, size); |
| } |
| |
| //! perform work on constWorklist |
| |
| //! |
| void updateConstInfo(BasicBlock_O1* bb) { |
| if(bb == NULL) return; |
| int k; |
| for(k = 0; k < num_const_worklist; k++) { |
| //int indexOrig = constWorklist[k]; |
| //compileTable[indexOrig].isConst = false; |
| //int A = compileTable[indexOrig].regNum; |
| //LowOpndRegType type = compileTable[indexOrig].physicalType & MASK_FOR_TYPE; |
| setVRToNonConst(constWorklist[k], OpndSize_32); |
| } |
| } |
| //! check whether the current bytecode generates a const |
| |
| //! if yes, update constVRTable; otherwise, update constWorklist |
| //! if a bytecode uses vA (const), and updates vA to non const, getConstInfo will return false and update constWorklist to make sure when lowering the bytecode, vA is treated as constant |
| bool getConstInfo(BasicBlock_O1* bb) { |
| compileTableEntry* infoArray = compileTable; |
| u2 inst_op = INST_INST(inst); |
| u2 vA = 0, vB = 0, v1, v2; |
| u2 BBBB; |
| u2 tmp_u2; |
| s4 tmp_s4; |
| u4 tmp_u4; |
| int entry, tmpValue[2], tmpValue2[2]; |
| num_const_worklist = 0; |
| |
| switch(inst_op) { |
| //for other opcode, if update the register, set isConst to false |
| case OP_MOVE: |
| case OP_MOVE_OBJECT: |
| case OP_MOVE_FROM16: |
| case OP_MOVE_OBJECT_FROM16: |
| case OP_MOVE_16: |
| case OP_MOVE_OBJECT_16: |
| if(inst_op == OP_MOVE || inst_op == OP_MOVE_OBJECT) { |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| } |
| else if(inst_op == OP_MOVE_FROM16 || inst_op == OP_MOVE_OBJECT_FROM16) { |
| vA = INST_AA(inst); |
| vB = FETCH(1); |
| } |
| else if(inst_op == OP_MOVE_16 || inst_op == OP_MOVE_OBJECT_16) { |
| vA = FETCH(1); |
| vB = FETCH(2); |
| } |
| if(isVirtualRegConstant(vB, LowOpndRegType_gp, tmpValue, false) == 3) { |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = tmpValue[0]; |
| compileTable[entry].refCount--; |
| touchOneVR(vB, LowOpndRegType_gp); |
| return true; |
| } else { |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| } |
| return false; |
| case OP_MOVE_WIDE: |
| case OP_MOVE_WIDE_FROM16: |
| case OP_MOVE_WIDE_16: |
| if(inst_op == OP_MOVE_WIDE) { |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| } |
| else if(inst_op == OP_MOVE_WIDE_FROM16) { |
| vA = INST_AA(inst); |
| vB = FETCH(1); |
| } |
| else if(inst_op == OP_MOVE_WIDE_16) { |
| vA = FETCH(1); |
| vB = FETCH(2); |
| } |
| if(isVirtualRegConstant(vB, LowOpndRegType_xmm, tmpValue, false) == 3) { |
| entry = findVirtualRegInTable(vA, LowOpndRegType_xmm, true); |
| setVRToConst(vA, OpndSize_64, tmpValue); |
| compileTable[entry].refCount--; |
| touchOneVR(vB, LowOpndRegType_xmm); |
| return true; |
| } else { |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| } |
| return false; |
| case OP_MOVE_RESULT: |
| case OP_MOVE_RESULT_OBJECT: |
| case OP_MOVE_EXCEPTION: |
| case OP_CONST_STRING: |
| case OP_CONST_STRING_JUMBO: |
| case OP_CONST_CLASS: |
| case OP_NEW_INSTANCE: |
| case OP_CMPL_FLOAT: |
| case OP_CMPG_FLOAT: |
| case OP_CMPL_DOUBLE: |
| case OP_CMPG_DOUBLE: |
| case OP_AGET: |
| case OP_AGET_OBJECT: |
| case OP_AGET_BOOLEAN: |
| case OP_AGET_BYTE: |
| case OP_AGET_CHAR: |
| case OP_AGET_SHORT: |
| case OP_SGET: |
| case OP_SGET_OBJECT: |
| case OP_SGET_VOLATILE: |
| case OP_SGET_OBJECT_VOLATILE: |
| case OP_SGET_BOOLEAN: |
| case OP_SGET_BYTE: |
| case OP_SGET_CHAR: |
| case OP_SGET_SHORT: |
| vA = INST_AA(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| case OP_MOVE_RESULT_WIDE: |
| case OP_AGET_WIDE: |
| case OP_SGET_WIDE: |
| case OP_SGET_WIDE_VOLATILE: |
| vA = INST_AA(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| return false; |
| case OP_INSTANCE_OF: |
| case OP_ARRAY_LENGTH: |
| case OP_NEW_ARRAY: |
| case OP_IGET: |
| case OP_IGET_OBJECT: |
| case OP_IGET_VOLATILE: |
| case OP_IGET_OBJECT_VOLATILE: |
| case OP_IGET_BOOLEAN: |
| case OP_IGET_BYTE: |
| case OP_IGET_CHAR: |
| case OP_IGET_SHORT: |
| case OP_IGET_QUICK: |
| case OP_IGET_OBJECT_QUICK: |
| vA = INST_A(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| case OP_IGET_WIDE: |
| case OP_IGET_WIDE_VOLATILE: |
| case OP_IGET_WIDE_QUICK: |
| vA = INST_A(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| return false; |
| //TODO: constant folding for float/double/long ALU |
| case OP_ADD_FLOAT: |
| case OP_SUB_FLOAT: |
| case OP_MUL_FLOAT: |
| case OP_DIV_FLOAT: |
| case OP_REM_FLOAT: |
| vA = INST_AA(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| case OP_ADD_DOUBLE: |
| case OP_SUB_DOUBLE: |
| case OP_MUL_DOUBLE: |
| case OP_DIV_DOUBLE: |
| case OP_REM_DOUBLE: |
| vA = INST_AA(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| return false; |
| case OP_NEG_FLOAT: |
| case OP_INT_TO_FLOAT: |
| case OP_LONG_TO_FLOAT: |
| case OP_FLOAT_TO_INT: |
| case OP_DOUBLE_TO_INT: |
| case OP_ADD_FLOAT_2ADDR: |
| case OP_SUB_FLOAT_2ADDR: |
| case OP_MUL_FLOAT_2ADDR: |
| case OP_DIV_FLOAT_2ADDR: |
| case OP_REM_FLOAT_2ADDR: |
| case OP_DOUBLE_TO_FLOAT: |
| vA = INST_A(inst); |
| constWorklist[num_const_worklist] = vA; //change constWorklist to point to vA TODO |
| num_const_worklist++; |
| return false; |
| case OP_FLOAT_TO_LONG: |
| case OP_DOUBLE_TO_LONG: |
| case OP_FLOAT_TO_DOUBLE: |
| vA = INST_A(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| return false; |
| case OP_NEG_DOUBLE: |
| case OP_INT_TO_DOUBLE: //fp stack |
| case OP_LONG_TO_DOUBLE: |
| case OP_ADD_DOUBLE_2ADDR: |
| case OP_SUB_DOUBLE_2ADDR: |
| case OP_MUL_DOUBLE_2ADDR: |
| case OP_DIV_DOUBLE_2ADDR: |
| case OP_REM_DOUBLE_2ADDR: |
| //ops on float, double |
| vA = INST_A(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| return false; |
| case OP_NEG_INT: |
| case OP_NOT_INT: |
| case OP_LONG_TO_INT: |
| case OP_INT_TO_BYTE: |
| case OP_INT_TO_CHAR: |
| case OP_INT_TO_SHORT: |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| if(isVirtualRegConstant(vB, LowOpndRegType_gp, tmpValue, false) == 3) { |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| if(inst_op == OP_NEG_INT) |
| infoArray[entry].value[0] = -tmpValue[0]; |
| if(inst_op == OP_NOT_INT) |
| infoArray[entry].value[0] = ~tmpValue[0]; //CHECK |
| if(inst_op == OP_LONG_TO_INT) |
| infoArray[entry].value[0] = tmpValue[0]; |
| if(inst_op == OP_INT_TO_BYTE)// sar |
| infoArray[entry].value[0] = (tmpValue[0] << 24) >> 24; |
| if(inst_op == OP_INT_TO_CHAR) //shr |
| infoArray[entry].value[0] = ((unsigned int)(tmpValue[0] << 16)) >> 16; |
| if(inst_op == OP_INT_TO_SHORT) //sar |
| infoArray[entry].value[0] = (tmpValue[0] << 16) >> 16; |
| tmpValue[0] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| compileTable[entry].refCount--; |
| touchOneVR(vB, LowOpndRegType_gp); |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %d", vA, infoArray[entry].value[0]); |
| #endif |
| return true; |
| } |
| else { |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| } |
| case OP_NEG_LONG: |
| case OP_NOT_LONG: |
| case OP_INT_TO_LONG: |
| vA = INST_A(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; //fixed on 10/15/2009 |
| num_const_worklist++; |
| return false; |
| case OP_DIV_INT_2ADDR: |
| case OP_REM_INT_2ADDR: |
| case OP_REM_INT_LIT16: |
| case OP_DIV_INT_LIT16: |
| case OP_REM_INT_LIT8: |
| case OP_DIV_INT_LIT8: |
| case OP_DIV_INT: |
| case OP_REM_INT: |
| if(inst_op == OP_DIV_INT || inst_op == OP_DIV_INT_LIT8 || |
| inst_op == OP_REM_INT || inst_op == OP_REM_INT_LIT8) |
| vA = INST_AA(inst); |
| else |
| vA = INST_A(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| case OP_ADD_INT_2ADDR: |
| case OP_SUB_INT_2ADDR: |
| case OP_MUL_INT_2ADDR: |
| case OP_AND_INT_2ADDR: |
| case OP_OR_INT_2ADDR: |
| case OP_XOR_INT_2ADDR: |
| case OP_SHL_INT_2ADDR: |
| case OP_SHR_INT_2ADDR: |
| case OP_USHR_INT_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| if(isVirtualRegConstant(vA, LowOpndRegType_gp, tmpValue, false) == 3 && |
| isVirtualRegConstant(v2, LowOpndRegType_gp, tmpValue2, false) == 3) { |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| if(inst_op == OP_ADD_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] + tmpValue2[0]; |
| if(inst_op == OP_SUB_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] - tmpValue2[0]; |
| if(inst_op == OP_MUL_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] * tmpValue2[0]; |
| if(inst_op == OP_DIV_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] / tmpValue2[0]; |
| if(inst_op == OP_REM_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] % tmpValue2[0]; |
| if(inst_op == OP_AND_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] & tmpValue2[0]; |
| if(inst_op == OP_OR_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] | tmpValue2[0]; |
| if(inst_op == OP_XOR_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] ^ tmpValue2[0]; |
| if(inst_op == OP_SHL_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] << tmpValue2[0]; |
| if(inst_op == OP_SHR_INT_2ADDR) |
| infoArray[entry].value[0] = tmpValue[0] >> tmpValue2[0]; |
| if(inst_op == OP_USHR_INT_2ADDR) |
| infoArray[entry].value[0] = (unsigned int)tmpValue[0] >> tmpValue2[0]; |
| tmpValue[0] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| compileTable[entry].refCount--; |
| touchOneVR(v2, LowOpndRegType_gp); |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %d", vA, infoArray[entry].value[0]); |
| #endif |
| return true; |
| } |
| else { |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| } |
| case OP_ADD_INT_LIT16: |
| case OP_RSUB_INT: |
| case OP_MUL_INT_LIT16: |
| case OP_AND_INT_LIT16: |
| case OP_OR_INT_LIT16: |
| case OP_XOR_INT_LIT16: |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| tmp_s4 = (s2)FETCH(1); |
| if(isVirtualRegConstant(vB, LowOpndRegType_gp, tmpValue, false) == 3) { |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| if(inst_op == OP_ADD_INT_LIT16) |
| infoArray[entry].value[0] = tmpValue[0] + tmp_s4; |
| if(inst_op == OP_RSUB_INT) |
| infoArray[entry].value[0] = tmp_s4 - tmpValue[0]; |
| if(inst_op == OP_MUL_INT_LIT16) |
| infoArray[entry].value[0] = tmpValue[0] * tmp_s4; |
| if(inst_op == OP_DIV_INT_LIT16) |
| infoArray[entry].value[0] = tmpValue[0] / tmp_s4; |
| if(inst_op == OP_REM_INT_LIT16) |
| infoArray[entry].value[0] = tmpValue[0] % tmp_s4; |
| if(inst_op == OP_AND_INT_LIT16) |
| infoArray[entry].value[0] = tmpValue[0] & tmp_s4; |
| if(inst_op == OP_OR_INT_LIT16) |
| infoArray[entry].value[0] = tmpValue[0] | tmp_s4; |
| if(inst_op == OP_XOR_INT_LIT16) |
| infoArray[entry].value[0] = tmpValue[0] ^ tmp_s4; |
| tmpValue[0] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| compileTable[entry].refCount--; |
| touchOneVR(vB, LowOpndRegType_gp); |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %d", vA, infoArray[entry].value[0]); |
| #endif |
| return true; |
| } |
| else { |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| } |
| case OP_ADD_INT: |
| case OP_SUB_INT: |
| case OP_MUL_INT: |
| case OP_AND_INT: |
| case OP_OR_INT: |
| case OP_XOR_INT: |
| case OP_SHL_INT: |
| case OP_SHR_INT: |
| case OP_USHR_INT: |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| if(isVirtualRegConstant(v1, LowOpndRegType_gp, tmpValue, false) == 3 && |
| isVirtualRegConstant(v2, LowOpndRegType_gp, tmpValue2, false) == 3) { |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| if(inst_op == OP_ADD_INT) |
| infoArray[entry].value[0] = tmpValue[0] + tmpValue2[0]; |
| if(inst_op == OP_SUB_INT) |
| infoArray[entry].value[0] = tmpValue[0] - tmpValue2[0]; |
| if(inst_op == OP_MUL_INT) |
| infoArray[entry].value[0] = tmpValue[0] * tmpValue2[0]; |
| if(inst_op == OP_DIV_INT) |
| infoArray[entry].value[0] = tmpValue[0] / tmpValue2[0]; |
| if(inst_op == OP_REM_INT) |
| infoArray[entry].value[0] = tmpValue[0] % tmpValue2[0]; |
| if(inst_op == OP_AND_INT) |
| infoArray[entry].value[0] = tmpValue[0] & tmpValue2[0]; |
| if(inst_op == OP_OR_INT) |
| infoArray[entry].value[0] = tmpValue[0] | tmpValue2[0]; |
| if(inst_op == OP_XOR_INT) |
| infoArray[entry].value[0] = tmpValue[0] ^ tmpValue2[0]; |
| if(inst_op == OP_SHL_INT) |
| infoArray[entry].value[0] = tmpValue[0] << tmpValue2[0]; |
| if(inst_op == OP_SHR_INT) |
| infoArray[entry].value[0] = tmpValue[0] >> tmpValue2[0]; |
| if(inst_op == OP_USHR_INT) |
| infoArray[entry].value[0] = (unsigned int)tmpValue[0] >> tmpValue2[0]; |
| tmpValue[0] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| compileTable[entry].refCount--; |
| touchOneVR(v1, LowOpndRegType_gp); |
| touchOneVR(v2, LowOpndRegType_gp); |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %d", vA, infoArray[entry].value[0]); |
| #endif |
| return true; |
| } |
| else { |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| } |
| case OP_ADD_INT_LIT8: //INST_AA |
| case OP_RSUB_INT_LIT8: |
| case OP_MUL_INT_LIT8: |
| case OP_AND_INT_LIT8: |
| case OP_OR_INT_LIT8: |
| case OP_XOR_INT_LIT8: |
| case OP_SHL_INT_LIT8: |
| case OP_SHR_INT_LIT8: |
| case OP_USHR_INT_LIT8: |
| vA = INST_AA(inst); |
| vB = (u2)FETCH(1) & 0xff; |
| tmp_s4 = (s2)FETCH(1) >> 8; |
| if(isVirtualRegConstant(vB, LowOpndRegType_gp, tmpValue, false) == 3) { |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| if(inst_op == OP_ADD_INT_LIT8) |
| infoArray[entry].value[0] = tmpValue[0] + tmp_s4; |
| if(inst_op == OP_RSUB_INT_LIT8) |
| infoArray[entry].value[0] = tmp_s4 - tmpValue[0]; |
| if(inst_op == OP_MUL_INT_LIT8) |
| infoArray[entry].value[0] = tmpValue[0] * tmp_s4; |
| if(inst_op == OP_DIV_INT_LIT8) |
| infoArray[entry].value[0] = tmpValue[0] / tmp_s4; |
| if(inst_op == OP_REM_INT_LIT8) |
| infoArray[entry].value[0] = tmpValue[0] % tmp_s4; |
| if(inst_op == OP_AND_INT_LIT8) |
| infoArray[entry].value[0] = tmpValue[0] & tmp_s4; |
| if(inst_op == OP_OR_INT_LIT8) |
| infoArray[entry].value[0] = tmpValue[0] | tmp_s4; |
| if(inst_op == OP_XOR_INT_LIT8) |
| infoArray[entry].value[0] = tmpValue[0] ^ tmp_s4; |
| if(inst_op == OP_SHL_INT_LIT8) |
| infoArray[entry].value[0] = tmpValue[0] << tmp_s4; |
| if(inst_op == OP_SHR_INT_LIT8) |
| infoArray[entry].value[0] = tmpValue[0] >> tmp_s4; |
| if(inst_op == OP_USHR_INT_LIT8) |
| infoArray[entry].value[0] = (unsigned int)tmpValue[0] >> tmp_s4; |
| tmpValue[0] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| compileTable[entry].refCount--; |
| touchOneVR(vB, LowOpndRegType_gp); |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %d", vA, infoArray[entry].value[0]); |
| #endif |
| return true; |
| } |
| else { |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| } |
| case OP_ADD_LONG: |
| case OP_SUB_LONG: |
| case OP_AND_LONG: |
| case OP_OR_LONG: |
| case OP_XOR_LONG: |
| case OP_MUL_LONG: |
| case OP_DIV_LONG: |
| case OP_REM_LONG: |
| case OP_SHL_LONG: |
| case OP_SHR_LONG: |
| case OP_USHR_LONG: |
| //TODO bytecode is not going to update state registers |
| //constant folding |
| vA = INST_AA(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| return false; |
| case OP_CMP_LONG: |
| vA = INST_AA(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| case OP_ADD_LONG_2ADDR: |
| case OP_SUB_LONG_2ADDR: |
| case OP_AND_LONG_2ADDR: |
| case OP_OR_LONG_2ADDR: |
| case OP_XOR_LONG_2ADDR: |
| case OP_MUL_LONG_2ADDR: |
| case OP_DIV_LONG_2ADDR: |
| case OP_REM_LONG_2ADDR: |
| case OP_SHL_LONG_2ADDR: |
| case OP_SHR_LONG_2ADDR: |
| case OP_USHR_LONG_2ADDR: |
| vA = INST_A(inst); |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| return false; |
| case OP_CONST_4: |
| vA = INST_A(inst); |
| tmp_s4 = (s4) (INST_B(inst) << 28) >> 28; |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = tmp_s4; |
| tmpValue[0] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %d", vA, tmp_s4); |
| #endif |
| return true; |
| case OP_CONST_16: |
| BBBB = FETCH(1); |
| vA = INST_AA(inst); |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s2)BBBB; |
| tmpValue[0] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %d", vA, infoArray[entry].value[0]); |
| #endif |
| return true; |
| case OP_CONST: |
| vA = INST_AA(inst); |
| tmp_u4 = FETCH(1); |
| tmp_u4 |= (u4)FETCH(2) << 16; |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s4)tmp_u4; |
| tmpValue[0] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %d", vA, infoArray[entry].value[0]); |
| #endif |
| return true; |
| case OP_CONST_HIGH16: |
| vA = INST_AA(inst); |
| tmp_u2 = FETCH(1); |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s4)tmp_u2<<16; |
| tmpValue[0] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_32, tmpValue); |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %d", vA, infoArray[entry].value[0]); |
| #endif |
| return true; |
| case OP_CONST_WIDE_16: |
| vA = INST_AA(inst); |
| tmp_u2 = FETCH(1); |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s2)tmp_u2; |
| tmpValue[0] = infoArray[entry].value[0]; |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %x", vA, infoArray[entry].value[0]); |
| #endif |
| |
| entry = findVirtualRegInTable(vA+1, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s2)tmp_u2>>31; |
| tmpValue[1] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_64, tmpValue); |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %x", vA+1, infoArray[entry].value[0]); |
| #endif |
| return true; |
| case OP_CONST_WIDE_32: |
| vA = INST_AA(inst); |
| tmp_u4 = FETCH(1); |
| tmp_u4 |= (u4)FETCH(2) << 16; |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s4)tmp_u4; |
| tmpValue[0] = infoArray[entry].value[0]; |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %x", vA, infoArray[entry].value[0]); |
| #endif |
| |
| entry = findVirtualRegInTable(vA+1, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s4)tmp_u4>>31; |
| tmpValue[1] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_64, tmpValue); |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %x", vA+1, infoArray[entry].value[0]); |
| #endif |
| return true; |
| case OP_CONST_WIDE: |
| vA = INST_AA(inst); |
| tmp_u4 = FETCH(1); |
| tmp_u4 |= (u8)FETCH(2) << 16; |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s4)tmp_u4; |
| tmpValue[0] = infoArray[entry].value[0]; |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %x", vA, infoArray[entry].value[0]); |
| #endif |
| |
| tmp_u4 = (u8)FETCH(3); |
| tmp_u4 |= (u8)FETCH(4) << 16; |
| entry = findVirtualRegInTable(vA+1, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s4)tmp_u4; |
| tmpValue[1] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_64, tmpValue); |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %x", vA+1, infoArray[entry].value[0]); |
| #endif |
| return true; |
| case OP_CONST_WIDE_HIGH16: |
| vA = INST_AA(inst); |
| tmp_u2 = FETCH(1); |
| entry = findVirtualRegInTable(vA, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = 0; |
| tmpValue[0] = infoArray[entry].value[0]; |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %x", vA, infoArray[entry].value[0]); |
| #endif |
| |
| entry = findVirtualRegInTable(vA+1, LowOpndRegType_gp, true); |
| infoArray[entry].isConst = true; |
| infoArray[entry].value[0] = (s4)tmp_u2<<16; |
| tmpValue[1] = infoArray[entry].value[0]; |
| setVRToConst(vA, OpndSize_64, tmpValue); |
| compileTable[entry].refCount--; |
| #ifdef DEBUG_CONST |
| LOGD("getConstInfo: set VR %d to %x", vA+1, infoArray[entry].value[0]); |
| #endif |
| return true; |
| #ifdef SUPPORT_HLO |
| case OP_X_AGET_QUICK: |
| case OP_X_AGET_OBJECT_QUICK: |
| case OP_X_AGET_BOOLEAN_QUICK: |
| case OP_X_AGET_BYTE_QUICK: |
| case OP_X_AGET_CHAR_QUICK: |
| case OP_X_AGET_SHORT_QUICK: |
| vA = FETCH(1) & 0xff; |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| case OP_X_AGET_WIDE_QUICK: |
| vA = FETCH(1) & 0xff; |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| return false; |
| case OP_X_DEREF_GET: |
| case OP_X_DEREF_GET_OBJECT: |
| case OP_X_DEREF_GET_BOOLEAN: |
| case OP_X_DEREF_GET_BYTE: |
| case OP_X_DEREF_GET_CHAR: |
| case OP_X_DEREF_GET_SHORT: |
| vA = FETCH(1) & 0xff; |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| return false; |
| case OP_X_DEREF_GET_WIDE: |
| vA = FETCH(1) & 0xff; |
| constWorklist[num_const_worklist] = vA; |
| num_const_worklist++; |
| constWorklist[num_const_worklist] = vA+1; |
| num_const_worklist++; |
| return false; |
| #endif |
| } |
| return false; |
| } |
| |
| //! This function updates infoArray with virtual registers accessed when lowering the bytecode, and returns size of the bytecode in unit of u2 |
| |
| //! uses of virtual registers are added to infoArray first |
| int getVirtualRegInfo(VirtualRegInfo* infoArray) { |
| u2 inst_op = INST_INST(inst); |
| u2 vA = 0, vB = 0, vref, vindex; |
| u2 v1, v2, length, vD, vG, vE, vF, count; |
| u4 v1_u4, v2_u4; |
| int kk, num, num_entry; |
| s4 tmp_s4; |
| s2 tmp_s2; |
| u4 tmp_u4; |
| int codeSize = 0; |
| num_regs_per_bytecode = 0; |
| //update infoArray[xx].allocConstraints |
| for(num = 0; num < MAX_REG_PER_BYTECODE; num++) { |
| for(kk = 0; kk < 8; kk++) { |
| infoArray[num].allocConstraints[kk].physicalReg = (PhysicalReg)kk; |
| infoArray[num].allocConstraints[kk].count = 0; |
| } |
| } |
| |
| switch (inst_op) { |
| case OP_NOP: |
| codeSize = 1; |
| break; |
| case OP_MOVE: |
| case OP_MOVE_OBJECT: |
| case OP_MOVE_FROM16: |
| case OP_MOVE_OBJECT_FROM16: |
| case OP_MOVE_16: |
| case OP_MOVE_OBJECT_16: |
| if(inst_op == OP_MOVE || inst_op == OP_MOVE_OBJECT) { |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| codeSize = 1; |
| } |
| else if(inst_op == OP_MOVE_FROM16 || inst_op == OP_MOVE_OBJECT_FROM16) { |
| vA = INST_AA(inst); |
| vB = FETCH(1); |
| codeSize = 2; |
| } |
| else if(inst_op == OP_MOVE_16 || inst_op == OP_MOVE_OBJECT_16) { |
| vA = FETCH(1); |
| vB = FETCH(2); |
| codeSize = 3; |
| } |
| infoArray[1].regNum = vA; //dst |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = vB; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_MOVE_WIDE: |
| case OP_MOVE_WIDE_FROM16: |
| case OP_MOVE_WIDE_16: |
| if(inst_op == OP_MOVE_WIDE) { |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| codeSize = 1; |
| } |
| else if(inst_op == OP_MOVE_WIDE_FROM16) { |
| vA = INST_AA(inst); |
| vB = FETCH(1); |
| codeSize = 2; |
| } |
| else if(inst_op == OP_MOVE_WIDE_16) { |
| vA = FETCH(1); |
| vB = FETCH(2); |
| codeSize = 3; |
| } |
| infoArray[1].regNum = vA; //dst |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[0].regNum = vB; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_MOVE_RESULT: //access memory |
| case OP_MOVE_RESULT_OBJECT: |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| codeSize = 1; |
| num_regs_per_bytecode = 1; |
| break; |
| case OP_MOVE_RESULT_WIDE: //note: 2 destinations |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| codeSize = 1; |
| num_regs_per_bytecode = 1; |
| break; |
| case OP_MOVE_EXCEPTION: //access memory |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| codeSize = 1; |
| num_regs_per_bytecode = 1; |
| break; |
| case OP_RETURN_VOID: |
| case OP_RETURN_VOID_BARRIER: |
| codeSize = 1; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| num_regs_per_bytecode = 0; |
| break; |
| case OP_RETURN: |
| case OP_RETURN_OBJECT: |
| vA = INST_AA(inst); |
| codeSize = 1; |
| infoArray[0].regNum = vA; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| num_regs_per_bytecode = 1; |
| break; |
| case OP_RETURN_WIDE: |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 1; |
| codeSize = 1; |
| break; |
| case OP_CONST_4: |
| vA = INST_A(inst); |
| tmp_s4 = (s4) (INST_B(inst) << 28) >> 28; |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 1; |
| codeSize = 1; |
| break; |
| case OP_CONST_16: |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 1; |
| codeSize = 2; |
| break; |
| case OP_CONST: |
| vA = INST_AA(inst); |
| tmp_u4 = FETCH(1); |
| tmp_u4 |= (u4)FETCH(2) << 16; |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 1; |
| codeSize = 3; |
| break; |
| case OP_CONST_HIGH16: |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 1; |
| codeSize = 2; |
| break; |
| case OP_CONST_WIDE_16: |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vA+1; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| codeSize = 2; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_CONST_WIDE_32: |
| vA = INST_AA(inst); |
| tmp_u4 = FETCH(1); |
| tmp_u4 |= (u4)FETCH(2) << 16; |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vA+1; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| codeSize = 3; |
| break; |
| case OP_CONST_WIDE: |
| vA = INST_AA(inst); |
| tmp_u4 = FETCH(1); |
| tmp_u4 |= (u8)FETCH(2) << 16; |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| tmp_u4 = (u8)FETCH(3); |
| tmp_u4 |= (u8)FETCH(4) << 16; |
| infoArray[1].regNum = vA+1; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| codeSize = 5; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_CONST_WIDE_HIGH16: |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vA+1; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| codeSize = 2; |
| break; |
| case OP_CONST_STRING: |
| case OP_CONST_STRING_JUMBO: |
| case OP_CONST_CLASS: |
| vA = INST_AA(inst); |
| if(inst_op == OP_CONST_STRING || inst_op == OP_CONST_CLASS) |
| codeSize = 2; |
| else if(inst_op == OP_CONST_STRING_JUMBO) |
| codeSize = 3; |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[0].allocConstraints[PhysicalReg_EAX].count = 1; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| num_regs_per_bytecode = 1; |
| break; |
| case OP_MONITOR_ENTER: |
| vA = INST_AA(inst); |
| codeSize = 1; |
| infoArray[0].regNum = vA; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 1; |
| break; |
| case OP_MONITOR_EXIT: |
| vA = INST_AA(inst); |
| codeSize = 1; |
| infoArray[0].regNum = vA; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); //eax is used as return value from c function |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 1; |
| break; |
| case OP_CHECK_CAST: |
| codeSize = 2; |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_ECX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 1; |
| break; |
| case OP_INSTANCE_OF: |
| codeSize = 2; |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| infoArray[0].regNum = vB; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vA; //dst |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_ARRAY_LENGTH: |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| codeSize = 1; |
| infoArray[0].regNum = vB; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vA; //dst |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| //%edx is used in this bytecode, update currentBB->allocConstraints |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_NEW_INSTANCE: |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //dst |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[0].allocConstraints[PhysicalReg_EAX].count = 1; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_ECX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 1; |
| codeSize = 2; |
| break; |
| case OP_NEW_ARRAY: |
| vA = INST_A(inst); //destination |
| vB = INST_B(inst); //length |
| infoArray[0].regNum = vB; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vA; //dst |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[1].allocConstraints[PhysicalReg_EAX].count = 1; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 2; |
| codeSize = 2; |
| break; |
| case OP_FILLED_NEW_ARRAY: {//update return value |
| //can use up to 5 registers to fill the content of array |
| length = INST_B(inst); |
| u2 vv = FETCH(2); |
| v1 = vv & 0xf; |
| v2 = (vv >> 4) & 0xf; |
| u2 v3 = (vv >> 8) & 0xf; |
| u2 v4 = (vv >> 12) & 0xf; |
| u2 v5 = INST_A(inst); |
| if(length >= 1) { |
| infoArray[0].regNum = v1; //src |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| } |
| if(length >= 2) { |
| infoArray[1].regNum = v2; //src |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| } |
| if(length >= 3) { |
| infoArray[2].regNum = v3; //src |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_U; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| } |
| if(length >= 4) { |
| infoArray[3].regNum = v4; //src |
| infoArray[3].refCount = 1; |
| infoArray[3].accessType = REGACCESS_U; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| } |
| if(length >= 5) { |
| infoArray[4].regNum = v5; //src |
| infoArray[4].refCount = 1; |
| infoArray[4].accessType = REGACCESS_U; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| } |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = length; |
| codeSize = 3; |
| break; |
| } |
| case OP_FILLED_NEW_ARRAY_RANGE: {//use "length" virtual registers |
| length = INST_AA(inst); |
| u4 vC = (u4)FETCH(2); |
| for(kk = 0; kk < length; kk++) { |
| infoArray[kk].regNum = vC+kk; //src |
| infoArray[kk].refCount = 1; |
| infoArray[kk].accessType = REGACCESS_U; |
| infoArray[kk].physicalType = LowOpndRegType_gp; |
| } |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = length; |
| codeSize = 3; |
| break; |
| } |
| case OP_FILL_ARRAY_DATA: //update content of array, read memory |
| vA = INST_AA(inst); //use virtual register, but has side-effect, update memory |
| infoArray[0].regNum = vA; //use |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 1; |
| codeSize = 3; |
| break; |
| case OP_THROW: //update glue->exception |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //use |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 1; |
| codeSize = 1; |
| break; |
| case OP_THROW_VERIFICATION_ERROR: |
| num_regs_per_bytecode = 0; |
| codeSize = 2; |
| break; |
| case OP_GOTO: |
| codeSize = 1; |
| num_regs_per_bytecode = 0; |
| break; |
| case OP_GOTO_16: |
| codeSize = 2; |
| num_regs_per_bytecode = 0; |
| break; |
| case OP_GOTO_32: |
| codeSize = 3; |
| num_regs_per_bytecode = 0; |
| break; |
| case OP_PACKED_SWITCH: |
| case OP_SPARSE_SWITCH: |
| vA = INST_AA(inst); |
| codeSize = 3; |
| infoArray[0].regNum = vA; //use |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 1; |
| break; |
| |
| case OP_CMPL_FLOAT: //move 32 bits from memory to lower part of XMM register |
| case OP_CMPG_FLOAT: |
| codeSize = 2; |
| vA = INST_AA(inst); |
| v1_u4 = FETCH(1) & 0xff; |
| v2_u4 = FETCH(1) >> 8; |
| num_regs_per_bytecode = 1; |
| infoArray[0].regNum = v1_u4; //use ss or sd CHECK |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_ss; |
| infoArray[1].regNum = v2_u4; //use |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_ss; |
| num_regs_per_bytecode = 3; |
| num_entry = 2; |
| infoArray[num_entry].regNum = vA; //define |
| infoArray[num_entry].refCount = 1; |
| infoArray[num_entry].accessType = REGACCESS_D; |
| infoArray[num_entry].physicalType = LowOpndRegType_gp; |
| break; |
| case OP_CMPL_DOUBLE: //move 64 bits from memory to lower part of XMM register |
| case OP_CMPG_DOUBLE: |
| case OP_CMP_LONG: //load v1, v1+1, v2, v2+1 to gpr |
| codeSize = 2; |
| vA = INST_AA(inst); |
| v1_u4 = FETCH(1) & 0xff; |
| v2_u4 = FETCH(1) >> 8; |
| num_regs_per_bytecode = 1; |
| if(inst_op == OP_CMP_LONG) { |
| infoArray[0].regNum = v1_u4; //use |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = v1_u4 + 1; //use |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = v2_u4; //use |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_U; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = v2_u4 + 1; //use |
| infoArray[3].refCount = 1; |
| infoArray[3].accessType = REGACCESS_U; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 5; |
| num_entry = 4; |
| infoArray[num_entry].regNum = vA; //define |
| infoArray[num_entry].refCount = 2; |
| infoArray[num_entry].accessType = REGACCESS_D; |
| infoArray[num_entry].physicalType = LowOpndRegType_gp; |
| } |
| else { |
| infoArray[0].regNum = v1_u4; //use ss or sd CHECK |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = v2_u4; //use |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 3; |
| num_entry = 2; |
| infoArray[num_entry].regNum = vA; //define |
| infoArray[num_entry].refCount = 1; |
| infoArray[num_entry].accessType = REGACCESS_D; |
| infoArray[num_entry].physicalType = LowOpndRegType_gp; |
| } |
| break; |
| case OP_IF_EQ: |
| case OP_IF_NE: |
| case OP_IF_LT: |
| case OP_IF_GE: |
| case OP_IF_GT: |
| case OP_IF_LE: |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| infoArray[0].regNum = vA; //use |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vB; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| codeSize =12; |
| break; |
| case OP_IF_EQZ: |
| case OP_IF_NEZ: |
| case OP_IF_LTZ: |
| case OP_IF_GEZ: |
| case OP_IF_GTZ: |
| case OP_IF_LEZ: |
| vA = INST_AA(inst); |
| infoArray[0].regNum = vA; //use |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 1; |
| codeSize = 2; |
| break; |
| case OP_AGET: |
| codeSize = 2; |
| case OP_AGET_WIDE: |
| codeSize = 2; |
| case OP_AGET_OBJECT: |
| codeSize = 2; |
| case OP_AGET_BOOLEAN: //movez 8 |
| codeSize = 2; |
| case OP_AGET_BYTE: //moves 8 |
| codeSize = 2; |
| case OP_AGET_CHAR: //movez 16 |
| codeSize = 2; |
| case OP_AGET_SHORT: //moves 16 |
| codeSize = 2; |
| vA = INST_AA(inst); |
| vref = FETCH(1) & 0xff; |
| vindex = FETCH(1) >> 8; |
| if(inst_op == OP_AGET_WIDE) { |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_xmm; //64, 128 not used in lowering |
| } else { |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| } |
| infoArray[0].regNum = vref; //use |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vindex; //use |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_APUT: |
| case OP_APUT_WIDE: |
| case OP_APUT_OBJECT: |
| case OP_APUT_BOOLEAN: |
| case OP_APUT_BYTE: |
| case OP_APUT_CHAR: |
| case OP_APUT_SHORT: |
| vA = INST_AA(inst); |
| vref = FETCH(1) & 0xff; |
| vindex = FETCH(1) >> 8; |
| codeSize = 2; |
| if(inst_op == OP_APUT_WIDE) { |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; //64, 128 not used in lowering |
| } else { |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| } |
| infoArray[1].regNum = vref; //use |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = vindex; //use |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_U; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| if(inst_op == OP_APUT_OBJECT) { |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| } |
| num_regs_per_bytecode = 3; |
| break; |
| |
| case OP_IGET: |
| case OP_IGET_WIDE: |
| case OP_IGET_OBJECT: |
| case OP_IGET_VOLATILE: |
| case OP_IGET_WIDE_VOLATILE: |
| case OP_IGET_OBJECT_VOLATILE: |
| case OP_IGET_BOOLEAN: |
| case OP_IGET_BYTE: |
| case OP_IGET_CHAR: |
| case OP_IGET_SHORT: |
| case OP_IGET_QUICK: |
| case OP_IGET_WIDE_QUICK: |
| case OP_IGET_OBJECT_QUICK: |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| codeSize = 2; |
| if(inst_op == OP_IGET_WIDE || inst_op == OP_IGET_WIDE_QUICK) { |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_xmm; //64 |
| } else if(inst_op == OP_IGET_WIDE_VOLATILE) { |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = vA+1; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| } else { |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| } |
| infoArray[0].regNum = vB; //object instance |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| if(inst_op == OP_IGET_WIDE_VOLATILE) |
| num_regs_per_bytecode = 3; |
| else |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_IPUT: |
| case OP_IPUT_WIDE: |
| case OP_IPUT_OBJECT: |
| case OP_IPUT_VOLATILE: |
| case OP_IPUT_WIDE_VOLATILE: |
| case OP_IPUT_OBJECT_VOLATILE: |
| case OP_IPUT_BOOLEAN: |
| case OP_IPUT_BYTE: |
| case OP_IPUT_CHAR: |
| case OP_IPUT_SHORT: |
| case OP_IPUT_QUICK: |
| case OP_IPUT_WIDE_QUICK: |
| case OP_IPUT_OBJECT_QUICK: |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| codeSize = 2; |
| if(inst_op == OP_IPUT_WIDE || inst_op == OP_IPUT_WIDE_QUICK || inst_op == OP_IPUT_WIDE_VOLATILE) { |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; //64 |
| } else { |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| } |
| infoArray[1].regNum = vB; //object instance |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_SGET: |
| case OP_SGET_WIDE: |
| case OP_SGET_OBJECT: |
| case OP_SGET_VOLATILE: |
| case OP_SGET_WIDE_VOLATILE: |
| case OP_SGET_OBJECT_VOLATILE: |
| case OP_SGET_BOOLEAN: |
| case OP_SGET_BYTE: |
| case OP_SGET_CHAR: |
| case OP_SGET_SHORT: |
| vA = INST_AA(inst); |
| codeSize = 2; |
| if(inst_op == OP_SGET_WIDE) { |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_xmm; //64 |
| } else if(inst_op == OP_SGET_WIDE_VOLATILE) { |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vA+1; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| } else { |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_D; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| } |
| if(inst_op == OP_SGET_WIDE_VOLATILE) |
| num_regs_per_bytecode = 2; |
| else |
| num_regs_per_bytecode = 1; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| break; |
| case OP_SPUT: |
| case OP_SPUT_WIDE: |
| case OP_SPUT_OBJECT: |
| case OP_SPUT_VOLATILE: |
| case OP_SPUT_WIDE_VOLATILE: |
| case OP_SPUT_OBJECT_VOLATILE: |
| case OP_SPUT_BOOLEAN: |
| case OP_SPUT_BYTE: |
| case OP_SPUT_CHAR: |
| case OP_SPUT_SHORT: |
| vA = INST_AA(inst); |
| codeSize = 2; |
| if(inst_op == OP_SPUT_WIDE || inst_op == OP_SPUT_WIDE_VOLATILE) { |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; //64 |
| } else { |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| } |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| num_regs_per_bytecode = 1; |
| break; |
| |
| case OP_INVOKE_VIRTUAL: |
| case OP_INVOKE_SUPER: |
| case OP_INVOKE_DIRECT: |
| case OP_INVOKE_STATIC: |
| case OP_INVOKE_INTERFACE: |
| case OP_INVOKE_VIRTUAL_QUICK: |
| case OP_INVOKE_SUPER_QUICK: |
| codeSize = 3; |
| vD = FETCH(2) & 0xf; //object for virtual,direct & interface |
| count = INST_B(inst); |
| vE = (FETCH(2) >> 4) & 0xf; |
| vF = (FETCH(2) >> 8) & 0xf; |
| vG = (FETCH(2) >> 12) & 0xf; |
| vA = INST_A(inst); //5th argument |
| if(count == 0) { |
| if(inst_op == OP_INVOKE_VIRTUAL || inst_op == OP_INVOKE_DIRECT || |
| inst_op == OP_INVOKE_INTERFACE || inst_op == OP_INVOKE_VIRTUAL_QUICK || |
| inst_op == OP_INVOKE_SUPER_QUICK) { |
| infoArray[0].regNum = vD; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 1; |
| } |
| num_regs_per_bytecode = 0; |
| } |
| else num_regs_per_bytecode = count; |
| if(count >= 1) { |
| infoArray[0].regNum = vD; |
| if(inst_op == OP_INVOKE_VIRTUAL_QUICK || |
| inst_op == OP_INVOKE_SUPER_QUICK) { |
| infoArray[0].refCount = 2; |
| } else if(inst_op == OP_INVOKE_VIRTUAL || inst_op == OP_INVOKE_DIRECT || inst_op == OP_INVOKE_INTERFACE) { |
| infoArray[0].refCount = 2; |
| } else { |
| infoArray[0].refCount = 1; |
| } |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| } |
| if(count >= 2) { |
| infoArray[1].regNum = vE; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| } |
| if(count >= 3) { |
| infoArray[2].regNum = vF; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_U; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| } |
| if(count >= 4) { |
| infoArray[3].regNum = vG; |
| infoArray[3].refCount = 1; |
| infoArray[3].accessType = REGACCESS_U; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| } |
| if(count >= 5) { |
| infoArray[4].regNum = vA; |
| infoArray[4].refCount = 1; |
| infoArray[4].accessType = REGACCESS_U; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| } |
| if(inst_op != OP_INVOKE_VIRTUAL_QUICK && inst_op != OP_INVOKE_SUPER_QUICK) |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_ECX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| break; |
| case OP_INVOKE_VIRTUAL_RANGE: |
| case OP_INVOKE_SUPER_RANGE: |
| case OP_INVOKE_DIRECT_RANGE: |
| case OP_INVOKE_STATIC_RANGE: |
| case OP_INVOKE_INTERFACE_RANGE: |
| case OP_INVOKE_VIRTUAL_QUICK_RANGE: |
| case OP_INVOKE_SUPER_QUICK_RANGE: |
| codeSize = 3; |
| vD = FETCH(2); |
| count = INST_AA(inst); |
| if(count == 0) { |
| if(inst_op == OP_INVOKE_VIRTUAL_RANGE || inst_op == OP_INVOKE_DIRECT_RANGE || |
| inst_op == OP_INVOKE_INTERFACE_RANGE || inst_op == OP_INVOKE_VIRTUAL_QUICK_RANGE || |
| inst_op == OP_INVOKE_SUPER_QUICK_RANGE) { |
| infoArray[0].regNum = vD; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| } |
| } |
| if(count > 0) { //same for count > 10 |
| for(kk = 0; kk < count; kk++) { |
| infoArray[kk].regNum = vD+kk; //src |
| if(kk == 0 && (inst_op == OP_INVOKE_VIRTUAL_QUICK_RANGE || |
| inst_op == OP_INVOKE_SUPER_QUICK_RANGE)) |
| infoArray[kk].refCount = 2; |
| else if(kk == 0 && (inst_op == OP_INVOKE_VIRTUAL_RANGE || |
| inst_op == OP_INVOKE_DIRECT_RANGE || |
| inst_op == OP_INVOKE_INTERFACE_RANGE)) |
| infoArray[kk].refCount = 2; |
| else |
| infoArray[kk].refCount = 1; |
| infoArray[kk].accessType = REGACCESS_U; |
| infoArray[kk].physicalType = LowOpndRegType_gp; |
| } |
| } |
| if(inst_op != OP_INVOKE_VIRTUAL_QUICK_RANGE && inst_op != OP_INVOKE_SUPER_QUICK_RANGE) |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_ECX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = count; |
| break; |
| case OP_NEG_INT: |
| case OP_NOT_INT: |
| case OP_NEG_FLOAT: |
| vA = INST_A(inst); //destination |
| vB = INST_B(inst); |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| codeSize = 1; |
| break; |
| case OP_NEG_LONG: |
| case OP_NOT_LONG: |
| case OP_NEG_DOUBLE: |
| vA = INST_A(inst); //destination |
| vB = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_INT_TO_LONG: //hard-coded registers |
| vA = INST_A(inst); //destination |
| vB = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; //save from %eax |
| infoArray[1].allocConstraints[PhysicalReg_EAX].count = 1; |
| infoArray[2].regNum = vA+1; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[2].allocConstraints[PhysicalReg_EDX].count = 1; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[0].allocConstraints[PhysicalReg_EAX].count = 1; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_INT_TO_FLOAT: //32 to 32 |
| case OP_INT_TO_DOUBLE: //32 to 64 |
| case OP_LONG_TO_FLOAT: //64 to 32 |
| case OP_LONG_TO_DOUBLE: //64 to 64 |
| case OP_FLOAT_TO_DOUBLE: //32 to 64 |
| case OP_DOUBLE_TO_FLOAT: //64 to 32 |
| vA = INST_A(inst); //destination |
| vB = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| if(inst_op == OP_INT_TO_DOUBLE || inst_op == OP_LONG_TO_DOUBLE || inst_op == OP_FLOAT_TO_DOUBLE) |
| infoArray[1].physicalType = LowOpndRegType_fs; |
| else |
| infoArray[1].physicalType = LowOpndRegType_fs_s; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| if(inst_op == OP_INT_TO_FLOAT || inst_op == OP_INT_TO_DOUBLE || inst_op == OP_FLOAT_TO_DOUBLE) |
| infoArray[0].physicalType = LowOpndRegType_fs_s; //float |
| else |
| infoArray[0].physicalType = LowOpndRegType_fs; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_LONG_TO_INT: |
| vA = INST_A(inst); //destination |
| vB = INST_B(inst); |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| codeSize = 1; |
| break; |
| case OP_FLOAT_TO_INT: |
| case OP_DOUBLE_TO_INT: //for reaching-def analysis |
| vA = INST_A(inst); //destination |
| vB = INST_B(inst); |
| codeSize = 1; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 3; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_fs_s; //store_int_fp_stack_VR |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| if(inst_op == OP_DOUBLE_TO_INT) |
| infoArray[0].physicalType = LowOpndRegType_fs; |
| else |
| infoArray[0].physicalType = LowOpndRegType_fs_s; |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_FLOAT_TO_LONG: |
| case OP_DOUBLE_TO_LONG: |
| vA = INST_A(inst); //destination |
| vB = INST_B(inst); |
| codeSize = 1; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 3; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_fs; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| if(inst_op == OP_DOUBLE_TO_LONG) |
| infoArray[0].physicalType = LowOpndRegType_fs; |
| else |
| infoArray[0].physicalType = LowOpndRegType_fs_s; |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_INT_TO_BYTE: |
| case OP_INT_TO_CHAR: |
| case OP_INT_TO_SHORT: |
| vA = INST_A(inst); //destination |
| vB = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| break; |
| |
| case OP_ADD_INT: |
| case OP_SUB_INT: |
| case OP_MUL_INT: |
| case OP_AND_INT: |
| case OP_OR_INT: |
| case OP_XOR_INT: |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| codeSize = 2; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_DIV_INT: |
| case OP_REM_INT: |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| codeSize = 2; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 2; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].allocConstraints[PhysicalReg_EAX].count = 1; //for v1 |
| if(inst_op == OP_REM_INT) |
| infoArray[2].allocConstraints[PhysicalReg_EDX].count = 1;//vA |
| else |
| infoArray[2].allocConstraints[PhysicalReg_EAX].count = 1;//vA |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_SHL_INT: |
| case OP_SHR_INT: |
| case OP_USHR_INT: |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| codeSize = 2; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = v2; // in ecx |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[1].allocConstraints[PhysicalReg_ECX].count = 1; |
| updateCurrentBBWithConstraints(PhysicalReg_ECX); |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_ADD_LONG: |
| case OP_SUB_LONG: |
| case OP_AND_LONG: |
| case OP_OR_LONG: |
| case OP_XOR_LONG: |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| codeSize = 2; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_MUL_LONG: //used int |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = v1+1; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = v2; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_U; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = v2+1; |
| infoArray[3].refCount = 1; |
| infoArray[3].accessType = REGACCESS_U; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = vA; |
| infoArray[4].refCount = 1; |
| infoArray[4].accessType = REGACCESS_D; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = vA+1; |
| infoArray[5].refCount = 1; |
| infoArray[5].accessType = REGACCESS_D; |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 6; |
| codeSize = 2; |
| break; |
| case OP_DIV_LONG: //v1: xmm v2,vA: |
| case OP_REM_LONG: |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = v2+1; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_U; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = vA; |
| infoArray[3].refCount = 1; |
| infoArray[3].accessType = REGACCESS_D; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = vA+1; |
| infoArray[4].refCount = 1; |
| infoArray[4].accessType = REGACCESS_D; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 5; |
| codeSize = 2; |
| break; |
| case OP_SHL_LONG: //v2: 32, move_ss; v1,vA: xmm CHECK |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_ss; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 3; |
| codeSize = 2; |
| break; |
| case OP_SHR_LONG: //v2: 32, move_ss; v1,vA: xmm CHECK |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_ss; |
| infoArray[2].regNum = v1+1; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_U; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = vA; |
| infoArray[3].refCount = 1; |
| infoArray[3].accessType = REGACCESS_D; |
| infoArray[3].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 4; |
| codeSize = 2; |
| break; |
| case OP_USHR_LONG: //v2: move_ss; v1,vA: move_sd |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; //sd |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_ss; //ss |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_xmm; //sd |
| num_regs_per_bytecode = 3; |
| codeSize = 2; |
| break; |
| case OP_ADD_FLOAT: //move_ss |
| case OP_SUB_FLOAT: |
| case OP_MUL_FLOAT: |
| case OP_DIV_FLOAT: |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| codeSize = 2; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_ss; |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_ss; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_ss; |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_REM_FLOAT: //32 bit GPR, fp_stack for output |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| codeSize = 2; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_fs_s; |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_ADD_DOUBLE: //move_sd |
| case OP_SUB_DOUBLE: |
| case OP_MUL_DOUBLE: |
| case OP_DIV_DOUBLE: |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| codeSize = 2; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 3; |
| break; |
| case OP_REM_DOUBLE: //64 bit XMM, fp_stack for output |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| v2 = *((u1*)rPC + 3); |
| codeSize = 2; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_D; |
| infoArray[2].physicalType = LowOpndRegType_fs; |
| infoArray[0].regNum = v1; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 3; |
| break; |
| |
| case OP_ADD_INT_2ADDR: |
| case OP_SUB_INT_2ADDR: |
| case OP_MUL_INT_2ADDR: |
| case OP_AND_INT_2ADDR: |
| case OP_OR_INT_2ADDR: |
| case OP_XOR_INT_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 2; |
| infoArray[1].accessType = REGACCESS_UD; //use then define |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_DIV_INT_2ADDR: |
| case OP_REM_INT_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 3; |
| infoArray[1].accessType = REGACCESS_UD; //use then define |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].allocConstraints[PhysicalReg_EAX].count = 1; //for v1 is vA |
| if(inst_op == OP_REM_INT_2ADDR) |
| infoArray[1].allocConstraints[PhysicalReg_EDX].count = 1;//vA |
| else |
| infoArray[1].allocConstraints[PhysicalReg_EAX].count = 1;//vA |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_SHL_INT_2ADDR: |
| case OP_SHR_INT_2ADDR: |
| case OP_USHR_INT_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 2; |
| infoArray[1].accessType = REGACCESS_UD; //use then define |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[0].allocConstraints[PhysicalReg_ECX].count = 1; //v2 |
| updateCurrentBBWithConstraints(PhysicalReg_ECX); |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_ADD_LONG_2ADDR: |
| case OP_SUB_LONG_2ADDR: |
| case OP_AND_LONG_2ADDR: |
| case OP_OR_LONG_2ADDR: |
| case OP_XOR_LONG_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 2; |
| infoArray[1].accessType = REGACCESS_UD; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_MUL_LONG_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| codeSize = 1; |
| num_regs_per_bytecode = 4; |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = v2+1; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 2; |
| infoArray[2].accessType = REGACCESS_UD; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = vA+1; |
| infoArray[3].refCount = 2; |
| infoArray[3].accessType = REGACCESS_UD; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| break; |
| case OP_DIV_LONG_2ADDR: //vA used as xmm, then updated as gps |
| case OP_REM_LONG_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| num_regs_per_bytecode = 5; |
| codeSize = 1; |
| infoArray[0].regNum = vA; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = v2; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = v2+1; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_U; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = vA; |
| infoArray[3].refCount = 1; |
| infoArray[3].accessType = REGACCESS_D; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = vA+1; |
| infoArray[4].refCount = 1; |
| infoArray[4].accessType = REGACCESS_D; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| break; |
| case OP_SHL_LONG_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| num_regs_per_bytecode = 2; |
| codeSize = 1; |
| infoArray[0].regNum = v2; //ss |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_ss; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 2; |
| infoArray[1].accessType = REGACCESS_UD; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| break; |
| case OP_SHR_LONG_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| num_regs_per_bytecode = 3; |
| codeSize = 1; |
| infoArray[0].regNum = v2; //ss |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_ss; |
| infoArray[1].regNum = vA+1; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = vA; |
| infoArray[2].refCount = 2; |
| infoArray[2].accessType = REGACCESS_UD; |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| break; |
| case OP_USHR_LONG_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| num_regs_per_bytecode = 2; |
| codeSize = 1; |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_ss; //ss CHECK |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 2; |
| infoArray[1].accessType = REGACCESS_UD; |
| infoArray[1].physicalType = LowOpndRegType_xmm; //sd |
| break; |
| case OP_ADD_FLOAT_2ADDR: |
| case OP_SUB_FLOAT_2ADDR: |
| case OP_MUL_FLOAT_2ADDR: |
| case OP_DIV_FLOAT_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 2; |
| infoArray[1].accessType = REGACCESS_UD; |
| infoArray[1].physicalType = LowOpndRegType_ss; |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_ss; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_REM_FLOAT_2ADDR: //load vA as GPR, store from fs |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 2; |
| infoArray[1].accessType = REGACCESS_UD; |
| infoArray[1].physicalType = LowOpndRegType_gp; //CHECK |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_ADD_DOUBLE_2ADDR: |
| case OP_SUB_DOUBLE_2ADDR: |
| case OP_MUL_DOUBLE_2ADDR: |
| case OP_DIV_DOUBLE_2ADDR: |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 2; |
| infoArray[1].accessType = REGACCESS_UD; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_REM_DOUBLE_2ADDR: //load to xmm, store from fs |
| vA = INST_A(inst); |
| v2 = INST_B(inst); |
| codeSize = 1; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 2; |
| infoArray[1].accessType = REGACCESS_UD; |
| infoArray[1].physicalType = LowOpndRegType_xmm; //CHECK |
| infoArray[0].regNum = v2; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| num_regs_per_bytecode = 2; |
| break; |
| |
| case OP_ADD_INT_LIT16: |
| case OP_RSUB_INT: |
| case OP_MUL_INT_LIT16: |
| case OP_AND_INT_LIT16: |
| case OP_OR_INT_LIT16: |
| case OP_XOR_INT_LIT16: |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| codeSize = 2; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_DIV_INT_LIT16: |
| case OP_REM_INT_LIT16: |
| vA = INST_A(inst); |
| vB = INST_B(inst); |
| codeSize = 2; |
| tmp_s4 = (s2)FETCH(1); |
| tmp_s2 = tmp_s4; |
| if(tmp_s2 == 0) { |
| num_regs_per_bytecode = 0; |
| break; |
| } |
| infoArray[1].regNum = vA; //in edx for rem, in eax |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = vB; //in eax |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| if(inst_op == OP_DIV_INT_LIT16) { |
| int power = isPowerOfTwo(tmp_s2); |
| if(power >= 1) { /* divide by a power of 2 constant */ |
| infoArray[1].refCount = 1; |
| break; |
| } |
| } |
| if(tmp_s2 == -1) |
| infoArray[1].refCount = 2; |
| else |
| infoArray[1].refCount = 1; |
| if(inst_op == OP_REM_INT_LIT16) |
| infoArray[1].allocConstraints[PhysicalReg_EDX].count = 1; |
| else |
| infoArray[1].allocConstraints[PhysicalReg_EAX].count = 1; |
| infoArray[0].allocConstraints[PhysicalReg_EAX].count = 1; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| break; |
| case OP_ADD_INT_LIT8: |
| case OP_RSUB_INT_LIT8: |
| case OP_MUL_INT_LIT8: |
| case OP_AND_INT_LIT8: |
| case OP_OR_INT_LIT8: |
| case OP_XOR_INT_LIT8: |
| case OP_SHL_INT_LIT8: |
| case OP_SHR_INT_LIT8: |
| case OP_USHR_INT_LIT8: |
| codeSize = 2; |
| vA = INST_AA(inst); |
| vB = (u2)FETCH(1) & 0xff; |
| infoArray[1].regNum = vA; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| break; |
| case OP_DIV_INT_LIT8: |
| case OP_REM_INT_LIT8: |
| codeSize = 2; |
| vA = INST_AA(inst); |
| vB = (u2)FETCH(1) & 0xff; |
| tmp_s2 = (s2)FETCH(1) >> 8; |
| if(tmp_s2 == 0) { |
| num_regs_per_bytecode = 0; |
| break; |
| } |
| |
| infoArray[1].regNum = vA; |
| infoArray[1].accessType = REGACCESS_D; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[0].regNum = vB; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| num_regs_per_bytecode = 2; |
| if(inst_op == OP_DIV_INT_LIT8) { |
| int power = isPowerOfTwo(tmp_s2); |
| if(power >= 1) { /* divide by a power of 2 constant */ |
| infoArray[1].refCount = 1; |
| break; |
| } |
| } |
| |
| if(tmp_s2 == -1) |
| infoArray[1].refCount = 2; |
| else |
| infoArray[1].refCount = 1; |
| if(inst_op == OP_REM_INT_LIT8) |
| infoArray[1].allocConstraints[PhysicalReg_EDX].count = 1; |
| else |
| infoArray[1].allocConstraints[PhysicalReg_EAX].count = 1; |
| infoArray[0].allocConstraints[PhysicalReg_EAX].count = 1; |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| break; |
| case OP_EXECUTE_INLINE: //update glue->retval |
| case OP_EXECUTE_INLINE_RANGE: |
| u4 vC; |
| if(inst_op == OP_EXECUTE_INLINE) |
| num = INST_B(inst); |
| else |
| num = INST_AA(inst); |
| if(inst_op == OP_EXECUTE_INLINE) { |
| vC = FETCH(2) & 0xf; |
| vD = (FETCH(2) >> 4) & 0xf; |
| vE = (FETCH(2) >> 8) & 0xf; |
| vF = FETCH(2) >> 12; |
| } else { |
| vC = FETCH(2); |
| vD = vC + 1; |
| vE = vC + 2; |
| vF = vC + 3; |
| } |
| codeSize = 3; |
| if(num >= 1) { |
| infoArray[0].regNum = vC; |
| infoArray[0].refCount = 1; |
| infoArray[0].accessType = REGACCESS_U; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| } |
| if(num >= 2) { |
| infoArray[1].regNum = vD; |
| infoArray[1].refCount = 1; |
| infoArray[1].accessType = REGACCESS_U; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| } |
| if(num >= 3) { |
| infoArray[2].regNum = vE; |
| infoArray[2].refCount = 1; |
| infoArray[2].accessType = REGACCESS_U; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| } |
| if(num >= 4) { |
| infoArray[3].regNum = vF; |
| infoArray[3].refCount = 1; |
| infoArray[3].accessType = REGACCESS_U; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| } |
| updateCurrentBBWithConstraints(PhysicalReg_EAX); |
| updateCurrentBBWithConstraints(PhysicalReg_EDX); |
| num_regs_per_bytecode = num; |
| break; |
| #if FIXME |
| case OP_INVOKE_OBJECT_INIT_RANGE: |
| codeSize = 3; |
| num_regs_per_bytecode = 0; |
| break; |
| #endif |
| } |
| return codeSize; |
| } |
| //! Updates infoArray(TempRegInfo) with temporaries accessed by INVOKE_NO_RANGE |
| |
| //! |
| int updateInvokeNoRange(TempRegInfo* infoArray, int startInd) { |
| int j = startInd; |
| //invokeMethodNoRange |
| int count = INST_B(inst); |
| if(count == 5) { |
| infoArray[j].regNum = 22; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 4) { |
| infoArray[j].regNum = 23; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 3) { |
| infoArray[j].regNum = 24; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 2) { |
| infoArray[j].regNum = 25; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 1) { |
| infoArray[j].regNum = 26; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| return j; |
| } |
| //! Updates infoArray(TempRegInfo) with temporaries accessed by INVOKE_RANGE |
| |
| //! LOOP_COUNT is used to indicate a variable is live through a loop |
| int updateInvokeRange(TempRegInfo* infoArray, int startIndex) { |
| int j = startIndex; |
| int count = INST_AA(inst); |
| infoArray[j].regNum = 21; |
| if(count <= 10) { |
| infoArray[j].refCount = 1+count; //DU |
| } else { |
| infoArray[j].refCount = 2+3*LOOP_COUNT; |
| } |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| if(count >= 1 && count <= 10) { |
| infoArray[j].regNum = 22; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 2 && count <= 10) { |
| infoArray[j].regNum = 23; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 3 && count <= 10) { |
| infoArray[j].regNum = 24; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 4 && count <= 10) { |
| infoArray[j].regNum = 25; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 5 && count <= 10) { |
| infoArray[j].regNum = 26; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 6 && count <= 10) { |
| infoArray[j].regNum = 27; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 7 && count <= 10) { |
| infoArray[j].regNum = 28; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 8 && count <= 10) { |
| infoArray[j].regNum = 29; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count >= 9 && count <= 10) { |
| infoArray[j].regNum = 30; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count == 10) { |
| infoArray[j].regNum = 31; |
| infoArray[j].refCount = 2; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| if(count > 10) { |
| //NOTE: inside a loop, LOOP_COUNT can't be 1 |
| // if LOOP_COUNT is 1, it is likely that a logical register is freed inside the loop |
| // and the next iteration will have incorrect result |
| infoArray[j].regNum = 12; |
| infoArray[j].refCount = 1+3*LOOP_COUNT; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| infoArray[j].regNum = 13; |
| infoArray[j].refCount = 1+LOOP_COUNT; //DU |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| infoArray[j].regNum = 14; |
| //MUST be 2, otherwise, transferToState will think its state was in memory |
| infoArray[j].refCount = 2; //DU local |
| infoArray[j].physicalType = LowOpndRegType_gp; |
| j++; |
| } |
| return j; |
| } |
| |
| /* update temporaries used by RETURN bytecodes |
| a temporary is represented by <number, type of the temporary> |
| */ |
| int updateReturnCommon(TempRegInfo* infoArray) { |
| int numTmps; |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; //DU |
| infoArray[0].physicalType = LowOpndRegType_scratch; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| infoArray[2].regNum = PhysicalReg_EAX; |
| infoArray[2].refCount = 5; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[3].regNum = 1; |
| #if defined(ENABLE_TRACING)//WITH_DEBUGGER is true WITH_PROFILER can be false |
| infoArray[3].refCount = 6+4; |
| #else |
| infoArray[3].refCount = 6; //DU |
| #endif |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 2; |
| infoArray[4].refCount = 4; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = 5; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| infoArray[6].regNum = 10; |
| infoArray[6].refCount = 3; |
| infoArray[6].physicalType = LowOpndRegType_gp; |
| infoArray[7].regNum = 6; |
| infoArray[7].refCount = 4; //DU |
| infoArray[7].physicalType = LowOpndRegType_gp; |
| infoArray[8].regNum = 3; |
| infoArray[8].refCount = 3; |
| infoArray[8].physicalType = LowOpndRegType_gp; |
| infoArray[9].regNum = 7; |
| infoArray[9].refCount = 2; //DU |
| infoArray[9].physicalType = LowOpndRegType_gp; |
| numTmps = 12; |
| #if defined(ENABLE_TRACING) |
| infoArray[12].regNum = 4; |
| infoArray[12].refCount = 3; //DU |
| infoArray[12].physicalType = LowOpndRegType_gp; |
| infoArray[13].regNum = 3; |
| infoArray[13].refCount = 2; //DU |
| infoArray[13].physicalType = LowOpndRegType_scratch; |
| infoArray[14].regNum = 15; |
| infoArray[14].refCount = 2; //DU |
| infoArray[14].physicalType = LowOpndRegType_gp; |
| infoArray[15].regNum = 16; |
| infoArray[15].refCount = 2; //DU |
| infoArray[15].physicalType = LowOpndRegType_gp; |
| infoArray[16].regNum = PhysicalReg_EDX; |
| infoArray[16].refCount = 2; //DU |
| infoArray[16].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[17].regNum = 6; |
| infoArray[17].refCount = 2; //DU |
| infoArray[17].physicalType = LowOpndRegType_scratch; |
| numTmps = 18; |
| #endif |
| infoArray[10].regNum = 14; |
| infoArray[10].refCount = 2; //DU |
| infoArray[10].physicalType = LowOpndRegType_gp; |
| infoArray[11].regNum = 4; |
| infoArray[11].refCount = 2; //DU |
| infoArray[11].physicalType = LowOpndRegType_scratch; |
| #ifdef DEBUG_CALL_STACK |
| infoArray[numTmps].regNum = 5; |
| infoArray[numTmps].refCount = 2; |
| infoArray[numTmps].physicalType = LowOpndRegType_scratch; |
| numTmps++; |
| #endif |
| infoArray[numTmps].regNum = PhysicalReg_EBX; |
| /* used to hold chaining cell |
| updated to be returnAddr |
| then conditionally updated to zero |
| used to update inJitCodeCache |
| compare against zero to determine whether to jump to native code |
| jump to native code (%ebx) |
| */ |
| infoArray[numTmps].refCount = 3+1+1; |
| infoArray[numTmps].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| numTmps++; |
| infoArray[numTmps].regNum = 17; |
| infoArray[numTmps].refCount = 2; //DU |
| infoArray[numTmps].physicalType = LowOpndRegType_gp; |
| numTmps++; |
| infoArray[numTmps].regNum = 7; |
| infoArray[numTmps].refCount = 4; //DU |
| infoArray[numTmps].physicalType = LowOpndRegType_scratch; |
| numTmps++; |
| return numTmps; |
| } |
| |
| /* update temporaries used by predicted INVOKE_VIRTUAL & INVOKE_INTERFACE */ |
| int updateGenPrediction(TempRegInfo* infoArray, bool isInterface) { |
| infoArray[0].regNum = 40; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 41; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 32; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| |
| if(isInterface) { |
| infoArray[0].refCount = 2+2; |
| infoArray[1].refCount = 3+2-1; //for temp41, -1 for gingerbread |
| infoArray[3].regNum = 33; |
| infoArray[3].refCount = 4+1; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = PhysicalReg_EAX; |
| infoArray[4].refCount = 5; |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[5].regNum = PhysicalReg_ECX; |
| infoArray[5].refCount = 1+1+2; //used in ArgsDone (twice) |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[6].regNum = 10; |
| infoArray[6].refCount = 2; |
| infoArray[6].physicalType = LowOpndRegType_scratch; |
| infoArray[7].regNum = 9; |
| infoArray[7].refCount = 2; |
| infoArray[7].physicalType = LowOpndRegType_scratch; |
| infoArray[8].regNum = 8; |
| infoArray[8].refCount = 2; |
| infoArray[8].physicalType = LowOpndRegType_scratch; |
| infoArray[9].regNum = PhysicalReg_EDX; //space holder |
| infoArray[9].refCount = 1; |
| infoArray[9].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[10].regNum = 43; |
| infoArray[10].refCount = 3; |
| infoArray[10].physicalType = LowOpndRegType_gp; |
| infoArray[11].regNum = 44; |
| infoArray[11].refCount = 3; |
| infoArray[11].physicalType = LowOpndRegType_gp; |
| infoArray[12].regNum = 45; |
| infoArray[12].refCount = 2; |
| infoArray[12].physicalType = LowOpndRegType_gp; |
| infoArray[13].regNum = 7; |
| infoArray[13].refCount = 4; |
| infoArray[13].physicalType = LowOpndRegType_scratch; |
| return 14; |
| } else { //virtual or virtual_quick |
| infoArray[0].refCount = 2+2; |
| infoArray[1].refCount = 3+2-2; //for temp41, -2 for gingerbread |
| infoArray[2].refCount++; //for temp32 gingerbread |
| infoArray[3].regNum = 33; |
| infoArray[3].refCount = 4+1; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 34; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = PhysicalReg_EAX; |
| infoArray[5].refCount = 2; |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[6].regNum = PhysicalReg_ECX; |
| infoArray[6].refCount = 1+3+2; |
| infoArray[6].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[7].regNum = 10; |
| infoArray[7].refCount = 2; |
| infoArray[7].physicalType = LowOpndRegType_scratch; |
| infoArray[8].regNum = PhysicalReg_EDX; //space holder |
| infoArray[8].refCount = 1; |
| infoArray[8].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[9].regNum = 43; |
| infoArray[9].refCount = 3; |
| infoArray[9].physicalType = LowOpndRegType_gp; |
| infoArray[10].regNum = 44; |
| infoArray[10].refCount = 3; |
| infoArray[10].physicalType = LowOpndRegType_gp; |
| infoArray[11].regNum = 7; |
| infoArray[11].refCount = 4; |
| infoArray[11].physicalType = LowOpndRegType_scratch; |
| return 12; |
| } |
| } |
| |
| int updateMarkCard(TempRegInfo* infoArray, int j1/*valReg*/, |
| int j2/*tgtAddrReg*/, int j3/*scratchReg*/) { |
| infoArray[j3].regNum = 11; |
| infoArray[j3].physicalType = LowOpndRegType_gp; |
| infoArray[j3].refCount = 3; |
| infoArray[j3].is8Bit = true; |
| infoArray[j1].refCount++; |
| infoArray[j2].refCount += 2; |
| infoArray[j3+1].regNum = 6; |
| infoArray[j3+1].physicalType = LowOpndRegType_scratch; |
| infoArray[j3+1].refCount = 2; |
| return j3+2; |
| } |
| |
| int updateMarkCard_notNull(TempRegInfo* infoArray, |
| int j2/*tgtAddrReg*/, int j3/*scratchReg*/) { |
| infoArray[j3].regNum = 11; |
| infoArray[j3].physicalType = LowOpndRegType_gp; |
| infoArray[j3].refCount = 3; |
| infoArray[j3].is8Bit = true; |
| infoArray[j2].refCount += 2; |
| infoArray[j3+1].regNum = 2; |
| infoArray[j3+1].refCount = 2; //DU |
| infoArray[j3+1].physicalType = LowOpndRegType_scratch; |
| return j3+2; |
| } |
| |
| int iget_obj_inst = -1; |
| //! This function updates infoArray with temporaries accessed when lowering the bytecode |
| |
| //! returns the number of temporaries |
| int getTempRegInfo(TempRegInfo* infoArray) { //returns an array of TempRegInfo |
| int k; |
| int numTmps; |
| for(k = 0; k < MAX_TEMP_REG_PER_BYTECODE; k++) { |
| infoArray[k].linkageToVR = -1; |
| infoArray[k].versionNum = 0; |
| infoArray[k].shareWithVR = true; |
| infoArray[k].is8Bit = false; |
| } |
| u2 vA, v1, length, num, tmp; |
| u2 inst_op = INST_INST(inst); |
| s2 tmp_s2; |
| s4 tmp_s4; |
| switch(inst_op) { |
| case OP_APUT_BYTE: |
| for(k = 0; k < MAX_TEMP_REG_PER_BYTECODE; k++) |
| infoArray[k].shareWithVR = true; //false; |
| break; |
| } |
| switch (INST_INST(inst)) { |
| case OP_NOP: |
| return 0; |
| case OP_MOVE: |
| case OP_MOVE_OBJECT: |
| case OP_MOVE_FROM16: |
| case OP_MOVE_OBJECT_FROM16: |
| case OP_MOVE_16: |
| case OP_MOVE_OBJECT_16: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| return 1; |
| case OP_MOVE_WIDE: |
| case OP_MOVE_WIDE_FROM16: |
| case OP_MOVE_WIDE_16: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| return 1; |
| case OP_MOVE_RESULT: |
| case OP_MOVE_RESULT_OBJECT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| return 2; |
| case OP_MOVE_RESULT_WIDE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| return 2; |
| case OP_MOVE_EXCEPTION: |
| infoArray[0].regNum = 2; |
| infoArray[0].refCount = 3; //DUU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 3; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 1; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| return 3; |
| |
| case OP_CONST_4: |
| case OP_CONST_16: |
| case OP_CONST: |
| case OP_CONST_HIGH16: |
| case OP_CONST_WIDE_16: |
| case OP_CONST_WIDE_32: |
| case OP_CONST_WIDE: |
| case OP_CONST_WIDE_HIGH16: |
| return 0; |
| case OP_CONST_STRING: //hardcode %eax |
| case OP_CONST_STRING_JUMBO: |
| infoArray[0].regNum = 3; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| infoArray[2].regNum = 2; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| infoArray[3].regNum = PhysicalReg_EAX; |
| infoArray[3].refCount = 4; |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 4; |
| case OP_CONST_CLASS: |
| infoArray[0].regNum = 3; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| infoArray[2].regNum = 2; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| infoArray[3].regNum = PhysicalReg_EAX; |
| infoArray[3].refCount = 4; |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 4; |
| |
| case OP_MONITOR_ENTER: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 3; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 1; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| infoArray[3].regNum = 2; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_scratch; |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 5; |
| case OP_MONITOR_EXIT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = PhysicalReg_EAX; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[2].regNum = 1; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| infoArray[3].regNum = PhysicalReg_EDX; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[4].regNum = 2; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_scratch; |
| infoArray[5].regNum = 3; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| return 6; |
| case OP_CHECK_CAST: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 4; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 6; |
| infoArray[2].refCount = 3; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| |
| infoArray[3].regNum = 1; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_scratch; |
| infoArray[4].regNum = 2; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[5].regNum = PhysicalReg_EAX; |
| /* %eax has 3 live ranges |
| 1> 5 accesses: to resolve the class object |
| 2> call dvmInstanceofNonTrivial to define %eax, then use it once |
| 3> move exception object to %eax, then jump to throw_exception |
| if WITH_JIT is true, the first live range has 6 accesses |
| */ |
| infoArray[5].refCount = 6; |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[6].regNum = PhysicalReg_EDX; |
| infoArray[6].refCount = 2; //export_pc |
| infoArray[6].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[7].regNum = PhysicalReg_ECX; |
| infoArray[7].refCount = 1; |
| infoArray[7].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[8].regNum = 3; |
| infoArray[8].refCount = 2; //DU |
| infoArray[8].physicalType = LowOpndRegType_scratch; |
| return 9; |
| case OP_INSTANCE_OF: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 3; |
| infoArray[1].refCount = 4; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 4; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 6; |
| infoArray[3].refCount = 3; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| |
| infoArray[4].regNum = 1; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_scratch; |
| infoArray[5].regNum = 2; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[6].regNum = PhysicalReg_EAX; |
| infoArray[6].refCount = 6; |
| infoArray[6].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[7].regNum = 3; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_scratch; |
| infoArray[8].regNum = PhysicalReg_EDX; |
| infoArray[8].refCount = 2; //export_pc for class_resolve |
| infoArray[8].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 9; |
| |
| case OP_ARRAY_LENGTH: |
| vA = INST_A(inst); |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[1].linkageToVR = vA; |
| infoArray[2].regNum = PhysicalReg_EDX; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 3; |
| case OP_NEW_INSTANCE: |
| infoArray[0].regNum = PhysicalReg_EAX; |
| //6: class object |
| //3: defined by C function, used twice |
| infoArray[0].refCount = 6; //next version has 3 references |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[1].regNum = PhysicalReg_ECX; //before common_throw_message |
| infoArray[1].refCount = 1; |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 5; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[3].is8Bit = true; |
| infoArray[4].regNum = 6; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| |
| infoArray[5].regNum = 1; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| infoArray[6].regNum = 2; |
| infoArray[6].refCount = 2; //DU |
| infoArray[6].physicalType = LowOpndRegType_scratch; |
| infoArray[7].regNum = 3; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[8].regNum = PhysicalReg_EDX; //before common_throw_message |
| infoArray[8].refCount = 2; |
| infoArray[8].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[9].regNum = 4; |
| infoArray[9].refCount = 2; //DU |
| infoArray[9].physicalType = LowOpndRegType_scratch; |
| return 10; |
| |
| case OP_NEW_ARRAY: |
| infoArray[0].regNum = PhysicalReg_EAX; |
| //4: class object |
| //3: defined by C function, used twice |
| infoArray[0].refCount = 4; //next version has 3 references |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[1].regNum = PhysicalReg_EDX; //before common_throw_message |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 5; |
| infoArray[3].refCount = 3; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| |
| infoArray[4].regNum = 1; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_scratch; |
| infoArray[5].regNum = 2; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| infoArray[6].regNum = 3; |
| infoArray[6].refCount = 2; //DU |
| infoArray[6].physicalType = LowOpndRegType_scratch; |
| infoArray[7].regNum = 4; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_scratch; |
| return 8; |
| |
| case OP_FILLED_NEW_ARRAY: |
| length = INST_B(inst); |
| infoArray[0].regNum = PhysicalReg_EAX; |
| //4: class object |
| //3: defined by C function, used twice (array object) |
| //length: access array object to update the content |
| infoArray[0].refCount = 4; //next version has 5+length references |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[1].regNum = PhysicalReg_EDX; //before common_throw_message |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 5; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 6; |
| infoArray[4].refCount = 8; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[4].is8Bit = true; |
| |
| if(length >= 1) { |
| infoArray[5].regNum = 7; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| } |
| if(length >= 2) { |
| infoArray[6].regNum = 8; |
| infoArray[6].refCount = 2; //DU |
| infoArray[6].physicalType = LowOpndRegType_gp; |
| } |
| if(length >= 3) { |
| infoArray[7].regNum = 9; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_gp; |
| } |
| if(length >= 4) { |
| infoArray[8].regNum = 10; |
| infoArray[8].refCount = 2; //DU |
| infoArray[8].physicalType = LowOpndRegType_gp; |
| } |
| if(length >= 5) { |
| infoArray[9].regNum = 11; |
| infoArray[9].refCount = 2; //DU |
| infoArray[9].physicalType = LowOpndRegType_gp; |
| } |
| infoArray[5+length].regNum = 1; |
| infoArray[5+length].refCount = 2; //DU |
| infoArray[5+length].physicalType = LowOpndRegType_scratch; |
| infoArray[6+length].regNum = 2; |
| infoArray[6+length].refCount = 4; //DU |
| infoArray[6+length].physicalType = LowOpndRegType_scratch; |
| infoArray[7+length].regNum = 3; |
| infoArray[7+length].refCount = 2; //DU |
| infoArray[7+length].physicalType = LowOpndRegType_scratch; |
| infoArray[8+length].regNum = 4; |
| infoArray[8+length].refCount = 5; //DU |
| infoArray[8+length].physicalType = LowOpndRegType_scratch; |
| return 9+length; |
| |
| case OP_FILLED_NEW_ARRAY_RANGE: |
| length = INST_AA(inst); |
| infoArray[0].regNum = PhysicalReg_EAX; |
| //4: class object |
| //3: defined by C function, used twice (array object) |
| //if length is 0, no access to array object |
| //else, used inside a loop |
| infoArray[0].refCount = 4; //next version: 5+(length >= 1 ? LOOP_COUNT : 0) |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[1].regNum = PhysicalReg_EDX; //before common_throw_message |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 5; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 6; |
| infoArray[4].refCount = 8; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[4].is8Bit = true; |
| |
| infoArray[5].regNum = 1; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| infoArray[6].regNum = 2; |
| infoArray[6].refCount = 4; //DU |
| infoArray[6].physicalType = LowOpndRegType_scratch; |
| infoArray[7].regNum = 3; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[8].regNum = 7; |
| infoArray[8].refCount = 3*(length >= 1 ? LOOP_COUNT : 0); |
| infoArray[8].physicalType = LowOpndRegType_gp; |
| infoArray[9].regNum = 8; |
| infoArray[9].refCount = 3*(length >= 1 ? LOOP_COUNT : 0); |
| infoArray[9].physicalType = LowOpndRegType_gp; |
| infoArray[10].regNum = 9; |
| infoArray[10].refCount = 2*(length >= 1 ? LOOP_COUNT : 0); |
| infoArray[10].physicalType = LowOpndRegType_gp; |
| infoArray[11].regNum = 10; |
| infoArray[11].refCount = 2*(length >= 1 ? LOOP_COUNT : 0); |
| infoArray[11].physicalType = LowOpndRegType_gp; |
| infoArray[12].regNum = 4; |
| infoArray[12].refCount = 5; //DU |
| infoArray[12].physicalType = LowOpndRegType_scratch; |
| return 13; |
| |
| case OP_FILL_ARRAY_DATA: |
| infoArray[0].regNum = PhysicalReg_EAX; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[1].regNum = PhysicalReg_EDX; //before common_throw_message |
| #if 0//def HARDREG_OPT |
| infoArray[1].refCount = 3; //next version has refCount of 2 |
| #else |
| infoArray[1].refCount = 5; |
| #endif |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[2].regNum =1; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| |
| infoArray[3].regNum = 1; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_scratch; |
| infoArray[4].regNum = 2; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_scratch; |
| return 5; |
| |
| case OP_THROW: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = PhysicalReg_EDX; //before common_throw_message |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[2].regNum = 1; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| infoArray[3].regNum = 2; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_scratch; |
| return 4; |
| case OP_THROW_VERIFICATION_ERROR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = PhysicalReg_EDX; //export_pc |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[2].regNum = 1; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| infoArray[3].regNum = 2; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_scratch; |
| return 4; |
| |
| case OP_GOTO: //called function common_periodicChecks4 |
| #if defined(ENABLE_TRACING) |
| tt = INST_AA(inst); |
| tmp_s2 = (s2)((s2)tt << 8) >> 8; |
| if(tmp_s2 < 0) { |
| infoArray[0].regNum = PhysicalReg_EDX; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 1; |
| } |
| #endif |
| return 0; |
| case OP_GOTO_16: |
| #if defined(ENABLE_TRACING) |
| tmp_s2 = (s2)FETCH(1); |
| if(tmp_s2 < 0) { |
| infoArray[0].regNum = PhysicalReg_EDX; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 1; |
| } |
| #endif |
| return 0; |
| case OP_GOTO_32: |
| #if defined(ENABLE_TRACING) |
| tmp_u4 = (u4)FETCH(1); |
| tmp_u4 |= (u4)FETCH(2) << 16; |
| if(((s4)tmp_u4) < 0) { |
| infoArray[0].regNum = PhysicalReg_EDX; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 1; |
| } |
| #endif |
| return 0; |
| case OP_IF_EQ: |
| case OP_IF_NE: |
| case OP_IF_LT: |
| case OP_IF_GE: |
| case OP_IF_GT: |
| case OP_IF_LE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| #if defined(ENABLE_TRACING) |
| tmp_s2 = (s2)FETCH(1); |
| if(tmp_s2 < 0) { |
| infoArray[1].regNum = PhysicalReg_EDX; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 2; |
| } |
| #endif |
| return 1; |
| case OP_IF_EQZ: //called function common_periodicChecks4 |
| case OP_IF_NEZ: |
| case OP_IF_LTZ: |
| case OP_IF_GEZ: |
| case OP_IF_GTZ: |
| case OP_IF_LEZ: |
| #if defined(ENABLE_TRACING) |
| tmp_s2 = (s2)FETCH(1); |
| if(tmp_s2 < 0) { |
| infoArray[0].regNum = PhysicalReg_EDX; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 1; |
| } |
| #endif |
| return 0; |
| case OP_PACKED_SWITCH: //jump common_backwardBranch, which calls common_periodicChecks_entry, then jump_reg %eax |
| case OP_SPARSE_SWITCH: //%edx, %eax |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = PhysicalReg_EDX; |
| infoArray[1].refCount = 6; |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[2].regNum = PhysicalReg_EAX; //return by dvm helper |
| infoArray[2].refCount = 2+1; //2 uses |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = 1; |
| infoArray[3].refCount = 2; |
| infoArray[3].physicalType = LowOpndRegType_scratch; |
| infoArray[4].regNum = 2; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_scratch; |
| return 5; |
| |
| case OP_AGET: |
| case OP_AGET_OBJECT: |
| case OP_AGET_BOOLEAN: |
| case OP_AGET_BYTE: |
| case OP_AGET_CHAR: |
| case OP_AGET_SHORT: |
| vA = INST_AA(inst); |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[3].linkageToVR = vA; |
| if(inst_op == OP_AGET_BYTE || inst_op == OP_AGET_BOOLEAN) |
| infoArray[3].is8Bit = true; |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 5; |
| case OP_AGET_WIDE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 1; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_xmm; |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 5; |
| |
| case OP_APUT: |
| case OP_APUT_BOOLEAN: |
| case OP_APUT_BYTE: |
| case OP_APUT_CHAR: |
| case OP_APUT_SHORT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| if(inst_op == OP_APUT_BYTE || inst_op == OP_APUT_BOOLEAN) |
| infoArray[3].is8Bit = true; |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 5; |
| case OP_APUT_WIDE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 1; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_xmm; |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 5; |
| case OP_APUT_OBJECT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 5+1; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; //live through function call dvmCanPut |
| infoArray[1].refCount = 3+1; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 4+1; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 5; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = 6; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| |
| infoArray[6].regNum = PhysicalReg_EDX; |
| infoArray[6].refCount = 2; //DU |
| infoArray[6].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[7].regNum = PhysicalReg_EAX; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[8].regNum = 1; |
| infoArray[8].refCount = 2; //DU |
| infoArray[8].physicalType = LowOpndRegType_scratch; |
| infoArray[0].shareWithVR = false; |
| return updateMarkCard_notNull(infoArray, |
| 0/*index for tgtAddrReg*/, 9); |
| |
| case OP_IGET: |
| case OP_IGET_OBJECT: |
| case OP_IGET_VOLATILE: |
| case OP_IGET_OBJECT_VOLATILE: |
| case OP_IGET_BOOLEAN: |
| case OP_IGET_BYTE: |
| case OP_IGET_CHAR: |
| case OP_IGET_SHORT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_scratch; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[2].regNum = PhysicalReg_EDX; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = PhysicalReg_EAX; |
| infoArray[3].refCount = 3; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[4].regNum = 3; |
| infoArray[4].refCount = 3; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = 7; |
| #ifdef DEBUG_IGET_OBJ |
| //add hack for a specific instance (iget_obj_inst) of IGET_OBJECT within a method |
| if(inst_op == OP_IGET_OBJECT && !strncmp(currentMethod->clazz->descriptor, "Lspec/benchmarks/_228_jack/Parse", 32) && |
| !strncmp(currentMethod->name, "buildPhase3", 11)) |
| { |
| #if 0 |
| if(iget_obj_inst == 12) { |
| LOGD("increase count for instance %d of %s %s", iget_obj_inst, currentMethod->clazz->descriptor, currentMethod->name); |
| infoArray[5].refCount = 4; //DU |
| } |
| else |
| #endif |
| infoArray[5].refCount = 3; |
| iget_obj_inst++; |
| } |
| else |
| infoArray[5].refCount = 3; |
| #else |
| infoArray[5].refCount = 3; //DU |
| #endif |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| infoArray[6].regNum = 8; |
| infoArray[6].refCount = 2; //DU |
| infoArray[6].physicalType = LowOpndRegType_gp; |
| infoArray[7].regNum = 9; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_gp; |
| return 8; |
| case OP_IPUT: |
| case OP_IPUT_OBJECT: |
| case OP_IPUT_VOLATILE: |
| case OP_IPUT_OBJECT_VOLATILE: |
| case OP_IPUT_BOOLEAN: |
| case OP_IPUT_BYTE: |
| case OP_IPUT_CHAR: |
| case OP_IPUT_SHORT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_scratch; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[2].regNum = PhysicalReg_EDX; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = PhysicalReg_EAX; |
| infoArray[3].refCount = 3; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[4].regNum = 3; |
| infoArray[4].refCount = 3; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = 7; |
| infoArray[5].refCount = 3; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| infoArray[6].regNum = 8; |
| infoArray[6].refCount = 2; //DU |
| infoArray[6].physicalType = LowOpndRegType_gp; |
| infoArray[7].regNum = 9; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_gp; |
| if(inst_op == OP_IPUT_OBJECT || inst_op == OP_IPUT_OBJECT_VOLATILE) { |
| infoArray[5].shareWithVR = false; |
| return updateMarkCard(infoArray, 7/*index for valReg*/, |
| 5/*index for tgtAddrReg*/, 8); |
| } |
| return 8; |
| case OP_IGET_WIDE: |
| case OP_IGET_WIDE_VOLATILE: |
| case OP_IPUT_WIDE: |
| case OP_IPUT_WIDE_VOLATILE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_scratch; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[2].regNum = PhysicalReg_EDX; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = PhysicalReg_EAX; |
| infoArray[3].refCount = 3; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[4].regNum = 3; |
| infoArray[4].refCount = 3; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = 7; |
| infoArray[5].refCount = 3; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| infoArray[6].regNum = 8; |
| infoArray[6].refCount = 2; //DU |
| infoArray[6].physicalType = LowOpndRegType_gp; |
| infoArray[7].regNum = 1; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_xmm; |
| |
| if(inst_op == OP_IPUT_WIDE_VOLATILE || inst_op == OP_IGET_WIDE_VOLATILE) { |
| infoArray[8].regNum = 3; |
| infoArray[8].refCount = 2; //DU |
| infoArray[8].physicalType = LowOpndRegType_scratch; |
| infoArray[9].regNum = 9; |
| infoArray[9].refCount = 2; //DU |
| infoArray[9].physicalType = LowOpndRegType_gp; |
| return 10; |
| } |
| return 8; |
| |
| case OP_SGET: |
| case OP_SGET_OBJECT: |
| case OP_SGET_VOLATILE: |
| case OP_SGET_OBJECT_VOLATILE: |
| case OP_SGET_BOOLEAN: |
| case OP_SGET_BYTE: |
| case OP_SGET_CHAR: |
| case OP_SGET_SHORT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_scratch; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[2].regNum = PhysicalReg_EAX; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = 3; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 7; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = PhysicalReg_EDX; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 6; |
| case OP_SPUT: |
| case OP_SPUT_OBJECT: |
| case OP_SPUT_VOLATILE: |
| case OP_SPUT_OBJECT_VOLATILE: |
| case OP_SPUT_BOOLEAN: |
| case OP_SPUT_BYTE: |
| case OP_SPUT_CHAR: |
| case OP_SPUT_SHORT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_scratch; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[2].regNum = PhysicalReg_EAX; |
| infoArray[2].refCount = 2+1; //access clazz of the field |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = 3; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 7; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = PhysicalReg_EDX; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| if(inst_op == OP_SPUT_OBJECT || inst_op == OP_SPUT_OBJECT_VOLATILE) { |
| infoArray[2].shareWithVR = false; |
| infoArray[6].regNum = 12; |
| infoArray[6].refCount = 1; //1 def, 2 uses in updateMarkCard |
| infoArray[6].physicalType = LowOpndRegType_gp; |
| return updateMarkCard(infoArray, 4/*index for valReg*/, |
| 6/*index for tgtAddrReg */, 7); |
| } |
| return 6; |
| case OP_SGET_WIDE: |
| case OP_SGET_WIDE_VOLATILE: |
| case OP_SPUT_WIDE: |
| case OP_SPUT_WIDE_VOLATILE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_scratch; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_scratch; |
| |
| infoArray[2].regNum = PhysicalReg_EAX; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = 3; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 1; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_xmm; |
| infoArray[5].regNum = PhysicalReg_EDX; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| if(inst_op == OP_SPUT_WIDE_VOLATILE || inst_op == OP_SGET_WIDE_VOLATILE) { |
| infoArray[6].regNum = 3; |
| infoArray[6].refCount = 2; //DU |
| infoArray[6].physicalType = LowOpndRegType_scratch; |
| infoArray[7].regNum = 9; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_gp; |
| return 8; |
| } |
| return 6; |
| |
| case OP_IGET_QUICK: |
| case OP_IGET_OBJECT_QUICK: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = PhysicalReg_EDX; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 3; |
| case OP_IPUT_QUICK: |
| case OP_IPUT_OBJECT_QUICK: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = PhysicalReg_EDX; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| if(inst_op == OP_IPUT_OBJECT_QUICK) { |
| infoArray[0].shareWithVR = false; |
| return updateMarkCard(infoArray, 1/*index for valReg*/, |
| 0/*index for tgtAddrReg*/, 3); |
| } |
| return 3; |
| case OP_IGET_WIDE_QUICK: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[2].regNum = PhysicalReg_EDX; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 3; |
| case OP_IPUT_WIDE_QUICK: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[2].regNum = PhysicalReg_EDX; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 3; |
| |
| case OP_RETURN_VOID: |
| case OP_RETURN_VOID_BARRIER: |
| return updateReturnCommon(infoArray); |
| case OP_RETURN: |
| case OP_RETURN_OBJECT: |
| numTmps = updateReturnCommon(infoArray); |
| |
| infoArray[numTmps].regNum = 21; |
| infoArray[numTmps].refCount = 2; //DU |
| infoArray[numTmps].physicalType = LowOpndRegType_gp; |
| numTmps++; |
| infoArray[numTmps].regNum = 22; |
| infoArray[numTmps].refCount = 2; //DU |
| infoArray[numTmps].physicalType = LowOpndRegType_gp; |
| numTmps++; |
| return numTmps; |
| case OP_RETURN_WIDE: |
| numTmps = updateReturnCommon(infoArray); |
| |
| infoArray[numTmps].regNum = 10; |
| infoArray[numTmps].refCount = 2; //DU |
| infoArray[numTmps].physicalType = LowOpndRegType_scratch; |
| numTmps++; |
| infoArray[numTmps].regNum = 1; |
| infoArray[numTmps].refCount = 2; //DU |
| infoArray[numTmps].physicalType = LowOpndRegType_xmm; |
| numTmps++; |
| return numTmps; |
| |
| case OP_INVOKE_VIRTUAL: |
| case OP_INVOKE_VIRTUAL_RANGE: |
| #ifdef PREDICTED_CHAINING |
| numTmps = updateGenPrediction(infoArray, false /*not interface*/); |
| infoArray[numTmps].regNum = 5; |
| infoArray[numTmps].refCount = 3; //DU |
| infoArray[numTmps].physicalType = LowOpndRegType_gp; |
| numTmps++; |
| if(inst_op == OP_INVOKE_VIRTUAL) |
| k = updateInvokeNoRange(infoArray, numTmps); |
| else |
| k = updateInvokeRange(infoArray, numTmps); |
| return k; |
| #else |
| infoArray[0].regNum = 3; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 7; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 8; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 6; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 5; |
| infoArray[4].refCount = 3; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = PhysicalReg_EDX; |
| infoArray[5].refCount = 2; //2 versions, first version DU is for exception, 2nd version: eip right before jumping to invokeArgsDone |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[6].regNum = PhysicalReg_ECX; //ecx is ued in invokeArgsDone |
| infoArray[6].refCount = 1+1; //used in .invokeArgsDone |
| infoArray[6].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| //when WITH_JIT is true and PREDICTED_CHAINING is false |
| // temp 8 and EAX are not used; but it is okay to keep it here |
| infoArray[7].regNum = PhysicalReg_EAX; |
| infoArray[7].refCount = 4; //DU |
| infoArray[7].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[8].regNum = 1; |
| infoArray[8].refCount = 2; //DU |
| infoArray[8].physicalType = LowOpndRegType_scratch; |
| infoArray[9].regNum = 2; |
| infoArray[9].refCount = 2; //DU |
| infoArray[9].physicalType = LowOpndRegType_scratch; |
| if(inst_op == OP_INVOKE_VIRTUAL) |
| k = updateInvokeNoRange(infoArray, 10); |
| else |
| k = updateInvokeRange(infoArray, 10); |
| return k; |
| #endif |
| case OP_INVOKE_SUPER: |
| case OP_INVOKE_SUPER_RANGE: |
| infoArray[0].regNum = 3; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 7; |
| infoArray[1].refCount = 3; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 8; |
| infoArray[2].refCount = 3; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 6; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 9; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| |
| infoArray[5].regNum = PhysicalReg_EDX; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[6].regNum = PhysicalReg_ECX; |
| infoArray[6].refCount = 1+1; //DU |
| infoArray[6].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[7].regNum = PhysicalReg_EAX; |
| infoArray[7].refCount = 4; //DU |
| infoArray[7].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[8].regNum = 1; |
| infoArray[8].refCount = 2; //DU |
| infoArray[8].physicalType = LowOpndRegType_scratch; |
| infoArray[9].regNum = 2; |
| infoArray[9].refCount = 2; //DU |
| infoArray[9].physicalType = LowOpndRegType_scratch; |
| infoArray[10].regNum = 3; |
| infoArray[10].refCount = 2; //DU |
| infoArray[10].physicalType = LowOpndRegType_scratch; |
| infoArray[11].regNum = 4; |
| infoArray[11].refCount = 2; //DU |
| infoArray[11].physicalType = LowOpndRegType_scratch; |
| if(inst_op == OP_INVOKE_SUPER) |
| k = updateInvokeNoRange(infoArray, 12); |
| else |
| k = updateInvokeRange(infoArray, 12); |
| return k; |
| case OP_INVOKE_DIRECT: |
| case OP_INVOKE_DIRECT_RANGE: |
| infoArray[0].regNum = 3; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 5; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| |
| infoArray[2].regNum = PhysicalReg_EDX; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = PhysicalReg_ECX; |
| infoArray[3].refCount = 2; |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[4].regNum = PhysicalReg_EAX; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[5].regNum = 1; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| infoArray[6].regNum = 2; |
| infoArray[6].refCount = 2; //DU |
| infoArray[6].physicalType = LowOpndRegType_scratch; |
| if(inst_op == OP_INVOKE_DIRECT) |
| k = updateInvokeNoRange(infoArray, 7); |
| else |
| k = updateInvokeRange(infoArray, 7); |
| return k; |
| case OP_INVOKE_STATIC: |
| case OP_INVOKE_STATIC_RANGE: |
| infoArray[0].regNum = 3; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| |
| infoArray[1].regNum = PhysicalReg_EDX; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[2].regNum = PhysicalReg_ECX; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = PhysicalReg_EAX; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[4].regNum = 1; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_scratch; |
| infoArray[5].regNum = 2; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| if(inst_op == OP_INVOKE_STATIC) |
| k = updateInvokeNoRange(infoArray, 6); |
| else |
| k = updateInvokeRange(infoArray, 6); |
| return k; |
| case OP_INVOKE_INTERFACE: |
| case OP_INVOKE_INTERFACE_RANGE: |
| #ifdef PREDICTED_CHAINING |
| numTmps = updateGenPrediction(infoArray, true /*interface*/); |
| infoArray[numTmps].regNum = 1; |
| infoArray[numTmps].refCount = 3; //DU |
| infoArray[numTmps].physicalType = LowOpndRegType_gp; |
| numTmps++; |
| if(inst_op == OP_INVOKE_INTERFACE) |
| k = updateInvokeNoRange(infoArray, numTmps); |
| else |
| k = updateInvokeRange(infoArray, numTmps); |
| return k; |
| #else |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 3; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 4; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 5; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[5].regNum = PhysicalReg_ECX; |
| infoArray[5].refCount = 1+1; //DU |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[6].regNum = PhysicalReg_EAX; |
| infoArray[6].refCount = 2+1; //2 uses |
| infoArray[6].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[7].regNum = 1; |
| infoArray[7].refCount = 2; //DU |
| infoArray[7].physicalType = LowOpndRegType_scratch; |
| infoArray[8].regNum = 2; |
| infoArray[8].refCount = 2; //DU |
| infoArray[8].physicalType = LowOpndRegType_scratch; |
| infoArray[9].regNum = 3; |
| infoArray[9].refCount = 2; //DU |
| infoArray[9].physicalType = LowOpndRegType_scratch; |
| if(inst_op == OP_INVOKE_INTERFACE) |
| k = updateInvokeNoRange(infoArray, 10); |
| else |
| k = updateInvokeRange(infoArray, 10); |
| return k; |
| #endif |
| ////////////////////////////////////////////// ALU |
| case OP_NEG_INT: |
| case OP_NOT_INT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[0].shareWithVR = false; |
| return 1; |
| case OP_NEG_LONG: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //define, use |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 4; //define, update, use |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| return 2; |
| case OP_NOT_LONG: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| return 2; |
| case OP_NEG_FLOAT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[0].shareWithVR = false; |
| return 1; |
| case OP_NEG_DOUBLE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //define, use |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; //define, update, use |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| return 2; |
| case OP_INT_TO_LONG: //hard-code eax & edx |
| infoArray[0].regNum = PhysicalReg_EAX; |
| infoArray[0].refCount = 2+1; |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = PhysicalReg_EDX; |
| infoArray[1].refCount = 1+1; //cdq accesses edx & eax |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 2; |
| case OP_INT_TO_FLOAT: |
| case OP_INT_TO_DOUBLE: |
| case OP_LONG_TO_FLOAT: |
| case OP_LONG_TO_DOUBLE: |
| case OP_FLOAT_TO_DOUBLE: |
| case OP_DOUBLE_TO_FLOAT: |
| return 0; //fp stack |
| case OP_LONG_TO_INT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| return 1; |
| case OP_FLOAT_TO_INT: |
| case OP_DOUBLE_TO_INT: //fp stack |
| return 0; |
| case OP_FLOAT_TO_LONG: |
| case OP_DOUBLE_TO_LONG: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //define, use |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //define, use |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //define, use |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| return 3; |
| case OP_INT_TO_BYTE: |
| case OP_INT_TO_CHAR: |
| case OP_INT_TO_SHORT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; //define, update, update, use |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[0].shareWithVR = false; |
| return 1; |
| |
| case OP_ADD_INT: |
| case OP_SUB_INT: |
| case OP_MUL_INT: |
| case OP_AND_INT: |
| case OP_OR_INT: |
| case OP_XOR_INT: |
| case OP_ADD_INT_2ADDR: |
| case OP_SUB_INT_2ADDR: |
| case OP_MUL_INT_2ADDR: |
| case OP_AND_INT_2ADDR: |
| case OP_OR_INT_2ADDR: |
| case OP_XOR_INT_2ADDR: |
| if(inst_op == OP_ADD_INT || inst_op == OP_SUB_INT || inst_op == OP_MUL_INT || |
| inst_op == OP_AND_INT || inst_op == OP_OR_INT || inst_op == OP_XOR_INT) { |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| } else { |
| vA = INST_A(inst); |
| v1 = vA; |
| } |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| if(vA != v1) |
| infoArray[0].shareWithVR = false; |
| return 1; //common_alu_int |
| |
| case OP_SHL_INT: |
| case OP_SHR_INT: |
| case OP_USHR_INT: |
| case OP_SHL_INT_2ADDR: |
| case OP_SHR_INT_2ADDR: |
| case OP_USHR_INT_2ADDR: //use %cl or %ecx? |
| if(inst_op == OP_SHL_INT || inst_op == OP_SHR_INT || inst_op == OP_USHR_INT) { |
| vA = INST_AA(inst); |
| v1 = *((u1*)rPC + 2); |
| } else { |
| vA = INST_A(inst); |
| v1 = vA; |
| } |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| if(vA != v1) |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = PhysicalReg_ECX; |
| infoArray[1].refCount = 2; //define, use |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 2;//common_shift_int |
| |
| case OP_DIV_INT: |
| case OP_REM_INT: |
| case OP_DIV_INT_2ADDR: |
| case OP_REM_INT_2ADDR: //hard-code %eax, %edx (dividend in edx:eax; quotient in eax; remainder in edx) |
| infoArray[0].regNum = 2; |
| infoArray[0].refCount = 4; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = PhysicalReg_EAX; //dividend, quotient |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[1].shareWithVR = false; |
| infoArray[2].regNum = PhysicalReg_EDX; //export_pc, output for REM |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[3].regNum = 1; |
| infoArray[3].refCount = 2; //define, use |
| infoArray[3].physicalType = LowOpndRegType_scratch; |
| if(inst_op == OP_DIV_INT || inst_op == OP_DIV_INT_2ADDR) { |
| infoArray[1].refCount = 5; |
| infoArray[2].refCount = 4; |
| } else { |
| infoArray[1].refCount = 4; |
| infoArray[2].refCount = 5; |
| } |
| return 4; |
| |
| case OP_ADD_INT_LIT16: |
| case OP_MUL_INT_LIT16: |
| case OP_AND_INT_LIT16: |
| case OP_OR_INT_LIT16: |
| case OP_XOR_INT_LIT16: |
| case OP_ADD_INT_LIT8: |
| case OP_MUL_INT_LIT8: |
| case OP_AND_INT_LIT8: |
| case OP_OR_INT_LIT8: |
| case OP_XOR_INT_LIT8: |
| case OP_SHL_INT_LIT8: |
| case OP_SHR_INT_LIT8: |
| case OP_USHR_INT_LIT8: |
| if(inst_op == OP_ADD_INT_LIT16 || inst_op == OP_MUL_INT_LIT16 || |
| inst_op == OP_AND_INT_LIT16 || inst_op == OP_OR_INT_LIT16 || inst_op == OP_XOR_INT_LIT16) { |
| vA = INST_A(inst); |
| v1 = INST_B(inst); |
| } else { |
| vA = INST_AA(inst); |
| v1 = (u2)FETCH(1) & 0xff; |
| } |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| if(vA != v1) |
| infoArray[0].shareWithVR = false; |
| return 1; |
| |
| case OP_RSUB_INT_LIT8: |
| case OP_RSUB_INT: |
| vA = INST_AA(inst); |
| v1 = (inst_op == OP_RSUB_INT) ? INST_B(inst) : ((u2)FETCH(1) & 0xff); |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| if(vA != v1) |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| if(vA != v1) |
| infoArray[1].shareWithVR = false; |
| return 2; |
| |
| case OP_DIV_INT_LIT16: |
| case OP_REM_INT_LIT16: |
| case OP_DIV_INT_LIT8: |
| case OP_REM_INT_LIT8: |
| if(inst_op == OP_DIV_INT_LIT8 || inst_op == OP_REM_INT_LIT8) { |
| tmp_s2 = (s2)FETCH(1) >> 8; |
| } |
| else { |
| tmp_s4 = (s2)FETCH(1); |
| tmp_s2 = tmp_s4; |
| } |
| if((inst_op == OP_DIV_INT_LIT8 || inst_op == OP_DIV_INT_LIT16)) { |
| int power = isPowerOfTwo(tmp_s2); |
| if(power >= 1) { /* divide by a power of 2 constant */ |
| infoArray[0].regNum = 2; |
| infoArray[0].refCount = 3; //define, use, use |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 1; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| if(power == 1) infoArray[1].refCount = 5; |
| else infoArray[1].refCount = 6; |
| return 2; |
| } |
| } |
| if(tmp_s2 == 0) { |
| //export_pc |
| infoArray[0].regNum = PhysicalReg_EDX; //export_pc, output for REM |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 1; |
| } |
| if(inst_op == OP_DIV_INT_LIT16 || inst_op == OP_DIV_INT_LIT8) { |
| if(tmp_s2 == -1) |
| infoArray[1].refCount = 4+1; |
| else |
| infoArray[1].refCount = 4; |
| infoArray[2].refCount = 2; //edx |
| } else { |
| if(tmp_s2 == -1) |
| infoArray[1].refCount = 3+1; |
| else |
| infoArray[1].refCount = 3; |
| infoArray[2].refCount = 3; //edx |
| } |
| infoArray[0].regNum = 2; |
| infoArray[0].refCount = 2; //define, use |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = PhysicalReg_EAX; //dividend, quotient |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[1].shareWithVR = false; |
| infoArray[2].regNum = PhysicalReg_EDX; //export_pc, output for REM |
| infoArray[2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 3; |
| |
| case OP_ADD_LONG: |
| case OP_SUB_LONG: |
| case OP_AND_LONG: |
| case OP_OR_LONG: |
| case OP_XOR_LONG: |
| case OP_ADD_LONG_2ADDR: |
| case OP_SUB_LONG_2ADDR: |
| case OP_AND_LONG_2ADDR: |
| case OP_OR_LONG_2ADDR: |
| case OP_XOR_LONG_2ADDR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //define, use |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| return 2; |
| |
| case OP_SHL_LONG: |
| case OP_SHL_LONG_2ADDR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; //define, update, use |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[1].shareWithVR = false; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //define, use |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| return 3; |
| |
| case OP_SHR_LONG: |
| case OP_SHR_LONG_2ADDR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 4; //define, update, use |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[1].shareWithVR = false; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //define, use |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 3; |
| infoArray[3].physicalType = LowOpndRegType_xmm; |
| infoArray[4].regNum = 5; |
| infoArray[4].refCount = 3; |
| infoArray[4].physicalType = LowOpndRegType_xmm; |
| return 5; |
| |
| case OP_USHR_LONG: |
| case OP_USHR_LONG_2ADDR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //define, update, use |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; //define, update, use |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[1].shareWithVR = false; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //define, use |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| return 3; |
| |
| case OP_MUL_LONG: //general purpose register |
| case OP_MUL_LONG_2ADDR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 6; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 3; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = PhysicalReg_EAX; |
| infoArray[3].refCount = 2+1; //for mul_opc |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; //for mul_opc |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 5; |
| |
| case OP_DIV_LONG: |
| case OP_REM_LONG: |
| case OP_DIV_LONG_2ADDR: |
| case OP_REM_LONG_2ADDR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 1; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_xmm; |
| infoArray[3].regNum = PhysicalReg_EAX; |
| infoArray[3].refCount = 2; //defined by function call |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; //next version has 2 references |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[5].regNum = 1; |
| infoArray[5].refCount = 2; |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| return 6; |
| |
| case OP_ADD_FLOAT: |
| case OP_SUB_FLOAT: |
| case OP_MUL_FLOAT: |
| case OP_ADD_FLOAT_2ADDR: |
| case OP_SUB_FLOAT_2ADDR: |
| case OP_MUL_FLOAT_2ADDR: |
| case OP_ADD_DOUBLE: //PhysicalReg_FP TODO |
| case OP_SUB_DOUBLE: |
| case OP_MUL_DOUBLE: |
| case OP_ADD_DOUBLE_2ADDR: |
| case OP_SUB_DOUBLE_2ADDR: |
| case OP_MUL_DOUBLE_2ADDR: |
| case OP_DIV_FLOAT: |
| case OP_DIV_FLOAT_2ADDR: |
| case OP_DIV_DOUBLE: |
| case OP_DIV_DOUBLE_2ADDR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| //for ALU ops with 2ADDR, the temp variable can share the same physical |
| //reg as the virtual register, since the content of VR is updated by |
| //the content of the temp variable |
| if(inst_op == OP_ADD_FLOAT || inst_op == OP_SUB_FLOAT || |
| inst_op == OP_MUL_FLOAT || inst_op == OP_ADD_DOUBLE || |
| inst_op == OP_SUB_DOUBLE || inst_op == OP_MUL_DOUBLE || |
| inst_op == OP_DIV_FLOAT || inst_op == OP_DIV_DOUBLE) |
| infoArray[0].shareWithVR = false; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| return 2; |
| case OP_REM_FLOAT: |
| case OP_REM_FLOAT_2ADDR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 1; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| return 3; |
| |
| case OP_REM_DOUBLE: |
| case OP_REM_DOUBLE_2ADDR: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| infoArray[2].regNum = 1; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| return 3; |
| |
| case OP_CMPL_FLOAT: |
| case OP_CMPL_DOUBLE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 2; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 3; |
| infoArray[3].refCount = 2; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 4; //return |
| infoArray[4].refCount = 5; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| return 5; |
| |
| case OP_CMPG_FLOAT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 2; |
| infoArray[2].refCount = 3; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 3; |
| infoArray[3].refCount = 5; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| return 4; |
| break; |
| case OP_CMPG_DOUBLE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_xmm; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 2; |
| infoArray[2].refCount = 3; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 3; |
| infoArray[3].refCount = 5; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| return 4; |
| |
| case OP_CMP_LONG: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 3; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 3; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 5; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = 6; |
| infoArray[5].refCount = 7; |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| return 6; |
| |
| case OP_EXECUTE_INLINE: |
| case OP_EXECUTE_INLINE_RANGE: |
| if(inst_op == OP_EXECUTE_INLINE) |
| num = INST_B(inst); |
| else |
| num = INST_AA(inst); |
| tmp = FETCH(1); |
| switch (tmp) { |
| case INLINE_STRING_LENGTH: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 1; |
| infoArray[3].refCount = 2; |
| infoArray[3].physicalType = LowOpndRegType_scratch; |
| return 4; |
| case INLINE_STRING_IS_EMPTY: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 4; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 1; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_scratch; |
| return 3; |
| case INLINE_STRING_FASTINDEXOF_II: |
| #if defined(USE_GLOBAL_STRING_DEFS) |
| break; |
| #else |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 14 * LOOP_COUNT; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3 * LOOP_COUNT; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 11 * LOOP_COUNT; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 3 * LOOP_COUNT; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 5; |
| infoArray[4].refCount = 9 * LOOP_COUNT; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = 6; |
| infoArray[5].refCount = 4 * LOOP_COUNT; |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| infoArray[6].regNum = 7; |
| infoArray[6].refCount = 2; |
| infoArray[6].physicalType = LowOpndRegType_gp; |
| infoArray[7].regNum = 1; |
| infoArray[7].refCount = 2; |
| infoArray[7].physicalType = LowOpndRegType_scratch; |
| return 8; |
| #endif |
| case INLINE_MATH_ABS_LONG: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 7; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 3; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 3; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 5; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = 6; |
| infoArray[5].refCount = 5; |
| infoArray[5].physicalType = LowOpndRegType_gp; |
| return 6; |
| case INLINE_MATH_ABS_INT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 5; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 4; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| return 3; |
| case INLINE_MATH_MAX_INT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| return 3; |
| case INLINE_MATH_ABS_FLOAT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| return 2; |
| case INLINE_MATH_ABS_DOUBLE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 3; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| return 3; |
| case INLINE_FLOAT_TO_RAW_INT_BITS: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| return 2; |
| case INLINE_INT_BITS_TO_FLOAT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| return 2; |
| case INLINE_DOUBLE_TO_RAW_LONG_BITS: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 3; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| return 3; |
| case INLINE_LONG_BITS_TO_DOUBLE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 3; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| return 3; |
| default: |
| break; |
| } |
| |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 4; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| if(num >= 1) { |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| } |
| if(num >= 2) { |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| } |
| if(num >= 3) { |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 2; |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| } |
| if(num >= 4) { |
| infoArray[4].regNum = 5; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| } |
| infoArray[num+1].regNum = 6; |
| infoArray[num+1].refCount = 2; |
| infoArray[num+1].physicalType = LowOpndRegType_gp; |
| infoArray[num+2].regNum = PhysicalReg_EAX; |
| infoArray[num+2].refCount = 2; |
| infoArray[num+2].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[num+3].regNum = PhysicalReg_EDX; |
| infoArray[num+3].refCount = 2; |
| infoArray[num+3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[num+4].regNum = 1; |
| infoArray[num+4].refCount = 4; |
| infoArray[num+4].physicalType = LowOpndRegType_scratch; |
| return num+5; |
| #if FIXME |
| case OP_INVOKE_OBJECT_INIT_RANGE: |
| return 0; |
| #endif |
| case OP_INVOKE_VIRTUAL_QUICK: |
| case OP_INVOKE_VIRTUAL_QUICK_RANGE: |
| #ifdef PREDICTED_CHAINING |
| numTmps = updateGenPrediction(infoArray, false /*not interface*/); |
| infoArray[numTmps].regNum = 1; |
| infoArray[numTmps].refCount = 3; //DU |
| infoArray[numTmps].physicalType = LowOpndRegType_gp; |
| numTmps++; |
| if(inst_op == OP_INVOKE_VIRTUAL_QUICK) |
| k = updateInvokeNoRange(infoArray, numTmps); |
| else |
| k = updateInvokeRange(infoArray, numTmps); |
| return k; |
| #else |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| |
| infoArray[3].regNum = PhysicalReg_ECX; |
| infoArray[3].refCount = 1+1; |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| if(inst_op == OP_INVOKE_VIRTUAL_QUICK_RANGE) |
| k = updateInvokeRange(infoArray, 5); |
| else |
| k = updateInvokeNoRange(infoArray, 5); |
| return k; |
| #endif |
| case OP_INVOKE_SUPER_QUICK: |
| case OP_INVOKE_SUPER_QUICK_RANGE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 4; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 5; |
| infoArray[2].refCount = 2; |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| |
| infoArray[3].regNum = PhysicalReg_ECX; |
| infoArray[3].refCount = 1+1; |
| infoArray[3].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| infoArray[4].regNum = PhysicalReg_EDX; |
| infoArray[4].refCount = 2; |
| infoArray[4].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| |
| infoArray[5].regNum = 1; |
| infoArray[5].refCount = 2; |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| infoArray[6].regNum = 2; |
| infoArray[6].refCount = 2; |
| infoArray[6].physicalType = LowOpndRegType_scratch; |
| if(inst_op == OP_INVOKE_SUPER_QUICK_RANGE) |
| k = updateInvokeRange(infoArray, 7); |
| else |
| k = updateInvokeNoRange(infoArray, 7); |
| return k; |
| #ifdef SUPPORT_HLO |
| case kExtInstruction: |
| switch(inst) { |
| case OP_X_AGET_QUICK: |
| case OP_X_AGET_OBJECT_QUICK: |
| case OP_X_AGET_BOOLEAN_QUICK: |
| case OP_X_AGET_BYTE_QUICK: |
| case OP_X_AGET_CHAR_QUICK: |
| case OP_X_AGET_SHORT_QUICK: |
| vA = FETCH(1) & 0xff; |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[3].linkageToVR = vA; |
| if(inst == OP_X_AGET_BYTE_QUICK || inst == OP_X_AGET_BOOLEAN_QUICK) |
| infoArray[3].is8Bit = true; |
| return 4; |
| case OP_X_AGET_WIDE_QUICK: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 1; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_xmm; |
| return 4; |
| case OP_X_APUT_QUICK: |
| case OP_X_APUT_OBJECT_QUICK: |
| case OP_X_APUT_BOOLEAN_QUICK: |
| case OP_X_APUT_BYTE_QUICK: |
| case OP_X_APUT_CHAR_QUICK: |
| case OP_X_APUT_SHORT_QUICK: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 4; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| if(inst == OP_X_APUT_BYTE_QUICK || inst == OP_X_APUT_BOOLEAN_QUICK) |
| infoArray[3].is8Bit = true; |
| return 4; |
| case OP_X_APUT_WIDE_QUICK: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 1; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_xmm; |
| return 4; |
| case OP_X_DEREF_GET: |
| case OP_X_DEREF_GET_OBJECT: |
| case OP_X_DEREF_GET_BOOLEAN: |
| case OP_X_DEREF_GET_BYTE: |
| case OP_X_DEREF_GET_CHAR: |
| case OP_X_DEREF_GET_SHORT: |
| vA = FETCH(1) & 0xff; |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[1].linkageToVR = vA; |
| if(inst == OP_X_DEREF_GET_BYTE || inst == OP_X_DEREF_GET_BOOLEAN) |
| infoArray[1].is8Bit = true; |
| return 2; |
| case OP_X_DEREF_GET_WIDE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| return 2; |
| case OP_X_DEREF_PUT: |
| case OP_X_DEREF_PUT_OBJECT: |
| case OP_X_DEREF_PUT_BOOLEAN: |
| case OP_X_DEREF_PUT_BYTE: |
| case OP_X_DEREF_PUT_CHAR: |
| case OP_X_DEREF_PUT_SHORT: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| if(inst == OP_X_DEREF_PUT_BYTE || inst == OP_X_DEREF_PUT_BOOLEAN) |
| infoArray[1].is8Bit = true; |
| return 2; |
| case OP_X_DEREF_PUT_WIDE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 1; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_xmm; |
| return 2; |
| case OP_X_ARRAY_CHECKS: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| return 2; |
| case OP_X_CHECK_BOUNDS: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 2; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| return 2; |
| case OP_X_CHECK_NULL: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 2; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = PhysicalReg_EDX; |
| infoArray[1].refCount = 2; |
| infoArray[1].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 2; |
| case OP_X_CHECK_TYPE: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 3; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 5; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 6; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 1; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_scratch; |
| infoArray[5].regNum = PhysicalReg_EAX; |
| infoArray[5].refCount = 2; |
| infoArray[5].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 6; |
| case OP_X_ARRAY_OBJECT_CHECKS: |
| infoArray[0].regNum = 1; |
| infoArray[0].refCount = 3; //DU |
| infoArray[0].physicalType = LowOpndRegType_gp; |
| infoArray[1].regNum = 2; |
| infoArray[1].refCount = 4; //DU |
| infoArray[1].physicalType = LowOpndRegType_gp; |
| infoArray[2].regNum = 3; |
| infoArray[2].refCount = 2; //DU |
| infoArray[2].physicalType = LowOpndRegType_gp; |
| infoArray[3].regNum = 5; |
| infoArray[3].refCount = 2; //DU |
| infoArray[3].physicalType = LowOpndRegType_gp; |
| infoArray[4].regNum = 6; |
| infoArray[4].refCount = 2; //DU |
| infoArray[4].physicalType = LowOpndRegType_gp; |
| infoArray[5].regNum = 1; |
| infoArray[5].refCount = 2; //DU |
| infoArray[5].physicalType = LowOpndRegType_scratch; |
| infoArray[6].regNum = PhysicalReg_EAX; |
| infoArray[6].refCount = 2; |
| infoArray[6].physicalType = LowOpndRegType_gp | LowOpndRegType_hard; |
| return 7; |
| } |
| #endif |
| } |
| return -1; |
| } |