1169689Skan/* mips16 floating point support code 2169689Skan Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. 3169689Skan Contributed by Cygnus Support 4169689Skan 5169689SkanThis file is free software; you can redistribute it and/or modify it 6169689Skanunder the terms of the GNU General Public License as published by the 7169689SkanFree Software Foundation; either version 2, or (at your option) any 8169689Skanlater version. 9169689Skan 10169689SkanIn addition to the permissions in the GNU General Public License, the 11169689SkanFree Software Foundation gives you unlimited permission to link the 12169689Skancompiled version of this file with other programs, and to distribute 13169689Skanthose programs without any restriction coming from the use of this 14169689Skanfile. (The General Public License restrictions do apply in other 15169689Skanrespects; for example, they cover modification of the file, and 16169689Skandistribution when not linked into another program.) 17169689Skan 18169689SkanThis file is distributed in the hope that it will be useful, but 19169689SkanWITHOUT ANY WARRANTY; without even the implied warranty of 20169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21169689SkanGeneral Public License for more details. 22169689Skan 23169689SkanYou should have received a copy of the GNU General Public License 24169689Skanalong with this program; see the file COPYING. If not, write to 25169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 26169689SkanBoston, MA 02110-1301, USA. */ 27169689Skan 28169689Skan/* As a special exception, if you link this library with other files, 29169689Skan some of which are compiled with GCC, to produce an executable, 30169689Skan this library does not by itself cause the resulting executable 31169689Skan to be covered by the GNU General Public License. 32169689Skan This exception does not however invalidate any other reasons why 33169689Skan the executable file might be covered by the GNU General Public License. */ 34169689Skan 35169689Skan/* This file contains mips16 floating point support functions. These 36169689Skan functions are called by mips16 code to handle floating point when 37169689Skan -msoft-float is not used. They accept the arguments and return 38169689Skan values using the soft-float calling convention, but do the actual 39169689Skan operation using the hard floating point instructions. */ 40169689Skan 41169689Skan/* This file contains 32 bit assembly code. */ 42169689Skan .set nomips16 43169689Skan 44169689Skan/* Start a function. */ 45169689Skan 46169689Skan#define STARTFN(NAME) .globl NAME; .ent NAME; NAME: 47169689Skan 48169689Skan/* Finish a function. */ 49169689Skan 50169689Skan#define ENDFN(NAME) .end NAME 51169689Skan 52169689Skan/* Single precision math. */ 53169689Skan 54169689Skan/* This macro defines a function which loads two single precision 55169689Skan values, performs an operation, and returns the single precision 56169689Skan result. */ 57169689Skan 58169689Skan#define SFOP(NAME, OPCODE) \ 59169689SkanSTARTFN (NAME); \ 60169689Skan .set noreorder; \ 61169689Skan mtc1 $4,$f0; \ 62169689Skan mtc1 $5,$f2; \ 63169689Skan nop; \ 64169689Skan OPCODE $f0,$f0,$f2; \ 65169689Skan mfc1 $2,$f0; \ 66169689Skan j $31; \ 67169689Skan nop; \ 68169689Skan .set reorder; \ 69169689Skan ENDFN (NAME) 70169689Skan 71169689Skan#ifdef L_m16addsf3 72169689SkanSFOP(__mips16_addsf3, add.s) 73169689Skan#endif 74169689Skan#ifdef L_m16subsf3 75169689SkanSFOP(__mips16_subsf3, sub.s) 76169689Skan#endif 77169689Skan#ifdef L_m16mulsf3 78169689SkanSFOP(__mips16_mulsf3, mul.s) 79169689Skan#endif 80169689Skan#ifdef L_m16divsf3 81169689SkanSFOP(__mips16_divsf3, div.s) 82169689Skan#endif 83169689Skan 84169689Skan#define SFOP2(NAME, OPCODE) \ 85169689SkanSTARTFN (NAME); \ 86169689Skan .set noreorder; \ 87169689Skan mtc1 $4,$f0; \ 88169689Skan nop; \ 89169689Skan OPCODE $f0,$f0; \ 90169689Skan mfc1 $2,$f0; \ 91169689Skan j $31; \ 92169689Skan nop; \ 93169689Skan .set reorder; \ 94169689Skan ENDFN (NAME) 95169689Skan 96169689Skan#ifdef L_m16negsf2 97169689SkanSFOP2(__mips16_negsf2, neg.s) 98169689Skan#endif 99169689Skan#ifdef L_m16abssf2 100169689SkanSFOP2(__mips16_abssf2, abs.s) 101169689Skan#endif 102169689Skan 103169689Skan/* Single precision comparisons. */ 104169689Skan 105169689Skan/* This macro defines a function which loads two single precision 106169689Skan values, performs a floating point comparison, and returns the 107169689Skan specified values according to whether the comparison is true or 108169689Skan false. */ 109169689Skan 110169689Skan#define SFCMP(NAME, OPCODE, TRUE, FALSE) \ 111169689SkanSTARTFN (NAME); \ 112169689Skan mtc1 $4,$f0; \ 113169689Skan mtc1 $5,$f2; \ 114169689Skan OPCODE $f0,$f2; \ 115169689Skan li $2,TRUE; \ 116169689Skan bc1t 1f; \ 117169689Skan li $2,FALSE; \ 118169689Skan1:; \ 119169689Skan j $31; \ 120169689Skan ENDFN (NAME) 121169689Skan 122169689Skan/* This macro is like SFCMP, but it reverses the comparison. */ 123169689Skan 124169689Skan#define SFREVCMP(NAME, OPCODE, TRUE, FALSE) \ 125169689SkanSTARTFN (NAME); \ 126169689Skan mtc1 $4,$f0; \ 127169689Skan mtc1 $5,$f2; \ 128169689Skan OPCODE $f2,$f0; \ 129169689Skan li $2,TRUE; \ 130169689Skan bc1t 1f; \ 131169689Skan li $2,FALSE; \ 132169689Skan1:; \ 133169689Skan j $31; \ 134169689Skan ENDFN (NAME) 135169689Skan 136169689Skan#ifdef L_m16eqsf2 137169689SkanSFCMP(__mips16_eqsf2, c.eq.s, 0, 1) 138169689Skan#endif 139169689Skan#ifdef L_m16nesf2 140169689SkanSFCMP(__mips16_nesf2, c.eq.s, 0, 1) 141169689Skan#endif 142169689Skan#ifdef L_m16gtsf2 143169689SkanSFREVCMP(__mips16_gtsf2, c.lt.s, 1, 0) 144169689Skan#endif 145169689Skan#ifdef L_m16gesf2 146169689SkanSFREVCMP(__mips16_gesf2, c.le.s, 0, -1) 147169689Skan#endif 148169689Skan#ifdef L_m16lesf2 149169689SkanSFCMP(__mips16_lesf2, c.le.s, 0, 1) 150169689Skan#endif 151169689Skan#ifdef L_m16ltsf2 152169689SkanSFCMP(__mips16_ltsf2, c.lt.s, -1, 0) 153169689Skan#endif 154169689Skan 155169689Skan/* Single precision conversions. */ 156169689Skan 157169689Skan#ifdef L_m16fltsisf 158169689SkanSTARTFN (__mips16_floatsisf) 159169689Skan .set noreorder 160169689Skan mtc1 $4,$f0 161169689Skan nop 162169689Skan cvt.s.w $f0,$f0 163169689Skan mfc1 $2,$f0 164169689Skan j $31 165169689Skan nop 166169689Skan .set reorder 167169689Skan ENDFN (__mips16_floatsisf) 168169689Skan#endif 169169689Skan 170169689Skan#ifdef L_m16fix_truncsfsi 171169689SkanSTARTFN (__mips16_fix_truncsfsi) 172169689Skan .set noreorder 173169689Skan mtc1 $4,$f0 174169689Skan nop 175169689Skan trunc.w.s $f0,$f0,$4 176169689Skan mfc1 $2,$f0 177169689Skan j $31 178169689Skan nop 179169689Skan .set reorder 180169689Skan ENDFN (__mips16_fix_truncsfsi) 181169689Skan#endif 182169689Skan 183169689Skan#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) 184169689Skan 185169689Skan/* The double precision operations. We need to use different code 186169689Skan based on the preprocessor symbol __mips64, because the way in which 187169689Skan double precision values will change. Without __mips64, the value 188169689Skan is passed in two 32 bit registers. With __mips64, the value is 189169689Skan passed in a single 64 bit register. */ 190169689Skan 191169689Skan/* Load the first double precision operand. */ 192169689Skan 193169689Skan#if defined(__mips64) 194169689Skan#define LDDBL1 dmtc1 $4,$f12 195169689Skan#elif defined(__mipsfp64) 196169689Skan#define LDDBL1 sw $4,0($29); sw $5,4($29); l.d $f12,0($29) 197169689Skan#elif defined(__MIPSEB__) 198169689Skan#define LDDBL1 mtc1 $4,$f13; mtc1 $5,$f12 199169689Skan#else 200169689Skan#define LDDBL1 mtc1 $4,$f12; mtc1 $5,$f13 201169689Skan#endif 202169689Skan 203169689Skan/* Load the second double precision operand. */ 204169689Skan 205169689Skan#if defined(__mips64) 206169689Skan/* XXX this should be $6 for Algo arg passing model */ 207169689Skan#define LDDBL2 dmtc1 $5,$f14 208169689Skan#elif defined(__mipsfp64) 209169689Skan#define LDDBL2 sw $6,8($29); sw $7,12($29); l.d $f14,8($29) 210169689Skan#elif defined(__MIPSEB__) 211169689Skan#define LDDBL2 mtc1 $6,$f15; mtc1 $7,$f14 212169689Skan#else 213169689Skan#define LDDBL2 mtc1 $6,$f14; mtc1 $7,$f15 214169689Skan#endif 215169689Skan 216169689Skan/* Move the double precision return value to the right place. */ 217169689Skan 218169689Skan#if defined(__mips64) 219169689Skan#define RETDBL dmfc1 $2,$f0 220169689Skan#elif defined(__mipsfp64) 221169689Skan#define RETDBL s.d $f0,0($29); lw $2,0($29); lw $3,4($29) 222169689Skan#elif defined(__MIPSEB__) 223169689Skan#define RETDBL mfc1 $2,$f1; mfc1 $3,$f0 224169689Skan#else 225169689Skan#define RETDBL mfc1 $2,$f0; mfc1 $3,$f1 226169689Skan#endif 227169689Skan 228169689Skan/* Double precision math. */ 229169689Skan 230169689Skan/* This macro defines a function which loads two double precision 231169689Skan values, performs an operation, and returns the double precision 232169689Skan result. */ 233169689Skan 234169689Skan#define DFOP(NAME, OPCODE) \ 235169689SkanSTARTFN (NAME); \ 236169689Skan .set noreorder; \ 237169689Skan LDDBL1; \ 238169689Skan LDDBL2; \ 239169689Skan nop; \ 240169689Skan OPCODE $f0,$f12,$f14; \ 241169689Skan RETDBL; \ 242169689Skan j $31; \ 243169689Skan nop; \ 244169689Skan .set reorder; \ 245169689Skan ENDFN (NAME) 246169689Skan 247169689Skan#ifdef L_m16adddf3 248169689SkanDFOP(__mips16_adddf3, add.d) 249169689Skan#endif 250169689Skan#ifdef L_m16subdf3 251169689SkanDFOP(__mips16_subdf3, sub.d) 252169689Skan#endif 253169689Skan#ifdef L_m16muldf3 254169689SkanDFOP(__mips16_muldf3, mul.d) 255169689Skan#endif 256169689Skan#ifdef L_m16divdf3 257169689SkanDFOP(__mips16_divdf3, div.d) 258169689Skan#endif 259169689Skan 260169689Skan#define DFOP2(NAME, OPCODE) \ 261169689SkanSTARTFN (NAME); \ 262169689Skan .set noreorder; \ 263169689Skan LDDBL1; \ 264169689Skan nop; \ 265169689Skan OPCODE $f0,$f12; \ 266169689Skan RETDBL; \ 267169689Skan j $31; \ 268169689Skan nop; \ 269169689Skan .set reorder; \ 270169689Skan ENDFN (NAME) 271169689Skan 272169689Skan#ifdef L_m16negdf2 273169689SkanDFOP2(__mips16_negdf2, neg.d) 274169689Skan#endif 275169689Skan#ifdef L_m16absdf2 276169689SkanDFOP2(__mips16_absdf2, abs.d) 277169689Skan#endif 278169689Skan 279169689Skan 280169689Skan/* Conversions between single and double precision. */ 281169689Skan 282169689Skan#ifdef L_m16extsfdf2 283169689SkanSTARTFN (__mips16_extendsfdf2) 284169689Skan .set noreorder 285169689Skan mtc1 $4,$f12 286169689Skan nop 287169689Skan cvt.d.s $f0,$f12 288169689Skan RETDBL 289169689Skan j $31 290169689Skan nop 291169689Skan .set reorder 292169689Skan ENDFN (__mips16_extendsfdf2) 293169689Skan#endif 294169689Skan 295169689Skan#ifdef L_m16trdfsf2 296169689SkanSTARTFN (__mips16_truncdfsf2) 297169689Skan .set noreorder 298169689Skan LDDBL1 299169689Skan nop 300169689Skan cvt.s.d $f0,$f12 301169689Skan mfc1 $2,$f0 302169689Skan j $31 303169689Skan nop 304169689Skan .set reorder 305169689Skan ENDFN (__mips16_truncdfsf2) 306169689Skan#endif 307169689Skan 308169689Skan/* Double precision comparisons. */ 309169689Skan 310169689Skan/* This macro defines a function which loads two double precision 311169689Skan values, performs a floating point comparison, and returns the 312169689Skan specified values according to whether the comparison is true or 313169689Skan false. */ 314169689Skan 315169689Skan#define DFCMP(NAME, OPCODE, TRUE, FALSE) \ 316169689SkanSTARTFN (NAME); \ 317169689Skan LDDBL1; \ 318169689Skan LDDBL2; \ 319169689Skan OPCODE $f12,$f14; \ 320169689Skan li $2,TRUE; \ 321169689Skan bc1t 1f; \ 322169689Skan li $2,FALSE; \ 323169689Skan1:; \ 324169689Skan j $31; \ 325169689Skan ENDFN (NAME) 326169689Skan 327169689Skan/* This macro is like DFCMP, but it reverses the comparison. */ 328169689Skan 329169689Skan#define DFREVCMP(NAME, OPCODE, TRUE, FALSE) \ 330169689SkanSTARTFN (NAME); \ 331169689Skan LDDBL1; \ 332169689Skan LDDBL2; \ 333169689Skan OPCODE $f14,$f12; \ 334169689Skan li $2,TRUE; \ 335169689Skan bc1t 1f; \ 336169689Skan li $2,FALSE; \ 337169689Skan1:; \ 338169689Skan j $31; \ 339169689Skan ENDFN (NAME) 340169689Skan 341169689Skan#ifdef L_m16eqdf2 342169689SkanDFCMP(__mips16_eqdf2, c.eq.d, 0, 1) 343169689Skan#endif 344169689Skan#ifdef L_m16nedf2 345169689SkanDFCMP(__mips16_nedf2, c.eq.d, 0, 1) 346169689Skan#endif 347169689Skan#ifdef L_m16gtdf2 348169689SkanDFREVCMP(__mips16_gtdf2, c.lt.d, 1, 0) 349169689Skan#endif 350169689Skan#ifdef L_m16gedf2 351169689SkanDFREVCMP(__mips16_gedf2, c.le.d, 0, -1) 352169689Skan#endif 353169689Skan#ifdef L_m16ledf2 354169689SkanDFCMP(__mips16_ledf2, c.le.d, 0, 1) 355169689Skan#endif 356169689Skan#ifdef L_m16ltdf2 357169689SkanDFCMP(__mips16_ltdf2, c.lt.d, -1, 0) 358169689Skan#endif 359169689Skan 360169689Skan/* Double precision conversions. */ 361169689Skan 362169689Skan#ifdef L_m16fltsidf 363169689SkanSTARTFN (__mips16_floatsidf) 364169689Skan .set noreorder 365169689Skan mtc1 $4,$f12 366169689Skan nop 367169689Skan cvt.d.w $f0,$f12 368169689Skan RETDBL 369169689Skan j $31 370169689Skan nop 371169689Skan .set reorder 372169689Skan ENDFN (__mips16_floatsidf) 373169689Skan#endif 374169689Skan 375169689Skan#ifdef L_m16fix_truncdfsi 376169689SkanSTARTFN (__mips16_fix_truncdfsi) 377169689Skan .set noreorder 378169689Skan LDDBL1 379169689Skan nop 380169689Skan trunc.w.d $f0,$f12,$4 381169689Skan mfc1 $2,$f0 382169689Skan j $31 383169689Skan nop 384169689Skan .set reorder 385169689Skan ENDFN (__mips16_fix_truncdfsi) 386169689Skan#endif 387169689Skan#endif /* !__mips_single_float */ 388169689Skan 389169689Skan/* These functions are used to return floating point values from 390169689Skan mips16 functions. In this case we can put mtc1 in a jump delay slot, 391169689Skan because we know that the next instruction will not refer to a floating 392169689Skan point register. */ 393169689Skan 394169689Skan#ifdef L_m16retsf 395169689SkanSTARTFN (__mips16_ret_sf) 396169689Skan .set noreorder 397169689Skan j $31 398169689Skan mtc1 $2,$f0 399169689Skan .set reorder 400169689Skan ENDFN (__mips16_ret_sf) 401169689Skan#endif 402169689Skan 403169689Skan#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) 404169689Skan#ifdef L_m16retdf 405169689SkanSTARTFN (__mips16_ret_df) 406169689Skan .set noreorder 407169689Skan#if defined(__mips64) 408169689Skan j $31 409169689Skan dmtc1 $2,$f0 410169689Skan#elif defined(__mipsfp64) 411169689Skan sw $2,0($29) 412169689Skan sw $3,4($29) 413169689Skan l.d $f0,0($29) 414169689Skan#elif defined(__MIPSEB__) 415169689Skan mtc1 $2,$f1 416169689Skan j $31 417169689Skan mtc1 $3,$f0 418169689Skan#else 419169689Skan mtc1 $2,$f0 420169689Skan j $31 421169689Skan mtc1 $3,$f1 422169689Skan#endif 423169689Skan .set reorder 424169689Skan ENDFN (__mips16_ret_df) 425169689Skan#endif 426169689Skan#endif /* !__mips_single_float */ 427169689Skan 428169689Skan/* These functions are used by 16 bit code when calling via a function 429169689Skan pointer. They must copy the floating point arguments from the gp 430169689Skan regs into the fp regs. The function to call will be in $2. The 431169689Skan exact set of floating point arguments to copy is encoded in the 432169689Skan function name; the final number is an fp_code, as described in 433169689Skan mips.h in the comment about CUMULATIVE_ARGS. */ 434169689Skan 435169689Skan#ifdef L_m16stub1 436169689Skan/* (float) */ 437169689SkanSTARTFN (__mips16_call_stub_1) 438169689Skan .set noreorder 439169689Skan mtc1 $4,$f12 440169689Skan j $2 441169689Skan nop 442169689Skan .set reorder 443169689Skan ENDFN (__mips16_call_stub_1) 444169689Skan#endif 445169689Skan 446169689Skan#ifdef L_m16stub5 447169689Skan/* (float, float) */ 448169689SkanSTARTFN (__mips16_call_stub_5) 449169689Skan .set noreorder 450169689Skan mtc1 $4,$f12 451169689Skan mtc1 $5,$f14 452169689Skan j $2 453169689Skan nop 454169689Skan .set reorder 455169689Skan ENDFN (__mips16_call_stub_5) 456169689Skan#endif 457169689Skan 458169689Skan#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) 459169689Skan 460169689Skan#ifdef L_m16stub2 461169689Skan/* (double) */ 462169689SkanSTARTFN (__mips16_call_stub_2) 463169689Skan .set noreorder 464169689Skan LDDBL1 465169689Skan j $2 466169689Skan nop 467169689Skan .set reorder 468169689Skan ENDFN (__mips16_call_stub_2) 469169689Skan#endif 470169689Skan 471169689Skan#ifdef L_m16stub6 472169689Skan/* (double, float) */ 473169689SkanSTARTFN (__mips16_call_stub_6) 474169689Skan .set noreorder 475169689Skan LDDBL1 476169689Skan mtc1 $6,$f14 477169689Skan j $2 478169689Skan nop 479169689Skan .set reorder 480169689Skan ENDFN (__mips16_call_stub_6) 481169689Skan#endif 482169689Skan 483169689Skan#ifdef L_m16stub9 484169689Skan/* (float, double) */ 485169689SkanSTARTFN (__mips16_call_stub_9) 486169689Skan .set noreorder 487169689Skan mtc1 $4,$f12 488169689Skan LDDBL2 489169689Skan j $2 490169689Skan nop 491169689Skan .set reorder 492169689Skan ENDFN (__mips16_call_stub_9) 493169689Skan#endif 494169689Skan 495169689Skan#ifdef L_m16stub10 496169689Skan/* (double, double) */ 497169689SkanSTARTFN (__mips16_call_stub_10) 498169689Skan .set noreorder 499169689Skan LDDBL1 500169689Skan LDDBL2 501169689Skan j $2 502169689Skan nop 503169689Skan .set reorder 504169689Skan ENDFN (__mips16_call_stub_10) 505169689Skan#endif 506169689Skan#endif /* !__mips_single_float */ 507169689Skan 508169689Skan/* Now we have the same set of functions, except that this time the 509169689Skan function being called returns an SFmode value. The calling 510169689Skan function will arrange to preserve $18, so these functions are free 511169689Skan to use it to hold the return address. 512169689Skan 513169689Skan Note that we do not know whether the function we are calling is 16 514169689Skan bit or 32 bit. However, it does not matter, because 16 bit 515169689Skan functions always return floating point values in both the gp and 516169689Skan the fp regs. It would be possible to check whether the function 517169689Skan being called is 16 bits, in which case the copy is unnecessary; 518169689Skan however, it's faster to always do the copy. */ 519169689Skan 520169689Skan#ifdef L_m16stubsf0 521169689Skan/* () */ 522169689SkanSTARTFN (__mips16_call_stub_sf_0) 523169689Skan .set noreorder 524169689Skan move $18,$31 525169689Skan jal $2 526169689Skan nop 527169689Skan mfc1 $2,$f0 528169689Skan j $18 529169689Skan nop 530169689Skan .set reorder 531169689Skan ENDFN (__mips16_call_stub_sf_0) 532169689Skan#endif 533169689Skan 534169689Skan#ifdef L_m16stubsf1 535169689Skan/* (float) */ 536169689SkanSTARTFN (__mips16_call_stub_sf_1) 537169689Skan .set noreorder 538169689Skan mtc1 $4,$f12 539169689Skan move $18,$31 540169689Skan jal $2 541169689Skan nop 542169689Skan mfc1 $2,$f0 543169689Skan j $18 544169689Skan nop 545169689Skan .set reorder 546169689Skan ENDFN (__mips16_call_stub_sf_1) 547169689Skan#endif 548169689Skan 549169689Skan#ifdef L_m16stubsf5 550169689Skan/* (float, float) */ 551169689SkanSTARTFN (__mips16_call_stub_sf_5) 552169689Skan .set noreorder 553169689Skan mtc1 $4,$f12 554169689Skan mtc1 $5,$f14 555169689Skan move $18,$31 556169689Skan jal $2 557169689Skan nop 558169689Skan mfc1 $2,$f0 559169689Skan j $18 560169689Skan nop 561169689Skan .set reorder 562169689Skan ENDFN (__mips16_call_stub_sf_5) 563169689Skan#endif 564169689Skan 565169689Skan#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT) 566169689Skan#ifdef L_m16stubsf2 567169689Skan/* (double) */ 568169689SkanSTARTFN (__mips16_call_stub_sf_2) 569169689Skan .set noreorder 570169689Skan LDDBL1 571169689Skan move $18,$31 572169689Skan jal $2 573169689Skan nop 574169689Skan mfc1 $2,$f0 575169689Skan j $18 576169689Skan nop 577169689Skan .set reorder 578169689Skan ENDFN (__mips16_call_stub_sf_2) 579169689Skan#endif 580169689Skan 581169689Skan#ifdef L_m16stubsf6 582169689Skan/* (double, float) */ 583169689SkanSTARTFN (__mips16_call_stub_sf_6) 584169689Skan .set noreorder 585169689Skan LDDBL1 586169689Skan mtc1 $6,$f14 587169689Skan move $18,$31 588169689Skan jal $2 589169689Skan nop 590169689Skan mfc1 $2,$f0 591169689Skan j $18 592169689Skan nop 593169689Skan .set reorder 594169689Skan ENDFN (__mips16_call_stub_sf_6) 595169689Skan#endif 596169689Skan 597169689Skan#ifdef L_m16stubsf9 598169689Skan/* (float, double) */ 599169689SkanSTARTFN (__mips16_call_stub_sf_9) 600169689Skan .set noreorder 601169689Skan mtc1 $4,$f12 602169689Skan LDDBL2 603169689Skan move $18,$31 604169689Skan jal $2 605169689Skan nop 606169689Skan mfc1 $2,$f0 607169689Skan j $18 608169689Skan nop 609169689Skan .set reorder 610169689Skan ENDFN (__mips16_call_stub_sf_9) 611169689Skan#endif 612169689Skan 613169689Skan#ifdef L_m16stubsf10 614169689Skan/* (double, double) */ 615169689SkanSTARTFN (__mips16_call_stub_sf_10) 616169689Skan .set noreorder 617169689Skan LDDBL1 618169689Skan LDDBL2 619169689Skan move $18,$31 620169689Skan jal $2 621169689Skan nop 622169689Skan mfc1 $2,$f0 623169689Skan j $18 624169689Skan nop 625169689Skan .set reorder 626169689Skan ENDFN (__mips16_call_stub_sf_10) 627169689Skan#endif 628169689Skan 629169689Skan/* Now we have the same set of functions again, except that this time 630169689Skan the function being called returns an DFmode value. */ 631169689Skan 632169689Skan#ifdef L_m16stubdf0 633169689Skan/* () */ 634169689SkanSTARTFN (__mips16_call_stub_df_0) 635169689Skan .set noreorder 636169689Skan move $18,$31 637169689Skan jal $2 638169689Skan nop 639169689Skan RETDBL 640169689Skan j $18 641169689Skan nop 642169689Skan .set reorder 643169689Skan ENDFN (__mips16_call_stub_df_0) 644169689Skan#endif 645169689Skan 646169689Skan#ifdef L_m16stubdf1 647169689Skan/* (float) */ 648169689SkanSTARTFN (__mips16_call_stub_df_1) 649169689Skan .set noreorder 650169689Skan mtc1 $4,$f12 651169689Skan move $18,$31 652169689Skan jal $2 653169689Skan nop 654169689Skan RETDBL 655169689Skan j $18 656169689Skan nop 657169689Skan .set reorder 658169689Skan ENDFN (__mips16_call_stub_df_1) 659169689Skan#endif 660169689Skan 661169689Skan#ifdef L_m16stubdf2 662169689Skan/* (double) */ 663169689SkanSTARTFN (__mips16_call_stub_df_2) 664169689Skan .set noreorder 665169689Skan LDDBL1 666169689Skan move $18,$31 667169689Skan jal $2 668169689Skan nop 669169689Skan RETDBL 670169689Skan j $18 671169689Skan nop 672169689Skan .set reorder 673169689Skan ENDFN (__mips16_call_stub_df_2) 674169689Skan#endif 675169689Skan 676169689Skan#ifdef L_m16stubdf5 677169689Skan/* (float, float) */ 678169689SkanSTARTFN (__mips16_call_stub_df_5) 679169689Skan .set noreorder 680169689Skan mtc1 $4,$f12 681169689Skan mtc1 $5,$f14 682169689Skan move $18,$31 683169689Skan jal $2 684169689Skan nop 685169689Skan RETDBL 686169689Skan j $18 687169689Skan nop 688169689Skan .set reorder 689169689Skan ENDFN (__mips16_call_stub_df_5) 690169689Skan#endif 691169689Skan 692169689Skan#ifdef L_m16stubdf6 693169689Skan/* (double, float) */ 694169689SkanSTARTFN (__mips16_call_stub_df_6) 695169689Skan .set noreorder 696169689Skan LDDBL1 697169689Skan mtc1 $6,$f14 698169689Skan move $18,$31 699169689Skan jal $2 700169689Skan nop 701169689Skan RETDBL 702169689Skan j $18 703169689Skan nop 704169689Skan .set reorder 705169689Skan ENDFN (__mips16_call_stub_df_6) 706169689Skan#endif 707169689Skan 708169689Skan#ifdef L_m16stubdf9 709169689Skan/* (float, double) */ 710169689SkanSTARTFN (__mips16_call_stub_df_9) 711169689Skan .set noreorder 712169689Skan mtc1 $4,$f12 713169689Skan LDDBL2 714169689Skan move $18,$31 715169689Skan jal $2 716169689Skan nop 717169689Skan RETDBL 718169689Skan j $18 719169689Skan nop 720169689Skan .set reorder 721169689Skan ENDFN (__mips16_call_stub_df_9) 722169689Skan#endif 723169689Skan 724169689Skan#ifdef L_m16stubdf10 725169689Skan/* (double, double) */ 726169689SkanSTARTFN (__mips16_call_stub_df_10) 727169689Skan .set noreorder 728169689Skan LDDBL1 729169689Skan LDDBL2 730169689Skan move $18,$31 731169689Skan jal $2 732169689Skan nop 733169689Skan RETDBL 734169689Skan j $18 735169689Skan nop 736169689Skan .set reorder 737169689Skan ENDFN (__mips16_call_stub_df_10) 738169689Skan#endif 739169689Skan#endif /* !__mips_single_float */ 740