* 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'.
This commit is contained in:
Adam Nemet 2008-04-28 17:06:28 +00:00
parent 39c5c16818
commit 037b32b9ff
3 changed files with 208 additions and 81 deletions

View File

@ -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'

View File

@ -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\

View File

@ -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.