aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog34
-rw-r--r--gas/config/tc-mips.c213
-rw-r--r--gas/doc/c-mips.texi42
3 files changed, 208 insertions, 81 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 6a1a35d..0894c85 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,37 @@
+2008-04-28 Adam Nemet <anemet@caviumnetworks.com>
+
+ * 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) <M_LDC1_AB, M_SDC1_AB, M_L_DOB, M_L_DAB, M_S_DAB,
+ M_S_DOB>: 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 <davem@davemloft.net>
* 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 f089345..811f0d8 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 e6fe033..136d2d2 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.