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