xref: /aosp_15_r20/art/runtime/interpreter/mterp/arm64ng/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.
4*795d594fSAndroid Build Coastguard Worker     *
5*795d594fSAndroid Build Coastguard Worker     * For: add-float, sub-float, mul-float, div-float
6*795d594fSAndroid Build Coastguard Worker     * form: <op> s0, s0, s1
7*795d594fSAndroid Build Coastguard Worker     */
8*795d594fSAndroid Build Coastguard Worker    /* floatop vAA, vBB, vCC */
9*795d594fSAndroid Build Coastguard Worker    FETCH w0, 1                         // r0<- CCBB
10*795d594fSAndroid Build Coastguard Worker    lsr     w1, w0, #8                  // r2<- CC
11*795d594fSAndroid Build Coastguard Worker    and     w0, w0, #255                // r1<- BB
12*795d594fSAndroid Build Coastguard Worker    GET_VREG  s1, w1
13*795d594fSAndroid Build Coastguard Worker    GET_VREG  s0, w0
14*795d594fSAndroid Build Coastguard Worker    $instr                              // s0<- op
15*795d594fSAndroid Build Coastguard Worker    lsr     w1, wINST, #8               // r1<- AA
16*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
17*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
18*795d594fSAndroid Build Coastguard Worker    SET_VREG_FLOAT s0, w1
19*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker%def fbinopWide(instr="fadd d0, d1, d2", result="d0", r1="d1", r2="d2"):
22*795d594fSAndroid Build Coastguard Worker    /*
23*795d594fSAndroid Build Coastguard Worker     * Generic 64-bit floating-point operation.
24*795d594fSAndroid Build Coastguard Worker     */
25*795d594fSAndroid Build Coastguard Worker    /* binop vAA, vBB, vCC */
26*795d594fSAndroid Build Coastguard Worker    FETCH w0, 1                         // w0<- CCBB
27*795d594fSAndroid Build Coastguard Worker    lsr     w4, wINST, #8               // w4<- AA
28*795d594fSAndroid Build Coastguard Worker    lsr     w2, w0, #8                  // w2<- CC
29*795d594fSAndroid Build Coastguard Worker    and     w1, w0, #255                // w1<- BB
30*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE $r2, w2             // w2<- vCC
31*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE $r1, w1             // w1<- vBB
32*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
33*795d594fSAndroid Build Coastguard Worker    $instr                              // $result<- op, w0-w4 changed
34*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
35*795d594fSAndroid Build Coastguard Worker    SET_VREG_DOUBLE $result, w4         // vAA<- $result
36*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker%def fbinop2addr(instr=""):
39*795d594fSAndroid Build Coastguard Worker    /*
40*795d594fSAndroid Build Coastguard Worker     * Generic 32-bit floating point "/2addr" binary operation.  Provide
41*795d594fSAndroid Build Coastguard Worker     * an "instr" line that specifies an instruction that performs
42*795d594fSAndroid Build Coastguard Worker     * "s2 = s0 op s1".
43*795d594fSAndroid Build Coastguard Worker     *
44*795d594fSAndroid Build Coastguard Worker     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
45*795d594fSAndroid Build Coastguard Worker     */
46*795d594fSAndroid Build Coastguard Worker    /* binop/2addr vA, vB */
47*795d594fSAndroid Build Coastguard Worker    lsr     w3, wINST, #12              // w3<- B
48*795d594fSAndroid Build Coastguard Worker    ubfx    w9, wINST, #8, #4           // w9<- A
49*795d594fSAndroid Build Coastguard Worker    GET_VREG s1, w3
50*795d594fSAndroid Build Coastguard Worker    GET_VREG s0, w9
51*795d594fSAndroid Build Coastguard Worker    $instr                              // s2<- op
52*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
53*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
54*795d594fSAndroid Build Coastguard Worker    SET_VREG_FLOAT s2, w9
55*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
56*795d594fSAndroid Build Coastguard Worker
57*795d594fSAndroid Build Coastguard Worker%def fbinopWide2addr(instr="fadd d0, d0, d1", r0="d0", r1="d1"):
58*795d594fSAndroid Build Coastguard Worker    /*
59*795d594fSAndroid Build Coastguard Worker     * Generic 64-bit floating point "/2addr" binary operation.
60*795d594fSAndroid Build Coastguard Worker     */
61*795d594fSAndroid Build Coastguard Worker    /* binop/2addr vA, vB */
62*795d594fSAndroid Build Coastguard Worker    lsr     w1, wINST, #12              // w1<- B
63*795d594fSAndroid Build Coastguard Worker    ubfx    w2, wINST, #8, #4           // w2<- A
64*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE $r1, w1             // x1<- vB
65*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE $r0, w2             // x0<- vA
66*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
67*795d594fSAndroid Build Coastguard Worker    $instr                              // result<- op
68*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
69*795d594fSAndroid Build Coastguard Worker    SET_VREG_DOUBLE $r0, w2             // vAA<- result
70*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
71*795d594fSAndroid Build Coastguard Worker
72*795d594fSAndroid Build Coastguard Worker%def fcmp(r1="s1", r2="s2", cond="lt"):
73*795d594fSAndroid Build Coastguard Worker    /*
74*795d594fSAndroid Build Coastguard Worker     * Compare two floating-point values.  Puts 0, 1, or -1 into the
75*795d594fSAndroid Build Coastguard Worker     * destination register based on the results of the comparison.
76*795d594fSAndroid Build Coastguard Worker     */
77*795d594fSAndroid Build Coastguard Worker    /* op vAA, vBB, vCC */
78*795d594fSAndroid Build Coastguard Worker    FETCH w0, 1                         // w0<- CCBB
79*795d594fSAndroid Build Coastguard Worker%  if r1.startswith("d"):
80*795d594fSAndroid Build Coastguard Worker    LOAD_SCALED_VREG_MASK w5, 0xff      // w4<- ff * sizeof(vreg)
81*795d594fSAndroid Build Coastguard Worker    lsr     w4, wINST, #8               // w4<- AA
82*795d594fSAndroid Build Coastguard Worker    EXTRACT_SCALED_VREG w2, w5, w0, 0   // w2<- BB * sizeof(vreg)
83*795d594fSAndroid Build Coastguard Worker    EXTRACT_SCALED_VREG w3, w5, w0, 8   // w3<- CC * sizeof(vreg)
84*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_PRESCALED $r1, w2
85*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE_PRESCALED $r2, w3
86*795d594fSAndroid Build Coastguard Worker%  else:
87*795d594fSAndroid Build Coastguard Worker    lsr     w4, wINST, #8               // w4<- AA
88*795d594fSAndroid Build Coastguard Worker    and     w2, w0, #255                // w2<- BB
89*795d594fSAndroid Build Coastguard Worker    lsr     w3, w0, #8                  // w3<- CC
90*795d594fSAndroid Build Coastguard Worker    GET_VREG $r1, w2
91*795d594fSAndroid Build Coastguard Worker    GET_VREG $r2, w3
92*795d594fSAndroid Build Coastguard Worker%  #endif
93*795d594fSAndroid Build Coastguard Worker    fcmp $r1, $r2
94*795d594fSAndroid Build Coastguard Worker    cset w0, ne
95*795d594fSAndroid Build Coastguard Worker    cneg w0, w0, $cond
96*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
97*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
98*795d594fSAndroid Build Coastguard Worker    SET_VREG w0, w4                     // vAA<- w0
99*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
100*795d594fSAndroid Build Coastguard Worker
101*795d594fSAndroid Build Coastguard Worker%def funopNarrow(srcreg="s0", tgtreg="d0", instr=""):
102*795d594fSAndroid Build Coastguard Worker    /*
103*795d594fSAndroid Build Coastguard Worker     * Generic 32bit-to-32bit floating point unary operation.  Provide an
104*795d594fSAndroid Build Coastguard Worker     * "instr" line that specifies an instruction that performs "$tgtreg = op $srcreg".
105*795d594fSAndroid Build Coastguard Worker     *
106*795d594fSAndroid Build Coastguard Worker     * For: int-to-float, float-to-int
107*795d594fSAndroid Build Coastguard Worker     * TODO: refactor all of the conversions - parameterize width and use same template.
108*795d594fSAndroid Build Coastguard Worker     */
109*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
110*795d594fSAndroid Build Coastguard Worker    lsr     w3, wINST, #12              // w3<- B
111*795d594fSAndroid Build Coastguard Worker    ubfx    w4, wINST, #8, #4           // w4<- A
112*795d594fSAndroid Build Coastguard Worker    GET_VREG $srcreg, w3
113*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
114*795d594fSAndroid Build Coastguard Worker    $instr                              // d0<- op
115*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from wINST
116*795d594fSAndroid Build Coastguard Worker    SET_VREG_FLOAT $tgtreg, w4          // vA<- d0
117*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
118*795d594fSAndroid Build Coastguard Worker
119*795d594fSAndroid Build Coastguard Worker%def funopNarrower(srcreg="s0", tgtreg="d0", instr=""):
120*795d594fSAndroid Build Coastguard Worker    /*
121*795d594fSAndroid Build Coastguard Worker     * Generic 64bit-to-32bit floating point unary operation.  Provide an
122*795d594fSAndroid Build Coastguard Worker     * "instr" line that specifies an instruction that performs "$tgtreg = op $srcreg".
123*795d594fSAndroid Build Coastguard Worker     *
124*795d594fSAndroid Build Coastguard Worker     * For: int-to-double, float-to-double, float-to-long
125*795d594fSAndroid Build Coastguard Worker     */
126*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
127*795d594fSAndroid Build Coastguard Worker    lsr     w3, wINST, #12              // w3<- B
128*795d594fSAndroid Build Coastguard Worker    ubfx    w4, wINST, #8, #4           // w4<- A
129*795d594fSAndroid Build Coastguard Worker%  if srcreg.startswith("d"):
130*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE $srcreg, w3
131*795d594fSAndroid Build Coastguard Worker%  else:
132*795d594fSAndroid Build Coastguard Worker    GET_VREG_WIDE $srcreg, w3
133*795d594fSAndroid Build Coastguard Worker%  #endif
134*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
135*795d594fSAndroid Build Coastguard Worker    $instr                              // d0<- op
136*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from wINST
137*795d594fSAndroid Build Coastguard Worker    SET_VREG_FLOAT $tgtreg, w4          // vA<- d0
138*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
139*795d594fSAndroid Build Coastguard Worker
140*795d594fSAndroid Build Coastguard Worker%def funopWide(srcreg="s0", tgtreg="d0", instr=""):
141*795d594fSAndroid Build Coastguard Worker    /*
142*795d594fSAndroid Build Coastguard Worker     * Generic 64bit-to-64bit floating point unary operation.  Provide an
143*795d594fSAndroid Build Coastguard Worker     * "instr" line that specifies an instruction that performs "$tgtreg = op $srcreg".
144*795d594fSAndroid Build Coastguard Worker     *
145*795d594fSAndroid Build Coastguard Worker     * For: long-to-double, double-to-long
146*795d594fSAndroid Build Coastguard Worker     */
147*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
148*795d594fSAndroid Build Coastguard Worker    lsr     w3, wINST, #12              // w3<- B
149*795d594fSAndroid Build Coastguard Worker    ubfx    w4, wINST, #8, #4           // w4<- A
150*795d594fSAndroid Build Coastguard Worker%  if srcreg.startswith("d"):
151*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE $srcreg, w3
152*795d594fSAndroid Build Coastguard Worker%  else:
153*795d594fSAndroid Build Coastguard Worker    GET_VREG_WIDE $srcreg, w3
154*795d594fSAndroid Build Coastguard Worker%  #endif
155*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
156*795d594fSAndroid Build Coastguard Worker    $instr                              // d0<- op
157*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from wINST
158*795d594fSAndroid Build Coastguard Worker%  if tgtreg.startswith("d"):
159*795d594fSAndroid Build Coastguard Worker    SET_VREG_DOUBLE $tgtreg, w4         // vA<- d0
160*795d594fSAndroid Build Coastguard Worker%  else:
161*795d594fSAndroid Build Coastguard Worker    SET_VREG_WIDE $tgtreg, w4           // vA<- d0
162*795d594fSAndroid Build Coastguard Worker%  #endif
163*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
164*795d594fSAndroid Build Coastguard Worker
165*795d594fSAndroid Build Coastguard Worker%def funopWider(srcreg="s0", tgtreg="d0", instr=""):
166*795d594fSAndroid Build Coastguard Worker    /*
167*795d594fSAndroid Build Coastguard Worker     * Generic 32bit-to-64bit floating point unary operation.  Provide an
168*795d594fSAndroid Build Coastguard Worker     * "instr" line that specifies an instruction that performs "$tgtreg = op $srcreg".
169*795d594fSAndroid Build Coastguard Worker     *
170*795d594fSAndroid Build Coastguard Worker     * For: int-to-double, float-to-double, float-to-long
171*795d594fSAndroid Build Coastguard Worker     */
172*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
173*795d594fSAndroid Build Coastguard Worker    lsr     w3, wINST, #12              // w3<- B
174*795d594fSAndroid Build Coastguard Worker    ubfx    w4, wINST, #8, #4           // w4<- A
175*795d594fSAndroid Build Coastguard Worker    GET_VREG $srcreg, w3
176*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                // advance rPC, load wINST
177*795d594fSAndroid Build Coastguard Worker    $instr                              // d0<- op
178*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from wINST
179*795d594fSAndroid Build Coastguard Worker    SET_VREG_WIDE $tgtreg, w4           // vA<- d0
180*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
181*795d594fSAndroid Build Coastguard Worker
182*795d594fSAndroid Build Coastguard Worker%def op_add_double():
183*795d594fSAndroid Build Coastguard Worker%  fbinopWide(instr="fadd d0, d1, d2", result="d0", r1="d1", r2="d2")
184*795d594fSAndroid Build Coastguard Worker
185*795d594fSAndroid Build Coastguard Worker%def op_add_double_2addr():
186*795d594fSAndroid Build Coastguard Worker%  fbinopWide2addr(instr="fadd     d0, d0, d1", r0="d0", r1="d1")
187*795d594fSAndroid Build Coastguard Worker
188*795d594fSAndroid Build Coastguard Worker%def op_add_float():
189*795d594fSAndroid Build Coastguard Worker%  fbinop(instr="fadd   s0, s0, s1")
190*795d594fSAndroid Build Coastguard Worker
191*795d594fSAndroid Build Coastguard Worker%def op_add_float_2addr():
192*795d594fSAndroid Build Coastguard Worker%  fbinop2addr(instr="fadd   s2, s0, s1")
193*795d594fSAndroid Build Coastguard Worker
194*795d594fSAndroid Build Coastguard Worker%def op_cmpg_double():
195*795d594fSAndroid Build Coastguard Worker%  fcmp(r1="d1", r2="d2", cond="cc")
196*795d594fSAndroid Build Coastguard Worker
197*795d594fSAndroid Build Coastguard Worker%def op_cmpg_float():
198*795d594fSAndroid Build Coastguard Worker%  fcmp(r1="s1", r2="s2", cond="cc")
199*795d594fSAndroid Build Coastguard Worker
200*795d594fSAndroid Build Coastguard Worker%def op_cmpl_double():
201*795d594fSAndroid Build Coastguard Worker%  fcmp(r1="d1", r2="d2", cond="lt")
202*795d594fSAndroid Build Coastguard Worker
203*795d594fSAndroid Build Coastguard Worker%def op_cmpl_float():
204*795d594fSAndroid Build Coastguard Worker%  fcmp(r1="s1", r2="s2", cond="lt")
205*795d594fSAndroid Build Coastguard Worker
206*795d594fSAndroid Build Coastguard Worker%def op_div_double():
207*795d594fSAndroid Build Coastguard Worker%  fbinopWide(instr="fdiv d0, d1, d2", result="d0", r1="d1", r2="d2")
208*795d594fSAndroid Build Coastguard Worker
209*795d594fSAndroid Build Coastguard Worker%def op_div_double_2addr():
210*795d594fSAndroid Build Coastguard Worker%  fbinopWide2addr(instr="fdiv     d0, d0, d1", r0="d0", r1="d1")
211*795d594fSAndroid Build Coastguard Worker
212*795d594fSAndroid Build Coastguard Worker%def op_div_float():
213*795d594fSAndroid Build Coastguard Worker%  fbinop(instr="fdiv   s0, s0, s1")
214*795d594fSAndroid Build Coastguard Worker
215*795d594fSAndroid Build Coastguard Worker%def op_div_float_2addr():
216*795d594fSAndroid Build Coastguard Worker%  fbinop2addr(instr="fdiv   s2, s0, s1")
217*795d594fSAndroid Build Coastguard Worker
218*795d594fSAndroid Build Coastguard Worker%def op_double_to_float():
219*795d594fSAndroid Build Coastguard Worker%  funopNarrower(instr="fcvt s0, d0", srcreg="d0", tgtreg="s0")
220*795d594fSAndroid Build Coastguard Worker
221*795d594fSAndroid Build Coastguard Worker%def op_double_to_int():
222*795d594fSAndroid Build Coastguard Worker%  funopNarrower(instr="fcvtzs w0, d0", srcreg="d0", tgtreg="w0")
223*795d594fSAndroid Build Coastguard Worker
224*795d594fSAndroid Build Coastguard Worker%def op_double_to_long():
225*795d594fSAndroid Build Coastguard Worker%  funopWide(instr="fcvtzs x0, d0", srcreg="d0", tgtreg="x0")
226*795d594fSAndroid Build Coastguard Worker
227*795d594fSAndroid Build Coastguard Worker%def op_float_to_double():
228*795d594fSAndroid Build Coastguard Worker%  funopWider(instr="fcvt  d0, s0", srcreg="s0", tgtreg="d0")
229*795d594fSAndroid Build Coastguard Worker
230*795d594fSAndroid Build Coastguard Worker%def op_float_to_int():
231*795d594fSAndroid Build Coastguard Worker%  funopNarrow(instr="fcvtzs w0, s0", srcreg="s0", tgtreg="w0")
232*795d594fSAndroid Build Coastguard Worker
233*795d594fSAndroid Build Coastguard Worker%def op_float_to_long():
234*795d594fSAndroid Build Coastguard Worker%  funopWider(instr="fcvtzs x0, s0", srcreg="s0", tgtreg="x0")
235*795d594fSAndroid Build Coastguard Worker
236*795d594fSAndroid Build Coastguard Worker%def op_int_to_double():
237*795d594fSAndroid Build Coastguard Worker%  funopWider(instr="scvtf d0, w0", srcreg="w0", tgtreg="d0")
238*795d594fSAndroid Build Coastguard Worker
239*795d594fSAndroid Build Coastguard Worker%def op_int_to_float():
240*795d594fSAndroid Build Coastguard Worker%  funopNarrow(instr="scvtf s0, w0", srcreg="w0", tgtreg="s0")
241*795d594fSAndroid Build Coastguard Worker
242*795d594fSAndroid Build Coastguard Worker%def op_long_to_double():
243*795d594fSAndroid Build Coastguard Worker%  funopWide(instr="scvtf d0, x0", srcreg="x0", tgtreg="d0")
244*795d594fSAndroid Build Coastguard Worker
245*795d594fSAndroid Build Coastguard Worker%def op_long_to_float():
246*795d594fSAndroid Build Coastguard Worker%  funopNarrower(instr="scvtf s0, x0", srcreg="x0", tgtreg="s0")
247*795d594fSAndroid Build Coastguard Worker
248*795d594fSAndroid Build Coastguard Worker%def op_mul_double():
249*795d594fSAndroid Build Coastguard Worker%  fbinopWide(instr="fmul d0, d1, d2", result="d0", r1="d1", r2="d2")
250*795d594fSAndroid Build Coastguard Worker
251*795d594fSAndroid Build Coastguard Worker%def op_mul_double_2addr():
252*795d594fSAndroid Build Coastguard Worker%  fbinopWide2addr(instr="fmul     d0, d0, d1", r0="d0", r1="d1")
253*795d594fSAndroid Build Coastguard Worker
254*795d594fSAndroid Build Coastguard Worker%def op_mul_float():
255*795d594fSAndroid Build Coastguard Worker%  fbinop(instr="fmul   s0, s0, s1")
256*795d594fSAndroid Build Coastguard Worker
257*795d594fSAndroid Build Coastguard Worker%def op_mul_float_2addr():
258*795d594fSAndroid Build Coastguard Worker%  fbinop2addr(instr="fmul   s2, s0, s1")
259*795d594fSAndroid Build Coastguard Worker
260*795d594fSAndroid Build Coastguard Worker%def op_neg_double():
261*795d594fSAndroid Build Coastguard Worker%  unopWide(instr="eor     x0, x0, #0x8000000000000000")
262*795d594fSAndroid Build Coastguard Worker
263*795d594fSAndroid Build Coastguard Worker%def op_neg_float():
264*795d594fSAndroid Build Coastguard Worker%  unop(instr="eor     w0, w0, #0x80000000")
265*795d594fSAndroid Build Coastguard Worker
266*795d594fSAndroid Build Coastguard Worker%def op_rem_double():
267*795d594fSAndroid Build Coastguard Worker    /* rem vAA, vBB, vCC */
268*795d594fSAndroid Build Coastguard Worker    FETCH w0, 1                         // w0<- CCBB
269*795d594fSAndroid Build Coastguard Worker    lsr     w2, w0, #8                  // w2<- CC
270*795d594fSAndroid Build Coastguard Worker    and     w1, w0, #255                // w1<- BB
271*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE d1, w2              // d1<- vCC
272*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE d0, w1              // d0<- vBB
273*795d594fSAndroid Build Coastguard Worker    bl  fmod
274*795d594fSAndroid Build Coastguard Worker    lsr     w4, wINST, #8               // w4<- AA
275*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 2                // advance rPC, load rINST
276*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
277*795d594fSAndroid Build Coastguard Worker    SET_VREG_WIDE d0, w4                // vAA<- result
278*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
279*795d594fSAndroid Build Coastguard Worker    /* 11-14 instructions */
280*795d594fSAndroid Build Coastguard Worker
281*795d594fSAndroid Build Coastguard Worker%def op_rem_double_2addr():
282*795d594fSAndroid Build Coastguard Worker    /* rem vA, vB */
283*795d594fSAndroid Build Coastguard Worker    lsr     w1, wINST, #12              // w1<- B
284*795d594fSAndroid Build Coastguard Worker    ubfx    w2, wINST, #8, #4           // w2<- A
285*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE d1, w1              // d1<- vB
286*795d594fSAndroid Build Coastguard Worker    GET_VREG_DOUBLE d0, w2              // d0<- vA
287*795d594fSAndroid Build Coastguard Worker    bl fmod
288*795d594fSAndroid Build Coastguard Worker    ubfx    w2, wINST, #8, #4           // w2<- A (need to reload - killed across call)
289*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
290*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
291*795d594fSAndroid Build Coastguard Worker    SET_VREG_WIDE d0, w2                // vAA<- result
292*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
293*795d594fSAndroid Build Coastguard Worker    /* 10-13 instructions */
294*795d594fSAndroid Build Coastguard Worker
295*795d594fSAndroid Build Coastguard Worker%def op_rem_float():
296*795d594fSAndroid Build Coastguard Worker/* EABI doesn't define a float remainder function, but libm does */
297*795d594fSAndroid Build Coastguard Worker%  fbinop(instr="bl      fmodf")
298*795d594fSAndroid Build Coastguard Worker
299*795d594fSAndroid Build Coastguard Worker%def op_rem_float_2addr():
300*795d594fSAndroid Build Coastguard Worker    /* rem vA, vB */
301*795d594fSAndroid Build Coastguard Worker    lsr     w3, wINST, #12              // w3<- B
302*795d594fSAndroid Build Coastguard Worker    ubfx    w9, wINST, #8, #4           // w9<- A
303*795d594fSAndroid Build Coastguard Worker    GET_VREG s1, w3
304*795d594fSAndroid Build Coastguard Worker    GET_VREG s0, w9
305*795d594fSAndroid Build Coastguard Worker    bl  fmodf
306*795d594fSAndroid Build Coastguard Worker    ubfx    w9, wINST, #8, #4           // w9<- A
307*795d594fSAndroid Build Coastguard Worker    FETCH_ADVANCE_INST 1                // advance rPC, load rINST
308*795d594fSAndroid Build Coastguard Worker    GET_INST_OPCODE ip                  // extract opcode from rINST
309*795d594fSAndroid Build Coastguard Worker    SET_VREG_FLOAT s0, w9
310*795d594fSAndroid Build Coastguard Worker    GOTO_OPCODE ip                      // jump to next instruction
311*795d594fSAndroid Build Coastguard Worker
312*795d594fSAndroid Build Coastguard Worker%def op_sub_double():
313*795d594fSAndroid Build Coastguard Worker%  fbinopWide(instr="fsub d0, d1, d2", result="d0", r1="d1", r2="d2")
314*795d594fSAndroid Build Coastguard Worker
315*795d594fSAndroid Build Coastguard Worker%def op_sub_double_2addr():
316*795d594fSAndroid Build Coastguard Worker%  fbinopWide2addr(instr="fsub     d0, d0, d1", r0="d0", r1="d1")
317*795d594fSAndroid Build Coastguard Worker
318*795d594fSAndroid Build Coastguard Worker%def op_sub_float():
319*795d594fSAndroid Build Coastguard Worker%  fbinop(instr="fsub   s0, s0, s1")
320*795d594fSAndroid Build Coastguard Worker
321*795d594fSAndroid Build Coastguard Worker%def op_sub_float_2addr():
322*795d594fSAndroid Build Coastguard Worker%  fbinop2addr(instr="fsub   s2, s0, s1")
323