OSDN Git Service

Licensing changes to GPLv3 resp. GPLv3 with GCC Runtime Exception.
[pf3gnuchains/gcc-fork.git] / gcc / config / mips / mips16.S
1 /* mips16 floating point support code
2    Copyright (C) 1996, 1997, 1998, 2008, 2009 Free Software Foundation, Inc.
3    Contributed by Cygnus Support
4
5 This file is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3, or (at your option) any
8 later version.
9
10 This file is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 General Public License for more details.
14
15 Under Section 7 of GPL version 3, you are granted additional
16 permissions described in the GCC Runtime Library Exception, version
17 3.1, as published by the Free Software Foundation.
18
19 You should have received a copy of the GNU General Public License and
20 a copy of the GCC Runtime Library Exception along with this program;
21 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22 <http://www.gnu.org/licenses/>.  */
23
24 /* This file contains mips16 floating point support functions.  These
25    functions are called by mips16 code to handle floating point when
26    -msoft-float is not used.  They accept the arguments and return
27    values using the soft-float calling convention, but do the actual
28    operation using the hard floating point instructions.  */
29
30 #if defined _MIPS_SIM && (_MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIO64)
31
32 /* This file contains 32-bit assembly code.  */
33         .set nomips16
34
35 /* Start a function.  */
36
37 #define STARTFN(NAME) .globl NAME; .ent NAME; NAME:
38
39 /* Finish a function.  */
40
41 #define ENDFN(NAME) .end NAME
42
43 /* ARG1
44         The FPR that holds the first floating-point argument.
45
46    ARG2
47         The FPR that holds the second floating-point argument.
48
49    RET
50         The FPR that holds a floating-point return value.  */
51
52 #define RET $f0
53 #define ARG1 $f12
54 #ifdef __mips64
55 #define ARG2 $f13
56 #else
57 #define ARG2 $f14
58 #endif
59
60 /* Set 64-bit register GPR so that its high 32 bits contain HIGH_FPR
61    and so that its low 32 bits contain LOW_FPR.  */
62 #define MERGE_GPRf(GPR, HIGH_FPR, LOW_FPR)      \
63         .set    noat;                           \
64         mfc1    GPR, HIGH_FPR;                  \
65         mfc1    $1, LOW_FPR;                    \
66         dsll    GPR, GPR, 32;                   \
67         or      GPR, GPR, $1;                   \
68         .set    at
69
70 /* Move the high 32 bits of GPR to HIGH_FPR and the low 32 bits of
71    GPR to LOW_FPR.  */
72 #define MERGE_GPRt(GPR, HIGH_FPR, LOW_FPR)      \
73         .set    noat;                           \
74         dsrl    $1, GPR, 32;                    \
75         mtc1    GPR, LOW_FPR;                   \
76         mtc1    $1, HIGH_FPR;                   \
77         .set    at
78
79 /* Jump to T, and use "OPCODE, OP2" to implement a delayed move.  */
80 #define DELAYt(T, OPCODE, OP2)                  \
81         .set    noreorder;                      \
82         jr      T;                              \
83         OPCODE, OP2;                            \
84         .set    reorder
85
86 /* Use "OPCODE. OP2" and jump to T.  */
87 #define DELAYf(T, OPCODE, OP2) OPCODE, OP2; jr T
88
89 /* MOVE_SF_BYTE0(D)
90         Move the first single-precision floating-point argument between
91         GPRs and FPRs.
92
93    MOVE_SI_BYTE0(D)
94         Likewise the first single-precision integer argument.
95
96    MOVE_SF_BYTE4(D)
97         Move the second single-precision floating-point argument between
98         GPRs and FPRs, given that the first argument occupies 4 bytes.
99
100    MOVE_SF_BYTE8(D)
101         Move the second single-precision floating-point argument between
102         GPRs and FPRs, given that the first argument occupies 8 bytes.
103
104    MOVE_DF_BYTE0(D)
105         Move the first double-precision floating-point argument between
106         GPRs and FPRs.
107
108    MOVE_DF_BYTE8(D)
109         Likewise the second double-precision floating-point argument.
110
111    MOVE_SF_RET(D, T)
112         Likewise a single-precision floating-point return value,
113         then jump to T.
114
115    MOVE_SC_RET(D, T)
116         Likewise a complex single-precision floating-point return value.
117
118    MOVE_DF_RET(D, T)
119         Likewise a double-precision floating-point return value.
120
121    MOVE_DC_RET(D, T)
122         Likewise a complex double-precision floating-point return value.
123
124    MOVE_SI_RET(D, T)
125         Likewise a single-precision integer return value.
126
127    The D argument is "t" to move to FPRs and "f" to move from FPRs.
128    The return macros may assume that the target of the jump does not
129    use a floating-point register.  */
130
131 #define MOVE_SF_RET(D, T) DELAY##D (T, m##D##c1 $2,$f0)
132 #define MOVE_SI_RET(D, T) DELAY##D (T, m##D##c1 $2,$f0)
133
134 #if defined(__mips64) && defined(__MIPSEB__)
135 #define MOVE_SC_RET(D, T) MERGE_GPR##D ($2, $f0, $f1); jr T
136 #elif defined(__mips64)
137 /* The high 32 bits of $2 correspond to the second word in memory;
138    i.e. the imaginary part.  */
139 #define MOVE_SC_RET(D, T) MERGE_GPR##D ($2, $f1, $f0); jr T
140 #elif __mips_fpr == 64
141 #define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f1)
142 #else
143 #define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f2)
144 #endif
145
146 #if defined(__mips64)
147 #define MOVE_SF_BYTE0(D) m##D##c1 $4,$f12
148 #define MOVE_SF_BYTE4(D) m##D##c1 $5,$f13
149 #define MOVE_SF_BYTE8(D) m##D##c1 $5,$f13
150 #else
151 #define MOVE_SF_BYTE0(D) m##D##c1 $4,$f12
152 #define MOVE_SF_BYTE4(D) m##D##c1 $5,$f14
153 #define MOVE_SF_BYTE8(D) m##D##c1 $6,$f14
154 #endif
155 #define MOVE_SI_BYTE0(D) MOVE_SF_BYTE0(D)
156
157 #if defined(__mips64)
158 #define MOVE_DF_BYTE0(D) dm##D##c1 $4,$f12
159 #define MOVE_DF_BYTE8(D) dm##D##c1 $5,$f13
160 #define MOVE_DF_RET(D, T) DELAY##D (T, dm##D##c1 $2,$f0)
161 #define MOVE_DC_RET(D, T) dm##D##c1 $3,$f1; MOVE_DF_RET (D, T)
162 #elif __mips_fpr == 64 && defined(__MIPSEB__)
163 #define MOVE_DF_BYTE0(D) m##D##c1 $5,$f12; m##D##hc1 $4,$f12
164 #define MOVE_DF_BYTE8(D) m##D##c1 $7,$f14; m##D##hc1 $6,$f14
165 #define MOVE_DF_RET(D, T) m##D##c1 $3,$f0; DELAY##D (T, m##D##hc1 $2,$f0)
166 #define MOVE_DC_RET(D, T) m##D##c1 $5,$f1; m##D##hc1 $4,$f1; MOVE_DF_RET (D, T)
167 #elif __mips_fpr == 64
168 #define MOVE_DF_BYTE0(D) m##D##c1 $4,$f12; m##D##hc1 $5,$f12
169 #define MOVE_DF_BYTE8(D) m##D##c1 $6,$f14; m##D##hc1 $7,$f14
170 #define MOVE_DF_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##hc1 $3,$f0)
171 #define MOVE_DC_RET(D, T) m##D##c1 $4,$f1; m##D##hc1 $5,$f1; MOVE_DF_RET (D, T)
172 #elif defined(__MIPSEB__)
173 /* FPRs are little-endian.  */
174 #define MOVE_DF_BYTE0(D) m##D##c1 $4,$f13; m##D##c1 $5,$f12
175 #define MOVE_DF_BYTE8(D) m##D##c1 $6,$f15; m##D##c1 $7,$f14
176 #define MOVE_DF_RET(D, T) m##D##c1 $2,$f1; DELAY##D (T, m##D##c1 $3,$f0)
177 #define MOVE_DC_RET(D, T) m##D##c1 $4,$f3; m##D##c1 $5,$f2; MOVE_DF_RET (D, T)
178 #else
179 #define MOVE_DF_BYTE0(D) m##D##c1 $4,$f12; m##D##c1 $5,$f13
180 #define MOVE_DF_BYTE8(D) m##D##c1 $6,$f14; m##D##c1 $7,$f15
181 #define MOVE_DF_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f1)
182 #define MOVE_DC_RET(D, T) m##D##c1 $4,$f2; m##D##c1 $5,$f3; MOVE_DF_RET (D, T)
183 #endif
184
185 /* Single-precision math.  */
186
187 /* Define a function NAME that loads two single-precision values,
188    performs FPU operation OPCODE on them, and returns the single-
189    precision result.  */
190
191 #define OPSF3(NAME, OPCODE)     \
192 STARTFN (NAME);                 \
193         MOVE_SF_BYTE0 (t);      \
194         MOVE_SF_BYTE4 (t);      \
195         OPCODE  RET,ARG1,ARG2;  \
196         MOVE_SF_RET (f, $31);   \
197         ENDFN (NAME)
198
199 #ifdef L_m16addsf3
200 OPSF3 (__mips16_addsf3, add.s)
201 #endif
202 #ifdef L_m16subsf3
203 OPSF3 (__mips16_subsf3, sub.s)
204 #endif
205 #ifdef L_m16mulsf3
206 OPSF3 (__mips16_mulsf3, mul.s)
207 #endif
208 #ifdef L_m16divsf3
209 OPSF3 (__mips16_divsf3, div.s)
210 #endif
211
212 /* Define a function NAME that loads a single-precision value,
213    performs FPU operation OPCODE on it, and returns the single-
214    precision result.  */
215
216 #define OPSF2(NAME, OPCODE)     \
217 STARTFN (NAME);                 \
218         MOVE_SF_BYTE0 (t);      \
219         OPCODE  RET,ARG1;       \
220         MOVE_SF_RET (f, $31);   \
221         ENDFN (NAME)
222
223 #ifdef L_m16negsf2
224 OPSF2 (__mips16_negsf2, neg.s)
225 #endif
226 #ifdef L_m16abssf2
227 OPSF2 (__mips16_abssf2, abs.s)
228 #endif
229
230 /* Single-precision comparisons.  */
231
232 /* Define a function NAME that loads two single-precision values,
233    performs floating point comparison OPCODE, and returns TRUE or
234    FALSE depending on the result.  */
235
236 #define CMPSF(NAME, OPCODE, TRUE, FALSE)        \
237 STARTFN (NAME);                                 \
238         MOVE_SF_BYTE0 (t);                      \
239         MOVE_SF_BYTE4 (t);                      \
240         OPCODE  ARG1,ARG2;                      \
241         li      $2,TRUE;                        \
242         bc1t    1f;                             \
243         li      $2,FALSE;                       \
244 1:;                                             \
245         j       $31;                            \
246         ENDFN (NAME)
247
248 /* Like CMPSF, but reverse the comparison operands.  */
249
250 #define REVCMPSF(NAME, OPCODE, TRUE, FALSE)     \
251 STARTFN (NAME);                                 \
252         MOVE_SF_BYTE0 (t);                      \
253         MOVE_SF_BYTE4 (t);                      \
254         OPCODE  ARG2,ARG1;                      \
255         li      $2,TRUE;                        \
256         bc1t    1f;                             \
257         li      $2,FALSE;                       \
258 1:;                                             \
259         j       $31;                            \
260         ENDFN (NAME)
261
262 #ifdef L_m16eqsf2
263 CMPSF (__mips16_eqsf2, c.eq.s, 0, 1)
264 #endif
265 #ifdef L_m16nesf2
266 CMPSF (__mips16_nesf2, c.eq.s, 0, 1)
267 #endif
268 #ifdef L_m16gtsf2
269 REVCMPSF (__mips16_gtsf2, c.lt.s, 1, 0)
270 #endif
271 #ifdef L_m16gesf2
272 REVCMPSF (__mips16_gesf2, c.le.s, 0, -1)
273 #endif
274 #ifdef L_m16lesf2
275 CMPSF (__mips16_lesf2, c.le.s, 0, 1)
276 #endif
277 #ifdef L_m16ltsf2
278 CMPSF (__mips16_ltsf2, c.lt.s, -1, 0)
279 #endif
280 #ifdef L_m16unordsf2
281 CMPSF(__mips16_unordsf2, c.un.s, 1, 0)
282 #endif
283
284
285 /* Single-precision conversions.  */
286
287 #ifdef L_m16fltsisf
288 STARTFN (__mips16_floatsisf)
289         MOVE_SF_BYTE0 (t)
290         cvt.s.w RET,ARG1
291         MOVE_SF_RET (f, $31)
292         ENDFN (__mips16_floatsisf)
293 #endif
294
295 #ifdef L_m16fltunsisf
296 STARTFN (__mips16_floatunsisf)
297         .set    noreorder
298         bltz    $4,1f
299         MOVE_SF_BYTE0 (t)
300         .set    reorder
301         cvt.s.w RET,ARG1
302         MOVE_SF_RET (f, $31)
303 1:              
304         and     $2,$4,1
305         srl     $3,$4,1
306         or      $2,$2,$3
307         mtc1    $2,RET
308         cvt.s.w RET,RET
309         add.s   RET,RET,RET
310         MOVE_SF_RET (f, $31)
311         ENDFN (__mips16_floatunsisf)
312 #endif
313         
314 #ifdef L_m16fix_truncsfsi
315 STARTFN (__mips16_fix_truncsfsi)
316         MOVE_SF_BYTE0 (t)
317         trunc.w.s RET,ARG1,$4
318         MOVE_SI_RET (f, $31)
319         ENDFN (__mips16_fix_truncsfsi)
320 #endif
321
322 #if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
323
324 /* Double-precision math.  */
325
326 /* Define a function NAME that loads two double-precision values,
327    performs FPU operation OPCODE on them, and returns the double-
328    precision result.  */
329
330 #define OPDF3(NAME, OPCODE)     \
331 STARTFN (NAME);                 \
332         MOVE_DF_BYTE0 (t);      \
333         MOVE_DF_BYTE8 (t);      \
334         OPCODE RET,ARG1,ARG2;   \
335         MOVE_DF_RET (f, $31);   \
336         ENDFN (NAME)
337
338 #ifdef L_m16adddf3
339 OPDF3 (__mips16_adddf3, add.d)
340 #endif
341 #ifdef L_m16subdf3
342 OPDF3 (__mips16_subdf3, sub.d)
343 #endif
344 #ifdef L_m16muldf3
345 OPDF3 (__mips16_muldf3, mul.d)
346 #endif
347 #ifdef L_m16divdf3
348 OPDF3 (__mips16_divdf3, div.d)
349 #endif
350
351 /* Define a function NAME that loads a double-precision value,
352    performs FPU operation OPCODE on it, and returns the double-
353    precision result.  */
354
355 #define OPDF2(NAME, OPCODE)     \
356 STARTFN (NAME);                 \
357         MOVE_DF_BYTE0 (t);      \
358         OPCODE RET,ARG1;        \
359         MOVE_DF_RET (f, $31);   \
360         ENDFN (NAME)
361
362 #ifdef L_m16negdf2
363 OPDF2 (__mips16_negdf2, neg.d)
364 #endif
365 #ifdef L_m16absdf2
366 OPDF2 (__mips16_absdf2, abs.d)
367 #endif
368
369 /* Conversions between single and double precision.  */
370
371 #ifdef L_m16extsfdf2
372 STARTFN (__mips16_extendsfdf2)
373         MOVE_SF_BYTE0 (t)
374         cvt.d.s RET,ARG1
375         MOVE_DF_RET (f, $31)
376         ENDFN (__mips16_extendsfdf2)
377 #endif
378
379 #ifdef L_m16trdfsf2
380 STARTFN (__mips16_truncdfsf2)
381         MOVE_DF_BYTE0 (t)
382         cvt.s.d RET,ARG1
383         MOVE_SF_RET (f, $31)
384         ENDFN (__mips16_truncdfsf2)
385 #endif
386
387 /* Double-precision comparisons.  */
388
389 /* Define a function NAME that loads two double-precision values,
390    performs floating point comparison OPCODE, and returns TRUE or
391    FALSE depending on the result.  */
392
393 #define CMPDF(NAME, OPCODE, TRUE, FALSE)        \
394 STARTFN (NAME);                                 \
395         MOVE_DF_BYTE0 (t);                      \
396         MOVE_DF_BYTE8 (t);                      \
397         OPCODE  ARG1,ARG2;                      \
398         li      $2,TRUE;                        \
399         bc1t    1f;                             \
400         li      $2,FALSE;                       \
401 1:;                                             \
402         j       $31;                            \
403         ENDFN (NAME)
404
405 /* Like CMPDF, but reverse the comparison operands.  */
406
407 #define REVCMPDF(NAME, OPCODE, TRUE, FALSE)     \
408 STARTFN (NAME);                                 \
409         MOVE_DF_BYTE0 (t);                      \
410         MOVE_DF_BYTE8 (t);                      \
411         OPCODE  ARG2,ARG1;                      \
412         li      $2,TRUE;                        \
413         bc1t    1f;                             \
414         li      $2,FALSE;                       \
415 1:;                                             \
416         j       $31;                            \
417         ENDFN (NAME)
418
419 #ifdef L_m16eqdf2
420 CMPDF (__mips16_eqdf2, c.eq.d, 0, 1)
421 #endif
422 #ifdef L_m16nedf2
423 CMPDF (__mips16_nedf2, c.eq.d, 0, 1)
424 #endif
425 #ifdef L_m16gtdf2
426 REVCMPDF (__mips16_gtdf2, c.lt.d, 1, 0)
427 #endif
428 #ifdef L_m16gedf2
429 REVCMPDF (__mips16_gedf2, c.le.d, 0, -1)
430 #endif
431 #ifdef L_m16ledf2
432 CMPDF (__mips16_ledf2, c.le.d, 0, 1)
433 #endif
434 #ifdef L_m16ltdf2
435 CMPDF (__mips16_ltdf2, c.lt.d, -1, 0)
436 #endif
437 #ifdef L_m16unorddf2
438 CMPDF(__mips16_unorddf2, c.un.d, 1, 0)
439 #endif
440
441 /* Double-precision conversions.  */
442
443 #ifdef L_m16fltsidf
444 STARTFN (__mips16_floatsidf)
445         MOVE_SI_BYTE0 (t)
446         cvt.d.w RET,ARG1
447         MOVE_DF_RET (f, $31)
448         ENDFN (__mips16_floatsidf)
449 #endif
450         
451 #ifdef L_m16fltunsidf
452 STARTFN (__mips16_floatunsidf)
453         MOVE_SI_BYTE0 (t)
454         cvt.d.w RET,ARG1
455         bgez    $4,1f
456         li.d    ARG1, 4.294967296e+9
457         add.d   RET, RET, ARG1
458 1:      MOVE_DF_RET (f, $31)
459         ENDFN (__mips16_floatunsidf)
460 #endif
461         
462 #ifdef L_m16fix_truncdfsi
463 STARTFN (__mips16_fix_truncdfsi)
464         MOVE_DF_BYTE0 (t)
465         trunc.w.d RET,ARG1,$4
466         MOVE_SI_RET (f, $31)
467         ENDFN (__mips16_fix_truncdfsi)
468 #endif
469 #endif /* !__mips_single_float */
470
471 /* Define a function NAME that moves a return value of mode MODE from
472    FPRs to GPRs.  */
473
474 #define RET_FUNCTION(NAME, MODE)        \
475 STARTFN (NAME);                         \
476         MOVE_##MODE##_RET (t, $31);     \
477         ENDFN (NAME)
478
479 #ifdef L_m16retsf
480 RET_FUNCTION (__mips16_ret_sf, SF)
481 #endif
482
483 #ifdef L_m16retsc
484 RET_FUNCTION (__mips16_ret_sc, SC)
485 #endif
486
487 #if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
488 #ifdef L_m16retdf
489 RET_FUNCTION (__mips16_ret_df, DF)
490 #endif
491
492 #ifdef L_m16retdc
493 RET_FUNCTION (__mips16_ret_dc, DC)
494 #endif
495 #endif /* !__mips_single_float */
496
497 /* STUB_ARGS_X copies the arguments from GPRs to FPRs for argument
498    code X.  X is calculated as ARG1 + ARG2 * 4, where ARG1 and ARG2
499    classify the first and second arguments as follows:
500
501         1: a single-precision argument
502         2: a double-precision argument
503         0: no argument, or not one of the above.  */
504
505 #define STUB_ARGS_0                                             /* () */
506 #define STUB_ARGS_1 MOVE_SF_BYTE0 (t)                           /* (sf) */
507 #define STUB_ARGS_5 MOVE_SF_BYTE0 (t); MOVE_SF_BYTE4 (t)        /* (sf, sf) */
508 #define STUB_ARGS_9 MOVE_SF_BYTE0 (t); MOVE_DF_BYTE8 (t)        /* (sf, df) */
509 #define STUB_ARGS_2 MOVE_DF_BYTE0 (t)                           /* (df) */
510 #define STUB_ARGS_6 MOVE_DF_BYTE0 (t); MOVE_SF_BYTE8 (t)        /* (df, sf) */
511 #define STUB_ARGS_10 MOVE_DF_BYTE0 (t); MOVE_DF_BYTE8 (t)       /* (df, df) */
512
513 /* These functions are used by 16-bit code when calling via a function
514    pointer.  They must copy the floating point arguments from the GPRs
515    to FPRs and then call function $2.  */
516
517 #define CALL_STUB_NO_RET(NAME, CODE)    \
518 STARTFN (NAME);                         \
519         STUB_ARGS_##CODE;               \
520         .set    noreorder;              \
521         jr      $2;                     \
522         move    $25,$2;                 \
523         .set    reorder;                \
524         ENDFN (NAME)
525
526 #ifdef L_m16stub1
527 CALL_STUB_NO_RET (__mips16_call_stub_1, 1)
528 #endif
529
530 #ifdef L_m16stub5
531 CALL_STUB_NO_RET (__mips16_call_stub_5, 5)
532 #endif
533
534 #if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
535
536 #ifdef L_m16stub2
537 CALL_STUB_NO_RET (__mips16_call_stub_2, 2)
538 #endif
539
540 #ifdef L_m16stub6
541 CALL_STUB_NO_RET (__mips16_call_stub_6, 6)
542 #endif
543
544 #ifdef L_m16stub9
545 CALL_STUB_NO_RET (__mips16_call_stub_9, 9)
546 #endif
547
548 #ifdef L_m16stub10
549 CALL_STUB_NO_RET (__mips16_call_stub_10, 10)
550 #endif
551 #endif /* !__mips_single_float */
552
553 /* Now we have the same set of functions, except that this time the
554    function being called returns an SFmode, SCmode, DFmode or DCmode
555    value; we need to instantiate a set for each case.  The calling
556    function will arrange to preserve $18, so these functions are free
557    to use it to hold the return address.
558
559    Note that we do not know whether the function we are calling is 16
560    bit or 32 bit.  However, it does not matter, because 16-bit
561    functions always return floating point values in both the gp and
562    the fp regs.  It would be possible to check whether the function
563    being called is 16 bits, in which case the copy is unnecessary;
564    however, it's faster to always do the copy.  */
565
566 #define CALL_STUB_RET(NAME, CODE, MODE) \
567 STARTFN (NAME);                         \
568         move    $18,$31;                \
569         STUB_ARGS_##CODE;               \
570         .set    noreorder;              \
571         jalr    $2;                     \
572         move    $25,$2;                 \
573         .set    reorder;                \
574         MOVE_##MODE##_RET (f, $18);     \
575         ENDFN (NAME)
576
577 /* First, instantiate the single-float set.  */
578
579 #ifdef L_m16stubsf0
580 CALL_STUB_RET (__mips16_call_stub_sf_0, 0, SF)
581 #endif
582
583 #ifdef L_m16stubsf1
584 CALL_STUB_RET (__mips16_call_stub_sf_1, 1, SF)
585 #endif
586
587 #ifdef L_m16stubsf5
588 CALL_STUB_RET (__mips16_call_stub_sf_5, 5, SF)
589 #endif
590
591 #if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
592 #ifdef L_m16stubsf2
593 CALL_STUB_RET (__mips16_call_stub_sf_2, 2, SF)
594 #endif
595
596 #ifdef L_m16stubsf6
597 CALL_STUB_RET (__mips16_call_stub_sf_6, 6, SF)
598 #endif
599
600 #ifdef L_m16stubsf9
601 CALL_STUB_RET (__mips16_call_stub_sf_9, 9, SF)
602 #endif
603
604 #ifdef L_m16stubsf10
605 CALL_STUB_RET (__mips16_call_stub_sf_10, 10, SF)
606 #endif
607 #endif /* !__mips_single_float */
608
609
610 /* Now we have the same set of functions again, except that this time
611    the function being called returns an DFmode value.  */
612
613 #if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
614 #ifdef L_m16stubdf0
615 CALL_STUB_RET (__mips16_call_stub_df_0, 0, DF)
616 #endif
617
618 #ifdef L_m16stubdf1
619 CALL_STUB_RET (__mips16_call_stub_df_1, 1, DF)
620 #endif
621
622 #ifdef L_m16stubdf5
623 CALL_STUB_RET (__mips16_call_stub_df_5, 5, DF)
624 #endif
625
626 #ifdef L_m16stubdf2
627 CALL_STUB_RET (__mips16_call_stub_df_2, 2, DF)
628 #endif
629
630 #ifdef L_m16stubdf6
631 CALL_STUB_RET (__mips16_call_stub_df_6, 6, DF)
632 #endif
633
634 #ifdef L_m16stubdf9
635 CALL_STUB_RET (__mips16_call_stub_df_9, 9, DF)
636 #endif
637
638 #ifdef L_m16stubdf10
639 CALL_STUB_RET (__mips16_call_stub_df_10, 10, DF)
640 #endif
641 #endif /* !__mips_single_float */
642
643
644 /* Ho hum.  Here we have the same set of functions again, this time
645    for when the function being called returns an SCmode value.  */
646
647 #ifdef L_m16stubsc0
648 CALL_STUB_RET (__mips16_call_stub_sc_0, 0, SC)
649 #endif
650
651 #ifdef L_m16stubsc1
652 CALL_STUB_RET (__mips16_call_stub_sc_1, 1, SC)
653 #endif
654
655 #ifdef L_m16stubsc5
656 CALL_STUB_RET (__mips16_call_stub_sc_5, 5, SC)
657 #endif
658
659 #if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
660 #ifdef L_m16stubsc2
661 CALL_STUB_RET (__mips16_call_stub_sc_2, 2, SC)
662 #endif
663
664 #ifdef L_m16stubsc6
665 CALL_STUB_RET (__mips16_call_stub_sc_6, 6, SC)
666 #endif
667
668 #ifdef L_m16stubsc9
669 CALL_STUB_RET (__mips16_call_stub_sc_9, 9, SC)
670 #endif
671
672 #ifdef L_m16stubsc10
673 CALL_STUB_RET (__mips16_call_stub_sc_10, 10, SC)
674 #endif
675 #endif /* !__mips_single_float */
676
677
678 /* Finally, another set of functions for DCmode.  */
679
680 #if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
681 #ifdef L_m16stubdc0
682 CALL_STUB_RET (__mips16_call_stub_dc_0, 0, DC)
683 #endif
684
685 #ifdef L_m16stubdc1
686 CALL_STUB_RET (__mips16_call_stub_dc_1, 1, DC)
687 #endif
688
689 #ifdef L_m16stubdc5
690 CALL_STUB_RET (__mips16_call_stub_dc_5, 5, DC)
691 #endif
692
693 #ifdef L_m16stubdc2
694 CALL_STUB_RET (__mips16_call_stub_dc_2, 2, DC)
695 #endif
696
697 #ifdef L_m16stubdc6
698 CALL_STUB_RET (__mips16_call_stub_dc_6, 6, DC)
699 #endif
700
701 #ifdef L_m16stubdc9
702 CALL_STUB_RET (__mips16_call_stub_dc_9, 9, DC)
703 #endif
704
705 #ifdef L_m16stubdc10
706 CALL_STUB_RET (__mips16_call_stub_dc_10, 10, DC)
707 #endif
708 #endif /* !__mips_single_float */
709 #endif