xref: /aosp_15_r20/art/runtime/interpreter/mterp/armng/floating_point.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker%def fbinop(instr=""):
2*795d594fSAndroid Build Coastguard Worker    /*
3*795d594fSAndroid Build Coastguard Worker     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4*795d594fSAndroid Build Coastguard Worker     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5*795d594fSAndroid Build Coastguard Worker     * use the "softfp" ABI, this must be an instruction, not a function call.
6*795d594fSAndroid Build Coastguard Worker     *
7*795d594fSAndroid Build Coastguard Worker     * For: add-float, sub-float, mul-float, div-float
8*795d594fSAndroid Build Coastguard Worker     */
9*795d594fSAndroid Build Coastguard Worker    /* floatop vAA, vBB, vCC */
10*795d594fSAndroid Build Coastguard Worker    FETCH r0, 1                         @ r0<- CCBB
11*795d594fSAndroid Build Coastguard Worker    mov     r4, rINST, lsr #8           @ r4<- AA
12*795d594fSAndroid Build Coastguard Worker    mov     r3, r0, lsr #8              @ r3<- CC
13*795d594fSAndroid Build Coastguard Worker    and     r2, r0, #255                @ r2<- BB
14*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
15*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
16*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s1, r3       @ s1<- vCC
17*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s0, r2       @ s0<- vBB
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
20*795d594fSAndroid Build Coastguard Worker    $instr                              @ s2<- op
21*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
22*795d594fSAndroid Build Coastguard Worker    SET_VREG_FLOAT s2, r4, lr           @ vAA<- s2
23*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
24*795d594fSAndroid Build Coastguard Worker
25*795d594fSAndroid Build Coastguard Worker%def fbinop2addr(instr=""):
26*795d594fSAndroid Build Coastguard Worker    /*
27*795d594fSAndroid Build Coastguard Worker     * Generic 32-bit floating point "/2addr" binary operation.  Provide
28*795d594fSAndroid Build Coastguard Worker     * an "instr" line that specifies an instruction that performs
29*795d594fSAndroid Build Coastguard Worker     * "s2 = s0 op s1".
30*795d594fSAndroid Build Coastguard Worker     *
31*795d594fSAndroid Build Coastguard Worker     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
32*795d594fSAndroid Build Coastguard Worker     */
33*795d594fSAndroid Build Coastguard Worker    /* binop/2addr vA, vB */
34*795d594fSAndroid Build Coastguard Worker    mov     r3, rINST, lsr #12          @ r3<- B
35*795d594fSAndroid Build Coastguard Worker    ubfx    r4, rINST, #8, #4           @ r4<- A
36*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
37*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &vA
38*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s1, r3       @ s1<- vB
39*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
40*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s0, r4       @ s0<- vA
41*795d594fSAndroid Build Coastguard Worker    $instr                              @ s2<- op
42*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
43*795d594fSAndroid Build Coastguard Worker    SET_VREG_FLOAT_BY_ADDR s2, r4       @ vAA<- s2 No need to clear as it's 2addr
44*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker%def fbinopWide(instr=""):
47*795d594fSAndroid Build Coastguard Worker    /*
48*795d594fSAndroid Build Coastguard Worker     * Generic 64-bit double-precision floating point binary operation.
49*795d594fSAndroid Build Coastguard Worker     * Provide an "instr" line that specifies an instruction that performs
50*795d594fSAndroid Build Coastguard Worker     * "d2 = d0 op d1".
51*795d594fSAndroid Build Coastguard Worker     *
52*795d594fSAndroid Build Coastguard Worker     * for: add-double, sub-double, mul-double, div-double
53*795d594fSAndroid Build Coastguard Worker     */
54*795d594fSAndroid Build Coastguard Worker    /* doubleop vAA, vBB, vCC */
55*795d594fSAndroid Build Coastguard Worker    FETCH r0, 1                         @ r0<- CCBB
56*795d594fSAndroid Build Coastguard Worker    mov     r4, rINST, lsr #8           @ r4<- AA
57*795d594fSAndroid Build Coastguard Worker    mov     r3, r0, lsr #8              @ r3<- CC
58*795d594fSAndroid Build Coastguard Worker    and     r2, r0, #255                @ r2<- BB
59*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
60*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
61*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d1, r3      @ d1<- vCC
62*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d0, r2      @ d0<- vBB
63*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
64*795d594fSAndroid Build Coastguard Worker    $instr                              @ d2<- op
65*795d594fSAndroid Build Coastguard Worker    CLEAR_SHADOW_PAIR r4, ip, lr        @ Zero shadow regs
66*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
67*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &vAA
68*795d594fSAndroid Build Coastguard Worker    SET_VREG_DOUBLE_BY_ADDR d2, r4      @ vAA<- d2
69*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
70*795d594fSAndroid Build Coastguard Worker
71*795d594fSAndroid Build Coastguard Worker%def fbinopWide2addr(instr=""):
72*795d594fSAndroid Build Coastguard Worker    /*
73*795d594fSAndroid Build Coastguard Worker     * Generic 64-bit floating point "/2addr" binary operation.  Provide
74*795d594fSAndroid Build Coastguard Worker     * an "instr" line that specifies an instruction that performs
75*795d594fSAndroid Build Coastguard Worker     * "d2 = d0 op d1".
76*795d594fSAndroid Build Coastguard Worker     *
77*795d594fSAndroid Build Coastguard Worker     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
78*795d594fSAndroid Build Coastguard Worker     *      div-double/2addr
79*795d594fSAndroid Build Coastguard Worker     */
80*795d594fSAndroid Build Coastguard Worker    /* binop/2addr vA, vB */
81*795d594fSAndroid Build Coastguard Worker    mov     r3, rINST, lsr #12          @ r3<- B
82*795d594fSAndroid Build Coastguard Worker    ubfx    r4, rINST, #8, #4           @ r4<- A
83*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
84*795d594fSAndroid Build Coastguard Worker    CLEAR_SHADOW_PAIR r4, ip, r0        @ Zero out shadow regs
85*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d1, r3      @ d1<- vB
86*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &vA
87*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
88*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d0, r4      @ d0<- vA
89*795d594fSAndroid Build Coastguard Worker    $instr                              @ d2<- op
90*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
91*795d594fSAndroid Build Coastguard Worker    SET_VREG_DOUBLE_BY_ADDR d2, r4      @ vAA<- d2
92*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Worker%def funop(instr=""):
95*795d594fSAndroid Build Coastguard Worker    /*
96*795d594fSAndroid Build Coastguard Worker     * Generic 32-bit unary floating-point operation.  Provide an "instr"
97*795d594fSAndroid Build Coastguard Worker     * line that specifies an instruction that performs "s1 = op s0".
98*795d594fSAndroid Build Coastguard Worker     *
99*795d594fSAndroid Build Coastguard Worker     * for: int-to-float, float-to-int
100*795d594fSAndroid Build Coastguard Worker     */
101*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
102*795d594fSAndroid Build Coastguard Worker    mov     r3, rINST, lsr #12          @ r3<- B
103*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
104*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s0, r3       @ s0<- vB
105*795d594fSAndroid Build Coastguard Worker    ubfx    r4, rINST, #8, #4           @ r4<- A
106*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
107*795d594fSAndroid Build Coastguard Worker    $instr                              @ s1<- op
108*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
109*795d594fSAndroid Build Coastguard Worker    SET_VREG_FLOAT s1, r4, lr           @ vA<- s1
110*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
111*795d594fSAndroid Build Coastguard Worker
112*795d594fSAndroid Build Coastguard Worker%def funopNarrower(instr=""):
113*795d594fSAndroid Build Coastguard Worker    /*
114*795d594fSAndroid Build Coastguard Worker     * Generic 64bit-to-32bit unary floating point operation.  Provide an
115*795d594fSAndroid Build Coastguard Worker     * "instr" line that specifies an instruction that performs "s0 = op d0".
116*795d594fSAndroid Build Coastguard Worker     *
117*795d594fSAndroid Build Coastguard Worker     * For: double-to-int, double-to-float
118*795d594fSAndroid Build Coastguard Worker     */
119*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
120*795d594fSAndroid Build Coastguard Worker    mov     r3, rINST, lsr #12          @ r3<- B
121*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
122*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d0, r3      @ d0<- vB
123*795d594fSAndroid Build Coastguard Worker    ubfx    r4, rINST, #8, #4           @ r4<- A
124*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
125*795d594fSAndroid Build Coastguard Worker    $instr                              @ s0<- op
126*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
127*795d594fSAndroid Build Coastguard Worker    SET_VREG_FLOAT s0, r4, lr           @ vA<- s0
128*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
129*795d594fSAndroid Build Coastguard Worker
130*795d594fSAndroid Build Coastguard Worker%def funopWider(instr=""):
131*795d594fSAndroid Build Coastguard Worker    /*
132*795d594fSAndroid Build Coastguard Worker     * Generic 32bit-to-64bit floating point unary operation.  Provide an
133*795d594fSAndroid Build Coastguard Worker     * "instr" line that specifies an instruction that performs "d0 = op s0".
134*795d594fSAndroid Build Coastguard Worker     *
135*795d594fSAndroid Build Coastguard Worker     * For: int-to-double, float-to-double
136*795d594fSAndroid Build Coastguard Worker     */
137*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
138*795d594fSAndroid Build Coastguard Worker    mov     r3, rINST, lsr #12          @ r3<- B
139*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vB
140*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s0, r3       @ s0<- vB
141*795d594fSAndroid Build Coastguard Worker    ubfx    r4, rINST, #8, #4           @ r4<- A
142*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
143*795d594fSAndroid Build Coastguard Worker    $instr                              @ d0<- op
144*795d594fSAndroid Build Coastguard Worker    CLEAR_SHADOW_PAIR r4, ip, lr        @ Zero shadow regs
145*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
146*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &vA
147*795d594fSAndroid Build Coastguard Worker    SET_VREG_DOUBLE_BY_ADDR d0, r4      @ vA<- d0
148*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
149*795d594fSAndroid Build Coastguard Worker
150*795d594fSAndroid Build Coastguard Worker%def op_add_double():
151*795d594fSAndroid Build Coastguard Worker%  fbinopWide(instr="faddd   d2, d0, d1")
152*795d594fSAndroid Build Coastguard Worker
153*795d594fSAndroid Build Coastguard Worker%def op_add_double_2addr():
154*795d594fSAndroid Build Coastguard Worker%  fbinopWide2addr(instr="faddd   d2, d0, d1")
155*795d594fSAndroid Build Coastguard Worker
156*795d594fSAndroid Build Coastguard Worker%def op_add_float():
157*795d594fSAndroid Build Coastguard Worker%  fbinop(instr="fadds   s2, s0, s1")
158*795d594fSAndroid Build Coastguard Worker
159*795d594fSAndroid Build Coastguard Worker%def op_add_float_2addr():
160*795d594fSAndroid Build Coastguard Worker%  fbinop2addr(instr="fadds   s2, s0, s1")
161*795d594fSAndroid Build Coastguard Worker
162*795d594fSAndroid Build Coastguard Worker%def op_cmpg_double():
163*795d594fSAndroid Build Coastguard Worker    /*
164*795d594fSAndroid Build Coastguard Worker     * Compare two floating-point values.  Puts 0, 1, or -1 into the
165*795d594fSAndroid Build Coastguard Worker     * destination register based on the results of the comparison.
166*795d594fSAndroid Build Coastguard Worker     *
167*795d594fSAndroid Build Coastguard Worker     * int compare(x, y) {
168*795d594fSAndroid Build Coastguard Worker     *     if (x == y) {
169*795d594fSAndroid Build Coastguard Worker     *         return 0;
170*795d594fSAndroid Build Coastguard Worker     *     } else if (x < y) {
171*795d594fSAndroid Build Coastguard Worker     *         return -1;
172*795d594fSAndroid Build Coastguard Worker     *     } else if (x > y) {
173*795d594fSAndroid Build Coastguard Worker     *         return 1;
174*795d594fSAndroid Build Coastguard Worker     *     } else {
175*795d594fSAndroid Build Coastguard Worker     *         return 1;
176*795d594fSAndroid Build Coastguard Worker     *     }
177*795d594fSAndroid Build Coastguard Worker     * }
178*795d594fSAndroid Build Coastguard Worker     */
179*795d594fSAndroid Build Coastguard Worker    /* op vAA, vBB, vCC */
180*795d594fSAndroid Build Coastguard Worker    FETCH r0, 1                         @ r0<- CCBB
181*795d594fSAndroid Build Coastguard Worker    mov     r4, rINST, lsr #8           @ r4<- AA
182*795d594fSAndroid Build Coastguard Worker    and     r2, r0, #255                @ r2<- BB
183*795d594fSAndroid Build Coastguard Worker    mov     r3, r0, lsr #8              @ r3<- CC
184*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
185*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
186*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d0, r2      @ d0<- vBB
187*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d1, r3      @ d1<- vCC
188*795d594fSAndroid Build Coastguard Worker    vcmpe.f64 d0, d1                    @ compare (vBB, vCC)
189*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
190*795d594fSAndroid Build Coastguard Worker    mvn     r0, #0                      @ r0<- -1 (default)
191*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
192*795d594fSAndroid Build Coastguard Worker    fmstat
193*795d594fSAndroid Build Coastguard Worker    it      hi
194*795d594fSAndroid Build Coastguard Worker    movhi   r0, #1                      @ (greater than, or unordered) r0<- 1
195*795d594fSAndroid Build Coastguard Worker    moveq   r0, #0                      @ (equal) r0<- 0
196*795d594fSAndroid Build Coastguard Worker    SET_VREG r0, r4                     @ vAA<- r0
197*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
198*795d594fSAndroid Build Coastguard Worker
199*795d594fSAndroid Build Coastguard Worker%def op_cmpg_float():
200*795d594fSAndroid Build Coastguard Worker    /*
201*795d594fSAndroid Build Coastguard Worker     * Compare two floating-point values.  Puts 0, 1, or -1 into the
202*795d594fSAndroid Build Coastguard Worker     * destination register based on the results of the comparison.
203*795d594fSAndroid Build Coastguard Worker     *
204*795d594fSAndroid Build Coastguard Worker     * int compare(x, y) {
205*795d594fSAndroid Build Coastguard Worker     *     if (x == y) {
206*795d594fSAndroid Build Coastguard Worker     *         return 0;
207*795d594fSAndroid Build Coastguard Worker     *     } else if (x < y) {
208*795d594fSAndroid Build Coastguard Worker     *         return -1;
209*795d594fSAndroid Build Coastguard Worker     *     } else if (x > y) {
210*795d594fSAndroid Build Coastguard Worker     *         return 1;
211*795d594fSAndroid Build Coastguard Worker     *     } else {
212*795d594fSAndroid Build Coastguard Worker     *         return 1;
213*795d594fSAndroid Build Coastguard Worker     *     }
214*795d594fSAndroid Build Coastguard Worker     * }
215*795d594fSAndroid Build Coastguard Worker     */
216*795d594fSAndroid Build Coastguard Worker    /* op vAA, vBB, vCC */
217*795d594fSAndroid Build Coastguard Worker    FETCH r0, 1                         @ r0<- CCBB
218*795d594fSAndroid Build Coastguard Worker    mov     r4, rINST, lsr #8           @ r4<- AA
219*795d594fSAndroid Build Coastguard Worker    and     r2, r0, #255                @ r2<- BB
220*795d594fSAndroid Build Coastguard Worker    mov     r3, r0, lsr #8              @ r3<- CC
221*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
222*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
223*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s0, r2       @ s0<- vBB
224*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s1, r3       @ s1<- vCC
225*795d594fSAndroid Build Coastguard Worker    vcmpe.f32 s0, s1                    @ compare (vBB, vCC)
226*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
227*795d594fSAndroid Build Coastguard Worker    mvn     r0, #0                      @ r0<- -1 (default)
228*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
229*795d594fSAndroid Build Coastguard Worker    fmstat
230*795d594fSAndroid Build Coastguard Worker    it      hi
231*795d594fSAndroid Build Coastguard Worker    movhi   r0, #1                      @ (greater than, or unordered) r0<- 1
232*795d594fSAndroid Build Coastguard Worker    moveq   r0, #0                      @ (equal) r0<- 0
233*795d594fSAndroid Build Coastguard Worker    SET_VREG r0, r4                     @ vAA<- r0
234*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
235*795d594fSAndroid Build Coastguard Worker
236*795d594fSAndroid Build Coastguard Worker%def op_cmpl_double():
237*795d594fSAndroid Build Coastguard Worker    /*
238*795d594fSAndroid Build Coastguard Worker     * Compare two floating-point values.  Puts 0, 1, or -1 into the
239*795d594fSAndroid Build Coastguard Worker     * destination register based on the results of the comparison.
240*795d594fSAndroid Build Coastguard Worker     *
241*795d594fSAndroid Build Coastguard Worker     * int compare(x, y) {
242*795d594fSAndroid Build Coastguard Worker     *     if (x == y) {
243*795d594fSAndroid Build Coastguard Worker     *         return 0;
244*795d594fSAndroid Build Coastguard Worker     *     } else if (x > y) {
245*795d594fSAndroid Build Coastguard Worker     *         return 1;
246*795d594fSAndroid Build Coastguard Worker     *     } else if (x < y) {
247*795d594fSAndroid Build Coastguard Worker     *         return -1;
248*795d594fSAndroid Build Coastguard Worker     *     } else {
249*795d594fSAndroid Build Coastguard Worker     *         return -1;
250*795d594fSAndroid Build Coastguard Worker     *     }
251*795d594fSAndroid Build Coastguard Worker     * }
252*795d594fSAndroid Build Coastguard Worker     */
253*795d594fSAndroid Build Coastguard Worker    /* op vAA, vBB, vCC */
254*795d594fSAndroid Build Coastguard Worker    FETCH r0, 1                         @ r0<- CCBB
255*795d594fSAndroid Build Coastguard Worker    mov     r4, rINST, lsr #8           @ r4<- AA
256*795d594fSAndroid Build Coastguard Worker    and     r2, r0, #255                @ r2<- BB
257*795d594fSAndroid Build Coastguard Worker    mov     r3, r0, lsr #8              @ r3<- CC
258*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
259*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
260*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d0, r2      @ d0<- vBB
261*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d1, r3      @ d1<- vCC
262*795d594fSAndroid Build Coastguard Worker    vcmpe.f64 d0, d1                    @ compare (vBB, vCC)
263*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
264*795d594fSAndroid Build Coastguard Worker    mvn     r0, #0                      @ r0<- -1 (default)
265*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
266*795d594fSAndroid Build Coastguard Worker    fmstat                              @ export status flags
267*795d594fSAndroid Build Coastguard Worker    it gt
268*795d594fSAndroid Build Coastguard Worker    movgt   r0, #1                      @ (greater than) r1<- 1
269*795d594fSAndroid Build Coastguard Worker    it eq
270*795d594fSAndroid Build Coastguard Worker    moveq   r0, #0                      @ (equal) r1<- 0
271*795d594fSAndroid Build Coastguard Worker    SET_VREG r0, r4                     @ vAA<- r0
272*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
273*795d594fSAndroid Build Coastguard Worker
274*795d594fSAndroid Build Coastguard Worker%def op_cmpl_float():
275*795d594fSAndroid Build Coastguard Worker    /*
276*795d594fSAndroid Build Coastguard Worker     * Compare two floating-point values.  Puts 0, 1, or -1 into the
277*795d594fSAndroid Build Coastguard Worker     * destination register based on the results of the comparison.
278*795d594fSAndroid Build Coastguard Worker     *
279*795d594fSAndroid Build Coastguard Worker     * int compare(x, y) {
280*795d594fSAndroid Build Coastguard Worker     *     if (x == y) {
281*795d594fSAndroid Build Coastguard Worker     *         return 0;
282*795d594fSAndroid Build Coastguard Worker     *     } else if (x > y) {
283*795d594fSAndroid Build Coastguard Worker     *         return 1;
284*795d594fSAndroid Build Coastguard Worker     *     } else if (x < y) {
285*795d594fSAndroid Build Coastguard Worker     *         return -1;
286*795d594fSAndroid Build Coastguard Worker     *     } else {
287*795d594fSAndroid Build Coastguard Worker     *         return -1;
288*795d594fSAndroid Build Coastguard Worker     *     }
289*795d594fSAndroid Build Coastguard Worker     * }
290*795d594fSAndroid Build Coastguard Worker     */
291*795d594fSAndroid Build Coastguard Worker    /* op vAA, vBB, vCC */
292*795d594fSAndroid Build Coastguard Worker    FETCH r0, 1                         @ r0<- CCBB
293*795d594fSAndroid Build Coastguard Worker    mov     r4, rINST, lsr #8           @ r4<- AA
294*795d594fSAndroid Build Coastguard Worker    and     r2, r0, #255                @ r2<- BB
295*795d594fSAndroid Build Coastguard Worker    mov     r3, r0, lsr #8              @ r3<- CC
296*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &vBB
297*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &vCC
298*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s0, r2       @ s0<- vBB
299*795d594fSAndroid Build Coastguard Worker    GET_VREG_FLOAT_BY_ADDR s1, r3       @ s1<- vCC
300*795d594fSAndroid Build Coastguard Worker    vcmpe.f32  s0, s1                   @ compare (vBB, vCC)
301*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
302*795d594fSAndroid Build Coastguard Worker    mvn     r0, #0                      @ r0<- -1 (default)
303*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
304*795d594fSAndroid Build Coastguard Worker    fmstat                              @ export status flags
305*795d594fSAndroid Build Coastguard Worker    it gt
306*795d594fSAndroid Build Coastguard Worker    movgt   r0, #1                      @ (greater than) r1<- 1
307*795d594fSAndroid Build Coastguard Worker    it eq
308*795d594fSAndroid Build Coastguard Worker    moveq   r0, #0                      @ (equal) r1<- 0
309*795d594fSAndroid Build Coastguard Worker    SET_VREG r0, r4                     @ vAA<- r0
310*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
311*795d594fSAndroid Build Coastguard Worker
312*795d594fSAndroid Build Coastguard Worker%def op_div_double():
313*795d594fSAndroid Build Coastguard Worker%  fbinopWide(instr="fdivd   d2, d0, d1")
314*795d594fSAndroid Build Coastguard Worker
315*795d594fSAndroid Build Coastguard Worker%def op_div_double_2addr():
316*795d594fSAndroid Build Coastguard Worker%  fbinopWide2addr(instr="fdivd   d2, d0, d1")
317*795d594fSAndroid Build Coastguard Worker
318*795d594fSAndroid Build Coastguard Worker%def op_div_float():
319*795d594fSAndroid Build Coastguard Worker%  fbinop(instr="fdivs   s2, s0, s1")
320*795d594fSAndroid Build Coastguard Worker
321*795d594fSAndroid Build Coastguard Worker%def op_div_float_2addr():
322*795d594fSAndroid Build Coastguard Worker%  fbinop2addr(instr="fdivs   s2, s0, s1")
323*795d594fSAndroid Build Coastguard Worker
324*795d594fSAndroid Build Coastguard Worker%def op_double_to_float():
325*795d594fSAndroid Build Coastguard Worker%  funopNarrower(instr="vcvt.f32.f64  s0, d0")
326*795d594fSAndroid Build Coastguard Worker
327*795d594fSAndroid Build Coastguard Worker%def op_double_to_int():
328*795d594fSAndroid Build Coastguard Worker%  funopNarrower(instr="vcvt.s32.f64  s0, d0")
329*795d594fSAndroid Build Coastguard Worker
330*795d594fSAndroid Build Coastguard Worker%def op_double_to_long():
331*795d594fSAndroid Build Coastguard Worker%  unopWide(instr="bl      nterp_d2l_doconv")
332*795d594fSAndroid Build Coastguard Worker
333*795d594fSAndroid Build Coastguard Worker%def op_float_to_double():
334*795d594fSAndroid Build Coastguard Worker%  funopWider(instr="vcvt.f64.f32  d0, s0")
335*795d594fSAndroid Build Coastguard Worker
336*795d594fSAndroid Build Coastguard Worker%def op_float_to_int():
337*795d594fSAndroid Build Coastguard Worker%  funop(instr="vcvt.s32.f32 s1, s0")
338*795d594fSAndroid Build Coastguard Worker
339*795d594fSAndroid Build Coastguard Worker%def op_float_to_long():
340*795d594fSAndroid Build Coastguard Worker%  unopWider(instr="bl      nterp_f2l_doconv")
341*795d594fSAndroid Build Coastguard Worker
342*795d594fSAndroid Build Coastguard Worker%def op_int_to_double():
343*795d594fSAndroid Build Coastguard Worker%  funopWider(instr="vcvt.f64.s32  d0, s0")
344*795d594fSAndroid Build Coastguard Worker
345*795d594fSAndroid Build Coastguard Worker%def op_int_to_float():
346*795d594fSAndroid Build Coastguard Worker%  funop(instr="vcvt.f32.s32  s1, s0")
347*795d594fSAndroid Build Coastguard Worker
348*795d594fSAndroid Build Coastguard Worker%def op_long_to_double():
349*795d594fSAndroid Build Coastguard Worker    /*
350*795d594fSAndroid Build Coastguard Worker     * Specialised 64-bit floating point operation.
351*795d594fSAndroid Build Coastguard Worker     *
352*795d594fSAndroid Build Coastguard Worker     * Note: The result will be returned in d2.
353*795d594fSAndroid Build Coastguard Worker     *
354*795d594fSAndroid Build Coastguard Worker     * For: long-to-double
355*795d594fSAndroid Build Coastguard Worker     */
356*795d594fSAndroid Build Coastguard Worker    mov     r3, rINST, lsr #12          @ r3<- B
357*795d594fSAndroid Build Coastguard Worker    ubfx    r4, rINST, #8, #4           @ r4<- A
358*795d594fSAndroid Build Coastguard Worker    CLEAR_SHADOW_PAIR r4, ip, lr        @ Zero shadow regs
359*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[B]
360*795d594fSAndroid Build Coastguard Worker    VREG_INDEX_TO_ADDR r4, r4           @ r4<- &fp[A]
361*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_BY_ADDR d0, r3      @ d0<- vBB
362*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                @ advance rPC, load rINST
363*795d594fSAndroid Build Coastguard Worker
364*795d594fSAndroid Build Coastguard Worker    vcvt.f64.s32    d1, s1              @ d1<- (double)(vAAh)
365*795d594fSAndroid Build Coastguard Worker    vcvt.f64.u32    d2, s0              @ d2<- (double)(vAAl)
366*795d594fSAndroid Build Coastguard Worker    vldr            d3, constval$opcode
367*795d594fSAndroid Build Coastguard Worker    vmla.f64        d2, d1, d3          @ d2<- vAAh*2^32 + vAAl
368*795d594fSAndroid Build Coastguard Worker
369*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  @ extract opcode from rINST
370*795d594fSAndroid Build Coastguard Worker    SET_VREG_DOUBLE_BY_ADDR d2, r4      @ vAA<- d2
371*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      @ jump to next instruction
372*795d594fSAndroid Build Coastguard Worker
373*795d594fSAndroid Build Coastguard Worker    /* literal pool helper */
374*795d594fSAndroid Build Coastguard Workerconstval${opcode}:
375*795d594fSAndroid Build Coastguard Worker    .8byte          0x41f0000000000000
376*795d594fSAndroid Build Coastguard Worker
377*795d594fSAndroid Build Coastguard Worker%def op_long_to_float():
378*795d594fSAndroid Build Coastguard Worker%  unopNarrower(instr="bl      __aeabi_l2f")
379*795d594fSAndroid Build Coastguard Worker
380*795d594fSAndroid Build Coastguard Worker%def op_mul_double():
381*795d594fSAndroid Build Coastguard Worker%  fbinopWide(instr="fmuld   d2, d0, d1")
382*795d594fSAndroid Build Coastguard Worker
383*795d594fSAndroid Build Coastguard Worker%def op_mul_double_2addr():
384*795d594fSAndroid Build Coastguard Worker%  fbinopWide2addr(instr="fmuld   d2, d0, d1")
385*795d594fSAndroid Build Coastguard Worker
386*795d594fSAndroid Build Coastguard Worker%def op_mul_float():
387*795d594fSAndroid Build Coastguard Worker%  fbinop(instr="fmuls   s2, s0, s1")
388*795d594fSAndroid Build Coastguard Worker
389*795d594fSAndroid Build Coastguard Worker%def op_mul_float_2addr():
390*795d594fSAndroid Build Coastguard Worker%  fbinop2addr(instr="fmuls   s2, s0, s1")
391*795d594fSAndroid Build Coastguard Worker
392*795d594fSAndroid Build Coastguard Worker%def op_neg_double():
393*795d594fSAndroid Build Coastguard Worker%  unopWide(instr="add     r1, r1, #0x80000000")
394*795d594fSAndroid Build Coastguard Worker
395*795d594fSAndroid Build Coastguard Worker%def op_neg_float():
396*795d594fSAndroid Build Coastguard Worker%  unop(instr="add     r0, r0, #0x80000000")
397*795d594fSAndroid Build Coastguard Worker
398*795d594fSAndroid Build Coastguard Worker%def op_rem_double():
399*795d594fSAndroid Build Coastguard Worker/* EABI doesn't define a double remainder function, but libm does */
400*795d594fSAndroid Build Coastguard Worker%  binopWide(instr="bl      fmod")
401*795d594fSAndroid Build Coastguard Worker
402*795d594fSAndroid Build Coastguard Worker%def op_rem_double_2addr():
403*795d594fSAndroid Build Coastguard Worker/* EABI doesn't define a double remainder function, but libm does */
404*795d594fSAndroid Build Coastguard Worker%  binopWide2addr(instr="bl      fmod")
405*795d594fSAndroid Build Coastguard Worker
406*795d594fSAndroid Build Coastguard Worker%def op_rem_float():
407*795d594fSAndroid Build Coastguard Worker/* EABI doesn't define a float remainder function, but libm does */
408*795d594fSAndroid Build Coastguard Worker%  binop(instr="bl      fmodf")
409*795d594fSAndroid Build Coastguard Worker
410*795d594fSAndroid Build Coastguard Worker%def op_rem_float_2addr():
411*795d594fSAndroid Build Coastguard Worker/* EABI doesn't define a float remainder function, but libm does */
412*795d594fSAndroid Build Coastguard Worker%  binop2addr(instr="bl      fmodf")
413*795d594fSAndroid Build Coastguard Worker
414*795d594fSAndroid Build Coastguard Worker%def op_sub_double():
415*795d594fSAndroid Build Coastguard Worker%  fbinopWide(instr="fsubd   d2, d0, d1")
416*795d594fSAndroid Build Coastguard Worker
417*795d594fSAndroid Build Coastguard Worker%def op_sub_double_2addr():
418*795d594fSAndroid Build Coastguard Worker%  fbinopWide2addr(instr="fsubd   d2, d0, d1")
419*795d594fSAndroid Build Coastguard Worker
420*795d594fSAndroid Build Coastguard Worker%def op_sub_float():
421*795d594fSAndroid Build Coastguard Worker%  fbinop(instr="fsubs   s2, s0, s1")
422*795d594fSAndroid Build Coastguard Worker
423*795d594fSAndroid Build Coastguard Worker%def op_sub_float_2addr():
424*795d594fSAndroid Build Coastguard Worker%  fbinop2addr(instr="fsubs   s2, s0, s1")
425