xref: /aosp_15_r20/art/runtime/interpreter/mterp/arm64ng/arithmetic.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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