1*795d594fSAndroid Build Coastguard Worker%def binop(preinstr="", result="r0", chkzero="0", instr=""): 2*795d594fSAndroid Build Coastguard Worker /* 3*795d594fSAndroid Build Coastguard Worker * Generic 32-bit binary operation. Provide an "instr" line that 4*795d594fSAndroid Build Coastguard Worker * specifies an instruction that performs "result = r0 op r1". 5*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 6*795d594fSAndroid Build Coastguard Worker * comes back in a register other than r0, you can override "result".) 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 9*795d594fSAndroid Build Coastguard Worker * vCC (r1). Useful for integer division and modulus. Note that we 10*795d594fSAndroid Build Coastguard Worker * *don't* check for (INT_MIN / -1) here, because the ARM math lib 11*795d594fSAndroid Build Coastguard Worker * handles it correctly. 12*795d594fSAndroid Build Coastguard Worker * 13*795d594fSAndroid Build Coastguard Worker * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int, 14*795d594fSAndroid Build Coastguard Worker * xor-int, shl-int, shr-int, ushr-int, add-float, sub-float, 15*795d594fSAndroid Build Coastguard Worker * mul-float, div-float, rem-float 16*795d594fSAndroid Build Coastguard Worker */ 17*795d594fSAndroid Build Coastguard Worker /* binop vAA, vBB, vCC */ 18*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- CCBB 19*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 20*795d594fSAndroid Build Coastguard Worker mov r3, r0, lsr #8 @ r3<- CC 21*795d594fSAndroid Build Coastguard Worker and r2, r0, #255 @ r2<- BB 22*795d594fSAndroid Build Coastguard Worker GET_VREG r1, r3 @ r1<- vCC 23*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vBB 24*795d594fSAndroid Build Coastguard Worker .if $chkzero 25*795d594fSAndroid Build Coastguard Worker cmp r1, #0 @ is second operand zero? 26*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 27*795d594fSAndroid Build Coastguard Worker .endif 28*795d594fSAndroid Build Coastguard Worker 29*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 30*795d594fSAndroid Build Coastguard Worker $preinstr @ optional op; may set condition codes 31*795d594fSAndroid Build Coastguard Worker $instr @ $result<- op, r0-r3 changed 32*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 33*795d594fSAndroid Build Coastguard Worker SET_VREG $result, r4 @ vAA<- $result 34*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 35*795d594fSAndroid Build Coastguard Worker /* 11-14 instructions */ 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker%def binop2addr(preinstr="", result="r0", chkzero="0", instr=""): 38*795d594fSAndroid Build Coastguard Worker /* 39*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 40*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = r0 op r1". 41*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 42*795d594fSAndroid Build Coastguard Worker * comes back in a register other than r0, you can override "result".) 43*795d594fSAndroid Build Coastguard Worker * 44*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 45*795d594fSAndroid Build Coastguard Worker * vCC (r1). Useful for integer division and modulus. 46*795d594fSAndroid Build Coastguard Worker * 47*795d594fSAndroid Build Coastguard Worker * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 48*795d594fSAndroid Build Coastguard Worker * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 49*795d594fSAndroid Build Coastguard Worker * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 50*795d594fSAndroid Build Coastguard Worker * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 51*795d594fSAndroid Build Coastguard Worker */ 52*795d594fSAndroid Build Coastguard Worker /* binop/2addr vA, vB */ 53*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 54*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 55*795d594fSAndroid Build Coastguard Worker GET_VREG r1, r3 @ r1<- vB 56*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r4 @ r0<- vA 57*795d594fSAndroid Build Coastguard Worker .if $chkzero 58*795d594fSAndroid Build Coastguard Worker cmp r1, #0 @ is second operand zero? 59*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 60*795d594fSAndroid Build Coastguard Worker .endif 61*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 62*795d594fSAndroid Build Coastguard Worker 63*795d594fSAndroid Build Coastguard Worker $preinstr @ optional op; may set condition codes 64*795d594fSAndroid Build Coastguard Worker $instr @ $result<- op, r0-r3 changed 65*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 66*795d594fSAndroid Build Coastguard Worker SET_VREG $result, r4 @ vAA<- $result 67*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 68*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker%def binopLit16(result="r0", chkzero="0", instr=""): 71*795d594fSAndroid Build Coastguard Worker /* 72*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "lit16" binary operation. Provide an "instr" line 73*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = r0 op r1". 74*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 75*795d594fSAndroid Build Coastguard Worker * comes back in a register other than r0, you can override "result".) 76*795d594fSAndroid Build Coastguard Worker * 77*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 78*795d594fSAndroid Build Coastguard Worker * vCC (r1). Useful for integer division and modulus. 79*795d594fSAndroid Build Coastguard Worker * 80*795d594fSAndroid Build Coastguard Worker * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 81*795d594fSAndroid Build Coastguard Worker * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 82*795d594fSAndroid Build Coastguard Worker */ 83*795d594fSAndroid Build Coastguard Worker /* binop/lit16 vA, vB, #+CCCC */ 84*795d594fSAndroid Build Coastguard Worker FETCH_S r1, 1 @ r1<- ssssCCCC (sign-extended) 85*795d594fSAndroid Build Coastguard Worker mov r2, rINST, lsr #12 @ r2<- B 86*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 87*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vB 88*795d594fSAndroid Build Coastguard Worker .if $chkzero 89*795d594fSAndroid Build Coastguard Worker cmp r1, #0 @ is second operand zero? 90*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 91*795d594fSAndroid Build Coastguard Worker .endif 92*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker $instr @ $result<- op, r0-r3 changed 95*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 96*795d594fSAndroid Build Coastguard Worker SET_VREG $result, r4 @ vAA<- $result 97*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 98*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker%def binopLit8(extract="asr r1, r3, #8", result="r0", chkzero="0", instr=""): 101*795d594fSAndroid Build Coastguard Worker /* 102*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "lit8" binary operation. Provide an "instr" line 103*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = r0 op r1". 104*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 105*795d594fSAndroid Build Coastguard Worker * comes back in a register other than r0, you can override "result".) 106*795d594fSAndroid Build Coastguard Worker * 107*795d594fSAndroid Build Coastguard Worker * You can override "extract" if the extraction of the literal value 108*795d594fSAndroid Build Coastguard Worker * from r3 to r1 is not the default "asr r1, r3, #8". The extraction 109*795d594fSAndroid Build Coastguard Worker * can be omitted completely if the shift is embedded in "instr". 110*795d594fSAndroid Build Coastguard Worker * 111*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 112*795d594fSAndroid Build Coastguard Worker * vCC (r1). Useful for integer division and modulus. 113*795d594fSAndroid Build Coastguard Worker * 114*795d594fSAndroid Build Coastguard Worker * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 115*795d594fSAndroid Build Coastguard Worker * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 116*795d594fSAndroid Build Coastguard Worker * shl-int/lit8, shr-int/lit8, ushr-int/lit8 117*795d594fSAndroid Build Coastguard Worker */ 118*795d594fSAndroid Build Coastguard Worker /* binop/lit8 vAA, vBB, #+CC */ 119*795d594fSAndroid Build Coastguard Worker FETCH_S r3, 1 @ r3<- ssssCCBB (sign-extended for CC) 120*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 121*795d594fSAndroid Build Coastguard Worker and r2, r3, #255 @ r2<- BB 122*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vBB 123*795d594fSAndroid Build Coastguard Worker $extract @ optional; typically r1<- ssssssCC (sign extended) 124*795d594fSAndroid Build Coastguard Worker .if $chkzero 125*795d594fSAndroid Build Coastguard Worker @cmp r1, #0 @ is second operand zero? 126*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 127*795d594fSAndroid Build Coastguard Worker .endif 128*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 129*795d594fSAndroid Build Coastguard Worker 130*795d594fSAndroid Build Coastguard Worker $instr @ $result<- op, r0-r3 changed 131*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 132*795d594fSAndroid Build Coastguard Worker SET_VREG $result, r4 @ vAA<- $result 133*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 134*795d594fSAndroid Build Coastguard Worker /* 10-12 instructions */ 135*795d594fSAndroid Build Coastguard Worker 136*795d594fSAndroid Build Coastguard Worker%def binopWide(preinstr="", result0="r0", result1="r1", chkzero="0", instr=""): 137*795d594fSAndroid Build Coastguard Worker /* 138*795d594fSAndroid Build Coastguard Worker * Generic 64-bit binary operation. Provide an "instr" line that 139*795d594fSAndroid Build Coastguard Worker * specifies an instruction that performs "result = r0-r1 op r2-r3". 140*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 141*795d594fSAndroid Build Coastguard Worker * comes back in a register other than r0, you can override "result".) 142*795d594fSAndroid Build Coastguard Worker * 143*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 144*795d594fSAndroid Build Coastguard Worker * vCC (r1). Useful for integer division and modulus. 145*795d594fSAndroid Build Coastguard Worker * 146*795d594fSAndroid Build Coastguard Worker * for: add-long, sub-long, div-long, rem-long, and-long, or-long, 147*795d594fSAndroid Build Coastguard Worker * xor-long, add-double, sub-double, mul-double, div-double, 148*795d594fSAndroid Build Coastguard Worker * rem-double 149*795d594fSAndroid Build Coastguard Worker * 150*795d594fSAndroid Build Coastguard Worker * IMPORTANT: you may specify "chkzero" or "preinstr" but not both. 151*795d594fSAndroid Build Coastguard Worker */ 152*795d594fSAndroid Build Coastguard Worker /* binop vAA, vBB, vCC */ 153*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- CCBB 154*795d594fSAndroid Build Coastguard Worker mov rINST, rINST, lsr #8 @ rINST<- AA 155*795d594fSAndroid Build Coastguard Worker and r2, r0, #255 @ r2<- BB 156*795d594fSAndroid Build Coastguard Worker mov r3, r0, lsr #8 @ r3<- CC 157*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, rINST @ r4<- &fp[AA] 158*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r2, r2 @ r2<- &fp[BB] 159*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r3, r3 @ r3<- &fp[CC] 160*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r2 @ r0/r1<- vBB/vBB+1 161*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r2, r3, r3 @ r2/r3<- vCC/vCC+1 162*795d594fSAndroid Build Coastguard Worker .if $chkzero 163*795d594fSAndroid Build Coastguard Worker orrs ip, r2, r3 @ second arg (r2-r3) is zero? 164*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 165*795d594fSAndroid Build Coastguard Worker .endif 166*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR rINST, lr, ip @ Zero out the shadow regs 167*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 168*795d594fSAndroid Build Coastguard Worker $preinstr @ optional op; may set condition codes 169*795d594fSAndroid Build Coastguard Worker $instr @ result<- op, r0-r3 changed 170*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 171*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR $result0,$result1,r4 @ vAA/vAA+1<, $result0/$result1 172*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 173*795d594fSAndroid Build Coastguard Worker /* 14-17 instructions */ 174*795d594fSAndroid Build Coastguard Worker 175*795d594fSAndroid Build Coastguard Worker%def binopWide2addr(preinstr="", result0="r0", result1="r1", chkzero="0", instr=""): 176*795d594fSAndroid Build Coastguard Worker /* 177*795d594fSAndroid Build Coastguard Worker * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 178*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = r0-r1 op r2-r3". 179*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 180*795d594fSAndroid Build Coastguard Worker * comes back in a register other than r0, you can override "result".) 181*795d594fSAndroid Build Coastguard Worker * 182*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 183*795d594fSAndroid Build Coastguard Worker * vCC (r1). Useful for integer division and modulus. 184*795d594fSAndroid Build Coastguard Worker * 185*795d594fSAndroid Build Coastguard Worker * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr, 186*795d594fSAndroid Build Coastguard Worker * and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr, 187*795d594fSAndroid Build Coastguard Worker * sub-double/2addr, mul-double/2addr, div-double/2addr, 188*795d594fSAndroid Build Coastguard Worker * rem-double/2addr 189*795d594fSAndroid Build Coastguard Worker */ 190*795d594fSAndroid Build Coastguard Worker /* binop/2addr vA, vB */ 191*795d594fSAndroid Build Coastguard Worker mov r1, rINST, lsr #12 @ r1<- B 192*795d594fSAndroid Build Coastguard Worker ubfx rINST, rINST, #8, #4 @ rINST<- A 193*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r1, r1 @ r1<- &fp[B] 194*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, rINST @ r4<- &fp[A] 195*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r2, r3, r1 @ r2/r3<- vBB/vBB+1 196*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r4 @ r0/r1<- vAA/vAA+1 197*795d594fSAndroid Build Coastguard Worker .if $chkzero 198*795d594fSAndroid Build Coastguard Worker orrs ip, r2, r3 @ second arg (r2-r3) is zero? 199*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 200*795d594fSAndroid Build Coastguard Worker .endif 201*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR rINST, ip, lr @ Zero shadow regs 202*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 203*795d594fSAndroid Build Coastguard Worker $preinstr @ optional op; may set condition codes 204*795d594fSAndroid Build Coastguard Worker $instr @ result<- op, r0-r3 changed 205*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 206*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR $result0,$result1,r4 @ vAA/vAA+1<- $result0/$result1 207*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 208*795d594fSAndroid Build Coastguard Worker /* 12-15 instructions */ 209*795d594fSAndroid Build Coastguard Worker 210*795d594fSAndroid Build Coastguard Worker%def unop(preinstr="", instr=""): 211*795d594fSAndroid Build Coastguard Worker /* 212*795d594fSAndroid Build Coastguard Worker * Generic 32-bit unary operation. Provide an "instr" line that 213*795d594fSAndroid Build Coastguard Worker * specifies an instruction that performs "result = op r0". 214*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. 215*795d594fSAndroid Build Coastguard Worker * 216*795d594fSAndroid Build Coastguard Worker * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 217*795d594fSAndroid Build Coastguard Worker * int-to-byte, int-to-char, int-to-short 218*795d594fSAndroid Build Coastguard Worker */ 219*795d594fSAndroid Build Coastguard Worker /* unop vA, vB */ 220*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 221*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 222*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r3 @ r0<- vB 223*795d594fSAndroid Build Coastguard Worker $preinstr @ optional op; may set condition codes 224*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 225*795d594fSAndroid Build Coastguard Worker $instr @ r0<- op, r0-r3 changed 226*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 227*795d594fSAndroid Build Coastguard Worker SET_VREG r0, r4 @ vAA<- r0 228*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 229*795d594fSAndroid Build Coastguard Worker /* 8-9 instructions */ 230*795d594fSAndroid Build Coastguard Worker 231*795d594fSAndroid Build Coastguard Worker%def unopNarrower(preinstr="", instr=""): 232*795d594fSAndroid Build Coastguard Worker /* 233*795d594fSAndroid Build Coastguard Worker * Generic 64bit-to-32bit unary operation. Provide an "instr" line 234*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = op r0/r1", where 235*795d594fSAndroid Build Coastguard Worker * "result" is a 32-bit quantity in r0. 236*795d594fSAndroid Build Coastguard Worker * 237*795d594fSAndroid Build Coastguard Worker * For: long-to-float 238*795d594fSAndroid Build Coastguard Worker * 239*795d594fSAndroid Build Coastguard Worker * (This would work for long-to-int, but that instruction is actually 240*795d594fSAndroid Build Coastguard Worker * an exact match for op_move.) 241*795d594fSAndroid Build Coastguard Worker */ 242*795d594fSAndroid Build Coastguard Worker /* unop vA, vB */ 243*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 244*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 245*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r3, r3 @ r3<- &fp[B] 246*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r3 @ r0/r1<- vB/vB+1 247*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 248*795d594fSAndroid Build Coastguard Worker $preinstr @ optional op; may set condition codes 249*795d594fSAndroid Build Coastguard Worker $instr @ r0<- op, r0-r3 changed 250*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 251*795d594fSAndroid Build Coastguard Worker SET_VREG r0, r4 @ vA<- r0 252*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 253*795d594fSAndroid Build Coastguard Worker /* 9-10 instructions */ 254*795d594fSAndroid Build Coastguard Worker 255*795d594fSAndroid Build Coastguard Worker%def unopWide(preinstr="", instr=""): 256*795d594fSAndroid Build Coastguard Worker /* 257*795d594fSAndroid Build Coastguard Worker * Generic 64-bit unary operation. Provide an "instr" line that 258*795d594fSAndroid Build Coastguard Worker * specifies an instruction that performs "result = op r0/r1". 259*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. 260*795d594fSAndroid Build Coastguard Worker * 261*795d594fSAndroid Build Coastguard Worker * For: neg-long, not-long, neg-double, long-to-double, double-to-long 262*795d594fSAndroid Build Coastguard Worker */ 263*795d594fSAndroid Build Coastguard Worker /* unop vA, vB */ 264*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 265*795d594fSAndroid Build Coastguard Worker ubfx rINST, rINST, #8, #4 @ rINST<- A 266*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r3, r3 @ r3<- &fp[B] 267*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, rINST @ r4<- &fp[A] 268*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r3 @ r0/r1<- vAA 269*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR rINST, ip, lr @ Zero shadow regs 270*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 271*795d594fSAndroid Build Coastguard Worker $preinstr @ optional op; may set condition codes 272*795d594fSAndroid Build Coastguard Worker $instr @ r0/r1<- op, r2-r3 changed 273*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 274*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1, r4 @ vAA<- r0/r1 275*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 276*795d594fSAndroid Build Coastguard Worker /* 10-11 instructions */ 277*795d594fSAndroid Build Coastguard Worker 278*795d594fSAndroid Build Coastguard Worker%def unopWider(preinstr="", instr=""): 279*795d594fSAndroid Build Coastguard Worker /* 280*795d594fSAndroid Build Coastguard Worker * Generic 32bit-to-64bit unary operation. Provide an "instr" line 281*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = op r0", where 282*795d594fSAndroid Build Coastguard Worker * "result" is a 64-bit quantity in r0/r1. 283*795d594fSAndroid Build Coastguard Worker * 284*795d594fSAndroid Build Coastguard Worker * For: int-to-long, int-to-double, float-to-long, float-to-double 285*795d594fSAndroid Build Coastguard Worker */ 286*795d594fSAndroid Build Coastguard Worker /* unop vA, vB */ 287*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 288*795d594fSAndroid Build Coastguard Worker ubfx rINST, rINST, #8, #4 @ rINST<- A 289*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r3 @ r0<- vB 290*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, rINST @ r4<- &fp[A] 291*795d594fSAndroid Build Coastguard Worker $preinstr @ optional op; may set condition codes 292*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR rINST, ip, lr @ Zero shadow regs 293*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 294*795d594fSAndroid Build Coastguard Worker $instr @ r0<- op, r0-r3 changed 295*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 296*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1, r4 @ vA/vA+1<- r0/r1 297*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 298*795d594fSAndroid Build Coastguard Worker /* 9-10 instructions */ 299*795d594fSAndroid Build Coastguard Worker 300*795d594fSAndroid Build Coastguard Worker%def op_add_int(): 301*795d594fSAndroid Build Coastguard Worker% binop(instr="add r0, r0, r1") 302*795d594fSAndroid Build Coastguard Worker 303*795d594fSAndroid Build Coastguard Worker%def op_add_int_2addr(): 304*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="add r0, r0, r1") 305*795d594fSAndroid Build Coastguard Worker 306*795d594fSAndroid Build Coastguard Worker%def op_add_int_lit16(): 307*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="add r0, r0, r1") 308*795d594fSAndroid Build Coastguard Worker 309*795d594fSAndroid Build Coastguard Worker%def op_add_int_lit8(): 310*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="", instr="add r0, r0, r3, asr #8") 311*795d594fSAndroid Build Coastguard Worker 312*795d594fSAndroid Build Coastguard Worker%def op_add_long(): 313*795d594fSAndroid Build Coastguard Worker% binopWide(preinstr="adds r0, r0, r2", instr="adc r1, r1, r3") 314*795d594fSAndroid Build Coastguard Worker 315*795d594fSAndroid Build Coastguard Worker%def op_add_long_2addr(): 316*795d594fSAndroid Build Coastguard Worker% binopWide2addr(preinstr="adds r0, r0, r2", instr="adc r1, r1, r3") 317*795d594fSAndroid Build Coastguard Worker 318*795d594fSAndroid Build Coastguard Worker%def op_and_int(): 319*795d594fSAndroid Build Coastguard Worker% binop(instr="and r0, r0, r1") 320*795d594fSAndroid Build Coastguard Worker 321*795d594fSAndroid Build Coastguard Worker%def op_and_int_2addr(): 322*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="and r0, r0, r1") 323*795d594fSAndroid Build Coastguard Worker 324*795d594fSAndroid Build Coastguard Worker%def op_and_int_lit16(): 325*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="and r0, r0, r1") 326*795d594fSAndroid Build Coastguard Worker 327*795d594fSAndroid Build Coastguard Worker%def op_and_int_lit8(): 328*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="", instr="and r0, r0, r3, asr #8") 329*795d594fSAndroid Build Coastguard Worker 330*795d594fSAndroid Build Coastguard Worker%def op_and_long(): 331*795d594fSAndroid Build Coastguard Worker% binopWide(preinstr="and r0, r0, r2", instr="and r1, r1, r3") 332*795d594fSAndroid Build Coastguard Worker 333*795d594fSAndroid Build Coastguard Worker%def op_and_long_2addr(): 334*795d594fSAndroid Build Coastguard Worker% binopWide2addr(preinstr="and r0, r0, r2", instr="and r1, r1, r3") 335*795d594fSAndroid Build Coastguard Worker 336*795d594fSAndroid Build Coastguard Worker%def op_cmp_long(): 337*795d594fSAndroid Build Coastguard Worker /* 338*795d594fSAndroid Build Coastguard Worker * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 339*795d594fSAndroid Build Coastguard Worker * register based on the results of the comparison. 340*795d594fSAndroid Build Coastguard Worker */ 341*795d594fSAndroid Build Coastguard Worker /* cmp-long vAA, vBB, vCC */ 342*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- CCBB 343*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 344*795d594fSAndroid Build Coastguard Worker and r2, r0, #255 @ r2<- BB 345*795d594fSAndroid Build Coastguard Worker mov r3, r0, lsr #8 @ r3<- CC 346*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r2, r2 @ r2<- &fp[BB] 347*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r3, r3 @ r3<- &fp[CC] 348*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r2 @ r0/r1<- vBB/vBB+1 349*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r2, r3, r3 @ r2/r3<- vCC/vCC+1 350*795d594fSAndroid Build Coastguard Worker cmp r0, r2 351*795d594fSAndroid Build Coastguard Worker sbcs ip, r1, r3 @ Sets correct CCs for checking LT (but not EQ/NE) 352*795d594fSAndroid Build Coastguard Worker mov r3, #-1 353*795d594fSAndroid Build Coastguard Worker it ge 354*795d594fSAndroid Build Coastguard Worker movge r3, #1 355*795d594fSAndroid Build Coastguard Worker it eq 356*795d594fSAndroid Build Coastguard Worker cmpeq r0, r2 357*795d594fSAndroid Build Coastguard Worker it eq 358*795d594fSAndroid Build Coastguard Worker moveq r3, #0 359*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 360*795d594fSAndroid Build Coastguard Worker SET_VREG r3, r4 @ vAA<- ip 361*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 362*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 363*795d594fSAndroid Build Coastguard Worker 364*795d594fSAndroid Build Coastguard Worker%def op_div_int(): 365*795d594fSAndroid Build Coastguard Worker /* 366*795d594fSAndroid Build Coastguard Worker * Specialized 32-bit binary operation 367*795d594fSAndroid Build Coastguard Worker * 368*795d594fSAndroid Build Coastguard Worker * Performs "r0 = r0 div r1". The selection between sdiv or the gcc helper 369*795d594fSAndroid Build Coastguard Worker * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for 370*795d594fSAndroid Build Coastguard Worker * ARMv7 CPUs that have hardware division support). 371*795d594fSAndroid Build Coastguard Worker * 372*795d594fSAndroid Build Coastguard Worker * div-int 373*795d594fSAndroid Build Coastguard Worker * 374*795d594fSAndroid Build Coastguard Worker */ 375*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- CCBB 376*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 377*795d594fSAndroid Build Coastguard Worker mov r3, r0, lsr #8 @ r3<- CC 378*795d594fSAndroid Build Coastguard Worker and r2, r0, #255 @ r2<- BB 379*795d594fSAndroid Build Coastguard Worker GET_VREG r1, r3 @ r1<- vCC 380*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vBB 381*795d594fSAndroid Build Coastguard Worker cmp r1, #0 @ is second operand zero? 382*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 383*795d594fSAndroid Build Coastguard Worker 384*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 385*795d594fSAndroid Build Coastguard Worker#ifdef __ARM_ARCH_EXT_IDIV__ 386*795d594fSAndroid Build Coastguard Worker sdiv r0, r0, r1 @ r0<- op 387*795d594fSAndroid Build Coastguard Worker#else 388*795d594fSAndroid Build Coastguard Worker bl __aeabi_idiv @ r0<- op, r0-r3 changed 389*795d594fSAndroid Build Coastguard Worker#endif 390*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 391*795d594fSAndroid Build Coastguard Worker SET_VREG r0, r4 @ vAA<- r0 392*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 393*795d594fSAndroid Build Coastguard Worker /* 11-14 instructions */ 394*795d594fSAndroid Build Coastguard Worker 395*795d594fSAndroid Build Coastguard Worker%def op_div_int_2addr(): 396*795d594fSAndroid Build Coastguard Worker /* 397*795d594fSAndroid Build Coastguard Worker * Specialized 32-bit binary operation 398*795d594fSAndroid Build Coastguard Worker * 399*795d594fSAndroid Build Coastguard Worker * Performs "r0 = r0 div r1". The selection between sdiv or the gcc helper 400*795d594fSAndroid Build Coastguard Worker * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for 401*795d594fSAndroid Build Coastguard Worker * ARMv7 CPUs that have hardware division support). 402*795d594fSAndroid Build Coastguard Worker * 403*795d594fSAndroid Build Coastguard Worker * div-int/2addr 404*795d594fSAndroid Build Coastguard Worker * 405*795d594fSAndroid Build Coastguard Worker */ 406*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 407*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 408*795d594fSAndroid Build Coastguard Worker GET_VREG r1, r3 @ r1<- vB 409*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r4 @ r0<- vA 410*795d594fSAndroid Build Coastguard Worker cmp r1, #0 @ is second operand zero? 411*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 412*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 413*795d594fSAndroid Build Coastguard Worker 414*795d594fSAndroid Build Coastguard Worker#ifdef __ARM_ARCH_EXT_IDIV__ 415*795d594fSAndroid Build Coastguard Worker sdiv r0, r0, r1 @ r0<- op 416*795d594fSAndroid Build Coastguard Worker#else 417*795d594fSAndroid Build Coastguard Worker bl __aeabi_idiv @ r0<- op, r0-r3 changed 418*795d594fSAndroid Build Coastguard Worker#endif 419*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 420*795d594fSAndroid Build Coastguard Worker SET_VREG r0, r4 @ vAA<- r0 421*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 422*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 423*795d594fSAndroid Build Coastguard Worker 424*795d594fSAndroid Build Coastguard Worker 425*795d594fSAndroid Build Coastguard Worker%def op_div_int_lit16(): 426*795d594fSAndroid Build Coastguard Worker /* 427*795d594fSAndroid Build Coastguard Worker * Specialized 32-bit binary operation 428*795d594fSAndroid Build Coastguard Worker * 429*795d594fSAndroid Build Coastguard Worker * Performs "r0 = r0 div r1". The selection between sdiv or the gcc helper 430*795d594fSAndroid Build Coastguard Worker * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for 431*795d594fSAndroid Build Coastguard Worker * ARMv7 CPUs that have hardware division support). 432*795d594fSAndroid Build Coastguard Worker * 433*795d594fSAndroid Build Coastguard Worker * div-int/lit16 434*795d594fSAndroid Build Coastguard Worker * 435*795d594fSAndroid Build Coastguard Worker */ 436*795d594fSAndroid Build Coastguard Worker FETCH_S r1, 1 @ r1<- ssssCCCC (sign-extended) 437*795d594fSAndroid Build Coastguard Worker mov r2, rINST, lsr #12 @ r2<- B 438*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 439*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vB 440*795d594fSAndroid Build Coastguard Worker cmp r1, #0 @ is second operand zero? 441*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 442*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 443*795d594fSAndroid Build Coastguard Worker 444*795d594fSAndroid Build Coastguard Worker#ifdef __ARM_ARCH_EXT_IDIV__ 445*795d594fSAndroid Build Coastguard Worker sdiv r0, r0, r1 @ r0<- op 446*795d594fSAndroid Build Coastguard Worker#else 447*795d594fSAndroid Build Coastguard Worker bl __aeabi_idiv @ r0<- op, r0-r3 changed 448*795d594fSAndroid Build Coastguard Worker#endif 449*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 450*795d594fSAndroid Build Coastguard Worker SET_VREG r0, r4 @ vAA<- r0 451*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 452*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 453*795d594fSAndroid Build Coastguard Worker 454*795d594fSAndroid Build Coastguard Worker%def op_div_int_lit8(): 455*795d594fSAndroid Build Coastguard Worker /* 456*795d594fSAndroid Build Coastguard Worker * Specialized 32-bit binary operation 457*795d594fSAndroid Build Coastguard Worker * 458*795d594fSAndroid Build Coastguard Worker * Performs "r0 = r0 div r1". The selection between sdiv or the gcc helper 459*795d594fSAndroid Build Coastguard Worker * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for 460*795d594fSAndroid Build Coastguard Worker * ARMv7 CPUs that have hardware division support). 461*795d594fSAndroid Build Coastguard Worker * 462*795d594fSAndroid Build Coastguard Worker * div-int/lit8 463*795d594fSAndroid Build Coastguard Worker * 464*795d594fSAndroid Build Coastguard Worker */ 465*795d594fSAndroid Build Coastguard Worker FETCH_S r3, 1 @ r3<- ssssCCBB (sign-extended for CC 466*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 467*795d594fSAndroid Build Coastguard Worker and r2, r3, #255 @ r2<- BB 468*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vBB 469*795d594fSAndroid Build Coastguard Worker movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 470*795d594fSAndroid Build Coastguard Worker @cmp r1, #0 @ is second operand zero? 471*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 472*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 473*795d594fSAndroid Build Coastguard Worker 474*795d594fSAndroid Build Coastguard Worker#ifdef __ARM_ARCH_EXT_IDIV__ 475*795d594fSAndroid Build Coastguard Worker sdiv r0, r0, r1 @ r0<- op 476*795d594fSAndroid Build Coastguard Worker#else 477*795d594fSAndroid Build Coastguard Worker bl __aeabi_idiv @ r0<- op, r0-r3 changed 478*795d594fSAndroid Build Coastguard Worker#endif 479*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 480*795d594fSAndroid Build Coastguard Worker SET_VREG r0, r4 @ vAA<- r0 481*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 482*795d594fSAndroid Build Coastguard Worker /* 10-12 instructions */ 483*795d594fSAndroid Build Coastguard Worker 484*795d594fSAndroid Build Coastguard Worker%def op_div_long(): 485*795d594fSAndroid Build Coastguard Worker% binopWide(instr="bl __aeabi_ldivmod", chkzero="1") 486*795d594fSAndroid Build Coastguard Worker 487*795d594fSAndroid Build Coastguard Worker%def op_div_long_2addr(): 488*795d594fSAndroid Build Coastguard Worker% binopWide2addr(instr="bl __aeabi_ldivmod", chkzero="1") 489*795d594fSAndroid Build Coastguard Worker 490*795d594fSAndroid Build Coastguard Worker%def op_int_to_byte(): 491*795d594fSAndroid Build Coastguard Worker% unop(instr="sxtb r0, r0") 492*795d594fSAndroid Build Coastguard Worker 493*795d594fSAndroid Build Coastguard Worker%def op_int_to_char(): 494*795d594fSAndroid Build Coastguard Worker% unop(instr="uxth r0, r0") 495*795d594fSAndroid Build Coastguard Worker 496*795d594fSAndroid Build Coastguard Worker%def op_int_to_long(): 497*795d594fSAndroid Build Coastguard Worker% unopWider(instr="mov r1, r0, asr #31") 498*795d594fSAndroid Build Coastguard Worker 499*795d594fSAndroid Build Coastguard Worker%def op_int_to_short(): 500*795d594fSAndroid Build Coastguard Worker% unop(instr="sxth r0, r0") 501*795d594fSAndroid Build Coastguard Worker 502*795d594fSAndroid Build Coastguard Worker%def op_long_to_int(): 503*795d594fSAndroid Build Coastguard Worker/* we ignore the high word, making this equivalent to a 32-bit reg move */ 504*795d594fSAndroid Build Coastguard Worker% op_move() 505*795d594fSAndroid Build Coastguard Worker 506*795d594fSAndroid Build Coastguard Worker/* 507*795d594fSAndroid Build Coastguard Worker * We use "mul r0, r1, r0" instead of "r0, r0, r1". The latter was illegal in old versions. 508*795d594fSAndroid Build Coastguard Worker * Also, for T32, this operand order allows using a 16-bit instruction (encoding T1) while the 509*795d594fSAndroid Build Coastguard Worker * other order would require 32-bit instruction (encoding T2). 510*795d594fSAndroid Build Coastguard Worker */ 511*795d594fSAndroid Build Coastguard Worker 512*795d594fSAndroid Build Coastguard Worker%def op_mul_int(): 513*795d594fSAndroid Build Coastguard Worker% binop(instr="mul r0, r1, r0") 514*795d594fSAndroid Build Coastguard Worker 515*795d594fSAndroid Build Coastguard Worker%def op_mul_int_2addr(): 516*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="mul r0, r1, r0") 517*795d594fSAndroid Build Coastguard Worker 518*795d594fSAndroid Build Coastguard Worker%def op_mul_int_lit16(): 519*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="mul r0, r1, r0") 520*795d594fSAndroid Build Coastguard Worker 521*795d594fSAndroid Build Coastguard Worker%def op_mul_int_lit8(): 522*795d594fSAndroid Build Coastguard Worker% binopLit8(instr="mul r0, r1, r0") 523*795d594fSAndroid Build Coastguard Worker 524*795d594fSAndroid Build Coastguard Worker%def op_mul_long(): 525*795d594fSAndroid Build Coastguard Worker /* 526*795d594fSAndroid Build Coastguard Worker * Signed 64-bit integer multiply. 527*795d594fSAndroid Build Coastguard Worker * 528*795d594fSAndroid Build Coastguard Worker * Consider WXxYZ (r1r0 x r3r2) with a long multiply: 529*795d594fSAndroid Build Coastguard Worker * WX 530*795d594fSAndroid Build Coastguard Worker * x YZ 531*795d594fSAndroid Build Coastguard Worker * -------- 532*795d594fSAndroid Build Coastguard Worker * ZW ZX 533*795d594fSAndroid Build Coastguard Worker * YW YX 534*795d594fSAndroid Build Coastguard Worker * 535*795d594fSAndroid Build Coastguard Worker * The low word of the result holds ZX, the high word holds 536*795d594fSAndroid Build Coastguard Worker * (ZW+YX) + (the high overflow from ZX). YW doesn't matter because 537*795d594fSAndroid Build Coastguard Worker * it doesn't fit in the low 64 bits. 538*795d594fSAndroid Build Coastguard Worker * 539*795d594fSAndroid Build Coastguard Worker * Unlike most ARM math operations, multiply instructions have 540*795d594fSAndroid Build Coastguard Worker * restrictions on using the same register more than once (Rd and Rn 541*795d594fSAndroid Build Coastguard Worker * cannot be the same). 542*795d594fSAndroid Build Coastguard Worker */ 543*795d594fSAndroid Build Coastguard Worker /* mul-long vAA, vBB, vCC */ 544*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- CCBB 545*795d594fSAndroid Build Coastguard Worker and r2, r0, #255 @ r2<- BB 546*795d594fSAndroid Build Coastguard Worker mov r3, r0, lsr #8 @ r3<- CC 547*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r2, r2 @ r2<- &fp[BB] 548*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r3, r3 @ r3<- &fp[CC] 549*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r2 @ r0/r1<- vBB/vBB+1 550*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r2, r3, r3 @ r2/r3<- vCC/vCC+1 551*795d594fSAndroid Build Coastguard Worker mul ip, r0, r3 @ ip<- YxX 552*795d594fSAndroid Build Coastguard Worker umull r0, lr, r2, r0 @ r0/lr <- ZxX RdLo == Rn - this is OK. 553*795d594fSAndroid Build Coastguard Worker mla r3, r1, r2, ip @ r3<- YxX + (ZxW) 554*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 555*795d594fSAndroid Build Coastguard Worker add r1, r3, lr @ r1<- lr + low(ZxW + (YxX)) 556*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR r4, lr, ip @ Zero out the shadow regs 557*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, r4 @ r2<- &fp[AA] 558*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 559*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 560*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1 , r4 @ vAA/vAA+1<- r1/r2 561*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 562*795d594fSAndroid Build Coastguard Worker 563*795d594fSAndroid Build Coastguard Worker%def op_mul_long_2addr(): 564*795d594fSAndroid Build Coastguard Worker /* 565*795d594fSAndroid Build Coastguard Worker * Signed 64-bit integer multiply, "/2addr" version. 566*795d594fSAndroid Build Coastguard Worker * 567*795d594fSAndroid Build Coastguard Worker * See op_mul_long for an explanation. 568*795d594fSAndroid Build Coastguard Worker * 569*795d594fSAndroid Build Coastguard Worker * We get a little tight on registers, so to avoid looking up &fp[A] 570*795d594fSAndroid Build Coastguard Worker * again we stuff it into rINST. 571*795d594fSAndroid Build Coastguard Worker */ 572*795d594fSAndroid Build Coastguard Worker /* mul-long/2addr vA, vB */ 573*795d594fSAndroid Build Coastguard Worker mov r1, rINST, lsr #12 @ r1<- B 574*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 575*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r1, r1 @ r1<- &fp[B] 576*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR rINST, r4 @ rINST<- &fp[A] 577*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r2, r3, r1 @ r2/r3<- vBB/vBB+1 578*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, rINST @ r0/r1<- vAA/vAA+1 579*795d594fSAndroid Build Coastguard Worker mul ip, r0, r3 @ ip<- YxX 580*795d594fSAndroid Build Coastguard Worker umull r0, lr, r2, r0 @ r0/lr <- ZxX RdLo == Rn - this is OK. 581*795d594fSAndroid Build Coastguard Worker mla r3, r1, r2, ip @ r3<- YxX + (ZxW) 582*795d594fSAndroid Build Coastguard Worker mov r4, rINST @ Save vAA before FETCH_ADVANCE_INST 583*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 584*795d594fSAndroid Build Coastguard Worker add r1, r3, lr @ r1<- lr + low(ZxW + (YxX)) 585*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 586*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1, r4 @ vAA/vAA+1<- r0/r1 587*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 588*795d594fSAndroid Build Coastguard Worker 589*795d594fSAndroid Build Coastguard Worker%def op_neg_int(): 590*795d594fSAndroid Build Coastguard Worker% unop(instr="rsb r0, r0, #0") 591*795d594fSAndroid Build Coastguard Worker 592*795d594fSAndroid Build Coastguard Worker%def op_neg_long(): 593*795d594fSAndroid Build Coastguard Worker% unopWide(preinstr="rsbs r0, r0, #0", instr="rsc r1, r1, #0") 594*795d594fSAndroid Build Coastguard Worker 595*795d594fSAndroid Build Coastguard Worker%def op_not_int(): 596*795d594fSAndroid Build Coastguard Worker% unop(instr="mvn r0, r0") 597*795d594fSAndroid Build Coastguard Worker 598*795d594fSAndroid Build Coastguard Worker%def op_not_long(): 599*795d594fSAndroid Build Coastguard Worker% unopWide(preinstr="mvn r0, r0", instr="mvn r1, r1") 600*795d594fSAndroid Build Coastguard Worker 601*795d594fSAndroid Build Coastguard Worker%def op_or_int(): 602*795d594fSAndroid Build Coastguard Worker% binop(instr="orr r0, r0, r1") 603*795d594fSAndroid Build Coastguard Worker 604*795d594fSAndroid Build Coastguard Worker%def op_or_int_2addr(): 605*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="orr r0, r0, r1") 606*795d594fSAndroid Build Coastguard Worker 607*795d594fSAndroid Build Coastguard Worker%def op_or_int_lit16(): 608*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="orr r0, r0, r1") 609*795d594fSAndroid Build Coastguard Worker 610*795d594fSAndroid Build Coastguard Worker%def op_or_int_lit8(): 611*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="", instr="orr r0, r0, r3, asr #8") 612*795d594fSAndroid Build Coastguard Worker 613*795d594fSAndroid Build Coastguard Worker%def op_or_long(): 614*795d594fSAndroid Build Coastguard Worker% binopWide(preinstr="orr r0, r0, r2", instr="orr r1, r1, r3") 615*795d594fSAndroid Build Coastguard Worker 616*795d594fSAndroid Build Coastguard Worker%def op_or_long_2addr(): 617*795d594fSAndroid Build Coastguard Worker% binopWide2addr(preinstr="orr r0, r0, r2", instr="orr r1, r1, r3") 618*795d594fSAndroid Build Coastguard Worker 619*795d594fSAndroid Build Coastguard Worker%def op_rem_int(): 620*795d594fSAndroid Build Coastguard Worker /* 621*795d594fSAndroid Build Coastguard Worker * Specialized 32-bit binary operation 622*795d594fSAndroid Build Coastguard Worker * 623*795d594fSAndroid Build Coastguard Worker * Performs "r1 = r0 rem r1". The selection between sdiv block or the gcc helper 624*795d594fSAndroid Build Coastguard Worker * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for 625*795d594fSAndroid Build Coastguard Worker * ARMv7 CPUs that have hardware division support). 626*795d594fSAndroid Build Coastguard Worker * 627*795d594fSAndroid Build Coastguard Worker * NOTE: idivmod returns quotient in r0 and remainder in r1 628*795d594fSAndroid Build Coastguard Worker * 629*795d594fSAndroid Build Coastguard Worker * rem-int 630*795d594fSAndroid Build Coastguard Worker * 631*795d594fSAndroid Build Coastguard Worker */ 632*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- CCBB 633*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 634*795d594fSAndroid Build Coastguard Worker mov r3, r0, lsr #8 @ r3<- CC 635*795d594fSAndroid Build Coastguard Worker and r2, r0, #255 @ r2<- BB 636*795d594fSAndroid Build Coastguard Worker GET_VREG r1, r3 @ r1<- vCC 637*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vBB 638*795d594fSAndroid Build Coastguard Worker cmp r1, #0 @ is second operand zero? 639*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 640*795d594fSAndroid Build Coastguard Worker 641*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 642*795d594fSAndroid Build Coastguard Worker#ifdef __ARM_ARCH_EXT_IDIV__ 643*795d594fSAndroid Build Coastguard Worker sdiv r2, r0, r1 644*795d594fSAndroid Build Coastguard Worker mls r1, r1, r2, r0 @ r1<- op, r0-r2 changed 645*795d594fSAndroid Build Coastguard Worker#else 646*795d594fSAndroid Build Coastguard Worker bl __aeabi_idivmod @ r1<- op, r0-r3 changed 647*795d594fSAndroid Build Coastguard Worker#endif 648*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 649*795d594fSAndroid Build Coastguard Worker SET_VREG r1, r4 @ vAA<- r1 650*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 651*795d594fSAndroid Build Coastguard Worker /* 11-14 instructions */ 652*795d594fSAndroid Build Coastguard Worker 653*795d594fSAndroid Build Coastguard Worker%def op_rem_int_2addr(): 654*795d594fSAndroid Build Coastguard Worker /* 655*795d594fSAndroid Build Coastguard Worker * Specialized 32-bit binary operation 656*795d594fSAndroid Build Coastguard Worker * 657*795d594fSAndroid Build Coastguard Worker * Performs "r1 = r0 rem r1". The selection between sdiv block or the gcc helper 658*795d594fSAndroid Build Coastguard Worker * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for 659*795d594fSAndroid Build Coastguard Worker * ARMv7 CPUs that have hardware division support). 660*795d594fSAndroid Build Coastguard Worker * 661*795d594fSAndroid Build Coastguard Worker * NOTE: idivmod returns quotient in r0 and remainder in r1 662*795d594fSAndroid Build Coastguard Worker * 663*795d594fSAndroid Build Coastguard Worker * rem-int/2addr 664*795d594fSAndroid Build Coastguard Worker * 665*795d594fSAndroid Build Coastguard Worker */ 666*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 667*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 668*795d594fSAndroid Build Coastguard Worker GET_VREG r1, r3 @ r1<- vB 669*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r4 @ r0<- vA 670*795d594fSAndroid Build Coastguard Worker cmp r1, #0 @ is second operand zero? 671*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 672*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 673*795d594fSAndroid Build Coastguard Worker 674*795d594fSAndroid Build Coastguard Worker#ifdef __ARM_ARCH_EXT_IDIV__ 675*795d594fSAndroid Build Coastguard Worker sdiv r2, r0, r1 676*795d594fSAndroid Build Coastguard Worker mls r1, r1, r2, r0 @ r1<- op 677*795d594fSAndroid Build Coastguard Worker#else 678*795d594fSAndroid Build Coastguard Worker bl __aeabi_idivmod @ r1<- op, r0-r3 changed 679*795d594fSAndroid Build Coastguard Worker#endif 680*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 681*795d594fSAndroid Build Coastguard Worker SET_VREG r1, r4 @ vAA<- r1 682*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 683*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 684*795d594fSAndroid Build Coastguard Worker 685*795d594fSAndroid Build Coastguard Worker 686*795d594fSAndroid Build Coastguard Worker%def op_rem_int_lit16(): 687*795d594fSAndroid Build Coastguard Worker /* 688*795d594fSAndroid Build Coastguard Worker * Specialized 32-bit binary operation 689*795d594fSAndroid Build Coastguard Worker * 690*795d594fSAndroid Build Coastguard Worker * Performs "r1 = r0 rem r1". The selection between sdiv block or the gcc helper 691*795d594fSAndroid Build Coastguard Worker * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for 692*795d594fSAndroid Build Coastguard Worker * ARMv7 CPUs that have hardware division support). 693*795d594fSAndroid Build Coastguard Worker * 694*795d594fSAndroid Build Coastguard Worker * NOTE: idivmod returns quotient in r0 and remainder in r1 695*795d594fSAndroid Build Coastguard Worker * 696*795d594fSAndroid Build Coastguard Worker * rem-int/lit16 697*795d594fSAndroid Build Coastguard Worker * 698*795d594fSAndroid Build Coastguard Worker */ 699*795d594fSAndroid Build Coastguard Worker FETCH_S r1, 1 @ r1<- ssssCCCC (sign-extended) 700*795d594fSAndroid Build Coastguard Worker mov r2, rINST, lsr #12 @ r2<- B 701*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 702*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vB 703*795d594fSAndroid Build Coastguard Worker cmp r1, #0 @ is second operand zero? 704*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 705*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 706*795d594fSAndroid Build Coastguard Worker 707*795d594fSAndroid Build Coastguard Worker#ifdef __ARM_ARCH_EXT_IDIV__ 708*795d594fSAndroid Build Coastguard Worker sdiv r2, r0, r1 709*795d594fSAndroid Build Coastguard Worker mls r1, r1, r2, r0 @ r1<- op 710*795d594fSAndroid Build Coastguard Worker#else 711*795d594fSAndroid Build Coastguard Worker bl __aeabi_idivmod @ r1<- op, r0-r3 changed 712*795d594fSAndroid Build Coastguard Worker#endif 713*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 714*795d594fSAndroid Build Coastguard Worker SET_VREG r1, r4 @ vAA<- r1 715*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 716*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 717*795d594fSAndroid Build Coastguard Worker 718*795d594fSAndroid Build Coastguard Worker%def op_rem_int_lit8(): 719*795d594fSAndroid Build Coastguard Worker /* 720*795d594fSAndroid Build Coastguard Worker * Specialized 32-bit binary operation 721*795d594fSAndroid Build Coastguard Worker * 722*795d594fSAndroid Build Coastguard Worker * Performs "r1 = r0 rem r1". The selection between sdiv block or the gcc helper 723*795d594fSAndroid Build Coastguard Worker * depends on the compile time value of __ARM_ARCH_EXT_IDIV__ (defined for 724*795d594fSAndroid Build Coastguard Worker * ARMv7 CPUs that have hardware division support). 725*795d594fSAndroid Build Coastguard Worker * 726*795d594fSAndroid Build Coastguard Worker * NOTE: idivmod returns quotient in r0 and remainder in r1 727*795d594fSAndroid Build Coastguard Worker * 728*795d594fSAndroid Build Coastguard Worker * rem-int/lit8 729*795d594fSAndroid Build Coastguard Worker * 730*795d594fSAndroid Build Coastguard Worker */ 731*795d594fSAndroid Build Coastguard Worker FETCH_S r3, 1 @ r3<- ssssCCBB (sign-extended for CC) 732*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 733*795d594fSAndroid Build Coastguard Worker and r2, r3, #255 @ r2<- BB 734*795d594fSAndroid Build Coastguard Worker GET_VREG r0, r2 @ r0<- vBB 735*795d594fSAndroid Build Coastguard Worker movs r1, r3, asr #8 @ r1<- ssssssCC (sign extended) 736*795d594fSAndroid Build Coastguard Worker @cmp r1, #0 @ is second operand zero? 737*795d594fSAndroid Build Coastguard Worker beq common_errDivideByZero 738*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 739*795d594fSAndroid Build Coastguard Worker 740*795d594fSAndroid Build Coastguard Worker#ifdef __ARM_ARCH_EXT_IDIV__ 741*795d594fSAndroid Build Coastguard Worker sdiv r2, r0, r1 742*795d594fSAndroid Build Coastguard Worker mls r1, r1, r2, r0 @ r1<- op 743*795d594fSAndroid Build Coastguard Worker#else 744*795d594fSAndroid Build Coastguard Worker bl __aeabi_idivmod @ r1<- op, r0-r3 changed 745*795d594fSAndroid Build Coastguard Worker#endif 746*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 747*795d594fSAndroid Build Coastguard Worker SET_VREG r1, r4 @ vAA<- r1 748*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 749*795d594fSAndroid Build Coastguard Worker /* 10-12 instructions */ 750*795d594fSAndroid Build Coastguard Worker 751*795d594fSAndroid Build Coastguard Worker%def op_rem_long(): 752*795d594fSAndroid Build Coastguard Worker/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 753*795d594fSAndroid Build Coastguard Worker% binopWide(instr="bl __aeabi_ldivmod", result0="r2", result1="r3", chkzero="1") 754*795d594fSAndroid Build Coastguard Worker 755*795d594fSAndroid Build Coastguard Worker%def op_rem_long_2addr(): 756*795d594fSAndroid Build Coastguard Worker/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */ 757*795d594fSAndroid Build Coastguard Worker% binopWide2addr(instr="bl __aeabi_ldivmod", result0="r2", result1="r3", chkzero="1") 758*795d594fSAndroid Build Coastguard Worker 759*795d594fSAndroid Build Coastguard Worker%def op_rsub_int(): 760*795d594fSAndroid Build Coastguard Worker/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 761*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="rsb r0, r0, r1") 762*795d594fSAndroid Build Coastguard Worker 763*795d594fSAndroid Build Coastguard Worker%def op_rsub_int_lit8(): 764*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="", instr="rsb r0, r0, r3, asr #8") 765*795d594fSAndroid Build Coastguard Worker 766*795d594fSAndroid Build Coastguard Worker%def op_shl_int(): 767*795d594fSAndroid Build Coastguard Worker% binop(preinstr="and r1, r1, #31", instr="mov r0, r0, lsl r1") 768*795d594fSAndroid Build Coastguard Worker 769*795d594fSAndroid Build Coastguard Worker%def op_shl_int_2addr(): 770*795d594fSAndroid Build Coastguard Worker% binop2addr(preinstr="and r1, r1, #31", instr="mov r0, r0, lsl r1") 771*795d594fSAndroid Build Coastguard Worker 772*795d594fSAndroid Build Coastguard Worker%def op_shl_int_lit8(): 773*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="ubfx r1, r3, #8, #5", instr="mov r0, r0, lsl r1") 774*795d594fSAndroid Build Coastguard Worker 775*795d594fSAndroid Build Coastguard Worker%def op_shl_long(): 776*795d594fSAndroid Build Coastguard Worker /* 777*795d594fSAndroid Build Coastguard Worker * Long integer shift. This is different from the generic 32/64-bit 778*795d594fSAndroid Build Coastguard Worker * binary operations because vAA/vBB are 64-bit but vCC (the shift 779*795d594fSAndroid Build Coastguard Worker * distance) is 32-bit. Also, Dalvik requires us to mask off the low 780*795d594fSAndroid Build Coastguard Worker * 6 bits of the shift distance. 781*795d594fSAndroid Build Coastguard Worker */ 782*795d594fSAndroid Build Coastguard Worker /* shl-long vAA, vBB, vCC */ 783*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- CCBB 784*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 785*795d594fSAndroid Build Coastguard Worker and r3, r0, #255 @ r3<- BB 786*795d594fSAndroid Build Coastguard Worker mov r0, r0, lsr #8 @ r0<- CC 787*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r3, r3 @ r3<- &fp[BB] 788*795d594fSAndroid Build Coastguard Worker GET_VREG r2, r0 @ r2<- vCC 789*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r3 @ r0/r1<- vBB/vBB+1 790*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR r4, lr, ip @ Zero out the shadow regs 791*795d594fSAndroid Build Coastguard Worker and r2, r2, #63 @ r2<- r2 & 0x3f 792*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[AA] 793*795d594fSAndroid Build Coastguard Worker mov r1, r1, asl r2 @ r1<- r1 << r2 794*795d594fSAndroid Build Coastguard Worker rsb r3, r2, #32 @ r3<- 32 - r2 795*795d594fSAndroid Build Coastguard Worker orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 796*795d594fSAndroid Build Coastguard Worker subs ip, r2, #32 @ ip<- r2 - 32 797*795d594fSAndroid Build Coastguard Worker it pl 798*795d594fSAndroid Build Coastguard Worker movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 799*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 800*795d594fSAndroid Build Coastguard Worker mov r0, r0, asl r2 @ r0<- r0 << r2 801*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 802*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1, r4 @ vAA/vAA+1<- r0/r1 803*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 804*795d594fSAndroid Build Coastguard Worker 805*795d594fSAndroid Build Coastguard Worker%def op_shl_long_2addr(): 806*795d594fSAndroid Build Coastguard Worker /* 807*795d594fSAndroid Build Coastguard Worker * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 808*795d594fSAndroid Build Coastguard Worker * 32-bit shift distance. 809*795d594fSAndroid Build Coastguard Worker */ 810*795d594fSAndroid Build Coastguard Worker /* shl-long/2addr vA, vB */ 811*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 812*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 813*795d594fSAndroid Build Coastguard Worker GET_VREG r2, r3 @ r2<- vB 814*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR r4, lr, ip @ Zero out the shadow regs 815*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[A] 816*795d594fSAndroid Build Coastguard Worker and r2, r2, #63 @ r2<- r2 & 0x3f 817*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r4 @ r0/r1<- vAA/vAA+1 818*795d594fSAndroid Build Coastguard Worker mov r1, r1, asl r2 @ r1<- r1 << r2 819*795d594fSAndroid Build Coastguard Worker rsb r3, r2, #32 @ r3<- 32 - r2 820*795d594fSAndroid Build Coastguard Worker orr r1, r1, r0, lsr r3 @ r1<- r1 | (r0 << (32-r2)) 821*795d594fSAndroid Build Coastguard Worker subs ip, r2, #32 @ ip<- r2 - 32 822*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 823*795d594fSAndroid Build Coastguard Worker it pl 824*795d594fSAndroid Build Coastguard Worker movpl r1, r0, asl ip @ if r2 >= 32, r1<- r0 << (r2-32) 825*795d594fSAndroid Build Coastguard Worker mov r0, r0, asl r2 @ r0<- r0 << r2 826*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 827*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1, r4 @ vAA/vAA+1<- r0/r1 828*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 829*795d594fSAndroid Build Coastguard Worker 830*795d594fSAndroid Build Coastguard Worker%def op_shr_int(): 831*795d594fSAndroid Build Coastguard Worker% binop(preinstr="and r1, r1, #31", instr="mov r0, r0, asr r1") 832*795d594fSAndroid Build Coastguard Worker 833*795d594fSAndroid Build Coastguard Worker%def op_shr_int_2addr(): 834*795d594fSAndroid Build Coastguard Worker% binop2addr(preinstr="and r1, r1, #31", instr="mov r0, r0, asr r1") 835*795d594fSAndroid Build Coastguard Worker 836*795d594fSAndroid Build Coastguard Worker%def op_shr_int_lit8(): 837*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="ubfx r1, r3, #8, #5", instr="mov r0, r0, asr r1") 838*795d594fSAndroid Build Coastguard Worker 839*795d594fSAndroid Build Coastguard Worker%def op_shr_long(): 840*795d594fSAndroid Build Coastguard Worker /* 841*795d594fSAndroid Build Coastguard Worker * Long integer shift. This is different from the generic 32/64-bit 842*795d594fSAndroid Build Coastguard Worker * binary operations because vAA/vBB are 64-bit but vCC (the shift 843*795d594fSAndroid Build Coastguard Worker * distance) is 32-bit. Also, Dalvik requires us to mask off the low 844*795d594fSAndroid Build Coastguard Worker * 6 bits of the shift distance. 845*795d594fSAndroid Build Coastguard Worker */ 846*795d594fSAndroid Build Coastguard Worker /* shr-long vAA, vBB, vCC */ 847*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- CCBB 848*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 849*795d594fSAndroid Build Coastguard Worker and r3, r0, #255 @ r3<- BB 850*795d594fSAndroid Build Coastguard Worker mov r0, r0, lsr #8 @ r0<- CC 851*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r3, r3 @ r3<- &fp[BB] 852*795d594fSAndroid Build Coastguard Worker GET_VREG r2, r0 @ r2<- vCC 853*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r3 @ r0/r1<- vBB/vBB+1 854*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR r4, lr, ip @ Zero out the shadow regs 855*795d594fSAndroid Build Coastguard Worker and r2, r2, #63 @ r0<- r0 & 0x3f 856*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[AA] 857*795d594fSAndroid Build Coastguard Worker mov r0, r0, lsr r2 @ r0<- r2 >> r2 858*795d594fSAndroid Build Coastguard Worker rsb r3, r2, #32 @ r3<- 32 - r2 859*795d594fSAndroid Build Coastguard Worker orr r0, r0, r1, lsl r3 @ r0<- r0 | (r1 << (32-r2)) 860*795d594fSAndroid Build Coastguard Worker subs ip, r2, #32 @ ip<- r2 - 32 861*795d594fSAndroid Build Coastguard Worker it pl 862*795d594fSAndroid Build Coastguard Worker movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 863*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 864*795d594fSAndroid Build Coastguard Worker mov r1, r1, asr r2 @ r1<- r1 >> r2 865*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 866*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1, r4 @ vAA/vAA+1<- r0/r1 867*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 868*795d594fSAndroid Build Coastguard Worker 869*795d594fSAndroid Build Coastguard Worker%def op_shr_long_2addr(): 870*795d594fSAndroid Build Coastguard Worker /* 871*795d594fSAndroid Build Coastguard Worker * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 872*795d594fSAndroid Build Coastguard Worker * 32-bit shift distance. 873*795d594fSAndroid Build Coastguard Worker */ 874*795d594fSAndroid Build Coastguard Worker /* shr-long/2addr vA, vB */ 875*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 876*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 877*795d594fSAndroid Build Coastguard Worker GET_VREG r2, r3 @ r2<- vB 878*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR r4, lr, ip @ Zero out the shadow regs 879*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[A] 880*795d594fSAndroid Build Coastguard Worker and r2, r2, #63 @ r2<- r2 & 0x3f 881*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r4 @ r0/r1<- vAA/vAA+1 882*795d594fSAndroid Build Coastguard Worker mov r0, r0, lsr r2 @ r0<- r2 >> r2 883*795d594fSAndroid Build Coastguard Worker rsb r3, r2, #32 @ r3<- 32 - r2 884*795d594fSAndroid Build Coastguard Worker orr r0, r0, r1, lsl r3 @ r0<- r0 | (r1 << (32-r2)) 885*795d594fSAndroid Build Coastguard Worker subs ip, r2, #32 @ ip<- r2 - 32 886*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 887*795d594fSAndroid Build Coastguard Worker it pl 888*795d594fSAndroid Build Coastguard Worker movpl r0, r1, asr ip @ if r2 >= 32, r0<-r1 >> (r2-32) 889*795d594fSAndroid Build Coastguard Worker mov r1, r1, asr r2 @ r1<- r1 >> r2 890*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 891*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1, r4 @ vAA/vAA+1<- r0/r1 892*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 893*795d594fSAndroid Build Coastguard Worker 894*795d594fSAndroid Build Coastguard Worker%def op_sub_int(): 895*795d594fSAndroid Build Coastguard Worker% binop(instr="sub r0, r0, r1") 896*795d594fSAndroid Build Coastguard Worker 897*795d594fSAndroid Build Coastguard Worker%def op_sub_int_2addr(): 898*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="sub r0, r0, r1") 899*795d594fSAndroid Build Coastguard Worker 900*795d594fSAndroid Build Coastguard Worker%def op_sub_long(): 901*795d594fSAndroid Build Coastguard Worker% binopWide(preinstr="subs r0, r0, r2", instr="sbc r1, r1, r3") 902*795d594fSAndroid Build Coastguard Worker 903*795d594fSAndroid Build Coastguard Worker%def op_sub_long_2addr(): 904*795d594fSAndroid Build Coastguard Worker% binopWide2addr(preinstr="subs r0, r0, r2", instr="sbc r1, r1, r3") 905*795d594fSAndroid Build Coastguard Worker 906*795d594fSAndroid Build Coastguard Worker%def op_ushr_int(): 907*795d594fSAndroid Build Coastguard Worker% binop(preinstr="and r1, r1, #31", instr="mov r0, r0, lsr r1") 908*795d594fSAndroid Build Coastguard Worker 909*795d594fSAndroid Build Coastguard Worker%def op_ushr_int_2addr(): 910*795d594fSAndroid Build Coastguard Worker% binop2addr(preinstr="and r1, r1, #31", instr="mov r0, r0, lsr r1") 911*795d594fSAndroid Build Coastguard Worker 912*795d594fSAndroid Build Coastguard Worker%def op_ushr_int_lit8(): 913*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="ubfx r1, r3, #8, #5", instr="mov r0, r0, lsr r1") 914*795d594fSAndroid Build Coastguard Worker 915*795d594fSAndroid Build Coastguard Worker%def op_ushr_long(): 916*795d594fSAndroid Build Coastguard Worker /* 917*795d594fSAndroid Build Coastguard Worker * Long integer shift. This is different from the generic 32/64-bit 918*795d594fSAndroid Build Coastguard Worker * binary operations because vAA/vBB are 64-bit but vCC (the shift 919*795d594fSAndroid Build Coastguard Worker * distance) is 32-bit. Also, Dalvik requires us to mask off the low 920*795d594fSAndroid Build Coastguard Worker * 6 bits of the shift distance. 921*795d594fSAndroid Build Coastguard Worker */ 922*795d594fSAndroid Build Coastguard Worker /* ushr-long vAA, vBB, vCC */ 923*795d594fSAndroid Build Coastguard Worker FETCH r0, 1 @ r0<- CCBB 924*795d594fSAndroid Build Coastguard Worker mov r4, rINST, lsr #8 @ r4<- AA 925*795d594fSAndroid Build Coastguard Worker and r3, r0, #255 @ r3<- BB 926*795d594fSAndroid Build Coastguard Worker mov r0, r0, lsr #8 @ r0<- CC 927*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r3, r3 @ r3<- &fp[BB] 928*795d594fSAndroid Build Coastguard Worker GET_VREG r2, r0 @ r2<- vCC 929*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r3 @ r0/r1<- vBB/vBB+1 930*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR r4, lr, ip @ Zero out the shadow regs 931*795d594fSAndroid Build Coastguard Worker and r2, r2, #63 @ r0<- r0 & 0x3f 932*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[AA] 933*795d594fSAndroid Build Coastguard Worker mov r0, r0, lsr r2 @ r0<- r2 >> r2 934*795d594fSAndroid Build Coastguard Worker rsb r3, r2, #32 @ r3<- 32 - r2 935*795d594fSAndroid Build Coastguard Worker orr r0, r0, r1, lsl r3 @ r0<- r0 | (r1 << (32-r2)) 936*795d594fSAndroid Build Coastguard Worker subs ip, r2, #32 @ ip<- r2 - 32 937*795d594fSAndroid Build Coastguard Worker it pl 938*795d594fSAndroid Build Coastguard Worker movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 939*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 940*795d594fSAndroid Build Coastguard Worker mov r1, r1, lsr r2 @ r1<- r1 >>> r2 941*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 942*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1, r4 @ vAA/vAA+1<- r0/r1 943*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 944*795d594fSAndroid Build Coastguard Worker 945*795d594fSAndroid Build Coastguard Worker%def op_ushr_long_2addr(): 946*795d594fSAndroid Build Coastguard Worker /* 947*795d594fSAndroid Build Coastguard Worker * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 948*795d594fSAndroid Build Coastguard Worker * 32-bit shift distance. 949*795d594fSAndroid Build Coastguard Worker */ 950*795d594fSAndroid Build Coastguard Worker /* ushr-long/2addr vA, vB */ 951*795d594fSAndroid Build Coastguard Worker mov r3, rINST, lsr #12 @ r3<- B 952*795d594fSAndroid Build Coastguard Worker ubfx r4, rINST, #8, #4 @ r4<- A 953*795d594fSAndroid Build Coastguard Worker GET_VREG r2, r3 @ r2<- vB 954*795d594fSAndroid Build Coastguard Worker CLEAR_SHADOW_PAIR r4, lr, ip @ Zero out the shadow regs 955*795d594fSAndroid Build Coastguard Worker VREG_INDEX_TO_ADDR r4, r4 @ r4<- &fp[A] 956*795d594fSAndroid Build Coastguard Worker and r2, r2, #63 @ r2<- r2 & 0x3f 957*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_BY_ADDR r0, r1, r4 @ r0/r1<- vAA/vAA+1 958*795d594fSAndroid Build Coastguard Worker mov r0, r0, lsr r2 @ r0<- r2 >> r2 959*795d594fSAndroid Build Coastguard Worker rsb r3, r2, #32 @ r3<- 32 - r2 960*795d594fSAndroid Build Coastguard Worker orr r0, r0, r1, lsl r3 @ r0<- r0 | (r1 << (32-r2)) 961*795d594fSAndroid Build Coastguard Worker subs ip, r2, #32 @ ip<- r2 - 32 962*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 @ advance rPC, load rINST 963*795d594fSAndroid Build Coastguard Worker it pl 964*795d594fSAndroid Build Coastguard Worker movpl r0, r1, lsr ip @ if r2 >= 32, r0<-r1 >>> (r2-32) 965*795d594fSAndroid Build Coastguard Worker mov r1, r1, lsr r2 @ r1<- r1 >>> r2 966*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip @ extract opcode from rINST 967*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_BY_ADDR r0, r1, r4 @ vAA/vAA+1<- r0/r1 968*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip @ jump to next instruction 969*795d594fSAndroid Build Coastguard Worker 970*795d594fSAndroid Build Coastguard Worker%def op_xor_int(): 971*795d594fSAndroid Build Coastguard Worker% binop(instr="eor r0, r0, r1") 972*795d594fSAndroid Build Coastguard Worker 973*795d594fSAndroid Build Coastguard Worker%def op_xor_int_2addr(): 974*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="eor r0, r0, r1") 975*795d594fSAndroid Build Coastguard Worker 976*795d594fSAndroid Build Coastguard Worker%def op_xor_int_lit16(): 977*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="eor r0, r0, r1") 978*795d594fSAndroid Build Coastguard Worker 979*795d594fSAndroid Build Coastguard Worker%def op_xor_int_lit8(): 980*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="", instr="eor r0, r0, r3, asr #8") 981*795d594fSAndroid Build Coastguard Worker 982*795d594fSAndroid Build Coastguard Worker%def op_xor_long(): 983*795d594fSAndroid Build Coastguard Worker% binopWide(preinstr="eor r0, r0, r2", instr="eor r1, r1, r3") 984*795d594fSAndroid Build Coastguard Worker 985*795d594fSAndroid Build Coastguard Worker%def op_xor_long_2addr(): 986*795d594fSAndroid Build Coastguard Worker% binopWide2addr(preinstr="eor r0, r0, r2", instr="eor r1, r1, r3") 987