You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
5.7 KiB
209 lines
5.7 KiB
%def bincmp(revcmp=""):
|
|
/*
|
|
* 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 %eax, %ecx # eax <- vA
|
|
sarl $$4, rINST # rINST <- B
|
|
cmpl VREG_ADDRESS(rINST), %eax # compare (vA, vB)
|
|
j${revcmp} 1f
|
|
movswl 2(rPC), rINST # Get signed branch offset
|
|
testl rINST, rINST
|
|
jmp MterpCommonTakenBranch
|
|
1:
|
|
cmpw $$JIT_CHECK_OSR, rPROFILE
|
|
je .L_check_not_taken_osr
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
|
|
|
|
%def zcmp(revcmp=""):
|
|
/*
|
|
* 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, VREG_ADDRESS(rINST) # compare (vA, 0)
|
|
j${revcmp} 1f
|
|
movswl 2(rPC), rINST # fetch signed displacement
|
|
testl rINST, rINST
|
|
jmp MterpCommonTakenBranch
|
|
1:
|
|
cmpw $$JIT_CHECK_OSR, rPROFILE
|
|
je .L_check_not_taken_osr
|
|
ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
|
|
|
|
%def op_goto():
|
|
/*
|
|
* 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 # rINST <- ssssssAA
|
|
testl rINST, rINST
|
|
jmp MterpCommonTakenBranch
|
|
|
|
%def op_goto_16():
|
|
/*
|
|
* Unconditional branch, 16-bit offset.
|
|
*
|
|
* The branch distance is a signed code-unit offset, which we need to
|
|
* double to get a byte offset.
|
|
*/
|
|
/* goto/16 +AAAA */
|
|
movswl 2(rPC), rINST # rINST <- ssssAAAA
|
|
testl rINST, rINST
|
|
jmp MterpCommonTakenBranch
|
|
|
|
%def op_goto_32():
|
|
/*
|
|
* Unconditional branch, 32-bit offset.
|
|
*
|
|
* The branch distance is a signed code-unit offset, which we need to
|
|
* double to get a byte offset.
|
|
*
|
|
* Unlike most opcodes, this one is allowed to branch to itself, so
|
|
* our "backward branch" test must be "<=0" instead of "<0". Because
|
|
* we need the V bit set, we'll use an adds to convert from Dalvik
|
|
* offset to byte offset.
|
|
*/
|
|
/* goto/32 +AAAAAAAA */
|
|
movl 2(rPC), rINST # rINST <- AAAAAAAA
|
|
testl rINST, rINST
|
|
jmp MterpCommonTakenBranch
|
|
|
|
%def op_if_eq():
|
|
% bincmp(revcmp="ne")
|
|
|
|
%def op_if_eqz():
|
|
% zcmp(revcmp="ne")
|
|
|
|
%def op_if_ge():
|
|
% bincmp(revcmp="l")
|
|
|
|
%def op_if_gez():
|
|
% zcmp(revcmp="l")
|
|
|
|
%def op_if_gt():
|
|
% bincmp(revcmp="le")
|
|
|
|
%def op_if_gtz():
|
|
% zcmp(revcmp="le")
|
|
|
|
%def op_if_le():
|
|
% bincmp(revcmp="g")
|
|
|
|
%def op_if_lez():
|
|
% zcmp(revcmp="g")
|
|
|
|
%def op_if_lt():
|
|
% bincmp(revcmp="ge")
|
|
|
|
%def op_if_ltz():
|
|
% zcmp(revcmp="ge")
|
|
|
|
%def op_if_ne():
|
|
% bincmp(revcmp="e")
|
|
|
|
%def op_if_nez():
|
|
% zcmp(revcmp="e")
|
|
|
|
%def op_packed_switch(func="MterpDoPackedSwitch"):
|
|
/*
|
|
* 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 %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
|
|
call SYMBOL($func)
|
|
REFRESH_IBASE
|
|
testl %eax, %eax
|
|
movl %eax, rINST
|
|
jmp MterpCommonTakenBranch
|
|
|
|
%def op_return():
|
|
/*
|
|
* Return a 32-bit value.
|
|
*
|
|
* for: return, return-object
|
|
*/
|
|
/* op vAA */
|
|
.extern MterpThreadFenceForConstructor
|
|
call SYMBOL(MterpThreadFenceForConstructor)
|
|
movl rSELF, %eax
|
|
testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
|
|
jz 1f
|
|
movl %eax, OUT_ARG0(%esp)
|
|
call SYMBOL(MterpSuspendCheck)
|
|
1:
|
|
GET_VREG %eax, rINST # eax <- vAA
|
|
xorl %ecx, %ecx
|
|
jmp MterpReturn
|
|
|
|
%def op_return_object():
|
|
% op_return()
|
|
|
|
%def op_return_void():
|
|
.extern MterpThreadFenceForConstructor
|
|
call SYMBOL(MterpThreadFenceForConstructor)
|
|
movl rSELF, %eax
|
|
testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
|
|
jz 1f
|
|
movl %eax, OUT_ARG0(%esp)
|
|
call SYMBOL(MterpSuspendCheck)
|
|
1:
|
|
xorl %eax, %eax
|
|
xorl %ecx, %ecx
|
|
jmp MterpReturn
|
|
|
|
%def op_return_wide():
|
|
/*
|
|
* Return a 64-bit value.
|
|
*/
|
|
/* return-wide vAA */
|
|
.extern MterpThreadFenceForConstructor
|
|
call SYMBOL(MterpThreadFenceForConstructor)
|
|
movl rSELF, %eax
|
|
testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax)
|
|
jz 1f
|
|
movl %eax, OUT_ARG0(%esp)
|
|
call SYMBOL(MterpSuspendCheck)
|
|
1:
|
|
GET_VREG %eax, rINST # eax <- v[AA+0]
|
|
GET_VREG_HIGH %ecx, rINST # ecx <- v[AA+1]
|
|
jmp MterpReturn
|
|
|
|
%def op_sparse_switch():
|
|
% op_packed_switch(func="MterpDoSparseSwitch")
|
|
|
|
%def op_throw():
|
|
/*
|
|
* Throw an exception object in the current thread.
|
|
*/
|
|
/* throw vAA */
|
|
EXPORT_PC
|
|
GET_VREG %eax, rINST # eax<- vAA (exception object)
|
|
testl %eax, %eax
|
|
jz common_errNullObject
|
|
movl rSELF,%ecx
|
|
movl %eax, THREAD_EXCEPTION_OFFSET(%ecx)
|
|
jmp MterpException
|