10c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/* 20c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * Copyright (C) 2012 The Android Open Source Project 30c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * 40c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * Licensed under the Apache License, Version 2.0 (the "License"); 50c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * you may not use this file except in compliance with the License. 60c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * You may obtain a copy of the License at 70c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * 80c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * http://www.apache.org/licenses/LICENSE-2.0 90c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * 100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * Unless required by applicable law or agreed to in writing, software 110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * distributed under the License is distributed on an "AS IS" BASIS, 120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * See the License for the specific language governing permissions and 140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen * limitations under the License. 150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen */ 160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! \file LowerJump.cpp 190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen \brief This file lowers the following bytecodes: IF_XXX, GOTO 200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include <math.h> 220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "libdex/DexOpcodes.h" 230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "libdex/DexFile.h" 240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "Lower.h" 250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "NcgAot.h" 260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "enc_wrapper.h" 270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "interp/InterpDefs.h" 280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#include "NcgHelper.h" 290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenLabelMap* globalMap; 310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenLabelMap* globalShortMap;//make sure for each bytecode, there is no duplicated label 320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenLabelMap* globalWorklist = NULL; 330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenLabelMap* globalShortWorklist; 340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint globalMapNum; 360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint globalWorklistNum; 370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint globalDataWorklistNum; 380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint VMAPIWorklistNum; 390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint globalPCWorklistNum; 400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint chainingWorklistNum; 410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenLabelMap* globalDataWorklist = NULL; 430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenLabelMap* globalPCWorklist = NULL; 440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenLabelMap* chainingWorklist = NULL; 450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenLabelMap* VMAPIWorklist = NULL; 460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenchar* ncgClassData; 480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenchar* ncgClassDataPtr; 490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenchar* ncgMethodData; 500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenchar* ncgMethodDataPtr; 510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint ncgClassNum; 520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint ncgMethodNum; 530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenNCGWorklist* globalNCGWorklist; 550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenDataWorklist* methodDataWorklist; 560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef ENABLE_TRACING 570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenMapWorklist* methodMapWorklist; 580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief search globalShortMap to find the entry for the given label 610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenLabelMap* findItemForShortLabel(const char* label) { 640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = globalShortMap; 650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!strcmp(label, ptr->label)) { 670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return ptr; 680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = ptr->nextItem; 700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return NULL; 720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//assume size of "jump reg" is 2 740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define JUMP_REG_SIZE 2 750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define ADD_REG_REG_SIZE 3 760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief update value of the immediate in the given jump instruction 780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chencheck whether the immediate is out of range for the pre-set size 800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint updateJumpInst(char* jumpInst, OpndSize immSize, int relativeNCG) { 820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG_JUMP 830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("update jump inst @ %p with %d", jumpInst, relativeNCG); 840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(immSize == OpndSize_8) { //-128 to 127 860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(relativeNCG >= 128 || relativeNCG < -128) { 870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("pre-allocated space for a forward jump is not big enough"); 880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dvmAbort(); 890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(immSize == OpndSize_16) { //-2^16 to 2^16-1 920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(relativeNCG >= 32768 || relativeNCG < -32768) { 930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("pre-allocated space for a forward jump is not big enough"); 940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dvmAbort(); 950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen encoder_update_imm(relativeNCG, jumpInst); 980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 1020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief insert a label 1030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenIt takes argument checkDup, if checkDup is true, an entry is created in globalShortMap, entries in globalShortWorklist are checked, if there exists a match, the immediate in the jump instruction is updated and the entry is removed from globalShortWorklist; 1050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenotherwise, an entry is created in globalMap. 1060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 1070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertLabel(const char* label, bool checkDup) { 1080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* item = NULL; 1090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!checkDup) { 1100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item = (LabelMap*)malloc(sizeof(LabelMap)); 1110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 1120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 1130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 1140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen snprintf(item->label, LABEL_SIZE, "%s", label); 1160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = stream; 1170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = globalMap; 1180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalMap = item; 1190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG_CODE_SIZE 1200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insert global label %s %p", label, stream); 1210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 1220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalMapNum++; 1230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 1240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item = (LabelMap*)malloc(sizeof(LabelMap)); 1270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 1280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 1290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 1300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen snprintf(item->label, LABEL_SIZE, "%s", label); 1320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = stream; 1330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = globalShortMap; 1340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalShortMap = item; 1350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 1360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insert short-term label %s %p", label, stream); 1370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 1380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = globalShortWorklist; 1390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr_prevItem = NULL; 1400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 1410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!strcmp(ptr->label, label)) { 1420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //perform work 1430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relativeNCG = stream - ptr->codePtr; 1440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unsigned instSize = encoder_get_inst_size(ptr->codePtr); 1450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relativeNCG -= instSize; //size of the instruction 1460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 1470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("perform work short-term %p for label %s relative %d", ptr->codePtr, label, relativeNCG); 1480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 1490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen updateJumpInst(ptr->codePtr, ptr->size, relativeNCG); 1500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //remove work 1510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(ptr_prevItem == NULL) { 1520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalShortWorklist = ptr->nextItem; 1530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 1540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = globalShortWorklist; //ptr_prevItem is still NULL 1550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else { 1570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr_prevItem->nextItem = ptr->nextItem; 1580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 1590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = ptr_prevItem->nextItem; 1600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else { 1630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr_prevItem = ptr; 1640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = ptr->nextItem; 1650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } //while 1670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 1680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 1700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief search globalMap to find the entry for the given label 1710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 1730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenchar* findCodeForLabel(const char* label) { 1740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = globalMap; 1750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 1760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!strcmp(label, ptr->label)) { 1770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return ptr->codePtr; 1780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = ptr->nextItem; 1800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return NULL; 1820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 1840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief search globalShortMap to find the entry for the given label 1850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 1860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 1870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenchar* findCodeForShortLabel(const char* label) { 1880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = globalShortMap; 1890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 1900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!strcmp(label, ptr->label)) { 1910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return ptr->codePtr; 1920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = ptr->nextItem; 1940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 1950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return NULL; 1960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertLabelWorklist(const char* label, OpndSize immSize) { 1980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* item = (LabelMap*)malloc(sizeof(LabelMap)); 1990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 2000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 2010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 2020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 2030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen snprintf(item->label, LABEL_SIZE, "%s", label); 2040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = stream; 2050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->size = immSize; 2060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = globalWorklist; 2070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalWorklist = item; 2080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 2090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insert globalWorklist: %s %p", label, stream); 2100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 2110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 2120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 2130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertShortWorklist(const char* label, OpndSize immSize) { 2150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* item = (LabelMap*)malloc(sizeof(LabelMap)); 2160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 2170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 2180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 2190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 2200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen snprintf(item->label, LABEL_SIZE, "%s", label); 2210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = stream; 2220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->size = immSize; 2230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = globalShortWorklist; 2240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalShortWorklist = item; 2250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 2260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insert globalShortWorklist: %s %p", label, stream); 2270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 2280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 2290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 2300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 2310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief free memory allocated for globalMap 2320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 2340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid freeLabelMap() { 2350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = globalMap; 2360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 2370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalMap = ptr->nextItem; 2380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 2390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = globalMap; 2400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 2410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 2420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 2430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief free memory allocated for globalShortMap 2440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 2460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid freeShortMap() { 2470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = globalShortMap; 2480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 2490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalShortMap = ptr->nextItem; 2500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 2510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = globalShortMap; 2520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 2530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalShortMap = NULL; 2540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 2550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertGlobalPCWorklist(char * offset, char * codeStart) 2570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen{ 2580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* item = (LabelMap*)malloc(sizeof(LabelMap)); 2590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 2600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 2610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 2620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 2630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen snprintf(item->label, LABEL_SIZE, "%s", "export_pc"); 2640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->size = OpndSize_32; 2650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = offset; //points to the immediate operand 2660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->addend = codeStart - streamMethodStart; //relative code pointer 2670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = globalPCWorklist; 2680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalPCWorklist = item; 2690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalPCWorklistNum ++; 2700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 2720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insert globalPCWorklist: %p %p %p %x %p", globalDvmNcg->streamCode, codeStart, streamCode, item->addend, item->codePtr); 2730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 2740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 2750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 2760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertChainingWorklist(int bbId, char * codeStart) 2780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen{ 2790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* item = (LabelMap*)malloc(sizeof(LabelMap)); 2800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 2810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 2820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 2830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 2840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->size = OpndSize_32; 2850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = codeStart; //points to the move instruction 2860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->addend = bbId; //relative code pointer 2870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = chainingWorklist; 2880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen chainingWorklist = item; 2890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 2910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insertChainingWorklist: %p basic block %d", codeStart, bbId); 2920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 2930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 2940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 2950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 2960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertGlobalDataWorklist(char * offset, const char* label) 2970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen{ 2980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* item = (LabelMap*)malloc(sizeof(LabelMap)); 2990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 3000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 3010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 3020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 3030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen snprintf(item->label, LABEL_SIZE, "%s", label); 3040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = offset; 3050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->size = OpndSize_32; 3060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = globalDataWorklist; 3070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalDataWorklist = item; 3080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalDataWorklistNum ++; 3090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 3110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insert globalDataWorklist: %s %p", label, offset); 3120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 3130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 3150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 3160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertVMAPIWorklist(char * offset, const char* label) 3180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen{ 3190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* item = (LabelMap*)malloc(sizeof(LabelMap)); 3200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 3210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 3220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 3230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 3240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen snprintf(item->label, LABEL_SIZE, "%s", label); 3250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = offset; 3260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->size = OpndSize_32; 3270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = VMAPIWorklist; 3290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen VMAPIWorklist = item; 3300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen VMAPIWorklistNum ++; 3320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 3340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insert VMAPIWorklist: %s %p", label, offset); 3350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 3360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 3370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 3380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//////////////////////////////////////////////// 3390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint updateImmRMInst(char* moveInst, const char* label, int relativeNCG); //forward declaration 3420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//////////////////// performLabelWorklist is defined differently for code cache 3430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid performChainingWorklist() { 3440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = chainingWorklist; 3450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 3460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int tmpNCG = traceLabelList[ptr->addend].lop.generic.offset; 3470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen char* NCGaddr = streamMethodStart + tmpNCG; 3480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen updateImmRMInst(ptr->codePtr, "", (int)NCGaddr); 3490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen chainingWorklist = ptr->nextItem; 3500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 3510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = chainingWorklist; 3520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 3530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 3540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid freeChainingWorklist() { 3550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = chainingWorklist; 3560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 3570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen chainingWorklist = ptr->nextItem; 3580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 3590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = chainingWorklist; 3600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 3610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 3620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//Work only for initNCG 3640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid performLabelWorklist() { 3650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = globalWorklist; 3660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 3670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 3680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("perform work global %p for label %s", ptr->codePtr, ptr->label); 3690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 3700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen char* targetCode = findCodeForLabel(ptr->label); 3710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(targetCode != NULL); 3720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relativeNCG = targetCode - ptr->codePtr; 3730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unsigned instSize = encoder_get_inst_size(ptr->codePtr); 3740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relativeNCG -= instSize; //size of the instruction 3750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen updateJumpInst(ptr->codePtr, ptr->size, relativeNCG); 3760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalWorklist = ptr->nextItem; 3770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 3780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = globalWorklist; 3790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 3800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 3810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid freeLabelWorklist() { 3820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen LabelMap* ptr = globalWorklist; 3830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 3840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalWorklist = ptr->nextItem; 3850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 3860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = globalWorklist; 3870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 3880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 3890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/////////////////////////////////////////////////// 3910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 3920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief update value of the immediate in the given move instruction 3930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 3940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 3950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint updateImmRMInst(char* moveInst, const char* label, int relativeNCG) { 3960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 3970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("perform work ImmRM inst @ %p for label %s with %d", moveInst, label, relativeNCG); 3980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 3990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen encoder_update_imm_rm(relativeNCG, moveInst); 4000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 4010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 4020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! maximum instruction size for jump,jcc,call: 6 for jcc rel32 4030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define MAX_JCC_SIZE 6 4040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! minimum instruction size for jump,jcc,call: 2 4050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define MIN_JCC_SIZE 2 4060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 4070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief estimate size of the immediate 4080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenSomehow, 16 bit jump does not work. This function will return either 8 bit or 32 bit 4100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenEXAMPLE: 4110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen native code at A: ... 4120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen native code at B: jump relOffset (target is A) 4130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen native code at B': 4140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen --> relOffset = A - B' = A - B - size of the jump instruction 4150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Argument "target" is equal to A - B. To determine size of the immediate, we check tha value of "target - size of the jump instructoin" 4160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 4170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenOpndSize estOpndSizeFromImm(int target) { 4180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(target-MIN_JCC_SIZE < 128 && target-MAX_JCC_SIZE >= -128) return OpndSize_8; 4190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef SUPPORT_IMM_16 4200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(target-MIN_JCC_SIZE < 32768 && target-MAX_JCC_SIZE >= -32768) return OpndSize_16; 4210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 4220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return OpndSize_32; 4230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 4240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 4250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief return size of a jump or call instruction 4260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 4280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenunsigned getJmpCallInstSize(OpndSize size, JmpCall_type type) { 4290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(type == JmpCall_uncond) { 4300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(size == OpndSize_8) return 2; 4310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(size == OpndSize_16) return 4; 4320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 5; 4330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 4340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(type == JmpCall_cond) { 4350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(size == OpndSize_8) return 2; 4360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(size == OpndSize_16) return 5; 4370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 6; 4380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 4390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(type == JmpCall_reg) { 4400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(size == OpndSize_32); 4410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return JUMP_REG_SIZE; 4420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 4430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(type == JmpCall_call) { 4440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(size != OpndSize_8); 4450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(size == OpndSize_16) return 4; 4460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 5; 4470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 4480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 4490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 4500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 4510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief check whether a branch target is already handled, if yes, return the size of the immediate; otherwise, call insertShortWorklist or insertLabelWorklist. 4520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenIf the branch target is not handled, call insertShortWorklist or insertLabelWorklist depending on isShortTerm, unknown is set to true, immSize is set to 32 if isShortTerm is false, set to 32 if isShortTerm is true and target is check_cast_null, set to 8 otherwise. 4540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenIf the branch target is handled, call estOpndSizeFromImm to set immSize for jump instruction, returns the value of the immediate 4560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 4570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint getRelativeOffset(const char* target, bool isShortTerm, JmpCall_type type, bool* unknown, OpndSize* immSize) { 4580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen char* targetPtrInStream = NULL; 4590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(isShortTerm) targetPtrInStream = findCodeForShortLabel(target); 4600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else targetPtrInStream = findCodeForLabel(target); 4610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 4620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relOffset; 4630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *unknown = false; 4640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(targetPtrInStream == NULL) { 4650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //branch target is not handled yet 4660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relOffset = 0; 4670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *unknown = true; 4680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(isShortTerm) { 4690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* for backward jump, at this point, we don't know how far the target is from this jump 4700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen since the lable is only used within a single bytecode, we assume OpndSize_8 is big enough 4710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen but there are special cases where we should use 32 bit offset 4720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen */ 4730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!strcmp(target, ".check_cast_null") || !strcmp(target, ".stackOverflow") || 4740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen !strcmp(target, ".invokeChain") || 4750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen !strcmp(target, ".new_instance_done") || 4760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen !strcmp(target, ".new_array_done") || 4770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen !strcmp(target, ".fill_array_data_done") || 4780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen !strcmp(target, ".inlined_string_compare_done") || 4790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen !strncmp(target, "after_exception", 15)) { 4800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef SUPPORT_IMM_16 4810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *immSize = OpndSize_16; 4820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#else 4830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *immSize = OpndSize_32; 4840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 4850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } else { 4860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *immSize = OpndSize_8; 4870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 4880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG_JUMP 4890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insert to short worklist %s %d", target, *immSize); 4900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 4910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertShortWorklist(target, *immSize); 4920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 4930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else { 4940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef SUPPORT_IMM_16 4950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *immSize = OpndSize_16; 4960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#else 4970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *immSize = OpndSize_32; 4980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 4990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabelWorklist(target, *immSize); 5000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(type == JmpCall_call) { //call sz16 does not work in gdb 5020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *immSize = OpndSize_32; 5030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 5050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else if (!isShortTerm) { 5070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef SUPPORT_IMM_16 5080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *immSize = OpndSize_16; 5090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#else 5100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *immSize = OpndSize_32; 5110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 5120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabelWorklist(target, *immSize); 5130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 5160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("backward branch @ %p for label %s", stream, target); 5170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 5180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relOffset = targetPtrInStream - stream; 5190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(type == JmpCall_call) *immSize = OpndSize_32; 5200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else 5210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *immSize = estOpndSizeFromImm(relOffset); 5220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relOffset -= getJmpCallInstSize(*immSize, type); 5240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return relOffset; 5250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 5280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief generate a single native instruction "jcc imm" to jump to a label 5290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 5310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid conditional_jump(ConditionCode cc, const char* target, bool isShortTerm) { 5320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(jumpToException(target) && currentExceptionBlockIdx >= 0) { //jump to the exceptionThrow block 5330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen condJumpToBasicBlock(stream, cc, currentExceptionBlockIdx); 5340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return; 5350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Mnemonic m = (Mnemonic)(Mnemonic_Jcc + cc); 5370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen bool unknown; 5380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen OpndSize size; 5390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int imm = 0; 5400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen imm = getRelativeOffset(target, isShortTerm, JmpCall_cond, &unknown, &size); 5410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dump_label(m, size, imm, target, isShortTerm); 5420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 5440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief generate a single native instruction "jmp imm" to jump to ".invokeArgsDone" 5450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 5470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid goto_invokeArgsDone() { 5480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump_global_API(".invokeArgsDone", false); 5490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 5510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief generate a single native instruction "jmp imm" to jump to a label 5520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenIf the target is ".invokeArgsDone" and mode is NCG O1, extra work is performed to dump content of virtual registers to memory. 5540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 5550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid unconditional_jump(const char* target, bool isShortTerm) { 5560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(jumpToException(target) && currentExceptionBlockIdx >= 0) { //jump to the exceptionThrow block 5570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen jumpToBasicBlock(stream, currentExceptionBlockIdx); 5580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return; 5590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Mnemonic m = Mnemonic_JMP; 5610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen bool unknown; 5620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen OpndSize size; 5630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(gDvm.executionMode == kExecutionModeNcgO1) { 5640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //for other three labels used by JIT: invokeArgsDone_formal, _native, _jit 5650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!strncmp(target, ".invokeArgsDone", 15)) { 5660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen touchEcx(); //keep ecx live, if ecx was spilled, it is loaded here 5670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen beforeCall(target); // 5680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!strcmp(target, ".invokeArgsDone")) { 5700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen nextVersionOfHardReg(PhysicalReg_EDX, 1); //edx will be used in a function 5710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call("ncgGetEIP"); //must be immediately before JMP 5720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int imm = 0; 5750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen imm = getRelativeOffset(target, isShortTerm, JmpCall_uncond, &unknown, &size); 5760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dump_label(m, size, imm, target, isShortTerm); 5770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(gDvm.executionMode == kExecutionModeNcgO1) { 5780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(!strncmp(target, ".invokeArgsDone", 15)) { 5790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen afterCall(target); //un-spill before executing the next bytecode 5800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 5820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 5840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief generate a single native instruction "jcc imm" 5850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 5870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid conditional_jump_int(ConditionCode cc, int target, OpndSize size) { 5880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Mnemonic m = (Mnemonic)(Mnemonic_Jcc + cc); 5890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dump_ncg(m, size, target); 5900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 5920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief generate a single native instruction "jmp imm" 5930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 5940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 5950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid unconditional_jump_int(int target, OpndSize size) { 5960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Mnemonic m = Mnemonic_JMP; 5970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dump_ncg(m, size, target); 5980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 5990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 6000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief generate a single native instruction "jmp reg" 6010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 6030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid unconditional_jump_reg(int reg, bool isPhysical) { 6040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dump_reg(Mnemonic_JMP, ATOM_NORMAL, OpndSize_32, reg, isPhysical, LowOpndRegType_gp); 6050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 6080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief generate a single native instruction to call a function 6090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenIf mode is NCG O1, extra work is performed to dump content of virtual registers to memory. 6110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 6120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid call(const char* target) { 6130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(gDvm.executionMode == kExecutionModeNcgO1) { 6140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen beforeCall(target); 6150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 6160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Mnemonic m = Mnemonic_CALL; 6170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen bool dummy; 6180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen OpndSize size; 6190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relOffset = 0; 6200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relOffset = getRelativeOffset(target, false, JmpCall_call, &dummy, &size); 6210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dump_label(m, size, relOffset, target, false); 6220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(gDvm.executionMode == kExecutionModeNcgO1) { 6230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen afterCall(target); 6240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 6250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 6270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief generate a single native instruction to call a function 6280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 6300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid call_reg(int reg, bool isPhysical) { 6310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Mnemonic m = Mnemonic_CALL; 6320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dump_reg(m, ATOM_NORMAL, OpndSize_32, reg, isPhysical, LowOpndRegType_gp); 6330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid call_reg_noalloc(int reg, bool isPhysical) { 6350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Mnemonic m = Mnemonic_CALL; 6360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dump_reg_noalloc(m, OpndSize_32, reg, isPhysical, LowOpndRegType_gp); 6370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 6400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief generate a single native instruction to call a function 6410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 6430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid call_mem(int disp, int reg, bool isPhysical) { 6440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen Mnemonic m = Mnemonic_CALL; 6450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dump_mem(m, ATOM_NORMAL, OpndSize_32, disp, reg, isPhysical); 6460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 6490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief insert an entry to globalNCGWorklist 6500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 6520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertNCGWorklist(s4 relativePC, OpndSize immSize) { 6530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int offsetNCG2 = stream - streamMethodStart; 6540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 6550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("insert NCGWorklist (goto forward) @ %p offsetPC %x relativePC %x offsetNCG %x", stream, offsetPC, relativePC, offsetNCG2); 6560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 6570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen NCGWorklist* item = (NCGWorklist*)malloc(sizeof(NCGWorklist)); 6580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 6590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 6600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 6610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 6620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->relativePC = relativePC; 6630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->offsetPC = offsetPC; 6640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->offsetNCG = offsetNCG2; 6650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = stream; 6660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->size = immSize; 6670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = globalNCGWorklist; 6680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalNCGWorklist = item; 6690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 6700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef ENABLE_TRACING 6720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertMapWorklist(s4 BCOffset, s4 NCGOffset, int isStartOfPC) { 6730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 6740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 6750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 6760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 6770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief insert an entry to methodDataWorklist 6780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 6790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenThis function is used by bytecode FILL_ARRAY_DATA, PACKED_SWITCH, SPARSE_SWITCH 6800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 6810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint insertDataWorklist(s4 relativePC, char* codePtr1) { 6820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //insert according to offsetPC+relativePC, smallest at the head 6830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen DataWorklist* item = (DataWorklist*)malloc(sizeof(DataWorklist)); 6840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(item == NULL) { 6850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGE("Memory allocation failed"); 6860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return -1; 6870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 6880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->relativePC = relativePC; 6890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->offsetPC = offsetPC; 6900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr = codePtr1; 6910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->codePtr2 = stream; //jump_reg for switch 6920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen DataWorklist* ptr = methodDataWorklist; 6930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen DataWorklist* prev_ptr = NULL; 6940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 6950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int tmpPC = ptr->offsetPC + ptr->relativePC; 6960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int tmpPC2 = relativePC + offsetPC; 6970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(tmpPC2 < tmpPC) { 6980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen break; 6990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 7000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen prev_ptr = ptr; 7010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = ptr->nextItem; 7020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 7030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //insert item before ptr 7040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(prev_ptr != NULL) { 7050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen prev_ptr->nextItem = item; 7060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 7070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen else methodDataWorklist = item; 7080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen item->nextItem = ptr; 7090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 7100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 7110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 7130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief work on globalNCGWorklist 7140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 7160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint performNCGWorklist() { 7170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen NCGWorklist* ptr = globalNCGWorklist; 7180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 7190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGV("perform NCG worklist: @ %p target block %d target NCG %x", 7200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr->codePtr, ptr->relativePC, traceLabelList[ptr->relativePC].lop.generic.offset); 7210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int tmpNCG = traceLabelList[ptr->relativePC].lop.generic.offset; 7220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(tmpNCG >= 0); 7230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relativeNCG = tmpNCG - ptr->offsetNCG; 7240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unsigned instSize = encoder_get_inst_size(ptr->codePtr); 7250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relativeNCG -= instSize; 7260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen updateJumpInst(ptr->codePtr, ptr->size, relativeNCG); 7270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalNCGWorklist = ptr->nextItem; 7280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 7290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = globalNCGWorklist; 7300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 7310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 7320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 7330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid freeNCGWorklist() { 7340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen NCGWorklist* ptr = globalNCGWorklist; 7350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 7360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalNCGWorklist = ptr->nextItem; 7370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 7380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = globalNCGWorklist; 7390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 7400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 7410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 7430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief used by bytecode SWITCH 7440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChentargetPC points to start of the data section 7460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenCode sequence for SWITCH 7470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call ncgGetEIP 7480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen @codeInst: add_reg_reg %eax, %edx 7490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen jump_reg %edx 7500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenThis function returns the offset in native code between add_reg_reg and the data section 7510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 7520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint getRelativeNCGForSwitch(int targetPC, char* codeInst) { 7530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int tmpNCG = mapFromBCtoNCG[targetPC]; 7540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int offsetNCG2 = codeInst - streamMethodStart; 7550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relativeOff = tmpNCG - offsetNCG2; 7560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return relativeOff; 7570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 7580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 7590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief work on methodDataWorklist 7600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 7620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint performDataWorklist() { 7630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen DataWorklist* ptr = methodDataWorklist; 7640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(ptr == NULL) return 0; 7650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen char* codeCacheEnd = ((char *) gDvmJit.codeCache) + gDvmJit.codeCacheSize - CODE_CACHE_PADDING; 7670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 insnsSize = dvmGetMethodInsnsSize(currentMethod); //bytecode 7680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //align stream to multiple of 4 7690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int alignBytes = (int)stream & 3; 7700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(alignBytes != 0) alignBytes = 4-alignBytes; 7710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen stream += alignBytes; 7720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 7740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int tmpPC = ptr->offsetPC + ptr->relativePC; 7750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int endPC = insnsSize; 7760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(ptr->nextItem != NULL) endPC = ptr->nextItem->offsetPC + ptr->nextItem->relativePC; 7770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen mapFromBCtoNCG[tmpPC] = stream - streamMethodStart; //offsetNCG in byte 7780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //handle fill_array_data, packed switch & sparse switch 7800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 tmpInst = *(currentMethod->insns + ptr->offsetPC); 7810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2* sizePtr; 7820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4* entryPtr_bytecode; 7830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 tSize, iVer; 7840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 sz; 7850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if (gDvmJit.codeCacheFull == true) { 7870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // We are out of code cache space. Skip writing data/code to 7880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen // code cache. Simply free the item. 7890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen methodDataWorklist = ptr->nextItem; 7900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 7910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = methodDataWorklist; 7920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 7930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 7940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen switch (INST_INST(tmpInst)) { 7950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen case OP_FILL_ARRAY_DATA: 7960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen sz = (endPC-tmpPC)*sizeof(u2); 7970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if ((stream + sz) < codeCacheEnd) { 7980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen memcpy(stream, (u2*)currentMethod->insns+tmpPC, sz); 7990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG_CODE_SIZE 8000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("copy data section to stream %p: start at %d, %d bytes", stream, tmpPC, sz); 8010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 8020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 8030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("update data section at %p with %d", ptr->codePtr, stream-ptr->codePtr); 8040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 8050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen updateImmRMInst(ptr->codePtr, "", stream - ptr->codePtr); 8060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen stream += sz; 8070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } else { 8080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen gDvmJit.codeCacheFull = true; 8090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 8100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen break; 8110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen case OP_PACKED_SWITCH: 8120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen updateImmRMInst(ptr->codePtr, "", stream-ptr->codePtr); 8130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen sizePtr = (u2*)currentMethod->insns+tmpPC + 1 /*signature*/; 8140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen entryPtr_bytecode = (s4*)(sizePtr + 1 /*size*/ + 2 /*firstKey*/); 8150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen tSize = *(sizePtr); 8160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen sz = tSize * 4; /* expected size needed in stream */ 8170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if ((stream + sz) < codeCacheEnd) { 8180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen for(iVer = 0; iVer < tSize; iVer++) { 8190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //update entries 8200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4 relativePC = *entryPtr_bytecode; //relative to ptr->offsetPC 8210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //need stream, offsetPC, 8220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relativeNCG = getRelativeNCGForSwitch(relativePC+ptr->offsetPC, ptr->codePtr2); 8230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG_CODE_SIZE 8240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("convert target from %d to %d", relativePC+ptr->offsetPC, relativeNCG); 8250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 8260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *((s4*)stream) = relativeNCG; 8270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen stream += 4; 8280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen entryPtr_bytecode++; 8290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 8300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } else { 8310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen gDvmJit.codeCacheFull = true; 8320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 8330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen break; 8340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen case OP_SPARSE_SWITCH: 8350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen updateImmRMInst(ptr->codePtr, "", stream-ptr->codePtr); 8360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen sizePtr = (u2*)currentMethod->insns+tmpPC + 1 /*signature*/; 8370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4* keyPtr_bytecode = (s4*)(sizePtr + 1 /*size*/); 8380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen tSize = *(sizePtr); 8390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen entryPtr_bytecode = (s4*)(keyPtr_bytecode + tSize); 8400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen sz = tSize * (sizeof(s4) + 4); /* expected size needed in stream */ 8410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if ((stream + sz) < codeCacheEnd) { 8420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen memcpy(stream, keyPtr_bytecode, tSize*sizeof(s4)); 8430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen stream += tSize*sizeof(s4); 8440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen for(iVer = 0; iVer < tSize; iVer++) { 8450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //update entries 8460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4 relativePC = *entryPtr_bytecode; //relative to ptr->offsetPC 8470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //need stream, offsetPC, 8480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relativeNCG = getRelativeNCGForSwitch(relativePC+ptr->offsetPC, ptr->codePtr2); 8490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *((s4*)stream) = relativeNCG; 8500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen stream += 4; 8510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen entryPtr_bytecode++; 8520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 8530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } else { 8540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen gDvmJit.codeCacheFull = true; 8550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 8560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen break; 8570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 8580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 8590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //remove the item 8600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen methodDataWorklist = ptr->nextItem; 8610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 8620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = methodDataWorklist; 8630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 8640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 8650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 8660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenvoid freeDataWorklist() { 8670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen DataWorklist* ptr = methodDataWorklist; 8680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen while(ptr != NULL) { 8690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen methodDataWorklist = ptr->nextItem; 8700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen free(ptr); 8710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ptr = methodDataWorklist; 8720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 8730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 8740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 8750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen////////////////////////// 8760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 8770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief check whether a branch target (specified by relative offset in bytecode) is already handled, if yes, return the size of the immediate; otherwise, call insertNCGWorklist. 8780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 8790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenIf the branch target is not handled, call insertNCGWorklist, unknown is set to true, immSize is set to 32. 8800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 8810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenIf the branch target is handled, call estOpndSizeFromImm to set immSize for jump instruction, returns the value of the immediate 8820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 8830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint getRelativeNCG(s4 tmp, JmpCall_type type, bool* unknown, OpndSize* size) {//tmp: relativePC 8840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int tmpNCG = traceLabelList[tmp].lop.generic.offset; 8850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 8860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *unknown = false; 8870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(tmpNCG <0) { 8880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *unknown = true; 8890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef SUPPORT_IMM_16 8900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *size = OpndSize_16; 8910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#else 8920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *size = OpndSize_32; 8930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 8940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertNCGWorklist(tmp, *size); 8950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 8960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 8970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int offsetNCG2 = stream - streamMethodStart; 8980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_NCG 8990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ALOGI("goto backward @ %p offsetPC %d relativePC %d offsetNCG %d relativeNCG %d", stream, offsetPC, tmp, offsetNCG2, tmpNCG-offsetNCG2); 9000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 9010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relativeOff = tmpNCG - offsetNCG2; 9020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen *size = estOpndSizeFromImm(relativeOff); 9030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return relativeOff - getJmpCallInstSize(*size, type); 9040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 9050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 9060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief a helper function to handle backward branch 9070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Cheninput: jump target in %eax; at end of the function, jump to %eax 9090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 9100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_backwardBranch() { 9110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_backwardBranch", false); 9120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen spill_reg(PhysicalReg_EAX, true); 9130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call("common_periodicChecks_entry"); 9140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unspill_reg(PhysicalReg_EAX, true); 9150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump_reg(PhysicalReg_EAX, true); 9160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 9170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 9180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//when this is called from JIT, there is no need to check GC 9190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_goto(s4 tmp) { //tmp: target basic block id 9200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen bool unknown; 9210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen OpndSize size; 9220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 9230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 9240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relativeNCG = tmp; 9260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relativeNCG = getRelativeNCG(tmp, JmpCall_uncond, &unknown, &size); 9270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump_int(relativeNCG, size); 9280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 1; 9290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 9300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_if(s4 tmp, ConditionCode cc_next, ConditionCode cc) { 9310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen bool unknown; 9320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen OpndSize size; 9330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int relativeNCG = traceCurrentBB->taken ? traceCurrentBB->taken->id : 0; 9340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(traceCurrentBB->taken) 9360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relativeNCG = getRelativeNCG(traceCurrentBB->taken->id, JmpCall_cond, &unknown, &size); 9370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump_int(cc, relativeNCG, size); 9380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relativeNCG = traceCurrentBB->fallThrough ? traceCurrentBB->fallThrough->id : 0; 9390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if(traceCurrentBB->fallThrough) 9400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen relativeNCG = getRelativeNCG(traceCurrentBB->fallThrough->id, JmpCall_uncond, &unknown, &size); 9410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump_int(relativeNCG, size); 9420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 2; 9430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 9440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 9460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function to handle null object error 9470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 9490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_errNullObject() { 9500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_errNullObject", false); 9510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 9520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, LstrNullPointerException, PhysicalReg_ECX, true); 9530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_throw", false); 9540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 9550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 9560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 9570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function to handle string index error 9580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 9600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_StringIndexOutOfBounds() { 9610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_StringIndexOutOfBounds", false); 9620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 9630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, LstrStringIndexOutOfBoundsException, PhysicalReg_ECX, true); 9640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_throw", false); 9650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 9660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 9670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 9690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function to handle array index error 9700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 9720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_errArrayIndex() { 9730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_errArrayIndex", false); 9740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 9750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, LstrArrayIndexException, PhysicalReg_ECX, true); 9760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_throw", false); 9770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 9780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 9790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 9800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function to handle array store error 9810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 9830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_errArrayStore() { 9840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_errArrayStore", false); 9850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 9860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, LstrArrayStoreException, PhysicalReg_ECX, true); 9870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_throw", false); 9880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 9890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 9900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 9910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function to handle negative array size error 9920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 9930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 9940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_errNegArraySize() { 9950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_errNegArraySize", false); 9960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 9970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, LstrNegativeArraySizeException, PhysicalReg_ECX, true); 9980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_throw", false); 9990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 10000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 10010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 10020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function to handle divide-by-zero error 10030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 10050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_errDivideByZero() { 10060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_errDivideByZero", false); 10070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, LstrDivideByZero, PhysicalReg_EAX, true); 10080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, LstrArithmeticException, PhysicalReg_ECX, true); 10090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_throw", false); 10100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 10110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 10120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 10130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function to handle no such method error 10140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 10160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_errNoSuchMethod() { 10170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_errNoSuchMethod", false); 10180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 10190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, LstrNoSuchMethodError, PhysicalReg_ECX, true); 10200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_throw", false); 10210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 10220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 10230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint call_dvmFindCatchBlock(); 10240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_ESI //self callee-saved 10260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_EBX //exception callee-saved 10270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_3 PhysicalReg_EAX //method that caused exception 10280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 10290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function common_exceptionThrown 10300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 10320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_exceptionThrown() { 10330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_exceptionThrown", false); 10340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen typedef void (*vmHelper)(int); 10350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen vmHelper funcPtr = dvmJitToExceptionThrown; 10360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, (int)funcPtr, C_SCRATCH_1, isScratchPhysical); 10370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump_reg(C_SCRATCH_1, isScratchPhysical); 10380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 10390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 10400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 10410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 10420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_3 10430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 10450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function to throw an exception with message 10460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenINPUT: obj_reg(%eax), exceptionPtrReg(%ecx) 10480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenSCRATCH: C_SCRATCH_1(%esi) & C_SCRATCH_2(%edx) 10490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenOUTPUT: no 10500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 10510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint throw_exception_message(int exceptionPtrReg, int obj_reg, bool isPhysical, 10520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int startLR/*logical register index*/, bool startPhysical) { 10530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_throw_message", false); 10540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX; 10550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 10560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offObject_clazz, obj_reg, isPhysical, C_SCRATCH_1, isScratchPhysical); 10580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offClassObject_descriptor, C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical); 10590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 10600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, C_SCRATCH_2, isScratchPhysical, 4, PhysicalReg_ESP, true); 10610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, exceptionPtrReg, true, 0, PhysicalReg_ESP, true); 10620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmThrowWithMessage(); 10630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 10640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_exceptionThrown", false); 10650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 10660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 10670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 10680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function to throw an exception 10690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenscratch: C_SCRATCH_1(%edx) 10710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 10720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint throw_exception(int exceptionPtrReg, int immReg, 10730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int startLR/*logical register index*/, bool startPhysical) { 10740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_throw", false); 10750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_EDX; scratchRegs[1] = PhysicalReg_Null; 10760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 10770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 10790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, immReg, true, 4, PhysicalReg_ESP, true); 10800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, exceptionPtrReg, true, 0, PhysicalReg_ESP, true); 10810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmThrow(); 10820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 10830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_exceptionThrown", false); 10840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 10850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 10860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode GOTO 10880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 10900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_goto() { 10910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = traceCurrentBB->taken->id; 10920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int retval = common_goto(tmp); 10930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 1; 10940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return retval; 10950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 10960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode GOTO_16 10970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 10980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 10990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_goto_16() { 11000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = traceCurrentBB->taken->id; 11010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int retval = common_goto(tmp); 11020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 11030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return retval; 11040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 11050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode GOTO_32 11060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 11070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 11080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_goto_32() { 11090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = traceCurrentBB->taken->id; 11100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen int retval = common_goto((s4)tmp); 11110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 3; 11120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return retval; 11130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 11140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 11150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode PACKED_SWITCH 11160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 11170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 11180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_packed_switch() { 11190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 tmp = (u4)FETCH(1); 11200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen tmp |= (u4)FETCH(2) << 16; 11210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 11220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 11230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_EACH_BYTECODE 11240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 tSize = 0; 11250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4 firstKey = 0; 11260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4* entries = NULL; 11270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#else 11280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2* switchData = rPC + (s4)tmp; 11290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if (*switchData++ != kPackedSwitchSignature) { 11300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* should have been caught by verifier */ 11310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dvmThrowInternalError( 11320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen "bad packed switch magic"); 11330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; //no_op 11340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 11350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 tSize = *switchData++; 11360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(tSize > 0); 11370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4 firstKey = *switchData++; 11380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen firstKey |= (*switchData++) << 16; 11390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4* entries = (s4*) switchData; 11400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(((u4)entries & 0x3) == 0); 11410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 11420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 11430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 11440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //dvmNcgHandlePackedSwitch: testVal, size, first_key, targets 11450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-16, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 11460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, tSize, 8, PhysicalReg_ESP, true); 11470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, firstKey, 4, PhysicalReg_ESP, true); 11480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 11490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* "entries" is constant for JIT 11500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen it is the 1st argument to dvmJitHandlePackedSwitch */ 11510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, (int)entries, 0, PhysicalReg_ESP, true); 11520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 1, false, 12, PhysicalReg_ESP, true); 11530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 11540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if value out of range, fall through (no_op) 11550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //return targets[testVal - first_key] 11560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; 11570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmJitHandlePackedSwitch(); 11580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(16, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 11590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //TODO: eax should be absolute address, call globalVREndOfBB, constVREndOfBB 11600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //conditional_jump_global_API(Condition_LE, "common_backwardBranch", false); 11610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 11620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); //update GG VRs 11630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //get rPC, %eax has the relative PC offset 11640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen alu_binary_imm_reg(OpndSize_32, add_opc, (int)rPC, PhysicalReg_EAX, true); 11650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_2; 116619eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji#if defined(WITH_JIT_TUNING) 116719eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji /* Fall back to interpreter after resolving address of switch target. 116819eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji * Indicate a kSwitchOverflow. Note: This is not an "overflow". But it helps 116919eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji * count the times we return from a Switch 117019eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji */ 117119eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji move_imm_to_mem(OpndSize_32, kSwitchOverflow, 0, PhysicalReg_ESP, true); 117219eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji#endif 11730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen jumpToInterpNoChain(); 11740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 3; 11750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 11760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 11770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 11780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 11790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 11800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode SPARSE_SWITCH 11810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 11820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 11830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_sparse_switch() { 11840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u4 tmp = (u4)FETCH(1); 11850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen tmp |= (u4)FETCH(2) << 16; 11860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 11870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef DEBUG_EACH_BYTECODE 11880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 tSize = 0; 11890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen const s4* keys = NULL; 11900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4* entries = NULL; 11910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#else 11920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2* switchData = rPC + (s4)tmp; 11930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 11940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen if (*switchData++ != kSparseSwitchSignature) { 11950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* should have been caught by verifier */ 11960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen dvmThrowInternalError( 11970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen "bad sparse switch magic"); 11980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; //no_op 11990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen } 12000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 tSize = *switchData++; 12010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(tSize > 0); 12020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen const s4* keys = (const s4*) switchData; 12030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(((u4)keys & 0x3) == 0); 12040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s4* entries = (s4*)switchData + tSize; 12050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen assert(((u4)entries & 0x3) == 0); 12060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 12070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 12080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 12090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //dvmNcgHandleSparseSwitch: keys, size, testVal 12100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 12110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, tSize, 4, PhysicalReg_ESP, true); 12120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 12130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* "keys" is constant for JIT 12140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen it is the 1st argument to dvmJitHandleSparseSwitch */ 12150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, (int)keys, 0, PhysicalReg_ESP, true); 12160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, 1, false, 8, PhysicalReg_ESP, true); 12170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 12180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_1; 12190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //if testVal is in keys, return the corresponding target 12200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //otherwise, fall through (no_op) 12210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmJitHandleSparseSwitch(); 12220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 12230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //TODO: eax should be absolute address, call globalVREndOfBB constVREndOfBB 12240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //conditional_jump_global_API(Condition_LE, "common_backwardBranch", false); 12250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 12260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 12270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //get rPC, %eax has the relative PC offset 12280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen alu_binary_imm_reg(OpndSize_32, add_opc, (int)rPC, PhysicalReg_EAX, true); 12290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_SCRATCH_2; 123019eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji#if defined(WITH_JIT_TUNING) 123119eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji /* Fall back to interpreter after resolving address of switch target. 123219eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji * Indicate a kSwitchOverflow. Note: This is not an "overflow". But it helps 123319eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji * count the times we return from a Switch 123419eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji */ 123519eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji move_imm_to_mem(OpndSize_32, kSwitchOverflow, 0, PhysicalReg_ESP, true); 123619eb287ac848f10e03ca2614bf53bd9d1ddd3724Udayan Banerji#endif 12370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen jumpToInterpNoChain(); 12380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 3; 12390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 12400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 12410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 12420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 12430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 12440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_EBX 12450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_EQ 12460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 12470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 12480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_eq() { 12490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_A(inst); 12500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vB = INST_B(inst); 12510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 12520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 12530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_VR_reg(OpndSize_32, vB, 1, false); 12540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 12550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 12560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_NE, Condition_E); 12570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 12580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 12590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 12600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_NE 12610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 12620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 12630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_ne() { 12640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_A(inst); 12650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vB = INST_B(inst); 12660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 12670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 12680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_VR_reg(OpndSize_32, vB, 1, false); 12690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 12700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 12710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_E, Condition_NE); 12720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 12730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 12740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 12750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_LT 12760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 12770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 12780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_lt() { 12790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_A(inst); 12800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vB = INST_B(inst); 12810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 12820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 12830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_VR_reg(OpndSize_32, vB, 1, false); 12840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 12850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 12860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_GE, Condition_L); 12870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 12880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 12890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 12900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_GE 12910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 12920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 12930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_ge() { 12940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_A(inst); 12950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vB = INST_B(inst); 12960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 12970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 12980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_VR_reg(OpndSize_32, vB, 1, false); 12990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 13000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 13010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_L, Condition_GE); 13020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 13030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 13040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 13050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_GT 13060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 13070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 13080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_gt() { 13090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_A(inst); 13100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vB = INST_B(inst); 13110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 13120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 13130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_VR_reg(OpndSize_32, vB, 1, false); 13140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 13150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 13160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_LE, Condition_G); 13170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 13180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 13190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 13200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_LE 13210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 13220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 13230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_le() { 13240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_A(inst); 13250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vB = INST_B(inst); 13260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 13270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_virtual_reg(vA, OpndSize_32, 1, false); 13280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_VR_reg(OpndSize_32, vB, 1, false); 13290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 13300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 13310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_G, Condition_LE); 13320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 13330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 13340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 13350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 13360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_EQZ 13370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 13380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 13390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_eqz() { 13400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 13410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 13420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_VR(OpndSize_32, 13430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 0, vA); 13440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 13450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 13460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_NE, Condition_E); 13470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 13480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 13490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 13500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_NEZ 13510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 13520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 13530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_nez() { 13540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 13550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 13560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_VR(OpndSize_32, 13570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 0, vA); 13580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 13590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 13600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_E, Condition_NE); 13610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 13620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 13630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 13640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_LTZ 13650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 13660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 13670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_ltz() { 13680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 13690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 13700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_VR(OpndSize_32, 13710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 0, vA); 13720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 13730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 13740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_GE, Condition_L); 13750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 13760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 13770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 13780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_GEZ 13790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 13800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 13810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_gez() { 13820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 13830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 13840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_VR(OpndSize_32, 13850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 0, vA); 13860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 13870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 13880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_L, Condition_GE); 13890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 13900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 13910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 13920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_GTZ 13930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 13940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 13950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_gtz() { 13960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 13970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 13980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_VR(OpndSize_32, 13990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 0, vA); 14000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 14010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 14020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_LE, Condition_G); 14030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 14040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 14050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 14060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! lower bytecode IF_LEZ 14070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//! 14090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint op_if_lez() { 14100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen u2 vA = INST_AA(inst); 14110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen s2 tmp = (s2)FETCH(1); 14120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_VR(OpndSize_32, 14130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 0, vA); 14140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen constVREndOfBB(); 14150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen globalVREndOfBB(currentMethod); 14160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen common_if(tmp, Condition_G, Condition_LE); 14170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen rPC += 2; 14180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 14190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 14200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_1 PhysicalReg_ECX 14220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#define P_GPR_2 PhysicalReg_EBX 14230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 14240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function common_periodicChecks4 to check GC request 14250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan ChenBCOffset in %edx 14260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 14270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_periodicChecks4() { 14280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_periodicChecks4", false); 14290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#if (!defined(ENABLE_TRACING)) 14300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_self_pointer(PhysicalReg_ECX, true); 14310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offsetof(Thread, suspendCount), PhysicalReg_ECX, true, PhysicalReg_EAX, true); 14320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); //suspendCount 14330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, "common_handleSuspend4", true); //called once 14340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen x86_return(); 14350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_handleSuspend4", true); 14370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen push_reg_to_stack(OpndSize_32, PhysicalReg_ECX, true); 14380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmCheckSuspendPending(); 14390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(4, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 14400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen x86_return(); 14410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#else 14430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /////////////////// 14440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //get debuggerActive: 3 memory accesses, and $7 14450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offGlue_pSelfSuspendCount, PhysicalReg_Glue, true, P_GPR_1, true); 14460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offGlue_pIntoDebugger, PhysicalReg_Glue, true, P_GPR_2, true); 14470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_mem(OpndSize_32, 0, 0, P_GPR_1, true); //suspendCount 14490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, "common_handleSuspend4_1", true); //called once 14500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_mem(OpndSize_32, 0, 0, P_GPR_2, true); //debugger active 14520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, "common_debuggerActive4", true); 14540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //recover registers and return 14560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen x86_return(); 14570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_handleSuspend4_1", true); 14590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen push_mem_to_stack(OpndSize_32, offGlue_self, PhysicalReg_Glue, true); 14600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmCheckSuspendPending(); 14610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(4, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 14620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen x86_return(); 14630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_debuggerActive4", true); 14650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //%edx: offsetBC (at run time, get method->insns_bytecode, then calculate BCPointer) 14660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offGlue_method, PhysicalReg_Glue, true, P_GPR_1, true); 14670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offMethod_insns_bytecode, P_GPR_1, true, P_GPR_2, true); 14680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen alu_binary_reg_reg(OpndSize_32, add_opc, P_GPR_2, true, PhysicalReg_EDX, true); 14690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_mem(OpndSize_32, 0, offGlue_entryPoint, PhysicalReg_Glue, true); 14700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_gotoBail", false); //update glue->rPC with edx 14710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 14720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 14730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 14740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//input: %edx PC adjustment 14750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen//CHECK: should %edx be saved before calling dvmCheckSuspendPending? 14760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 14770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function common_periodicChecks_entry to check GC request 14780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 14800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_periodicChecks_entry() { 14810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_periodicChecks_entry", false); 14820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EAX; 14830c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 14840c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_suspendCount(P_GPR_1, true); 14850c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14860c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //get debuggerActive: 3 memory accesses, and $7 14870c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#if 0 //defined(WITH_DEBUGGER) 14880c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_debuggerActive(P_GPR_2, true); 14890c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 14900c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14910c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, P_GPR_1, true); //suspendCount 14920c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, "common_handleSuspend", true); //called once 14930c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 14940c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#if 0 //defined(WITH_DEBUGGER) 14950c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef NCG_DEBUG 14960c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen compare_imm_reg(OpndSize_32, 0, P_GPR_2, true); //debugger active 14970c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen conditional_jump(Condition_NE, "common_debuggerActive", true); 14980c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 14990c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 15000c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 15010c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //recover registers and return 15020c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen x86_return(); 15030c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_handleSuspend", true); 15040c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_self_pointer(P_GPR_1, true); 15050c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(-4, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 15060c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, P_GPR_1, true, 0, PhysicalReg_ESP, true); 15070c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen call_dvmCheckSuspendPending(); 15080c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(4, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 15090c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen x86_return(); 15100c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#ifdef NCG_DEBUG 15110c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_debuggerActive", true); 15120c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //adjust PC!!! use 0(%esp) TODO 15130c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set_glue_entryPoint_imm(0); //kInterpEntryInstr); 15140c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen unconditional_jump("common_gotoBail", false); 15150c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#endif 15160c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 15170c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 15180c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_1 15190c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen#undef P_GPR_2 15200c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 15210c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function common_gotoBail 15220c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen input: %edx: BCPointer %esi: Glue 15230c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set %eax to 1 (switch interpreter = true), recover the callee-saved registers and return 15240c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 15250c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_gotoBail() { 15260c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_gotoBail", false); 15270c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //scratchRegs[0] = PhysicalReg_EDX; scratchRegs[1] = PhysicalReg_ESI; 15280c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 15290c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen //save_pc_fp_to_glue(); 15300c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_self_pointer(PhysicalReg_EAX, true); 15310c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, PhysicalReg_FP, true, offsetof(Thread, interpSave.curFrame), PhysicalReg_EAX, true); 15320c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, PhysicalReg_EDX, true, offsetof(Thread, interpSave.pc), PhysicalReg_EAX, true); 15330c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 15340c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.bailPtr), PhysicalReg_EAX, true, PhysicalReg_ESP, true); 15350c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_ESP, true, PhysicalReg_EBP, true); 15360c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(FRAME_SIZE-4, PhysicalReg_EBP, true, PhysicalReg_EBP, true); 15370c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 1, PhysicalReg_EAX, true); //return value 15380c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -4, PhysicalReg_EBP, true, PhysicalReg_EDI, true); 15390c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -8, PhysicalReg_EBP, true, PhysicalReg_ESI, true); 15400c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -12, PhysicalReg_EBP, true, PhysicalReg_EBX, true); 15410c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_EBP, true, PhysicalReg_ESP, true); 15420c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, 0, PhysicalReg_ESP, true, PhysicalReg_EBP, true); 15430c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(4, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 15440c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen x86_return(); 15450c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 15460c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 15470c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen/*! 15480c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen\brief helper function common_gotoBail_0 15490c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 15500c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen set %eax to 0, recover the callee-saved registers and return 15510c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen*/ 15520c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chenint common_gotoBail_0() { 15530c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen insertLabel("common_gotoBail_0", false); 15540c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 15550c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen get_self_pointer(PhysicalReg_EAX, true); 15560c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, PhysicalReg_FP, true, offsetof(Thread, interpSave.curFrame), PhysicalReg_EAX, true); 15570c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_mem(OpndSize_32, PhysicalReg_EDX, true, offsetof(Thread, interpSave.pc), PhysicalReg_EAX, true); 15580c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen 15590c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen /* 15600c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen movl offThread_bailPtr(%ecx),%esp # Restore "setjmp" esp 15610c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen movl %esp,%ebp 15620c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen addl $(FRAME_SIZE-4), %ebp # Restore %ebp at point of setjmp 15630c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen movl EDI_SPILL(%ebp),%edi 15640c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen movl ESI_SPILL(%ebp),%esi 15650c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen movl EBX_SPILL(%ebp),%ebx 15660c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen movl %ebp, %esp # strip frame 15670c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen pop %ebp # restore caller's ebp 15680c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen ret # return to dvmMterpStdRun's caller 15690c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen */ 15700c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.bailPtr), PhysicalReg_EAX, true, PhysicalReg_ESP, true); 15710c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_ESP, true, PhysicalReg_EBP, true); 15720c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(FRAME_SIZE-4, PhysicalReg_EBP, true, PhysicalReg_EBP, true); 15730c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_imm_to_reg(OpndSize_32, 0, PhysicalReg_EAX, true); //return value 15740c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -4, PhysicalReg_EBP, true, PhysicalReg_EDI, true); 15750c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -8, PhysicalReg_EBP, true, PhysicalReg_ESI, true); 15760c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, -12, PhysicalReg_EBP, true, PhysicalReg_EBX, true); 15770c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_reg_to_reg(OpndSize_32, PhysicalReg_EBP, true, PhysicalReg_ESP, true); 15780c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen move_mem_to_reg(OpndSize_32, 0, PhysicalReg_ESP, true, PhysicalReg_EBP, true); 15790c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen load_effective_addr(4, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 15800c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen x86_return(); 15810c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen return 0; 15820c2dc522d0e120f346cf0a40c8cf0c93346131c2Dong-Yuan Chen} 1583