LowerHelper.cpp revision 0c2dc522d0e120f346cf0a40c8cf0c93346131c2
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18/*! \file LowerHelper.cpp
19    \brief This file implements helper functions for lowering
20
21With NCG O0: all registers are hard-coded ;
22With NCG O1: the lowering module will use variables that will be allocated to a physical register by the register allocator.
23
24register types: FS 32-bit or 64-bit;
25                XMM: SS(32-bit) SD (64-bit);
26                GPR: 8-bit, 16-bit, 32-bit;
27LowOpndRegType tells whether it is gpr, xmm or fs;
28OpndSize can be OpndSize_8, OpndSize_16, OpndSize_32, OpndSize_64
29
30A single native instruction can use multiple physical registers.
31  we can't call freeReg in the middle of emitting a native instruction,
32  since it may free the physical register used by an operand and cause two operands being allocated to the same physical register.
33
34When allocating a physical register for an operand, we can't spill the operands that are already allocated. To avoid that, we call startNativeCode before each native instruction, here flag "canSpill" is set to true for each physical register;
35  when a physical register is allocated, we set its flag "canSpill" to false;
36  at end of each native instruction, call endNativeCode to set flag "canSpill" to true.
37*/
38
39#include "libdex/DexOpcodes.h"
40#include "libdex/DexFile.h"
41#include "Lower.h"
42#include "NcgAot.h"
43#include "enc_wrapper.h"
44#include "vm/mterp/Mterp.h"
45#include "NcgHelper.h"
46#include <math.h>
47#include "interp/InterpState.h"
48
49extern "C" int64_t __divdi3(int64_t, int64_t);
50extern "C" int64_t __moddi3(int64_t, int64_t);
51bool isScratchPhysical;
52LowOp* lirTable[200];
53int num_lirs_in_table = 0;
54
55//4 tables are defined: GPR integer ALU ops, ALU ops in FPU, SSE 32-bit, SSE 64-bit
56//the index to the table is the opcode
57//add_opc,    or_opc,     adc_opc,    sbb_opc,
58//and_opc,    sub_opc,    xor_opc,    cmp_opc,
59//mul_opc,    imul_opc,   div_opc,    idiv_opc,
60//sll_opc,    srl_opc,    sra, (SSE)
61//shl_opc,    shr_opc,    sal_opc,    sar_opc, //integer shift
62//neg_opc,    not_opc,    andn_opc, (SSE)
63//n_alu
64//!mnemonic for integer ALU operations
65const  Mnemonic map_of_alu_opcode_2_mnemonic[] = {
66    Mnemonic_ADD,  Mnemonic_OR,   Mnemonic_ADC,  Mnemonic_SBB,
67    Mnemonic_AND,  Mnemonic_SUB,  Mnemonic_XOR,  Mnemonic_CMP,
68    Mnemonic_MUL,  Mnemonic_IMUL, Mnemonic_DIV,  Mnemonic_IDIV,
69    Mnemonic_Null, Mnemonic_Null, Mnemonic_Null,
70    Mnemonic_SHL,  Mnemonic_SHR,  Mnemonic_SAL,  Mnemonic_SAR,
71    Mnemonic_NEG,  Mnemonic_NOT,  Mnemonic_Null,
72    Mnemonic_Null
73};
74//!mnemonic for ALU operations in FPU
75const  Mnemonic map_of_fpu_opcode_2_mnemonic[] = {
76    Mnemonic_FADD,  Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,
77    Mnemonic_Null,  Mnemonic_FSUB,  Mnemonic_Null,  Mnemonic_Null,
78    Mnemonic_FMUL,  Mnemonic_Null,  Mnemonic_FDIV,  Mnemonic_Null,
79    Mnemonic_Null,  Mnemonic_Null,
80    Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,
81    Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,
82    Mnemonic_Null
83};
84//!mnemonic for SSE 32-bit
85const  Mnemonic map_of_sse_opcode_2_mnemonic[] = {
86    Mnemonic_ADDSD,  Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,
87    Mnemonic_Null,   Mnemonic_SUBSD, Mnemonic_XORPD, Mnemonic_Null,
88    Mnemonic_MULSD,  Mnemonic_Null,  Mnemonic_DIVSD,  Mnemonic_Null,
89    Mnemonic_Null,   Mnemonic_Null,
90    Mnemonic_Null,   Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,
91    Mnemonic_Null,   Mnemonic_Null,  Mnemonic_Null,
92    Mnemonic_Null
93};
94//!mnemonic for SSE 64-bit integer
95const  Mnemonic map_of_64_opcode_2_mnemonic[] = {
96    Mnemonic_PADDQ, Mnemonic_POR,   Mnemonic_Null,  Mnemonic_Null,
97    Mnemonic_PAND,  Mnemonic_PSUBQ, Mnemonic_PXOR,  Mnemonic_Null,
98    Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,
99    Mnemonic_PSLLQ, Mnemonic_PSRLQ, Mnemonic_Null,
100    Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,  Mnemonic_Null,
101    Mnemonic_Null,  Mnemonic_Null,  Mnemonic_PANDN,
102    Mnemonic_Null
103};
104
105////////////////////////////////////////////////
106//!update fields of LowOpndReg
107
108//!
109void set_reg_opnd(LowOpndReg* op_reg, int reg, bool isPhysical, LowOpndRegType type) {
110    op_reg->regType = type;
111    if(isPhysical) {
112        op_reg->logicalReg = -1;
113        op_reg->physicalReg = reg;
114    }
115    else
116        op_reg->logicalReg = reg;
117    return;
118}
119//!update fields of LowOpndMem
120
121//!
122void set_mem_opnd(LowOpndMem* mem, int disp, int base, bool isPhysical) {
123    mem->m_disp.value = disp;
124    mem->hasScale = false;
125    mem->m_base.regType = LowOpndRegType_gp;
126    if(isPhysical) {
127        mem->m_base.logicalReg = -1;
128        mem->m_base.physicalReg = base;
129    } else {
130        mem->m_base.logicalReg = base;
131    }
132    return;
133}
134//!update fields of LowOpndMem
135
136//!
137void set_mem_opnd_scale(LowOpndMem* mem, int base, bool isPhysical, int disp, int index, bool indexPhysical, int scale) {
138    mem->hasScale = true;
139    mem->m_base.regType = LowOpndRegType_gp;
140    if(isPhysical) {
141        mem->m_base.logicalReg = -1;
142        mem->m_base.physicalReg = base;
143    } else {
144        mem->m_base.logicalReg = base;
145    }
146    if(indexPhysical) {
147        mem->m_index.logicalReg = -1;
148        mem->m_index.physicalReg = index;
149    } else {
150        mem->m_index.logicalReg = index;
151    }
152    mem->m_disp.value = disp;
153    mem->m_scale.value = scale;
154    return;
155}
156//!return either LowOpndRegType_xmm or LowOpndRegType_gp
157
158//!
159inline LowOpndRegType getTypeFromIntSize(OpndSize size) {
160    return size == OpndSize_64 ? LowOpndRegType_xmm : LowOpndRegType_gp;
161}
162
163// copied from JIT compiler
164typedef struct AtomMemBlock {
165    size_t bytesAllocated;
166    struct AtomMemBlock *next;
167    char ptr[0];
168} AtomMemBlock;
169
170#define ATOMBLOCK_DEFAULT_SIZE 4096
171AtomMemBlock *atomMemHead = NULL;
172AtomMemBlock *currentAtomMem = NULL;
173void * atomNew(size_t size) {
174    lowOpTimeStamp++; //one LowOp constructed
175    if(atomMemHead == NULL) {
176        atomMemHead = (AtomMemBlock*)malloc(sizeof(AtomMemBlock) + ATOMBLOCK_DEFAULT_SIZE);
177        if(atomMemHead == NULL) {
178            ALOGE("Memory allocation failed");
179            return NULL;
180        }
181        currentAtomMem = atomMemHead;
182        currentAtomMem->bytesAllocated = 0;
183        currentAtomMem->next = NULL;
184    }
185    size = (size + 3) & ~3;
186    if (size > ATOMBLOCK_DEFAULT_SIZE) {
187        ALOGE("Requesting %d bytes which exceed the maximal size allowed", size);
188        return NULL;
189    }
190retry:
191    if (size + currentAtomMem->bytesAllocated <= ATOMBLOCK_DEFAULT_SIZE) {
192        void *ptr;
193        ptr = &currentAtomMem->ptr[currentAtomMem->bytesAllocated];
194        return ptr;
195    }
196    if (currentAtomMem->next) {
197        currentAtomMem = currentAtomMem->next;
198        goto retry;
199    }
200    /* Time to allocate a new arena */
201    AtomMemBlock *newAtomMem = (AtomMemBlock*)malloc(sizeof(AtomMemBlock) + ATOMBLOCK_DEFAULT_SIZE);
202    if(newAtomMem == NULL) {
203        ALOGE("Memory allocation failed");
204        return NULL;
205    }
206    newAtomMem->bytesAllocated = 0;
207    newAtomMem->next = NULL;
208    currentAtomMem->next = newAtomMem;
209    currentAtomMem = newAtomMem;
210    goto retry;
211    ALOGE("atomNew requesting %d bytes", size);
212    return NULL;
213}
214
215void freeAtomMem() {
216    //LOGI("free all atom memory");
217    AtomMemBlock * tmpMem = atomMemHead;
218    while(tmpMem != NULL) {
219        tmpMem->bytesAllocated = 0;
220        tmpMem = tmpMem->next;
221    }
222    currentAtomMem = atomMemHead;
223}
224
225LowOpImm* dump_special(AtomOpCode cc, int imm) {
226    LowOpImm* op = (LowOpImm*)atomNew(sizeof(LowOpImm));
227    op->lop.opCode = Mnemonic_NULL;
228    op->lop.opCode2 = cc;
229    op->lop.opnd1.type = LowOpndType_Imm;
230    op->lop.numOperands = 1;
231    op->immOpnd.value = imm;
232    //stream = encoder_imm(m, size, imm, stream);
233    return op;
234}
235
236LowOpLabel* lower_label(Mnemonic m, OpndSize size, int imm, const char* label, bool isLocal) {
237    stream = encoder_imm(m, size, imm, stream);
238    return NULL;
239}
240
241LowOpLabel* dump_label(Mnemonic m, OpndSize size, int imm,
242               const char* label, bool isLocal) {
243    return lower_label(m, size, imm, label, isLocal);
244}
245
246LowOpNCG* dump_ncg(Mnemonic m, OpndSize size, int imm) {
247    stream = encoder_imm(m, size, imm, stream);
248    return NULL;
249}
250
251//!update fields of LowOp and generate a x86 instruction with a single immediate operand
252
253//!
254LowOpImm* lower_imm(Mnemonic m, OpndSize size, int imm, bool updateTable) {
255    stream = encoder_imm(m, size, imm, stream);
256    return NULL;
257}
258
259LowOpImm* dump_imm(Mnemonic m, OpndSize size, int imm) {
260    return lower_imm(m, size, imm, true);
261}
262
263LowOpImm* dump_imm_with_codeaddr(Mnemonic m, OpndSize size,
264               int imm, char* codePtr) {
265    encoder_imm(m, size, imm, codePtr);
266    return NULL;
267}
268
269//!update fields of LowOp and generate a x86 instruction that takes a single memory operand
270
271//!With NCG O1, we call freeReg to free up physical registers, then call registerAlloc to allocate a physical register for memory base
272LowOpMem* lower_mem(Mnemonic m, AtomOpCode m2, OpndSize size,
273               int disp, int base_reg) {
274    stream = encoder_mem(m, size, disp, base_reg, true, stream);
275    return NULL;
276}
277
278LowOpMem* dump_mem(Mnemonic m, AtomOpCode m2, OpndSize size,
279               int disp, int base_reg, bool isBasePhysical) {
280    if(gDvm.executionMode == kExecutionModeNcgO1) {
281        freeReg(true);
282        //type of the base is gpr
283        int regAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
284        return lower_mem(m, m2, size, disp, regAll);
285    } else {
286        stream = encoder_mem(m, size, disp, base_reg, isBasePhysical, stream);
287        return NULL;
288    }
289}
290//!update fields of LowOp and generate a x86 instruction that takes a single reg operand
291
292//!With NCG O1, wecall freeReg to free up physical registers, then call registerAlloc to allocate a physical register for the single operand
293LowOpReg* lower_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
294               int reg, LowOpndRegType type) {
295    stream = encoder_reg(m, size, reg, true, type, stream);
296    return NULL;
297}
298
299LowOpReg* dump_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
300               int reg, bool isPhysical, LowOpndRegType type) {
301    if(gDvm.executionMode == kExecutionModeNcgO1) {
302        freeReg(true);
303        if(m == Mnemonic_MUL || m == Mnemonic_IDIV) {
304            //these two instructions use eax & edx implicitly
305            touchEax();
306            touchEdx();
307        }
308        int regAll = registerAlloc(type, reg, isPhysical, true);
309        return lower_reg(m, m2, size, regAll, type);
310    } else {
311        stream = encoder_reg(m, size, reg, isPhysical, type, stream);
312        return NULL;
313    }
314}
315LowOpReg* dump_reg_noalloc(Mnemonic m, OpndSize size,
316               int reg, bool isPhysical, LowOpndRegType type) {
317    return lower_reg(m, ATOM_NORMAL, size, reg, type);
318}
319
320LowOpRegReg* lower_reg_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
321                 int reg, int reg2, LowOpndRegType type) {
322    if(m == Mnemonic_FUCOMP || m == Mnemonic_FUCOM) {
323        stream = encoder_compare_fp_stack(m == Mnemonic_FUCOMP,
324                                          reg-reg2, size==OpndSize_64, stream);
325    }
326    else {
327        stream = encoder_reg_reg(m, size, reg, true, reg2, true, type, stream);
328    }
329    return NULL;
330}
331
332//!update fields of LowOp and generate a x86 instruction that takes two reg operands
333
334//Here, both registers are physical
335LowOpRegReg* dump_reg_reg_noalloc(Mnemonic m, OpndSize size,
336                           int reg, bool isPhysical,
337                           int reg2, bool isPhysical2, LowOpndRegType type) {
338    return lower_reg_reg(m, ATOM_NORMAL, size, reg, reg2, type);
339}
340
341inline bool isMnemonicMove(Mnemonic m) {
342    return (m == Mnemonic_MOV || m == Mnemonic_MOVQ ||
343            m == Mnemonic_MOVSS || m == Mnemonic_MOVSD);
344}
345//!update fields of LowOp and generate a x86 instruction that takes two reg operands
346
347//!here dst reg is already allocated to a physical reg
348//! we should not spill the physical register for dst when allocating for src
349LowOpRegReg* dump_reg_reg_noalloc_dst(Mnemonic m, OpndSize size,
350                               int reg, bool isPhysical,
351                               int reg2, bool isPhysical2, LowOpndRegType type) {
352    if(gDvm.executionMode == kExecutionModeNcgO1) {
353        int regAll = registerAlloc(type, reg, isPhysical, true);
354        /* remove move from one register to the same register */
355        if(isMnemonicMove(m) && regAll == reg2) return NULL;
356        return lower_reg_reg(m, ATOM_NORMAL, size, regAll, reg2, type);
357    } else {
358        stream = encoder_reg_reg(m, size, reg, isPhysical, reg2, isPhysical2, type, stream);
359        return NULL;
360    }
361}
362//!update fields of LowOp and generate a x86 instruction that takes two reg operands
363
364//!here src reg is already allocated to a physical reg
365LowOpRegReg* dump_reg_reg_noalloc_src(Mnemonic m, AtomOpCode m2, OpndSize size,
366                               int reg, bool isPhysical,
367                               int reg2, bool isPhysical2, LowOpndRegType type) {
368    if(gDvm.executionMode == kExecutionModeNcgO1) {
369        int regAll2;
370        if(isMnemonicMove(m) && checkTempReg2(reg2, type, isPhysical2, reg)) { //dst reg is logical
371            //only from get_virtual_reg_all
372            regAll2 = registerAllocMove(reg2, type, isPhysical2, reg);
373        } else {
374            regAll2 = registerAlloc(type, reg2, isPhysical2, true);
375            return lower_reg_reg(m, m2, size, reg, regAll2, type);
376        }
377    } else {
378        stream = encoder_reg_reg(m, size, reg, isPhysical, reg2, isPhysical2, type, stream);
379        return NULL;
380    }
381    return NULL;
382}
383//!update fields of LowOp and generate a x86 instruction that takes two reg operands
384
385//!
386LowOpRegReg* dump_reg_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
387                   int reg, bool isPhysical,
388                   int reg2, bool isPhysical2, LowOpndRegType type) {
389    if(gDvm.executionMode == kExecutionModeNcgO1) {
390        startNativeCode(-1, -1);
391        //reg is source if m is MOV
392        freeReg(true);
393        int regAll = registerAlloc(type, reg, isPhysical, true);
394        int regAll2;
395        LowOpRegReg* op = NULL;
396#ifdef MOVE_OPT2
397        if(isMnemonicMove(m) &&
398           ((reg != PhysicalReg_EDI && reg != PhysicalReg_ESP && reg != PhysicalReg_EBP) || (!isPhysical)) &&
399           isPhysical2 == false) { //dst reg is logical
400            //called from move_reg_to_reg
401            regAll2 = registerAllocMove(reg2, type, isPhysical2, regAll);
402        } else {
403#endif
404            donotSpillReg(regAll);
405            regAll2 = registerAlloc(type, reg2, isPhysical2, true);
406            op = lower_reg_reg(m, m2, size, regAll, regAll2, type);
407#ifdef MOVE_OPT2
408        }
409#endif
410        endNativeCode();
411        return op;
412    }
413    else {
414        stream = encoder_reg_reg(m, size, reg, isPhysical, reg2, isPhysical2, type, stream);
415    }
416    return NULL;
417}
418
419LowOpRegMem* lower_mem_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
420                 int disp, int base_reg,
421                 MemoryAccessType mType, int mIndex,
422                 int reg, LowOpndRegType type, bool isMoves) {
423    if(m == Mnemonic_MOVSX) {
424        stream = encoder_moves_mem_to_reg(size, disp, base_reg, true,
425                                          reg, true, stream);
426    }
427    else if(m == Mnemonic_MOVZX) {
428        stream = encoder_movez_mem_to_reg(size, disp, base_reg, true,
429                                          reg, true, stream);
430    }
431    else {
432        stream = encoder_mem_reg(m, size, disp, base_reg, true,
433                                 reg, true, type, stream);
434    }
435    return NULL;
436}
437
438//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand
439
440//!Here, operands are already allocated to physical registers
441LowOpRegMem* dump_mem_reg_noalloc(Mnemonic m, OpndSize size,
442                           int disp, int base_reg, bool isBasePhysical,
443                           MemoryAccessType mType, int mIndex,
444                           int reg, bool isPhysical, LowOpndRegType type) {
445    return lower_mem_reg(m, ATOM_NORMAL, size, disp, base_reg, mType, mIndex, reg, type, false);
446}
447//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand
448
449//!Here, memory operand is already allocated to physical register
450LowOpRegMem* dump_mem_reg_noalloc_mem(Mnemonic m, AtomOpCode m2, OpndSize size,
451                               int disp, int base_reg, bool isBasePhysical,
452                               MemoryAccessType mType, int mIndex,
453                               int reg, bool isPhysical, LowOpndRegType type) {
454    if(gDvm.executionMode == kExecutionModeNcgO1) {
455        int regAll = registerAlloc(type, reg, isPhysical, true);
456        return lower_mem_reg(m, m2, size, disp, base_reg, mType, mIndex, regAll, type, false);
457    } else {
458        stream = encoder_mem_reg(m, size, disp, base_reg, isBasePhysical,
459                                 reg, isPhysical, type, stream);
460    }
461    return NULL;
462}
463//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand
464
465//!
466LowOpRegMem* dump_mem_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
467                   int disp, int base_reg, bool isBasePhysical,
468                   MemoryAccessType mType, int mIndex,
469                   int reg, bool isPhysical, LowOpndRegType type) {
470    if(gDvm.executionMode == kExecutionModeNcgO1) {
471        startNativeCode(-1, -1);
472        freeReg(true);
473        int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
474        //it is okay to use the same physical register
475        if(isMnemonicMove(m)) {
476            freeReg(true);
477        } else {
478            donotSpillReg(baseAll);
479        }
480        int regAll = registerAlloc(type, reg, isPhysical, true);
481        endNativeCode();
482        return lower_mem_reg(m, m2, size, disp, baseAll, mType, mIndex, regAll, type, false);
483    } else {
484        stream = encoder_mem_reg(m, size, disp, base_reg, isBasePhysical,
485                                 reg, isPhysical, type, stream);
486    }
487    return NULL;
488}
489//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand
490
491//!
492LowOpRegMem* dump_moves_mem_reg(Mnemonic m, OpndSize size,
493                         int disp, int base_reg, bool isBasePhysical,
494             int reg, bool isPhysical) {
495    if(gDvm.executionMode == kExecutionModeNcgO1) {
496        startNativeCode(-1, -1);
497        freeReg(true);
498        int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
499        donotSpillReg(baseAll);
500        int regAll = registerAlloc(LowOpndRegType_gp, reg, isPhysical, true);
501        endNativeCode();
502        return lower_mem_reg(m, ATOM_NORMAL, size, disp, baseAll, MemoryAccess_Unknown, -1,
503            regAll, LowOpndRegType_gp, true/*moves*/);
504    } else {
505        stream = encoder_moves_mem_to_reg(size, disp, base_reg, isBasePhysical, reg, isPhysical, stream);
506    }
507    return NULL;
508}
509//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand
510
511//!
512LowOpRegMem* dump_movez_mem_reg(Mnemonic m, OpndSize size,
513             int disp, int base_reg, bool isBasePhysical,
514             int reg, bool isPhysical) {
515    if(gDvm.executionMode == kExecutionModeNcgO1) {
516        startNativeCode(-1, -1);
517        freeReg(true);
518        int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
519        donotSpillReg(baseAll);
520        int regAll = registerAlloc(LowOpndRegType_gp, reg, isPhysical, true);
521        endNativeCode();
522        return lower_mem_reg(m, ATOM_NORMAL, size, disp, baseAll, MemoryAccess_Unknown, -1,
523            regAll, LowOpndRegType_gp, true/*moves*/);
524    } else {
525        stream = encoder_movez_mem_to_reg(size, disp, base_reg, isBasePhysical, reg, isPhysical, stream);
526    }
527    return NULL;
528}
529
530//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one reg operand
531
532//!
533LowOpRegReg* dump_movez_reg_reg(Mnemonic m, OpndSize size,
534             int reg, bool isPhysical,
535             int reg2, bool isPhysical2) {
536    LowOpRegReg* op = (LowOpRegReg*)atomNew(sizeof(LowOpRegReg));
537    op->lop.opCode = m;
538    op->lop.opnd1.size = OpndSize_32;
539    op->lop.opnd1.type = LowOpndType_Reg;
540    op->lop.opnd2.size = size;
541    op->lop.opnd2.type = LowOpndType_Reg;
542    set_reg_opnd(&(op->regOpnd1), reg2, isPhysical2, LowOpndRegType_gp);
543    set_reg_opnd(&(op->regOpnd2), reg, isPhysical, LowOpndRegType_gp);
544    if(gDvm.executionMode == kExecutionModeNcgO1) {
545        startNativeCode(-1, -1);
546        //reg is source if m is MOV
547        freeReg(true);
548        int regAll = registerAlloc(LowOpndRegType_gp, reg, isPhysical, true);
549        donotSpillReg(regAll);
550        int regAll2 = registerAlloc(LowOpndRegType_gp, reg2, isPhysical2, true);
551        stream = encoder_movez_reg_to_reg(size, regAll, true, regAll2, true,
552                                          LowOpndRegType_gp, stream);
553        endNativeCode();
554    }
555    else {
556        stream = encoder_movez_reg_to_reg(size, reg, isPhysical, reg2,
557                                        isPhysical2, LowOpndRegType_gp, stream);
558    }
559    return NULL;
560}
561
562//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand
563
564//!
565LowOpRegMem* lower_mem_scale_reg(Mnemonic m, OpndSize size, int base_reg, int disp, int index_reg,
566                 int scale, int reg, LowOpndRegType type) {
567    bool isMovzs = (m == Mnemonic_MOVZX || m == Mnemonic_MOVSX);
568    if(isMovzs)
569        stream = encoder_movzs_mem_disp_scale_reg(m, size, base_reg, true, disp, index_reg, true,
570                                                  scale, reg, true, type, stream);
571    else {
572        if(disp == 0)
573            stream = encoder_mem_scale_reg(m, size, base_reg, true, index_reg, true,
574                                           scale, reg, true, type, stream);
575        else
576            stream = encoder_mem_disp_scale_reg(m, size, base_reg, true, disp, index_reg, true,
577                                                scale, reg, true, type, stream);
578    }
579    return NULL;
580}
581
582LowOpRegMem* dump_mem_scale_reg(Mnemonic m, OpndSize size,
583                         int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale,
584                         int reg, bool isPhysical, LowOpndRegType type) {
585    if(gDvm.executionMode == kExecutionModeNcgO1) {
586        startNativeCode(-1, -1);
587        freeReg(true);
588        int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
589        donotSpillReg(baseAll); //make sure index will not use the same physical reg
590        int indexAll = registerAlloc(LowOpndRegType_gp, index_reg, isIndexPhysical, true);
591        if(isMnemonicMove(m)) {
592            freeReg(true);
593            doSpillReg(baseAll); //base can be used now
594        } else {
595            donotSpillReg(indexAll);
596        }
597        bool isMovzs = (m == Mnemonic_MOVZX || m == Mnemonic_MOVSX);
598        int regAll = registerAlloc(isMovzs ? LowOpndRegType_gp : type, reg, isPhysical, true);
599        endNativeCode();
600        return lower_mem_scale_reg(m, size, baseAll, disp, indexAll, scale, regAll, type);
601    } else {
602        stream = encoder_mem_scale_reg(m, size, base_reg, isBasePhysical, index_reg,
603                                       isIndexPhysical, scale, reg, isPhysical, type, stream);
604    }
605    return NULL;
606}
607//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand
608
609//!
610LowOpMemReg* lower_reg_mem_scale(Mnemonic m, OpndSize size, int reg,
611                 int base_reg, int disp, int index_reg, int scale, LowOpndRegType type) {
612    if(disp == 0)
613        stream = encoder_reg_mem_scale(m, size, reg, true, base_reg, true,
614                                       index_reg, true, scale, type, stream);
615    else
616        stream = encoder_reg_mem_disp_scale(m, size, reg, true, base_reg, true,
617                                            disp, index_reg, true, scale, type, stream);
618    return NULL;
619}
620
621LowOpMemReg* dump_reg_mem_scale(Mnemonic m, OpndSize size,
622                         int reg, bool isPhysical,
623                         int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale,
624                         LowOpndRegType type) {
625    if(gDvm.executionMode == kExecutionModeNcgO1) {
626        startNativeCode(-1, -1);
627        freeReg(true);
628        int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
629        donotSpillReg(baseAll);
630        int indexAll = registerAlloc(LowOpndRegType_gp, index_reg, isIndexPhysical, true);
631        donotSpillReg(indexAll);
632        int regAll = registerAlloc(type, reg, isPhysical, true);
633        endNativeCode();
634        return lower_reg_mem_scale(m, size, regAll, baseAll, disp, indexAll, scale, type);
635    } else {
636        stream = encoder_reg_mem_scale(m, size, reg, isPhysical, base_reg, isBasePhysical,
637                                       index_reg, isIndexPhysical, scale, type, stream);
638    }
639    return NULL;
640}
641//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand
642
643//!Here operands are already allocated
644LowOpMemReg* lower_reg_mem(Mnemonic m, AtomOpCode m2, OpndSize size, int reg,
645                 int disp, int base_reg, MemoryAccessType mType, int mIndex,
646                 LowOpndRegType type) {
647    stream = encoder_reg_mem(m, size, reg, true, disp, base_reg, true, type, stream);
648    return NULL;
649}
650
651LowOpMemReg* dump_reg_mem_noalloc(Mnemonic m, OpndSize size,
652                           int reg, bool isPhysical,
653                           int disp, int base_reg, bool isBasePhysical,
654                           MemoryAccessType mType, int mIndex, LowOpndRegType type) {
655    return lower_reg_mem(m, ATOM_NORMAL, size, reg, disp, base_reg, mType, mIndex, type);
656}
657//!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand
658
659//!
660LowOpMemReg* dump_reg_mem(Mnemonic m, AtomOpCode m2, OpndSize size,
661                   int reg, bool isPhysical,
662                   int disp, int base_reg, bool isBasePhysical,
663                   MemoryAccessType mType, int mIndex, LowOpndRegType type) {
664    if(gDvm.executionMode == kExecutionModeNcgO1) {
665        startNativeCode(-1, -1);
666        freeReg(true);
667        int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
668        donotSpillReg(baseAll);
669        int regAll = registerAlloc(type, reg, isPhysical, true);
670        endNativeCode();
671        return lower_reg_mem(m, m2, size, regAll, disp, baseAll, mType, mIndex, type);
672    } else {
673        stream = encoder_reg_mem(m, size, reg, isPhysical, disp, base_reg, isBasePhysical, type, stream);
674    }
675    return NULL;
676}
677//!update fields of LowOp and generate a x86 instruction that takes one immediate and one reg operand
678
679//!The reg operand is allocated already
680LowOpRegImm* lower_imm_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
681                 int imm, int reg, LowOpndRegType type, bool chaining) {
682    stream = encoder_imm_reg(m, size, imm, reg, true, type, stream);
683    return NULL;
684}
685
686LowOpRegImm* dump_imm_reg_noalloc(Mnemonic m, OpndSize size,
687                           int imm, int reg, bool isPhysical, LowOpndRegType type) {
688    return lower_imm_reg(m, ATOM_NORMAL, size, imm, reg, type, false);
689}
690//!update fields of LowOp and generate a x86 instruction that takes one immediate and one reg operand
691
692//!
693LowOpRegImm* dump_imm_reg(Mnemonic m, AtomOpCode m2, OpndSize size,
694                   int imm, int reg, bool isPhysical, LowOpndRegType type, bool chaining) {
695    if(gDvm.executionMode == kExecutionModeNcgO1) {
696        freeReg(true);
697        int regAll = registerAlloc(type, reg, isPhysical, true);
698        return lower_imm_reg(m, m2, size, imm, regAll, type, chaining);
699    } else {
700        stream = encoder_imm_reg(m, size, imm, reg, isPhysical, type, stream);
701    }
702    return NULL;
703}
704//!update fields of LowOp and generate a x86 instruction that takes one immediate and one mem operand
705
706//!The mem operand is already allocated
707LowOpMemImm* lower_imm_mem(Mnemonic m, AtomOpCode m2, OpndSize size, int imm,
708                 int disp, int base_reg, MemoryAccessType mType, int mIndex,
709                 bool chaining) {
710    stream = encoder_imm_mem(m, size, imm, disp, base_reg, true, stream);
711    return NULL;
712}
713
714LowOpMemImm* dump_imm_mem_noalloc(Mnemonic m, OpndSize size,
715                           int imm,
716                           int disp, int base_reg, bool isBasePhysical,
717                           MemoryAccessType mType, int mIndex) {
718    return lower_imm_mem(m, ATOM_NORMAL, size, imm, disp, base_reg, mType, mIndex, false);
719}
720//!update fields of LowOp and generate a x86 instruction that takes one immediate and one mem operand
721
722//!
723LowOpMemImm* dump_imm_mem(Mnemonic m, AtomOpCode m2, OpndSize size,
724                   int imm,
725                   int disp, int base_reg, bool isBasePhysical,
726                   MemoryAccessType mType, int mIndex, bool chaining) {
727    if(gDvm.executionMode == kExecutionModeNcgO1) {
728        /* do not free register if the base is %edi, %esp, or %ebp
729           make sure dump_imm_mem will only generate a single instruction */
730        if(!isBasePhysical || (base_reg != PhysicalReg_EDI &&
731                               base_reg != PhysicalReg_ESP &&
732                               base_reg != PhysicalReg_EBP)) {
733            freeReg(true);
734        }
735        int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
736        return lower_imm_mem(m, m2, size, imm, disp, baseAll, mType, mIndex, chaining);
737    } else {
738        stream = encoder_imm_mem(m, size, imm, disp, base_reg, isBasePhysical, stream);
739    }
740    return NULL;
741}
742//!update fields of LowOp and generate a x86 instruction that uses the FP stack and takes one mem operand
743
744//!
745LowOpMemReg* lower_fp_mem(Mnemonic m, OpndSize size, int reg,
746                  int disp, int base_reg, MemoryAccessType mType, int mIndex) {
747    stream = encoder_fp_mem(m, size, reg, disp, base_reg, true, stream);
748    return NULL;
749}
750
751LowOpMemReg* dump_fp_mem(Mnemonic m, OpndSize size, int reg,
752                  int disp, int base_reg, bool isBasePhysical,
753                  MemoryAccessType mType, int mIndex) {
754    if(gDvm.executionMode == kExecutionModeNcgO1) {
755        freeReg(true);
756        int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
757        return lower_fp_mem(m, size, reg, disp, baseAll, mType, mIndex);
758    } else {
759        stream = encoder_fp_mem(m, size, reg, disp, base_reg, isBasePhysical, stream);
760    }
761    return NULL;
762}
763//!update fields of LowOp and generate a x86 instruction that uses the FP stack and takes one mem operand
764
765//!
766LowOpRegMem* lower_mem_fp(Mnemonic m, OpndSize size, int disp, int base_reg,
767                 MemoryAccessType mType, int mIndex, int reg) {
768    stream = encoder_mem_fp(m, size, disp, base_reg, true, reg, stream);
769    return NULL;
770}
771
772LowOpRegMem* dump_mem_fp(Mnemonic m, OpndSize size,
773                  int disp, int base_reg, bool isBasePhysical,
774                  MemoryAccessType mType, int mIndex,
775                  int reg) {
776    if(gDvm.executionMode == kExecutionModeNcgO1) {
777        freeReg(true);
778        int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true);
779        return lower_mem_fp(m, size, disp, baseAll, mType, mIndex, reg);
780    } else {
781        stream = encoder_mem_fp(m, size, disp, base_reg, isBasePhysical, reg, stream);
782    }
783    return NULL;
784}
785///////////////////////////////////////////////////////////////
786///////////////////////////////////////////////////////////////
787//OPERAND ORDER:
788//LowOp same as EncoderBase destination first
789//parameter order of function: src first
790
791////////////////////////////////// IA32 native instructions //////////////
792//! generate a native instruction lea
793
794//!
795void load_effective_addr(int disp, int base_reg, bool isBasePhysical,
796                          int reg, bool isPhysical) {
797    Mnemonic m = Mnemonic_LEA;
798    dump_mem_reg(m, ATOM_NORMAL, OpndSize_32, disp, base_reg, isBasePhysical,
799        MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp);
800}
801//! generate a native instruction lea
802
803//!
804void load_effective_addr_scale(int base_reg, bool isBasePhysical,
805                int index_reg, bool isIndexPhysical, int scale,
806                int reg, bool isPhysical) {
807    Mnemonic m = Mnemonic_LEA;
808    dump_mem_scale_reg(m, OpndSize_32,
809                              base_reg, isBasePhysical, 0/*disp*/, index_reg, isIndexPhysical, scale,
810                              reg, isPhysical, LowOpndRegType_gp);
811}
812//!fldcw
813
814//!
815void load_fpu_cw(int disp, int base_reg, bool isBasePhysical) {
816    Mnemonic m = Mnemonic_FLDCW;
817    dump_mem(m, ATOM_NORMAL, OpndSize_16, disp, base_reg, isBasePhysical);
818}
819//!fnstcw
820
821//!
822void store_fpu_cw(bool checkException, int disp, int base_reg, bool isBasePhysical) {
823    assert(!checkException);
824    Mnemonic m = Mnemonic_FNSTCW;
825    dump_mem(m, ATOM_NORMAL, OpndSize_16, disp, base_reg, isBasePhysical);
826}
827//!cdq
828
829//!
830void convert_integer(OpndSize srcSize, OpndSize dstSize) { //cbw, cwd, cdq
831    assert(srcSize == OpndSize_32 && dstSize == OpndSize_64);
832    Mnemonic m = Mnemonic_CDQ;
833    dump_reg_reg(m, ATOM_NORMAL, OpndSize_32, PhysicalReg_EAX, true, PhysicalReg_EDX, true, LowOpndRegType_gp);
834}
835//!fld: load from memory (float or double) to stack
836
837//!
838void load_fp_stack(LowOp* op, OpndSize size, int disp, int base_reg, bool isBasePhysical) {//fld(s|l)
839    Mnemonic m = Mnemonic_FLD;
840    dump_mem_fp(m, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, 0); //ST0
841}
842//! fild: load from memory (int or long) to stack
843
844//!
845void load_int_fp_stack(OpndSize size, int disp, int base_reg, bool isBasePhysical) {//fild(ll|l)
846    Mnemonic m = Mnemonic_FILD;
847    dump_mem_fp(m, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, 0); //ST0
848}
849//!fild: load from memory (absolute addr)
850
851//!
852void load_int_fp_stack_imm(OpndSize size, int imm) {//fild(ll|l)
853    return load_int_fp_stack(size, imm, PhysicalReg_Null, true);
854}
855//!fst: store from stack to memory (float or double)
856
857//!
858void store_fp_stack(LowOp* op, bool pop, OpndSize size, int disp, int base_reg, bool isBasePhysical) {//fst(p)(s|l)
859    Mnemonic m = pop ? Mnemonic_FSTP : Mnemonic_FST;
860    dump_fp_mem(m, size, 0, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1);
861}
862//!fist: store from stack to memory (int or long)
863
864//!
865void store_int_fp_stack(LowOp* op, bool pop, OpndSize size, int disp, int base_reg, bool isBasePhysical) {//fist(p)(l)
866    Mnemonic m = pop ? Mnemonic_FISTP : Mnemonic_FIST;
867    dump_fp_mem(m, size, 0, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1);
868}
869//!cmp reg, mem
870
871//!
872void compare_reg_mem(LowOp* op, OpndSize size, int reg, bool isPhysical,
873              int disp, int base_reg, bool isBasePhysical) {
874    Mnemonic m = Mnemonic_CMP;
875    dump_reg_mem(m, ATOM_NORMAL, size, reg, isPhysical, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, getTypeFromIntSize(size));
876}
877//!cmp mem, reg
878
879//!
880void compare_mem_reg(OpndSize size,
881              int disp, int base_reg, bool isBasePhysical,
882              int reg, bool isPhysical) {
883    Mnemonic m = Mnemonic_CMP;
884    dump_mem_reg(m, ATOM_NORMAL, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, reg, isPhysical, getTypeFromIntSize(size));
885}
886//! compare a VR with a temporary variable
887
888//!
889void compare_VR_reg_all(OpndSize size,
890             int vA,
891             int reg, bool isPhysical, Mnemonic m) {
892    LowOpndRegType type = getTypeFromIntSize(size);
893    LowOpndRegType pType = type;
894    if(m == Mnemonic_COMISS) {
895        size = OpndSize_32;
896        type = LowOpndRegType_ss;
897        pType = LowOpndRegType_xmm;
898    }
899    if(gDvm.executionMode == kExecutionModeNcgO1) {
900        int tmpValue[2];
901        int isConst = isVirtualRegConstant(vA, type, tmpValue, true/*updateRefCount*/);
902        if(isConst == 3) {
903            if(m == Mnemonic_COMISS) {
904#ifdef DEBUG_NCG_O1
905                LOGI("VR is const and SS in compare_VR_reg");
906#endif
907                dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
908                //dumpImmToMem(vA+1, OpndSize_32, 0); //CHECK necessary? will overwrite vA+1!!!
909                dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, reg, isPhysical, pType);
910                return;
911            }
912            else if(size != OpndSize_64) {
913#ifdef DEBUG_NCG_O1
914                LOGI("VR is const and 32 bits in compare_VR_reg");
915#endif
916                dump_imm_reg(m, ATOM_NORMAL, size, tmpValue[0], reg, isPhysical, pType, false);
917                return;
918            }
919            else if(size == OpndSize_64) {
920#ifdef DEBUG_NCG_O1
921                LOGI("VR is const and 64 bits in compare_VR_reg");
922#endif
923                dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
924                dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]);
925                dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true,
926                    MemoryAccess_VR, vA, reg, isPhysical, pType);
927                return;
928            }
929        }
930        if(isConst == 1) dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
931        if(isConst == 2) dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]);
932        freeReg(true);
933        int regAll = checkVirtualReg(vA, type, 0/*do not update*/);
934        if(regAll != PhysicalReg_Null) { //do not spill regAll when allocating register for dst
935            startNativeCode(-1, -1);
936            donotSpillReg(regAll);
937            dump_reg_reg_noalloc_src(m, ATOM_NORMAL, size, regAll, true, reg, isPhysical, pType);
938            endNativeCode();
939        }
940        else {
941            //virtual register is not allocated to a physical register
942            dump_mem_reg_noalloc_mem(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true,
943                MemoryAccess_VR, vA, reg, isPhysical, pType);
944        }
945        updateRefCount(vA, type);
946        return;
947    } else {
948        dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true,
949            MemoryAccess_VR, vA, reg, isPhysical, pType);
950        return;
951    }
952}
953void compare_VR_reg(OpndSize size,
954             int vA,
955             int reg, bool isPhysical) {
956    Mnemonic m = Mnemonic_CMP;
957    return compare_VR_reg_all(size, vA, reg, isPhysical, m);
958}
959void compare_VR_ss_reg(int vA, int reg, bool isPhysical) {
960    Mnemonic m = Mnemonic_COMISS;
961    return compare_VR_reg_all(OpndSize_32, vA, reg, isPhysical, m);
962}
963void compare_VR_sd_reg(int vA, int reg, bool isPhysical) {
964    Mnemonic m = Mnemonic_COMISD;
965    return compare_VR_reg_all(OpndSize_64, vA, reg, isPhysical, m);
966}
967//!load VR to stack
968
969//!
970void load_fp_stack_VR_all(OpndSize size, int vB, Mnemonic m) {
971    if(gDvm.executionMode == kExecutionModeNcgO1) {
972        //can't load from immediate to fp stack
973        int tmpValue[2];
974        int isConst = isVirtualRegConstant(vB, getTypeFromIntSize(size), tmpValue, false/*updateRefCount*/);
975        if(isConst > 0) {
976            if(size != OpndSize_64) {
977#ifdef DEBUG_NCG_O1
978                LOGI("VR is const and 32 bits in load_fp_stack");
979#endif
980                dumpImmToMem(vB, OpndSize_32, tmpValue[0]);
981            }
982            else {
983#ifdef DEBUG_NCG_O1
984                LOGI("VR is const and 64 bits in load_fp_stack_VR");
985#endif
986                if(isConst == 1 || isConst == 3) dumpImmToMem(vB, OpndSize_32, tmpValue[0]);
987                if(isConst == 2 || isConst == 3) dumpImmToMem(vB+1, OpndSize_32, tmpValue[1]);
988            }
989        }
990        else { //if VR was updated by a def of gp, a xfer point was inserted
991            //if VR was updated by a def of xmm, a xfer point was inserted
992#if 0
993            int regAll = checkVirtualReg(vB, size, 1);
994            if(regAll != PhysicalReg_Null) //dump from register to memory
995                dump_reg_mem_noalloc(m, size, regAll, true, 4*vB, PhysicalReg_FP, true,
996                    MemoryAccess_VR, vB, getTypeFromIntSize(size));
997#endif
998        }
999        dump_mem_fp(m, size, 4*vB, PhysicalReg_FP, true, MemoryAccess_VR, vB, 0);
1000    } else {
1001        dump_mem_fp(m, size, 4*vB, PhysicalReg_FP, true, MemoryAccess_VR, vB, 0);
1002    }
1003}
1004//!load VR(float or double) to stack
1005
1006//!
1007void load_fp_stack_VR(OpndSize size, int vA) {//fld(s|l)
1008    Mnemonic m = Mnemonic_FLD;
1009    return load_fp_stack_VR_all(size, vA, m);
1010}
1011//!load VR(int or long) to stack
1012
1013//!
1014void load_int_fp_stack_VR(OpndSize size, int vA) {//fild(ll|l)
1015    Mnemonic m = Mnemonic_FILD;
1016    return load_fp_stack_VR_all(size, vA, m);
1017}
1018//!store from stack to VR (float or double)
1019
1020//!
1021void store_fp_stack_VR(bool pop, OpndSize size, int vA) {//fst(p)(s|l)
1022    Mnemonic m = pop ? Mnemonic_FSTP : Mnemonic_FST;
1023    dump_fp_mem(m, size, 0, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA);
1024    if(gDvm.executionMode == kExecutionModeNcgO1) {
1025        if(size == OpndSize_32)
1026            updateVirtualReg(vA, LowOpndRegType_fs_s);
1027        else
1028            updateVirtualReg(vA, LowOpndRegType_fs);
1029    }
1030}
1031//!store from stack to VR (int or long)
1032
1033//!
1034void store_int_fp_stack_VR(bool pop, OpndSize size, int vA) {//fist(p)(l)
1035    Mnemonic m = pop ? Mnemonic_FISTP : Mnemonic_FIST;
1036    dump_fp_mem(m, size, 0, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA);
1037    if(gDvm.executionMode == kExecutionModeNcgO1) {
1038        if(size == OpndSize_32)
1039            updateVirtualReg(vA, LowOpndRegType_fs_s);
1040        else
1041            updateVirtualReg(vA, LowOpndRegType_fs);
1042    }
1043}
1044//! ALU ops in FPU, one operand is a VR
1045
1046//!
1047void fpu_VR(ALU_Opcode opc, OpndSize size, int vA) {
1048    Mnemonic m = map_of_fpu_opcode_2_mnemonic[opc];
1049    if(gDvm.executionMode == kExecutionModeNcgO1) {
1050        int tmpValue[2];
1051        int isConst = isVirtualRegConstant(vA, getTypeFromIntSize(size), tmpValue, false/*updateRefCount*/);
1052        if(isConst > 0) {
1053            if(size != OpndSize_64) {
1054                //allocate a register for dst
1055                dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
1056            }
1057            else {
1058                if((isConst == 1 || isConst == 3) && size == OpndSize_64) {
1059                    dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
1060                }
1061                if((isConst == 2 || isConst == 3) && size == OpndSize_64) {
1062                    dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]);
1063                }
1064            }
1065        }
1066        if(!isInMemory(vA, size)) {
1067            ALOGE("fpu_VR");
1068        }
1069        dump_mem_fp(m, size, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, 0);
1070    } else {
1071        dump_mem_fp(m, size, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, 0);
1072    }
1073}
1074//! cmp imm reg
1075
1076//!
1077void compare_imm_reg(OpndSize size, int imm,
1078              int reg, bool isPhysical) {
1079    if(imm == 0) {
1080        LowOpndRegType type = getTypeFromIntSize(size);
1081        Mnemonic m = Mnemonic_TEST;
1082        if(gDvm.executionMode == kExecutionModeNcgO1) {
1083            freeReg(true);
1084            int regAll = registerAlloc(type, reg, isPhysical, true);
1085            lower_reg_reg(m, ATOM_NORMAL, size, regAll, regAll, type);
1086        } else {
1087            stream = encoder_reg_reg(m, size, reg, isPhysical, reg, isPhysical, type, stream);
1088        }
1089        return;
1090    }
1091    Mnemonic m = Mnemonic_CMP;
1092    dump_imm_reg(m, ATOM_NORMAL, size, imm, reg, isPhysical, getTypeFromIntSize(size), false);
1093}
1094//! cmp imm mem
1095
1096//!
1097void compare_imm_mem(OpndSize size, int imm,
1098              int disp, int base_reg, bool isBasePhysical) {
1099    Mnemonic m = Mnemonic_CMP;
1100    dump_imm_mem(m, ATOM_NORMAL, size, imm, disp,
1101                        base_reg, isBasePhysical, MemoryAccess_Unknown, -1, false);
1102}
1103//! cmp imm VR
1104
1105//!
1106void compare_imm_VR(OpndSize size, int imm,
1107             int vA) {
1108    Mnemonic m = Mnemonic_CMP;
1109    if(gDvm.executionMode == kExecutionModeNcgO1) {
1110        if(size != OpndSize_32) ALOGE("only 32 bits supported in compare_imm_VR");
1111        int tmpValue[2];
1112        int isConst = isVirtualRegConstant(vA, getTypeFromIntSize(size), tmpValue, false/*updateRefCount*/);
1113        if(isConst > 0) {
1114            dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
1115        }
1116        int regAll = checkVirtualReg(vA, getTypeFromIntSize(size), 0);
1117        if(regAll != PhysicalReg_Null)
1118            dump_imm_reg_noalloc(m, size, imm, regAll, true, LowOpndRegType_gp);
1119        else
1120            dump_imm_mem_noalloc(m, size, imm, 4*vA, PhysicalReg_FP, true,
1121                MemoryAccess_VR, vA);
1122        updateRefCount(vA, getTypeFromIntSize(size));
1123    } else {
1124        dump_imm_mem(m, ATOM_NORMAL, size, imm, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, false);
1125    }
1126}
1127//! cmp reg reg
1128
1129//!
1130void compare_reg_reg(int reg1, bool isPhysical1,
1131              int reg2, bool isPhysical2) {
1132    Mnemonic m = Mnemonic_CMP;
1133    dump_reg_reg(m, ATOM_NORMAL, OpndSize_32, reg1, isPhysical1, reg2, isPhysical2, LowOpndRegType_gp);
1134}
1135void compare_reg_reg_16(int reg1, bool isPhysical1,
1136              int reg2, bool isPhysical2) {
1137    Mnemonic m = Mnemonic_CMP;
1138    dump_reg_reg(m, ATOM_NORMAL, OpndSize_16, reg1, isPhysical1, reg2, isPhysical2, LowOpndRegType_gp);
1139}
1140
1141//! comiss mem reg
1142
1143//!SSE, XMM: comparison of floating point numbers
1144void compare_ss_mem_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical,
1145             int reg, bool isPhysical) {
1146    Mnemonic m = Mnemonic_COMISS;
1147    dump_mem_reg(m, ATOM_NORMAL, OpndSize_32, disp, base_reg, isBasePhysical,
1148        MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_xmm);
1149}
1150//! comiss reg reg
1151
1152//!
1153void compare_ss_reg_with_reg(LowOp* op, int reg1, bool isPhysical1,
1154                  int reg2, bool isPhysical2) {
1155    Mnemonic m = Mnemonic_COMISS;
1156    dump_reg_reg(m,  ATOM_NORMAL, OpndSize_32, reg1, isPhysical1, reg2, isPhysical2, LowOpndRegType_xmm);
1157}
1158//! comisd mem reg
1159
1160//!
1161void compare_sd_mem_with_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical,
1162                  int reg, bool isPhysical) {
1163    Mnemonic m = Mnemonic_COMISD;
1164    dump_mem_reg(m, ATOM_NORMAL, OpndSize_64, disp, base_reg, isBasePhysical,
1165        MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_xmm);
1166}
1167//! comisd reg reg
1168
1169//!
1170void compare_sd_reg_with_reg(LowOp* op, int reg1, bool isPhysical1,
1171                  int reg2, bool isPhysical2) {
1172    Mnemonic m = Mnemonic_COMISD;
1173    dump_reg_reg(m, ATOM_NORMAL, OpndSize_64, reg1, isPhysical1, reg2, isPhysical2, LowOpndRegType_xmm);
1174}
1175//! fucom[p]
1176
1177//!
1178void compare_fp_stack(bool pop, int reg, bool isDouble) { //compare ST(0) with ST(reg)
1179    Mnemonic m = pop ? Mnemonic_FUCOMP : Mnemonic_FUCOM;
1180    lower_reg_reg(m, ATOM_NORMAL, isDouble ? OpndSize_64 : OpndSize_32,
1181                  PhysicalReg_ST0+reg, PhysicalReg_ST0, LowOpndRegType_fs);
1182}
1183/*!
1184\brief generate a single return instruction
1185
1186*/
1187LowOp* lower_return() {
1188    stream = encoder_return(stream);
1189    return NULL;
1190}
1191
1192void x86_return() {
1193    lower_return();
1194}
1195
1196//!test imm reg
1197
1198//!
1199void test_imm_reg(OpndSize size, int imm, int reg, bool isPhysical) {
1200    dump_imm_reg(Mnemonic_TEST, ATOM_NORMAL, size, imm, reg, isPhysical, getTypeFromIntSize(size), false);
1201}
1202//!test imm mem
1203
1204//!
1205void test_imm_mem(OpndSize size, int imm, int disp, int reg, bool isPhysical) {
1206    dump_imm_mem(Mnemonic_TEST, ATOM_NORMAL, size, imm, disp, reg, isPhysical, MemoryAccess_Unknown, -1, false);
1207}
1208//!alu unary op with one reg operand
1209
1210//!
1211void alu_unary_reg(OpndSize size, ALU_Opcode opc, int reg, bool isPhysical) {
1212    Mnemonic m;
1213    if(size == OpndSize_64)
1214        m = map_of_64_opcode_2_mnemonic[opc];
1215    else
1216        m = map_of_alu_opcode_2_mnemonic[opc];
1217    dump_reg(m, ATOM_NORMAL_ALU, size, reg, isPhysical, getTypeFromIntSize(size));
1218}
1219//!alu unary op with one mem operand
1220
1221//!
1222void alu_unary_mem(LowOp* op, OpndSize size, ALU_Opcode opc, int disp, int base_reg, bool isBasePhysical) {
1223    Mnemonic m;
1224    if(size == OpndSize_64)
1225        m = map_of_64_opcode_2_mnemonic[opc];
1226    else
1227        m = map_of_alu_opcode_2_mnemonic[opc];
1228    dump_mem(m, ATOM_NORMAL_ALU, size, disp, base_reg, isBasePhysical);
1229}
1230//!alu binary op with immediate and one mem operand
1231
1232//!
1233void alu_binary_imm_mem(OpndSize size, ALU_Opcode opc, int imm, int disp, int base_reg, bool isBasePhysical) {
1234    Mnemonic m;
1235    if(size == OpndSize_64)
1236        m = map_of_64_opcode_2_mnemonic[opc];
1237    else
1238        m = map_of_alu_opcode_2_mnemonic[opc];
1239    dump_imm_mem(m, ATOM_NORMAL_ALU, size, imm, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, false);
1240}
1241//!alu binary op with immediate and one reg operand
1242
1243//!
1244void alu_binary_imm_reg(OpndSize size, ALU_Opcode opc, int imm, int reg, bool isPhysical) {
1245    Mnemonic m;
1246    if(size == OpndSize_64)
1247        m = map_of_64_opcode_2_mnemonic[opc];
1248    else
1249        m = map_of_alu_opcode_2_mnemonic[opc];
1250    dump_imm_reg(m, ATOM_NORMAL_ALU, size, imm, reg, isPhysical, getTypeFromIntSize(size), false);
1251}
1252//!alu binary op with one mem operand and one reg operand
1253
1254//!
1255void alu_binary_mem_reg(OpndSize size, ALU_Opcode opc,
1256             int disp, int base_reg, bool isBasePhysical,
1257             int reg, bool isPhysical) {
1258    Mnemonic m;
1259    if(size == OpndSize_64)
1260        m = map_of_64_opcode_2_mnemonic[opc];
1261    else
1262        m = map_of_alu_opcode_2_mnemonic[opc];
1263    dump_mem_reg(m, ATOM_NORMAL_ALU, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, reg, isPhysical, getTypeFromIntSize(size));
1264}
1265
1266void alu_sd_binary_VR_reg(ALU_Opcode opc, int vA, int reg, bool isPhysical, bool isSD) {
1267    Mnemonic m;
1268    if(isSD) m = map_of_sse_opcode_2_mnemonic[opc];
1269    else m = (Mnemonic)(map_of_sse_opcode_2_mnemonic[opc]+1); //from SD to SS
1270    OpndSize size = isSD ? OpndSize_64 : OpndSize_32;
1271    if(gDvm.executionMode == kExecutionModeNcgO1) {
1272        LowOpndRegType type = isSD ? LowOpndRegType_xmm : LowOpndRegType_ss; //type of the mem operand
1273        int tmpValue[2];
1274        int isConst = isVirtualRegConstant(vA, type, tmpValue,
1275                          true/*updateRefCount*/);
1276        if(isConst == 3 && !isSD) {
1277            //isConst can be 0 or 3, mem32, use xmm
1278            dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
1279            dump_mem_reg(m, ATOM_NORMAL_ALU, OpndSize_32, 4*vA, PhysicalReg_FP, true,
1280                       MemoryAccess_VR, vA, reg, isPhysical,
1281                       LowOpndRegType_xmm);
1282            return;
1283        }
1284        if(isConst == 3 && isSD) {
1285            dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
1286            dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]);
1287            dump_mem_reg(m, ATOM_NORMAL_ALU, OpndSize_64, 4*vA, PhysicalReg_FP, true,
1288                       MemoryAccess_VR, vA, reg, isPhysical, LowOpndRegType_xmm);
1289            return;
1290        }
1291        if(isConst == 1) dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
1292        if(isConst == 2) dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]);
1293        freeReg(true);
1294
1295        int regAll = checkVirtualReg(vA, type, 0/*do not update refCount*/);
1296        if(regAll != PhysicalReg_Null) {
1297            startNativeCode(-1, -1); //should we use vA, type
1298            //CHECK: callupdateVRAtUse
1299            donotSpillReg(regAll);
1300            dump_reg_reg_noalloc_src(m, ATOM_NORMAL_ALU, size, regAll, true, reg,
1301                         isPhysical, LowOpndRegType_xmm);
1302            endNativeCode();
1303        }
1304        else {
1305            dump_mem_reg_noalloc_mem(m, ATOM_NORMAL_ALU, size, 4*vA, PhysicalReg_FP, true,
1306                         MemoryAccess_VR, vA, reg, isPhysical, LowOpndRegType_xmm);
1307        }
1308        updateRefCount(vA, type);
1309    }
1310    else {
1311        dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true,
1312                    MemoryAccess_VR, vA, reg, isPhysical, LowOpndRegType_xmm);
1313    }
1314}
1315
1316//!alu binary op with a VR and one reg operand
1317
1318//!
1319void alu_binary_VR_reg(OpndSize size, ALU_Opcode opc, int vA, int reg, bool isPhysical) {
1320    Mnemonic m;
1321    if(size == OpndSize_64)
1322        m = map_of_64_opcode_2_mnemonic[opc];
1323    else
1324        m = map_of_alu_opcode_2_mnemonic[opc];
1325    if(gDvm.executionMode == kExecutionModeNcgO1) {
1326        int tmpValue[2];
1327        int isConst = isVirtualRegConstant(vA, getTypeFromIntSize(size), tmpValue,
1328                          true/*updateRefCount*/);
1329        if(isConst == 3 && size != OpndSize_64) {
1330            //allocate a register for dst
1331            dump_imm_reg(m, ATOM_NORMAL_ALU, size, tmpValue[0], reg, isPhysical,
1332                       getTypeFromIntSize(size), false);
1333            return;
1334        }
1335        if(isConst == 3 && size == OpndSize_64) {
1336            dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
1337            dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]);
1338            dump_mem_reg(m, ATOM_NORMAL_ALU, size, 4*vA, PhysicalReg_FP, true,
1339                MemoryAccess_VR, vA, reg, isPhysical, getTypeFromIntSize(size));
1340            return;
1341        }
1342        if(isConst == 1) dumpImmToMem(vA, OpndSize_32, tmpValue[0]);
1343        if(isConst == 2) dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]);
1344
1345        freeReg(true);
1346        int regAll = checkVirtualReg(vA, getTypeFromIntSize(size), 0);
1347        if(regAll != PhysicalReg_Null) {
1348            startNativeCode(-1, -1);
1349            donotSpillReg(regAll);
1350            dump_reg_reg_noalloc_src(m, ATOM_NORMAL_ALU, size, regAll, true, reg,
1351                         isPhysical, getTypeFromIntSize(size));
1352            endNativeCode();
1353        }
1354        else {
1355            dump_mem_reg_noalloc_mem(m, ATOM_NORMAL_ALU, size, 4*vA, PhysicalReg_FP, true,
1356                MemoryAccess_VR, vA, reg, isPhysical, getTypeFromIntSize(size));
1357        }
1358        updateRefCount(vA, getTypeFromIntSize(size));
1359    }
1360    else {
1361        dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true,
1362            MemoryAccess_VR, vA, reg, isPhysical, getTypeFromIntSize(size));
1363    }
1364}
1365//!alu binary op with two reg operands
1366
1367//!
1368void alu_binary_reg_reg(OpndSize size, ALU_Opcode opc,
1369                         int reg1, bool isPhysical1,
1370                         int reg2, bool isPhysical2) {
1371    Mnemonic m;
1372    if(size == OpndSize_64)
1373        m = map_of_64_opcode_2_mnemonic[opc];
1374    else
1375        m = map_of_alu_opcode_2_mnemonic[opc];
1376    dump_reg_reg(m, ATOM_NORMAL_ALU, size, reg1, isPhysical1, reg2, isPhysical2, getTypeFromIntSize(size));
1377}
1378//!alu binary op with one reg operand and one mem operand
1379
1380//!
1381void alu_binary_reg_mem(OpndSize size, ALU_Opcode opc,
1382             int reg, bool isPhysical,
1383             int disp, int base_reg, bool isBasePhysical) { //destination is mem!!
1384    Mnemonic m;
1385    if(size == OpndSize_64)
1386        m = map_of_64_opcode_2_mnemonic[opc];
1387    else
1388        m = map_of_alu_opcode_2_mnemonic[opc];
1389    dump_reg_mem(m, ATOM_NORMAL_ALU, size, reg, isPhysical, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, getTypeFromIntSize(size));
1390}
1391//!FPU ops with one mem operand
1392
1393//!
1394void fpu_mem(LowOp* op, ALU_Opcode opc, OpndSize size, int disp, int base_reg, bool isBasePhysical) {
1395    Mnemonic m = map_of_fpu_opcode_2_mnemonic[opc];
1396    dump_mem_fp(m, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, 0);
1397}
1398//!SSE 32-bit ALU
1399
1400//!
1401void alu_ss_binary_reg_reg(ALU_Opcode opc, int reg, bool isPhysical,
1402                int reg2, bool isPhysical2) {
1403    Mnemonic m = (Mnemonic)(map_of_sse_opcode_2_mnemonic[opc]+1); //from SD to SS
1404    dump_reg_reg(m, ATOM_NORMAL_ALU, OpndSize_32, reg, isPhysical, reg2, isPhysical2, LowOpndRegType_xmm);
1405}
1406//!SSE 64-bit ALU
1407
1408//!
1409void alu_sd_binary_reg_reg(ALU_Opcode opc, int reg, bool isPhysical,
1410                int reg2, bool isPhysical2) {
1411    Mnemonic m = map_of_sse_opcode_2_mnemonic[opc];
1412    dump_reg_reg(m, ATOM_NORMAL_ALU, OpndSize_64, reg, isPhysical, reg2, isPhysical2, LowOpndRegType_xmm);
1413}
1414//!push reg to native stack
1415
1416//!
1417void push_reg_to_stack(OpndSize size, int reg, bool isPhysical) {
1418    dump_reg(Mnemonic_PUSH, ATOM_NORMAL, size, reg, isPhysical, getTypeFromIntSize(size));
1419}
1420//!push mem to native stack
1421
1422//!
1423void push_mem_to_stack(OpndSize size, int disp, int base_reg, bool isBasePhysical) {
1424    dump_mem(Mnemonic_PUSH, ATOM_NORMAL, size, disp, base_reg, isBasePhysical);
1425}
1426//!move from reg to memory
1427
1428//!
1429void move_reg_to_mem(OpndSize size,
1430                      int reg, bool isPhysical,
1431                      int disp, int base_reg, bool isBasePhysical) {
1432    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1433    dump_reg_mem(m, ATOM_NORMAL, size, reg, isPhysical, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, getTypeFromIntSize(size));
1434}
1435//!move from reg to memory
1436
1437//!Operands are already allocated
1438void move_reg_to_mem_noalloc(OpndSize size,
1439                  int reg, bool isPhysical,
1440                  int disp, int base_reg, bool isBasePhysical,
1441                  MemoryAccessType mType, int mIndex) {
1442    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1443    dump_reg_mem_noalloc(m, size, reg, isPhysical, disp, base_reg, isBasePhysical, mType, mIndex, getTypeFromIntSize(size));
1444}
1445//!move from memory to reg
1446
1447//!
1448LowOpRegMem* move_mem_to_reg(OpndSize size,
1449                      int disp, int base_reg, bool isBasePhysical,
1450                      int reg, bool isPhysical) {
1451    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1452    return dump_mem_reg(m, ATOM_NORMAL, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, reg, isPhysical, getTypeFromIntSize(size));
1453}
1454//!move from memory to reg
1455
1456//!Operands are already allocated
1457LowOpRegMem* move_mem_to_reg_noalloc(OpndSize size,
1458                  int disp, int base_reg, bool isBasePhysical,
1459                  MemoryAccessType mType, int mIndex,
1460                  int reg, bool isPhysical) {
1461    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1462    return dump_mem_reg_noalloc(m, size, disp, base_reg, isBasePhysical, mType, mIndex, reg, isPhysical, getTypeFromIntSize(size));
1463}
1464//!movss from memory to reg
1465
1466//!Operands are already allocated
1467LowOpRegMem* move_ss_mem_to_reg_noalloc(int disp, int base_reg, bool isBasePhysical,
1468                 MemoryAccessType mType, int mIndex,
1469                 int reg, bool isPhysical) {
1470    return dump_mem_reg_noalloc(Mnemonic_MOVSS, OpndSize_32, disp, base_reg, isBasePhysical, mType, mIndex, reg, isPhysical, LowOpndRegType_xmm);
1471}
1472//!movss from reg to memory
1473
1474//!Operands are already allocated
1475LowOpMemReg* move_ss_reg_to_mem_noalloc(int reg, bool isPhysical,
1476                 int disp, int base_reg, bool isBasePhysical,
1477                 MemoryAccessType mType, int mIndex) {
1478    return dump_reg_mem_noalloc(Mnemonic_MOVSS, OpndSize_32, reg, isPhysical, disp, base_reg, isBasePhysical, mType, mIndex, LowOpndRegType_xmm);
1479}
1480//!movzx from memory to reg
1481
1482//!
1483void movez_mem_to_reg(OpndSize size,
1484               int disp, int base_reg, bool isBasePhysical,
1485               int reg, bool isPhysical) {
1486    Mnemonic m = Mnemonic_MOVZX;
1487    dump_movez_mem_reg(m, size, disp, base_reg, isBasePhysical, reg, isPhysical);
1488}
1489
1490//!movzx from one reg to another reg
1491
1492//!
1493void movez_reg_to_reg(OpndSize size,
1494                      int reg, bool isPhysical,
1495                      int reg2, bool isPhysical2) {
1496    Mnemonic m = Mnemonic_MOVZX;
1497    dump_movez_reg_reg(m, size, reg, isPhysical, reg2, isPhysical2);
1498}
1499
1500void movez_mem_disp_scale_to_reg(OpndSize size,
1501                 int base_reg, bool isBasePhysical,
1502                 int disp, int index_reg, bool isIndexPhysical, int scale,
1503                 int reg, bool isPhysical) {
1504    dump_mem_scale_reg(Mnemonic_MOVZX, size, base_reg, isBasePhysical,
1505                 disp, index_reg, isIndexPhysical, scale,
1506                 reg, isPhysical, LowOpndRegType_gp);
1507}
1508void moves_mem_disp_scale_to_reg(OpndSize size,
1509                  int base_reg, bool isBasePhysical,
1510                  int disp, int index_reg, bool isIndexPhysical, int scale,
1511                  int reg, bool isPhysical) {
1512    dump_mem_scale_reg(Mnemonic_MOVSX, size, base_reg, isBasePhysical,
1513                  disp, index_reg, isIndexPhysical, scale,
1514                  reg, isPhysical, LowOpndRegType_gp);
1515}
1516
1517//!movsx from memory to reg
1518
1519//!
1520void moves_mem_to_reg(LowOp* op, OpndSize size,
1521               int disp, int base_reg, bool isBasePhysical,
1522               int reg, bool isPhysical) {
1523    Mnemonic m = Mnemonic_MOVSX;
1524    dump_moves_mem_reg(m, size, disp, base_reg, isBasePhysical, reg, isPhysical);
1525}
1526//!mov from one reg to another reg
1527
1528//!
1529void move_reg_to_reg(OpndSize size,
1530                      int reg, bool isPhysical,
1531                      int reg2, bool isPhysical2) {
1532    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1533    dump_reg_reg(m, ATOM_NORMAL, size, reg, isPhysical, reg2, isPhysical2, getTypeFromIntSize(size));
1534}
1535//!mov from one reg to another reg
1536
1537//!Operands are already allocated
1538void move_reg_to_reg_noalloc(OpndSize size,
1539                  int reg, bool isPhysical,
1540                  int reg2, bool isPhysical2) {
1541    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1542    dump_reg_reg_noalloc(m, size, reg, isPhysical, reg2, isPhysical2, getTypeFromIntSize(size));
1543}
1544//!move from memory to reg
1545
1546//!
1547void move_mem_scale_to_reg(OpndSize size,
1548                int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale,
1549                int reg, bool isPhysical) {
1550    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1551    dump_mem_scale_reg(m, size, base_reg, isBasePhysical, 0/*disp*/, index_reg, isIndexPhysical, scale,
1552                              reg, isPhysical, getTypeFromIntSize(size));
1553}
1554void move_mem_disp_scale_to_reg(OpndSize size,
1555                int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale,
1556                int reg, bool isPhysical) {
1557    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1558    dump_mem_scale_reg(m, size, base_reg, isBasePhysical, disp, index_reg, isIndexPhysical, scale,
1559                              reg, isPhysical, getTypeFromIntSize(size));
1560}
1561//!move from reg to memory
1562
1563//!
1564void move_reg_to_mem_scale(OpndSize size,
1565                int reg, bool isPhysical,
1566                int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale) {
1567    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1568    dump_reg_mem_scale(m, size, reg, isPhysical,
1569                              base_reg, isBasePhysical, 0/*disp*/, index_reg, isIndexPhysical, scale,
1570                              getTypeFromIntSize(size));
1571}
1572void move_reg_to_mem_disp_scale(OpndSize size,
1573                int reg, bool isPhysical,
1574                int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale) {
1575    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1576    dump_reg_mem_scale(m, size, reg, isPhysical,
1577                              base_reg, isBasePhysical, disp, index_reg, isIndexPhysical, scale,
1578                              getTypeFromIntSize(size));
1579}
1580
1581void move_chain_to_mem(OpndSize size, int imm,
1582                        int disp, int base_reg, bool isBasePhysical) {
1583    dump_imm_mem(Mnemonic_MOV, ATOM_NORMAL, size, imm, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, true);
1584}
1585
1586//!move an immediate to memory
1587
1588//!
1589void move_imm_to_mem(OpndSize size, int imm,
1590                      int disp, int base_reg, bool isBasePhysical) {
1591    assert(size != OpndSize_64);
1592    if(size == OpndSize_64) ALOGE("move_imm_to_mem with 64 bits");
1593    dump_imm_mem(Mnemonic_MOV, ATOM_NORMAL, size, imm, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, false);
1594}
1595//! set a VR to an immediate
1596
1597//!
1598void set_VR_to_imm(u2 vA, OpndSize size, int imm) {
1599    assert(size != OpndSize_64);
1600    if(size == OpndSize_64) ALOGE("move_imm_to_mem with 64 bits");
1601    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1602    if(gDvm.executionMode == kExecutionModeNcgO1) {
1603        int regAll = checkVirtualReg(vA, getTypeFromIntSize(size), 0);
1604        if(regAll != PhysicalReg_Null) {
1605            dump_imm_reg_noalloc(m, size, imm, regAll, true, LowOpndRegType_gp);
1606            updateRefCount(vA, getTypeFromIntSize(size));
1607            updateVirtualReg(vA, getTypeFromIntSize(size));
1608            return;
1609        }
1610        //will call freeReg
1611        freeReg(true);
1612        regAll = registerAlloc(LowOpndRegType_virtual | getTypeFromIntSize(size), vA, false/*dummy*/, true);
1613        if(regAll == PhysicalReg_Null) {
1614            dump_imm_mem_noalloc(m, size, imm, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA);
1615            return;
1616        }
1617        dump_imm_reg_noalloc(m, size, imm, regAll, true, LowOpndRegType_gp);
1618        updateVirtualReg(vA, getTypeFromIntSize(size));
1619    }
1620    else {
1621        dump_imm_mem(m, ATOM_NORMAL, size, imm, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, false);
1622    }
1623}
1624void set_VR_to_imm_noupdateref(LowOp* op, u2 vA, OpndSize size, int imm) {
1625    return;
1626}
1627//! set a VR to an immediate
1628
1629//! Do not allocate a physical register for the VR
1630void set_VR_to_imm_noalloc(u2 vA, OpndSize size, int imm) {
1631    assert(size != OpndSize_64);
1632    if(size == OpndSize_64) ALOGE("move_imm_to_mem with 64 bits");
1633    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1634    dump_imm_mem_noalloc(m, size, imm, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA);
1635}
1636
1637void move_chain_to_reg(OpndSize size, int imm, int reg, bool isPhysical) {
1638    dump_imm_reg(Mnemonic_MOV, ATOM_NORMAL, size, imm, reg, isPhysical, LowOpndRegType_gp, true);
1639}
1640
1641//! move an immediate to reg
1642
1643//!
1644void move_imm_to_reg(OpndSize size, int imm, int reg, bool isPhysical) {
1645    assert(size != OpndSize_64);
1646    if(size == OpndSize_64) ALOGE("move_imm_to_reg with 64 bits");
1647    Mnemonic m = Mnemonic_MOV;
1648    dump_imm_reg(m, ATOM_NORMAL, size, imm, reg, isPhysical, LowOpndRegType_gp, false);
1649}
1650//! move an immediate to reg
1651
1652//! The operand is already allocated
1653void move_imm_to_reg_noalloc(OpndSize size, int imm, int reg, bool isPhysical) {
1654    assert(size != OpndSize_64);
1655    if(size == OpndSize_64) ALOGE("move_imm_to_reg with 64 bits");
1656    Mnemonic m = Mnemonic_MOV;
1657    dump_imm_reg_noalloc(m, size, imm, reg, isPhysical, LowOpndRegType_gp);
1658}
1659//!cmov from reg to reg
1660
1661//!
1662void conditional_move_reg_to_reg(OpndSize size, ConditionCode cc, int reg1, bool isPhysical1, int reg, bool isPhysical) {
1663    Mnemonic m = (Mnemonic)(Mnemonic_CMOVcc+cc);
1664    dump_reg_reg(m, ATOM_NORMAL, size, reg1, isPhysical1, reg, isPhysical, LowOpndRegType_gp);
1665}
1666//!movss from memory to reg
1667
1668//!
1669void move_ss_mem_to_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical,
1670                         int reg, bool isPhysical) {
1671    dump_mem_reg(Mnemonic_MOVSS, ATOM_NORMAL, OpndSize_32, disp, base_reg, isBasePhysical,
1672        MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_xmm);
1673}
1674//!movss from reg to memory
1675
1676//!
1677void move_ss_reg_to_mem(LowOp* op, int reg, bool isPhysical,
1678                         int disp, int base_reg, bool isBasePhysical) {
1679    dump_reg_mem(Mnemonic_MOVSS, ATOM_NORMAL, OpndSize_32, reg, isPhysical, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, LowOpndRegType_xmm);
1680}
1681//!movsd from memory to reg
1682
1683//!
1684void move_sd_mem_to_reg(int disp, int base_reg, bool isBasePhysical,
1685                         int reg, bool isPhysical) {
1686    dump_mem_reg(Mnemonic_MOVSD, ATOM_NORMAL, OpndSize_64, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_xmm);
1687}
1688//!movsd from reg to memory
1689
1690//!
1691void move_sd_reg_to_mem(LowOp* op, int reg, bool isPhysical,
1692                         int disp, int base_reg, bool isBasePhysical) {
1693    dump_reg_mem(Mnemonic_MOVSD, ATOM_NORMAL, OpndSize_64, reg, isPhysical,
1694                        disp, base_reg, isBasePhysical,
1695                        MemoryAccess_Unknown, -1, LowOpndRegType_xmm);
1696}
1697//!load from VR to a temporary
1698
1699//!
1700void get_virtual_reg_all(u2 vB, OpndSize size, int reg, bool isPhysical, Mnemonic m) {
1701    LowOpndRegType type = getTypeFromIntSize(size);
1702    LowOpndRegType pType = type;//gp or xmm
1703    OpndSize size2 = size;
1704    Mnemonic m2 = m;
1705    if(m == Mnemonic_MOVSS) {
1706        size = OpndSize_32;
1707        size2 = OpndSize_64;
1708        type = LowOpndRegType_ss;
1709        pType = LowOpndRegType_xmm;
1710        m2 = Mnemonic_MOVQ; //to move from one xmm register to another
1711    }
1712    if(gDvm.executionMode == kExecutionModeNcgO1) {
1713        int tmpValue[2];
1714        int isConst;
1715        isConst = isVirtualRegConstant(vB, type, tmpValue, true/*updateRefCount*/);
1716        if(isConst == 3) {
1717            if(m == Mnemonic_MOVSS) { //load 32 bits from VR
1718                //VR is not mapped to a register but in memory
1719                dumpImmToMem(vB, OpndSize_32, tmpValue[0]);
1720                //temporary reg has "pType" (which is xmm)
1721                dump_mem_reg(m, ATOM_NORMAL, size, 4*vB, PhysicalReg_FP, true,
1722                    MemoryAccess_VR, vB, reg, isPhysical, pType);
1723                return;
1724            }
1725            else if(m == Mnemonic_MOVSD || size == OpndSize_64) {
1726                //VR is not mapped to a register but in memory
1727                dumpImmToMem(vB, OpndSize_32, tmpValue[0]);
1728                dumpImmToMem(vB+1, OpndSize_32, tmpValue[1]);
1729                dump_mem_reg(m, ATOM_NORMAL, size, 4*vB, PhysicalReg_FP, true,
1730                    MemoryAccess_VR, vB, reg, isPhysical, pType);
1731                return;
1732            }
1733            else if(size != OpndSize_64) {
1734                //VR is not mapped to a register
1735                dump_imm_reg(m, ATOM_NORMAL, size, tmpValue[0], reg, isPhysical, pType, false);
1736                return;
1737            }
1738        }
1739        if(isConst == 1) dumpImmToMem(vB, OpndSize_32, tmpValue[0]);
1740        if(isConst == 2) dumpImmToMem(vB+1, OpndSize_32, tmpValue[1]);
1741        freeReg(true);
1742        int regAll = checkVirtualReg(vB, type, 0);
1743        if(regAll != PhysicalReg_Null) {
1744            startNativeCode(vB, type);
1745            donotSpillReg(regAll);
1746            //check XFER_MEM_TO_XMM
1747            updateVRAtUse(vB, type, regAll);
1748            //temporary reg has "pType"
1749            dump_reg_reg_noalloc_src(m2, ATOM_NORMAL, size2, regAll, true, reg, isPhysical, pType); //register allocator handles assembly move
1750            endNativeCode();
1751            updateRefCount(vB, type);
1752            return;
1753        }
1754        //not allocated to a register yet, no need to check XFER_MEM_TO_XMM
1755        regAll = registerAlloc(LowOpndRegType_virtual | type, vB, false/*dummy*/, false);
1756        if(regAll == PhysicalReg_Null) {
1757            dump_mem_reg_noalloc(m, size, 4*vB, PhysicalReg_FP, true,
1758                MemoryAccess_VR, vB, reg, isPhysical, pType);
1759            return;
1760        }
1761
1762        //temporary reg has pType
1763        if(checkTempReg2(reg, pType, isPhysical, regAll)) {
1764            registerAllocMove(reg, pType, isPhysical, regAll);
1765            dump_mem_reg_noalloc(m, size, 4*vB, PhysicalReg_FP, true,
1766                MemoryAccess_VR, vB, regAll, true, pType);
1767            updateRefCount(vB, type);
1768            return;
1769        }
1770        else {
1771            dump_mem_reg_noalloc(m, size, 4*vB, PhysicalReg_FP, true,
1772                MemoryAccess_VR, vB, regAll, true, pType);
1773            //xmm with 32 bits
1774            startNativeCode(vB, type);
1775            donotSpillReg(regAll);
1776            dump_reg_reg_noalloc_src(m2, ATOM_NORMAL, size2, regAll, true, reg, isPhysical, pType);
1777            endNativeCode();
1778            updateRefCount(vB, type);
1779            return;
1780        }
1781    }
1782    else {
1783        dump_mem_reg(m, ATOM_NORMAL, size, 4*vB, PhysicalReg_FP, true,
1784            MemoryAccess_VR, vB, reg, isPhysical, pType);
1785    }
1786}
1787void get_virtual_reg(u2 vB, OpndSize size, int reg, bool isPhysical) {
1788    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1789    return get_virtual_reg_all(vB, size, reg, isPhysical, m);
1790}
1791void get_virtual_reg_noalloc(u2 vB, OpndSize size, int reg, bool isPhysical) {
1792    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1793    dump_mem_reg_noalloc(m, size, 4*vB, PhysicalReg_FP, true,
1794        MemoryAccess_VR, vB, reg, isPhysical, getTypeFromIntSize(size));
1795}
1796//3 cases: gp, xmm, ss
1797//ss: the temporary register is xmm
1798//!load from a temporary to a VR
1799
1800//!
1801void set_virtual_reg_all(u2 vA, OpndSize size, int reg, bool isPhysical, Mnemonic m) {
1802    LowOpndRegType type = getTypeFromIntSize(size);
1803    LowOpndRegType pType = type;//gp or xmm
1804    OpndSize size2 = size;
1805    Mnemonic m2 = m;
1806    if(m == Mnemonic_MOVSS) {
1807        size = OpndSize_32;
1808        size2 = OpndSize_64;
1809        type = LowOpndRegType_ss;
1810        pType = LowOpndRegType_xmm;
1811        m2 = Mnemonic_MOVQ;
1812    }
1813    if(gDvm.executionMode == kExecutionModeNcgO1) {
1814        //3 cases
1815        //1: virtual register is already allocated to a physical register
1816        //   call dump_reg_reg_noalloc_dst
1817        //2: src reg is already allocated, VR is not yet allocated
1818        //   allocate VR to the same physical register used by src reg
1819        //   [call registerAllocMove]
1820        //3: both not yet allocated
1821        //   allocate a physical register for the VR
1822        //   then call dump_reg_reg_noalloc_dst
1823        //may need to convert from gp to xmm or the other way
1824        freeReg(true);
1825        int regAll = checkVirtualReg(vA, type, 0);
1826        if(regAll != PhysicalReg_Null)  { //case 1
1827            startNativeCode(-1, -1);
1828            donotSpillReg(regAll);
1829            dump_reg_reg_noalloc_dst(m2, size2, reg, isPhysical, regAll, true, pType); //temporary reg is "pType"
1830            endNativeCode();
1831            updateRefCount(vA, type);
1832            updateVirtualReg(vA, type); //will dump VR to memory, should happen afterwards
1833            return;
1834        }
1835        regAll = checkTempReg(reg, pType, isPhysical, vA); //vA is not used inside
1836        if(regAll != PhysicalReg_Null) { //case 2
1837            registerAllocMove(vA, LowOpndRegType_virtual | type, false, regAll);
1838            updateVirtualReg(vA, type); //will dump VR to memory, should happen afterwards
1839            return; //next native instruction starts at op
1840        }
1841        //case 3
1842        regAll = registerAlloc(LowOpndRegType_virtual | type, vA, false/*dummy*/, false);
1843        if(regAll == PhysicalReg_Null) {
1844            dump_reg_mem_noalloc(m, size, reg, isPhysical, 4*vA, PhysicalReg_FP, true,
1845                MemoryAccess_VR, vA, pType);
1846            return;
1847        }
1848        startNativeCode(-1, -1);
1849        donotSpillReg(regAll);
1850        dump_reg_reg_noalloc_dst(m2, size2, reg, isPhysical, regAll, true, pType);
1851        endNativeCode();
1852        updateRefCount(vA, type);
1853        updateVirtualReg(vA, type);
1854    }
1855    else {
1856        dump_reg_mem(m, ATOM_NORMAL, size, reg, isPhysical, 4*vA, PhysicalReg_FP, true,
1857            MemoryAccess_VR, vA, pType);
1858    }
1859}
1860void set_virtual_reg(u2 vA, OpndSize size, int reg, bool isPhysical) {
1861    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1862    return set_virtual_reg_all(vA, size, reg, isPhysical, m);
1863}
1864void set_virtual_reg_noalloc(u2 vA, OpndSize size, int reg, bool isPhysical) {
1865    Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV;
1866    dump_reg_mem_noalloc(m, size, reg, isPhysical, 4*vA, PhysicalReg_FP, true,
1867        MemoryAccess_VR, vA, getTypeFromIntSize(size));
1868}
1869void get_VR_ss(int vB, int reg, bool isPhysical) {
1870    return get_virtual_reg_all(vB, OpndSize_64, reg, isPhysical, Mnemonic_MOVSS);
1871}
1872void set_VR_ss(int vA, int reg, bool isPhysical) {
1873    return set_virtual_reg_all(vA, OpndSize_64, reg, isPhysical, Mnemonic_MOVSS);
1874}
1875void get_VR_sd(int vB, int reg, bool isPhysical) {
1876    return get_virtual_reg_all(vB, OpndSize_64, reg, isPhysical, Mnemonic_MOVSD);
1877}
1878void set_VR_sd(int vA, int reg, bool isPhysical) {
1879    return set_virtual_reg_all(vA, OpndSize_64, reg, isPhysical, Mnemonic_MOVSD);
1880}
1881////////////////////////////////// END: IA32 native instructions //////////////
1882//! generate native instructions to get current PC in the stack frame
1883
1884//!
1885int get_currentpc(int reg, bool isPhysical) {
1886    move_mem_to_reg(OpndSize_32, -sizeofStackSaveArea+offStackSaveArea_localRefTop, PhysicalReg_FP, true, reg, isPhysical);
1887    return 1;
1888}
1889//!generate native code to perform null check
1890
1891//!This function does not export PC
1892int simpleNullCheck(int reg, bool isPhysical, int vr) {
1893    if(isVRNullCheck(vr, OpndSize_32)) {
1894        updateRefCount2(reg, LowOpndRegType_gp, isPhysical);
1895        num_removed_nullCheck++;
1896        return 0;
1897    }
1898    compare_imm_reg(OpndSize_32, 0, reg, isPhysical);
1899    conditional_jump_global_API(Condition_E, "common_errNullObject", false);
1900    setVRNullCheck(vr, OpndSize_32);
1901    return 0;
1902}
1903
1904/* only for O1 code generator */
1905int boundCheck(int vr_array, int reg_array, bool isPhysical_array,
1906               int vr_index, int reg_index, bool isPhysical_index,
1907               int exceptionNum) {
1908#ifdef BOUNDCHECK_OPT
1909    if(isVRBoundCheck(vr_array, vr_index)) {
1910        updateRefCount2(reg_array, LowOpndRegType_gp, isPhysical_array);
1911        updateRefCount2(reg_index, LowOpndRegType_gp, isPhysical_index);
1912        return 0;
1913    }
1914#endif
1915    compare_mem_reg(OpndSize_32, offArrayObject_length,
1916                    reg_array, isPhysical_array,
1917                    reg_index, isPhysical_index);
1918
1919    char errName[256];
1920    sprintf(errName, "common_errArrayIndex");
1921    handlePotentialException(
1922                                       Condition_NC, Condition_C,
1923                                       exceptionNum, errName);
1924#ifdef BOUNDCHECK_OPT
1925    setVRBoundCheck(vr_array, vr_index);
1926#endif
1927    return 0;
1928}
1929
1930//!generate native code to perform null check
1931
1932//!
1933int nullCheck(int reg, bool isPhysical, int exceptionNum, int vr) {
1934    char label[LABEL_SIZE];
1935
1936    if(gDvm.executionMode == kExecutionModeNcgO1) {
1937        //nullCheck optimization is available in O1 mode only
1938        if(isVRNullCheck(vr, OpndSize_32)) {
1939            updateRefCount2(reg, LowOpndRegType_gp, isPhysical);
1940            if(exceptionNum <= 1) {
1941                updateRefCount2(PhysicalReg_EDX, LowOpndRegType_gp, true);
1942                updateRefCount2(PhysicalReg_EDX, LowOpndRegType_gp, true);
1943            }
1944            num_removed_nullCheck++;
1945            return 0;
1946        }
1947        compare_imm_reg(OpndSize_32, 0, reg, isPhysical);
1948        rememberState(exceptionNum);
1949        snprintf(label, LABEL_SIZE, "after_exception_%d", exceptionNum);
1950        conditional_jump(Condition_NE, label, true);
1951        if(exceptionNum > 1)
1952            nextVersionOfHardReg(PhysicalReg_EDX, 2); //next version has 2 ref count
1953        export_pc(); //use %edx
1954        constVREndOfBB();
1955        beforeCall("exception"); //dump GG, GL VRs
1956        unconditional_jump_global_API("common_errNullObject", false);
1957        insertLabel(label, true);
1958        goToState(exceptionNum);
1959        setVRNullCheck(vr, OpndSize_32);
1960    } else {
1961        compare_imm_reg(OpndSize_32, 0, reg, isPhysical);
1962        snprintf(label, LABEL_SIZE, "after_exception_%d", exceptionNum);
1963        conditional_jump(Condition_NE, label, true);
1964        export_pc(); //use %edx
1965        unconditional_jump_global_API("common_errNullObject", false);
1966        insertLabel(label, true);
1967    }
1968    return 0;
1969}
1970//!generate native code to handle potential exception
1971
1972//!
1973int handlePotentialException(
1974                             ConditionCode code_excep, ConditionCode code_okay,
1975                             int exceptionNum, const char* errName) {
1976    char label[LABEL_SIZE];
1977
1978    if(gDvm.executionMode == kExecutionModeNcgO1) {
1979        rememberState(exceptionNum);
1980        snprintf(label, LABEL_SIZE, "after_exception_%d", exceptionNum);
1981        conditional_jump(code_okay, label, true);
1982        if(exceptionNum > 1)
1983            nextVersionOfHardReg(PhysicalReg_EDX, 2); //next version has 2 ref count
1984        export_pc(); //use %edx
1985        constVREndOfBB();
1986        beforeCall("exception"); //dump GG, GL VRs
1987        if(!strcmp(errName, "common_throw_message")) {
1988            move_imm_to_reg(OpndSize_32, LstrInstantiationErrorPtr, PhysicalReg_ECX, true);
1989        }
1990        unconditional_jump_global_API(errName, false);
1991        insertLabel(label, true);
1992        goToState(exceptionNum);
1993    } else {
1994        snprintf(label, LABEL_SIZE, "after_exception_%d", exceptionNum);
1995        conditional_jump(code_okay, label, true);
1996        export_pc(); //use %edx
1997        if(!strcmp(errName, "common_throw_message")) {
1998            move_imm_to_reg(OpndSize_32, LstrInstantiationErrorPtr, PhysicalReg_ECX, true);
1999        }
2000        unconditional_jump_global_API(errName, false);
2001        insertLabel(label, true);
2002    }
2003    return 0;
2004}
2005//!generate native code to get the self pointer from glue
2006
2007//!It uses one scratch register
2008int get_self_pointer(int reg, bool isPhysical) {
2009    move_mem_to_reg(OpndSize_32, offEBP_self, PhysicalReg_EBP, true, reg, isPhysical);
2010    return 0;
2011}
2012//!generate native code to get ResStrings from glue
2013
2014//!It uses two scratch registers
2015int get_res_strings(int reg, bool isPhysical) {
2016    //if spill_loc_index > 0 || reg != NULL, use registerAlloc
2017    if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) {
2018        //if spill_loc_index > 0
2019        //  load from spilled location, update spill_loc_index & physicalReg
2020#if 0
2021        updateRefCount2(C_SCRATCH_1, LowOpndRegType_gp, isScratchPhysical);
2022        updateRefCount2(C_SCRATCH_1, LowOpndRegType_gp, isScratchPhysical);
2023        updateRefCount2(C_SCRATCH_2, LowOpndRegType_gp, isScratchPhysical);
2024        updateRefCount2(C_SCRATCH_2, LowOpndRegType_gp, isScratchPhysical);
2025#endif
2026        startNativeCode(-1, -1);
2027        freeReg(true);
2028        int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/);
2029        donotSpillReg(regAll);
2030        dump_mem_reg_noalloc_mem(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, offDvmDex_pResStrings, regAll, true, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp);
2031        endNativeCode();
2032    }
2033    else
2034        {
2035            get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2036            move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical);
2037            //glue is not in a physical reg nor in a spilled location
2038            updateGlue(C_SCRATCH_2, isScratchPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg
2039            move_mem_to_reg(OpndSize_32, offDvmDex_pResStrings, C_SCRATCH_2, isScratchPhysical, reg, isPhysical);
2040        }
2041    return 0;
2042}
2043int get_res_classes(int reg, bool isPhysical) {
2044    //if spill_loc_index > 0 || reg != NULL, use registerAlloc
2045    if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) {
2046        //if spill_loc_index > 0
2047        //  load from spilled location, updte spill_loc_index & physicalReg
2048        startNativeCode(-1, -1);
2049        freeReg(true);
2050        int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/);
2051        donotSpillReg(regAll);
2052        dump_mem_reg_noalloc_mem(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, offDvmDex_pResClasses, regAll, true, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp);
2053        endNativeCode();
2054    }
2055    else
2056        {
2057            get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2058            move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical);
2059            //glue is not in a physical reg nor in a spilled location
2060            updateGlue(C_SCRATCH_2, isScratchPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg
2061            move_mem_to_reg(OpndSize_32, offDvmDex_pResClasses, C_SCRATCH_2, isScratchPhysical, reg, isPhysical);
2062        }
2063    return 0;
2064}
2065//!generate native code to get ResFields from glue
2066
2067//!It uses two scratch registers
2068int get_res_fields(int reg, bool isPhysical) {
2069    //if spill_loc_index > 0 || reg != NULL, use registerAlloc
2070    if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) {
2071        //if spill_loc_index > 0
2072        //  load from spilled location, updte spill_loc_index & physicalReg
2073        startNativeCode(-1, -1);
2074        freeReg(true);
2075        int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/);
2076        donotSpillReg(regAll);
2077        dump_mem_reg_noalloc_mem(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, offDvmDex_pResFields, regAll, true, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp);
2078        endNativeCode();
2079    }
2080    else
2081        {
2082            get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2083            move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical);
2084            //glue is not in a physical reg nor in a spilled location
2085            updateGlue(C_SCRATCH_2, isScratchPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg
2086            move_mem_to_reg(OpndSize_32, offDvmDex_pResFields, C_SCRATCH_2, isScratchPhysical, reg, isPhysical);
2087        }
2088    return 0;
2089}
2090//!generate native code to get ResMethods from glue
2091
2092//!It uses two scratch registers
2093int get_res_methods(int reg, bool isPhysical) {
2094    //if spill_loc_index > 0 || reg != NULL, use registerAlloc
2095    if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) {
2096        //if spill_loc_index > 0
2097        //  load from spilled location, updte spill_loc_index & physicalReg
2098        startNativeCode(-1, -1);
2099        freeReg(true);
2100        int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/);
2101        donotSpillReg(regAll);
2102        dump_mem_reg_noalloc_mem(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, offDvmDex_pResMethods, regAll, true, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp);
2103        endNativeCode();
2104    }
2105    else
2106        {
2107            get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2108            move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical);
2109            //glue is not in a physical reg nor in a spilled location
2110            updateGlue(C_SCRATCH_2, isScratchPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg
2111            move_mem_to_reg(OpndSize_32, offDvmDex_pResMethods, C_SCRATCH_2, isScratchPhysical, reg, isPhysical);
2112        }
2113    return 0;
2114}
2115//!generate native code to get the current class object from glue
2116
2117//!It uses two scratch registers
2118int get_glue_method_class(int reg, bool isPhysical) {
2119    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2120    move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.method), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical);
2121    move_mem_to_reg(OpndSize_32, offMethod_clazz, C_SCRATCH_2, isScratchPhysical, reg, isPhysical);
2122    return 0;
2123}
2124//!generate native code to get the current method from glue
2125
2126//!It uses one scratch register
2127int get_glue_method(int reg, bool isPhysical) {
2128    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2129    move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.method), C_SCRATCH_1, isScratchPhysical, reg, isPhysical);
2130    return 0;
2131}
2132//!generate native code to set the current method in glue
2133
2134//!It uses one scratch register
2135int set_glue_method(int reg, bool isPhysical) {
2136    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2137    move_reg_to_mem(OpndSize_32, reg, isPhysical, offsetof(Thread, interpSave.method), C_SCRATCH_1, isScratchPhysical);
2138    return 0;
2139}
2140
2141//!generate native code to get DvmDex from glue
2142
2143//!It uses one scratch register
2144int get_glue_dvmdex(int reg, bool isPhysical) {
2145    //if spill_loc_index > 0 || reg != NULL, use registerAlloc
2146    if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) {
2147        //if spill_loc_index > 0
2148        //  load from spilled location, updte spill_loc_index & physicalReg
2149        startNativeCode(-1, -1);
2150        freeReg(true);
2151        int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/);
2152        donotSpillReg(regAll);
2153        dump_reg_reg_noalloc_src(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, regAll, true,
2154                                          reg, isPhysical, LowOpndRegType_gp);
2155        endNativeCode();
2156    }
2157    else
2158        {
2159            get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2160            move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, reg, isPhysical);
2161            //glue is not in a physical reg nor in a spilled location
2162            updateGlue(reg, isPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg
2163        }
2164    return 0;
2165}
2166//!generate native code to set DvmDex in glue
2167
2168//!It uses one scratch register
2169int set_glue_dvmdex(int reg, bool isPhysical) {
2170    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2171    move_reg_to_mem(OpndSize_32, reg, isPhysical, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical);
2172    return 0;
2173}
2174//!generate native code to get SuspendCount from glue
2175
2176//!It uses one scratch register
2177int get_suspendCount(int reg, bool isPhysical) {
2178    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2179    move_mem_to_reg(OpndSize_32, offsetof(Thread, suspendCount), C_SCRATCH_1, isScratchPhysical, reg, isPhysical);
2180    return 0;
2181}
2182
2183//!generate native code to get retval from glue
2184
2185//!It uses one scratch register
2186int get_return_value(OpndSize size, int reg, bool isPhysical) {
2187    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2188    move_mem_to_reg(size, offsetof(Thread, interpSave.retval), C_SCRATCH_1, isScratchPhysical, reg, isPhysical);
2189    return 0;
2190}
2191//!generate native code to set retval in glue
2192
2193//!It uses one scratch register
2194int set_return_value(OpndSize size, int reg, bool isPhysical) {
2195    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2196    move_reg_to_mem(size, reg, isPhysical, offsetof(Thread, interpSave.retval), C_SCRATCH_1, isScratchPhysical);
2197    return 0;
2198}
2199//!generate native code to clear exception object in glue
2200
2201//!It uses two scratch registers
2202int clear_exception() {
2203    get_self_pointer(C_SCRATCH_2, isScratchPhysical);
2204    move_imm_to_mem(OpndSize_32, 0, offsetof(Thread, exception), C_SCRATCH_2, isScratchPhysical);
2205    return 0;
2206}
2207//!generate native code to get exception object in glue
2208
2209//!It uses two scratch registers
2210int get_exception(int reg, bool isPhysical) {
2211    get_self_pointer(C_SCRATCH_2, isScratchPhysical);
2212    move_mem_to_reg(OpndSize_32, offsetof(Thread, exception), C_SCRATCH_2, isScratchPhysical, reg, isPhysical);
2213    return 0;
2214}
2215//!generate native code to set exception object in glue
2216
2217//!It uses two scratch registers
2218int set_exception(int reg, bool isPhysical) {
2219    get_self_pointer(C_SCRATCH_2, isScratchPhysical);
2220    move_reg_to_mem(OpndSize_32, reg, isPhysical, offsetof(Thread, exception), C_SCRATCH_2, isScratchPhysical);
2221    return 0;
2222}
2223//!generate native code to save frame pointer and current PC in stack frame to glue
2224
2225//!It uses two scratch registers
2226int save_pc_fp_to_glue() {
2227    get_self_pointer(C_SCRATCH_1, isScratchPhysical);
2228    move_reg_to_mem(OpndSize_32, PhysicalReg_FP, true, offsetof(Thread, interpSave.curFrame), C_SCRATCH_1, isScratchPhysical);
2229
2230    //from stack-save currentPc
2231    move_mem_to_reg(OpndSize_32, -sizeofStackSaveArea+offStackSaveArea_localRefTop, PhysicalReg_FP, true, C_SCRATCH_2, isScratchPhysical);
2232    move_reg_to_mem(OpndSize_32, C_SCRATCH_2, isScratchPhysical, offsetof(Thread, interpSave.pc), C_SCRATCH_1, isScratchPhysical);
2233    return 0;
2234}
2235//! get SaveArea pointer
2236
2237//!
2238int savearea_from_fp(int reg, bool isPhysical) {
2239    load_effective_addr(-sizeofStackSaveArea, PhysicalReg_FP, true, reg, isPhysical);
2240    return 0;
2241}
2242
2243#ifdef DEBUG_CALL_STACK3
2244int call_debug_dumpSwitch() {
2245    typedef void (*vmHelper)(int);
2246    vmHelper funcPtr = debug_dumpSwitch;
2247    callFuncPtr((int)funcPtr, "debug_dumpSwitch");
2248    return 0;
2249}
2250#endif
2251
2252int call_dvmQuasiAtomicSwap64() {
2253    typedef int64_t (*vmHelper)(int64_t, volatile int64_t*);
2254    vmHelper funcPtr = dvmQuasiAtomicSwap64;
2255    if(gDvm.executionMode == kExecutionModeNcgO1) {
2256        beforeCall("dvmQuasiAtomicSwap64");
2257        callFuncPtr((int)funcPtr, "dvmQuasiAtomicSwap64");
2258        afterCall("dvmQuasiAtomicSwap64");
2259    } else {
2260        callFuncPtr((int)funcPtr, "dvmQuasiAtomicSwap64");
2261    }
2262    return 0;
2263}
2264
2265int call_dvmQuasiAtomicRead64() {
2266    typedef int64_t (*vmHelper)(volatile const int64_t*);
2267    vmHelper funcPtr = dvmQuasiAtomicRead64;
2268    if(gDvm.executionMode == kExecutionModeNcgO1) {
2269        beforeCall("dvmQuasiAtomiRead64");
2270        callFuncPtr((int)funcPtr, "dvmQuasiAtomicRead64");
2271        afterCall("dvmQuasiAtomicRead64");
2272        touchEax(); //for return value
2273        touchEdx();
2274    } else {
2275        callFuncPtr((int)funcPtr, "dvmQuasiAtomicRead64");
2276    }
2277    return 0;
2278}
2279
2280int call_dvmJitToInterpPunt() {
2281    typedef void (*vmHelper)(int);
2282    vmHelper funcPtr = dvmJitToInterpPunt;
2283    callFuncPtr((int)funcPtr, "dvmJitToInterpPunt");
2284    return 0;
2285}
2286
2287int call_dvmJitToInterpNormal() {
2288    typedef void (*vmHelper)(int);
2289    vmHelper funcPtr = dvmJitToInterpNormal;
2290    if(gDvm.executionMode == kExecutionModeNcgO1) {
2291        beforeCall("dvmJitToInterpNormal");
2292        callFuncPtr((int)funcPtr, "dvmJitToInterpNormal");
2293        afterCall("dvmJitToInterpNormal");
2294        touchEbx();
2295    } else {
2296        callFuncPtr((int)funcPtr, "dvmJitToInterpNormal");
2297    }
2298    return 0;
2299}
2300
2301int call_dvmJitToInterpTraceSelectNoChain() {
2302    typedef void (*vmHelper)(int);
2303    vmHelper funcPtr = dvmJitToInterpTraceSelectNoChain;
2304    if(gDvm.executionMode == kExecutionModeNcgO1) {
2305        beforeCall("dvmJitToInterpTraceSelectNoChain");
2306        callFuncPtr((int)funcPtr, "dvmJitToInterpTraceSelectNoChain");
2307        afterCall("dvmJitToInterpTraceSelectNoChain");
2308        touchEbx();
2309    } else {
2310        callFuncPtr((int)funcPtr, "dvmJitToInterpTraceSelectNoChain");
2311    }
2312    return 0;
2313}
2314
2315int call_dvmJitToInterpTraceSelect() {
2316    typedef void (*vmHelper)(int);
2317    vmHelper funcPtr = dvmJitToInterpTraceSelect;
2318    if(gDvm.executionMode == kExecutionModeNcgO1) {
2319        beforeCall("dvmJitToInterpTraceSelect");
2320        callFuncPtr((int)funcPtr, "dvmJitToInterpTraceSelect");
2321        afterCall("dvmJitToInterpTraceSelect");
2322        touchEbx();
2323    } else {
2324        callFuncPtr((int)funcPtr, "dvmJitToInterpTraceSelect");
2325    }
2326    return 0;
2327}
2328
2329int call_dvmJitToPatchPredictedChain() {
2330    typedef const Method * (*vmHelper)(const Method *method,
2331                                       Thread *self,
2332                                       PredictedChainingCell *cell,
2333                                       const ClassObject *clazz);
2334    vmHelper funcPtr = dvmJitToPatchPredictedChain;
2335    if(gDvm.executionMode == kExecutionModeNcgO1) {
2336        beforeCall("dvmJitToPatchPredictedChain");
2337        callFuncPtr((int)funcPtr, "dvmJitToPatchPredictedChain");
2338        afterCall("dvmJitToPatchPredictedChain");
2339    } else {
2340        callFuncPtr((int)funcPtr, "dvmJitToPatchPredictedChain");
2341    }
2342    return 0;
2343}
2344
2345//!generate native code to call __moddi3
2346
2347//!
2348int call_moddi3() {
2349    if(gDvm.executionMode == kExecutionModeNcgO1) {
2350        beforeCall("moddi3");
2351        callFuncPtr((intptr_t)__moddi3, "__moddi3");
2352        afterCall("moddi3");
2353    } else {
2354        callFuncPtr((intptr_t)__moddi3, "__moddi3");
2355    }
2356    return 0;
2357}
2358//!generate native code to call __divdi3
2359
2360//!
2361int call_divdi3() {
2362    if(gDvm.executionMode == kExecutionModeNcgO1) {
2363        beforeCall("divdi3");
2364        callFuncPtr((intptr_t)__divdi3, "__divdi3");
2365        afterCall("divdi3");
2366    } else {
2367        callFuncPtr((intptr_t)__divdi3, "__divdi3");
2368    }
2369    return 0;
2370}
2371
2372//!generate native code to call fmod
2373
2374//!
2375int call_fmod() {
2376    typedef double (*libHelper)(double, double);
2377    libHelper funcPtr = fmod;
2378    if(gDvm.executionMode == kExecutionModeNcgO1) {
2379        beforeCall("fmod");
2380        callFuncPtr((int)funcPtr, "fmod");
2381        afterCall("fmod");
2382    } else {
2383        callFuncPtr((int)funcPtr, "fmod");
2384    }
2385    return 0;
2386}
2387//!generate native code to call fmodf
2388
2389//!
2390int call_fmodf() {
2391    typedef float (*libHelper)(float, float);
2392    libHelper funcPtr = fmodf;
2393    if(gDvm.executionMode == kExecutionModeNcgO1) {
2394        beforeCall("fmodf");
2395        callFuncPtr((int)funcPtr, "fmodf");
2396        afterCall("fmodf");
2397    } else {
2398        callFuncPtr((int)funcPtr, "fmodf");
2399    }
2400    return 0;
2401}
2402//!generate native code to call dvmFindCatchBlock
2403
2404//!
2405int call_dvmFindCatchBlock() {
2406    //int dvmFindCatchBlock(Thread* self, int relPc, Object* exception,
2407    //bool doUnroll, void** newFrame)
2408    typedef int (*vmHelper)(Thread*, int, Object*, bool, void**);
2409    vmHelper funcPtr = dvmFindCatchBlock;
2410    if(gDvm.executionMode == kExecutionModeNcgO1) {
2411        beforeCall("dvmFindCatchBlock");
2412        callFuncPtr((int)funcPtr, "dvmFindCatchBlock");
2413        afterCall("dvmFindCatchBlock");
2414    } else {
2415        callFuncPtr((int)funcPtr, "dvmFindCatchBlock");
2416    }
2417    return 0;
2418}
2419//!generate native code to call dvmThrowVerificationError
2420
2421//!
2422int call_dvmThrowVerificationError() {
2423    typedef void (*vmHelper)(const Method*, int, int);
2424    vmHelper funcPtr = dvmThrowVerificationError;
2425    if(gDvm.executionMode == kExecutionModeNcgO1) {
2426        beforeCall("dvmThrowVerificationError");
2427        callFuncPtr((int)funcPtr, "dvmThrowVerificationError");
2428        afterCall("dvmThrowVerificationError");
2429    } else {
2430        callFuncPtr((int)funcPtr, "dvmThrowVerificationError");
2431    }
2432    return 0;
2433}
2434
2435//!generate native code to call dvmResolveMethod
2436
2437//!
2438int call_dvmResolveMethod() {
2439    //Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx, MethodType methodType);
2440    typedef Method* (*vmHelper)(const ClassObject*, u4, MethodType);
2441    vmHelper funcPtr = dvmResolveMethod;
2442    if(gDvm.executionMode == kExecutionModeNcgO1) {
2443        beforeCall("dvmResolveMethod");
2444        callFuncPtr((int)funcPtr, "dvmResolveMethod");
2445        afterCall("dvmResolveMethod");
2446    } else {
2447        callFuncPtr((int)funcPtr, "dvmResolveMethod");
2448    }
2449    return 0;
2450}
2451//!generate native code to call dvmResolveClass
2452
2453//!
2454int call_dvmResolveClass() {
2455    //ClassObject* dvmResolveClass(const ClassObject* referrer, u4 classIdx, bool fromUnverifiedConstant)
2456    typedef ClassObject* (*vmHelper)(const ClassObject*, u4, bool);
2457    vmHelper funcPtr = dvmResolveClass;
2458    if(gDvm.executionMode == kExecutionModeNcgO1) {
2459        beforeCall("dvmResolveClass");
2460        callFuncPtr((int)funcPtr, "dvmResolveClass");
2461        afterCall("dvmResolveClass");
2462    } else {
2463        callFuncPtr((int)funcPtr, "dvmResolveClass");
2464    }
2465    return 0;
2466}
2467
2468//!generate native code to call dvmInstanceofNonTrivial
2469
2470//!
2471int call_dvmInstanceofNonTrivial() {
2472    typedef int (*vmHelper)(const ClassObject*, const ClassObject*);
2473    vmHelper funcPtr = dvmInstanceofNonTrivial;
2474    if(gDvm.executionMode == kExecutionModeNcgO1) {
2475        beforeCall("dvmInstanceofNonTrivial");
2476        callFuncPtr((int)funcPtr, "dvmInstanceofNonTrivial");
2477        afterCall("dvmInstanceofNonTrivial");
2478    } else {
2479        callFuncPtr((int)funcPtr, "dvmInstanceofNonTrivial");
2480    }
2481    return 0;
2482}
2483//!generate native code to call dvmThrowException
2484
2485//!
2486int call_dvmThrow() {
2487    typedef void (*vmHelper)(ClassObject* exceptionClass, const char*);
2488    vmHelper funcPtr = dvmThrowException;
2489    if(gDvm.executionMode == kExecutionModeNcgO1) {
2490        beforeCall("dvmThrowException");
2491        callFuncPtr((int)funcPtr, "dvmThrowException");
2492        afterCall("dvmThrowException");
2493    } else {
2494        callFuncPtr((int)funcPtr, "dvmThrowException");
2495    }
2496    return 0;
2497}
2498//!generate native code to call dvmThrowExceptionWithClassMessage
2499
2500//!
2501int call_dvmThrowWithMessage() {
2502    typedef void (*vmHelper)(ClassObject* exceptionClass, const char*);
2503    vmHelper funcPtr = dvmThrowExceptionWithClassMessage;
2504    if(gDvm.executionMode == kExecutionModeNcgO1) {
2505        beforeCall("dvmThrowExceptionWithClassMessage");
2506        callFuncPtr((int)funcPtr, "dvmThrowExceptionWithClassMessage");
2507        afterCall("dvmThrowExceptionWithClassMessage");
2508    } else {
2509        callFuncPtr((int)funcPtr, "dvmThrowExceptionWithClassMessage");
2510    }
2511    return 0;
2512}
2513//!generate native code to call dvmCheckSuspendPending
2514
2515//!
2516int call_dvmCheckSuspendPending() {
2517    typedef bool (*vmHelper)(Thread*);
2518    vmHelper funcPtr = dvmCheckSuspendPending;
2519    if(gDvm.executionMode == kExecutionModeNcgO1) {
2520        beforeCall("dvmCheckSuspendPending");
2521        callFuncPtr((int)funcPtr, "dvmCheckSuspendPending");
2522        afterCall("dvmCheckSuspendPending");
2523    } else {
2524        callFuncPtr((int)funcPtr, "dvmCheckSuspendPending");
2525    }
2526    return 0;
2527}
2528//!generate native code to call dvmLockObject
2529
2530//!
2531int call_dvmLockObject() {
2532    typedef void (*vmHelper)(struct Thread*, struct Object*);
2533    vmHelper funcPtr = dvmLockObject;
2534    if(gDvm.executionMode == kExecutionModeNcgO1) {
2535        beforeCall("dvmLockObject");
2536        callFuncPtr((int)funcPtr, "dvmLockObject");
2537        afterCall("dvmLockObject");
2538    } else {
2539        callFuncPtr((int)funcPtr, "dvmLockObject");
2540    }
2541    return 0;
2542}
2543//!generate native code to call dvmUnlockObject
2544
2545//!
2546int call_dvmUnlockObject() {
2547    typedef bool (*vmHelper)(Thread*, Object*);
2548    vmHelper funcPtr = dvmUnlockObject;
2549    if(gDvm.executionMode == kExecutionModeNcgO1) {
2550        beforeCall("dvmUnlockObject");
2551        callFuncPtr((int)funcPtr, "dvmUnlockObject");
2552        afterCall("dvmUnlockObject");
2553    } else {
2554        callFuncPtr((int)funcPtr, "dvmUnlockObject");
2555    }
2556    return 0;
2557}
2558//!generate native code to call dvmInitClass
2559
2560//!
2561int call_dvmInitClass() {
2562    typedef bool (*vmHelper)(ClassObject*);
2563    vmHelper funcPtr = dvmInitClass;
2564    if(gDvm.executionMode == kExecutionModeNcgO1) {
2565        beforeCall("dvmInitClass");
2566        callFuncPtr((int)funcPtr, "dvmInitClass");
2567        afterCall("dvmInitClass");
2568    } else {
2569        callFuncPtr((int)funcPtr, "dvmInitClass");
2570    }
2571    return 0;
2572}
2573//!generate native code to call dvmAllocObject
2574
2575//!
2576int call_dvmAllocObject() {
2577    typedef Object* (*vmHelper)(ClassObject*, int);
2578    vmHelper funcPtr = dvmAllocObject;
2579    if(gDvm.executionMode == kExecutionModeNcgO1) {
2580        beforeCall("dvmAllocObject");
2581        callFuncPtr((int)funcPtr, "dvmAllocObject");
2582        afterCall("dvmAllocObject");
2583    } else {
2584        callFuncPtr((int)funcPtr, "dvmAllocObject");
2585    }
2586    return 0;
2587}
2588//!generate native code to call dvmAllocArrayByClass
2589
2590//!
2591int call_dvmAllocArrayByClass() {
2592    typedef ArrayObject* (*vmHelper)(ClassObject*, size_t, int);
2593    vmHelper funcPtr = dvmAllocArrayByClass;
2594    if(gDvm.executionMode == kExecutionModeNcgO1) {
2595        beforeCall("dvmAllocArrayByClass");
2596        callFuncPtr((int)funcPtr, "dvmAllocArrayByClass");
2597        afterCall("dvmAllocArrayByClass");
2598    } else {
2599        callFuncPtr((int)funcPtr, "dvmAllocArrayByClass");
2600    }
2601    return 0;
2602}
2603//!generate native code to call dvmAllocPrimitiveArray
2604
2605//!
2606int call_dvmAllocPrimitiveArray() {
2607    typedef ArrayObject* (*vmHelper)(char, size_t, int);
2608    vmHelper funcPtr = dvmAllocPrimitiveArray;
2609    if(gDvm.executionMode == kExecutionModeNcgO1) {
2610        beforeCall("dvmAllocPrimitiveArray");
2611        callFuncPtr((int)funcPtr, "dvmAllocPrimitiveArray");
2612        afterCall("dvmAllocPrimitiveArray");
2613    } else {
2614        callFuncPtr((int)funcPtr, "dvmAllocPrimitiveArray");
2615    }
2616    return 0;
2617}
2618//!generate native code to call dvmInterpHandleFillArrayData
2619
2620//!
2621int call_dvmInterpHandleFillArrayData() {
2622    typedef bool (*vmHelper)(ArrayObject*, const u2*);
2623    vmHelper funcPtr = dvmInterpHandleFillArrayData;
2624    if(gDvm.executionMode == kExecutionModeNcgO1) {
2625        beforeCall("dvmInterpHandleFillArrayData"); //before move_imm_to_reg to avoid spilling C_SCRATCH_1
2626        callFuncPtr((int)funcPtr, "dvmInterpHandleFillArrayData");
2627        afterCall("dvmInterpHandleFillArrayData");
2628    } else {
2629        callFuncPtr((int)funcPtr, "dvmInterpHandleFillArrayData");
2630    }
2631    return 0;
2632}
2633
2634//!generate native code to call dvmNcgHandlePackedSwitch
2635
2636//!
2637int call_dvmNcgHandlePackedSwitch() {
2638    typedef s4 (*vmHelper)(const s4*, s4, u2, s4);
2639    vmHelper funcPtr = dvmNcgHandlePackedSwitch;
2640    if(gDvm.executionMode == kExecutionModeNcgO1) {
2641        beforeCall("dvmNcgHandlePackedSwitch");
2642        callFuncPtr((int)funcPtr, "dvmNcgHandlePackedSwitch");
2643        afterCall("dvmNcgHandlePackedSwitch");
2644    } else {
2645        callFuncPtr((int)funcPtr, "dvmNcgHandlePackedSwitch");
2646    }
2647    return 0;
2648}
2649
2650int call_dvmJitHandlePackedSwitch() {
2651    typedef s4 (*vmHelper)(const s4*, s4, u2, s4);
2652    vmHelper funcPtr = dvmJitHandlePackedSwitch;
2653    if(gDvm.executionMode == kExecutionModeNcgO1) {
2654        beforeCall("dvmJitHandlePackedSwitch");
2655        callFuncPtr((int)funcPtr, "dvmJitHandlePackedSwitch");
2656        afterCall("dvmJitHandlePackedSwitch");
2657    } else {
2658        callFuncPtr((int)funcPtr, "dvmJitHandlePackedSwitch");
2659    }
2660    return 0;
2661}
2662
2663//!generate native code to call dvmNcgHandleSparseSwitch
2664
2665//!
2666int call_dvmNcgHandleSparseSwitch() {
2667    typedef s4 (*vmHelper)(const s4*, u2, s4);
2668    vmHelper funcPtr = dvmNcgHandleSparseSwitch;
2669    if(gDvm.executionMode == kExecutionModeNcgO1) {
2670        beforeCall("dvmNcgHandleSparseSwitch");
2671        callFuncPtr((int)funcPtr, "dvmNcgHandleSparseSwitch");
2672        afterCall("dvmNcgHandleSparseSwitch");
2673    } else {
2674        callFuncPtr((int)funcPtr, "dvmNcgHandleSparseSwitch");
2675    }
2676    return 0;
2677}
2678
2679int call_dvmJitHandleSparseSwitch() {
2680    typedef s4 (*vmHelper)(const s4*, u2, s4);
2681    vmHelper funcPtr = dvmJitHandleSparseSwitch;
2682    if(gDvm.executionMode == kExecutionModeNcgO1) {
2683        beforeCall("dvmJitHandleSparseSwitch");
2684        callFuncPtr((int)funcPtr, "dvmJitHandleSparseSwitch");
2685        afterCall("dvmJitHandleSparseSwitch");
2686    } else {
2687        callFuncPtr((int)funcPtr, "dvmJitHandleSparseSwitch");
2688    }
2689    return 0;
2690}
2691
2692//!generate native code to call dvmCanPutArrayElement
2693
2694//!
2695int call_dvmCanPutArrayElement() {
2696    typedef bool (*vmHelper)(const ClassObject*, const ClassObject*);
2697    vmHelper funcPtr = dvmCanPutArrayElement;
2698    if(gDvm.executionMode == kExecutionModeNcgO1) {
2699        beforeCall("dvmCanPutArrayElement");
2700        callFuncPtr((int)funcPtr, "dvmCanPutArrayElement");
2701        afterCall("dvmCanPutArrayElement");
2702    } else {
2703        callFuncPtr((int)funcPtr, "dvmCanPutArrayElement");
2704    }
2705    return 0;
2706}
2707
2708//!generate native code to call dvmFindInterfaceMethodInCache2
2709
2710//!
2711int call_dvmFindInterfaceMethodInCache() {
2712    typedef Method* (*vmHelper)(ClassObject*, u4, const Method*, DvmDex*);
2713    vmHelper funcPtr = dvmFindInterfaceMethodInCache2;
2714    if(gDvm.executionMode == kExecutionModeNcgO1) {
2715        beforeCall("dvmFindInterfaceMethodInCache2");
2716        callFuncPtr((int)funcPtr, "dvmFindInterfaceMethodInCache2");
2717        afterCall("dvmFindInterfaceMethodInCache2");
2718    } else {
2719        callFuncPtr((int)funcPtr, "dvmFindInterfaceMethodInCache2");
2720    }
2721    return 0;
2722}
2723
2724//!generate native code to call dvmHandleStackOverflow
2725
2726//!
2727int call_dvmHandleStackOverflow() {
2728    typedef void (*vmHelper)(Thread*, const Method*);
2729    vmHelper funcPtr = dvmHandleStackOverflow;
2730    if(gDvm.executionMode == kExecutionModeNcgO1) {
2731        beforeCall("dvmHandleStackOverflow");
2732        callFuncPtr((int)funcPtr, "dvmHandleStackOverflow");
2733        afterCall("dvmHandleStackOverflow");
2734    } else {
2735        callFuncPtr((int)funcPtr, "dvmHandleStackOverflow");
2736    }
2737    return 0;
2738}
2739//!generate native code to call dvmResolveString
2740
2741//!
2742int call_dvmResolveString() {
2743    //StringObject* dvmResolveString(const ClassObject* referrer, u4 stringIdx)
2744    typedef StringObject* (*vmHelper)(const ClassObject*, u4);
2745    vmHelper funcPtr = dvmResolveString;
2746    if(gDvm.executionMode == kExecutionModeNcgO1) {
2747        beforeCall("dvmResolveString");
2748        callFuncPtr((int)funcPtr, "dvmResolveString");
2749        afterCall("dvmResolveString");
2750    } else {
2751        callFuncPtr((int)funcPtr, "dvmResolveString");
2752    }
2753    return 0;
2754}
2755//!generate native code to call dvmResolveInstField
2756
2757//!
2758int call_dvmResolveInstField() {
2759    //InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx)
2760    typedef InstField* (*vmHelper)(const ClassObject*, u4);
2761    vmHelper funcPtr = dvmResolveInstField;
2762    if(gDvm.executionMode == kExecutionModeNcgO1) {
2763        beforeCall("dvmResolveInstField");
2764        callFuncPtr((int)funcPtr, "dvmResolveInstField");
2765        afterCall("dvmResolveInstField");
2766    } else {
2767        callFuncPtr((int)funcPtr, "dvmResolveInstField");
2768    }
2769    return 0;
2770}
2771//!generate native code to call dvmResolveStaticField
2772
2773//!
2774int call_dvmResolveStaticField() {
2775    //StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx)
2776    typedef StaticField* (*vmHelper)(const ClassObject*, u4);
2777    vmHelper funcPtr = dvmResolveStaticField;
2778    if(gDvm.executionMode == kExecutionModeNcgO1) {
2779        beforeCall("dvmResolveStaticField");
2780        callFuncPtr((int)funcPtr, "dvmResolveStaticField");
2781        afterCall("dvmResolveStaticField");
2782    } else {
2783        callFuncPtr((int)funcPtr, "dvmResolveStaticField");
2784    }
2785    return 0;
2786}
2787
2788#define P_GPR_2 PhysicalReg_ECX
2789/*!
2790\brief This function is used to resolve a string reference
2791
2792INPUT: const pool index in %eax
2793
2794OUTPUT: resolved string in %eax
2795
2796The registers are hard-coded, 2 physical registers %esi and %edx are used as scratch registers;
2797It calls a C function dvmResolveString;
2798The only register that is still live after this function is ebx
2799*/
2800int const_string_resolve() {
2801    scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX;
2802    scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null;
2803    insertLabel(".const_string_resolve", false);
2804    //method stored in glue structure as well as on the interpreted stack
2805    get_glue_method_class(P_GPR_2, true);
2806    load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2807    move_reg_to_mem(OpndSize_32, PhysicalReg_EAX, true, 4, PhysicalReg_ESP, true);
2808    move_reg_to_mem(OpndSize_32, P_GPR_2, true, 0, PhysicalReg_ESP, true);
2809    call_dvmResolveString();
2810    load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2811    compare_imm_reg( OpndSize_32, 0, PhysicalReg_EAX, true);
2812    conditional_jump(Condition_E, "common_exceptionThrown", false);
2813    x86_return();
2814    return 0;
2815}
2816#undef P_GPR_2
2817/*!
2818\brief This function is used to resolve a class
2819
2820INPUT: const pool index in argument "indexReg" (%eax)
2821
2822OUTPUT: resolved class in %eax
2823
2824The registers are hard-coded, 3 physical registers (%esi, %edx, startLR:%eax) are used as scratch registers.
2825It calls a C function dvmResolveClass;
2826The only register that is still live after this function is ebx
2827*/
2828int resolve_class2(
2829           int startLR/*scratch register*/, bool isPhysical, int indexReg/*const pool index*/,
2830           bool indexPhysical, int thirdArg) {
2831    insertLabel(".class_resolve", false);
2832    scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX;
2833    scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null;
2834
2835    //push index to stack first, to free indexReg
2836    load_effective_addr(-12, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2837    move_reg_to_mem(OpndSize_32, indexReg, indexPhysical, 4, PhysicalReg_ESP, true);
2838    get_glue_method_class(startLR, isPhysical);
2839    move_imm_to_mem(OpndSize_32, thirdArg, 8, PhysicalReg_ESP, true);
2840    move_reg_to_mem(OpndSize_32, startLR, isPhysical, 0, PhysicalReg_ESP, true);
2841    call_dvmResolveClass();
2842    load_effective_addr(12, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2843    compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true);
2844    conditional_jump(Condition_E, "common_exceptionThrown", false);
2845
2846    x86_return();
2847    return 0;
2848}
2849/*!
2850\brief This function is used to resolve a method, and it is called once with %eax for both indexReg and startLR
2851
2852INPUT: const pool index in argument "indexReg" (%eax)
2853
2854OUTPUT: resolved method in %eax
2855
2856The registers are hard-coded, 3 physical registers (%esi, %edx, startLR:%eax) are used as scratch registers.
2857It calls a C function dvmResolveMethod;
2858The only register that is still live after this function is ebx
2859*/
2860int resolve_method2(
2861            int startLR/*logical register index*/, bool isPhysical, int indexReg/*const pool index*/,
2862            bool indexPhysical,
2863            int thirdArg/*VIRTUAL*/) {
2864    if(thirdArg == METHOD_VIRTUAL)
2865        insertLabel(".virtual_method_resolve", false);
2866    else if(thirdArg == METHOD_DIRECT)
2867        insertLabel(".direct_method_resolve", false);
2868    else if(thirdArg == METHOD_STATIC)
2869        insertLabel(".static_method_resolve", false);
2870
2871    load_effective_addr(-12, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2872    move_reg_to_mem(OpndSize_32, indexReg, indexPhysical, 4, PhysicalReg_ESP, true);
2873
2874    scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX;
2875    scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null;
2876    get_glue_method_class(startLR, isPhysical);
2877
2878    move_imm_to_mem(OpndSize_32, thirdArg, 8, PhysicalReg_ESP, true);
2879    move_reg_to_mem(OpndSize_32, startLR, isPhysical, 0, PhysicalReg_ESP, true);
2880    call_dvmResolveMethod();
2881    load_effective_addr(12, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2882    compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true);
2883    conditional_jump(Condition_E, "common_exceptionThrown", false);
2884
2885    x86_return();
2886    return 0;
2887}
2888/*!
2889\brief This function is used to resolve an instance field
2890
2891INPUT: const pool index in argument "indexReg" (%eax)
2892
2893OUTPUT: resolved field in %eax
2894
2895The registers are hard-coded, 3 physical registers (%esi, %edx, startLR:%eax) are used as scratch registers.
2896It calls a C function dvmResolveInstField;
2897The only register that is still live after this function is ebx
2898*/
2899int resolve_inst_field2(
2900            int startLR/*logical register index*/, bool isPhysical,
2901            int indexReg/*const pool index*/, bool indexPhysical) {
2902    insertLabel(".inst_field_resolve", false);
2903    scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX;
2904    scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null;
2905
2906    load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2907    move_reg_to_mem(OpndSize_32, indexReg, indexPhysical, 4, PhysicalReg_ESP, true);
2908    //method stored in glue structure as well as interpreted stack
2909    get_glue_method_class(startLR, isPhysical);
2910    move_reg_to_mem(OpndSize_32, startLR, isPhysical, 0, PhysicalReg_ESP, true);
2911    call_dvmResolveInstField();
2912    load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2913    compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true);
2914    conditional_jump(Condition_E, "common_exceptionThrown", false);
2915
2916    x86_return();
2917    return 0;
2918}
2919/*!
2920\brief This function is used to resolve a static field
2921
2922INPUT: const pool index in argument "indexReg" (%eax)
2923
2924OUTPUT: resolved field in %eax
2925
2926The registers are hard-coded, 3 physical registers (%esi, %edx, startLR:%eax) are used as scratch registers.
2927It calls a C function dvmResolveStaticField;
2928The only register that is still live after this function is ebx
2929*/
2930int resolve_static_field2(
2931              int startLR/*logical register index*/, bool isPhysical, int indexReg/*const pool index*/,
2932              bool indexPhysical) {
2933    insertLabel(".static_field_resolve", false);
2934    scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX;
2935    scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null;
2936
2937    load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2938    move_reg_to_mem(OpndSize_32, indexReg, indexPhysical, 4, PhysicalReg_ESP, true);
2939    get_glue_method_class(startLR, isPhysical);
2940    move_reg_to_mem(OpndSize_32, startLR, isPhysical, 0, PhysicalReg_ESP, true);
2941    call_dvmResolveStaticField();
2942    load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2943    compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true);
2944    conditional_jump(Condition_E, "common_exceptionThrown", false);
2945
2946    x86_return();
2947    return 0;
2948}
2949
2950int pushAllRegs() {
2951    load_effective_addr(-28, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2952    move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EAX, true, 24, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1);
2953    move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EBX, true, 20, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1);
2954    move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_ECX, true, 16, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1);
2955    move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EDX, true, 12, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1);
2956    move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_ESI, true, 8, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1);
2957    move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EDI, true, 4, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1);
2958    move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EBP, true, 0, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1);
2959    return 0;
2960}
2961int popAllRegs() {
2962    move_mem_to_reg_noalloc(OpndSize_32, 24, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EAX, true);
2963    move_mem_to_reg_noalloc(OpndSize_32, 20, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EBX, true);
2964    move_mem_to_reg_noalloc(OpndSize_32, 16, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_ECX, true);
2965    move_mem_to_reg_noalloc(OpndSize_32, 12, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EDX, true);
2966    move_mem_to_reg_noalloc(OpndSize_32, 8, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_ESI, true);
2967    move_mem_to_reg_noalloc(OpndSize_32, 4, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EDI, true);
2968    move_mem_to_reg_noalloc(OpndSize_32, 0, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EBP, true);
2969    load_effective_addr(28, PhysicalReg_ESP, true, PhysicalReg_ESP, true);
2970    return 0;
2971}
2972
2973void dump_nop(int size) {
2974    switch(size) {
2975        case 1:
2976          *stream = 0x90;
2977          break;
2978        case 2:
2979          *stream = 0x66;
2980          *(stream +1) = 0x90;
2981          break;
2982        case 3:
2983          *stream = 0x0f;
2984          *(stream + 1) = 0x1f;
2985          *(stream + 2) = 0x00;
2986          break;
2987        default:
2988          //TODO: add more cases.
2989          break;
2990    }
2991    stream += size;
2992}
2993