1/* mips16 floating point support code 2 Copyright (C) 1996-2013 Free Software Foundation, Inc. 3 Contributed by Cygnus Support 4 5This file is free software; you can redistribute it and/or modify it 6under the terms of the GNU General Public License as published by the 7Free Software Foundation; either version 3, or (at your option) any 8later version. 9 10This file is distributed in the hope that it will be useful, but 11WITHOUT ANY WARRANTY; without even the implied warranty of 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13General Public License for more details. 14 15Under Section 7 of GPL version 3, you are granted additional 16permissions described in the GCC Runtime Library Exception, version 173.1, as published by the Free Software Foundation. 18 19You should have received a copy of the GNU General Public License and 20a copy of the GCC Runtime Library Exception along with this program; 21see 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) \ 194STARTFN (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 202OPSF3 (__mips16_addsf3, add.s) 203#endif 204#ifdef L_m16subsf3 205OPSF3 (__mips16_subsf3, sub.s) 206#endif 207#ifdef L_m16mulsf3 208OPSF3 (__mips16_mulsf3, mul.s) 209#endif 210#ifdef L_m16divsf3 211OPSF3 (__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) \ 219STARTFN (NAME); \ 220 MOVE_SF_BYTE0 (t); \ 221 OPCODE RET,ARG1; \ 222 MOVE_SF_RET (f, $31); \ 223 ENDFN (NAME) 224 225#ifdef L_m16negsf2 226OPSF2 (__mips16_negsf2, neg.s) 227#endif 228#ifdef L_m16abssf2 229OPSF2 (__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) \ 239STARTFN (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; \ 2461:; \ 247 j $31; \ 248 ENDFN (NAME) 249 250/* Like CMPSF, but reverse the comparison operands. */ 251 252#define REVCMPSF(NAME, OPCODE, TRUE, FALSE) \ 253STARTFN (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; \ 2601:; \ 261 j $31; \ 262 ENDFN (NAME) 263 264#ifdef L_m16eqsf2 265CMPSF (__mips16_eqsf2, c.eq.s, 0, 1) 266#endif 267#ifdef L_m16nesf2 268CMPSF (__mips16_nesf2, c.eq.s, 0, 1) 269#endif 270#ifdef L_m16gtsf2 271REVCMPSF (__mips16_gtsf2, c.lt.s, 1, 0) 272#endif 273#ifdef L_m16gesf2 274REVCMPSF (__mips16_gesf2, c.le.s, 0, -1) 275#endif 276#ifdef L_m16lesf2 277CMPSF (__mips16_lesf2, c.le.s, 0, 1) 278#endif 279#ifdef L_m16ltsf2 280CMPSF (__mips16_ltsf2, c.lt.s, -1, 0) 281#endif 282#ifdef L_m16unordsf2 283CMPSF(__mips16_unordsf2, c.un.s, 1, 0) 284#endif 285 286 287/* Single-precision conversions. */ 288 289#ifdef L_m16fltsisf 290STARTFN (__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 298STARTFN (__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) 3051: 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 317STARTFN (__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) \ 333STARTFN (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 341OPDF3 (__mips16_adddf3, add.d) 342#endif 343#ifdef L_m16subdf3 344OPDF3 (__mips16_subdf3, sub.d) 345#endif 346#ifdef L_m16muldf3 347OPDF3 (__mips16_muldf3, mul.d) 348#endif 349#ifdef L_m16divdf3 350OPDF3 (__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) \ 358STARTFN (NAME); \ 359 MOVE_DF_BYTE0 (t); \ 360 OPCODE RET,ARG1; \ 361 MOVE_DF_RET (f, $31); \ 362 ENDFN (NAME) 363 364#ifdef L_m16negdf2 365OPDF2 (__mips16_negdf2, neg.d) 366#endif 367#ifdef L_m16absdf2 368OPDF2 (__mips16_absdf2, abs.d) 369#endif 370 371/* Conversions between single and double precision. */ 372 373#ifdef L_m16extsfdf2 374STARTFN (__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 382STARTFN (__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) \ 396STARTFN (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; \ 4031:; \ 404 j $31; \ 405 ENDFN (NAME) 406 407/* Like CMPDF, but reverse the comparison operands. */ 408 409#define REVCMPDF(NAME, OPCODE, TRUE, FALSE) \ 410STARTFN (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; \ 4171:; \ 418 j $31; \ 419 ENDFN (NAME) 420 421#ifdef L_m16eqdf2 422CMPDF (__mips16_eqdf2, c.eq.d, 0, 1) 423#endif 424#ifdef L_m16nedf2 425CMPDF (__mips16_nedf2, c.eq.d, 0, 1) 426#endif 427#ifdef L_m16gtdf2 428REVCMPDF (__mips16_gtdf2, c.lt.d, 1, 0) 429#endif 430#ifdef L_m16gedf2 431REVCMPDF (__mips16_gedf2, c.le.d, 0, -1) 432#endif 433#ifdef L_m16ledf2 434CMPDF (__mips16_ledf2, c.le.d, 0, 1) 435#endif 436#ifdef L_m16ltdf2 437CMPDF (__mips16_ltdf2, c.lt.d, -1, 0) 438#endif 439#ifdef L_m16unorddf2 440CMPDF(__mips16_unorddf2, c.un.d, 1, 0) 441#endif 442 443/* Double-precision conversions. */ 444 445#ifdef L_m16fltsidf 446STARTFN (__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 454STARTFN (__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 4601: MOVE_DF_RET (f, $31) 461 ENDFN (__mips16_floatunsidf) 462#endif 463 464#ifdef L_m16fix_truncdfsi 465STARTFN (__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) \ 477STARTFN (NAME); \ 478 MOVE_##MODE##_RET (t, $31); \ 479 ENDFN (NAME) 480 481#ifdef L_m16retsf 482RET_FUNCTION (__mips16_ret_sf, SF) 483#endif 484 485#ifdef L_m16retsc 486RET_FUNCTION (__mips16_ret_sc, SC) 487#endif 488 489#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) 490#ifdef L_m16retdf 491RET_FUNCTION (__mips16_ret_df, DF) 492#endif 493 494#ifdef L_m16retdc 495RET_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) \ 520STARTFN (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 529CALL_STUB_NO_RET (__mips16_call_stub_1, 1) 530#endif 531 532#ifdef L_m16stub5 533CALL_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 539CALL_STUB_NO_RET (__mips16_call_stub_2, 2) 540#endif 541 542#ifdef L_m16stub6 543CALL_STUB_NO_RET (__mips16_call_stub_6, 6) 544#endif 545 546#ifdef L_m16stub9 547CALL_STUB_NO_RET (__mips16_call_stub_9, 9) 548#endif 549 550#ifdef L_m16stub10 551CALL_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) \ 569STARTFN (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 590CALL_STUB_RET (__mips16_call_stub_sf_0, 0, SF) 591#endif 592 593#ifdef L_m16stubsf1 594CALL_STUB_RET (__mips16_call_stub_sf_1, 1, SF) 595#endif 596 597#ifdef L_m16stubsf5 598CALL_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 603CALL_STUB_RET (__mips16_call_stub_sf_2, 2, SF) 604#endif 605 606#ifdef L_m16stubsf6 607CALL_STUB_RET (__mips16_call_stub_sf_6, 6, SF) 608#endif 609 610#ifdef L_m16stubsf9 611CALL_STUB_RET (__mips16_call_stub_sf_9, 9, SF) 612#endif 613 614#ifdef L_m16stubsf10 615CALL_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 625CALL_STUB_RET (__mips16_call_stub_df_0, 0, DF) 626#endif 627 628#ifdef L_m16stubdf1 629CALL_STUB_RET (__mips16_call_stub_df_1, 1, DF) 630#endif 631 632#ifdef L_m16stubdf5 633CALL_STUB_RET (__mips16_call_stub_df_5, 5, DF) 634#endif 635 636#ifdef L_m16stubdf2 637CALL_STUB_RET (__mips16_call_stub_df_2, 2, DF) 638#endif 639 640#ifdef L_m16stubdf6 641CALL_STUB_RET (__mips16_call_stub_df_6, 6, DF) 642#endif 643 644#ifdef L_m16stubdf9 645CALL_STUB_RET (__mips16_call_stub_df_9, 9, DF) 646#endif 647 648#ifdef L_m16stubdf10 649CALL_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 658CALL_STUB_RET (__mips16_call_stub_sc_0, 0, SC) 659#endif 660 661#ifdef L_m16stubsc1 662CALL_STUB_RET (__mips16_call_stub_sc_1, 1, SC) 663#endif 664 665#ifdef L_m16stubsc5 666CALL_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 671CALL_STUB_RET (__mips16_call_stub_sc_2, 2, SC) 672#endif 673 674#ifdef L_m16stubsc6 675CALL_STUB_RET (__mips16_call_stub_sc_6, 6, SC) 676#endif 677 678#ifdef L_m16stubsc9 679CALL_STUB_RET (__mips16_call_stub_sc_9, 9, SC) 680#endif 681 682#ifdef L_m16stubsc10 683CALL_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 692CALL_STUB_RET (__mips16_call_stub_dc_0, 0, DC) 693#endif 694 695#ifdef L_m16stubdc1 696CALL_STUB_RET (__mips16_call_stub_dc_1, 1, DC) 697#endif 698 699#ifdef L_m16stubdc5 700CALL_STUB_RET (__mips16_call_stub_dc_5, 5, DC) 701#endif 702 703#ifdef L_m16stubdc2 704CALL_STUB_RET (__mips16_call_stub_dc_2, 2, DC) 705#endif 706 707#ifdef L_m16stubdc6 708CALL_STUB_RET (__mips16_call_stub_dc_6, 6, DC) 709#endif 710 711#ifdef L_m16stubdc9 712CALL_STUB_RET (__mips16_call_stub_dc_9, 9, DC) 713#endif 714 715#ifdef L_m16stubdc10 716CALL_STUB_RET (__mips16_call_stub_dc_10, 10, DC) 717#endif 718#endif /* !__mips_single_float */ 719 720#endif 721