1169689Skan/* mips16 floating point support code
2169689Skan   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
3169689Skan   Contributed by Cygnus Support
4169689Skan
5169689SkanThis file is free software; you can redistribute it and/or modify it
6169689Skanunder the terms of the GNU General Public License as published by the
7169689SkanFree Software Foundation; either version 2, or (at your option) any
8169689Skanlater version.
9169689Skan
10169689SkanIn addition to the permissions in the GNU General Public License, the
11169689SkanFree Software Foundation gives you unlimited permission to link the
12169689Skancompiled version of this file with other programs, and to distribute
13169689Skanthose programs without any restriction coming from the use of this
14169689Skanfile.  (The General Public License restrictions do apply in other
15169689Skanrespects; for example, they cover modification of the file, and
16169689Skandistribution when not linked into another program.)
17169689Skan
18169689SkanThis file is distributed in the hope that it will be useful, but
19169689SkanWITHOUT ANY WARRANTY; without even the implied warranty of
20169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21169689SkanGeneral Public License for more details.
22169689Skan
23169689SkanYou should have received a copy of the GNU General Public License
24169689Skanalong with this program; see the file COPYING.  If not, write to
25169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
26169689SkanBoston, MA 02110-1301, USA.  */
27169689Skan
28169689Skan/* As a special exception, if you link this library with other files,
29169689Skan   some of which are compiled with GCC, to produce an executable,
30169689Skan   this library does not by itself cause the resulting executable
31169689Skan   to be covered by the GNU General Public License.
32169689Skan   This exception does not however invalidate any other reasons why
33169689Skan   the executable file might be covered by the GNU General Public License.  */
34169689Skan
35169689Skan/* This file contains mips16 floating point support functions.  These
36169689Skan   functions are called by mips16 code to handle floating point when
37169689Skan   -msoft-float is not used.  They accept the arguments and return
38169689Skan   values using the soft-float calling convention, but do the actual
39169689Skan   operation using the hard floating point instructions.  */
40169689Skan
41169689Skan/* This file contains 32 bit assembly code.  */
42169689Skan	.set nomips16
43169689Skan
44169689Skan/* Start a function.  */
45169689Skan
46169689Skan#define STARTFN(NAME) .globl NAME; .ent NAME; NAME:
47169689Skan
48169689Skan/* Finish a function.  */
49169689Skan
50169689Skan#define ENDFN(NAME) .end NAME
51169689Skan
52169689Skan/* Single precision math.  */
53169689Skan
54169689Skan/* This macro defines a function which loads two single precision
55169689Skan   values, performs an operation, and returns the single precision
56169689Skan   result.  */
57169689Skan
58169689Skan#define SFOP(NAME, OPCODE)	\
59169689SkanSTARTFN (NAME);			\
60169689Skan	.set	noreorder;	\
61169689Skan	mtc1	$4,$f0;		\
62169689Skan	mtc1	$5,$f2;		\
63169689Skan	nop;			\
64169689Skan	OPCODE	$f0,$f0,$f2;	\
65169689Skan	mfc1	$2,$f0;		\
66169689Skan	j	$31;		\
67169689Skan	nop;			\
68169689Skan	.set	reorder;	\
69169689Skan	ENDFN (NAME)
70169689Skan
71169689Skan#ifdef L_m16addsf3
72169689SkanSFOP(__mips16_addsf3, add.s)
73169689Skan#endif
74169689Skan#ifdef L_m16subsf3
75169689SkanSFOP(__mips16_subsf3, sub.s)
76169689Skan#endif
77169689Skan#ifdef L_m16mulsf3
78169689SkanSFOP(__mips16_mulsf3, mul.s)
79169689Skan#endif
80169689Skan#ifdef L_m16divsf3
81169689SkanSFOP(__mips16_divsf3, div.s)
82169689Skan#endif
83169689Skan
84169689Skan#define SFOP2(NAME, OPCODE)	\
85169689SkanSTARTFN (NAME);			\
86169689Skan	.set	noreorder;	\
87169689Skan	mtc1	$4,$f0;		\
88169689Skan	nop;			\
89169689Skan	OPCODE	$f0,$f0;	\
90169689Skan	mfc1	$2,$f0;		\
91169689Skan	j	$31;		\
92169689Skan	nop;			\
93169689Skan	.set	reorder;	\
94169689Skan	ENDFN (NAME)
95169689Skan
96169689Skan#ifdef L_m16negsf2
97169689SkanSFOP2(__mips16_negsf2, neg.s)
98169689Skan#endif
99169689Skan#ifdef L_m16abssf2
100169689SkanSFOP2(__mips16_abssf2, abs.s)
101169689Skan#endif
102169689Skan
103169689Skan/* Single precision comparisons.  */
104169689Skan
105169689Skan/* This macro defines a function which loads two single precision
106169689Skan   values, performs a floating point comparison, and returns the
107169689Skan   specified values according to whether the comparison is true or
108169689Skan   false.  */
109169689Skan
110169689Skan#define SFCMP(NAME, OPCODE, TRUE, FALSE)	\
111169689SkanSTARTFN (NAME);					\
112169689Skan	mtc1	$4,$f0;				\
113169689Skan	mtc1	$5,$f2;				\
114169689Skan	OPCODE	$f0,$f2;			\
115169689Skan	li	$2,TRUE;			\
116169689Skan	bc1t	1f;				\
117169689Skan	li	$2,FALSE;			\
118169689Skan1:;						\
119169689Skan	j	$31;				\
120169689Skan	ENDFN (NAME)
121169689Skan
122169689Skan/* This macro is like SFCMP, but it reverses the comparison.  */
123169689Skan
124169689Skan#define SFREVCMP(NAME, OPCODE, TRUE, FALSE)	\
125169689SkanSTARTFN (NAME);					\
126169689Skan	mtc1	$4,$f0;				\
127169689Skan	mtc1	$5,$f2;				\
128169689Skan	OPCODE	$f2,$f0;			\
129169689Skan	li	$2,TRUE;			\
130169689Skan	bc1t	1f;				\
131169689Skan	li	$2,FALSE;			\
132169689Skan1:;						\
133169689Skan	j	$31;				\
134169689Skan	ENDFN (NAME)
135169689Skan
136169689Skan#ifdef L_m16eqsf2
137169689SkanSFCMP(__mips16_eqsf2, c.eq.s, 0, 1)
138169689Skan#endif
139169689Skan#ifdef L_m16nesf2
140169689SkanSFCMP(__mips16_nesf2, c.eq.s, 0, 1)
141169689Skan#endif
142169689Skan#ifdef L_m16gtsf2
143169689SkanSFREVCMP(__mips16_gtsf2, c.lt.s, 1, 0)
144169689Skan#endif
145169689Skan#ifdef L_m16gesf2
146169689SkanSFREVCMP(__mips16_gesf2, c.le.s, 0, -1)
147169689Skan#endif
148169689Skan#ifdef L_m16lesf2
149169689SkanSFCMP(__mips16_lesf2, c.le.s, 0, 1)
150169689Skan#endif
151169689Skan#ifdef L_m16ltsf2
152169689SkanSFCMP(__mips16_ltsf2, c.lt.s, -1, 0)
153169689Skan#endif
154169689Skan
155169689Skan/* Single precision conversions.  */
156169689Skan
157169689Skan#ifdef L_m16fltsisf
158169689SkanSTARTFN (__mips16_floatsisf)
159169689Skan	.set	noreorder
160169689Skan	mtc1	$4,$f0
161169689Skan	nop
162169689Skan	cvt.s.w	$f0,$f0
163169689Skan	mfc1	$2,$f0
164169689Skan	j	$31
165169689Skan	nop
166169689Skan	.set	reorder
167169689Skan	ENDFN (__mips16_floatsisf)
168169689Skan#endif
169169689Skan
170169689Skan#ifdef L_m16fix_truncsfsi
171169689SkanSTARTFN (__mips16_fix_truncsfsi)
172169689Skan	.set	noreorder
173169689Skan	mtc1	$4,$f0
174169689Skan	nop
175169689Skan	trunc.w.s $f0,$f0,$4
176169689Skan	mfc1	$2,$f0
177169689Skan	j	$31
178169689Skan	nop
179169689Skan	.set	reorder
180169689Skan	ENDFN (__mips16_fix_truncsfsi)
181169689Skan#endif
182169689Skan
183169689Skan#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
184169689Skan
185169689Skan/* The double precision operations.  We need to use different code
186169689Skan   based on the preprocessor symbol __mips64, because the way in which
187169689Skan   double precision values will change.  Without __mips64, the value
188169689Skan   is passed in two 32 bit registers.  With __mips64, the value is
189169689Skan   passed in a single 64 bit register.  */
190169689Skan
191169689Skan/* Load the first double precision operand.  */
192169689Skan
193169689Skan#if defined(__mips64)
194169689Skan#define LDDBL1 dmtc1 $4,$f12
195169689Skan#elif defined(__mipsfp64)
196169689Skan#define LDDBL1 sw $4,0($29); sw $5,4($29); l.d $f12,0($29)
197169689Skan#elif defined(__MIPSEB__)
198169689Skan#define LDDBL1 mtc1 $4,$f13; mtc1 $5,$f12
199169689Skan#else
200169689Skan#define LDDBL1 mtc1 $4,$f12; mtc1 $5,$f13
201169689Skan#endif
202169689Skan
203169689Skan/* Load the second double precision operand.  */
204169689Skan
205169689Skan#if defined(__mips64)
206169689Skan/* XXX this should be $6 for Algo arg passing model */
207169689Skan#define LDDBL2 dmtc1 $5,$f14
208169689Skan#elif defined(__mipsfp64)
209169689Skan#define LDDBL2 sw $6,8($29); sw $7,12($29); l.d $f14,8($29)
210169689Skan#elif defined(__MIPSEB__)
211169689Skan#define LDDBL2 mtc1 $6,$f15; mtc1 $7,$f14
212169689Skan#else
213169689Skan#define LDDBL2 mtc1 $6,$f14; mtc1 $7,$f15
214169689Skan#endif
215169689Skan
216169689Skan/* Move the double precision return value to the right place.  */
217169689Skan
218169689Skan#if defined(__mips64)
219169689Skan#define RETDBL dmfc1 $2,$f0
220169689Skan#elif defined(__mipsfp64)
221169689Skan#define RETDBL s.d $f0,0($29); lw $2,0($29); lw $3,4($29)
222169689Skan#elif defined(__MIPSEB__)
223169689Skan#define RETDBL mfc1 $2,$f1; mfc1 $3,$f0
224169689Skan#else
225169689Skan#define RETDBL mfc1 $2,$f0; mfc1 $3,$f1
226169689Skan#endif
227169689Skan
228169689Skan/* Double precision math.  */
229169689Skan
230169689Skan/* This macro defines a function which loads two double precision
231169689Skan   values, performs an operation, and returns the double precision
232169689Skan   result.  */
233169689Skan
234169689Skan#define DFOP(NAME, OPCODE)	\
235169689SkanSTARTFN (NAME);			\
236169689Skan	.set	noreorder;	\
237169689Skan	LDDBL1;			\
238169689Skan	LDDBL2;			\
239169689Skan	nop;			\
240169689Skan	OPCODE	$f0,$f12,$f14;	\
241169689Skan	RETDBL;			\
242169689Skan	j	$31;		\
243169689Skan	nop;			\
244169689Skan	.set	reorder;	\
245169689Skan	ENDFN (NAME)
246169689Skan
247169689Skan#ifdef L_m16adddf3
248169689SkanDFOP(__mips16_adddf3, add.d)
249169689Skan#endif
250169689Skan#ifdef L_m16subdf3
251169689SkanDFOP(__mips16_subdf3, sub.d)
252169689Skan#endif
253169689Skan#ifdef L_m16muldf3
254169689SkanDFOP(__mips16_muldf3, mul.d)
255169689Skan#endif
256169689Skan#ifdef L_m16divdf3
257169689SkanDFOP(__mips16_divdf3, div.d)
258169689Skan#endif
259169689Skan
260169689Skan#define DFOP2(NAME, OPCODE)	\
261169689SkanSTARTFN (NAME);			\
262169689Skan	.set	noreorder;	\
263169689Skan	LDDBL1;			\
264169689Skan	nop;			\
265169689Skan	OPCODE	$f0,$f12;	\
266169689Skan	RETDBL;			\
267169689Skan	j	$31;		\
268169689Skan	nop;			\
269169689Skan	.set	reorder;	\
270169689Skan	ENDFN (NAME)
271169689Skan
272169689Skan#ifdef L_m16negdf2
273169689SkanDFOP2(__mips16_negdf2, neg.d)
274169689Skan#endif
275169689Skan#ifdef L_m16absdf2
276169689SkanDFOP2(__mips16_absdf2, abs.d)
277169689Skan#endif
278169689Skan
279169689Skan
280169689Skan/* Conversions between single and double precision.  */
281169689Skan
282169689Skan#ifdef L_m16extsfdf2
283169689SkanSTARTFN (__mips16_extendsfdf2)
284169689Skan	.set	noreorder
285169689Skan	mtc1	$4,$f12
286169689Skan	nop
287169689Skan	cvt.d.s	$f0,$f12
288169689Skan	RETDBL
289169689Skan	j	$31
290169689Skan	nop
291169689Skan	.set	reorder
292169689Skan	ENDFN (__mips16_extendsfdf2)
293169689Skan#endif
294169689Skan
295169689Skan#ifdef L_m16trdfsf2
296169689SkanSTARTFN (__mips16_truncdfsf2)
297169689Skan	.set	noreorder
298169689Skan	LDDBL1
299169689Skan	nop
300169689Skan	cvt.s.d	$f0,$f12
301169689Skan	mfc1	$2,$f0
302169689Skan	j	$31
303169689Skan	nop
304169689Skan	.set	reorder
305169689Skan	ENDFN (__mips16_truncdfsf2)
306169689Skan#endif
307169689Skan
308169689Skan/* Double precision comparisons.  */
309169689Skan
310169689Skan/* This macro defines a function which loads two double precision
311169689Skan   values, performs a floating point comparison, and returns the
312169689Skan   specified values according to whether the comparison is true or
313169689Skan   false.  */
314169689Skan
315169689Skan#define DFCMP(NAME, OPCODE, TRUE, FALSE)	\
316169689SkanSTARTFN (NAME);					\
317169689Skan	LDDBL1;					\
318169689Skan	LDDBL2;					\
319169689Skan	OPCODE	$f12,$f14;			\
320169689Skan	li	$2,TRUE;			\
321169689Skan	bc1t	1f;				\
322169689Skan	li	$2,FALSE;			\
323169689Skan1:;						\
324169689Skan	j	$31;				\
325169689Skan	ENDFN (NAME)
326169689Skan
327169689Skan/* This macro is like DFCMP, but it reverses the comparison.  */
328169689Skan
329169689Skan#define DFREVCMP(NAME, OPCODE, TRUE, FALSE)	\
330169689SkanSTARTFN (NAME);					\
331169689Skan	LDDBL1;					\
332169689Skan	LDDBL2;					\
333169689Skan	OPCODE	$f14,$f12;			\
334169689Skan	li	$2,TRUE;			\
335169689Skan	bc1t	1f;				\
336169689Skan	li	$2,FALSE;			\
337169689Skan1:;						\
338169689Skan	j	$31;				\
339169689Skan	ENDFN (NAME)
340169689Skan
341169689Skan#ifdef L_m16eqdf2
342169689SkanDFCMP(__mips16_eqdf2, c.eq.d, 0, 1)
343169689Skan#endif
344169689Skan#ifdef L_m16nedf2
345169689SkanDFCMP(__mips16_nedf2, c.eq.d, 0, 1)
346169689Skan#endif
347169689Skan#ifdef L_m16gtdf2
348169689SkanDFREVCMP(__mips16_gtdf2, c.lt.d, 1, 0)
349169689Skan#endif
350169689Skan#ifdef L_m16gedf2
351169689SkanDFREVCMP(__mips16_gedf2, c.le.d, 0, -1)
352169689Skan#endif
353169689Skan#ifdef L_m16ledf2
354169689SkanDFCMP(__mips16_ledf2, c.le.d, 0, 1)
355169689Skan#endif
356169689Skan#ifdef L_m16ltdf2
357169689SkanDFCMP(__mips16_ltdf2, c.lt.d, -1, 0)
358169689Skan#endif
359169689Skan
360169689Skan/* Double precision conversions.  */
361169689Skan
362169689Skan#ifdef L_m16fltsidf
363169689SkanSTARTFN (__mips16_floatsidf)
364169689Skan	.set	noreorder
365169689Skan	mtc1	$4,$f12
366169689Skan	nop
367169689Skan	cvt.d.w	$f0,$f12
368169689Skan	RETDBL
369169689Skan	j	$31
370169689Skan	nop
371169689Skan	.set	reorder
372169689Skan	ENDFN (__mips16_floatsidf)
373169689Skan#endif
374169689Skan
375169689Skan#ifdef L_m16fix_truncdfsi
376169689SkanSTARTFN (__mips16_fix_truncdfsi)
377169689Skan	.set	noreorder
378169689Skan	LDDBL1
379169689Skan	nop
380169689Skan	trunc.w.d $f0,$f12,$4
381169689Skan	mfc1	$2,$f0
382169689Skan	j	$31
383169689Skan	nop
384169689Skan	.set	reorder
385169689Skan	ENDFN (__mips16_fix_truncdfsi)
386169689Skan#endif
387169689Skan#endif /* !__mips_single_float */
388169689Skan
389169689Skan/* These functions are used to return floating point values from
390169689Skan   mips16 functions.  In this case we can put mtc1 in a jump delay slot,
391169689Skan   because we know that the next instruction will not refer to a floating
392169689Skan   point register.  */
393169689Skan
394169689Skan#ifdef L_m16retsf
395169689SkanSTARTFN (__mips16_ret_sf)
396169689Skan	.set	noreorder
397169689Skan	j	$31
398169689Skan	mtc1	$2,$f0
399169689Skan	.set	reorder
400169689Skan	ENDFN (__mips16_ret_sf)
401169689Skan#endif
402169689Skan
403169689Skan#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
404169689Skan#ifdef L_m16retdf
405169689SkanSTARTFN (__mips16_ret_df)
406169689Skan	.set	noreorder
407169689Skan#if defined(__mips64)
408169689Skan	j	$31
409169689Skan	dmtc1	$2,$f0
410169689Skan#elif defined(__mipsfp64)
411169689Skan	sw	$2,0($29)
412169689Skan	sw	$3,4($29)
413169689Skan	l.d	$f0,0($29)
414169689Skan#elif defined(__MIPSEB__)
415169689Skan	mtc1	$2,$f1
416169689Skan	j	$31
417169689Skan	mtc1	$3,$f0
418169689Skan#else
419169689Skan	mtc1	$2,$f0
420169689Skan	j	$31
421169689Skan	mtc1	$3,$f1
422169689Skan#endif
423169689Skan	.set	reorder
424169689Skan	ENDFN (__mips16_ret_df)
425169689Skan#endif
426169689Skan#endif /* !__mips_single_float */
427169689Skan
428169689Skan/* These functions are used by 16 bit code when calling via a function
429169689Skan   pointer.  They must copy the floating point arguments from the gp
430169689Skan   regs into the fp regs.  The function to call will be in $2.  The
431169689Skan   exact set of floating point arguments to copy is encoded in the
432169689Skan   function name; the final number is an fp_code, as described in
433169689Skan   mips.h in the comment about CUMULATIVE_ARGS.  */
434169689Skan
435169689Skan#ifdef L_m16stub1
436169689Skan/* (float) */
437169689SkanSTARTFN (__mips16_call_stub_1)
438169689Skan	.set	noreorder
439169689Skan	mtc1	$4,$f12
440169689Skan	j	$2
441169689Skan	nop
442169689Skan	.set	reorder
443169689Skan	ENDFN (__mips16_call_stub_1)
444169689Skan#endif
445169689Skan
446169689Skan#ifdef L_m16stub5
447169689Skan/* (float, float) */
448169689SkanSTARTFN (__mips16_call_stub_5)
449169689Skan	.set	noreorder
450169689Skan	mtc1	$4,$f12
451169689Skan	mtc1	$5,$f14
452169689Skan	j	$2
453169689Skan	nop
454169689Skan	.set	reorder
455169689Skan	ENDFN (__mips16_call_stub_5)
456169689Skan#endif
457169689Skan
458169689Skan#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
459169689Skan
460169689Skan#ifdef L_m16stub2
461169689Skan/* (double) */
462169689SkanSTARTFN (__mips16_call_stub_2)
463169689Skan	.set	noreorder
464169689Skan	LDDBL1
465169689Skan	j	$2
466169689Skan	nop
467169689Skan	.set	reorder
468169689Skan	ENDFN (__mips16_call_stub_2)
469169689Skan#endif
470169689Skan
471169689Skan#ifdef L_m16stub6
472169689Skan/* (double, float) */
473169689SkanSTARTFN (__mips16_call_stub_6)
474169689Skan	.set	noreorder
475169689Skan	LDDBL1
476169689Skan	mtc1	$6,$f14
477169689Skan	j	$2
478169689Skan	nop
479169689Skan	.set	reorder
480169689Skan	ENDFN (__mips16_call_stub_6)
481169689Skan#endif
482169689Skan
483169689Skan#ifdef L_m16stub9
484169689Skan/* (float, double) */
485169689SkanSTARTFN (__mips16_call_stub_9)
486169689Skan	.set	noreorder
487169689Skan	mtc1	$4,$f12
488169689Skan	LDDBL2
489169689Skan	j	$2
490169689Skan	nop
491169689Skan	.set	reorder
492169689Skan	ENDFN (__mips16_call_stub_9)
493169689Skan#endif
494169689Skan
495169689Skan#ifdef L_m16stub10
496169689Skan/* (double, double) */
497169689SkanSTARTFN (__mips16_call_stub_10)
498169689Skan	.set	noreorder
499169689Skan	LDDBL1
500169689Skan	LDDBL2
501169689Skan	j	$2
502169689Skan	nop
503169689Skan	.set	reorder
504169689Skan	ENDFN (__mips16_call_stub_10)
505169689Skan#endif
506169689Skan#endif /* !__mips_single_float */
507169689Skan
508169689Skan/* Now we have the same set of functions, except that this time the
509169689Skan   function being called returns an SFmode value.  The calling
510169689Skan   function will arrange to preserve $18, so these functions are free
511169689Skan   to use it to hold the return address.
512169689Skan
513169689Skan   Note that we do not know whether the function we are calling is 16
514169689Skan   bit or 32 bit.  However, it does not matter, because 16 bit
515169689Skan   functions always return floating point values in both the gp and
516169689Skan   the fp regs.  It would be possible to check whether the function
517169689Skan   being called is 16 bits, in which case the copy is unnecessary;
518169689Skan   however, it's faster to always do the copy.  */
519169689Skan
520169689Skan#ifdef L_m16stubsf0
521169689Skan/* () */
522169689SkanSTARTFN (__mips16_call_stub_sf_0)
523169689Skan	.set	noreorder
524169689Skan	move	$18,$31
525169689Skan	jal	$2
526169689Skan	nop
527169689Skan	mfc1	$2,$f0
528169689Skan	j	$18
529169689Skan	nop
530169689Skan	.set	reorder
531169689Skan	ENDFN (__mips16_call_stub_sf_0)
532169689Skan#endif
533169689Skan
534169689Skan#ifdef L_m16stubsf1
535169689Skan/* (float) */
536169689SkanSTARTFN (__mips16_call_stub_sf_1)
537169689Skan	.set	noreorder
538169689Skan	mtc1	$4,$f12
539169689Skan	move	$18,$31
540169689Skan	jal	$2
541169689Skan	nop
542169689Skan	mfc1	$2,$f0
543169689Skan	j	$18
544169689Skan	nop
545169689Skan	.set	reorder
546169689Skan	ENDFN (__mips16_call_stub_sf_1)
547169689Skan#endif
548169689Skan
549169689Skan#ifdef L_m16stubsf5
550169689Skan/* (float, float) */
551169689SkanSTARTFN (__mips16_call_stub_sf_5)
552169689Skan	.set	noreorder
553169689Skan	mtc1	$4,$f12
554169689Skan	mtc1	$5,$f14
555169689Skan	move	$18,$31
556169689Skan	jal	$2
557169689Skan	nop
558169689Skan	mfc1	$2,$f0
559169689Skan	j	$18
560169689Skan	nop
561169689Skan	.set	reorder
562169689Skan	ENDFN (__mips16_call_stub_sf_5)
563169689Skan#endif
564169689Skan
565169689Skan#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
566169689Skan#ifdef L_m16stubsf2
567169689Skan/* (double) */
568169689SkanSTARTFN (__mips16_call_stub_sf_2)
569169689Skan	.set	noreorder
570169689Skan	LDDBL1
571169689Skan	move	$18,$31
572169689Skan	jal	$2
573169689Skan	nop
574169689Skan	mfc1	$2,$f0
575169689Skan	j	$18
576169689Skan	nop
577169689Skan	.set	reorder
578169689Skan	ENDFN (__mips16_call_stub_sf_2)
579169689Skan#endif
580169689Skan
581169689Skan#ifdef L_m16stubsf6
582169689Skan/* (double, float) */
583169689SkanSTARTFN (__mips16_call_stub_sf_6)
584169689Skan	.set	noreorder
585169689Skan	LDDBL1
586169689Skan	mtc1	$6,$f14
587169689Skan	move	$18,$31
588169689Skan	jal	$2
589169689Skan	nop
590169689Skan	mfc1	$2,$f0
591169689Skan	j	$18
592169689Skan	nop
593169689Skan	.set	reorder
594169689Skan	ENDFN (__mips16_call_stub_sf_6)
595169689Skan#endif
596169689Skan
597169689Skan#ifdef L_m16stubsf9
598169689Skan/* (float, double) */
599169689SkanSTARTFN (__mips16_call_stub_sf_9)
600169689Skan	.set	noreorder
601169689Skan	mtc1	$4,$f12
602169689Skan	LDDBL2
603169689Skan	move	$18,$31
604169689Skan	jal	$2
605169689Skan	nop
606169689Skan	mfc1	$2,$f0
607169689Skan	j	$18
608169689Skan	nop
609169689Skan	.set	reorder
610169689Skan	ENDFN (__mips16_call_stub_sf_9)
611169689Skan#endif
612169689Skan
613169689Skan#ifdef L_m16stubsf10
614169689Skan/* (double, double) */
615169689SkanSTARTFN (__mips16_call_stub_sf_10)
616169689Skan	.set	noreorder
617169689Skan	LDDBL1
618169689Skan	LDDBL2
619169689Skan	move	$18,$31
620169689Skan	jal	$2
621169689Skan	nop
622169689Skan	mfc1	$2,$f0
623169689Skan	j	$18
624169689Skan	nop
625169689Skan	.set	reorder
626169689Skan	ENDFN (__mips16_call_stub_sf_10)
627169689Skan#endif
628169689Skan
629169689Skan/* Now we have the same set of functions again, except that this time
630169689Skan   the function being called returns an DFmode value.  */
631169689Skan
632169689Skan#ifdef L_m16stubdf0
633169689Skan/* () */
634169689SkanSTARTFN (__mips16_call_stub_df_0)
635169689Skan	.set	noreorder
636169689Skan	move	$18,$31
637169689Skan	jal	$2
638169689Skan	nop
639169689Skan	RETDBL
640169689Skan	j	$18
641169689Skan	nop
642169689Skan	.set	reorder
643169689Skan	ENDFN (__mips16_call_stub_df_0)
644169689Skan#endif
645169689Skan
646169689Skan#ifdef L_m16stubdf1
647169689Skan/* (float) */
648169689SkanSTARTFN (__mips16_call_stub_df_1)
649169689Skan	.set	noreorder
650169689Skan	mtc1	$4,$f12
651169689Skan	move	$18,$31
652169689Skan	jal	$2
653169689Skan	nop
654169689Skan	RETDBL
655169689Skan	j	$18
656169689Skan	nop
657169689Skan	.set	reorder
658169689Skan	ENDFN (__mips16_call_stub_df_1)
659169689Skan#endif
660169689Skan
661169689Skan#ifdef L_m16stubdf2
662169689Skan/* (double) */
663169689SkanSTARTFN (__mips16_call_stub_df_2)
664169689Skan	.set	noreorder
665169689Skan	LDDBL1
666169689Skan	move	$18,$31
667169689Skan	jal	$2
668169689Skan	nop
669169689Skan	RETDBL
670169689Skan	j	$18
671169689Skan	nop
672169689Skan	.set	reorder
673169689Skan	ENDFN (__mips16_call_stub_df_2)
674169689Skan#endif
675169689Skan
676169689Skan#ifdef L_m16stubdf5
677169689Skan/* (float, float) */
678169689SkanSTARTFN (__mips16_call_stub_df_5)
679169689Skan	.set	noreorder
680169689Skan	mtc1	$4,$f12
681169689Skan	mtc1	$5,$f14
682169689Skan	move	$18,$31
683169689Skan	jal	$2
684169689Skan	nop
685169689Skan	RETDBL
686169689Skan	j	$18
687169689Skan	nop
688169689Skan	.set	reorder
689169689Skan	ENDFN (__mips16_call_stub_df_5)
690169689Skan#endif
691169689Skan
692169689Skan#ifdef L_m16stubdf6
693169689Skan/* (double, float) */
694169689SkanSTARTFN (__mips16_call_stub_df_6)
695169689Skan	.set	noreorder
696169689Skan	LDDBL1
697169689Skan	mtc1	$6,$f14
698169689Skan	move	$18,$31
699169689Skan	jal	$2
700169689Skan	nop
701169689Skan	RETDBL
702169689Skan	j	$18
703169689Skan	nop
704169689Skan	.set	reorder
705169689Skan	ENDFN (__mips16_call_stub_df_6)
706169689Skan#endif
707169689Skan
708169689Skan#ifdef L_m16stubdf9
709169689Skan/* (float, double) */
710169689SkanSTARTFN (__mips16_call_stub_df_9)
711169689Skan	.set	noreorder
712169689Skan	mtc1	$4,$f12
713169689Skan	LDDBL2
714169689Skan	move	$18,$31
715169689Skan	jal	$2
716169689Skan	nop
717169689Skan	RETDBL
718169689Skan	j	$18
719169689Skan	nop
720169689Skan	.set	reorder
721169689Skan	ENDFN (__mips16_call_stub_df_9)
722169689Skan#endif
723169689Skan
724169689Skan#ifdef L_m16stubdf10
725169689Skan/* (double, double) */
726169689SkanSTARTFN (__mips16_call_stub_df_10)
727169689Skan	.set	noreorder
728169689Skan	LDDBL1
729169689Skan	LDDBL2
730169689Skan	move	$18,$31
731169689Skan	jal	$2
732169689Skan	nop
733169689Skan	RETDBL
734169689Skan	j	$18
735169689Skan	nop
736169689Skan	.set	reorder
737169689Skan	ENDFN (__mips16_call_stub_df_10)
738169689Skan#endif
739169689Skan#endif /* !__mips_single_float */
740