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