URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [mips/] [mips16.S] - Rev 734
Compare with Previous | Blame | View Log
/* mips16 floating point support codeCopyright (C) 1996, 1997, 1998, 2008, 2009, 2010Free Software Foundation, Inc.Contributed by Cygnus SupportThis file is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 3, or (at your option) anylater version.This file is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.Under Section 7 of GPL version 3, you are granted additionalpermissions described in the GCC Runtime Library Exception, version3.1, as published by the Free Software Foundation.You should have received a copy of the GNU General Public License anda copy of the GCC Runtime Library Exception along with this program;see the files COPYING3 and COPYING.RUNTIME respectively. If not, see<http://www.gnu.org/licenses/>. *//* This file contains mips16 floating point support functions. Thesefunctions are called by mips16 code to handle floating point when-msoft-float is not used. They accept the arguments and returnvalues using the soft-float calling convention, but do the actualoperation using the hard floating point instructions. */#if defined _MIPS_SIM && (_MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIO64)/* This file contains 32-bit assembly code. */.set nomips16/* Start a function. */#define STARTFN(NAME) .globl NAME; .ent NAME; NAME:/* Finish a function. */#define ENDFN(NAME) .end NAME/* ARG1The FPR that holds the first floating-point argument.ARG2The FPR that holds the second floating-point argument.RETThe FPR that holds a floating-point return value. */#define RET $f0#define ARG1 $f12#ifdef __mips64#define ARG2 $f13#else#define ARG2 $f14#endif/* Set 64-bit register GPR so that its high 32 bits contain HIGH_FPRand so that its low 32 bits contain LOW_FPR. */#define MERGE_GPRf(GPR, HIGH_FPR, LOW_FPR) \.set noat; \mfc1 $1, LOW_FPR; \mfc1 GPR, HIGH_FPR; \dsll $1, $1, 32; \dsll GPR, GPR, 32; \dsrl $1, $1, 32; \or GPR, GPR, $1; \.set at/* Move the high 32 bits of GPR to HIGH_FPR and the low 32 bits ofGPR to LOW_FPR. */#define MERGE_GPRt(GPR, HIGH_FPR, LOW_FPR) \.set noat; \dsrl $1, GPR, 32; \mtc1 GPR, LOW_FPR; \mtc1 $1, HIGH_FPR; \.set at/* Jump to T, and use "OPCODE, OP2" to implement a delayed move. */#define DELAYt(T, OPCODE, OP2) \.set noreorder; \jr T; \OPCODE, OP2; \.set reorder/* Use "OPCODE. OP2" and jump to T. */#define DELAYf(T, OPCODE, OP2) OPCODE, OP2; jr T/* MOVE_SF_BYTE0(D)Move the first single-precision floating-point argument betweenGPRs and FPRs.MOVE_SI_BYTE0(D)Likewise the first single-precision integer argument.MOVE_SF_BYTE4(D)Move the second single-precision floating-point argument betweenGPRs and FPRs, given that the first argument occupies 4 bytes.MOVE_SF_BYTE8(D)Move the second single-precision floating-point argument betweenGPRs and FPRs, given that the first argument occupies 8 bytes.MOVE_DF_BYTE0(D)Move the first double-precision floating-point argument betweenGPRs and FPRs.MOVE_DF_BYTE8(D)Likewise the second double-precision floating-point argument.MOVE_SF_RET(D, T)Likewise a single-precision floating-point return value,then jump to T.MOVE_SC_RET(D, T)Likewise a complex single-precision floating-point return value.MOVE_DF_RET(D, T)Likewise a double-precision floating-point return value.MOVE_DC_RET(D, T)Likewise a complex double-precision floating-point return value.MOVE_SI_RET(D, T)Likewise a single-precision integer return value.The D argument is "t" to move to FPRs and "f" to move from FPRs.The return macros may assume that the target of the jump does notuse a floating-point register. */#define MOVE_SF_RET(D, T) DELAY##D (T, m##D##c1 $2,$f0)#define MOVE_SI_RET(D, T) DELAY##D (T, m##D##c1 $2,$f0)#if defined(__mips64) && defined(__MIPSEB__)#define MOVE_SC_RET(D, T) MERGE_GPR##D ($2, $f0, $f1); jr T#elif defined(__mips64)/* The high 32 bits of $2 correspond to the second word in memory;i.e. the imaginary part. */#define MOVE_SC_RET(D, T) MERGE_GPR##D ($2, $f1, $f0); jr T#elif __mips_fpr == 64#define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f1)#else#define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f2)#endif#if defined(__mips64)#define MOVE_SF_BYTE0(D) m##D##c1 $4,$f12#define MOVE_SF_BYTE4(D) m##D##c1 $5,$f13#define MOVE_SF_BYTE8(D) m##D##c1 $5,$f13#else#define MOVE_SF_BYTE0(D) m##D##c1 $4,$f12#define MOVE_SF_BYTE4(D) m##D##c1 $5,$f14#define MOVE_SF_BYTE8(D) m##D##c1 $6,$f14#endif#define MOVE_SI_BYTE0(D) MOVE_SF_BYTE0(D)#if defined(__mips64)#define MOVE_DF_BYTE0(D) dm##D##c1 $4,$f12#define MOVE_DF_BYTE8(D) dm##D##c1 $5,$f13#define MOVE_DF_RET(D, T) DELAY##D (T, dm##D##c1 $2,$f0)#define MOVE_DC_RET(D, T) dm##D##c1 $3,$f1; MOVE_DF_RET (D, T)#elif __mips_fpr == 64 && defined(__MIPSEB__)#define MOVE_DF_BYTE0(D) m##D##c1 $5,$f12; m##D##hc1 $4,$f12#define MOVE_DF_BYTE8(D) m##D##c1 $7,$f14; m##D##hc1 $6,$f14#define MOVE_DF_RET(D, T) m##D##c1 $3,$f0; DELAY##D (T, m##D##hc1 $2,$f0)#define MOVE_DC_RET(D, T) m##D##c1 $5,$f1; m##D##hc1 $4,$f1; MOVE_DF_RET (D, T)#elif __mips_fpr == 64#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f12; m##D##hc1 $5,$f12#define MOVE_DF_BYTE8(D) m##D##c1 $6,$f14; m##D##hc1 $7,$f14#define MOVE_DF_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##hc1 $3,$f0)#define MOVE_DC_RET(D, T) m##D##c1 $4,$f1; m##D##hc1 $5,$f1; MOVE_DF_RET (D, T)#elif defined(__MIPSEB__)/* FPRs are little-endian. */#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f13; m##D##c1 $5,$f12#define MOVE_DF_BYTE8(D) m##D##c1 $6,$f15; m##D##c1 $7,$f14#define MOVE_DF_RET(D, T) m##D##c1 $2,$f1; DELAY##D (T, m##D##c1 $3,$f0)#define MOVE_DC_RET(D, T) m##D##c1 $4,$f3; m##D##c1 $5,$f2; MOVE_DF_RET (D, T)#else#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f12; m##D##c1 $5,$f13#define MOVE_DF_BYTE8(D) m##D##c1 $6,$f14; m##D##c1 $7,$f15#define MOVE_DF_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f1)#define MOVE_DC_RET(D, T) m##D##c1 $4,$f2; m##D##c1 $5,$f3; MOVE_DF_RET (D, T)#endif/* Single-precision math. *//* Define a function NAME that loads two single-precision values,performs FPU operation OPCODE on them, and returns the single-precision result. */#define OPSF3(NAME, OPCODE) \STARTFN (NAME); \MOVE_SF_BYTE0 (t); \MOVE_SF_BYTE4 (t); \OPCODE RET,ARG1,ARG2; \MOVE_SF_RET (f, $31); \ENDFN (NAME)#ifdef L_m16addsf3OPSF3 (__mips16_addsf3, add.s)#endif#ifdef L_m16subsf3OPSF3 (__mips16_subsf3, sub.s)#endif#ifdef L_m16mulsf3OPSF3 (__mips16_mulsf3, mul.s)#endif#ifdef L_m16divsf3OPSF3 (__mips16_divsf3, div.s)#endif/* Define a function NAME that loads a single-precision value,performs FPU operation OPCODE on it, and returns the single-precision result. */#define OPSF2(NAME, OPCODE) \STARTFN (NAME); \MOVE_SF_BYTE0 (t); \OPCODE RET,ARG1; \MOVE_SF_RET (f, $31); \ENDFN (NAME)#ifdef L_m16negsf2OPSF2 (__mips16_negsf2, neg.s)#endif#ifdef L_m16abssf2OPSF2 (__mips16_abssf2, abs.s)#endif/* Single-precision comparisons. *//* Define a function NAME that loads two single-precision values,performs floating point comparison OPCODE, and returns TRUE orFALSE depending on the result. */#define CMPSF(NAME, OPCODE, TRUE, FALSE) \STARTFN (NAME); \MOVE_SF_BYTE0 (t); \MOVE_SF_BYTE4 (t); \OPCODE ARG1,ARG2; \li $2,TRUE; \bc1t 1f; \li $2,FALSE; \1:; \j $31; \ENDFN (NAME)/* Like CMPSF, but reverse the comparison operands. */#define REVCMPSF(NAME, OPCODE, TRUE, FALSE) \STARTFN (NAME); \MOVE_SF_BYTE0 (t); \MOVE_SF_BYTE4 (t); \OPCODE ARG2,ARG1; \li $2,TRUE; \bc1t 1f; \li $2,FALSE; \1:; \j $31; \ENDFN (NAME)#ifdef L_m16eqsf2CMPSF (__mips16_eqsf2, c.eq.s, 0, 1)#endif#ifdef L_m16nesf2CMPSF (__mips16_nesf2, c.eq.s, 0, 1)#endif#ifdef L_m16gtsf2REVCMPSF (__mips16_gtsf2, c.lt.s, 1, 0)#endif#ifdef L_m16gesf2REVCMPSF (__mips16_gesf2, c.le.s, 0, -1)#endif#ifdef L_m16lesf2CMPSF (__mips16_lesf2, c.le.s, 0, 1)#endif#ifdef L_m16ltsf2CMPSF (__mips16_ltsf2, c.lt.s, -1, 0)#endif#ifdef L_m16unordsf2CMPSF(__mips16_unordsf2, c.un.s, 1, 0)#endif/* Single-precision conversions. */#ifdef L_m16fltsisfSTARTFN (__mips16_floatsisf)MOVE_SF_BYTE0 (t)cvt.s.w RET,ARG1MOVE_SF_RET (f, $31)ENDFN (__mips16_floatsisf)#endif#ifdef L_m16fltunsisfSTARTFN (__mips16_floatunsisf).set noreorderbltz $4,1fMOVE_SF_BYTE0 (t).set reordercvt.s.w RET,ARG1MOVE_SF_RET (f, $31)1:and $2,$4,1srl $3,$4,1or $2,$2,$3mtc1 $2,RETcvt.s.w RET,RETadd.s RET,RET,RETMOVE_SF_RET (f, $31)ENDFN (__mips16_floatunsisf)#endif#ifdef L_m16fix_truncsfsiSTARTFN (__mips16_fix_truncsfsi)MOVE_SF_BYTE0 (t)trunc.w.s RET,ARG1,$4MOVE_SI_RET (f, $31)ENDFN (__mips16_fix_truncsfsi)#endif#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)/* Double-precision math. *//* Define a function NAME that loads two double-precision values,performs FPU operation OPCODE on them, and returns the double-precision result. */#define OPDF3(NAME, OPCODE) \STARTFN (NAME); \MOVE_DF_BYTE0 (t); \MOVE_DF_BYTE8 (t); \OPCODE RET,ARG1,ARG2; \MOVE_DF_RET (f, $31); \ENDFN (NAME)#ifdef L_m16adddf3OPDF3 (__mips16_adddf3, add.d)#endif#ifdef L_m16subdf3OPDF3 (__mips16_subdf3, sub.d)#endif#ifdef L_m16muldf3OPDF3 (__mips16_muldf3, mul.d)#endif#ifdef L_m16divdf3OPDF3 (__mips16_divdf3, div.d)#endif/* Define a function NAME that loads a double-precision value,performs FPU operation OPCODE on it, and returns the double-precision result. */#define OPDF2(NAME, OPCODE) \STARTFN (NAME); \MOVE_DF_BYTE0 (t); \OPCODE RET,ARG1; \MOVE_DF_RET (f, $31); \ENDFN (NAME)#ifdef L_m16negdf2OPDF2 (__mips16_negdf2, neg.d)#endif#ifdef L_m16absdf2OPDF2 (__mips16_absdf2, abs.d)#endif/* Conversions between single and double precision. */#ifdef L_m16extsfdf2STARTFN (__mips16_extendsfdf2)MOVE_SF_BYTE0 (t)cvt.d.s RET,ARG1MOVE_DF_RET (f, $31)ENDFN (__mips16_extendsfdf2)#endif#ifdef L_m16trdfsf2STARTFN (__mips16_truncdfsf2)MOVE_DF_BYTE0 (t)cvt.s.d RET,ARG1MOVE_SF_RET (f, $31)ENDFN (__mips16_truncdfsf2)#endif/* Double-precision comparisons. *//* Define a function NAME that loads two double-precision values,performs floating point comparison OPCODE, and returns TRUE orFALSE depending on the result. */#define CMPDF(NAME, OPCODE, TRUE, FALSE) \STARTFN (NAME); \MOVE_DF_BYTE0 (t); \MOVE_DF_BYTE8 (t); \OPCODE ARG1,ARG2; \li $2,TRUE; \bc1t 1f; \li $2,FALSE; \1:; \j $31; \ENDFN (NAME)/* Like CMPDF, but reverse the comparison operands. */#define REVCMPDF(NAME, OPCODE, TRUE, FALSE) \STARTFN (NAME); \MOVE_DF_BYTE0 (t); \MOVE_DF_BYTE8 (t); \OPCODE ARG2,ARG1; \li $2,TRUE; \bc1t 1f; \li $2,FALSE; \1:; \j $31; \ENDFN (NAME)#ifdef L_m16eqdf2CMPDF (__mips16_eqdf2, c.eq.d, 0, 1)#endif#ifdef L_m16nedf2CMPDF (__mips16_nedf2, c.eq.d, 0, 1)#endif#ifdef L_m16gtdf2REVCMPDF (__mips16_gtdf2, c.lt.d, 1, 0)#endif#ifdef L_m16gedf2REVCMPDF (__mips16_gedf2, c.le.d, 0, -1)#endif#ifdef L_m16ledf2CMPDF (__mips16_ledf2, c.le.d, 0, 1)#endif#ifdef L_m16ltdf2CMPDF (__mips16_ltdf2, c.lt.d, -1, 0)#endif#ifdef L_m16unorddf2CMPDF(__mips16_unorddf2, c.un.d, 1, 0)#endif/* Double-precision conversions. */#ifdef L_m16fltsidfSTARTFN (__mips16_floatsidf)MOVE_SI_BYTE0 (t)cvt.d.w RET,ARG1MOVE_DF_RET (f, $31)ENDFN (__mips16_floatsidf)#endif#ifdef L_m16fltunsidfSTARTFN (__mips16_floatunsidf)MOVE_SI_BYTE0 (t)cvt.d.w RET,ARG1bgez $4,1fli.d ARG1, 4.294967296e+9add.d RET, RET, ARG11: MOVE_DF_RET (f, $31)ENDFN (__mips16_floatunsidf)#endif#ifdef L_m16fix_truncdfsiSTARTFN (__mips16_fix_truncdfsi)MOVE_DF_BYTE0 (t)trunc.w.d RET,ARG1,$4MOVE_SI_RET (f, $31)ENDFN (__mips16_fix_truncdfsi)#endif#endif /* !__mips_single_float *//* Define a function NAME that moves a return value of mode MODE fromFPRs to GPRs. */#define RET_FUNCTION(NAME, MODE) \STARTFN (NAME); \MOVE_##MODE##_RET (t, $31); \ENDFN (NAME)#ifdef L_m16retsfRET_FUNCTION (__mips16_ret_sf, SF)#endif#ifdef L_m16retscRET_FUNCTION (__mips16_ret_sc, SC)#endif#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)#ifdef L_m16retdfRET_FUNCTION (__mips16_ret_df, DF)#endif#ifdef L_m16retdcRET_FUNCTION (__mips16_ret_dc, DC)#endif#endif /* !__mips_single_float *//* STUB_ARGS_X copies the arguments from GPRs to FPRs for argumentcode X. X is calculated as ARG1 + ARG2 * 4, where ARG1 and ARG2classify the first and second arguments as follows:1: a single-precision argument2: a double-precision argument0: no argument, or not one of the above. */#define STUB_ARGS_0 /* () */#define STUB_ARGS_1 MOVE_SF_BYTE0 (t) /* (sf) */#define STUB_ARGS_5 MOVE_SF_BYTE0 (t); MOVE_SF_BYTE4 (t) /* (sf, sf) */#define STUB_ARGS_9 MOVE_SF_BYTE0 (t); MOVE_DF_BYTE8 (t) /* (sf, df) */#define STUB_ARGS_2 MOVE_DF_BYTE0 (t) /* (df) */#define STUB_ARGS_6 MOVE_DF_BYTE0 (t); MOVE_SF_BYTE8 (t) /* (df, sf) */#define STUB_ARGS_10 MOVE_DF_BYTE0 (t); MOVE_DF_BYTE8 (t) /* (df, df) *//* These functions are used by 16-bit code when calling via a functionpointer. They must copy the floating point arguments from the GPRsto FPRs and then call function $2. */#define CALL_STUB_NO_RET(NAME, CODE) \STARTFN (NAME); \STUB_ARGS_##CODE; \.set noreorder; \jr $2; \move $25,$2; \.set reorder; \ENDFN (NAME)#ifdef L_m16stub1CALL_STUB_NO_RET (__mips16_call_stub_1, 1)#endif#ifdef L_m16stub5CALL_STUB_NO_RET (__mips16_call_stub_5, 5)#endif#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)#ifdef L_m16stub2CALL_STUB_NO_RET (__mips16_call_stub_2, 2)#endif#ifdef L_m16stub6CALL_STUB_NO_RET (__mips16_call_stub_6, 6)#endif#ifdef L_m16stub9CALL_STUB_NO_RET (__mips16_call_stub_9, 9)#endif#ifdef L_m16stub10CALL_STUB_NO_RET (__mips16_call_stub_10, 10)#endif#endif /* !__mips_single_float *//* Now we have the same set of functions, except that this time thefunction being called returns an SFmode, SCmode, DFmode or DCmodevalue; we need to instantiate a set for each case. The callingfunction will arrange to preserve $18, so these functions are freeto use it to hold the return address.Note that we do not know whether the function we are calling is 16bit or 32 bit. However, it does not matter, because 16-bitfunctions always return floating point values in both the gp andthe fp regs. It would be possible to check whether the functionbeing called is 16 bits, in which case the copy is unnecessary;however, it's faster to always do the copy. */#define CALL_STUB_RET(NAME, CODE, MODE) \STARTFN (NAME); \.cfi_startproc; \/* Create a fake CFA 4 bytes below the stack pointer. */ \.cfi_def_cfa 29,-4; \/* "Save" $sp in itself so we don't use the fake CFA. \This is: DW_CFA_val_expression r29, { DW_OP_reg29 }. */ \.cfi_escape 0x16,29,1,0x6d; \move $18,$31; \.cfi_register 31,18; \STUB_ARGS_##CODE; \.set noreorder; \jalr $2; \move $25,$2; \.set reorder; \MOVE_##MODE##_RET (f, $18); \.cfi_endproc; \ENDFN (NAME)/* First, instantiate the single-float set. */#ifdef L_m16stubsf0CALL_STUB_RET (__mips16_call_stub_sf_0, 0, SF)#endif#ifdef L_m16stubsf1CALL_STUB_RET (__mips16_call_stub_sf_1, 1, SF)#endif#ifdef L_m16stubsf5CALL_STUB_RET (__mips16_call_stub_sf_5, 5, SF)#endif#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)#ifdef L_m16stubsf2CALL_STUB_RET (__mips16_call_stub_sf_2, 2, SF)#endif#ifdef L_m16stubsf6CALL_STUB_RET (__mips16_call_stub_sf_6, 6, SF)#endif#ifdef L_m16stubsf9CALL_STUB_RET (__mips16_call_stub_sf_9, 9, SF)#endif#ifdef L_m16stubsf10CALL_STUB_RET (__mips16_call_stub_sf_10, 10, SF)#endif#endif /* !__mips_single_float *//* Now we have the same set of functions again, except that this timethe function being called returns an DFmode value. */#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)#ifdef L_m16stubdf0CALL_STUB_RET (__mips16_call_stub_df_0, 0, DF)#endif#ifdef L_m16stubdf1CALL_STUB_RET (__mips16_call_stub_df_1, 1, DF)#endif#ifdef L_m16stubdf5CALL_STUB_RET (__mips16_call_stub_df_5, 5, DF)#endif#ifdef L_m16stubdf2CALL_STUB_RET (__mips16_call_stub_df_2, 2, DF)#endif#ifdef L_m16stubdf6CALL_STUB_RET (__mips16_call_stub_df_6, 6, DF)#endif#ifdef L_m16stubdf9CALL_STUB_RET (__mips16_call_stub_df_9, 9, DF)#endif#ifdef L_m16stubdf10CALL_STUB_RET (__mips16_call_stub_df_10, 10, DF)#endif#endif /* !__mips_single_float *//* Ho hum. Here we have the same set of functions again, this timefor when the function being called returns an SCmode value. */#ifdef L_m16stubsc0CALL_STUB_RET (__mips16_call_stub_sc_0, 0, SC)#endif#ifdef L_m16stubsc1CALL_STUB_RET (__mips16_call_stub_sc_1, 1, SC)#endif#ifdef L_m16stubsc5CALL_STUB_RET (__mips16_call_stub_sc_5, 5, SC)#endif#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)#ifdef L_m16stubsc2CALL_STUB_RET (__mips16_call_stub_sc_2, 2, SC)#endif#ifdef L_m16stubsc6CALL_STUB_RET (__mips16_call_stub_sc_6, 6, SC)#endif#ifdef L_m16stubsc9CALL_STUB_RET (__mips16_call_stub_sc_9, 9, SC)#endif#ifdef L_m16stubsc10CALL_STUB_RET (__mips16_call_stub_sc_10, 10, SC)#endif#endif /* !__mips_single_float *//* Finally, another set of functions for DCmode. */#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)#ifdef L_m16stubdc0CALL_STUB_RET (__mips16_call_stub_dc_0, 0, DC)#endif#ifdef L_m16stubdc1CALL_STUB_RET (__mips16_call_stub_dc_1, 1, DC)#endif#ifdef L_m16stubdc5CALL_STUB_RET (__mips16_call_stub_dc_5, 5, DC)#endif#ifdef L_m16stubdc2CALL_STUB_RET (__mips16_call_stub_dc_2, 2, DC)#endif#ifdef L_m16stubdc6CALL_STUB_RET (__mips16_call_stub_dc_6, 6, DC)#endif#ifdef L_m16stubdc9CALL_STUB_RET (__mips16_call_stub_dc_9, 9, DC)#endif#ifdef L_m16stubdc10CALL_STUB_RET (__mips16_call_stub_dc_10, 10, DC)#endif#endif /* !__mips_single_float */#endif
