1%def bincmp(revcmp=""): 2/* 3 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 4 * fragment that specifies the *reverse* comparison to perform, e.g. 5 * for "if-le" you would use "gt". 6 * 7 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 8 */ 9 /* if-cmp vA, vB, +CCCC */ 10 movzx rINSTbl, %ecx # ecx <- A+ 11 andb $$0xf, %cl # ecx <- A 12 GET_VREG %eax, %ecx # eax <- vA 13 sarl $$4, rINST # rINST <- B 14 cmpl VREG_ADDRESS(rINST), %eax # compare (vA, vB) 15 j${revcmp} 1f 16 movswl 2(rPC), rINST # Get signed branch offset 17 testl rINST, rINST 18 jmp MterpCommonTakenBranch 191: 20 cmpw $$JIT_CHECK_OSR, rPROFILE 21 je .L_check_not_taken_osr 22 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 23 24%def zcmp(revcmp=""): 25/* 26 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 27 * fragment that specifies the *reverse* comparison to perform, e.g. 28 * for "if-le" you would use "gt". 29 * 30 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 31 */ 32 /* if-cmp vAA, +BBBB */ 33 cmpl $$0, VREG_ADDRESS(rINST) # compare (vA, 0) 34 j${revcmp} 1f 35 movswl 2(rPC), rINST # fetch signed displacement 36 testl rINST, rINST 37 jmp MterpCommonTakenBranch 381: 39 cmpw $$JIT_CHECK_OSR, rPROFILE 40 je .L_check_not_taken_osr 41 ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 42 43%def op_goto(): 44/* 45 * Unconditional branch, 8-bit offset. 46 * 47 * The branch distance is a signed code-unit offset, which we need to 48 * double to get a byte offset. 49 */ 50 /* goto +AA */ 51 movsbl rINSTbl, rINST # rINST <- ssssssAA 52 testl rINST, rINST 53 jmp MterpCommonTakenBranch 54 55%def op_goto_16(): 56/* 57 * Unconditional branch, 16-bit offset. 58 * 59 * The branch distance is a signed code-unit offset, which we need to 60 * double to get a byte offset. 61 */ 62 /* goto/16 +AAAA */ 63 movswl 2(rPC), rINST # rINST <- ssssAAAA 64 testl rINST, rINST 65 jmp MterpCommonTakenBranch 66 67%def op_goto_32(): 68/* 69 * Unconditional branch, 32-bit offset. 70 * 71 * The branch distance is a signed code-unit offset, which we need to 72 * double to get a byte offset. 73 * 74 * Unlike most opcodes, this one is allowed to branch to itself, so 75 * our "backward branch" test must be "<=0" instead of "<0". Because 76 * we need the V bit set, we'll use an adds to convert from Dalvik 77 * offset to byte offset. 78 */ 79 /* goto/32 +AAAAAAAA */ 80 movl 2(rPC), rINST # rINST <- AAAAAAAA 81 testl rINST, rINST 82 jmp MterpCommonTakenBranch 83 84%def op_if_eq(): 85% bincmp(revcmp="ne") 86 87%def op_if_eqz(): 88% zcmp(revcmp="ne") 89 90%def op_if_ge(): 91% bincmp(revcmp="l") 92 93%def op_if_gez(): 94% zcmp(revcmp="l") 95 96%def op_if_gt(): 97% bincmp(revcmp="le") 98 99%def op_if_gtz(): 100% zcmp(revcmp="le") 101 102%def op_if_le(): 103% bincmp(revcmp="g") 104 105%def op_if_lez(): 106% zcmp(revcmp="g") 107 108%def op_if_lt(): 109% bincmp(revcmp="ge") 110 111%def op_if_ltz(): 112% zcmp(revcmp="ge") 113 114%def op_if_ne(): 115% bincmp(revcmp="e") 116 117%def op_if_nez(): 118% zcmp(revcmp="e") 119 120%def op_packed_switch(func="MterpDoPackedSwitch"): 121/* 122 * Handle a packed-switch or sparse-switch instruction. In both cases 123 * we decode it and hand it off to a helper function. 124 * 125 * We don't really expect backward branches in a switch statement, but 126 * they're perfectly legal, so we check for them here. 127 * 128 * for: packed-switch, sparse-switch 129 */ 130 /* op vAA, +BBBB */ 131 movl 2(rPC), %ecx # ecx <- BBBBbbbb 132 GET_VREG %eax, rINST # eax <- vAA 133 leal (rPC,%ecx,2), %ecx # ecx <- PC + BBBBbbbb*2 134 movl %eax, OUT_ARG1(%esp) # ARG1 <- vAA 135 movl %ecx, OUT_ARG0(%esp) # ARG0 <- switchData 136 call SYMBOL($func) 137 REFRESH_IBASE 138 testl %eax, %eax 139 movl %eax, rINST 140 jmp MterpCommonTakenBranch 141 142%def op_return(): 143/* 144 * Return a 32-bit value. 145 * 146 * for: return, return-object 147 */ 148 /* op vAA */ 149 .extern MterpThreadFenceForConstructor 150 call SYMBOL(MterpThreadFenceForConstructor) 151 movl rSELF, %eax 152 testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax) 153 jz 1f 154 movl %eax, OUT_ARG0(%esp) 155 call SYMBOL(MterpSuspendCheck) 1561: 157 GET_VREG %eax, rINST # eax <- vAA 158 xorl %ecx, %ecx 159 jmp MterpReturn 160 161%def op_return_object(): 162% op_return() 163 164%def op_return_void(): 165 .extern MterpThreadFenceForConstructor 166 call SYMBOL(MterpThreadFenceForConstructor) 167 movl rSELF, %eax 168 testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax) 169 jz 1f 170 movl %eax, OUT_ARG0(%esp) 171 call SYMBOL(MterpSuspendCheck) 1721: 173 xorl %eax, %eax 174 xorl %ecx, %ecx 175 jmp MterpReturn 176 177%def op_return_void_no_barrier(): 178 movl rSELF, %eax 179 testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax) 180 jz 1f 181 movl %eax, OUT_ARG0(%esp) 182 call SYMBOL(MterpSuspendCheck) 1831: 184 xorl %eax, %eax 185 xorl %ecx, %ecx 186 jmp MterpReturn 187 188%def op_return_wide(): 189/* 190 * Return a 64-bit value. 191 */ 192 /* return-wide vAA */ 193 .extern MterpThreadFenceForConstructor 194 call SYMBOL(MterpThreadFenceForConstructor) 195 movl rSELF, %eax 196 testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), THREAD_FLAGS_OFFSET(%eax) 197 jz 1f 198 movl %eax, OUT_ARG0(%esp) 199 call SYMBOL(MterpSuspendCheck) 2001: 201 GET_VREG %eax, rINST # eax <- v[AA+0] 202 GET_VREG_HIGH %ecx, rINST # ecx <- v[AA+1] 203 jmp MterpReturn 204 205%def op_sparse_switch(): 206% op_packed_switch(func="MterpDoSparseSwitch") 207 208%def op_throw(): 209/* 210 * Throw an exception object in the current thread. 211 */ 212 /* throw vAA */ 213 EXPORT_PC 214 GET_VREG %eax, rINST # eax<- vAA (exception object) 215 testl %eax, %eax 216 jz common_errNullObject 217 movl rSELF,%ecx 218 movl %eax, THREAD_EXCEPTION_OFFSET(%ecx) 219 jmp MterpException 220