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