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