1*795d594fSAndroid Build Coastguard Worker%def bincmp(condition=""): 2*795d594fSAndroid Build Coastguard Worker /* 3*795d594fSAndroid Build Coastguard Worker * Generic two-operand compare-and-branch operation. Provide a "condition" 4*795d594fSAndroid Build Coastguard Worker * fragment that specifies the comparison to perform. 5*795d594fSAndroid Build Coastguard Worker * 6*795d594fSAndroid Build Coastguard Worker * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 7*795d594fSAndroid Build Coastguard Worker */ 8*795d594fSAndroid Build Coastguard Worker /* if-cmp vA, vB, +CCCC */ 9*795d594fSAndroid Build Coastguard Worker mov r1, rINST, lsr #12 @ r1<- B 10*795d594fSAndroid Build Coastguard Worker ubfx r0, rINST, #8, #4 @ r0<- A 11*795d594fSAndroid Build Coastguard Worker GET_VREG r3, r1 @ r3<- vB 12*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r0 @ r0<- vA 13*795d594fSAndroid Build Coastguard Worker FETCH_S rINST, 1 @ rINST<- branch offset, in code units 14*795d594fSAndroid Build Coastguard Worker cmp r0, r3 @ compare (vA, vB) 15*795d594fSAndroid Build Coastguard Worker b${condition} 1f 16*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 17*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 18*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 19*795d594fSAndroid Build Coastguard Worker1: 20*795d594fSAndroid Build Coastguard Worker FETCH_S rINST, 1 // rINST<- branch offset, in code units 21*795d594fSAndroid Build Coastguard Worker BRANCH 22*795d594fSAndroid Build Coastguard Worker 23*795d594fSAndroid Build Coastguard Worker%def zcmp(condition=""): 24*795d594fSAndroid Build Coastguard Worker /* 25*795d594fSAndroid Build Coastguard Worker * Generic one-operand compare-and-branch operation. Provide a "condition" 26*795d594fSAndroid Build Coastguard Worker * fragment that specifies the comparison to perform. 27*795d594fSAndroid Build Coastguard Worker * 28*795d594fSAndroid Build Coastguard Worker * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 29*795d594fSAndroid Build Coastguard Worker */ 30*795d594fSAndroid Build Coastguard Worker /* if-cmp vAA, +BBBB */ 31*795d594fSAndroid Build Coastguard Worker mov r0, rINST, lsr #8 @ r0<- AA 32*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r0 @ r0<- vAA 33*795d594fSAndroid Build Coastguard Worker FETCH_S rINST, 1 @ rINST<- branch offset, in code units 34*795d594fSAndroid Build Coastguard Worker cmp r0, #0 // compare (vA, 0) 35*795d594fSAndroid Build Coastguard Worker b${condition} 1f 36*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 37*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 38*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 39*795d594fSAndroid Build Coastguard Worker1: 40*795d594fSAndroid Build Coastguard Worker FETCH_S rINST, 1 // rINST<- branch offset, in code units 41*795d594fSAndroid Build Coastguard Worker BRANCH 42*795d594fSAndroid Build Coastguard Worker 43*795d594fSAndroid Build Coastguard Worker%def op_goto(): 44*795d594fSAndroid Build Coastguard Worker/* 45*795d594fSAndroid Build Coastguard Worker * Unconditional branch, 8-bit offset. 46*795d594fSAndroid Build Coastguard Worker * 47*795d594fSAndroid Build Coastguard Worker * The branch distance is a signed code-unit offset, which we need to 48*795d594fSAndroid Build Coastguard Worker * double to get a byte offset. 49*795d594fSAndroid Build Coastguard Worker */ 50*795d594fSAndroid Build Coastguard Worker /* goto +AA */ 51*795d594fSAndroid Build Coastguard Worker sbfx rINST, rINST, #8, #8 // rINST<- ssssssAA (sign-extended) 52*795d594fSAndroid Build Coastguard Worker BRANCH 53*795d594fSAndroid Build Coastguard Worker 54*795d594fSAndroid Build Coastguard Worker%def op_goto_16(): 55*795d594fSAndroid Build Coastguard Worker/* 56*795d594fSAndroid Build Coastguard Worker * Unconditional branch, 16-bit offset. 57*795d594fSAndroid Build Coastguard Worker * 58*795d594fSAndroid Build Coastguard Worker * The branch distance is a signed code-unit offset, which we need to 59*795d594fSAndroid Build Coastguard Worker * double to get a byte offset. 60*795d594fSAndroid Build Coastguard Worker */ 61*795d594fSAndroid Build Coastguard Worker /* goto/16 +AAAA */ 62*795d594fSAndroid Build Coastguard Worker FETCH_S rINST, 1 // wINST<- ssssAAAA (sign-extended) 63*795d594fSAndroid Build Coastguard Worker BRANCH 64*795d594fSAndroid Build Coastguard Worker 65*795d594fSAndroid Build Coastguard Worker%def op_goto_32(): 66*795d594fSAndroid Build Coastguard Worker/* 67*795d594fSAndroid Build Coastguard Worker * Unconditional branch, 32-bit offset. 68*795d594fSAndroid Build Coastguard Worker * 69*795d594fSAndroid Build Coastguard Worker * The branch distance is a signed code-unit offset, which we need to 70*795d594fSAndroid Build Coastguard Worker * double to get a byte offset. 71*795d594fSAndroid Build Coastguard Worker * 72*795d594fSAndroid Build Coastguard Worker * Because we need the SF bit set, we'll use an adds 73*795d594fSAndroid Build Coastguard Worker * to convert from Dalvik offset to byte offset. 74*795d594fSAndroid Build Coastguard Worker */ 75*795d594fSAndroid Build Coastguard Worker /* goto/32 +AAAAAAAA */ 76*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 // r0<- aaaa (lo) 77*795d594fSAndroid Build Coastguard Worker FETCH r1, 2 // r1<- AAAA (hi) 78*795d594fSAndroid Build Coastguard Worker orrs rINST, r0, r1, lsl #16 // wINST<- AAAAaaaa 79*795d594fSAndroid Build Coastguard Worker BRANCH 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker%def op_if_eq(): 82*795d594fSAndroid Build Coastguard Worker% bincmp(condition="eq") 83*795d594fSAndroid Build Coastguard Worker 84*795d594fSAndroid Build Coastguard Worker%def op_if_eqz(): 85*795d594fSAndroid Build Coastguard Worker% zcmp(condition="eq") 86*795d594fSAndroid Build Coastguard Worker 87*795d594fSAndroid Build Coastguard Worker%def op_if_ge(): 88*795d594fSAndroid Build Coastguard Worker% bincmp(condition="ge") 89*795d594fSAndroid Build Coastguard Worker 90*795d594fSAndroid Build Coastguard Worker%def op_if_gez(): 91*795d594fSAndroid Build Coastguard Worker% zcmp(condition="ge") 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker%def op_if_gt(): 94*795d594fSAndroid Build Coastguard Worker% bincmp(condition="gt") 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker%def op_if_gtz(): 97*795d594fSAndroid Build Coastguard Worker% zcmp(condition="gt") 98*795d594fSAndroid Build Coastguard Worker 99*795d594fSAndroid Build Coastguard Worker%def op_if_le(): 100*795d594fSAndroid Build Coastguard Worker% bincmp(condition="le") 101*795d594fSAndroid Build Coastguard Worker 102*795d594fSAndroid Build Coastguard Worker%def op_if_lez(): 103*795d594fSAndroid Build Coastguard Worker% zcmp(condition="le") 104*795d594fSAndroid Build Coastguard Worker 105*795d594fSAndroid Build Coastguard Worker%def op_if_lt(): 106*795d594fSAndroid Build Coastguard Worker% bincmp(condition="lt") 107*795d594fSAndroid Build Coastguard Worker 108*795d594fSAndroid Build Coastguard Worker%def op_if_ltz(): 109*795d594fSAndroid Build Coastguard Worker% zcmp(condition="lt") 110*795d594fSAndroid Build Coastguard Worker 111*795d594fSAndroid Build Coastguard Worker%def op_if_ne(): 112*795d594fSAndroid Build Coastguard Worker% bincmp(condition="ne") 113*795d594fSAndroid Build Coastguard Worker 114*795d594fSAndroid Build Coastguard Worker%def op_if_nez(): 115*795d594fSAndroid Build Coastguard Worker% zcmp(condition="ne") 116*795d594fSAndroid Build Coastguard Worker 117*795d594fSAndroid Build Coastguard Worker%def op_packed_switch(func="NterpDoPackedSwitch"): 118*795d594fSAndroid Build Coastguard Worker/* 119*795d594fSAndroid Build Coastguard Worker * Handle a packed-switch or sparse-switch instruction. In both cases 120*795d594fSAndroid Build Coastguard Worker * we decode it and hand it off to a helper function. 121*795d594fSAndroid Build Coastguard Worker * 122*795d594fSAndroid Build Coastguard Worker * We don't really expect backward branches in a switch statement, but 123*795d594fSAndroid Build Coastguard Worker * they're perfectly legal, so we check for them here. 124*795d594fSAndroid Build Coastguard Worker * 125*795d594fSAndroid Build Coastguard Worker * for: packed-switch, sparse-switch 126*795d594fSAndroid Build Coastguard Worker */ 127*795d594fSAndroid Build Coastguard Worker /* op vAA, +BBBB */ 128*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- bbbb (lo) 129*795d594fSAndroid Build Coastguard Worker FETCH r1, 2 @ r1<- BBBB (hi) 130*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #8 @ r3<- AA 131*795d594fSAndroid Build Coastguard Worker orr r0, r0, r1, lsl #16 @ r0<- BBBBbbbb 132*795d594fSAndroid Build Coastguard Worker GET_VREG r1, r3 @ r1<- vAA 133*795d594fSAndroid Build Coastguard Worker add r0, rPC, r0, lsl #1 @ r0<- PC + BBBBbbbb*2 134*795d594fSAndroid Build Coastguard Worker bl $func @ r0<- code-unit branch offset 135*795d594fSAndroid Build Coastguard Worker mov rINST, r0 136*795d594fSAndroid Build Coastguard Worker BRANCH 137*795d594fSAndroid Build Coastguard Worker 138*795d594fSAndroid Build Coastguard Worker%def op_sparse_switch(): 139*795d594fSAndroid Build Coastguard Worker% op_packed_switch(func="NterpDoSparseSwitch") 140*795d594fSAndroid Build Coastguard Worker 141*795d594fSAndroid Build Coastguard Worker/* 142*795d594fSAndroid Build Coastguard Worker * Return a 32-bit value. 143*795d594fSAndroid Build Coastguard Worker */ 144*795d594fSAndroid Build Coastguard Worker%def op_return(is_object="0", is_void="0", is_wide="0"): 145*795d594fSAndroid Build Coastguard Worker .if $is_void 146*795d594fSAndroid Build Coastguard Worker // Thread fence for constructor 147*795d594fSAndroid Build Coastguard Worker dmb ishst 148*795d594fSAndroid Build Coastguard Worker .else 149*795d594fSAndroid Build Coastguard Worker mov r2, rINST, lsr #8 @ r2<- AA 150*795d594fSAndroid Build Coastguard Worker .if $is_wide 151*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r2, r2 152*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r2 // r0,r1 <- vAA 153*795d594fSAndroid Build Coastguard Worker // In case we're going back to compiled code, put the 154*795d594fSAndroid Build Coastguard Worker // result also in d0. 155*795d594fSAndroid Build Coastguard Worker vmov d0, r0, r1 156*795d594fSAndroid Build Coastguard Worker .else 157*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 // r0<- vAA 158*795d594fSAndroid Build Coastguard Worker .if !$is_object 159*795d594fSAndroid Build Coastguard Worker // In case we're going back to compiled code, put the 160*795d594fSAndroid Build Coastguard Worker // result also in s0. 161*795d594fSAndroid Build Coastguard Worker vmov s0, r0 162*795d594fSAndroid Build Coastguard Worker .endif 163*795d594fSAndroid Build Coastguard Worker .endif 164*795d594fSAndroid Build Coastguard Worker .endif 165*795d594fSAndroid Build Coastguard Worker .cfi_remember_state 166*795d594fSAndroid Build Coastguard Worker ldr ip, [rREFS, #-4] 167*795d594fSAndroid Build Coastguard Worker mov sp, ip 168*795d594fSAndroid Build Coastguard Worker .cfi_def_cfa sp, CALLEE_SAVES_SIZE 169*795d594fSAndroid Build Coastguard Worker RESTORE_ALL_CALLEE_SAVES lr_to_pc=1 170*795d594fSAndroid Build Coastguard Worker .cfi_restore_state 171*795d594fSAndroid Build Coastguard Worker CFI_DEF_CFA_BREG_PLUS_UCONST CFI_REFS, -4, CALLEE_SAVES_SIZE 172*795d594fSAndroid Build Coastguard Worker 173*795d594fSAndroid Build Coastguard Worker%def op_return_object(): 174*795d594fSAndroid Build Coastguard Worker% op_return(is_object="1", is_void="0", is_wide="0") 175*795d594fSAndroid Build Coastguard Worker 176*795d594fSAndroid Build Coastguard Worker%def op_return_void(): 177*795d594fSAndroid Build Coastguard Worker% op_return(is_object="0", is_void="1", is_wide="0") 178*795d594fSAndroid Build Coastguard Worker 179*795d594fSAndroid Build Coastguard Worker%def op_return_wide(): 180*795d594fSAndroid Build Coastguard Worker% op_return(is_object="0", is_void="0", is_wide="1") 181*795d594fSAndroid Build Coastguard Worker 182*795d594fSAndroid Build Coastguard Worker%def op_throw(): 183*795d594fSAndroid Build Coastguard Worker EXPORT_PC 184*795d594fSAndroid Build Coastguard Worker mov r2, rINST, lsr #8 @ r2<- AA 185*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vAA (exception object) 186*795d594fSAndroid Build Coastguard Worker mov r1, rSELF 187*795d594fSAndroid Build Coastguard Worker bl art_quick_deliver_exception 188*795d594fSAndroid Build Coastguard Worker bkpt 0 189