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