1*795d594fSAndroid Build Coastguard Worker%def binop(preinstr="", result="w0", 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 = w0 op w1". 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 w0, 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 (w1). 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 w0, 1 // w0<- CCBB 19*795d594fSAndroid Build Coastguard Worker lsr w9, wINST, #8 // w9<- AA 20*795d594fSAndroid Build Coastguard Worker lsr w3, w0, #8 // w3<- CC 21*795d594fSAndroid Build Coastguard Worker and w2, w0, #255 // w2<- BB 22*795d594fSAndroid Build Coastguard Worker GET_VREG w1, w3 // w1<- vCC 23*795d594fSAndroid Build Coastguard Worker GET_VREG w0, w2 // w0<- vBB 24*795d594fSAndroid Build Coastguard Worker .if $chkzero 25*795d594fSAndroid Build Coastguard Worker cbz w1, common_errDivideByZero // is second operand zero? 26*795d594fSAndroid Build Coastguard Worker .endif 27*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 // advance rPC, load rINST 28*795d594fSAndroid Build Coastguard Worker $preinstr // optional op; may set condition codes 29*795d594fSAndroid Build Coastguard Worker $instr // $result<- op, w0-w3 changed 30*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 31*795d594fSAndroid Build Coastguard Worker SET_VREG $result, w9 // vAA<- $result 32*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 33*795d594fSAndroid Build Coastguard Worker /* 11-14 instructions */ 34*795d594fSAndroid Build Coastguard Worker 35*795d594fSAndroid Build Coastguard Worker%def binop2addr(preinstr="", result="w0", chkzero="0", instr=""): 36*795d594fSAndroid Build Coastguard Worker /* 37*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 38*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = w0 op w1". 39*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 40*795d594fSAndroid Build Coastguard Worker * comes back in a register other than w0, you can override "result".) 41*795d594fSAndroid Build Coastguard Worker * 42*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 43*795d594fSAndroid Build Coastguard Worker * vCC (w1). Useful for integer division and modulus. 44*795d594fSAndroid Build Coastguard Worker * 45*795d594fSAndroid Build Coastguard Worker * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 46*795d594fSAndroid Build Coastguard Worker * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 47*795d594fSAndroid Build Coastguard Worker * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 48*795d594fSAndroid Build Coastguard Worker * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 49*795d594fSAndroid Build Coastguard Worker */ 50*795d594fSAndroid Build Coastguard Worker /* binop/2addr vA, vB */ 51*795d594fSAndroid Build Coastguard Worker lsr w3, wINST, #12 // w3<- B 52*795d594fSAndroid Build Coastguard Worker ubfx w9, wINST, #8, #4 // w9<- A 53*795d594fSAndroid Build Coastguard Worker GET_VREG w1, w3 // w1<- vB 54*795d594fSAndroid Build Coastguard Worker GET_VREG w0, w9 // w0<- vA 55*795d594fSAndroid Build Coastguard Worker .if $chkzero 56*795d594fSAndroid Build Coastguard Worker cbz w1, common_errDivideByZero 57*795d594fSAndroid Build Coastguard Worker .endif 58*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 // advance rPC, load rINST 59*795d594fSAndroid Build Coastguard Worker $preinstr // optional op; may set condition codes 60*795d594fSAndroid Build Coastguard Worker $instr // $result<- op, w0-w3 changed 61*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 62*795d594fSAndroid Build Coastguard Worker SET_VREG $result, w9 // vAA<- $result 63*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 64*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 65*795d594fSAndroid Build Coastguard Worker 66*795d594fSAndroid Build Coastguard Worker%def binopLit16(preinstr="", result="w0", chkzero="0", instr=""): 67*795d594fSAndroid Build Coastguard Worker /* 68*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "lit16" binary operation. Provide an "instr" line 69*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = w0 op w1". 70*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 71*795d594fSAndroid Build Coastguard Worker * comes back in a register other than w0, you can override "result".) 72*795d594fSAndroid Build Coastguard Worker * 73*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 74*795d594fSAndroid Build Coastguard Worker * vCC (w1). Useful for integer division and modulus. 75*795d594fSAndroid Build Coastguard Worker * 76*795d594fSAndroid Build Coastguard Worker * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16, 77*795d594fSAndroid Build Coastguard Worker * rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16 78*795d594fSAndroid Build Coastguard Worker */ 79*795d594fSAndroid Build Coastguard Worker /* binop/lit16 vA, vB, #+CCCC */ 80*795d594fSAndroid Build Coastguard Worker FETCH_S w1, 1 // w1<- ssssCCCC (sign-extended) 81*795d594fSAndroid Build Coastguard Worker lsr w2, wINST, #12 // w2<- B 82*795d594fSAndroid Build Coastguard Worker ubfx w9, wINST, #8, #4 // w9<- A 83*795d594fSAndroid Build Coastguard Worker GET_VREG w0, w2 // w0<- vB 84*795d594fSAndroid Build Coastguard Worker .if $chkzero 85*795d594fSAndroid Build Coastguard Worker cbz w1, common_errDivideByZero 86*795d594fSAndroid Build Coastguard Worker .endif 87*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 // advance rPC, load rINST 88*795d594fSAndroid Build Coastguard Worker $preinstr 89*795d594fSAndroid Build Coastguard Worker $instr // $result<- op, w0-w3 changed 90*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 91*795d594fSAndroid Build Coastguard Worker SET_VREG $result, w9 // vAA<- $result 92*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 93*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker%def binopLit8(extract="asr w1, w3, #8", preinstr="", result="w0", chkzero="0", instr=""): 96*795d594fSAndroid Build Coastguard Worker /* 97*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "lit8" binary operation. Provide an "instr" line 98*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = w0 op w1". 99*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 100*795d594fSAndroid Build Coastguard Worker * comes back in a register other than w0, you can override "result".) 101*795d594fSAndroid Build Coastguard Worker * 102*795d594fSAndroid Build Coastguard Worker * You can override "extract" if the extraction of the literal value 103*795d594fSAndroid Build Coastguard Worker * from w3 to w1 is not the default "asr w1, w3, #8". The extraction 104*795d594fSAndroid Build Coastguard Worker * can be omitted completely if the shift is embedded in "instr". 105*795d594fSAndroid Build Coastguard Worker * 106*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 107*795d594fSAndroid Build Coastguard Worker * vCC (w1). Useful for integer division and modulus. 108*795d594fSAndroid Build Coastguard Worker * 109*795d594fSAndroid Build Coastguard Worker * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8, 110*795d594fSAndroid Build Coastguard Worker * rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8, 111*795d594fSAndroid Build Coastguard Worker * shl-int/lit8, shr-int/lit8, ushr-int/lit8 112*795d594fSAndroid Build Coastguard Worker */ 113*795d594fSAndroid Build Coastguard Worker /* binop/lit8 vAA, vBB, #+CC */ 114*795d594fSAndroid Build Coastguard Worker FETCH_S w3, 1 // w3<- ssssCCBB (sign-extended for CC) 115*795d594fSAndroid Build Coastguard Worker lsr w9, wINST, #8 // w9<- AA 116*795d594fSAndroid Build Coastguard Worker and w2, w3, #255 // w2<- BB 117*795d594fSAndroid Build Coastguard Worker GET_VREG w0, w2 // w0<- vBB 118*795d594fSAndroid Build Coastguard Worker $extract // optional; typically w1<- ssssssCC (sign extended) 119*795d594fSAndroid Build Coastguard Worker .if $chkzero 120*795d594fSAndroid Build Coastguard Worker cbz w1, common_errDivideByZero 121*795d594fSAndroid Build Coastguard Worker .endif 122*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 // advance rPC, load rINST 123*795d594fSAndroid Build Coastguard Worker $preinstr // optional op; may set condition codes 124*795d594fSAndroid Build Coastguard Worker $instr // $result<- op, w0-w3 changed 125*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 126*795d594fSAndroid Build Coastguard Worker SET_VREG $result, w9 // vAA<- $result 127*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 128*795d594fSAndroid Build Coastguard Worker /* 10-12 instructions */ 129*795d594fSAndroid Build Coastguard Worker 130*795d594fSAndroid Build Coastguard Worker%def binopWide(preinstr="", instr="add x0, x1, x2", result="x0", r1="x1", r2="x2", chkzero="0"): 131*795d594fSAndroid Build Coastguard Worker /* 132*795d594fSAndroid Build Coastguard Worker * Generic 64-bit binary operation. Provide an "instr" line that 133*795d594fSAndroid Build Coastguard Worker * specifies an instruction that performs "result = x1 op x2". 134*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. (If the result 135*795d594fSAndroid Build Coastguard Worker * comes back in a register other than x0, you can override "result".) 136*795d594fSAndroid Build Coastguard Worker * 137*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 138*795d594fSAndroid Build Coastguard Worker * vCC (w1). Useful for integer division and modulus. 139*795d594fSAndroid Build Coastguard Worker * 140*795d594fSAndroid Build Coastguard Worker * For: add-long, sub-long, mul-long, div-long, rem-long, and-long, or-long, 141*795d594fSAndroid Build Coastguard Worker * xor-long, add-double, sub-double, mul-double, div-double, rem-double 142*795d594fSAndroid Build Coastguard Worker */ 143*795d594fSAndroid Build Coastguard Worker /* binop vAA, vBB, vCC */ 144*795d594fSAndroid Build Coastguard Worker FETCH w0, 1 // w0<- CCBB 145*795d594fSAndroid Build Coastguard Worker LOAD_SCALED_VREG_MASK w5, 0xff // w5<- ff * sizeof(vreg) 146*795d594fSAndroid Build Coastguard Worker EXTRACT_SCALED_VREG w4, w5, wINST, 8 // w4<- AA * sizeof(vreg) 147*795d594fSAndroid Build Coastguard Worker EXTRACT_SCALED_VREG w2, w5, w0, 8 // w2<- CC * sizeof(vreg) 148*795d594fSAndroid Build Coastguard Worker EXTRACT_SCALED_VREG w1, w5, w0, 0 // w1<- BB * sizeof(vreg) 149*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_PRESCALED $r2, w2 // w2<- vCC 150*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_PRESCALED $r1, w1 // w1<- vBB 151*795d594fSAndroid Build Coastguard Worker .if $chkzero 152*795d594fSAndroid Build Coastguard Worker cbz $r2, common_errDivideByZero // is second operand zero? 153*795d594fSAndroid Build Coastguard Worker .endif 154*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 // advance rPC, load rINST 155*795d594fSAndroid Build Coastguard Worker $preinstr 156*795d594fSAndroid Build Coastguard Worker $instr // $result<- op, w0-w4 changed 157*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 158*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE_PRESCALED $result, w4 // vAA<- $result 159*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 160*795d594fSAndroid Build Coastguard Worker /* 11-14 instructions */ 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker%def binopWide2addr(preinstr="", instr="add x0, x0, x1", r0="x0", r1="x1", chkzero="0"): 163*795d594fSAndroid Build Coastguard Worker /* 164*795d594fSAndroid Build Coastguard Worker * Generic 64-bit "/2addr" binary operation. Provide an "instr" line 165*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "x0 = x0 op x1". 166*795d594fSAndroid Build Coastguard Worker * This must not be a function call, as we keep w2 live across it. 167*795d594fSAndroid Build Coastguard Worker * 168*795d594fSAndroid Build Coastguard Worker * If "chkzero" is set to 1, we perform a divide-by-zero check on 169*795d594fSAndroid Build Coastguard Worker * vCC (w1). Useful for integer division and modulus. 170*795d594fSAndroid Build Coastguard Worker * 171*795d594fSAndroid Build Coastguard Worker * For: add-long/2addr, sub-long/2addr, mul-long/2addr, div-long/2addr, 172*795d594fSAndroid Build Coastguard Worker * and-long/2addr, or-long/2addr, xor-long/2addr, 173*795d594fSAndroid Build Coastguard Worker * shl-long/2addr, shr-long/2addr, ushr-long/2addr, add-double/2addr, 174*795d594fSAndroid Build Coastguard Worker * sub-double/2addr, mul-double/2addr, div-double/2addr, rem-double/2addr 175*795d594fSAndroid Build Coastguard Worker */ 176*795d594fSAndroid Build Coastguard Worker /* binop/2addr vA, vB */ 177*795d594fSAndroid Build Coastguard Worker lsr w1, wINST, #12 // w1<- B 178*795d594fSAndroid Build Coastguard Worker ubfx w2, wINST, #8, #4 // w2<- A 179*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE $r1, w1 // x1<- vB 180*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE $r0, w2 // x0<- vA 181*795d594fSAndroid Build Coastguard Worker .if $chkzero 182*795d594fSAndroid Build Coastguard Worker cbz $r1, common_errDivideByZero 183*795d594fSAndroid Build Coastguard Worker .endif 184*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 // advance rPC, load rINST 185*795d594fSAndroid Build Coastguard Worker $preinstr 186*795d594fSAndroid Build Coastguard Worker $instr // result<- op 187*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 188*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE $r0, w2 // vAA<- result 189*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 190*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 191*795d594fSAndroid Build Coastguard Worker 192*795d594fSAndroid Build Coastguard Worker%def shiftWide(opcode="shl"): 193*795d594fSAndroid Build Coastguard Worker /* 194*795d594fSAndroid Build Coastguard Worker * 64-bit shift operation. 195*795d594fSAndroid Build Coastguard Worker * 196*795d594fSAndroid Build Coastguard Worker * For: shl-long, shr-long, ushr-long 197*795d594fSAndroid Build Coastguard Worker */ 198*795d594fSAndroid Build Coastguard Worker /* binop vAA, vBB, vCC */ 199*795d594fSAndroid Build Coastguard Worker FETCH w0, 1 // w0<- CCBB 200*795d594fSAndroid Build Coastguard Worker lsr w3, wINST, #8 // w3<- AA 201*795d594fSAndroid Build Coastguard Worker lsr w2, w0, #8 // w2<- CC 202*795d594fSAndroid Build Coastguard Worker GET_VREG w2, w2 // w2<- vCC (shift count) 203*795d594fSAndroid Build Coastguard Worker and w1, w0, #255 // w1<- BB 204*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE x1, w1 // x1<- vBB 205*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 // advance rPC, load rINST 206*795d594fSAndroid Build Coastguard Worker $opcode x0, x1, x2 // Do the shift. Only low 6 bits of x2 are used. 207*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 208*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE x0, w3 // vAA<- x0 209*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 210*795d594fSAndroid Build Coastguard Worker /* 11-14 instructions */ 211*795d594fSAndroid Build Coastguard Worker 212*795d594fSAndroid Build Coastguard Worker%def shiftWide2addr(opcode="lsl"): 213*795d594fSAndroid Build Coastguard Worker /* 214*795d594fSAndroid Build Coastguard Worker * Generic 64-bit shift operation. 215*795d594fSAndroid Build Coastguard Worker */ 216*795d594fSAndroid Build Coastguard Worker /* binop/2addr vA, vB */ 217*795d594fSAndroid Build Coastguard Worker lsr w1, wINST, #12 // w1<- B 218*795d594fSAndroid Build Coastguard Worker ubfx w2, wINST, #8, #4 // w2<- A 219*795d594fSAndroid Build Coastguard Worker GET_VREG w1, w1 // x1<- vB 220*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE x0, w2 // x0<- vA 221*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 // advance rPC, load rINST 222*795d594fSAndroid Build Coastguard Worker $opcode x0, x0, x1 // Do the shift. Only low 6 bits of x1 are used. 223*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 224*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE x0, w2 // vAA<- result 225*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 226*795d594fSAndroid Build Coastguard Worker /* 10-13 instructions */ 227*795d594fSAndroid Build Coastguard Worker 228*795d594fSAndroid Build Coastguard Worker%def unop(instr=""): 229*795d594fSAndroid Build Coastguard Worker /* 230*795d594fSAndroid Build Coastguard Worker * Generic 32-bit unary operation. Provide an "instr" line that 231*795d594fSAndroid Build Coastguard Worker * specifies an instruction that performs "result = op w0". 232*795d594fSAndroid Build Coastguard Worker * This could be an ARM instruction or a function call. 233*795d594fSAndroid Build Coastguard Worker * 234*795d594fSAndroid Build Coastguard Worker * for: neg-int, not-int, neg-float, int-to-float, float-to-int, 235*795d594fSAndroid Build Coastguard Worker * int-to-byte, int-to-char, int-to-short 236*795d594fSAndroid Build Coastguard Worker */ 237*795d594fSAndroid Build Coastguard Worker /* unop vA, vB */ 238*795d594fSAndroid Build Coastguard Worker lsr w3, wINST, #12 // w3<- B 239*795d594fSAndroid Build Coastguard Worker GET_VREG w0, w3 // w0<- vB 240*795d594fSAndroid Build Coastguard Worker ubfx w9, wINST, #8, #4 // w9<- A 241*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 // advance rPC, load rINST 242*795d594fSAndroid Build Coastguard Worker $instr // w0<- op, w0-w3 changed 243*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from rINST 244*795d594fSAndroid Build Coastguard Worker SET_VREG w0, w9 // vAA<- w0 245*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 246*795d594fSAndroid Build Coastguard Worker /* 8-9 instructions */ 247*795d594fSAndroid Build Coastguard Worker 248*795d594fSAndroid Build Coastguard Worker%def unopWide(instr="sub x0, xzr, x0"): 249*795d594fSAndroid Build Coastguard Worker /* 250*795d594fSAndroid Build Coastguard Worker * Generic 64-bit unary operation. Provide an "instr" line that 251*795d594fSAndroid Build Coastguard Worker * specifies an instruction that performs "result = op x0". 252*795d594fSAndroid Build Coastguard Worker * 253*795d594fSAndroid Build Coastguard Worker * For: neg-long, not-long 254*795d594fSAndroid Build Coastguard Worker */ 255*795d594fSAndroid Build Coastguard Worker /* unop vA, vB */ 256*795d594fSAndroid Build Coastguard Worker lsr w3, wINST, #12 // w3<- B 257*795d594fSAndroid Build Coastguard Worker ubfx w4, wINST, #8, #4 // w4<- A 258*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE x0, w3 259*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 // advance rPC, load wINST 260*795d594fSAndroid Build Coastguard Worker $instr 261*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from wINST 262*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE x0, w4 263*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 264*795d594fSAndroid Build Coastguard Worker /* 10-11 instructions */ 265*795d594fSAndroid Build Coastguard Worker 266*795d594fSAndroid Build Coastguard Worker%def op_add_int(): 267*795d594fSAndroid Build Coastguard Worker% binop(instr="add w0, w0, w1") 268*795d594fSAndroid Build Coastguard Worker 269*795d594fSAndroid Build Coastguard Worker%def op_add_int_2addr(): 270*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="add w0, w0, w1") 271*795d594fSAndroid Build Coastguard Worker 272*795d594fSAndroid Build Coastguard Worker%def op_add_int_lit16(): 273*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="add w0, w0, w1") 274*795d594fSAndroid Build Coastguard Worker 275*795d594fSAndroid Build Coastguard Worker%def op_add_int_lit8(): 276*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="", instr="add w0, w0, w3, asr #8") 277*795d594fSAndroid Build Coastguard Worker 278*795d594fSAndroid Build Coastguard Worker%def op_add_long(): 279*795d594fSAndroid Build Coastguard Worker% binopWide(instr="add x0, x1, x2") 280*795d594fSAndroid Build Coastguard Worker 281*795d594fSAndroid Build Coastguard Worker%def op_add_long_2addr(): 282*795d594fSAndroid Build Coastguard Worker% binopWide2addr(instr="add x0, x0, x1") 283*795d594fSAndroid Build Coastguard Worker 284*795d594fSAndroid Build Coastguard Worker%def op_and_int(): 285*795d594fSAndroid Build Coastguard Worker% binop(instr="and w0, w0, w1") 286*795d594fSAndroid Build Coastguard Worker 287*795d594fSAndroid Build Coastguard Worker%def op_and_int_2addr(): 288*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="and w0, w0, w1") 289*795d594fSAndroid Build Coastguard Worker 290*795d594fSAndroid Build Coastguard Worker%def op_and_int_lit16(): 291*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="and w0, w0, w1") 292*795d594fSAndroid Build Coastguard Worker 293*795d594fSAndroid Build Coastguard Worker%def op_and_int_lit8(): 294*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="", instr="and w0, w0, w3, asr #8") 295*795d594fSAndroid Build Coastguard Worker 296*795d594fSAndroid Build Coastguard Worker%def op_and_long(): 297*795d594fSAndroid Build Coastguard Worker% binopWide(instr="and x0, x1, x2") 298*795d594fSAndroid Build Coastguard Worker 299*795d594fSAndroid Build Coastguard Worker%def op_and_long_2addr(): 300*795d594fSAndroid Build Coastguard Worker% binopWide2addr(instr="and x0, x0, x1") 301*795d594fSAndroid Build Coastguard Worker 302*795d594fSAndroid Build Coastguard Worker%def op_cmp_long(): 303*795d594fSAndroid Build Coastguard Worker FETCH w0, 1 // w0<- CCBB 304*795d594fSAndroid Build Coastguard Worker LOAD_SCALED_VREG_MASK w5, 0xff // w4<- ff * sizeof(vreg) 305*795d594fSAndroid Build Coastguard Worker lsr w4, wINST, #8 // w4<- AA 306*795d594fSAndroid Build Coastguard Worker EXTRACT_SCALED_VREG w2, w5, w0, 0 // w2<- BB * sizeof(vreg) 307*795d594fSAndroid Build Coastguard Worker EXTRACT_SCALED_VREG w3, w5, w0, 8 // w3<- CC * sizeof(vreg) 308*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_PRESCALED x1, w2 309*795d594fSAndroid Build Coastguard Worker GET_VREG_WIDE_PRESCALED x2, w3 310*795d594fSAndroid Build Coastguard Worker cmp x1, x2 311*795d594fSAndroid Build Coastguard Worker cset w0, ne 312*795d594fSAndroid Build Coastguard Worker cneg w0, w0, lt 313*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 2 // advance rPC, load wINST 314*795d594fSAndroid Build Coastguard Worker SET_VREG w0, w4 315*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from wINST 316*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 317*795d594fSAndroid Build Coastguard Worker 318*795d594fSAndroid Build Coastguard Worker%def op_div_int(): 319*795d594fSAndroid Build Coastguard Worker% binop(instr="sdiv w0, w0, w1", chkzero="1") 320*795d594fSAndroid Build Coastguard Worker 321*795d594fSAndroid Build Coastguard Worker%def op_div_int_2addr(): 322*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="sdiv w0, w0, w1", chkzero="1") 323*795d594fSAndroid Build Coastguard Worker 324*795d594fSAndroid Build Coastguard Worker%def op_div_int_lit16(): 325*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="sdiv w0, w0, w1", chkzero="1") 326*795d594fSAndroid Build Coastguard Worker 327*795d594fSAndroid Build Coastguard Worker%def op_div_int_lit8(): 328*795d594fSAndroid Build Coastguard Worker% binopLit8(instr="sdiv w0, w0, w1", chkzero="1") 329*795d594fSAndroid Build Coastguard Worker 330*795d594fSAndroid Build Coastguard Worker%def op_div_long(): 331*795d594fSAndroid Build Coastguard Worker% binopWide(instr="sdiv x0, x1, x2", chkzero="1") 332*795d594fSAndroid Build Coastguard Worker 333*795d594fSAndroid Build Coastguard Worker%def op_div_long_2addr(): 334*795d594fSAndroid Build Coastguard Worker% binopWide2addr(instr="sdiv x0, x0, x1", chkzero="1") 335*795d594fSAndroid Build Coastguard Worker 336*795d594fSAndroid Build Coastguard Worker%def op_int_to_byte(): 337*795d594fSAndroid Build Coastguard Worker% unop(instr="sxtb w0, w0") 338*795d594fSAndroid Build Coastguard Worker 339*795d594fSAndroid Build Coastguard Worker%def op_int_to_char(): 340*795d594fSAndroid Build Coastguard Worker% unop(instr="uxth w0, w0") 341*795d594fSAndroid Build Coastguard Worker 342*795d594fSAndroid Build Coastguard Worker%def op_int_to_long(): 343*795d594fSAndroid Build Coastguard Worker /* int-to-long vA, vB */ 344*795d594fSAndroid Build Coastguard Worker lsr w3, wINST, #12 // w3<- B 345*795d594fSAndroid Build Coastguard Worker ubfx w4, wINST, #8, #4 // w4<- A 346*795d594fSAndroid Build Coastguard Worker GET_VREG_S x0, w3 // x0<- sign_extend(fp[B]) 347*795d594fSAndroid Build Coastguard Worker FETCH_ADVANCE_INST 1 // advance rPC, load wINST 348*795d594fSAndroid Build Coastguard Worker GET_INST_OPCODE ip // extract opcode from wINST 349*795d594fSAndroid Build Coastguard Worker SET_VREG_WIDE x0, w4 // fp[A]<- x0 350*795d594fSAndroid Build Coastguard Worker GOTO_OPCODE ip // jump to next instruction 351*795d594fSAndroid Build Coastguard Worker 352*795d594fSAndroid Build Coastguard Worker%def op_int_to_short(): 353*795d594fSAndroid Build Coastguard Worker% unop(instr="sxth w0, w0") 354*795d594fSAndroid Build Coastguard Worker 355*795d594fSAndroid Build Coastguard Worker%def op_long_to_int(): 356*795d594fSAndroid Build Coastguard Worker/* we ignore the high word, making this equivalent to a 32-bit reg move */ 357*795d594fSAndroid Build Coastguard Worker% op_move() 358*795d594fSAndroid Build Coastguard Worker 359*795d594fSAndroid Build Coastguard Worker%def op_mul_int(): 360*795d594fSAndroid Build Coastguard Worker/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ 361*795d594fSAndroid Build Coastguard Worker% binop(instr="mul w0, w1, w0") 362*795d594fSAndroid Build Coastguard Worker 363*795d594fSAndroid Build Coastguard Worker%def op_mul_int_2addr(): 364*795d594fSAndroid Build Coastguard Worker/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ 365*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="mul w0, w1, w0") 366*795d594fSAndroid Build Coastguard Worker 367*795d594fSAndroid Build Coastguard Worker%def op_mul_int_lit16(): 368*795d594fSAndroid Build Coastguard Worker/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ 369*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="mul w0, w1, w0") 370*795d594fSAndroid Build Coastguard Worker 371*795d594fSAndroid Build Coastguard Worker%def op_mul_int_lit8(): 372*795d594fSAndroid Build Coastguard Worker/* must be "mul w0, w1, w0" -- "w0, w0, w1" is illegal */ 373*795d594fSAndroid Build Coastguard Worker% binopLit8(instr="mul w0, w1, w0") 374*795d594fSAndroid Build Coastguard Worker 375*795d594fSAndroid Build Coastguard Worker%def op_mul_long(): 376*795d594fSAndroid Build Coastguard Worker% binopWide(instr="mul x0, x1, x2") 377*795d594fSAndroid Build Coastguard Worker 378*795d594fSAndroid Build Coastguard Worker%def op_mul_long_2addr(): 379*795d594fSAndroid Build Coastguard Worker% binopWide2addr(instr="mul x0, x0, x1") 380*795d594fSAndroid Build Coastguard Worker 381*795d594fSAndroid Build Coastguard Worker%def op_neg_int(): 382*795d594fSAndroid Build Coastguard Worker% unop(instr="sub w0, wzr, w0") 383*795d594fSAndroid Build Coastguard Worker 384*795d594fSAndroid Build Coastguard Worker%def op_neg_long(): 385*795d594fSAndroid Build Coastguard Worker% unopWide(instr="sub x0, xzr, x0") 386*795d594fSAndroid Build Coastguard Worker 387*795d594fSAndroid Build Coastguard Worker%def op_not_int(): 388*795d594fSAndroid Build Coastguard Worker% unop(instr="mvn w0, w0") 389*795d594fSAndroid Build Coastguard Worker 390*795d594fSAndroid Build Coastguard Worker%def op_not_long(): 391*795d594fSAndroid Build Coastguard Worker% unopWide(instr="mvn x0, x0") 392*795d594fSAndroid Build Coastguard Worker 393*795d594fSAndroid Build Coastguard Worker%def op_or_int(): 394*795d594fSAndroid Build Coastguard Worker% binop(instr="orr w0, w0, w1") 395*795d594fSAndroid Build Coastguard Worker 396*795d594fSAndroid Build Coastguard Worker%def op_or_int_2addr(): 397*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="orr w0, w0, w1") 398*795d594fSAndroid Build Coastguard Worker 399*795d594fSAndroid Build Coastguard Worker%def op_or_int_lit16(): 400*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="orr w0, w0, w1") 401*795d594fSAndroid Build Coastguard Worker 402*795d594fSAndroid Build Coastguard Worker%def op_or_int_lit8(): 403*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="", instr="orr w0, w0, w3, asr #8") 404*795d594fSAndroid Build Coastguard Worker 405*795d594fSAndroid Build Coastguard Worker%def op_or_long(): 406*795d594fSAndroid Build Coastguard Worker% binopWide(instr="orr x0, x1, x2") 407*795d594fSAndroid Build Coastguard Worker 408*795d594fSAndroid Build Coastguard Worker%def op_or_long_2addr(): 409*795d594fSAndroid Build Coastguard Worker% binopWide2addr(instr="orr x0, x0, x1") 410*795d594fSAndroid Build Coastguard Worker 411*795d594fSAndroid Build Coastguard Worker%def op_rem_int(): 412*795d594fSAndroid Build Coastguard Worker% binop(preinstr="sdiv w2, w0, w1", instr="msub w0, w2, w1, w0", chkzero="1") 413*795d594fSAndroid Build Coastguard Worker 414*795d594fSAndroid Build Coastguard Worker%def op_rem_int_2addr(): 415*795d594fSAndroid Build Coastguard Worker% binop2addr(preinstr="sdiv w2, w0, w1", instr="msub w0, w2, w1, w0", chkzero="1") 416*795d594fSAndroid Build Coastguard Worker 417*795d594fSAndroid Build Coastguard Worker%def op_rem_int_lit16(): 418*795d594fSAndroid Build Coastguard Worker% binopLit16(preinstr="sdiv w3, w0, w1", instr="msub w0, w3, w1, w0", chkzero="1") 419*795d594fSAndroid Build Coastguard Worker 420*795d594fSAndroid Build Coastguard Worker%def op_rem_int_lit8(): 421*795d594fSAndroid Build Coastguard Worker% binopLit8(preinstr="sdiv w3, w0, w1", instr="msub w0, w3, w1, w0", chkzero="1") 422*795d594fSAndroid Build Coastguard Worker 423*795d594fSAndroid Build Coastguard Worker%def op_rem_long(): 424*795d594fSAndroid Build Coastguard Worker% binopWide(preinstr="sdiv x3, x1, x2", instr="msub x0, x3, x2, x1", chkzero="1") 425*795d594fSAndroid Build Coastguard Worker 426*795d594fSAndroid Build Coastguard Worker%def op_rem_long_2addr(): 427*795d594fSAndroid Build Coastguard Worker% binopWide2addr(preinstr="sdiv x3, x0, x1", instr="msub x0, x3, x1, x0", chkzero="1") 428*795d594fSAndroid Build Coastguard Worker 429*795d594fSAndroid Build Coastguard Worker%def op_rsub_int(): 430*795d594fSAndroid Build Coastguard Worker/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */ 431*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="sub w0, w1, w0") 432*795d594fSAndroid Build Coastguard Worker 433*795d594fSAndroid Build Coastguard Worker%def op_rsub_int_lit8(): 434*795d594fSAndroid Build Coastguard Worker% binopLit8(instr="sub w0, w1, w0") 435*795d594fSAndroid Build Coastguard Worker 436*795d594fSAndroid Build Coastguard Worker%def op_shl_int(): 437*795d594fSAndroid Build Coastguard Worker% binop(instr="lsl w0, w0, w1") 438*795d594fSAndroid Build Coastguard Worker 439*795d594fSAndroid Build Coastguard Worker%def op_shl_int_2addr(): 440*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="lsl w0, w0, w1") 441*795d594fSAndroid Build Coastguard Worker 442*795d594fSAndroid Build Coastguard Worker%def op_shl_int_lit8(): 443*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="ubfx w1, w3, #8, #5", instr="lsl w0, w0, w1") 444*795d594fSAndroid Build Coastguard Worker 445*795d594fSAndroid Build Coastguard Worker%def op_shl_long(): 446*795d594fSAndroid Build Coastguard Worker% shiftWide(opcode="lsl") 447*795d594fSAndroid Build Coastguard Worker 448*795d594fSAndroid Build Coastguard Worker%def op_shl_long_2addr(): 449*795d594fSAndroid Build Coastguard Worker% shiftWide2addr(opcode="lsl") 450*795d594fSAndroid Build Coastguard Worker 451*795d594fSAndroid Build Coastguard Worker%def op_shr_int(): 452*795d594fSAndroid Build Coastguard Worker% binop(instr="asr w0, w0, w1") 453*795d594fSAndroid Build Coastguard Worker 454*795d594fSAndroid Build Coastguard Worker%def op_shr_int_2addr(): 455*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="asr w0, w0, w1") 456*795d594fSAndroid Build Coastguard Worker 457*795d594fSAndroid Build Coastguard Worker%def op_shr_int_lit8(): 458*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="ubfx w1, w3, #8, #5", instr="asr w0, w0, w1") 459*795d594fSAndroid Build Coastguard Worker 460*795d594fSAndroid Build Coastguard Worker%def op_shr_long(): 461*795d594fSAndroid Build Coastguard Worker% shiftWide(opcode="asr") 462*795d594fSAndroid Build Coastguard Worker 463*795d594fSAndroid Build Coastguard Worker%def op_shr_long_2addr(): 464*795d594fSAndroid Build Coastguard Worker% shiftWide2addr(opcode="asr") 465*795d594fSAndroid Build Coastguard Worker 466*795d594fSAndroid Build Coastguard Worker%def op_sub_int(): 467*795d594fSAndroid Build Coastguard Worker% binop(instr="sub w0, w0, w1") 468*795d594fSAndroid Build Coastguard Worker 469*795d594fSAndroid Build Coastguard Worker%def op_sub_int_2addr(): 470*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="sub w0, w0, w1") 471*795d594fSAndroid Build Coastguard Worker 472*795d594fSAndroid Build Coastguard Worker%def op_sub_long(): 473*795d594fSAndroid Build Coastguard Worker% binopWide(instr="sub x0, x1, x2") 474*795d594fSAndroid Build Coastguard Worker 475*795d594fSAndroid Build Coastguard Worker%def op_sub_long_2addr(): 476*795d594fSAndroid Build Coastguard Worker% binopWide2addr(instr="sub x0, x0, x1") 477*795d594fSAndroid Build Coastguard Worker 478*795d594fSAndroid Build Coastguard Worker%def op_ushr_int(): 479*795d594fSAndroid Build Coastguard Worker% binop(instr="lsr w0, w0, w1") 480*795d594fSAndroid Build Coastguard Worker 481*795d594fSAndroid Build Coastguard Worker%def op_ushr_int_2addr(): 482*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="lsr w0, w0, w1") 483*795d594fSAndroid Build Coastguard Worker 484*795d594fSAndroid Build Coastguard Worker%def op_ushr_int_lit8(): 485*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="ubfx w1, w3, #8, #5", instr="lsr w0, w0, w1") 486*795d594fSAndroid Build Coastguard Worker 487*795d594fSAndroid Build Coastguard Worker%def op_ushr_long(): 488*795d594fSAndroid Build Coastguard Worker% shiftWide(opcode="lsr") 489*795d594fSAndroid Build Coastguard Worker 490*795d594fSAndroid Build Coastguard Worker%def op_ushr_long_2addr(): 491*795d594fSAndroid Build Coastguard Worker% shiftWide2addr(opcode="lsr") 492*795d594fSAndroid Build Coastguard Worker 493*795d594fSAndroid Build Coastguard Worker%def op_xor_int(): 494*795d594fSAndroid Build Coastguard Worker% binop(instr="eor w0, w0, w1") 495*795d594fSAndroid Build Coastguard Worker 496*795d594fSAndroid Build Coastguard Worker%def op_xor_int_2addr(): 497*795d594fSAndroid Build Coastguard Worker% binop2addr(instr="eor w0, w0, w1") 498*795d594fSAndroid Build Coastguard Worker 499*795d594fSAndroid Build Coastguard Worker%def op_xor_int_lit16(): 500*795d594fSAndroid Build Coastguard Worker% binopLit16(instr="eor w0, w0, w1") 501*795d594fSAndroid Build Coastguard Worker 502*795d594fSAndroid Build Coastguard Worker%def op_xor_int_lit8(): 503*795d594fSAndroid Build Coastguard Worker% binopLit8(extract="", instr="eor w0, w0, w3, asr #8") 504*795d594fSAndroid Build Coastguard Worker 505*795d594fSAndroid Build Coastguard Worker%def op_xor_long(): 506*795d594fSAndroid Build Coastguard Worker% binopWide(instr="eor x0, x1, x2") 507*795d594fSAndroid Build Coastguard Worker 508*795d594fSAndroid Build Coastguard Worker%def op_xor_long_2addr(): 509*795d594fSAndroid Build Coastguard Worker% binopWide2addr(instr="eor x0, x0, x1") 510