1*795d594fSAndroid Build Coastguard Worker%def bincmp(revcmp=""): 2*795d594fSAndroid Build Coastguard Worker/* 3*795d594fSAndroid Build Coastguard Worker * Generic two-operand compare-and-branch operation. Provide a "revcmp" 4*795d594fSAndroid Build Coastguard Worker * fragment that specifies the *reverse* comparison to perform, e.g. 5*795d594fSAndroid Build Coastguard Worker * for "if-le" you would use "gt". 6*795d594fSAndroid Build Coastguard Worker * 7*795d594fSAndroid Build Coastguard Worker * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 8*795d594fSAndroid Build Coastguard Worker */ 9*795d594fSAndroid Build Coastguard Worker /* if-cmp vA, vB, +CCCC */ 10*795d594fSAndroid Build Coastguard Worker movl rINST, %ecx # rcx <- A+ 11*795d594fSAndroid Build Coastguard Worker sarl $$4, rINST # rINST <- B 12*795d594fSAndroid Build Coastguard Worker andb $$0xf, %cl # rcx <- A 13*795d594fSAndroid Build Coastguard Worker GET_VREG %eax, %ecx # eax <- vA 14*795d594fSAndroid Build Coastguard Worker cmpl VREG_ADDRESS(rINST), %eax # compare (vA, vB) 15*795d594fSAndroid Build Coastguard Worker j${revcmp} 1f 16*795d594fSAndroid Build Coastguard Worker movswl 2(rPC), rINST # Get signed branch offset 17*795d594fSAndroid Build Coastguard Worker BRANCH 18*795d594fSAndroid Build Coastguard Worker1: 19*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 20*795d594fSAndroid Build Coastguard Worker 21*795d594fSAndroid Build Coastguard Worker%def zcmp(revcmp=""): 22*795d594fSAndroid Build Coastguard Worker/* 23*795d594fSAndroid Build Coastguard Worker * Generic one-operand compare-and-branch operation. Provide a "revcmp" 24*795d594fSAndroid Build Coastguard Worker * fragment that specifies the *reverse* comparison to perform, e.g. 25*795d594fSAndroid Build Coastguard Worker * for "if-le" you would use "gt". 26*795d594fSAndroid Build Coastguard Worker * 27*795d594fSAndroid Build Coastguard Worker * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 28*795d594fSAndroid Build Coastguard Worker */ 29*795d594fSAndroid Build Coastguard Worker /* if-cmp vAA, +BBBB */ 30*795d594fSAndroid Build Coastguard Worker cmpl $$0, VREG_ADDRESS(rINST) # compare (vA, 0) 31*795d594fSAndroid Build Coastguard Worker j${revcmp} 1f 32*795d594fSAndroid Build Coastguard Worker movswl 2(rPC), rINST # fetch signed displacement 33*795d594fSAndroid Build Coastguard Worker BRANCH 34*795d594fSAndroid Build Coastguard Worker1: 35*795d594fSAndroid Build Coastguard Worker ADVANCE_PC_FETCH_AND_GOTO_NEXT 2 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker%def op_goto(): 38*795d594fSAndroid Build Coastguard Worker/* 39*795d594fSAndroid Build Coastguard Worker * Unconditional branch, 8-bit offset. 40*795d594fSAndroid Build Coastguard Worker * 41*795d594fSAndroid Build Coastguard Worker * The branch distance is a signed code-unit offset, which we need to 42*795d594fSAndroid Build Coastguard Worker * double to get a byte offset. 43*795d594fSAndroid Build Coastguard Worker */ 44*795d594fSAndroid Build Coastguard Worker /* goto +AA */ 45*795d594fSAndroid Build Coastguard Worker movsbl rINSTbl, rINST # rINST <- ssssssAA 46*795d594fSAndroid Build Coastguard Worker BRANCH 47*795d594fSAndroid Build Coastguard Worker 48*795d594fSAndroid Build Coastguard Worker%def op_goto_16(): 49*795d594fSAndroid Build Coastguard Worker/* 50*795d594fSAndroid Build Coastguard Worker * Unconditional branch, 16-bit offset. 51*795d594fSAndroid Build Coastguard Worker * 52*795d594fSAndroid Build Coastguard Worker * The branch distance is a signed code-unit offset, which we need to 53*795d594fSAndroid Build Coastguard Worker * double to get a byte offset. 54*795d594fSAndroid Build Coastguard Worker */ 55*795d594fSAndroid Build Coastguard Worker /* goto/16 +AAAA */ 56*795d594fSAndroid Build Coastguard Worker movswl 2(rPC), rINST # rINST <- ssssAAAA 57*795d594fSAndroid Build Coastguard Worker BRANCH 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker%def op_goto_32(): 60*795d594fSAndroid Build Coastguard Worker/* 61*795d594fSAndroid Build Coastguard Worker * Unconditional branch, 32-bit offset. 62*795d594fSAndroid Build Coastguard Worker * 63*795d594fSAndroid Build Coastguard Worker * The branch distance is a signed code-unit offset, which we need to 64*795d594fSAndroid Build Coastguard Worker * double to get a byte offset. 65*795d594fSAndroid Build Coastguard Worker */ 66*795d594fSAndroid Build Coastguard Worker /* goto/32 +AAAAAAAA */ 67*795d594fSAndroid Build Coastguard Worker movl 2(rPC), rINST # rINST <- AAAAAAAA 68*795d594fSAndroid Build Coastguard Worker BRANCH 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker%def op_if_eq(): 71*795d594fSAndroid Build Coastguard Worker% bincmp(revcmp="ne") 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker%def op_if_eqz(): 74*795d594fSAndroid Build Coastguard Worker% zcmp(revcmp="ne") 75*795d594fSAndroid Build Coastguard Worker 76*795d594fSAndroid Build Coastguard Worker%def op_if_ge(): 77*795d594fSAndroid Build Coastguard Worker% bincmp(revcmp="l") 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker%def op_if_gez(): 80*795d594fSAndroid Build Coastguard Worker% zcmp(revcmp="l") 81*795d594fSAndroid Build Coastguard Worker 82*795d594fSAndroid Build Coastguard Worker%def op_if_gt(): 83*795d594fSAndroid Build Coastguard Worker% bincmp(revcmp="le") 84*795d594fSAndroid Build Coastguard Worker 85*795d594fSAndroid Build Coastguard Worker%def op_if_gtz(): 86*795d594fSAndroid Build Coastguard Worker% zcmp(revcmp="le") 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker%def op_if_le(): 89*795d594fSAndroid Build Coastguard Worker% bincmp(revcmp="g") 90*795d594fSAndroid Build Coastguard Worker 91*795d594fSAndroid Build Coastguard Worker%def op_if_lez(): 92*795d594fSAndroid Build Coastguard Worker% zcmp(revcmp="g") 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker%def op_if_lt(): 95*795d594fSAndroid Build Coastguard Worker% bincmp(revcmp="ge") 96*795d594fSAndroid Build Coastguard Worker 97*795d594fSAndroid Build Coastguard Worker%def op_if_ltz(): 98*795d594fSAndroid Build Coastguard Worker% zcmp(revcmp="ge") 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker%def op_if_ne(): 101*795d594fSAndroid Build Coastguard Worker% bincmp(revcmp="e") 102*795d594fSAndroid Build Coastguard Worker 103*795d594fSAndroid Build Coastguard Worker%def op_if_nez(): 104*795d594fSAndroid Build Coastguard Worker% zcmp(revcmp="e") 105*795d594fSAndroid Build Coastguard Worker 106*795d594fSAndroid Build Coastguard Worker%def op_packed_switch(func="NterpDoPackedSwitch"): 107*795d594fSAndroid Build Coastguard Worker/* 108*795d594fSAndroid Build Coastguard Worker * Handle a packed-switch or sparse-switch instruction. In both cases 109*795d594fSAndroid Build Coastguard Worker * we decode it and hand it off to a helper function. 110*795d594fSAndroid Build Coastguard Worker * 111*795d594fSAndroid Build Coastguard Worker * We don't really expect backward branches in a switch statement, but 112*795d594fSAndroid Build Coastguard Worker * they're perfectly legal, so we check for them here. 113*795d594fSAndroid Build Coastguard Worker * 114*795d594fSAndroid Build Coastguard Worker * for: packed-switch, sparse-switch 115*795d594fSAndroid Build Coastguard Worker */ 116*795d594fSAndroid Build Coastguard Worker /* op vAA, +BBBB */ 117*795d594fSAndroid Build Coastguard Worker movl 2(rPC), ARG0 # eax <- BBBBbbbb 118*795d594fSAndroid Build Coastguard Worker leal (rPC,ARG0,2), ARG0 # eax <- PC + BBBBbbbb*2 119*795d594fSAndroid Build Coastguard Worker GET_VREG ARG1, rINST # ecx <- vAA 120*795d594fSAndroid Build Coastguard Worker pushl ARG1 121*795d594fSAndroid Build Coastguard Worker pushl ARG0 122*795d594fSAndroid Build Coastguard Worker call SYMBOL($func) 123*795d594fSAndroid Build Coastguard Worker addl MACRO_LITERAL(8), %esp 124*795d594fSAndroid Build Coastguard Worker RESTORE_IBASE 125*795d594fSAndroid Build Coastguard Worker FETCH_INST_CLEAR_OPCODE 126*795d594fSAndroid Build Coastguard Worker movl %eax, rINST 127*795d594fSAndroid Build Coastguard Worker BRANCH 128*795d594fSAndroid Build Coastguard Worker 129*795d594fSAndroid Build Coastguard Worker/* 130*795d594fSAndroid Build Coastguard Worker * Return a 32-bit value. 131*795d594fSAndroid Build Coastguard Worker */ 132*795d594fSAndroid Build Coastguard Worker%def op_return(is_object="0"): 133*795d594fSAndroid Build Coastguard Worker GET_VREG %eax, rINST # eax <- vAA 134*795d594fSAndroid Build Coastguard Worker .if !$is_object 135*795d594fSAndroid Build Coastguard Worker // In case we're going back to compiled code, put the 136*795d594fSAndroid Build Coastguard Worker // result also in a xmm register. 137*795d594fSAndroid Build Coastguard Worker movd %eax, %xmm0 138*795d594fSAndroid Build Coastguard Worker .endif 139*795d594fSAndroid Build Coastguard Worker CFI_REMEMBER_STATE 140*795d594fSAndroid Build Coastguard Worker movl -4(rREFS), %esp 141*795d594fSAndroid Build Coastguard Worker DROP_PARAMETERS_SAVES 142*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA(esp, CALLEE_SAVES_SIZE) 143*795d594fSAndroid Build Coastguard Worker RESTORE_ALL_CALLEE_SAVES 144*795d594fSAndroid Build Coastguard Worker ret 145*795d594fSAndroid Build Coastguard Worker CFI_RESTORE_STATE 146*795d594fSAndroid Build Coastguard Worker NTERP_DEF_CFA CFI_REFS 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker%def op_return_object(): 149*795d594fSAndroid Build Coastguard Worker% op_return(is_object="1") 150*795d594fSAndroid Build Coastguard Worker 151*795d594fSAndroid Build Coastguard Worker%def op_return_void(): 152*795d594fSAndroid Build Coastguard Worker // Thread fence for constructor is a no-op on x86_64. 153*795d594fSAndroid Build Coastguard Worker CFI_REMEMBER_STATE 154*795d594fSAndroid Build Coastguard Worker movl -4(rREFS), %esp 155*795d594fSAndroid Build Coastguard Worker DROP_PARAMETERS_SAVES 156*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA(esp, CALLEE_SAVES_SIZE) 157*795d594fSAndroid Build Coastguard Worker RESTORE_ALL_CALLEE_SAVES 158*795d594fSAndroid Build Coastguard Worker ret 159*795d594fSAndroid Build Coastguard Worker CFI_RESTORE_STATE 160*795d594fSAndroid Build Coastguard Worker NTERP_DEF_CFA CFI_REFS 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker%def op_return_wide(): 163*795d594fSAndroid Build Coastguard Worker // In case we're going back to compiled code, put the 164*795d594fSAndroid Build Coastguard Worker // result also in a xmm register. 165*795d594fSAndroid Build Coastguard Worker GET_WIDE_FP_VREG %xmm0, rINST 166*795d594fSAndroid Build Coastguard Worker GET_VREG %eax, rINST # eax <- vAA 167*795d594fSAndroid Build Coastguard Worker GET_VREG_HIGH %edx, rINST # edx <- vAA 168*795d594fSAndroid Build Coastguard Worker CFI_REMEMBER_STATE 169*795d594fSAndroid Build Coastguard Worker movl -4(rREFS), %esp 170*795d594fSAndroid Build Coastguard Worker DROP_PARAMETERS_SAVES 171*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA(esp, CALLEE_SAVES_SIZE) 172*795d594fSAndroid Build Coastguard Worker RESTORE_ALL_CALLEE_SAVES 173*795d594fSAndroid Build Coastguard Worker ret 174*795d594fSAndroid Build Coastguard Worker CFI_RESTORE_STATE 175*795d594fSAndroid Build Coastguard Worker NTERP_DEF_CFA CFI_REFS 176*795d594fSAndroid Build Coastguard Worker 177*795d594fSAndroid Build Coastguard Worker%def op_sparse_switch(): 178*795d594fSAndroid Build Coastguard Worker% op_packed_switch(func="NterpDoSparseSwitch") 179*795d594fSAndroid Build Coastguard Worker 180*795d594fSAndroid Build Coastguard Worker%def op_throw(): 181*795d594fSAndroid Build Coastguard Worker EXPORT_PC 182*795d594fSAndroid Build Coastguard Worker GET_VREG ARG0, rINST # eax <- vAA (exception object) 183*795d594fSAndroid Build Coastguard Worker movl rSELF:THREAD_SELF_OFFSET, ARG1 184*795d594fSAndroid Build Coastguard Worker call SYMBOL(art_quick_deliver_exception) 185*795d594fSAndroid Build Coastguard Worker int3 186