From 532f7559d3aa9ab87b3a6bfecabf9b2bc50a71af Mon Sep 17 00:00:00 2001 From: Adam Nemet Date: Mon, 28 Apr 2008 17:06:28 +0000 Subject: [PATCH] * config/tc-mips.c (file_mips_soft_float, file_mips_single_float): New statics. (OPTION_ELF_BASE): Make room for new option macros. (OPTION_SOFT_FLOAT, OPTION_HARD_FLOAT, OPTION_SINGLE_FLOAT, OPTION_DOUBLE_FLOAT): New option macros. (md_longopts): Add msoft-float, mhard-float, msingle-float and mdouble-float. (md_parse_option): Handle OPTION_SINGLE_FLOAT, OPTION_DOUBLE_FLOAT, OPTION_SOFT_FLOAT and OPTION_HARD_FLOAT. (md_show_usage): Add -msoft-float, -mhard-float, -msingle-float and -mdouble-float. (struct mips_set_options): New fields soft_float and single_float. (mips_opts): Initialized them. Add comment for each field initializer. (mips_after_parse_args): Set them based on file_mips_soft_float and file_mips_single_float. (s_mipsset): Add support for `.set softfloat', `.set hardfloat', `.set singlefloat' and `.set doublefloat'. (is_opcode_valid): New function to invoke OPCODE_IS_MEMBER. Handle single-float and soft-float instructions here. (macro_build, mips_ip): Use it instead of OPCODE_IS_MEMBER. (is_opcode_valid_16): New function. (mips16_ip): Use it instead of OPCODE_IS_MEMBER. (macro) : Remove special-casing of r4650. * doc/c-mips.texi (-march=): Add Octeon. (MIPS Opts): Document -msoft-float and -mhard-float. Document -msingle-float and -mdouble-float. (MIPS floating-point): New section. Document `.set softfloat' and `.set hardfloat'. Document `.set singlefloat' and `.set doublefloat'. --- gas/ChangeLog | 34 ++++++++ gas/config/tc-mips.c | 213 ++++++++++++++++++++++++++++++++------------------- gas/doc/c-mips.texi | 42 +++++++++- 3 files changed, 208 insertions(+), 81 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 6a1a35dfe1..0894c85a9d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,37 @@ +2008-04-28 Adam Nemet + + * config/tc-mips.c (file_mips_soft_float, file_mips_single_float): + New statics. + (OPTION_ELF_BASE): Make room for new option macros. + (OPTION_SOFT_FLOAT, OPTION_HARD_FLOAT, OPTION_SINGLE_FLOAT, + OPTION_DOUBLE_FLOAT): New option macros. + (md_longopts): Add msoft-float, mhard-float, msingle-float and + mdouble-float. + (md_parse_option): Handle OPTION_SINGLE_FLOAT, + OPTION_DOUBLE_FLOAT, OPTION_SOFT_FLOAT and OPTION_HARD_FLOAT. + (md_show_usage): Add -msoft-float, -mhard-float, -msingle-float + and -mdouble-float. + (struct mips_set_options): New fields soft_float and single_float. + (mips_opts): Initialized them. Add comment for each field + initializer. + (mips_after_parse_args): Set them based on file_mips_soft_float + and file_mips_single_float. + (s_mipsset): Add support for `.set softfloat', `.set hardfloat', + `.set singlefloat' and `.set doublefloat'. + (is_opcode_valid): New function to invoke OPCODE_IS_MEMBER. + Handle single-float and soft-float instructions here. + (macro_build, mips_ip): Use it instead of OPCODE_IS_MEMBER. + (is_opcode_valid_16): New function. + (mips16_ip): Use it instead of OPCODE_IS_MEMBER. + (macro) : Remove special-casing of r4650. + * doc/c-mips.texi (-march=): Add Octeon. + (MIPS Opts): Document -msoft-float and -mhard-float. Document + -msingle-float and -mdouble-float. + (MIPS floating-point): New section. Document `.set softfloat' and + `.set hardfloat'. Document `.set singlefloat' and `.set + doublefloat'. + 2008-04-25 David S. Miller * config/tc-sparc.c: Accept 'softint_clear' and 'softint_set' diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index f089345456..811f0d86fd 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -235,21 +235,41 @@ struct mips_set_options int arch; /* True if ".set sym32" is in effect. */ bfd_boolean sym32; + /* True if floating-point operations are not allowed. Changed by .set + softfloat or .set hardfloat, by command line options -msoft-float or + -mhard-float. The default is false. */ + bfd_boolean soft_float; + + /* True if only single-precision floating-point operations are allowed. + Changed by .set singlefloat or .set doublefloat, command-line options + -msingle-float or -mdouble-float. The default is false. */ + bfd_boolean single_float; }; +/* This is the struct we use to hold the current set of options. Note + that we must set the isa field to ISA_UNKNOWN and the ASE fields to + -1 to indicate that they have not been initialized. */ + /* True if -mgp32 was passed. */ static int file_mips_gp32 = -1; /* True if -mfp32 was passed. */ static int file_mips_fp32 = -1; -/* This is the struct we use to hold the current set of options. Note - that we must set the isa field to ISA_UNKNOWN and the ASE fields to - -1 to indicate that they have not been initialized. */ +/* 1 if -msoft-float, 0 if -mhard-float. The default is 0. */ +static int file_mips_soft_float = 0; + +/* 1 if -msingle-float, 0 if -mdouble-float. The default is 0. */ +static int file_mips_single_float = 0; static struct mips_set_options mips_opts = { - ISA_UNKNOWN, -1, -1, 0, -1, -1, -1, -1, 0, ATREG, 0, 0, 0, 0, 0, 0, CPU_UNKNOWN, FALSE + /* isa */ ISA_UNKNOWN, /* ase_mips3d */ -1, /* ase_mdmx */ -1, + /* ase_smartmips */ 0, /* ase_dsp */ -1, /* ase_dspr2 */ -1, /* ase_mt */ -1, + /* mips16 */ -1, /* noreorder */ 0, /* at */ ATREG, + /* warn_about_macros */ 0, /* nomove */ 0, /* nobopt */ 0, + /* noautoextend */ 0, /* gp32 */ 0, /* fp32 */ 0, /* arch */ CPU_UNKNOWN, + /* sym32 */ FALSE, /* soft_float */ FALSE, /* single_float */ FALSE }; /* These variables are filled in with the masks of registers used. @@ -1750,6 +1770,71 @@ reg_lookup (char **s, unsigned int types, unsigned int *regnop) return reg >= 0; } +/* Return TRUE if opcode MO is valid on the currently selected ISA and + architecture. If EXPANSIONP is TRUE then this check is done while + expanding a macro. Use is_opcode_valid_16 for MIPS16 opcodes. */ + +static bfd_boolean +is_opcode_valid (const struct mips_opcode *mo, bfd_boolean expansionp) +{ + int isa = mips_opts.isa; + int fp_s, fp_d; + + if (mips_opts.ase_mdmx) + isa |= INSN_MDMX; + if (mips_opts.ase_dsp) + isa |= INSN_DSP; + if (mips_opts.ase_dsp && ISA_SUPPORTS_DSP64_ASE) + isa |= INSN_DSP64; + if (mips_opts.ase_dspr2) + isa |= INSN_DSPR2; + if (mips_opts.ase_mt) + isa |= INSN_MT; + if (mips_opts.ase_mips3d) + isa |= INSN_MIPS3D; + if (mips_opts.ase_smartmips) + isa |= INSN_SMARTMIPS; + + /* For user code we don't check for mips_opts.mips16 since we want + to allow jalx if -mips16 was specified on the command line. */ + if (expansionp ? mips_opts.mips16 : file_ase_mips16) + isa |= INSN_MIPS16; + + if (!OPCODE_IS_MEMBER (mo, isa, mips_opts.arch)) + return FALSE; + + /* Check whether the instruction or macro requires single-precision or + double-precision floating-point support. Note that this information is + stored differently in the opcode table for insns and macros. */ + if (mo->pinfo == INSN_MACRO) + { + fp_s = mo->pinfo2 & INSN2_M_FP_S; + fp_d = mo->pinfo2 & INSN2_M_FP_D; + } + else + { + fp_s = mo->pinfo & FP_S; + fp_d = mo->pinfo & FP_D; + } + + if (fp_d && (mips_opts.soft_float || mips_opts.single_float)) + return FALSE; + + if (fp_s && mips_opts.soft_float) + return FALSE; + + return TRUE; +} + +/* Return TRUE if the MIPS16 opcode MO is valid on the currently + selected ISA and architecture. */ + +static bfd_boolean +is_opcode_valid_16 (const struct mips_opcode *mo) +{ + return OPCODE_IS_MEMBER (mo, mips_opts.isa, mips_opts.arch) ? TRUE : FALSE; +} + /* This function is called once, at assembler startup time. It should set up all the tables, etc. that the MD part of the assembler will need. */ @@ -3367,16 +3452,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...) macros will never generate MDMX, MIPS-3D, or MT instructions. */ if (strcmp (fmt, mo->args) == 0 && mo->pinfo != INSN_MACRO - && OPCODE_IS_MEMBER (mo, - (mips_opts.isa - | (mips_opts.mips16 ? INSN_MIPS16 : 0) - | (mips_opts.ase_dsp ? INSN_DSP : 0) - | ((mips_opts.ase_dsp && ISA_SUPPORTS_DSP64_ASE) - ? INSN_DSP64 : 0) - | (mips_opts.ase_dspr2 ? INSN_DSPR2 : 0) - | (mips_opts.ase_smartmips ? INSN_SMARTMIPS : 0)), - mips_opts.arch) - && (mips_opts.arch != CPU_R4650 || (mo->pinfo & FP_D) == 0)) + && is_opcode_valid (mo, TRUE)) break; ++mo; @@ -6120,11 +6196,6 @@ macro (struct mips_cl_insn *ip) lr = 1; goto ld; case M_LDC1_AB: - if (mips_opts.arch == CPU_R4650) - { - as_bad (_("opcode not supported on this processor")); - break; - } s = "ldc1"; /* Itbl support may require additional care here. */ coproc = 1; @@ -6211,11 +6282,6 @@ macro (struct mips_cl_insn *ip) s = "cache"; goto st; case M_SDC1_AB: - if (mips_opts.arch == CPU_R4650) - { - as_bad (_("opcode not supported on this processor")); - break; - } s = "sdc1"; coproc = 1; /* Itbl support may require additional care here. */ @@ -6757,11 +6823,6 @@ macro (struct mips_cl_insn *ip) } case M_L_DOB: - if (mips_opts.arch == CPU_R4650) - { - as_bad (_("opcode not supported on this processor")); - break; - } /* Even on a big endian machine $fn comes before $fn+1. We have to adjust when loading from memory. */ r = BFD_RELOC_LO16; @@ -6788,11 +6849,6 @@ macro (struct mips_cl_insn *ip) * But, the resulting address is the same after relocation so why * generate the extra instruction? */ - if (mips_opts.arch == CPU_R4650) - { - as_bad (_("opcode not supported on this processor")); - break; - } /* Itbl support may require additional care here. */ coproc = 1; if (mips_opts.isa != ISA_MIPS1) @@ -6806,12 +6862,6 @@ macro (struct mips_cl_insn *ip) goto ldd_std; case M_S_DAB: - if (mips_opts.arch == CPU_R4650) - { - as_bad (_("opcode not supported on this processor")); - break; - } - if (mips_opts.isa != ISA_MIPS1) { s = "sdc1"; @@ -7456,11 +7506,6 @@ macro2 (struct mips_cl_insn *ip) break; case M_S_DOB: - if (mips_opts.arch == CPU_R4650) - { - as_bad (_("opcode not supported on this processor")); - break; - } assert (mips_opts.isa == ISA_MIPS1); /* Even on a big endian machine $fn comes before $fn+1. We have to adjust when storing to memory. */ @@ -8452,31 +8497,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) assert (strcmp (insn->name, str) == 0); - if (OPCODE_IS_MEMBER (insn, - (mips_opts.isa - /* We don't check for mips_opts.mips16 here since - we want to allow jalx if -mips16 was specified - on the command line. */ - | (file_ase_mips16 ? INSN_MIPS16 : 0) - | (mips_opts.ase_mdmx ? INSN_MDMX : 0) - | (mips_opts.ase_dsp ? INSN_DSP : 0) - | ((mips_opts.ase_dsp && ISA_SUPPORTS_DSP64_ASE) - ? INSN_DSP64 : 0) - | (mips_opts.ase_dspr2 ? INSN_DSPR2 : 0) - | (mips_opts.ase_mt ? INSN_MT : 0) - | (mips_opts.ase_mips3d ? INSN_MIPS3D : 0) - | (mips_opts.ase_smartmips ? INSN_SMARTMIPS : 0)), - mips_opts.arch)) - ok = TRUE; - else - ok = FALSE; - - if (insn->pinfo != INSN_MACRO) - { - if (mips_opts.arch == CPU_R4650 && (insn->pinfo & FP_D) != 0) - ok = FALSE; - } - + ok = is_opcode_valid (insn, FALSE); if (! ok) { if (insn + 1 < &mips_opcodes[NUMOPCODES] @@ -9824,11 +9845,7 @@ mips16_ip (char *str, struct mips_cl_insn *ip) assert (strcmp (insn->name, str) == 0); - if (OPCODE_IS_MEMBER (insn, mips_opts.isa, mips_opts.arch)) - ok = TRUE; - else - ok = FALSE; - + ok = is_opcode_valid_16 (insn); if (! ok) { if (insn + 1 < &mips16_opcodes[bfd_mips16_num_opcodes] @@ -10957,10 +10974,18 @@ struct option md_longopts[] = #define OPTION_MNO_SYM32 (OPTION_MISC_BASE + 15) {"msym32", no_argument, NULL, OPTION_MSYM32}, {"mno-sym32", no_argument, NULL, OPTION_MNO_SYM32}, - +#define OPTION_SOFT_FLOAT (OPTION_MISC_BASE + 16) +#define OPTION_HARD_FLOAT (OPTION_MISC_BASE + 17) + {"msoft-float", no_argument, NULL, OPTION_SOFT_FLOAT}, + {"mhard-float", no_argument, NULL, OPTION_HARD_FLOAT}, +#define OPTION_SINGLE_FLOAT (OPTION_MISC_BASE + 18) +#define OPTION_DOUBLE_FLOAT (OPTION_MISC_BASE + 19) + {"msingle-float", no_argument, NULL, OPTION_SINGLE_FLOAT}, + {"mdouble-float", no_argument, NULL, OPTION_DOUBLE_FLOAT}, + /* ELF-specific options. */ #ifdef OBJ_ELF -#define OPTION_ELF_BASE (OPTION_MISC_BASE + 16) +#define OPTION_ELF_BASE (OPTION_MISC_BASE + 20) #define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0) {"KPIC", no_argument, NULL, OPTION_CALL_SHARED}, {"call_shared", no_argument, NULL, OPTION_CALL_SHARED}, @@ -11320,6 +11345,22 @@ md_parse_option (int c, char *arg) file_mips_fp32 = 0; break; + case OPTION_SINGLE_FLOAT: + file_mips_single_float = 1; + break; + + case OPTION_DOUBLE_FLOAT: + file_mips_single_float = 0; + break; + + case OPTION_SOFT_FLOAT: + file_mips_soft_float = 1; + break; + + case OPTION_HARD_FLOAT: + file_mips_soft_float = 0; + break; + #ifdef OBJ_ELF case OPTION_MABI: if (!IS_ELF) @@ -11597,6 +11638,8 @@ mips_after_parse_args (void) file_ase_mt = mips_opts.ase_mt; mips_opts.gp32 = file_mips_gp32; mips_opts.fp32 = file_mips_fp32; + mips_opts.soft_float = file_mips_soft_float; + mips_opts.single_float = file_mips_single_float; if (mips_flag_mdebug < 0) { @@ -12473,6 +12516,14 @@ s_mipsset (int x ATTRIBUTE_UNUSED) mips_cpu_info_from_isa (mips_opts.isa)->name); mips_opts.fp32 = 0; } + else if (strcmp (name, "softfloat") == 0) + mips_opts.soft_float = 1; + else if (strcmp (name, "hardfloat") == 0) + mips_opts.soft_float = 0; + else if (strcmp (name, "singlefloat") == 0) + mips_opts.single_float = 1; + else if (strcmp (name, "doublefloat") == 0) + mips_opts.single_float = 0; else if (strcmp (name, "mips16") == 0 || strcmp (name, "MIPS-16") == 0) mips_opts.mips16 = 1; @@ -15094,9 +15145,15 @@ MIPS options:\n\ -msym32 assume all symbols have 32-bit values\n\ -O0 remove unneeded NOPs, do not swap branches\n\ -O remove unneeded NOPs and swap branches\n\ ---[no-]construct-floats [dis]allow floating point values to be constructed\n\ --trap, --no-break trap exception on div by 0 and mult overflow\n\ --break, --no-trap break exception on div by 0 and mult overflow\n")); + fprintf (stream, _("\ +-mhard-float allow floating-point instructions\n\ +-msoft-float do not allow floating-point instructions\n\ +-msingle-float only allow 32-bit floating-point operations\n\ +-mdouble-float allow 32-bit and 64-bit floating-point operations\n\ +--[no-]construct-floats [dis]allow floating point values to be constructed\n" + )); #ifdef OBJ_ELF fprintf (stream, _("\ -KPIC, -call_shared generate SVR4 position independent code\n\ diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi index e6fe033db5..136d2d22bf 100644 --- a/gas/doc/c-mips.texi +++ b/gas/doc/c-mips.texi @@ -32,6 +32,7 @@ Assembly Language Programming'' in the same work. * MIPS option stack:: Directives to save and restore options * MIPS ASE instruction generation overrides:: Directives to control generation of MIPS ASE instructions +* MIPS floating-point:: Directives to override floating-point options @end menu @node MIPS Opts @@ -272,7 +273,8 @@ m4kp, sb1, sb1a, loongson2e, -loongson2f +loongson2f, +octeon @end quotation For compatibility reasons, @samp{@var{n}x} and @samp{@var{b}fx} are @@ -301,10 +303,21 @@ other assemblers, which use it to turn off C style preprocessing. With @sc{gnu} @code{@value{AS}}, there is no need for @samp{-nocpp}, because the @sc{gnu} assembler itself never runs the C preprocessor. +@item -msoft-float +@itemx -mhard-float +Disable or enable floating-point instructions. Note that by default +floating-point instructions are always allowed even with CPU targets +that don't have support for these instructions. + +@item -msingle-float +@itemx -mdouble-float +Disable or enable double-precision floating-point operations. Note +that by default double-precision floating-point operations are always +allowed even with CPU targets that don't have support for these +operations. + @item --construct-floats @itemx --no-construct-floats -@cindex --construct-floats -@cindex --no-construct-floats The @code{--no-construct-floats} option disables the construction of double width floating point constants by loading the two halves of the value into the two single width floating point registers that make up @@ -579,3 +592,26 @@ in the assembly. The @code{.set nomt} directive prevents MT instructions from being accepted. Traditional @sc{mips} assemblers do not support these directives. + +@node MIPS floating-point +@section Directives to override floating-point options + +@cindex Disable floating-point instructions +@kindex @code{.set softfloat} +@kindex @code{.set hardfloat} +The directives @code{.set softfloat} and @code{.set hardfloat} provide +finer control of disabling and enabling float-point instructions. +These directives always override the default (that hard-float +instructions are accepted) or the command-line options +(@samp{-msoft-float} and @samp{-mhard-float}). + +@cindex Disable single-precision floating-point operations +@kindex @code{.set softfloat} +@kindex @code{.set hardfloat} +The directives @code{.set singlefloat} and @code{.set doublefloat} +provide finer control of disabling and enabling double-precision +float-point operations. These directives always override the default +(that double-precision operations are accepted) or the command-line +options (@samp{-msingle-float} and @samp{-mdouble-float}). + +Traditional @sc{mips} assemblers do not support these directives. -- 2.11.0