Browse Source

* 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'.
msnyder-reverse-20080609-branch
Adam Nemet 19 years ago
parent
commit
037b32b9ff
  1. 34
      gas/ChangeLog
  2. 213
      gas/config/tc-mips.c
  3. 42
      gas/doc/c-mips.texi

34
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> 2008-04-25 David S. Miller <davem@davemloft.net>
* config/tc-sparc.c: Accept 'softint_clear' and 'softint_set' * config/tc-sparc.c: Accept 'softint_clear' and 'softint_set'

213
gas/config/tc-mips.c

@ -235,21 +235,41 @@ struct mips_set_options
int arch; int arch;
/* True if ".set sym32" is in effect. */ /* True if ".set sym32" is in effect. */
bfd_boolean sym32; 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. */ /* True if -mgp32 was passed. */
static int file_mips_gp32 = -1; static int file_mips_gp32 = -1;
/* True if -mfp32 was passed. */ /* True if -mfp32 was passed. */
static int file_mips_fp32 = -1; static int file_mips_fp32 = -1;
/* This is the struct we use to hold the current set of options. Note /* 1 if -msoft-float, 0 if -mhard-float. The default is 0. */
that we must set the isa field to ISA_UNKNOWN and the ASE fields to static int file_mips_soft_float = 0;
-1 to indicate that they have not been initialized. */
/* 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 = 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. /* 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 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 /* 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. */ 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. */ macros will never generate MDMX, MIPS-3D, or MT instructions. */
if (strcmp (fmt, mo->args) == 0 if (strcmp (fmt, mo->args) == 0
&& mo->pinfo != INSN_MACRO && mo->pinfo != INSN_MACRO
&& OPCODE_IS_MEMBER (mo, && is_opcode_valid (mo, TRUE))
(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))
break; break;
++mo; ++mo;
@ -6120,11 +6196,6 @@ macro (struct mips_cl_insn *ip)
lr = 1; lr = 1;
goto ld; goto ld;
case M_LDC1_AB: case M_LDC1_AB:
if (mips_opts.arch == CPU_R4650)
{
as_bad (_("opcode not supported on this processor"));
break;
}
s = "ldc1"; s = "ldc1";
/* Itbl support may require additional care here. */ /* Itbl support may require additional care here. */
coproc = 1; coproc = 1;
@ -6211,11 +6282,6 @@ macro (struct mips_cl_insn *ip)
s = "cache"; s = "cache";
goto st; goto st;
case M_SDC1_AB: case M_SDC1_AB:
if (mips_opts.arch == CPU_R4650)
{
as_bad (_("opcode not supported on this processor"));
break;
}
s = "sdc1"; s = "sdc1";
coproc = 1; coproc = 1;
/* Itbl support may require additional care here. */ /* Itbl support may require additional care here. */
@ -6757,11 +6823,6 @@ macro (struct mips_cl_insn *ip)
} }
case M_L_DOB: 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 /* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when loading from memory. */ to adjust when loading from memory. */
r = BFD_RELOC_LO16; 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 * But, the resulting address is the same after relocation so why
* generate the extra instruction? * 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. */ /* Itbl support may require additional care here. */
coproc = 1; coproc = 1;
if (mips_opts.isa != ISA_MIPS1) if (mips_opts.isa != ISA_MIPS1)
@ -6806,12 +6862,6 @@ macro (struct mips_cl_insn *ip)
goto ldd_std; goto ldd_std;
case M_S_DAB: 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) if (mips_opts.isa != ISA_MIPS1)
{ {
s = "sdc1"; s = "sdc1";
@ -7456,11 +7506,6 @@ macro2 (struct mips_cl_insn *ip)
break; break;
case M_S_DOB: 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); assert (mips_opts.isa == ISA_MIPS1);
/* Even on a big endian machine $fn comes before $fn+1. We have /* Even on a big endian machine $fn comes before $fn+1. We have
to adjust when storing to memory. */ 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); assert (strcmp (insn->name, str) == 0);
if (OPCODE_IS_MEMBER (insn, ok = is_opcode_valid (insn, FALSE);
(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;
}
if (! ok) if (! ok)
{ {
if (insn + 1 < &mips_opcodes[NUMOPCODES] 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); assert (strcmp (insn->name, str) == 0);
if (OPCODE_IS_MEMBER (insn, mips_opts.isa, mips_opts.arch)) ok = is_opcode_valid_16 (insn);
ok = TRUE;
else
ok = FALSE;
if (! ok) if (! ok)
{ {
if (insn + 1 < &mips16_opcodes[bfd_mips16_num_opcodes] 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) #define OPTION_MNO_SYM32 (OPTION_MISC_BASE + 15)
{"msym32", no_argument, NULL, OPTION_MSYM32}, {"msym32", no_argument, NULL, OPTION_MSYM32},
{"mno-sym32", no_argument, NULL, OPTION_MNO_SYM32}, {"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. */ /* ELF-specific options. */
#ifdef OBJ_ELF #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) #define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
{"KPIC", no_argument, NULL, OPTION_CALL_SHARED}, {"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
{"call_shared", 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; file_mips_fp32 = 0;
break; 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 #ifdef OBJ_ELF
case OPTION_MABI: case OPTION_MABI:
if (!IS_ELF) if (!IS_ELF)
@ -11597,6 +11638,8 @@ mips_after_parse_args (void)
file_ase_mt = mips_opts.ase_mt; file_ase_mt = mips_opts.ase_mt;
mips_opts.gp32 = file_mips_gp32; mips_opts.gp32 = file_mips_gp32;
mips_opts.fp32 = file_mips_fp32; 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) 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_cpu_info_from_isa (mips_opts.isa)->name);
mips_opts.fp32 = 0; 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 else if (strcmp (name, "mips16") == 0
|| strcmp (name, "MIPS-16") == 0) || strcmp (name, "MIPS-16") == 0)
mips_opts.mips16 = 1; mips_opts.mips16 = 1;
@ -15094,9 +15145,15 @@ MIPS options:\n\
-msym32 assume all symbols have 32-bit values\n\ -msym32 assume all symbols have 32-bit values\n\
-O0 remove unneeded NOPs, do not swap branches\n\ -O0 remove unneeded NOPs, do not swap branches\n\
-O remove unneeded NOPs and 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\ --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")); --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 #ifdef OBJ_ELF
fprintf (stream, _("\ fprintf (stream, _("\
-KPIC, -call_shared generate SVR4 position independent code\n\ -KPIC, -call_shared generate SVR4 position independent code\n\

42
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 option stack:: Directives to save and restore options
* MIPS ASE instruction generation overrides:: Directives to control * MIPS ASE instruction generation overrides:: Directives to control
generation of MIPS ASE instructions generation of MIPS ASE instructions
* MIPS floating-point:: Directives to override floating-point options
@end menu @end menu
@node MIPS Opts @node MIPS Opts
@ -272,7 +273,8 @@ m4kp,
sb1, sb1,
sb1a, sb1a,
loongson2e, loongson2e,
loongson2f loongson2f,
octeon
@end quotation @end quotation
For compatibility reasons, @samp{@var{n}x} and @samp{@var{b}fx} are 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} @code{@value{AS}}, there is no need for @samp{-nocpp}, because the
@sc{gnu} assembler itself never runs the C preprocessor. @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 @item --construct-floats
@itemx --no-construct-floats @itemx --no-construct-floats
@cindex --construct-floats
@cindex --no-construct-floats
The @code{--no-construct-floats} option disables the construction of The @code{--no-construct-floats} option disables the construction of
double width floating point constants by loading the two halves of the double width floating point constants by loading the two halves of the
value into the two single width floating point registers that make up 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. instructions from being accepted.
Traditional @sc{mips} assemblers do not support these directives. 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.

Loading…
Cancel
Save