blob: 1c86f46df0191da6123aa0adb757b7b28cd92a12 [file] [log] [blame]
/*
* This file was generated automatically by gen-mterp.py for 'x86'.
*
* --> DO NOT EDIT <--
*/
/* File: x86/header.S */
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* 32-bit x86 definitions and declarations.
*/
/*
386 ABI general notes:
Caller save set:
eax, edx, ecx, st(0)-st(7)
Callee save set:
ebx, esi, edi, ebp
Return regs:
32-bit in eax
64-bit in edx:eax (low-order 32 in eax)
fp on top of fp stack st(0)
Parameters passed on stack, pushed right-to-left. On entry to target, first
parm is at 4(%esp). Traditional entry code is:
functEntry:
push %ebp # save old frame pointer
mov %ebp,%esp # establish new frame pointer
sub FrameSize,%esp # Allocate storage for spill, locals & outs
Once past the prologue, arguments are referenced at ((argno + 2)*4)(%ebp)
Alignment of stack not strictly required, but should be for performance. We'll
align frame sizes to 16-byte multiples.
If we're not doing variable stack allocation (alloca), the frame pointer can be
eliminated and all arg references adjusted to be esp relative.
Mterp notes:
Some key interpreter variables will be assigned to registers. Note that each
will also have an associated spill location (mostly useful for those assigned
to callee save registers).
nick reg purpose
rPC edi interpreted program counter, used for fetching instructions
rFP esi interpreted frame pointer, used for accessing locals and args
rINSTw bx first 16-bit code of current instruction
rINSTbl bl opcode portion of instruction word
rINSTbh bh high byte of inst word, usually contains src/tgt reg names
rIBASE edx base of instruction handler table
Notes:
o High order 16 bits of ebx must be zero on entry to handler
o rPC, rFP, rINSTw/rINSTbl valid on handler entry and exit
o eax and ecx are scratch, rINSTw/ebx sometimes scratch
*/
#define rSELF (%ebp)
#define rPC %esi
#define rFP %edi
#define rINST %ebx
#define rINSTw %bx
#define rINSTbh %bh
#define rINSTbl %bl
#define rIBASE %edx
/* Frame diagram while executing dvmMterpStdRun, high to low addresses */
#define IN_ARG0 ( 12)
#define CALLER_RP ( 8)
#define PREV_FP ( 4)
#define rSELF_SPILL ( 0) /* <- dvmMterpStdRun ebp */
/* Spill offsets relative to %ebp */
#define EDI_SPILL ( -4)
#define ESI_SPILL ( -8)
#define EBX_SPILL (-12) /* <- esp following dmMterpStdRun header */
#define rPC_SPILL (-16)
#define rFP_SPILL (-20)
#define rINST_SPILL (-24)
#define rIBASE_SPILL (-28)
#define TMP_SPILL1 (-32)
#define TMP_SPILL2 (-36)
#define TMP_SPILL3 (-20)
#define LOCAL0_OFFSET (-44)
#define LOCAL1_OFFSET (-48)
#define LOCAL2_OFFSET (-52)
/* Out Arg offsets, relative to %sp */
#define OUT_ARG4 ( 16)
#define OUT_ARG3 ( 12)
#define OUT_ARG2 ( 8)
#define OUT_ARG1 ( 4)
#define OUT_ARG0 ( 0) /* <- dvmMterpStdRun esp */
#define FRAME_SIZE 80
#define SPILL(reg) movl reg##,reg##_SPILL(%ebp)
#define UNSPILL(reg) movl reg##_SPILL(%ebp),reg
#define SPILL_TMP1(reg) movl reg,TMP_SPILL1(%ebp)
#define UNSPILL_TMP1(reg) movl TMP_SPILL1(%ebp),reg
#define SPILL_TMP2(reg) movl reg,TMP_SPILL2(%ebp)
#define UNSPILL_TMP2(reg) movl TMP_SPILL2(%ebp),reg
#define SPILL_TMP3(reg) movl reg,TMP_SPILL3(%ebp)
#define UNSPILL_TMP3(reg) movl TMP_SPILL3(%ebp),reg
#if defined(WITH_JIT)
.macro GET_JIT_PROF_TABLE _self _reg
movl offThread_pJitProfTable(\_self),\_reg
.endm
.macro GET_JIT_THRESHOLD _self _reg
movl offThread_jitThreshold(\_self),\_reg
.endm
#endif
/* save/restore the PC and/or FP from the self struct */
.macro SAVE_PC_FP_TO_SELF _reg
movl rSELF,\_reg
movl rPC,offThread_pc(\_reg)
movl rFP,offThread_fp(\_reg)
.endm
.macro LOAD_PC_FP_FROM_SELF
movl rSELF,rFP
movl offThread_pc(rFP),rPC
movl offThread_fp(rFP),rFP
.endm
/* The interpreter assumes a properly aligned stack on entry, and
* will preserve 16-byte alignment.
*/
/*
* "export" the PC to the interpreted stack frame, f/b/o future exception
* objects. Must be done *before* something throws.
*
* In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
* fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
*
* It's okay to do this more than once.
*/
.macro EXPORT_PC
movl rPC, (-sizeofStackSaveArea + offStackSaveArea_currentPc)(rFP)
.endm
/*
* Given a frame pointer, find the stack save area.
*
* In C this is "((StackSaveArea*)(_fp) -1)".
*/
.macro SAVEAREA_FROM_FP _reg
leal -sizeofStackSaveArea(rFP), \_reg
.endm
/*
* Fetch the next instruction from rPC into rINSTw. Does not advance rPC.
*/
.macro FETCH_INST
movzwl (rPC),rINST
.endm
/*
* Fetch the opcode byte and zero-extend it into _reg. Must be used
* in conjunction with GOTO_NEXT_R
*/
.macro FETCH_INST_R _reg
movzbl (rPC),\_reg
.endm
/*
* Fetch the opcode byte at _count words offset from rPC and zero-extend
* it into _reg. Must be used in conjunction with GOTO_NEXT_R
*/
.macro FETCH_INST_OPCODE _count _reg
movzbl \_count*2(rPC),\_reg
.endm
/*
* Fetch the nth instruction word from rPC into rINSTw. Does not advance
* rPC, and _count is in words
*/
.macro FETCH_INST_WORD _count
movzwl \_count*2(rPC),rINST
.endm
/*
* Fetch instruction word indexed (used for branching).
* Index is in instruction word units.
*/
.macro FETCH_INST_INDEXED _reg
movzwl (rPC,\_reg,2),rINST
.endm
/*
* Advance rPC by instruction count
*/
.macro ADVANCE_PC _count
leal 2*\_count(rPC),rPC
.endm
/*
* Advance rPC by branch offset in register
*/
.macro ADVANCE_PC_INDEXED _reg
leal (rPC,\_reg,2),rPC
.endm
.macro GOTO_NEXT
movzx rINSTbl,%eax
movzbl rINSTbh,rINST
jmp *(rIBASE,%eax,4)
.endm
/*
* Version of GOTO_NEXT that assumes _reg preloaded with opcode.
* Should be paired with FETCH_INST_R
*/
.macro GOTO_NEXT_R _reg
movzbl 1(rPC),rINST
jmp *(rIBASE,\_reg,4)
.endm
/*
* Jumbo version of GOTO_NEXT that assumes _reg preloaded with table
* offset of the jumbo instruction, which is the top half of the extended
* opcode + 0x100. Loads rINST with BBBB field, similar to GOTO_NEXT_R
*/
.macro GOTO_NEXT_JUMBO_R _reg
movzwl 6(rPC),rINST
jmp *(rIBASE,\_reg,4)
.endm
/*
* Get/set the 32-bit value from a Dalvik register.
*/
.macro GET_VREG_R _reg _vreg
movl (rFP,\_vreg,4),\_reg
.endm
.macro SET_VREG _reg _vreg
movl \_reg,(rFP,\_vreg,4)
.endm
.macro GET_VREG_WORD _reg _vreg _offset
movl 4*(\_offset)(rFP,\_vreg,4),\_reg
.endm
.macro SET_VREG_WORD _reg _vreg _offset
movl \_reg,4*(\_offset)(rFP,\_vreg,4)
.endm
#define sReg0 LOCAL0_OFFSET(%ebp)
#define sReg1 LOCAL1_OFFSET(%ebp)
#define sReg2 LOCAL2_OFFSET(%ebp)
/*
* Hard coded helper values.
*/
.balign 16
.LdoubNeg:
.quad 0x8000000000000000
.L64bits:
.quad 0xFFFFFFFFFFFFFFFF
.LshiftMask2:
.quad 0x0000000000000000
.LshiftMask:
.quad 0x000000000000003F
.Lvalue64:
.quad 0x0000000000000040
.LvaluePosInfLong:
.quad 0x7FFFFFFFFFFFFFFF
.LvalueNegInfLong:
.quad 0x8000000000000000
.LvalueNanLong:
.quad 0x0000000000000000
.LintMin:
.long 0x80000000
.LintMax:
.long 0x7FFFFFFF
/*
* This is a #include, not a %include, because we want the C pre-processor
* to expand the macros into assembler assignment statements.
*/
#include "../common/asm-constants.h"
#if defined(WITH_JIT)
#include "../common/jit-config.h"
#endif
.global dvmAsmInstructionStartCode
.type dvmAsmInstructionStartCode, %function
dvmAsmInstructionStartCode = .L_OP_NOP
.text
/* ------------------------------ */
.L_OP_NOP: /* 0x00 */
/* File: x86/OP_NOP.S */
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE: /* 0x01 */
/* File: x86/OP_MOVE.S */
/* for move, move-object, long-to-int */
/* op vA, vB */
movzbl rINSTbl,%eax # eax<- BA
andb $0xf,%al # eax<- A
shrl $4,rINST # rINST<- B
GET_VREG_R rINST rINST
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
SET_VREG rINST %eax # fp[A]<-fp[B]
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_FROM16: /* 0x02 */
/* File: x86/OP_MOVE_FROM16.S */
/* for: move/from16, move-object/from16 */
/* op vAA, vBBBB */
movzx rINSTbl,%eax # eax <= AA
movw 2(rPC),rINSTw # rINSTw <= BBBB
GET_VREG_R rINST rINST # rINST- fp[BBBB]
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
SET_VREG rINST %eax # fp[AA]<- ecx]
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_16: /* 0x03 */
/* File: x86/OP_MOVE_16.S */
/* for: move/16, move-object/16 */
/* op vAAAA, vBBBB */
movzwl 4(rPC),%ecx # ecx<- BBBB
movzwl 2(rPC),%eax # eax<- AAAA
GET_VREG_R rINST %ecx
FETCH_INST_OPCODE 3 %ecx
ADVANCE_PC 3
SET_VREG rINST %eax
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_WIDE: /* 0x04 */
/* File: x86/OP_MOVE_WIDE.S */
/* move-wide vA, vB */
/* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
movzbl rINSTbl,%ecx # ecx <- BA
sarl $4,rINST # rINST<- B
GET_VREG_WORD %eax rINST 0 # eax<- v[B+0]
GET_VREG_WORD rINST rINST 1 # rINST<- v[B+1]
andb $0xf,%cl # ecx <- A
SET_VREG_WORD rINST %ecx 1 # v[A+1]<- rINST
SET_VREG_WORD %eax %ecx 0 # v[A+0]<- eax
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
/* File: x86/OP_MOVE_WIDE_FROM16.S */
/* move-wide/from16 vAA, vBBBB */
/* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
movzwl 2(rPC),%ecx # ecx<- BBBB
movzbl rINSTbl,%eax # eax<- AAAA
GET_VREG_WORD rINST %ecx 0 # rINST<- v[BBBB+0]
GET_VREG_WORD %ecx %ecx 1 # ecx<- v[BBBB+1]
SET_VREG_WORD rINST %eax 0 # v[AAAA+0]<- rINST
SET_VREG_WORD %ecx %eax 1 # v[AAAA+1]<- eax
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_WIDE_16: /* 0x06 */
/* File: x86/OP_MOVE_WIDE_16.S */
/* move-wide/16 vAAAA, vBBBB */
/* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
movzwl 4(rPC),%ecx # ecx<- BBBB
movzwl 2(rPC),%eax # eax<- AAAA
GET_VREG_WORD rINST %ecx 0 # rINSTw_WORD<- v[BBBB+0]
GET_VREG_WORD %ecx %ecx 1 # ecx<- v[BBBB+1]
SET_VREG_WORD rINST %eax 0 # v[AAAA+0]<- rINST
SET_VREG_WORD %ecx %eax 1 # v[AAAA+1]<- ecx
FETCH_INST_OPCODE 3 %ecx
ADVANCE_PC 3
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_OBJECT: /* 0x07 */
/* File: x86/OP_MOVE_OBJECT.S */
/* File: x86/OP_MOVE.S */
/* for move, move-object, long-to-int */
/* op vA, vB */
movzbl rINSTbl,%eax # eax<- BA
andb $0xf,%al # eax<- A
shrl $4,rINST # rINST<- B
GET_VREG_R rINST rINST
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
SET_VREG rINST %eax # fp[A]<-fp[B]
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
/* File: x86/OP_MOVE_OBJECT_FROM16.S */
/* File: x86/OP_MOVE_FROM16.S */
/* for: move/from16, move-object/from16 */
/* op vAA, vBBBB */
movzx rINSTbl,%eax # eax <= AA
movw 2(rPC),rINSTw # rINSTw <= BBBB
GET_VREG_R rINST rINST # rINST- fp[BBBB]
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
SET_VREG rINST %eax # fp[AA]<- ecx]
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_OBJECT_16: /* 0x09 */
/* File: x86/OP_MOVE_OBJECT_16.S */
/* File: x86/OP_MOVE_16.S */
/* for: move/16, move-object/16 */
/* op vAAAA, vBBBB */
movzwl 4(rPC),%ecx # ecx<- BBBB
movzwl 2(rPC),%eax # eax<- AAAA
GET_VREG_R rINST %ecx
FETCH_INST_OPCODE 3 %ecx
ADVANCE_PC 3
SET_VREG rINST %eax
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_RESULT: /* 0x0a */
/* File: x86/OP_MOVE_RESULT.S */
/* for: move-result, move-result-object */
/* op vAA */
movl rSELF,%eax # eax<- rSELF
movl offThread_retval(%eax),%eax # eax<- self->retval.l
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
SET_VREG %eax rINST # fp[AA]<- retval.l
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
/* File: x86/OP_MOVE_RESULT_WIDE.S */
/* move-result-wide vAA */
movl rSELF,%ecx
movl offThread_retval(%ecx),%eax
movl 4+offThread_retval(%ecx),%ecx
SET_VREG_WORD %eax rINST 0 # v[AA+0] <- eax
SET_VREG_WORD %ecx rINST 1 # v[AA+1] <- ecx
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
/* File: x86/OP_MOVE_RESULT_OBJECT.S */
/* File: x86/OP_MOVE_RESULT.S */
/* for: move-result, move-result-object */
/* op vAA */
movl rSELF,%eax # eax<- rSELF
movl offThread_retval(%eax),%eax # eax<- self->retval.l
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
SET_VREG %eax rINST # fp[AA]<- retval.l
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MOVE_EXCEPTION: /* 0x0d */
/* File: x86/OP_MOVE_EXCEPTION.S */
/* move-exception vAA */
movl rSELF,%ecx
movl offThread_exception(%ecx),%eax # eax<- dvmGetException bypass
SET_VREG %eax rINST # fp[AA]<- exception object
FETCH_INST_OPCODE 1 %eax
ADVANCE_PC 1
movl $0,offThread_exception(%ecx) # dvmClearException bypass
GOTO_NEXT_R %eax
/* ------------------------------ */
.L_OP_RETURN_VOID: /* 0x0e */
/* File: x86/OP_RETURN_VOID.S */
jmp common_returnFromMethod
/* ------------------------------ */
.L_OP_RETURN: /* 0x0f */
/* File: x86/OP_RETURN.S */
/*
* Return a 32-bit value. Copies the return value into the "self"
* structure, then jumps to the return handler.
*
* for: return, return-object
*/
/* op vAA */
movl rSELF,%ecx
GET_VREG_R %eax rINST # eax<- vAA
movl %eax,offThread_retval(%ecx) # retval.i <- AA
jmp common_returnFromMethod
/* ------------------------------ */
.L_OP_RETURN_WIDE: /* 0x10 */
/* File: x86/OP_RETURN_WIDE.S */
/*
* Return a 64-bit value. Copies the return value into the "self"
* structure, then jumps to the return handler.
*/
/* return-wide vAA */
movl rSELF,%ecx
GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0]
GET_VREG_WORD rINST rINST 1 # rINST<- v[AA+1]
movl %eax,offThread_retval(%ecx)
movl rINST,4+offThread_retval(%ecx)
jmp common_returnFromMethod
/* ------------------------------ */
.L_OP_RETURN_OBJECT: /* 0x11 */
/* File: x86/OP_RETURN_OBJECT.S */
/* File: x86/OP_RETURN.S */
/*
* Return a 32-bit value. Copies the return value into the "self"
* structure, then jumps to the return handler.
*
* for: return, return-object
*/
/* op vAA */
movl rSELF,%ecx
GET_VREG_R %eax rINST # eax<- vAA
movl %eax,offThread_retval(%ecx) # retval.i <- AA
jmp common_returnFromMethod
/* ------------------------------ */
.L_OP_CONST_4: /* 0x12 */
/* File: x86/OP_CONST_4.S */
/* const/4 vA, #+B */
movsx rINSTbl,%eax # eax<-ssssssBx
movl $0xf,rINST
andl %eax,rINST # rINST<- A
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
sarl $4,%eax
SET_VREG %eax rINST
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_CONST_16: /* 0x13 */
/* File: x86/OP_CONST_16.S */
/* const/16 vAA, #+BBBB */
movswl 2(rPC),%ecx # ecx<- ssssBBBB
FETCH_INST_OPCODE 2 %eax
ADVANCE_PC 2
SET_VREG %ecx rINST # vAA<- ssssBBBB
GOTO_NEXT_R %eax
/* ------------------------------ */
.L_OP_CONST: /* 0x14 */
/* File: x86/OP_CONST.S */
/* const vAA, #+BBBBbbbb */
movl 2(rPC),%eax # grab all 32 bits at once
movl rINST,rINST # rINST<- AA
FETCH_INST_OPCODE 3 %ecx
ADVANCE_PC 3
SET_VREG %eax rINST # vAA<- eax
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_CONST_HIGH16: /* 0x15 */
/* File: x86/OP_CONST_HIGH16.S */
/* const/high16 vAA, #+BBBB0000 */
movzwl 2(rPC),%eax # eax<- 0000BBBB
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
sall $16,%eax # eax<- BBBB0000
SET_VREG %eax rINST # vAA<- eax
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_CONST_WIDE_16: /* 0x16 */
/* File: x86/OP_CONST_WIDE_16.S */
/* const-wide/16 vAA, #+BBBB */
movswl 2(rPC),%eax # eax<- ssssBBBB
SPILL(rIBASE) # preserve rIBASE (cltd trashes it)
cltd # rIBASE:eax<- ssssssssssssBBBB
SET_VREG_WORD rIBASE rINST 1 # store msw
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE) # restore rIBASE
SET_VREG_WORD %eax rINST 0 # store lsw
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_CONST_WIDE_32: /* 0x17 */
/* File: x86/OP_CONST_WIDE_32.S */
/* const-wide/32 vAA, #+BBBBbbbb */
movl 2(rPC),%eax # eax<- BBBBbbbb
SPILL(rIBASE) # save rIBASE (cltd trashes it)
cltd # rIBASE:eax<- ssssssssssssBBBB
SET_VREG_WORD rIBASE rINST,1 # store msw
FETCH_INST_OPCODE 3 %ecx
UNSPILL(rIBASE) # restore rIBASE
SET_VREG_WORD %eax rINST 0 # store lsw
ADVANCE_PC 3
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_CONST_WIDE: /* 0x18 */
/* File: x86/OP_CONST_WIDE.S */
/* const-wide vAA, #+HHHHhhhhBBBBbbbb */
movl 2(rPC),%eax # eax<- lsw
movzbl rINSTbl,%ecx # ecx<- AA
movl 6(rPC),rINST # rINST<- msw
leal (rFP,%ecx,4),%ecx # dst addr
movl rINST,4(%ecx)
movl %eax,(%ecx)
FETCH_INST_OPCODE 5 %ecx
ADVANCE_PC 5
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
/* File: x86/OP_CONST_WIDE_HIGH16.S */
/* const-wide/high16 vAA, #+BBBB000000000000 */
movzwl 2(rPC),%eax # eax<- 0000BBBB
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
sall $16,%eax # eax<- BBBB0000
SET_VREG_WORD %eax rINST 1 # v[AA+1]<- eax
xorl %eax,%eax
SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_CONST_STRING: /* 0x1a */
/* File: x86/OP_CONST_STRING.S */
/* const/string vAA, String@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- BBBB
movl offThread_methodClassDex(%ecx),%ecx# ecx<- self->methodClassDex
movl offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings
movl (%ecx,%eax,4),%eax # eax<- rResString[BBBB]
FETCH_INST_OPCODE 2 %ecx
testl %eax,%eax # resolved yet?
je .LOP_CONST_STRING_resolve
SET_VREG %eax rINST # vAA<- rResString[BBBB]
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* This is the less common path, so we'll redo some work
here rather than force spills on the common path */
.LOP_CONST_STRING_resolve:
movl rSELF,%eax
EXPORT_PC
movl offThread_method(%eax),%eax # eax<- self->method
movzwl 2(rPC),%ecx # ecx<- BBBB
movl offMethod_clazz(%eax),%eax
movl %ecx,OUT_ARG1(%esp)
movl %eax,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveString # go resolve
UNSPILL(rIBASE)
testl %eax,%eax # failed?
je common_exceptionThrown
FETCH_INST_OPCODE 2 %ecx
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_CONST_STRING_JUMBO: /* 0x1b */
/* File: x86/OP_CONST_STRING_JUMBO.S */
/* const/string vAA, String@BBBBBBBB */
movl rSELF,%ecx
movl 2(rPC),%eax # eax<- BBBBBBBB
movl offThread_methodClassDex(%ecx),%ecx# ecx<- self->methodClassDex
movl offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings
movl (%ecx,%eax,4),%eax # eax<- rResString[BBBB]
FETCH_INST_OPCODE 3 %ecx
testl %eax,%eax # resolved yet?
je .LOP_CONST_STRING_JUMBO_resolve
SET_VREG %eax rINST # vAA<- rResString[BBBB]
ADVANCE_PC 3
GOTO_NEXT_R %ecx
/* This is the less common path, so we'll redo some work
here rather than force spills on the common path */
.LOP_CONST_STRING_JUMBO_resolve:
movl rSELF,%eax
EXPORT_PC
movl offThread_method(%eax),%eax # eax<- self->method
movl 2(rPC),%ecx # ecx<- BBBBBBBB
movl offMethod_clazz(%eax),%eax
movl %ecx,OUT_ARG1(%esp)
movl %eax,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveString # go resolve
UNSPILL(rIBASE)
testl %eax,%eax # failed?
je common_exceptionThrown
FETCH_INST_OPCODE 3 %ecx
SET_VREG %eax rINST
ADVANCE_PC 3
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_CONST_CLASS: /* 0x1c */
/* File: x86/OP_CONST_CLASS.S */
/* const/class vAA, Class@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- BBBB
movl offThread_methodClassDex(%ecx),%ecx# ecx<- self->methodClassDex
movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- dvmDex->pResClasses
movl (%ecx,%eax,4),%eax # eax<- rResClasses[BBBB]
testl %eax,%eax # resolved yet?
je .LOP_CONST_CLASS_resolve
FETCH_INST_OPCODE 2 %ecx
SET_VREG %eax rINST # vAA<- rResClasses[BBBB]
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* This is the less common path, so we'll redo some work
here rather than force spills on the common path */
.LOP_CONST_CLASS_resolve:
movl rSELF,%eax
EXPORT_PC
movl offThread_method(%eax),%eax # eax<- self->method
movl $1,OUT_ARG2(%esp) # true
movzwl 2(rPC),%ecx # ecx<- BBBB
movl offMethod_clazz(%eax),%eax
movl %ecx,OUT_ARG1(%esp)
movl %eax,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveClass # go resolve
UNSPILL(rIBASE)
testl %eax,%eax # failed?
je common_exceptionThrown
FETCH_INST_OPCODE 2 %ecx
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MONITOR_ENTER: /* 0x1d */
/* File: x86/OP_MONITOR_ENTER.S */
/*
* Synchronize on an object.
*/
/* monitor-enter vAA */
movl rSELF,%ecx
GET_VREG_R %eax rINST # eax<- vAA
FETCH_INST_WORD 1
testl %eax,%eax # null object?
EXPORT_PC # need for precise GC
je common_errNullObject
movl %ecx,OUT_ARG0(%esp)
movl %eax,OUT_ARG1(%esp)
SPILL(rIBASE)
call dvmLockObject # dvmLockObject(self,object)
UNSPILL(rIBASE)
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_MONITOR_EXIT: /* 0x1e */
/* File: x86/OP_MONITOR_EXIT.S */
/*
* Unlock an object.
*
* Exceptions that occur when unlocking a monitor need to appear as
* if they happened at the following instruction. See the Dalvik
* instruction spec.
*/
/* monitor-exit vAA */
GET_VREG_R %eax rINST
movl rSELF,%ecx
EXPORT_PC
testl %eax,%eax # null object?
je .LOP_MONITOR_EXIT_errNullObject # go if so
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmUnlockObject # unlock(self,obj)
UNSPILL(rIBASE)
FETCH_INST_OPCODE 1 %ecx
testl %eax,%eax # success?
ADVANCE_PC 1
je common_exceptionThrown # no, exception pending
GOTO_NEXT_R %ecx
.LOP_MONITOR_EXIT_errNullObject:
ADVANCE_PC 1 # advance before throw
jmp common_errNullObject
/* ------------------------------ */
.L_OP_CHECK_CAST: /* 0x1f */
/* File: x86/OP_CHECK_CAST.S */
/*
* Check to see if a cast from one class to another is allowed.
*/
/* check-cast vAA, class@BBBB */
movl rSELF,%ecx
GET_VREG_R rINST,rINST # rINST<- vAA (object)
movzwl 2(rPC),%eax # eax<- BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
testl rINST,rINST # is oject null?
movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
je .LOP_CHECK_CAST_okay # null obj, cast always succeeds
movl (%ecx,%eax,4),%eax # eax<- resolved class
movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz
testl %eax,%eax # have we resolved this before?
je .LOP_CHECK_CAST_resolve # no, go do it now
.LOP_CHECK_CAST_resolved:
cmpl %eax,%ecx # same class (trivial success)?
jne .LOP_CHECK_CAST_fullcheck # no, do full check
.LOP_CHECK_CAST_okay:
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/*
* Trivial test failed, need to perform full check. This is common.
* ecx holds obj->clazz
* eax holds class resolved from BBBB
* rINST holds object
*/
.LOP_CHECK_CAST_fullcheck:
movl %eax,sReg0 # we'll need the desired class on failure
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmInstanceofNonTrivial # eax<- boolean result
UNSPILL(rIBASE)
testl %eax,%eax # failed?
jne .LOP_CHECK_CAST_okay # no, success
# A cast has failed. We need to throw a ClassCastException.
EXPORT_PC
movl offObject_clazz(rINST),%eax
movl %eax,OUT_ARG0(%esp) # arg0<- obj->clazz
movl sReg0,%ecx
movl %ecx,OUT_ARG1(%esp) # arg1<- desired class
call dvmThrowClassCastException
jmp common_exceptionThrown
/*
* Resolution required. This is the least-likely path, and we're
* going to have to recreate some data.
*
* rINST holds object
*/
.LOP_CHECK_CAST_resolve:
movl rSELF,%ecx
EXPORT_PC
movzwl 2(rPC),%eax # eax<- BBBB
movl offThread_method(%ecx),%ecx # ecx<- self->method
movl %eax,OUT_ARG1(%esp) # arg1<- BBBB
movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
movl $0,OUT_ARG2(%esp) # arg2<- false
movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz
SPILL(rIBASE)
call dvmResolveClass # eax<- resolved ClassObject ptr
UNSPILL(rIBASE)
testl %eax,%eax # got null?
je common_exceptionThrown # yes, handle exception
movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz
jmp .LOP_CHECK_CAST_resolved # pick up where we left off
/* ------------------------------ */
.L_OP_INSTANCE_OF: /* 0x20 */
/* File: x86/OP_INSTANCE_OF.S */
/*
* Check to see if an object reference is an instance of a class.
*
* Most common situation is a non-null object, being compared against
* an already-resolved class.
*/
/* instance-of vA, vB, class@CCCC */
movl rINST,%eax # eax<- BA
sarl $4,%eax # eax<- B
GET_VREG_R %eax %eax # eax<- vB (obj)
movl rSELF,%ecx
testl %eax,%eax # object null?
movl offThread_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
SPILL(rIBASE) # preserve rIBASE
je .LOP_INSTANCE_OF_store # null obj, not instance, store it
movzwl 2(rPC),rIBASE # rIBASE<- CCCC
movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
movl (%ecx,rIBASE,4),%ecx # ecx<- resolved class
movl offObject_clazz(%eax),%eax # eax<- obj->clazz
testl %ecx,%ecx # have we resolved this before?
je .LOP_INSTANCE_OF_resolve # not resolved, do it now
.LOP_INSTANCE_OF_resolved: # eax<- obj->clazz, ecx<- resolved class
cmpl %eax,%ecx # same class (trivial success)?
je .LOP_INSTANCE_OF_trivial # yes, trivial finish
/*
* Trivial test failed, need to perform full check. This is common.
* eax holds obj->clazz
* ecx holds class resolved from BBBB
* rINST has BA
*/
movl %eax,OUT_ARG0(%esp)
movl %ecx,OUT_ARG1(%esp)
call dvmInstanceofNonTrivial # eax<- boolean result
# fall through to OP_INSTANCE_OF_store
/*
* eax holds boolean result
* rINST holds BA
*/
.LOP_INSTANCE_OF_store:
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
andb $0xf,rINSTbl # <- A
ADVANCE_PC 2
SET_VREG %eax rINST # vA<- eax
GOTO_NEXT_R %ecx
/*
* Trivial test succeeded, save and bail.
* r9 holds A
*/
.LOP_INSTANCE_OF_trivial:
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
andb $0xf,rINSTbl # <- A
ADVANCE_PC 2
movl $1,%eax
SET_VREG %eax rINST # vA<- true
GOTO_NEXT_R %ecx
/*
* Resolution required. This is the least-likely path.
*
* rIBASE holds BBBB
* rINST holds BA
*/
.LOP_INSTANCE_OF_resolve:
movl rIBASE,OUT_ARG1(%esp) # arg1<- BBBB
movl rSELF,%ecx
movl offThread_method(%ecx),%ecx
movl $1,OUT_ARG2(%esp) # arg2<- true
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
EXPORT_PC
movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz
call dvmResolveClass # eax<- resolved ClassObject ptr
testl %eax,%eax # success?
je common_exceptionThrown # no, handle exception
/* Now, we need to sync up with fast path. We need eax to
* hold the obj->clazz, and ecx to hold the resolved class
*/
movl %eax,%ecx # ecx<- resolved class
movl rINST,%eax # eax<- BA
sarl $4,%eax # eax<- B
GET_VREG_R %eax %eax # eax<- vB (obj)
movl offObject_clazz(%eax),%eax # eax<- obj->clazz
jmp .LOP_INSTANCE_OF_resolved
/* ------------------------------ */
.L_OP_ARRAY_LENGTH: /* 0x21 */
/* File: x86/OP_ARRAY_LENGTH.S */
/*
* Return the length of an array.
*/
mov rINST,%eax # eax<- BA
sarl $4,rINST # rINST<- B
GET_VREG_R %ecx rINST # ecx<- vB (object ref)
andb $0xf,%al # eax<- A
testl %ecx,%ecx # is null?
je common_errNullObject
movl offArrayObject_length(%ecx),rINST
FETCH_INST_OPCODE 1 %ecx
ADVANCE_PC 1
SET_VREG rINST %eax
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_NEW_INSTANCE: /* 0x22 */
/* File: x86/OP_NEW_INSTANCE.S */
/*
* Create a new instance of a class.
*/
/* new-instance vAA, class@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
SPILL(rIBASE)
movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
EXPORT_PC
movl (%ecx,%eax,4),%ecx # ecx<- resolved class
testl %ecx,%ecx # resolved?
je .LOP_NEW_INSTANCE_resolve # no, go do it
.LOP_NEW_INSTANCE_resolved: # on entry, ecx<- class
cmpb $CLASS_INITIALIZED,offClassObject_status(%ecx)
jne .LOP_NEW_INSTANCE_needinit
.LOP_NEW_INSTANCE_initialized: # on entry, ecx<- class
movl $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
call dvmAllocObject # eax<- new object
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
testl %eax,%eax # success?
je common_exceptionThrown # no, bail out
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/*
* Class initialization required.
*
* ecx holds class object
*/
.LOP_NEW_INSTANCE_needinit:
SPILL_TMP1(%ecx) # save object
movl %ecx,OUT_ARG0(%esp)
call dvmInitClass # initialize class
UNSPILL_TMP1(%ecx) # restore object
testl %eax,%eax # success?
jne .LOP_NEW_INSTANCE_initialized # success, continue
jmp common_exceptionThrown # go deal with init exception
/*
* Resolution required. This is the least-likely path.
*
*/
.LOP_NEW_INSTANCE_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax
movl offThread_method(%ecx),%ecx # ecx<- self->method
movl %eax,OUT_ARG1(%esp)
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl $0,OUT_ARG2(%esp)
movl %ecx,OUT_ARG0(%esp)
call dvmResolveClass # call(clazz,off,flags)
movl %eax,%ecx # ecx<- resolved ClassObject ptr
testl %ecx,%ecx # success?
jne .LOP_NEW_INSTANCE_resolved # good to go
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_NEW_ARRAY: /* 0x23 */
/* File: x86/OP_NEW_ARRAY.S */
/*
* Allocate an array of objects, specified with the array class
* and a count.
*
* The verifier guarantees that this is an array class, so we don't
* check for it here.
*/
/* new-array vA, vB, class@CCCC */
movl rSELF,%ecx
EXPORT_PC
movl offThread_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
movzwl 2(rPC),%eax # eax<- CCCC
movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
SPILL(rIBASE)
movl (%ecx,%eax,4),%ecx # ecx<- resolved class
movzbl rINSTbl,%eax
sarl $4,%eax # eax<- B
GET_VREG_R %eax %eax # eax<- vB (array length)
andb $0xf,rINSTbl # rINST<- A
testl %eax,%eax
js common_errNegativeArraySize # bail, passing len in eax
testl %ecx,%ecx # already resolved?
jne .LOP_NEW_ARRAY_finish # yes, fast path
/*
* Resolve class. (This is an uncommon case.)
* ecx holds class (null here)
* eax holds array length (vB)
*/
movl rSELF,%ecx
SPILL_TMP1(%eax) # save array length
movl offThread_method(%ecx),%ecx # ecx<- self->method
movzwl 2(rPC),%eax # eax<- CCCC
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl $0,OUT_ARG2(%esp)
movl %ecx,OUT_ARG0(%esp)
call dvmResolveClass # eax<- call(clazz,ref,flag)
movl %eax,%ecx
UNSPILL_TMP1(%eax)
testl %ecx,%ecx # successful resolution?
je common_exceptionThrown # no, bail.
# fall through to OP_NEW_ARRAY_finish
/*
* Finish allocation
*
* ecx holds class
* eax holds array length (vB)
*/
.LOP_NEW_ARRAY_finish:
movl %ecx,OUT_ARG0(%esp)
movl %eax,OUT_ARG1(%esp)
movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp)
call dvmAllocArrayByClass # eax<- call(clazz,length,flags)
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
testl %eax,%eax # failed?
je common_exceptionThrown # yup - go handle
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
/* File: x86/OP_FILLED_NEW_ARRAY.S */
/*
* Create a new array with elements filled from registers.
*
* for: filled-new-array, filled-new-array/range
*/
/* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
/* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
movl rSELF,%eax
movl offThread_methodClassDex(%eax),%eax # eax<- pDvmDex
movzwl 2(rPC),%ecx # ecx<- BBBB
movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses
SPILL(rIBASE) # preserve rIBASE
movl (%eax,%ecx,4),%eax # eax<- resolved class
EXPORT_PC
testl %eax,%eax # already resolved?
jne .LOP_FILLED_NEW_ARRAY_continue # yes, continue
# less frequent path, so we'll redo some work
movl rSELF,%eax
movl $0,OUT_ARG2(%esp) # arg2<- false
movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB
movl offThread_method(%eax),%eax # eax<- self->method
movl offMethod_clazz(%eax),%eax # eax<- method->clazz
movl %eax,OUT_ARG0(%esp) # arg0<- clazz
call dvmResolveClass # eax<- call(clazz,ref,flag)
testl %eax,%eax # null?
je common_exceptionThrown # yes, handle it
# note: fall through to .LOP_FILLED_NEW_ARRAY_continue
/*
* On entry:
* eax holds array class [r0]
* rINST holds AA or BB [r10]
* ecx is scratch
*/
.LOP_FILLED_NEW_ARRAY_continue:
movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor
movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags
movzbl 1(%ecx),%ecx # ecx<- descriptor[1]
movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass
movl rSELF,%eax
cmpb $'I',%cl # supported?
je 1f
cmpb $'L',%cl
je 1f
cmpb $'[',%cl
jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet
1:
movl %ecx,offThread_retval+4(%eax) # save type
.if (!0)
SPILL_TMP1(rINST) # save copy, need "B" later
sarl $4,rINST
.endif
movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length)
call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags)
movl rSELF,%ecx
testl %eax,%eax # alloc successful?
je common_exceptionThrown # no, handle exception
movl %eax,offThread_retval(%ecx) # retval.l<- new array
movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC
leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents
/* at this point:
* eax is pointer to tgt
* rINST is length
* ecx is FEDC or CCCC
* TMP_SPILL1 is BA
* We now need to copy values from registers into the array
*/
.if 0
# set up src pointer
SPILL_TMP2(%esi)
SPILL_TMP3(%edi)
leal (rFP,%ecx,4),%esi # set up src ptr
movl %eax,%edi # set up dst ptr
movl rINST,%ecx # load count register
rep
movsd
UNSPILL_TMP2(%esi)
UNSPILL_TMP3(%edi)
movl rSELF,%ecx
movl offThread_retval+4(%ecx),%eax # eax<- type
.else
testl rINST,rINST
je 4f
UNSPILL_TMP1(rIBASE) # restore "BA"
andl $0x0f,rIBASE # rIBASE<- 0000000A
sall $16,rIBASE # rIBASE<- 000A0000
orl %ecx,rIBASE # rIBASE<- 000AFEDC
3:
movl $0xf,%ecx
andl rIBASE,%ecx # ecx<- next reg to load
GET_VREG_R %ecx %ecx
shrl $4,rIBASE
leal 4(%eax),%eax
movl %ecx,-4(%eax)
sub $1,rINST
jne 3b
4:
movl rSELF,%ecx
movl offThread_retval+4(%ecx),%eax # eax<- type
.endif
cmpb $'I',%al # Int array?
je 5f # skip card mark if so
movl offThread_retval(%ecx),%eax # eax<- object head
movl offThread_cardTable(%ecx),%ecx # card table base
shrl $GC_CARD_SHIFT,%eax # convert to card num
movb %cl,(%ecx,%eax) # mark card based on object head
5:
UNSPILL(rIBASE) # restore rIBASE
FETCH_INST_OPCODE 3 %ecx
ADVANCE_PC 3
GOTO_NEXT_R %ecx
/*
* Throw an exception indicating that we have not implemented this
* mode of filled-new-array.
*/
.LOP_FILLED_NEW_ARRAY_notimpl:
movl $.LstrFilledNewArrayNotImplA,%eax
movl %eax,OUT_ARG0(%esp)
call dvmThrowInternalError
jmp common_exceptionThrown
/* ------------------------------ */
.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
/* File: x86/OP_FILLED_NEW_ARRAY_RANGE.S */
/* File: x86/OP_FILLED_NEW_ARRAY.S */
/*
* Create a new array with elements filled from registers.
*
* for: filled-new-array, filled-new-array/range
*/
/* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
/* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
movl rSELF,%eax
movl offThread_methodClassDex(%eax),%eax # eax<- pDvmDex
movzwl 2(rPC),%ecx # ecx<- BBBB
movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses
SPILL(rIBASE) # preserve rIBASE
movl (%eax,%ecx,4),%eax # eax<- resolved class
EXPORT_PC
testl %eax,%eax # already resolved?
jne .LOP_FILLED_NEW_ARRAY_RANGE_continue # yes, continue
# less frequent path, so we'll redo some work
movl rSELF,%eax
movl $0,OUT_ARG2(%esp) # arg2<- false
movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB
movl offThread_method(%eax),%eax # eax<- self->method
movl offMethod_clazz(%eax),%eax # eax<- method->clazz
movl %eax,OUT_ARG0(%esp) # arg0<- clazz
call dvmResolveClass # eax<- call(clazz,ref,flag)
testl %eax,%eax # null?
je common_exceptionThrown # yes, handle it
# note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue
/*
* On entry:
* eax holds array class [r0]
* rINST holds AA or BB [r10]
* ecx is scratch
*/
.LOP_FILLED_NEW_ARRAY_RANGE_continue:
movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor
movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags
movzbl 1(%ecx),%ecx # ecx<- descriptor[1]
movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass
movl rSELF,%eax
cmpb $'I',%cl # supported?
je 1f
cmpb $'L',%cl
je 1f
cmpb $'[',%cl
jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet
1:
movl %ecx,offThread_retval+4(%eax) # save type
.if (!1)
SPILL_TMP1(rINST) # save copy, need "B" later
sarl $4,rINST
.endif
movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length)
call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags)
movl rSELF,%ecx
testl %eax,%eax # alloc successful?
je common_exceptionThrown # no, handle exception
movl %eax,offThread_retval(%ecx) # retval.l<- new array
movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC
leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents
/* at this point:
* eax is pointer to tgt
* rINST is length
* ecx is FEDC or CCCC
* TMP_SPILL1 is BA
* We now need to copy values from registers into the array
*/
.if 1
# set up src pointer
SPILL_TMP2(%esi)
SPILL_TMP3(%edi)
leal (rFP,%ecx,4),%esi # set up src ptr
movl %eax,%edi # set up dst ptr
movl rINST,%ecx # load count register
rep
movsd
UNSPILL_TMP2(%esi)
UNSPILL_TMP3(%edi)
movl rSELF,%ecx
movl offThread_retval+4(%ecx),%eax # eax<- type
.else
testl rINST,rINST
je 4f
UNSPILL_TMP1(rIBASE) # restore "BA"
andl $0x0f,rIBASE # rIBASE<- 0000000A
sall $16,rIBASE # rIBASE<- 000A0000
orl %ecx,rIBASE # rIBASE<- 000AFEDC
3:
movl $0xf,%ecx
andl rIBASE,%ecx # ecx<- next reg to load
GET_VREG_R %ecx %ecx
shrl $4,rIBASE
leal 4(%eax),%eax
movl %ecx,-4(%eax)
sub $1,rINST
jne 3b
4:
movl rSELF,%ecx
movl offThread_retval+4(%ecx),%eax # eax<- type
.endif
cmpb $'I',%al # Int array?
je 5f # skip card mark if so
movl offThread_retval(%ecx),%eax # eax<- object head
movl offThread_cardTable(%ecx),%ecx # card table base
shrl $GC_CARD_SHIFT,%eax # convert to card num
movb %cl,(%ecx,%eax) # mark card based on object head
5:
UNSPILL(rIBASE) # restore rIBASE
FETCH_INST_OPCODE 3 %ecx
ADVANCE_PC 3
GOTO_NEXT_R %ecx
/*
* Throw an exception indicating that we have not implemented this
* mode of filled-new-array.
*/
.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
movl $.LstrFilledNewArrayNotImplA,%eax
movl %eax,OUT_ARG0(%esp)
call dvmThrowInternalError
jmp common_exceptionThrown
/* ------------------------------ */
.L_OP_FILL_ARRAY_DATA: /* 0x26 */
/* File: x86/OP_FILL_ARRAY_DATA.S */
/* fill-array-data vAA, +BBBBBBBB */
movl 2(rPC),%ecx # ecx<- BBBBbbbb
leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2
GET_VREG_R %eax rINST
EXPORT_PC
movl %eax,OUT_ARG0(%esp)
movl %ecx,OUT_ARG1(%esp)
SPILL(rIBASE)
call dvmInterpHandleFillArrayData
UNSPILL(rIBASE)
FETCH_INST_OPCODE 3 %ecx
testl %eax,%eax # exception thrown?
je common_exceptionThrown
ADVANCE_PC 3
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_THROW: /* 0x27 */
/* File: x86/OP_THROW.S */
/*
* Throw an exception object in the current thread.
*/
/* throw vAA */
EXPORT_PC
GET_VREG_R %eax rINST # eax<- exception object
movl rSELF,%ecx # ecx<- self
testl %eax,%eax # null object?
je common_errNullObject
movl %eax,offThread_exception(%ecx) # thread->exception<- obj
jmp common_exceptionThrown
/* ------------------------------ */
.L_OP_GOTO: /* 0x28 */
/* File: x86/OP_GOTO.S */
/*
* Unconditional branch, 8-bit offset.
*
* The branch distance is a signed code-unit offset, which we need to
* double to get a byte offset.
*/
/* goto +AA */
movsbl rINSTbl,rINST # ebx<- ssssssAA
testl rINST,rINST # test for <0
js common_backwardBranch
movl rINST,%eax
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_GOTO_16: /* 0x29 */
/* File: x86/OP_GOTO_16.S */
/*
* Unconditional branch, 16-bit offset.
*
* The branch distance is a signed code-unit offset
*/
/* goto/16 +AAAA */
movswl 2(rPC),rINST # rINST<- ssssAAAA
testl rINST,rINST # test for <0
js common_backwardBranch
movl rINST,%eax
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_GOTO_32: /* 0x2a */
/* File: x86/OP_GOTO_32.S */
/*
* Unconditional branch, 32-bit offset.
*
* The branch distance is a signed code-unit offset.
*
* Unlike most opcodes, this one is allowed to branch to itself, so
* our "backward branch" test must be "<=0" instead of "<0".
*/
/* goto/32 AAAAAAAA */
movl 2(rPC),rINST # rINST<- AAAAAAAA
cmpl $0,rINST # test for <= 0
jle common_backwardBranch
movl rINST,%eax
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_PACKED_SWITCH: /* 0x2b */
/* File: x86/OP_PACKED_SWITCH.S */
/*
* Handle a packed-switch or sparse-switch instruction. In both cases
* we decode it and hand it off to a helper function.
*
* We don't really expect backward branches in a switch statement, but
* they're perfectly legal, so we check for them here.
*
* for: packed-switch, sparse-switch
*/
/* op vAA, +BBBB */
movl 2(rPC),%ecx # ecx<- BBBBbbbb
GET_VREG_R %eax rINST # eax<- vAA
leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2
movl %eax,OUT_ARG1(%esp) # ARG1<- vAA
movl %ecx,OUT_ARG0(%esp) # ARG0<- switchData
SPILL(rIBASE)
call dvmInterpHandlePackedSwitch
UNSPILL(rIBASE)
testl %eax,%eax
movl %eax,rINST # set up word offset
jle common_backwardBranch # check on special actions
ADVANCE_PC_INDEXED rINST
FETCH_INST
GOTO_NEXT
/* ------------------------------ */
.L_OP_SPARSE_SWITCH: /* 0x2c */
/* File: x86/OP_SPARSE_SWITCH.S */
/* File: x86/OP_PACKED_SWITCH.S */
/*
* Handle a packed-switch or sparse-switch instruction. In both cases
* we decode it and hand it off to a helper function.
*
* We don't really expect backward branches in a switch statement, but
* they're perfectly legal, so we check for them here.
*
* for: packed-switch, sparse-switch
*/
/* op vAA, +BBBB */
movl 2(rPC),%ecx # ecx<- BBBBbbbb
GET_VREG_R %eax rINST # eax<- vAA
leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2
movl %eax,OUT_ARG1(%esp) # ARG1<- vAA
movl %ecx,OUT_ARG0(%esp) # ARG0<- switchData
SPILL(rIBASE)
call dvmInterpHandleSparseSwitch
UNSPILL(rIBASE)
testl %eax,%eax
movl %eax,rINST # set up word offset
jle common_backwardBranch # check on special actions
ADVANCE_PC_INDEXED rINST
FETCH_INST
GOTO_NEXT
/* ------------------------------ */
.L_OP_CMPL_FLOAT: /* 0x2d */
/* File: x86/OP_CMPL_FLOAT.S */
/* File: x86/OP_CMPG_DOUBLE.S */
/* float/double_cmp[gl] vAA, vBB, vCC */
movzbl 3(rPC),%eax # eax<- CC
movzbl 2(rPC),%ecx # ecx<- BB
.if 0
fldl (rFP,%eax,4)
fldl (rFP,%ecx,4)
.else
flds (rFP,%eax,4)
flds (rFP,%ecx,4)
.endif
xorl %ecx,%ecx
fucompp # z if equal, p set if NaN, c set if st0 < st1
fnstsw %ax
sahf
FETCH_INST_OPCODE 2 %eax
jp .LOP_CMPL_FLOAT_isNaN
je .LOP_CMPL_FLOAT_finish
sbbl %ecx,%ecx
jb .LOP_CMPL_FLOAT_finish
incl %ecx
.LOP_CMPL_FLOAT_finish:
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
.LOP_CMPL_FLOAT_isNaN:
movl $-1,%ecx
jmp .LOP_CMPL_FLOAT_finish
/* ------------------------------ */
.L_OP_CMPG_FLOAT: /* 0x2e */
/* File: x86/OP_CMPG_FLOAT.S */
/* File: x86/OP_CMPG_DOUBLE.S */
/* float/double_cmp[gl] vAA, vBB, vCC */
movzbl 3(rPC),%eax # eax<- CC
movzbl 2(rPC),%ecx # ecx<- BB
.if 0
fldl (rFP,%eax,4)
fldl (rFP,%ecx,4)
.else
flds (rFP,%eax,4)
flds (rFP,%ecx,4)
.endif
xorl %ecx,%ecx
fucompp # z if equal, p set if NaN, c set if st0 < st1
fnstsw %ax
sahf
FETCH_INST_OPCODE 2 %eax
jp .LOP_CMPG_FLOAT_isNaN
je .LOP_CMPG_FLOAT_finish
sbbl %ecx,%ecx
jb .LOP_CMPG_FLOAT_finish
incl %ecx
.LOP_CMPG_FLOAT_finish:
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
.LOP_CMPG_FLOAT_isNaN:
movl $1,%ecx
jmp .LOP_CMPG_FLOAT_finish
/* ------------------------------ */
.L_OP_CMPL_DOUBLE: /* 0x2f */
/* File: x86/OP_CMPL_DOUBLE.S */
/* File: x86/OP_CMPG_DOUBLE.S */
/* float/double_cmp[gl] vAA, vBB, vCC */
movzbl 3(rPC),%eax # eax<- CC
movzbl 2(rPC),%ecx # ecx<- BB
.if 1
fldl (rFP,%eax,4)
fldl (rFP,%ecx,4)
.else
flds (rFP,%eax,4)
flds (rFP,%ecx,4)
.endif
xorl %ecx,%ecx
fucompp # z if equal, p set if NaN, c set if st0 < st1
fnstsw %ax
sahf
FETCH_INST_OPCODE 2 %eax
jp .LOP_CMPL_DOUBLE_isNaN
je .LOP_CMPL_DOUBLE_finish
sbbl %ecx,%ecx
jb .LOP_CMPL_DOUBLE_finish
incl %ecx
.LOP_CMPL_DOUBLE_finish:
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
.LOP_CMPL_DOUBLE_isNaN:
movl $-1,%ecx
jmp .LOP_CMPL_DOUBLE_finish
/* ------------------------------ */
.L_OP_CMPG_DOUBLE: /* 0x30 */
/* File: x86/OP_CMPG_DOUBLE.S */
/* float/double_cmp[gl] vAA, vBB, vCC */
movzbl 3(rPC),%eax # eax<- CC
movzbl 2(rPC),%ecx # ecx<- BB
.if 1
fldl (rFP,%eax,4)
fldl (rFP,%ecx,4)
.else
flds (rFP,%eax,4)
flds (rFP,%ecx,4)
.endif
xorl %ecx,%ecx
fucompp # z if equal, p set if NaN, c set if st0 < st1
fnstsw %ax
sahf
FETCH_INST_OPCODE 2 %eax
jp .LOP_CMPG_DOUBLE_isNaN
je .LOP_CMPG_DOUBLE_finish
sbbl %ecx,%ecx
jb .LOP_CMPG_DOUBLE_finish
incl %ecx
.LOP_CMPG_DOUBLE_finish:
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
.LOP_CMPG_DOUBLE_isNaN:
movl $1,%ecx
jmp .LOP_CMPG_DOUBLE_finish
/* ------------------------------ */
.L_OP_CMP_LONG: /* 0x31 */
/* File: x86/OP_CMP_LONG.S */
/*
* Compare two 64-bit values. Puts 0, 1, or -1 into the destination
* register based on the results of the comparison.
*/
// TUNING: rework to avoid rIBASE spill
/* cmp-long vAA, vBB, vCC */
movzbl 2(rPC),%ecx # ecx<- BB
SPILL(rIBASE)
movzbl 3(rPC),rIBASE # rIBASE- CC
GET_VREG_WORD %eax %ecx,1 # eax<- v[BB+1]
GET_VREG_WORD %ecx %ecx 0 # ecx<- v[BB+0]
cmpl 4(rFP,rIBASE,4),%eax
jl .LOP_CMP_LONG_smaller
jg .LOP_CMP_LONG_bigger
sub (rFP,rIBASE,4),%ecx
ja .LOP_CMP_LONG_bigger
jb .LOP_CMP_LONG_smaller
SET_VREG %ecx rINST
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
.LOP_CMP_LONG_bigger:
movl $1,%ecx
SET_VREG %ecx rINST
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
.LOP_CMP_LONG_smaller:
movl $-1,%ecx
SET_VREG %ecx rINST
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_IF_EQ: /* 0x32 */
/* File: x86/OP_IF_EQ.S */
/* File: x86/bincmp.S */
/*
* Generic two-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
*/
/* if-cmp vA, vB, +CCCC */
movzx rINSTbl,%ecx # ecx <- A+
andb $0xf,%cl # ecx <- A
GET_VREG_R %eax %ecx # eax <- vA
sarl $4,rINST # rINST<- B
cmpl (rFP,rINST,4),%eax # compare (vA, vB)
movswl 2(rPC),rINST # Get signed branch offset
movl $2,%eax # assume not taken
jne 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_NE: /* 0x33 */
/* File: x86/OP_IF_NE.S */
/* File: x86/bincmp.S */
/*
* Generic two-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
*/
/* if-cmp vA, vB, +CCCC */
movzx rINSTbl,%ecx # ecx <- A+
andb $0xf,%cl # ecx <- A
GET_VREG_R %eax %ecx # eax <- vA
sarl $4,rINST # rINST<- B
cmpl (rFP,rINST,4),%eax # compare (vA, vB)
movswl 2(rPC),rINST # Get signed branch offset
movl $2,%eax # assume not taken
je 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_LT: /* 0x34 */
/* File: x86/OP_IF_LT.S */
/* File: x86/bincmp.S */
/*
* Generic two-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
*/
/* if-cmp vA, vB, +CCCC */
movzx rINSTbl,%ecx # ecx <- A+
andb $0xf,%cl # ecx <- A
GET_VREG_R %eax %ecx # eax <- vA
sarl $4,rINST # rINST<- B
cmpl (rFP,rINST,4),%eax # compare (vA, vB)
movswl 2(rPC),rINST # Get signed branch offset
movl $2,%eax # assume not taken
jge 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_GE: /* 0x35 */
/* File: x86/OP_IF_GE.S */
/* File: x86/bincmp.S */
/*
* Generic two-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
*/
/* if-cmp vA, vB, +CCCC */
movzx rINSTbl,%ecx # ecx <- A+
andb $0xf,%cl # ecx <- A
GET_VREG_R %eax %ecx # eax <- vA
sarl $4,rINST # rINST<- B
cmpl (rFP,rINST,4),%eax # compare (vA, vB)
movswl 2(rPC),rINST # Get signed branch offset
movl $2,%eax # assume not taken
jl 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_GT: /* 0x36 */
/* File: x86/OP_IF_GT.S */
/* File: x86/bincmp.S */
/*
* Generic two-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
*/
/* if-cmp vA, vB, +CCCC */
movzx rINSTbl,%ecx # ecx <- A+
andb $0xf,%cl # ecx <- A
GET_VREG_R %eax %ecx # eax <- vA
sarl $4,rINST # rINST<- B
cmpl (rFP,rINST,4),%eax # compare (vA, vB)
movswl 2(rPC),rINST # Get signed branch offset
movl $2,%eax # assume not taken
jle 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_LE: /* 0x37 */
/* File: x86/OP_IF_LE.S */
/* File: x86/bincmp.S */
/*
* Generic two-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
*/
/* if-cmp vA, vB, +CCCC */
movzx rINSTbl,%ecx # ecx <- A+
andb $0xf,%cl # ecx <- A
GET_VREG_R %eax %ecx # eax <- vA
sarl $4,rINST # rINST<- B
cmpl (rFP,rINST,4),%eax # compare (vA, vB)
movswl 2(rPC),rINST # Get signed branch offset
movl $2,%eax # assume not taken
jg 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_EQZ: /* 0x38 */
/* File: x86/OP_IF_EQZ.S */
/* File: x86/zcmp.S */
/*
* Generic one-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
*/
/* if-cmp vAA, +BBBB */
cmpl $0,(rFP,rINST,4) # compare (vA, 0)
movswl 2(rPC),rINST # fetch signed displacement
movl $2,%eax # assume branch not taken
jne 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_NEZ: /* 0x39 */
/* File: x86/OP_IF_NEZ.S */
/* File: x86/zcmp.S */
/*
* Generic one-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
*/
/* if-cmp vAA, +BBBB */
cmpl $0,(rFP,rINST,4) # compare (vA, 0)
movswl 2(rPC),rINST # fetch signed displacement
movl $2,%eax # assume branch not taken
je 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_LTZ: /* 0x3a */
/* File: x86/OP_IF_LTZ.S */
/* File: x86/zcmp.S */
/*
* Generic one-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
*/
/* if-cmp vAA, +BBBB */
cmpl $0,(rFP,rINST,4) # compare (vA, 0)
movswl 2(rPC),rINST # fetch signed displacement
movl $2,%eax # assume branch not taken
jge 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_GEZ: /* 0x3b */
/* File: x86/OP_IF_GEZ.S */
/* File: x86/zcmp.S */
/*
* Generic one-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
*/
/* if-cmp vAA, +BBBB */
cmpl $0,(rFP,rINST,4) # compare (vA, 0)
movswl 2(rPC),rINST # fetch signed displacement
movl $2,%eax # assume branch not taken
jl 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_GTZ: /* 0x3c */
/* File: x86/OP_IF_GTZ.S */
/* File: x86/zcmp.S */
/*
* Generic one-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
*/
/* if-cmp vAA, +BBBB */
cmpl $0,(rFP,rINST,4) # compare (vA, 0)
movswl 2(rPC),rINST # fetch signed displacement
movl $2,%eax # assume branch not taken
jle 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_IF_LEZ: /* 0x3d */
/* File: x86/OP_IF_LEZ.S */
/* File: x86/zcmp.S */
/*
* Generic one-operand compare-and-branch operation. Provide a "revcmp"
* fragment that specifies the *reverse* comparison to perform, e.g.
* for "if-le" you would use "gt".
*
* for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
*/
/* if-cmp vAA, +BBBB */
cmpl $0,(rFP,rINST,4) # compare (vA, 0)
movswl 2(rPC),rINST # fetch signed displacement
movl $2,%eax # assume branch not taken
jg 1f
testl rINST,rINST
js common_backwardBranch
movl rINST,%eax
1:
FETCH_INST_INDEXED %eax
ADVANCE_PC_INDEXED %eax
GOTO_NEXT
/* ------------------------------ */
.L_OP_UNUSED_3E: /* 0x3e */
/* File: x86/OP_UNUSED_3E.S */
/* File: x86/unused.S */
jmp common_abort
/* ------------------------------ */
.L_OP_UNUSED_3F: /* 0x3f */
/* File: x86/OP_UNUSED_3F.S */
/* File: x86/unused.S */
jmp common_abort
/* ------------------------------ */
.L_OP_UNUSED_40: /* 0x40 */
/* File: x86/OP_UNUSED_40.S */
/* File: x86/unused.S */
jmp common_abort
/* ------------------------------ */
.L_OP_UNUSED_41: /* 0x41 */
/* File: x86/OP_UNUSED_41.S */
/* File: x86/unused.S */
jmp common_abort
/* ------------------------------ */
.L_OP_UNUSED_42: /* 0x42 */
/* File: x86/OP_UNUSED_42.S */
/* File: x86/unused.S */
jmp common_abort
/* ------------------------------ */
.L_OP_UNUSED_43: /* 0x43 */
/* File: x86/OP_UNUSED_43.S */
/* File: x86/unused.S */
jmp common_abort
/* ------------------------------ */
.L_OP_AGET: /* 0x44 */
/* File: x86/OP_AGET.S */
/*
* Array get, 32 bits or less. vAA <- vBB[vCC].
*
* for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects
# arrayObj in eax
# index in ecx
movl offArrayObject_contents(%eax,%ecx,4),%eax
.LOP_AGET_finish:
FETCH_INST_OPCODE 2 %ecx
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_AGET_WIDE: /* 0x45 */
/* File: x86/OP_AGET_WIDE.S */
/*
* Array get, 64 bits. vAA <- vBB[vCC].
*
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects
# arrayObj in eax
# index in ecx
leal offArrayObject_contents(%eax,%ecx,8),%eax
movl (%eax),%ecx
movl 4(%eax),%eax
SET_VREG_WORD %ecx rINST 0
SET_VREG_WORD %eax rINST 1
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_AGET_OBJECT: /* 0x46 */
/* File: x86/OP_AGET_OBJECT.S */
/* File: x86/OP_AGET.S */
/*
* Array get, 32 bits or less. vAA <- vBB[vCC].
*
* for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects
# arrayObj in eax
# index in ecx
movl offArrayObject_contents(%eax,%ecx,4),%eax
.LOP_AGET_OBJECT_finish:
FETCH_INST_OPCODE 2 %ecx
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_AGET_BOOLEAN: /* 0x47 */
/* File: x86/OP_AGET_BOOLEAN.S */
/* File: x86/OP_AGET.S */
/*
* Array get, 32 bits or less. vAA <- vBB[vCC].
*
* for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects
# arrayObj in eax
# index in ecx
movzbl offArrayObject_contents(%eax,%ecx,1),%eax
.LOP_AGET_BOOLEAN_finish:
FETCH_INST_OPCODE 2 %ecx
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_AGET_BYTE: /* 0x48 */
/* File: x86/OP_AGET_BYTE.S */
/* File: x86/OP_AGET.S */
/*
* Array get, 32 bits or less. vAA <- vBB[vCC].
*
* for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects
# arrayObj in eax
# index in ecx
movsbl offArrayObject_contents(%eax,%ecx,1),%eax
.LOP_AGET_BYTE_finish:
FETCH_INST_OPCODE 2 %ecx
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_AGET_CHAR: /* 0x49 */
/* File: x86/OP_AGET_CHAR.S */
/* File: x86/OP_AGET.S */
/*
* Array get, 32 bits or less. vAA <- vBB[vCC].
*
* for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects
# arrayObj in eax
# index in ecx
movzwl offArrayObject_contents(%eax,%ecx,2),%eax
.LOP_AGET_CHAR_finish:
FETCH_INST_OPCODE 2 %ecx
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_AGET_SHORT: /* 0x4a */
/* File: x86/OP_AGET_SHORT.S */
/* File: x86/OP_AGET.S */
/*
* Array get, 32 bits or less. vAA <- vBB[vCC].
*
* for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects
# arrayObj in eax
# index in ecx
movswl offArrayObject_contents(%eax,%ecx,2),%eax
.LOP_AGET_SHORT_finish:
FETCH_INST_OPCODE 2 %ecx
SET_VREG %eax rINST
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_APUT: /* 0x4b */
/* File: x86/OP_APUT.S */
/*
* Array put, 32 bits or less. vBB[vCC] <- vAA
*
* for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects:
# arrayObj in eax
# index in ecx
leal offArrayObject_contents(%eax,%ecx,4),%eax
.LOP_APUT_finish:
GET_VREG_R rINST rINST
FETCH_INST_OPCODE 2 %ecx
movl rINST,(%eax)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_APUT_WIDE: /* 0x4c */
/* File: x86/OP_APUT_WIDE.S */
/*
* Array put, 64 bits. vBB[vCC]<-vAA.
*
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects:
# arrayObj in eax
# index in ecx
leal offArrayObject_contents(%eax,%ecx,8),%eax
GET_VREG_WORD %ecx rINST 0
GET_VREG_WORD rINST rINST 1
movl %ecx,(%eax)
FETCH_INST_OPCODE 2 %ecx
movl rINST,4(%eax)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_APUT_OBJECT: /* 0x4d */
/* File: x86/OP_APUT_OBJECT.S */
/*
* Array put, 32 bits or less. vBB[vCC] <- vAA
*
* for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
GET_VREG_R rINST rINST # rINST<- vAA
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects
# arrayObj in eax
# index in ecx
/* On entry:
* eax<- array object
* ecx<- index
* rINST<- vAA
*/
leal offArrayObject_contents(%eax,%ecx,4),%ecx
testl rINST,rINST # storing null reference?
je .LOP_APUT_OBJECT_skip_check
SPILL_TMP1(%ecx) # save target address
SPILL_TMP2(%eax) # save object head
movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
movl %ecx,sReg0 # store the two classes for later
movl %eax,sReg1
SPILL(rIBASE)
call dvmCanPutArrayElement # test object type vs. array type
UNSPILL(rIBASE)
UNSPILL_TMP1(%ecx) # recover target address
testl %eax,%eax
movl rSELF,%eax
jne .LOP_APUT_OBJECT_types_okay
# The types don't match. We need to throw an ArrayStoreException.
EXPORT_PC
movl sReg0,%eax # restore the two classes...
movl %eax,OUT_ARG0(%esp)
movl sReg1,%ecx
movl %ecx,OUT_ARG1(%esp)
call dvmThrowArrayStoreException # ...and throw
jmp common_exceptionThrown
.LOP_APUT_OBJECT_types_okay:
movl offThread_cardTable(%eax),%eax # get card table base
movl rINST,(%ecx) # store into array
UNSPILL_TMP2(rINST) # recover object head
FETCH_INST_OPCODE 2 %ecx
shrl $GC_CARD_SHIFT,rINST # object head to card number
movb %al,(%eax,rINST) # mark card using object head
ADVANCE_PC 2
GOTO_NEXT_R %ecx
.LOP_APUT_OBJECT_skip_check:
movl rINST,(%ecx)
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_APUT_BOOLEAN: /* 0x4e */
/* File: x86/OP_APUT_BOOLEAN.S */
/* File: x86/OP_APUT.S */
/*
* Array put, 32 bits or less. vBB[vCC] <- vAA
*
* for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects:
# arrayObj in eax
# index in ecx
leal offArrayObject_contents(%eax,%ecx,1),%eax
.LOP_APUT_BOOLEAN_finish:
GET_VREG_R rINST rINST
FETCH_INST_OPCODE 2 %ecx
movb rINSTbl,(%eax)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_APUT_BYTE: /* 0x4f */
/* File: x86/OP_APUT_BYTE.S */
/* File: x86/OP_APUT.S */
/*
* Array put, 32 bits or less. vBB[vCC] <- vAA
*
* for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects:
# arrayObj in eax
# index in ecx
leal offArrayObject_contents(%eax,%ecx,1),%eax
.LOP_APUT_BYTE_finish:
GET_VREG_R rINST rINST
FETCH_INST_OPCODE 2 %ecx
movb rINSTbl,(%eax)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_APUT_CHAR: /* 0x50 */
/* File: x86/OP_APUT_CHAR.S */
/* File: x86/OP_APUT.S */
/*
* Array put, 32 bits or less. vBB[vCC] <- vAA
*
* for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects:
# arrayObj in eax
# index in ecx
leal offArrayObject_contents(%eax,%ecx,2),%eax
.LOP_APUT_CHAR_finish:
GET_VREG_R rINST rINST
FETCH_INST_OPCODE 2 %ecx
movw rINSTw,(%eax)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_APUT_SHORT: /* 0x51 */
/* File: x86/OP_APUT_SHORT.S */
/* File: x86/OP_APUT.S */
/*
* Array put, 32 bits or less. vBB[vCC] <- vAA
*
* for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
*/
/* op vAA, vBB, vCC */
movzbl 2(rPC),%eax # eax<- BB
movzbl 3(rPC),%ecx # ecx<- CC
GET_VREG_R %eax %eax # eax<- vBB (array object)
GET_VREG_R %ecx %ecx # ecs<- vCC (requested index)
testl %eax,%eax # null array object?
je common_errNullObject # bail if so
cmpl offArrayObject_length(%eax),%ecx
jae common_errArrayIndex # index >= length, bail. Expects:
# arrayObj in eax
# index in ecx
leal offArrayObject_contents(%eax,%ecx,2),%eax
.LOP_APUT_SHORT_finish:
GET_VREG_R rINST rINST
FETCH_INST_OPCODE 2 %ecx
movw rINSTw,(%eax)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_IGET: /* 0x52 */
/* File: x86/OP_IGET.S */
/*
* General 32-bit instance field get.
*
* for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL(rIBASE) # preserve rIBASE
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IGET_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IGET_finish
jmp common_exceptionThrown
.LOP_IGET_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
FETCH_INST_OPCODE 2 %eax
UNSPILL(rIBASE)
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
/* ------------------------------ */
.L_OP_IGET_WIDE: /* 0x53 */
/* File: x86/OP_IGET_WIDE.S */
/*
* 64-bit instance field get.
*
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL(rIBASE) # preserve rIBASE
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IGET_WIDE_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp) # for dvmResolveInstField
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save objpointer across call
movl rPC,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IGET_WIDE_finish
jmp common_exceptionThrown
.LOP_IGET_WIDE_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
leal (%ecx,%eax,1),%eax # eax<- address of field
movl (%eax),%ecx # ecx<- lsw
movl 4(%eax),%eax # eax<- msw
SET_VREG_WORD %ecx rINST 0
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE) # restore rIBASE
SET_VREG_WORD %eax rINST 1
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_IGET_OBJECT: /* 0x54 */
/* File: x86/OP_IGET_OBJECT.S */
/* File: x86/OP_IGET.S */
/*
* General 32-bit instance field get.
*
* for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL(rIBASE) # preserve rIBASE
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IGET_OBJECT_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IGET_OBJECT_finish
jmp common_exceptionThrown
.LOP_IGET_OBJECT_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
FETCH_INST_OPCODE 2 %eax
UNSPILL(rIBASE)
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
/* ------------------------------ */
.L_OP_IGET_BOOLEAN: /* 0x55 */
/* File: x86/OP_IGET_BOOLEAN.S */
/* File: x86/OP_IGET.S */
/*
* General 32-bit instance field get.
*
* for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL(rIBASE) # preserve rIBASE
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IGET_BOOLEAN_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IGET_BOOLEAN_finish
jmp common_exceptionThrown
.LOP_IGET_BOOLEAN_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
FETCH_INST_OPCODE 2 %eax
UNSPILL(rIBASE)
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
/* ------------------------------ */
.L_OP_IGET_BYTE: /* 0x56 */
/* File: x86/OP_IGET_BYTE.S */
/* File: x86/OP_IGET.S */
/*
* General 32-bit instance field get.
*
* for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL(rIBASE) # preserve rIBASE
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IGET_BYTE_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IGET_BYTE_finish
jmp common_exceptionThrown
.LOP_IGET_BYTE_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
FETCH_INST_OPCODE 2 %eax
UNSPILL(rIBASE)
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
/* ------------------------------ */
.L_OP_IGET_CHAR: /* 0x57 */
/* File: x86/OP_IGET_CHAR.S */
/* File: x86/OP_IGET.S */
/*
* General 32-bit instance field get.
*
* for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL(rIBASE) # preserve rIBASE
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IGET_CHAR_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IGET_CHAR_finish
jmp common_exceptionThrown
.LOP_IGET_CHAR_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
FETCH_INST_OPCODE 2 %eax
UNSPILL(rIBASE)
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
/* ------------------------------ */
.L_OP_IGET_SHORT: /* 0x58 */
/* File: x86/OP_IGET_SHORT.S */
/* File: x86/OP_IGET.S */
/*
* General 32-bit instance field get.
*
* for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL(rIBASE) # preserve rIBASE
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IGET_SHORT_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp) # needed by dvmResolveInstField
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IGET_SHORT_finish
jmp common_exceptionThrown
.LOP_IGET_SHORT_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits)
FETCH_INST_OPCODE 2 %eax
UNSPILL(rIBASE)
SET_VREG %ecx rINST
ADVANCE_PC 2
GOTO_NEXT_R %eax
/* ------------------------------ */
.L_OP_IPUT: /* 0x59 */
/* File: x86/OP_IPUT.S */
/*
* General 32-bit instance field put.
*
* for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL (rIBASE)
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IPUT_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp)
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IPUT_finish
jmp common_exceptionThrown
.LOP_IPUT_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
GET_VREG_R rINST rINST # rINST<- v[A]
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movl rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_IPUT_WIDE: /* 0x5a */
/* File: x86/OP_IPUT_WIDE.S */
/*
* 64-bit instance field put.
*
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL(rIBASE)
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IPUT_WIDE_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp)
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # ... which returns InstrField ptr
jne .LOP_IPUT_WIDE_finish
jmp common_exceptionThrown
.LOP_IPUT_WIDE_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rIBASE is scratch, but needs to be unspilled
* rINST holds A
*/
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
leal (%ecx,%eax,1),%eax # eax<- address of field
GET_VREG_WORD %ecx rINST 0 # ecx<- lsw
GET_VREG_WORD rINST rINST 1 # rINST<- msw
movl rINST,4(%eax)
movl %ecx,(%eax)
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_IPUT_OBJECT: /* 0x5b */
/* File: x86/OP_IPUT_OBJECT.S */
/*
* Object field put.
*
* for: iput-object
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL(rIBASE)
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IPUT_OBJECT_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp)
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IPUT_OBJECT_finish
jmp common_exceptionThrown
.LOP_IPUT_OBJECT_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rIBASE is scratch, but needs to be unspilled
* rINST holds A
*/
GET_VREG_R rINST rINST # rINST<- v[A]
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movl rINST,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits)
movl rSELF,%eax
testl rINST,rINST # stored a NULL?
movl offThread_cardTable(%eax),%eax # get card table base
je 1f # skip card mark if null store
shrl $GC_CARD_SHIFT,%ecx # object head to card number
movb %al,(%eax,%ecx) # mark card using object head
1:
UNSPILL(rIBASE)
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_IPUT_BOOLEAN: /* 0x5c */
/* File: x86/OP_IPUT_BOOLEAN.S */
/* File: x86/OP_IPUT.S */
/*
* General 32-bit instance field put.
*
* for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL (rIBASE)
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IPUT_BOOLEAN_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp)
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IPUT_BOOLEAN_finish
jmp common_exceptionThrown
.LOP_IPUT_BOOLEAN_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
GET_VREG_R rINST rINST # rINST<- v[A]
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_IPUT_BYTE: /* 0x5d */
/* File: x86/OP_IPUT_BYTE.S */
/* File: x86/OP_IPUT.S */
/*
* General 32-bit instance field put.
*
* for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL (rIBASE)
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IPUT_BYTE_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp)
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IPUT_BYTE_finish
jmp common_exceptionThrown
.LOP_IPUT_BYTE_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
GET_VREG_R rINST rINST # rINST<- v[A]
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_IPUT_CHAR: /* 0x5e */
/* File: x86/OP_IPUT_CHAR.S */
/* File: x86/OP_IPUT.S */
/*
* General 32-bit instance field put.
*
* for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL (rIBASE)
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IPUT_CHAR_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp)
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IPUT_CHAR_finish
jmp common_exceptionThrown
.LOP_IPUT_CHAR_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
GET_VREG_R rINST rINST # rINST<- v[A]
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_IPUT_SHORT: /* 0x5f */
/* File: x86/OP_IPUT_SHORT.S */
/* File: x86/OP_IPUT.S */
/*
* General 32-bit instance field put.
*
* for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
*/
/* op vA, vB, field@CCCC */
movl rSELF,%ecx
SPILL (rIBASE)
movzwl 2(rPC),rIBASE # rIBASE<- 0000CCCC
movl offThread_methodClassDex(%ecx),%eax # eax<- DvmDex
movzbl rINSTbl,%ecx # ecx<- BA
sarl $4,%ecx # ecx<- B
movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields
andb $0xf,rINSTbl # rINST<- A
GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr
movl (%eax,rIBASE,4),%eax # resolved entry
testl %eax,%eax # is resolved entry null?
jne .LOP_IPUT_SHORT_finish # no, already resolved
movl rIBASE,OUT_ARG1(%esp)
movl rSELF,rIBASE
EXPORT_PC
movl offThread_method(rIBASE),rIBASE # rIBASE<- current method
movl offMethod_clazz(rIBASE),rIBASE # rIBASE<- method->clazz
SPILL_TMP1(%ecx) # save obj pointer across call
movl rIBASE,OUT_ARG0(%esp) # pass in method->clazz
call dvmResolveInstField # ... to dvmResolveInstField
UNSPILL_TMP1(%ecx)
testl %eax,%eax # returns InstrField ptr
jne .LOP_IPUT_SHORT_finish
jmp common_exceptionThrown
.LOP_IPUT_SHORT_finish:
/*
* Currently:
* eax holds resolved field
* ecx holds object
* rINST holds A
*/
GET_VREG_R rINST rINST # rINST<- v[A]
movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field
testl %ecx,%ecx # object null?
je common_errNullObject # object was null
movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits)
FETCH_INST_OPCODE 2 %ecx
UNSPILL(rIBASE)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/* ------------------------------ */
.L_OP_SGET: /* 0x60 */
/* File: x86/OP_SGET.S */
/*
* General 32-bit SGET handler.
*
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- DvmDex
movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
testl %eax,%eax # resolved entry null?
je .LOP_SGET_resolve # if not, make it so
.LOP_SGET_finish: # field ptr in eax
movl offStaticField_value(%eax),%eax
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
SET_VREG %eax rINST
GOTO_NEXT_R %ecx
/*
* Go resolve the field
*/
.LOP_SGET_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_method(%ecx),%ecx # ecx<- current method
EXPORT_PC # could throw, need to export
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveStaticField # eax<- resolved StaticField ptr
UNSPILL(rIBASE)
testl %eax,%eax
jne .LOP_SGET_finish # success, continue
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_SGET_WIDE: /* 0x61 */
/* File: x86/OP_SGET_WIDE.S */
/*
* 64-bit SGET handler.
*
*/
/* sget-wide vAA, field@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- DvmDex
movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
testl %eax,%eax # resolved entry null?
je .LOP_SGET_WIDE_resolve # if not, make it so
.LOP_SGET_WIDE_finish: # field ptr in eax
movl offStaticField_value(%eax),%ecx # ecx<- lsw
movl 4+offStaticField_value(%eax),%eax # eax<- msw
SET_VREG_WORD %ecx rINST 0
FETCH_INST_OPCODE 2 %ecx
SET_VREG_WORD %eax rINST 1
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/*
* Go resolve the field
*/
.LOP_SGET_WIDE_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_method(%ecx),%ecx # ecx<- current method
EXPORT_PC # could throw, need to export
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveStaticField # eax<- resolved StaticField ptr
UNSPILL(rIBASE)
testl %eax,%eax
jne .LOP_SGET_WIDE_finish # success, continue
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_SGET_OBJECT: /* 0x62 */
/* File: x86/OP_SGET_OBJECT.S */
/* File: x86/OP_SGET.S */
/*
* General 32-bit SGET handler.
*
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- DvmDex
movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
testl %eax,%eax # resolved entry null?
je .LOP_SGET_OBJECT_resolve # if not, make it so
.LOP_SGET_OBJECT_finish: # field ptr in eax
movl offStaticField_value(%eax),%eax
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
SET_VREG %eax rINST
GOTO_NEXT_R %ecx
/*
* Go resolve the field
*/
.LOP_SGET_OBJECT_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_method(%ecx),%ecx # ecx<- current method
EXPORT_PC # could throw, need to export
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveStaticField # eax<- resolved StaticField ptr
UNSPILL(rIBASE)
testl %eax,%eax
jne .LOP_SGET_OBJECT_finish # success, continue
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_SGET_BOOLEAN: /* 0x63 */
/* File: x86/OP_SGET_BOOLEAN.S */
/* File: x86/OP_SGET.S */
/*
* General 32-bit SGET handler.
*
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- DvmDex
movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
testl %eax,%eax # resolved entry null?
je .LOP_SGET_BOOLEAN_resolve # if not, make it so
.LOP_SGET_BOOLEAN_finish: # field ptr in eax
movl offStaticField_value(%eax),%eax
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
SET_VREG %eax rINST
GOTO_NEXT_R %ecx
/*
* Go resolve the field
*/
.LOP_SGET_BOOLEAN_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_method(%ecx),%ecx # ecx<- current method
EXPORT_PC # could throw, need to export
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveStaticField # eax<- resolved StaticField ptr
UNSPILL(rIBASE)
testl %eax,%eax
jne .LOP_SGET_BOOLEAN_finish # success, continue
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_SGET_BYTE: /* 0x64 */
/* File: x86/OP_SGET_BYTE.S */
/* File: x86/OP_SGET.S */
/*
* General 32-bit SGET handler.
*
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- DvmDex
movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
testl %eax,%eax # resolved entry null?
je .LOP_SGET_BYTE_resolve # if not, make it so
.LOP_SGET_BYTE_finish: # field ptr in eax
movl offStaticField_value(%eax),%eax
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
SET_VREG %eax rINST
GOTO_NEXT_R %ecx
/*
* Go resolve the field
*/
.LOP_SGET_BYTE_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_method(%ecx),%ecx # ecx<- current method
EXPORT_PC # could throw, need to export
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveStaticField # eax<- resolved StaticField ptr
UNSPILL(rIBASE)
testl %eax,%eax
jne .LOP_SGET_BYTE_finish # success, continue
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_SGET_CHAR: /* 0x65 */
/* File: x86/OP_SGET_CHAR.S */
/* File: x86/OP_SGET.S */
/*
* General 32-bit SGET handler.
*
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- DvmDex
movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
testl %eax,%eax # resolved entry null?
je .LOP_SGET_CHAR_resolve # if not, make it so
.LOP_SGET_CHAR_finish: # field ptr in eax
movl offStaticField_value(%eax),%eax
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
SET_VREG %eax rINST
GOTO_NEXT_R %ecx
/*
* Go resolve the field
*/
.LOP_SGET_CHAR_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_method(%ecx),%ecx # ecx<- current method
EXPORT_PC # could throw, need to export
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveStaticField # eax<- resolved StaticField ptr
UNSPILL(rIBASE)
testl %eax,%eax
jne .LOP_SGET_CHAR_finish # success, continue
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_SGET_SHORT: /* 0x66 */
/* File: x86/OP_SGET_SHORT.S */
/* File: x86/OP_SGET.S */
/*
* General 32-bit SGET handler.
*
* for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
*/
/* op vAA, field@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- DvmDex
movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
testl %eax,%eax # resolved entry null?
je .LOP_SGET_SHORT_resolve # if not, make it so
.LOP_SGET_SHORT_finish: # field ptr in eax
movl offStaticField_value(%eax),%eax
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
SET_VREG %eax rINST
GOTO_NEXT_R %ecx
/*
* Go resolve the field
*/
.LOP_SGET_SHORT_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_method(%ecx),%ecx # ecx<- current method
EXPORT_PC # could throw, need to export
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveStaticField # eax<- resolved StaticField ptr
UNSPILL(rIBASE)
testl %eax,%eax
jne .LOP_SGET_SHORT_finish # success, continue
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_SPUT: /* 0x67 */
/* File: x86/OP_SPUT.S */
/*
* General 32-bit SPUT handler.
*
* for: sput, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- DvmDex
movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
testl %eax,%eax # resolved entry null?
je .LOP_SPUT_resolve # if not, make it so
.LOP_SPUT_finish: # field ptr in eax
GET_VREG_R rINST rINST
FETCH_INST_OPCODE 2 %ecx
ADVANCE_PC 2
movl rINST,offStaticField_value(%eax)
GOTO_NEXT_R %ecx
/*
* Go resolve the field
*/
.LOP_SPUT_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_method(%ecx),%ecx # ecx<- current method
EXPORT_PC # could throw, need to export
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveStaticField # eax<- resolved StaticField ptr
UNSPILL(rIBASE)
testl %eax,%eax
jne .LOP_SPUT_finish # success, continue
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_SPUT_WIDE: /* 0x68 */
/* File: x86/OP_SPUT_WIDE.S */
/*
* General 32-bit SPUT handler.
*
* for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
*/
/* op vAA, field@BBBB */
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_methodClassDex(%ecx),%ecx # ecx<- DvmDex
movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields
movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr
testl %eax,%eax # resolved entry null?
je .LOP_SPUT_WIDE_resolve # if not, make it so
.LOP_SPUT_WIDE_finish: # field ptr in eax
GET_VREG_WORD %ecx rINST 0 # rINST<- lsw
GET_VREG_WORD rINST rINST 1 # ecx<- msw
movl %ecx,offStaticField_value(%eax)
FETCH_INST_OPCODE 2 %ecx
movl rINST,4+offStaticField_value(%eax)
ADVANCE_PC 2
GOTO_NEXT_R %ecx
/*
* Go resolve the field
*/
.LOP_SPUT_WIDE_resolve:
movl rSELF,%ecx
movzwl 2(rPC),%eax # eax<- field ref BBBB
movl offThread_method(%ecx),%ecx # ecx<- current method
EXPORT_PC # could throw, need to export
movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
movl %eax,OUT_ARG1(%esp)
movl %ecx,OUT_ARG0(%esp)
SPILL(rIBASE)
call dvmResolveStaticField # eax<- resolved StaticField ptr
UNSPILL(rIBASE)
testl %eax,%eax
jne .LOP_SPUT_WIDE_finish # success, continue
jmp common_exceptionThrown # no, handle exception
/* ------------------------------ */
.L_OP_SPUT_OBJECT: /* 0x69 */
/* File: x86/OP_SPUT_OBJECT.S */
/*
* SPUT object handler.
*/
/* op vAA, field@BBBB */