Add MIPS .module directive

gas/

	* config/tc-mips.c (file_mips_opts_checked): New static global.
	(s_module): New static function.
	(file_ase): Remove.
	(mips_pseudo_table): Add .module handler.
	(mips_set_ase): Add opts argument and use instead of mips_opts.
 	(md_assemble): Use file_mips_check_options.
	(md_parse_option): Update to use file_mips_opts instead of mips_opts.
	(mips_set_architecture): Delete function.  Moved to...
	(mips_after_parse_args): Here.  All logic now applies to
	file_mips_opts first and then copies the final state to mips_opts.
	Move error checking and defaults inference to mips_check_options and
	file_mips_check_options.
	(mips_check_options): New static function.  Common option checking for
	command line, .module and .set.  Use .module values in error messages
	instead of refering to command line options.
	(file_mips_check_options): New static function.  A wrapper for
	mips_check_options with file_mips_opts.  Updates BFD arch based on
	final options.
	(s_mipsset): Split into s_mipsset and parse_code_option.  Settings
	supported by both .set and .module are moved to parse_code_option.
	Warnings and errors are kept in s_mipsset because when
	parse_code_option is used with s_module the warnings are deferred
	until code is generated.  Any setting supporting 'default' value is
	kept in s_mipsset as it is not applicable to s_module. Inferred
	settings are also kept in s_mipsset as s_module does not infer any
	settings.  Use mips_check_options.
	(parse_code_option): New static function derived from s_mipsset.
	(s_module): New static function that implements .module.  Allows file
	level settings to be changed until code is generated.
	(s_cpload, s_cpsetup, s_cplocal): Use file_mips_check_options.
	(s_cprestore, s_cpreturn, s_cpadd, mips_address_bytes): Likewise.
	(mips_elf_final_processing): Update file_ase to file_mips_opts.ase.
	(md_mips_end): Use file_mips_check_options.
	* doc/c-mips.texi: Document .module.

gas/testsuite

	* gas/mips/mips.exp: Add new tests.  Use 64-bit ABI for relax-bc1any.
	Fix micromips arch definition to use mips64r2 consistently.
	* gas/mips/module-defer-warn1.s: New.
	* gas/mips/module-defer-warn1.d: New.
	* gas/mips/module-defer-warn2.s: New.
	* gas/mips/module-defer-warn2.l: New.
	* gas/mips/module-override.d: New.
	* gas/mips/module-override.s: New.
	* gas/mips/mips-gp32-fp64.l: Update expected output.
	* gas/mips/mips-gp64-fp32-pic.l: Update expected output.
	* gas/mips/mips-gp64-fp32.l: Update expected output.
This commit is contained in:
mfortune 2014-05-20 13:28:20 +01:00
parent 153ff4340d
commit 919731affb
12 changed files with 377 additions and 285 deletions

View file

@ -259,6 +259,9 @@ struct mips_set_options
bfd_boolean single_float;
};
/* Specifies whether module level options have been checked yet. */
static bfd_boolean file_mips_opts_checked = FALSE;
/* True if -mnan=2008, false if -mnan=legacy. */
static bfd_boolean mips_flag_nan2008 = FALSE;
@ -286,10 +289,6 @@ static struct mips_set_options mips_opts =
/* soft_float */ FALSE, /* single_float */ FALSE
};
/* The set of ASEs that were selected on the command line, either
explicitly via ASE options or implicitly through things like -march. */
static unsigned int file_ase;
/* Which bits of file_ase were explicitly set or cleared by ASE options. */
static unsigned int file_ase_explicit;
@ -1295,6 +1294,7 @@ static void s_ehword (int);
static void s_cpadd (int);
static void s_insn (int);
static void s_nan (int);
static void s_module (int);
static void s_mips_ent (int);
static void s_mips_end (int);
static void s_mips_frame (int);
@ -1307,6 +1307,7 @@ static bfd_boolean pic_need_relax (symbolS *, asection *);
static int relaxed_branch_length (fragS *, asection *, int);
static int relaxed_micromips_16bit_branch_length (fragS *, asection *, int);
static int relaxed_micromips_32bit_branch_length (fragS *, asection *, int);
static void file_mips_check_options (void);
/* Table and functions used to map between CPU/ISA names, and
ISA levels, and CPU numbers. */
@ -1692,6 +1693,7 @@ static const pseudo_typeS mips_pseudo_table[] =
{"cpadd", s_cpadd, 0},
{"insn", s_insn, 0},
{"nan", s_nan, 0},
{"module", s_module, 0},
/* Relatively generic pseudo-ops that happen to be used on MIPS
chips. */
@ -1759,6 +1761,7 @@ static const pseudo_typeS mips_nonecoff_pseudo_table[] =
int
mips_address_bytes (void)
{
file_mips_check_options ();
return HAVE_64BIT_ADDRESSES ? 8 : 4;
}
@ -1979,14 +1982,15 @@ mips_check_isa_supports_ases (void)
that were affected. */
static unsigned int
mips_set_ase (const struct mips_ase *ase, bfd_boolean enabled_p)
mips_set_ase (const struct mips_ase *ase, struct mips_set_options *opts,
bfd_boolean enabled_p)
{
unsigned int mask;
mask = mips_ase_mask (ase->flags);
mips_opts.ase &= ~mask;
opts->ase &= ~mask;
if (enabled_p)
mips_opts.ase |= ase->flags;
opts->ase |= ase->flags;
return mask;
}
@ -3631,6 +3635,139 @@ md_begin (void)
init_vr4120_conflicts ();
}
/* Perform consistency checks on the current options. */
static void
mips_check_options (struct mips_set_options *opts, bfd_boolean abi_checks)
{
/* Check the size of integer registers agrees with the ABI and ISA. */
if (opts->gp == 64 && !ISA_HAS_64BIT_REGS (opts->isa))
as_bad (_("`gp=64' used with a 32-bit processor"));
else if (abi_checks
&& opts->gp == 32 && ABI_NEEDS_64BIT_REGS (mips_abi))
as_bad (_("`gp=32' used with a 64-bit ABI"));
else if (abi_checks
&& opts->gp == 64 && ABI_NEEDS_32BIT_REGS (mips_abi))
as_bad (_("`gp=64' used with a 32-bit ABI"));
/* Check the size of the float registers agrees with the ABI and ISA. */
switch (opts->fp)
{
case 64:
if (!ISA_HAS_64BIT_FPRS (opts->isa))
as_bad (_("`fp=64' used with a 32-bit fpu"));
else if (abi_checks
&& ABI_NEEDS_32BIT_REGS (mips_abi)
&& !ISA_HAS_MXHC1 (opts->isa))
as_warn (_("`fp=64' used with a 32-bit ABI"));
break;
case 32:
if (abi_checks
&& ABI_NEEDS_64BIT_REGS (mips_abi))
as_warn (_("`fp=32' used with a 64-bit ABI"));
break;
default:
as_bad (_("Unknown size of floating point registers"));
break;
}
if (opts->micromips == 1 && opts->mips16 == 1)
as_bad (_("`mips16' cannot be used with `micromips'"));
}
/* Perform consistency checks on the module level options exactly once.
This is a deferred check that happens:
at the first .set directive
or, at the first pseudo op that generates code (inc .dc.a)
or, at the first instruction
or, at the end. */
static void
file_mips_check_options (void)
{
const struct mips_cpu_info *arch_info = 0;
if (file_mips_opts_checked)
return;
/* The following code determines the register size.
Similar code was added to GCC 3.3 (see override_options() in
config/mips/mips.c). The GAS and GCC code should be kept in sync
as much as possible. */
if (file_mips_opts.gp < 0)
{
/* Infer the integer register size from the ABI and processor.
Restrict ourselves to 32-bit registers if that's all the
processor has, or if the ABI cannot handle 64-bit registers. */
file_mips_opts.gp = (ABI_NEEDS_32BIT_REGS (mips_abi)
|| !ISA_HAS_64BIT_REGS (file_mips_opts.isa))
? 32 : 64;
}
if (file_mips_opts.fp < 0)
{
/* No user specified float register size.
??? GAS treats single-float processors as though they had 64-bit
float registers (although it complains when double-precision
instructions are used). As things stand, saying they have 32-bit
registers would lead to spurious "register must be even" messages.
So here we assume float registers are never smaller than the
integer ones. */
if (file_mips_opts.gp == 64)
/* 64-bit integer registers implies 64-bit float registers. */
file_mips_opts.fp = 64;
else if ((file_mips_opts.ase & FP64_ASES)
&& ISA_HAS_64BIT_FPRS (file_mips_opts.isa))
/* Handle ASEs that require 64-bit float registers, if possible. */
file_mips_opts.fp = 64;
else
/* 32-bit float registers. */
file_mips_opts.fp = 32;
}
arch_info = mips_cpu_info_from_arch (file_mips_opts.arch);
/* End of GCC-shared inference code. */
/* This flag is set when we have a 64-bit capable CPU but use only
32-bit wide registers. Note that EABI does not use it. */
if (ISA_HAS_64BIT_REGS (file_mips_opts.isa)
&& ((mips_abi == NO_ABI && file_mips_opts.gp == 32)
|| mips_abi == O32_ABI))
mips_32bitmode = 1;
if (file_mips_opts.isa == ISA_MIPS1 && mips_trap)
as_bad (_("trap exception not supported at ISA 1"));
/* If the selected architecture includes support for ASEs, enable
generation of code for them. */
if (file_mips_opts.mips16 == -1)
file_mips_opts.mips16 = (CPU_HAS_MIPS16 (file_mips_opts.arch)) ? 1 : 0;
if (file_mips_opts.micromips == -1)
file_mips_opts.micromips = (CPU_HAS_MICROMIPS (file_mips_opts.arch))
? 1 : 0;
/* Some ASEs require 64-bit FPRs, so -mfp32 should stop those ASEs from
being selected implicitly. */
if (file_mips_opts.fp != 64)
file_ase_explicit |= ASE_MIPS3D | ASE_MDMX | ASE_MSA;
/* If the user didn't explicitly select or deselect a particular ASE,
use the default setting for the CPU. */
file_mips_opts.ase |= (arch_info->ase & ~file_ase_explicit);
/* Set up the current options. These may change throughout assembly. */
mips_opts = file_mips_opts;
mips_check_isa_supports_ases ();
mips_check_options (&file_mips_opts, TRUE);
file_mips_opts_checked = TRUE;
if (!bfd_set_arch_mach (stdoutput, bfd_arch_mips, file_mips_opts.arch))
as_warn (_("could not set architecture and machine"));
}
void
md_assemble (char *str)
{
@ -3638,6 +3775,8 @@ md_assemble (char *str)
bfd_reloc_code_real_type unused_reloc[3]
= {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
file_mips_check_options ();
imm_expr.X_op = O_absent;
offset_expr.X_op = O_absent;
offset_reloc[0] = BFD_RELOC_UNUSED;
@ -13483,7 +13622,7 @@ md_parse_option (int c, char *arg)
for (i = 0; i < ARRAY_SIZE (mips_ases); i++)
if (c == mips_ases[i].option_on || c == mips_ases[i].option_off)
{
file_ase_explicit |= mips_set_ase (&mips_ases[i],
file_ase_explicit |= mips_set_ase (&mips_ases[i], &file_mips_opts,
c == mips_ases[i].option_on);
return 1;
}
@ -13625,32 +13764,32 @@ md_parse_option (int c, char *arg)
break;
case OPTION_MICROMIPS:
if (mips_opts.mips16 == 1)
if (file_mips_opts.mips16 == 1)
{
as_bad (_("-mmicromips cannot be used with -mips16"));
return 0;
}
mips_opts.micromips = 1;
file_mips_opts.micromips = 1;
mips_no_prev_insn ();
break;
case OPTION_NO_MICROMIPS:
mips_opts.micromips = 0;
file_mips_opts.micromips = 0;
mips_no_prev_insn ();
break;
case OPTION_MIPS16:
if (mips_opts.micromips == 1)
if (file_mips_opts.micromips == 1)
{
as_bad (_("-mips16 cannot be used with -micromips"));
return 0;
}
mips_opts.mips16 = 1;
file_mips_opts.mips16 = 1;
mips_no_prev_insn ();
break;
case OPTION_NO_MIPS16:
mips_opts.mips16 = 0;
file_mips_opts.mips16 = 0;
mips_no_prev_insn ();
break;
@ -13719,11 +13858,11 @@ md_parse_option (int c, char *arg)
break;
case OPTION_INSN32:
mips_opts.insn32 = TRUE;
file_mips_opts.insn32 = TRUE;
break;
case OPTION_NO_INSN32:
mips_opts.insn32 = FALSE;
file_mips_opts.insn32 = FALSE;
break;
case OPTION_MSHARED:
@ -13735,11 +13874,11 @@ md_parse_option (int c, char *arg)
break;
case OPTION_MSYM32:
mips_opts.sym32 = TRUE;
file_mips_opts.sym32 = TRUE;
break;
case OPTION_MNO_SYM32:
mips_opts.sym32 = FALSE;
file_mips_opts.sym32 = FALSE;
break;
/* When generating ELF code, we permit -KPIC and -call_shared to
@ -13892,22 +14031,7 @@ md_parse_option (int c, char *arg)
return 1;
}
/* Set up globals to generate code for the ISA or processor
described by INFO. */
static void
mips_set_architecture (const struct mips_cpu_info *info)
{
if (info != 0)
{
file_mips_opts.arch = info->cpu;
mips_opts.arch = info->cpu;
mips_opts.isa = info->isa;
}
}
/* Likewise for tuning. */
/* Set up globals to tune for the ISA or processor described by INFO. */
static void
mips_set_tune (const struct mips_cpu_info *info)
@ -13934,7 +14058,7 @@ mips_after_parse_args (void)
if (mips_abi == NO_ABI)
mips_abi = MIPS_DEFAULT_ABI;
/* The following code determines the architecture and register size.
/* The following code determines the architecture.
Similar code was added to GCC 3.3 (see override_options() in
config/mips/mips.c). The GAS and GCC code should be kept in sync
as much as possible. */
@ -13972,7 +14096,14 @@ mips_after_parse_args (void)
as_bad (_("-march=%s is not compatible with the selected ABI"),
arch_info->name);
mips_set_architecture (arch_info);
file_mips_opts.arch = arch_info->cpu;
file_mips_opts.isa = arch_info->isa;
/* Set up initial mips_opts state. */
mips_opts = file_mips_opts;
/* The register size inference code is now placed in
file_mips_check_options. */
/* Optimize for file_mips_opts.arch, unless -mtune selects a different
processor. */
@ -13984,103 +14115,6 @@ mips_after_parse_args (void)
else
mips_set_tune (tune_info);
if (file_mips_opts.gp >= 0)
{
/* The user specified the size of the integer registers. Make sure
it agrees with the ABI and ISA. */
if (file_mips_opts.gp == 64 && !ISA_HAS_64BIT_REGS (mips_opts.isa))
as_bad (_("-mgp64 used with a 32-bit processor"));
else if (file_mips_opts.gp == 32 && ABI_NEEDS_64BIT_REGS (mips_abi))
as_bad (_("-mgp32 used with a 64-bit ABI"));
else if (file_mips_opts.gp == 64 && ABI_NEEDS_32BIT_REGS (mips_abi))
as_bad (_("-mgp64 used with a 32-bit ABI"));
}
else
{
/* Infer the integer register size from the ABI and processor.
Restrict ourselves to 32-bit registers if that's all the
processor has, or if the ABI cannot handle 64-bit registers. */
file_mips_opts.gp = (ABI_NEEDS_32BIT_REGS (mips_abi)
|| !ISA_HAS_64BIT_REGS (mips_opts.isa))
? 32 : 64;
}
switch (file_mips_opts.fp)
{
default:
case -1:
/* No user specified float register size.
??? GAS treats single-float processors as though they had 64-bit
float registers (although it complains when double-precision
instructions are used). As things stand, saying they have 32-bit
registers would lead to spurious "register must be even" messages.
So here we assume float registers are never smaller than the
integer ones. */
if (file_mips_opts.gp == 64)
/* 64-bit integer registers implies 64-bit float registers. */
file_mips_opts.fp = 64;
else if ((mips_opts.ase & FP64_ASES)
&& ISA_HAS_64BIT_FPRS (mips_opts.isa))
/* Handle ASEs that require 64-bit float registers, if possible. */
file_mips_opts.fp = 64;
else
/* 32-bit float registers. */
file_mips_opts.fp = 32;
break;
/* The user specified the size of the float registers. Check if it
agrees with the ABI and ISA. */
case 64:
if (!ISA_HAS_64BIT_FPRS (mips_opts.isa))
as_bad (_("-mfp64 used with a 32-bit fpu"));
else if (ABI_NEEDS_32BIT_REGS (mips_abi)
&& !ISA_HAS_MXHC1 (mips_opts.isa))
as_warn (_("-mfp64 used with a 32-bit ABI"));
break;
case 32:
if (ABI_NEEDS_64BIT_REGS (mips_abi))
as_warn (_("-mfp32 used with a 64-bit ABI"));
break;
}
/* End of GCC-shared inference code. */
/* This flag is set when we have a 64-bit capable CPU but use only
32-bit wide registers. Note that EABI does not use it. */
if (ISA_HAS_64BIT_REGS (mips_opts.isa)
&& ((mips_abi == NO_ABI && file_mips_opts.gp == 32)
|| mips_abi == O32_ABI))
mips_32bitmode = 1;
if (mips_opts.isa == ISA_MIPS1 && mips_trap)
as_bad (_("trap exception not supported at ISA 1"));
/* If the selected architecture includes support for ASEs, enable
generation of code for them. */
if (mips_opts.mips16 == -1)
mips_opts.mips16 = (CPU_HAS_MIPS16 (file_mips_opts.arch)) ? 1 : 0;
if (mips_opts.micromips == -1)
mips_opts.micromips = (CPU_HAS_MICROMIPS (file_mips_opts.arch))
? 1 : 0;
/* MIPS3D, MDMX and MSA require 64-bit FPRs, so -mfp32 should stop those
ASEs from being selected implicitly. */
if (file_mips_opts.fp != 64)
file_ase_explicit |= ASE_MIPS3D | ASE_MDMX | ASE_MSA;
/* If the user didn't explicitly select or deselect a particular ASE,
use the default setting for the CPU. */
mips_opts.ase |= (arch_info->ase & ~file_ase_explicit);
file_mips_opts.isa = mips_opts.isa;
file_mips_opts.ase = mips_opts.ase;
mips_opts.gp = file_mips_opts.gp;
mips_opts.fp = file_mips_opts.fp;
mips_opts.soft_float = file_mips_opts.soft_float;
mips_opts.single_float = file_mips_opts.single_float;
mips_check_isa_supports_ases ();
if (mips_flag_mdebug < 0)
mips_flag_mdebug = 0;
}
@ -14968,30 +15002,11 @@ struct mips_option_stack
static struct mips_option_stack *mips_opts_stack;
/* Handle the .set pseudo-op. */
static void
s_mipsset (int x ATTRIBUTE_UNUSED)
static bfd_boolean
parse_code_option (char * name)
{
char *name = input_line_pointer, ch;
const struct mips_ase *ase;
while (!is_end_of_line[(unsigned char) *input_line_pointer])
++input_line_pointer;
ch = *input_line_pointer;
*input_line_pointer = '\0';
if (strcmp (name, "reorder") == 0)
{
if (mips_opts.noreorder)
end_noreorder ();
}
else if (strcmp (name, "noreorder") == 0)
{
if (!mips_opts.noreorder)
start_noreorder ();
}
else if (strncmp (name, "at=", 3) == 0)
if (strncmp (name, "at=", 3) == 0)
{
char *s = name + 3;
@ -14999,61 +15014,25 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
as_bad (_("unrecognized register name `%s'"), s);
}
else if (strcmp (name, "at") == 0)
{
mips_opts.at = ATREG;
}
mips_opts.at = ATREG;
else if (strcmp (name, "noat") == 0)
{
mips_opts.at = ZERO;
}
else if (strcmp (name, "macro") == 0)
{
mips_opts.warn_about_macros = 0;
}
else if (strcmp (name, "nomacro") == 0)
{
if (mips_opts.noreorder == 0)
as_bad (_("`noreorder' must be set before `nomacro'"));
mips_opts.warn_about_macros = 1;
}
mips_opts.at = ZERO;
else if (strcmp (name, "move") == 0 || strcmp (name, "novolatile") == 0)
{
mips_opts.nomove = 0;
}
mips_opts.nomove = 0;
else if (strcmp (name, "nomove") == 0 || strcmp (name, "volatile") == 0)
{
mips_opts.nomove = 1;
}
mips_opts.nomove = 1;
else if (strcmp (name, "bopt") == 0)
{
mips_opts.nobopt = 0;
}
mips_opts.nobopt = 0;
else if (strcmp (name, "nobopt") == 0)
{
mips_opts.nobopt = 1;
}
else if (strcmp (name, "gp=default") == 0)
mips_opts.gp = file_mips_opts.gp;
mips_opts.nobopt = 1;
else if (strcmp (name, "gp=32") == 0)
mips_opts.gp = 32;
else if (strcmp (name, "gp=64") == 0)
{
if (!ISA_HAS_64BIT_REGS (mips_opts.isa))
as_warn (_("%s isa does not support 64-bit registers"),
mips_cpu_info_from_isa (mips_opts.isa)->name);
mips_opts.gp = 64;
}
else if (strcmp (name, "fp=default") == 0)
mips_opts.fp = file_mips_opts.fp;
mips_opts.gp = 64;
else if (strcmp (name, "fp=32") == 0)
mips_opts.fp = 32;
else if (strcmp (name, "fp=64") == 0)
{
if (!ISA_HAS_64BIT_FPRS (mips_opts.isa))
as_warn (_("%s isa does not support 64-bit floating point registers"),
mips_cpu_info_from_isa (mips_opts.isa)->name);
mips_opts.fp = 64;
}
mips_opts.fp = 64;
else if (strcmp (name, "softfloat") == 0)
mips_opts.soft_float = 1;
else if (strcmp (name, "hardfloat") == 0)
@ -15064,45 +15043,29 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
mips_opts.single_float = 0;
else if (strcmp (name, "mips16") == 0
|| strcmp (name, "MIPS-16") == 0)
{
if (mips_opts.micromips == 1)
as_fatal (_("`mips16' cannot be used with `micromips'"));
mips_opts.mips16 = 1;
}
mips_opts.mips16 = 1;
else if (strcmp (name, "nomips16") == 0
|| strcmp (name, "noMIPS-16") == 0)
mips_opts.mips16 = 0;
else if (strcmp (name, "micromips") == 0)
{
if (mips_opts.mips16 == 1)
as_fatal (_("`micromips' cannot be used with `mips16'"));
mips_opts.micromips = 1;
}
mips_opts.micromips = 1;
else if (strcmp (name, "nomicromips") == 0)
mips_opts.micromips = 0;
else if (name[0] == 'n'
&& name[1] == 'o'
&& (ase = mips_lookup_ase (name + 2)))
mips_set_ase (ase, FALSE);
mips_set_ase (ase, &mips_opts, FALSE);
else if ((ase = mips_lookup_ase (name)))
mips_set_ase (ase, TRUE);
mips_set_ase (ase, &mips_opts, TRUE);
else if (strncmp (name, "mips", 4) == 0 || strncmp (name, "arch=", 5) == 0)
{
int reset = 0;
/* Permit the user to change the ISA and architecture on the fly.
Needless to say, misuse can cause serious problems. */
if (strcmp (name, "mips0") == 0 || strcmp (name, "arch=default") == 0)
{
reset = 1;
mips_opts.isa = file_mips_opts.isa;
mips_opts.arch = file_mips_opts.arch;
}
else if (strncmp (name, "arch=", 5) == 0)
if (strncmp (name, "arch=", 5) == 0)
{
const struct mips_cpu_info *p;
p = mips_parse_cpu("internal use", name + 5);
p = mips_parse_cpu ("internal use", name + 5);
if (!p)
as_bad (_("unknown architecture %s"), name + 5);
else
@ -15115,7 +15078,7 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
{
const struct mips_cpu_info *p;
p = mips_parse_cpu("internal use", name);
p = mips_parse_cpu ("internal use", name);
if (!p)
as_bad (_("unknown ISA level %s"), name + 4);
else
@ -15126,46 +15089,6 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
}
else
as_bad (_("unknown ISA or architecture %s"), name);
switch (mips_opts.isa)
{
case 0:
break;
case ISA_MIPS1:
case ISA_MIPS2:
case ISA_MIPS32:
case ISA_MIPS32R2:
case ISA_MIPS32R3:
case ISA_MIPS32R5:
mips_opts.gp = 32;
mips_opts.fp = 32;
break;
case ISA_MIPS3:
case ISA_MIPS4:
case ISA_MIPS5:
case ISA_MIPS64:
case ISA_MIPS64R2:
case ISA_MIPS64R3:
case ISA_MIPS64R5:
mips_opts.gp = 64;
if (mips_opts.arch == CPU_R5900)
{
mips_opts.fp = 32;
}
else
{
mips_opts.fp = 64;
}
break;
default:
as_bad (_("unknown ISA level %s"), name + 4);
break;
}
if (reset)
{
mips_opts.gp = file_mips_opts.gp;
mips_opts.fp = file_mips_opts.fp;
}
}
else if (strcmp (name, "autoextend") == 0)
mips_opts.noautoextend = 0;
@ -15175,6 +15098,68 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
mips_opts.insn32 = TRUE;
else if (strcmp (name, "noinsn32") == 0)
mips_opts.insn32 = FALSE;
else if (strcmp (name, "sym32") == 0)
mips_opts.sym32 = TRUE;
else if (strcmp (name, "nosym32") == 0)
mips_opts.sym32 = FALSE;
else
return FALSE;
return TRUE;
}
/* Handle the .set pseudo-op. */
static void
s_mipsset (int x ATTRIBUTE_UNUSED)
{
char *name = input_line_pointer, ch;
int prev_isa = mips_opts.isa;
file_mips_check_options ();
while (!is_end_of_line[(unsigned char) *input_line_pointer])
++input_line_pointer;
ch = *input_line_pointer;
*input_line_pointer = '\0';
if (strchr (name, ','))
{
/* Generic ".set" directive; use the generic handler. */
*input_line_pointer = ch;
input_line_pointer = name;
s_set (0);
return;
}
if (strcmp (name, "reorder") == 0)
{
if (mips_opts.noreorder)
end_noreorder ();
}
else if (strcmp (name, "noreorder") == 0)
{
if (!mips_opts.noreorder)
start_noreorder ();
}
else if (strcmp (name, "macro") == 0)
mips_opts.warn_about_macros = 0;
else if (strcmp (name, "nomacro") == 0)
{
if (mips_opts.noreorder == 0)
as_bad (_("`noreorder' must be set before `nomacro'"));
mips_opts.warn_about_macros = 1;
}
else if (strcmp (name, "gp=default") == 0)
mips_opts.gp = file_mips_opts.gp;
else if (strcmp (name, "fp=default") == 0)
mips_opts.fp = file_mips_opts.fp;
else if (strcmp (name, "mips0") == 0 || strcmp (name, "arch=default") == 0)
{
mips_opts.isa = file_mips_opts.isa;
mips_opts.arch = file_mips_opts.arch;
mips_opts.gp = file_mips_opts.gp;
mips_opts.fp = file_mips_opts.fp;
}
else if (strcmp (name, "push") == 0)
{
struct mips_option_stack *s;
@ -15205,23 +15190,75 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
free (s);
}
}
else if (strcmp (name, "sym32") == 0)
mips_opts.sym32 = TRUE;
else if (strcmp (name, "nosym32") == 0)
mips_opts.sym32 = FALSE;
else if (strchr (name, ','))
else if (!parse_code_option (name))
as_warn (_("tried to set unrecognized symbol: %s\n"), name);
/* The use of .set [arch|cpu]= historically 'fixes' the width of gp and fp
registers based on what is supported by the arch/cpu. */
if (mips_opts.isa != prev_isa)
{
/* Generic ".set" directive; use the generic handler. */
*input_line_pointer = ch;
input_line_pointer = name;
s_set (0);
return;
switch (mips_opts.isa)
{
case 0:
break;
case ISA_MIPS1:
case ISA_MIPS2:
case ISA_MIPS32:
case ISA_MIPS32R2:
case ISA_MIPS32R3:
case ISA_MIPS32R5:
mips_opts.gp = 32;
mips_opts.fp = 32;
break;
case ISA_MIPS3:
case ISA_MIPS4:
case ISA_MIPS5:
case ISA_MIPS64:
case ISA_MIPS64R2:
case ISA_MIPS64R3:
case ISA_MIPS64R5:
mips_opts.gp = 64;
if (mips_opts.arch == CPU_R5900)
mips_opts.fp = 32;
else
mips_opts.fp = 64;
break;
default:
as_bad (_("unknown ISA level %s"), name + 4);
break;
}
}
mips_check_options (&mips_opts, FALSE);
mips_check_isa_supports_ases ();
*input_line_pointer = ch;
demand_empty_rest_of_line ();
}
/* Handle the .module pseudo-op. */
static void
s_module (int ignore ATTRIBUTE_UNUSED)
{
char *name = input_line_pointer, ch;
while (!is_end_of_line[(unsigned char) *input_line_pointer])
++input_line_pointer;
ch = *input_line_pointer;
*input_line_pointer = '\0';
if (!file_mips_opts_checked)
{
if (!parse_code_option (name))
as_bad (_(".module used with unrecognized symbol: %s\n"), name);
/* Update module level settings from mips_opts. */
file_mips_opts = mips_opts;
}
else
{
as_warn (_("tried to set unrecognized symbol: %s\n"), name);
}
mips_check_isa_supports_ases ();
as_bad (_(".module is not permitted after generating code"));
*input_line_pointer = ch;
demand_empty_rest_of_line ();
}
@ -15268,6 +15305,8 @@ s_cpload (int ignore ATTRIBUTE_UNUSED)
int reg;
int in_shared;
file_mips_check_options ();
/* If we are not generating SVR4 PIC code, or if this is NewABI code,
.cpload is ignored. */
if (mips_pic != SVR4_PIC || HAVE_NEWABI)
@ -15345,6 +15384,8 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
expressionS ex_sym;
int reg1;
file_mips_check_options ();
/* If we are not generating SVR4 PIC code, .cpsetup is ignored.
We also need NewABI support. */
if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
@ -15448,6 +15489,8 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED)
static void
s_cplocal (int ignore ATTRIBUTE_UNUSED)
{
file_mips_check_options ();
/* If we are not generating SVR4 PIC code, or if this is not NewABI code,
.cplocal is ignored. */
if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
@ -15476,6 +15519,8 @@ s_cprestore (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
file_mips_check_options ();
/* If we are not generating SVR4 PIC code, or if this is NewABI code,
.cprestore is ignored. */
if (mips_pic != SVR4_PIC || HAVE_NEWABI)
@ -15523,6 +15568,8 @@ s_cpreturn (int ignore ATTRIBUTE_UNUSED)
{
expressionS ex;
file_mips_check_options ();
/* If we are not generating SVR4 PIC code, .cpreturn is ignored.
We also need NewABI support. */
if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
@ -15757,6 +15804,8 @@ s_cpadd (int ignore ATTRIBUTE_UNUSED)
{
int reg;
file_mips_check_options ();
/* This is ignored when not generating SVR4 PIC code. */
if (mips_pic != SVR4_PIC)
{
@ -17378,7 +17427,7 @@ mips_elf_final_processing (void)
elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_M16;
if (file_ase_micromips)
elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_MICROMIPS;
if (file_ase & ASE_MDMX)
if (file_mips_opts.ase & ASE_MDMX)
elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_MDMX;
/* Set the MIPS ELF ABI flags. */
@ -18356,4 +18405,7 @@ md_mips_end (void)
mips_emit_delays ();
if (cur_proc_ptr)
as_warn (_("missing .end at end of assembly"));
/* Just in case no code was emitted, do the consistency check. */
file_mips_check_options ();
}

View file

@ -693,6 +693,20 @@ Traditional MIPS assemblers do not support this directive.
@node MIPS assembly options
@section Directives to control code generation
@cindex MIPS directives to override command line options
@kindex @code{.module}
The @code{.module} directive allows command line options to be set directly
from assembly. The format of the directive matches the @code{.set}
directive but only those options which are relevant to a whole module are
supported. The effect of a @code{.module} directive is the same as the
corresponding command line option. Where @code{.set} directives support
returning to a default then the @code{.module} directives do not as they
define the defaults.
These module-level directives must appear first in assembly.
Traditional MIPS assemblers do not support this directive.
@cindex MIPS 32-bit microMIPS instruction generation override
@kindex @code{.set insn32}
@kindex @code{.set noinsn32}

View file

@ -1,2 +1,2 @@
Assembler messages:
Warning: -mfp64 used with a 32-bit ABI
.*Assembler messages:
.* Warning: `fp=64' used with a 32-bit ABI

View file

@ -1,2 +1,2 @@
Assembler messages:
Warning: -mfp32 used with a 64-bit ABI
.*Assembler messages:
.*:16: Warning: `fp=32' used with a 64-bit ABI

View file

@ -1,5 +1,5 @@
Assembler messages:
Warning: -mfp32 used with a 64-bit ABI
.*Assembler messages:
.* Warning: `fp=32' used with a 64-bit ABI
.*:92: Warning: macro instruction expanded into multiple instructions in a branch delay slot
.*:96: Warning: macro instruction expanded into multiple instructions in a branch delay slot
.*:100: Warning: macro instruction expanded into multiple instructions in a branch delay slot

View file

@ -442,7 +442,7 @@ mips_arch_create mips64r5 64 mips64r3 { mips32r5 ror } \
mips_arch_create mips16 32 {} {} \
{ -march=mips1 -mips16 } { -mmips:16 }
mips_arch_create micromips 64 mips64r2 {} \
{ -march=mips64 -mmicromips } {}
{ -march=mips64r2 -mmicromips } {}
mips_arch_create r3000 32 mips1 {} \
{ -march=r3000 -mtune=r3000 } { -mmips:3000 }
mips_arch_create r3900 32 mips1 { gpr_ilocks } \
@ -787,7 +787,7 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "relax-swap1-mips2"
run_dump_test "relax-swap2"
run_dump_test_arches "relax-swap3" [mips_arch_list_all]
run_list_test_arches "relax-bc1any" "-mips3d -relax-branch" \
run_list_test_arches "relax-bc1any" "-mips3d -mabi=o64 -relax-branch" \
[mips_arch_list_matching mips64 \
!micromips]
run_list_test_arches "relax-bposge" "-mdsp -relax-branch" \
@ -1200,4 +1200,8 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "attr-gnu-abi-fp-1"
run_dump_test "attr-gnu-abi-msa-1"
run_dump_test "module-override"
run_dump_test "module-defer-warn1"
run_list_test "module-defer-warn2" -32
}

View file

@ -0,0 +1,7 @@
# name: .module deferred warnings
# source: module-defer-warn1.s
# objdump: -p
# as: -32 -march=mips2 -mgp64
.*:.*file format.*elf.*mips.*
private flags = 1.......: .*\[mips2\].*

View file

@ -0,0 +1,2 @@
.module gp=32
addiu $2, $2, 1

View file

@ -0,0 +1,3 @@
.*: Assembler messages:
.*:2: Error: `gp=64' used with a 32-bit processor
.*:2: Error: `fp=64' used with a 32-bit fpu

View file

@ -0,0 +1,2 @@
.module gp=64
addiu $2, $2, 1

View file

@ -0,0 +1,7 @@
# name: .module command line override
# source: module-override.s
# objdump: -p
# as: -32 -march=mips32r2
.*:.*file format.*elf.*mips.*
private flags = 1.......: .*\[mips2\].*

View file

@ -0,0 +1 @@
.module mips2