From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12691 invoked by alias); 20 May 2014 14:07:41 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 12570 invoked by uid 89); 20 May 2014 14:07:39 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mailapp01.imgtec.com Received: from mailapp01.imgtec.com (HELO mailapp01.imgtec.com) (195.59.15.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 20 May 2014 14:07:35 +0000 Received: from KLMAIL01.kl.imgtec.org (unknown [192.168.5.35]) by Websense Email Security Gateway with ESMTPS id 503CCA91AF31C; Tue, 20 May 2014 15:07:27 +0100 (IST) Received: from KLMAIL02.kl.imgtec.org (192.168.5.97) by KLMAIL01.kl.imgtec.org (192.168.5.35) with Microsoft SMTP Server (TLS) id 14.3.181.6; Tue, 20 May 2014 15:07:30 +0100 Received: from LEMAIL01.le.imgtec.org (192.168.152.62) by klmail02.kl.imgtec.org (192.168.5.97) with Microsoft SMTP Server (TLS) id 14.3.181.6; Tue, 20 May 2014 15:07:30 +0100 Received: from LEMAIL01.le.imgtec.org ([fe80::5ae:ee16:f4b9:cda9]) by LEMAIL01.le.imgtec.org ([fe80::5ae:ee16:f4b9:cda9%17]) with mapi id 14.03.0174.001; Tue, 20 May 2014 15:07:29 +0100 From: Matthew Fortune To: Richard Sandiford CC: "binutils@sourceware.org" , Rich Fuhler Subject: [PATCH][MIPS] Implement .module directive Date: Tue, 20 May 2014 14:07:00 -0000 Message-ID: <6D39441BF12EF246A7ABCE6654B02353538578@LEMAIL01.le.imgtec.org> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-IsSubscribed: yes X-SW-Source: 2014-05/txt/msg00179.txt.bz2 Hi Richard, To cut down the patch for FPXX I have extracted the .module implementation. There is one functional change when compared to the previous implementation from the FPXX patch... The code that infers register size information is now moved into the file_mips_check_options function as it needs to apply after any .module arch=3Dxxx or .module mipsxxx directive. I have only added 3 tests for this just to check that error handling is deferred until code is seen and that command line options are overridden. A number of tests in the FPXX patch will also use the .module directive. I think the testsuite, as exists, covers the behaviour of the command line options so that is tested. Personally I don't think it is necessary to cover all the .module options explicitly, what do you think?=20 This patch assumes that the MSA fix has been applied as it moves the logic changed in that patch: http://sourceware.org/ml/binutils/2014-05/msg00175.html Regards, Matthew 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): 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. --- gas/config/tc-mips.c | 602 +++++++++++++++--------= ---- gas/doc/c-mips.texi | 14 + gas/testsuite/gas/mips/mips-gp32-fp64.l | 4 +- gas/testsuite/gas/mips/mips-gp64-fp32-pic.l | 4 +- gas/testsuite/gas/mips/mips-gp64-fp32.l | 4 +- gas/testsuite/gas/mips/mips.exp | 8 +- gas/testsuite/gas/mips/module-defer-warn1.d | 7 + gas/testsuite/gas/mips/module-defer-warn1.s | 2 + gas/testsuite/gas/mips/module-defer-warn2.l | 3 + gas/testsuite/gas/mips/module-defer-warn2.s | 2 + gas/testsuite/gas/mips/module-override.d | 7 + gas/testsuite/gas/mips/module-override.s | 1 + 12 files changed, 374 insertions(+), 284 deletions(-) create mode 100644 gas/testsuite/gas/mips/module-defer-warn1.d create mode 100644 gas/testsuite/gas/mips/module-defer-warn1.s create mode 100644 gas/testsuite/gas/mips/module-defer-warn2.l create mode 100644 gas/testsuite/gas/mips/module-defer-warn2.s create mode 100644 gas/testsuite/gas/mips/module-override.d create mode 100644 gas/testsuite/gas/mips/module-override.s diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 9ae6096..0f89bb9 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -259,6 +259,9 @@ struct mips_set_options bfd_boolean single_float; }; =20 +/* Specifies whether module level options have been checked yet. */ +static bfd_boolean file_mips_opts_checked =3D FALSE; + /* True if -mnan=3D2008, false if -mnan=3Dlegacy. */ static bfd_boolean mips_flag_nan2008 =3D FALSE; =20 @@ -286,10 +289,6 @@ static struct mips_set_options mips_opts =3D /* soft_float */ FALSE, /* single_float */ FALSE }; =20 -/* 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; =20 @@ -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); @@ -1692,6 +1692,7 @@ static const pseudo_typeS mips_pseudo_table[] =3D {"cpadd", s_cpadd, 0}, {"insn", s_insn, 0}, {"nan", s_nan, 0}, + {"module", s_module, 0}, =20 /* Relatively generic pseudo-ops that happen to be used on MIPS chips. */ @@ -1979,14 +1980,15 @@ mips_check_isa_supports_ases (void) that were affected. */ =20 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; =20 mask =3D mips_ase_mask (ase->flags); - mips_opts.ase &=3D ~mask; + opts->ase &=3D ~mask; if (enabled_p) - mips_opts.ase |=3D ase->flags; + opts->ase |=3D ase->flags; return mask; } =20 @@ -3631,6 +3633,139 @@ md_begin (void) init_vr4120_conflicts (); } =20 +/* 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 =3D=3D 64 && !ISA_HAS_64BIT_REGS (opts->isa)) + as_bad (_("`gp=3D64' used with a 32-bit processor")); + else if (abi_checks + && opts->gp =3D=3D 32 && ABI_NEEDS_64BIT_REGS (mips_abi)) + as_bad (_("`gp=3D32' used with a 64-bit ABI")); + else if (abi_checks + && opts->gp =3D=3D 64 && ABI_NEEDS_32BIT_REGS (mips_abi)) + as_bad (_("`gp=3D64' 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=3D64' used with a 32-bit fpu")); + else if (abi_checks + && ABI_NEEDS_32BIT_REGS (mips_abi) + && !ISA_HAS_MXHC1 (opts->isa)) + as_warn (_("`fp=3D64' used with a 32-bit ABI")); + break; + case 32: + if (abi_checks + && ABI_NEEDS_64BIT_REGS (mips_abi)) + as_warn (_("`fp=3D32' used with a 64-bit ABI")); + break; + default: + as_bad (_("Unknown size of floating point registers")); + break; + } + + if (opts->micromips =3D=3D 1 && opts->mips16 =3D=3D 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 + or, at the first instruction + or, at the end. */ + +static void +file_mips_check_options (void) +{ + const struct mips_cpu_info *arch_info =3D 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 =3D (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 =3D=3D 64) + /* 64-bit integer registers implies 64-bit float registers. */ + file_mips_opts.fp =3D 64; + else if ((file_mips_opts.ase & FP64_ASES) + && ISA_HAS_64BIT_FPRS (file_mips_opts.isa)) + /* -mips3d and -mdmx imply 64-bit float registers, if possible. */ + file_mips_opts.fp =3D 64; + else + /* 32-bit float registers. */ + file_mips_opts.fp =3D 32; + } + + arch_info =3D 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 =3D=3D NO_ABI && file_mips_opts.gp =3D=3D 32) + || mips_abi =3D=3D O32_ABI)) + mips_32bitmode =3D 1; + + if (file_mips_opts.isa =3D=3D 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 =3D=3D -1) + file_mips_opts.mips16 =3D (CPU_HAS_MIPS16 (file_mips_opts.arch)) ? 1 := 0; + if (file_mips_opts.micromips =3D=3D -1) + file_mips_opts.micromips =3D (CPU_HAS_MICROMIPS (file_mips_opts.arch)) + ? 1 : 0; + + /* MIPS3D and MDMX require 64-bit FPRs, so -mfp32 should stop those + ASEs from being selected implicitly. */ + if (file_mips_opts.fp !=3D 64) + file_ase_explicit |=3D 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 |=3D (arch_info->ase & ~file_ase_explicit); + + /* Set up the current options. These may change throughout assembly. */ + mips_opts =3D file_mips_opts; + + mips_check_isa_supports_ases (); + mips_check_options (&file_mips_opts, TRUE); + file_mips_opts_checked =3D 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 +3773,8 @@ md_assemble (char *str) bfd_reloc_code_real_type unused_reloc[3] =3D {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED}; =20 + file_mips_check_options (); + imm_expr.X_op =3D O_absent; offset_expr.X_op =3D O_absent; offset_reloc[0] =3D BFD_RELOC_UNUSED; @@ -13483,7 +13620,7 @@ md_parse_option (int c, char *arg) for (i =3D 0; i < ARRAY_SIZE (mips_ases); i++) if (c =3D=3D mips_ases[i].option_on || c =3D=3D mips_ases[i].option_of= f) { - file_ase_explicit |=3D mips_set_ase (&mips_ases[i], + file_ase_explicit |=3D mips_set_ase (&mips_ases[i], &file_mips_opts, c =3D=3D mips_ases[i].option_on); return 1; } @@ -13625,32 +13762,32 @@ md_parse_option (int c, char *arg) break; =20 case OPTION_MICROMIPS: - if (mips_opts.mips16 =3D=3D 1) + if (file_mips_opts.mips16 =3D=3D 1) { as_bad (_("-mmicromips cannot be used with -mips16")); return 0; } - mips_opts.micromips =3D 1; + file_mips_opts.micromips =3D 1; mips_no_prev_insn (); break; =20 case OPTION_NO_MICROMIPS: - mips_opts.micromips =3D 0; + file_mips_opts.micromips =3D 0; mips_no_prev_insn (); break; =20 case OPTION_MIPS16: - if (mips_opts.micromips =3D=3D 1) + if (file_mips_opts.micromips =3D=3D 1) { as_bad (_("-mips16 cannot be used with -micromips")); return 0; } - mips_opts.mips16 =3D 1; + file_mips_opts.mips16 =3D 1; mips_no_prev_insn (); break; =20 case OPTION_NO_MIPS16: - mips_opts.mips16 =3D 0; + file_mips_opts.mips16 =3D 0; mips_no_prev_insn (); break; =20 @@ -13719,11 +13856,11 @@ md_parse_option (int c, char *arg) break; =20 case OPTION_INSN32: - mips_opts.insn32 =3D TRUE; + file_mips_opts.insn32 =3D TRUE; break; =20 case OPTION_NO_INSN32: - mips_opts.insn32 =3D FALSE; + file_mips_opts.insn32 =3D FALSE; break; =20 case OPTION_MSHARED: @@ -13735,11 +13872,11 @@ md_parse_option (int c, char *arg) break; =20 case OPTION_MSYM32: - mips_opts.sym32 =3D TRUE; + file_mips_opts.sym32 =3D TRUE; break; =20 case OPTION_MNO_SYM32: - mips_opts.sym32 =3D FALSE; + file_mips_opts.sym32 =3D FALSE; break; =20 /* When generating ELF code, we permit -KPIC and -call_shared to @@ -13892,22 +14029,7 @@ md_parse_option (int c, char *arg) return 1; } =20 -/* 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 !=3D 0) - { - file_mips_opts.arch =3D info->cpu; - mips_opts.arch =3D info->cpu; - mips_opts.isa =3D info->isa; - } -} - - -/* Likewise for tuning. */ +/* Set up globals to tune for the ISA or processor described by INFO. */ =20 static void mips_set_tune (const struct mips_cpu_info *info) @@ -13934,7 +14056,7 @@ mips_after_parse_args (void) if (mips_abi =3D=3D NO_ABI) mips_abi =3D MIPS_DEFAULT_ABI; =20 - /* 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 +14094,14 @@ mips_after_parse_args (void) as_bad (_("-march=3D%s is not compatible with the selected ABI"), arch_info->name); =20 - mips_set_architecture (arch_info); + file_mips_opts.arch =3D arch_info->cpu; + file_mips_opts.isa =3D arch_info->isa; + + /* Set up initial mips_opts state. */ + mips_opts =3D file_mips_opts; + + /* The register size inference code is now placed in + file_mips_check_options. */ =20 /* Optimize for file_mips_opts.arch, unless -mtune selects a different processor. */ @@ -13984,103 +14113,6 @@ mips_after_parse_args (void) else mips_set_tune (tune_info); =20 - if (file_mips_opts.gp >=3D 0) - { - /* The user specified the size of the integer registers. Make sure - it agrees with the ABI and ISA. */ - if (file_mips_opts.gp =3D=3D 64 && !ISA_HAS_64BIT_REGS (mips_opts.is= a)) - as_bad (_("-mgp64 used with a 32-bit processor")); - else if (file_mips_opts.gp =3D=3D 32 && ABI_NEEDS_64BIT_REGS (mips_a= bi)) - as_bad (_("-mgp32 used with a 64-bit ABI")); - else if (file_mips_opts.gp =3D=3D 64 && ABI_NEEDS_32BIT_REGS (mips_a= bi)) - 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 =3D (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 =3D=3D 64) - /* 64-bit integer registers implies 64-bit float registers. */ - file_mips_opts.fp =3D 64; - else if ((mips_opts.ase & FP64_ASES) - && ISA_HAS_64BIT_FPRS (mips_opts.isa)) - /* -mips3d and -mdmx imply 64-bit float registers, if possible. */ - file_mips_opts.fp =3D 64; - else - /* 32-bit float registers. */ - file_mips_opts.fp =3D 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 =3D=3D NO_ABI && file_mips_opts.gp =3D=3D 32) - || mips_abi =3D=3D O32_ABI)) - mips_32bitmode =3D 1; - - if (mips_opts.isa =3D=3D 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 =3D=3D -1) - mips_opts.mips16 =3D (CPU_HAS_MIPS16 (file_mips_opts.arch)) ? 1 : 0; - if (mips_opts.micromips =3D=3D -1) - mips_opts.micromips =3D (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 !=3D 64) - file_ase_explicit |=3D 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 |=3D (arch_info->ase & ~file_ase_explicit); - - file_mips_opts.isa =3D mips_opts.isa; - file_mips_opts.ase =3D mips_opts.ase; - mips_opts.gp =3D file_mips_opts.gp; - mips_opts.fp =3D file_mips_opts.fp; - mips_opts.soft_float =3D file_mips_opts.soft_float; - mips_opts.single_float =3D file_mips_opts.single_float; - - mips_check_isa_supports_ases (); - if (mips_flag_mdebug < 0) mips_flag_mdebug =3D 0; } @@ -14968,30 +15000,11 @@ struct mips_option_stack =20 static struct mips_option_stack *mips_opts_stack; =20 -/* Handle the .set pseudo-op. */ - -static void -s_mipsset (int x ATTRIBUTE_UNUSED) +static bfd_boolean +parse_code_option (char * name) { - char *name =3D input_line_pointer, ch; const struct mips_ase *ase; - - while (!is_end_of_line[(unsigned char) *input_line_pointer]) - ++input_line_pointer; - ch =3D *input_line_pointer; - *input_line_pointer =3D '\0'; - - if (strcmp (name, "reorder") =3D=3D 0) - { - if (mips_opts.noreorder) - end_noreorder (); - } - else if (strcmp (name, "noreorder") =3D=3D 0) - { - if (!mips_opts.noreorder) - start_noreorder (); - } - else if (strncmp (name, "at=3D", 3) =3D=3D 0) + if (strncmp (name, "at=3D", 3) =3D=3D 0) { char *s =3D name + 3; =20 @@ -14999,61 +15012,25 @@ s_mipsset (int x ATTRIBUTE_UNUSED) as_bad (_("unrecognized register name `%s'"), s); } else if (strcmp (name, "at") =3D=3D 0) - { - mips_opts.at =3D ATREG; - } + mips_opts.at =3D ATREG; else if (strcmp (name, "noat") =3D=3D 0) - { - mips_opts.at =3D ZERO; - } - else if (strcmp (name, "macro") =3D=3D 0) - { - mips_opts.warn_about_macros =3D 0; - } - else if (strcmp (name, "nomacro") =3D=3D 0) - { - if (mips_opts.noreorder =3D=3D 0) - as_bad (_("`noreorder' must be set before `nomacro'")); - mips_opts.warn_about_macros =3D 1; - } + mips_opts.at =3D ZERO; else if (strcmp (name, "move") =3D=3D 0 || strcmp (name, "novolatile") = =3D=3D 0) - { - mips_opts.nomove =3D 0; - } + mips_opts.nomove =3D 0; else if (strcmp (name, "nomove") =3D=3D 0 || strcmp (name, "volatile") = =3D=3D 0) - { - mips_opts.nomove =3D 1; - } + mips_opts.nomove =3D 1; else if (strcmp (name, "bopt") =3D=3D 0) - { - mips_opts.nobopt =3D 0; - } + mips_opts.nobopt =3D 0; else if (strcmp (name, "nobopt") =3D=3D 0) - { - mips_opts.nobopt =3D 1; - } - else if (strcmp (name, "gp=3Ddefault") =3D=3D 0) - mips_opts.gp =3D file_mips_opts.gp; + mips_opts.nobopt =3D 1; else if (strcmp (name, "gp=3D32") =3D=3D 0) mips_opts.gp =3D 32; else if (strcmp (name, "gp=3D64") =3D=3D 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 =3D 64; - } - else if (strcmp (name, "fp=3Ddefault") =3D=3D 0) - mips_opts.fp =3D file_mips_opts.fp; + mips_opts.gp =3D 64; else if (strcmp (name, "fp=3D32") =3D=3D 0) mips_opts.fp =3D 32; else if (strcmp (name, "fp=3D64") =3D=3D 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 =3D 64; - } + mips_opts.fp =3D 64; else if (strcmp (name, "softfloat") =3D=3D 0) mips_opts.soft_float =3D 1; else if (strcmp (name, "hardfloat") =3D=3D 0) @@ -15064,45 +15041,29 @@ s_mipsset (int x ATTRIBUTE_UNUSED) mips_opts.single_float =3D 0; else if (strcmp (name, "mips16") =3D=3D 0 || strcmp (name, "MIPS-16") =3D=3D 0) - { - if (mips_opts.micromips =3D=3D 1) - as_fatal (_("`mips16' cannot be used with `micromips'")); - mips_opts.mips16 =3D 1; - } + mips_opts.mips16 =3D 1; else if (strcmp (name, "nomips16") =3D=3D 0 || strcmp (name, "noMIPS-16") =3D=3D 0) mips_opts.mips16 =3D 0; else if (strcmp (name, "micromips") =3D=3D 0) - { - if (mips_opts.mips16 =3D=3D 1) - as_fatal (_("`micromips' cannot be used with `mips16'")); - mips_opts.micromips =3D 1; - } + mips_opts.micromips =3D 1; else if (strcmp (name, "nomicromips") =3D=3D 0) mips_opts.micromips =3D 0; else if (name[0] =3D=3D 'n' && name[1] =3D=3D 'o' && (ase =3D mips_lookup_ase (name + 2))) - mips_set_ase (ase, FALSE); + mips_set_ase (ase, &mips_opts, FALSE); else if ((ase =3D mips_lookup_ase (name))) - mips_set_ase (ase, TRUE); + mips_set_ase (ase, &mips_opts, TRUE); else if (strncmp (name, "mips", 4) =3D=3D 0 || strncmp (name, "arch=3D",= 5) =3D=3D 0) { - int reset =3D 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") =3D=3D 0 || strcmp (name, "arch=3Ddefault= ") =3D=3D 0) - { - reset =3D 1; - mips_opts.isa =3D file_mips_opts.isa; - mips_opts.arch =3D file_mips_opts.arch; - } - else if (strncmp (name, "arch=3D", 5) =3D=3D 0) + if (strncmp (name, "arch=3D", 5) =3D=3D 0) { const struct mips_cpu_info *p; =20 - p =3D mips_parse_cpu("internal use", name + 5); + p =3D mips_parse_cpu ("internal use", name + 5); if (!p) as_bad (_("unknown architecture %s"), name + 5); else @@ -15115,7 +15076,7 @@ s_mipsset (int x ATTRIBUTE_UNUSED) { const struct mips_cpu_info *p; =20 - p =3D mips_parse_cpu("internal use", name); + p =3D mips_parse_cpu ("internal use", name); if (!p) as_bad (_("unknown ISA level %s"), name + 4); else @@ -15126,46 +15087,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 =3D 32; - mips_opts.fp =3D 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 =3D 64; - if (mips_opts.arch =3D=3D CPU_R5900) - { - mips_opts.fp =3D 32; - } - else - { - mips_opts.fp =3D 64; - } - break; - default: - as_bad (_("unknown ISA level %s"), name + 4); - break; - } - if (reset) - { - mips_opts.gp =3D file_mips_opts.gp; - mips_opts.fp =3D file_mips_opts.fp; - } } else if (strcmp (name, "autoextend") =3D=3D 0) mips_opts.noautoextend =3D 0; @@ -15175,6 +15096,68 @@ s_mipsset (int x ATTRIBUTE_UNUSED) mips_opts.insn32 =3D TRUE; else if (strcmp (name, "noinsn32") =3D=3D 0) mips_opts.insn32 =3D FALSE; + else if (strcmp (name, "sym32") =3D=3D 0) + mips_opts.sym32 =3D TRUE; + else if (strcmp (name, "nosym32") =3D=3D 0) + mips_opts.sym32 =3D FALSE; + else + return FALSE; + return TRUE; +} + +/* Handle the .set pseudo-op. */ + +static void +s_mipsset (int x ATTRIBUTE_UNUSED) +{ + char *name =3D input_line_pointer, ch; + int prev_isa =3D mips_opts.isa; + + file_mips_check_options (); + + while (!is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + ch =3D *input_line_pointer; + *input_line_pointer =3D '\0'; + + if (strchr (name, ',')) + { + /* Generic ".set" directive; use the generic handler. */ + *input_line_pointer =3D ch; + input_line_pointer =3D name; + s_set (0); + return; + } + + if (strcmp (name, "reorder") =3D=3D 0) + { + if (mips_opts.noreorder) + end_noreorder (); + } + else if (strcmp (name, "noreorder") =3D=3D 0) + { + if (!mips_opts.noreorder) + start_noreorder (); + } + else if (strcmp (name, "macro") =3D=3D 0) + mips_opts.warn_about_macros =3D 0; + else if (strcmp (name, "nomacro") =3D=3D 0) + { + if (mips_opts.noreorder =3D=3D 0) + as_bad (_("`noreorder' must be set before `nomacro'")); + mips_opts.warn_about_macros =3D 1; + } + else if (strcmp (name, "gp=3Ddefault") =3D=3D 0) + mips_opts.gp =3D file_mips_opts.gp; + else if (strcmp (name, "fp=3Ddefault") =3D=3D 0) + mips_opts.fp =3D file_mips_opts.fp; + else if (strcmp (name, "mips0") =3D=3D 0 || strcmp (name, "arch=3Ddefaul= t") =3D=3D 0) + { + mips_opts.isa =3D file_mips_opts.isa; + mips_opts.arch =3D file_mips_opts.arch; + mips_opts.gp =3D file_mips_opts.gp; + mips_opts.fp =3D file_mips_opts.fp; + } else if (strcmp (name, "push") =3D=3D 0) { struct mips_option_stack *s; @@ -15205,23 +15188,75 @@ s_mipsset (int x ATTRIBUTE_UNUSED) free (s); } } - else if (strcmp (name, "sym32") =3D=3D 0) - mips_opts.sym32 =3D TRUE; - else if (strcmp (name, "nosym32") =3D=3D 0) - mips_opts.sym32 =3D 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]=3D historically 'fixes' the width of gp an= d fp + registers based on what is supported by the arch/cpu. */ + if (mips_opts.isa !=3D prev_isa) { - /* Generic ".set" directive; use the generic handler. */ - *input_line_pointer =3D ch; - input_line_pointer =3D 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 =3D 32; + mips_opts.fp =3D 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 =3D 64; + if (mips_opts.arch =3D=3D CPU_R5900) + mips_opts.fp =3D 32; + else + mips_opts.fp =3D 64; + break; + default: + as_bad (_("unknown ISA level %s"), name + 4); + break; + } } - else + + mips_check_options (&mips_opts, FALSE); + + mips_check_isa_supports_ases (); + *input_line_pointer =3D ch; + demand_empty_rest_of_line (); +} + +/* Handle the .module pseudo-op. */ + +static void +s_module (int ignore ATTRIBUTE_UNUSED) +{ + char *name =3D input_line_pointer, ch; + + while (!is_end_of_line[(unsigned char) *input_line_pointer]) + ++input_line_pointer; + ch =3D *input_line_pointer; + *input_line_pointer =3D '\0'; + + if (!file_mips_opts_checked) { - as_warn (_("tried to set unrecognized symbol: %s\n"), name); + 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 =3D mips_opts; } - mips_check_isa_supports_ases (); + else + as_bad (_(".module is not permitted after generating code")); + *input_line_pointer =3D ch; demand_empty_rest_of_line (); } @@ -15268,6 +15303,8 @@ s_cpload (int ignore ATTRIBUTE_UNUSED) int reg; int in_shared; =20 + file_mips_check_options (); + /* If we are not generating SVR4 PIC code, or if this is NewABI code, .cpload is ignored. */ if (mips_pic !=3D SVR4_PIC || HAVE_NEWABI) @@ -15345,6 +15382,8 @@ s_cpsetup (int ignore ATTRIBUTE_UNUSED) expressionS ex_sym; int reg1; =20 + file_mips_check_options (); + /* If we are not generating SVR4 PIC code, .cpsetup is ignored. We also need NewABI support. */ if (mips_pic !=3D SVR4_PIC || ! HAVE_NEWABI) @@ -15448,6 +15487,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 !=3D SVR4_PIC || ! HAVE_NEWABI) @@ -15476,6 +15517,8 @@ s_cprestore (int ignore ATTRIBUTE_UNUSED) { expressionS ex; =20 + file_mips_check_options (); + /* If we are not generating SVR4 PIC code, or if this is NewABI code, .cprestore is ignored. */ if (mips_pic !=3D SVR4_PIC || HAVE_NEWABI) @@ -15523,6 +15566,8 @@ s_cpreturn (int ignore ATTRIBUTE_UNUSED) { expressionS ex; =20 + file_mips_check_options (); + /* If we are not generating SVR4 PIC code, .cpreturn is ignored. We also need NewABI support. */ if (mips_pic !=3D SVR4_PIC || ! HAVE_NEWABI) @@ -15757,6 +15802,8 @@ s_cpadd (int ignore ATTRIBUTE_UNUSED) { int reg; =20 + file_mips_check_options (); + /* This is ignored when not generating SVR4 PIC code. */ if (mips_pic !=3D SVR4_PIC) { @@ -17378,7 +17425,7 @@ mips_elf_final_processing (void) elf_elfheader (stdoutput)->e_flags |=3D EF_MIPS_ARCH_ASE_M16; if (file_ase_micromips) elf_elfheader (stdoutput)->e_flags |=3D EF_MIPS_ARCH_ASE_MICROMIPS; - if (file_ase & ASE_MDMX) + if (file_mips_opts.ase & ASE_MDMX) elf_elfheader (stdoutput)->e_flags |=3D EF_MIPS_ARCH_ASE_MDMX; =20 /* Set the MIPS ELF ABI flags. */ @@ -18356,4 +18403,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 (); } diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi index 2165c20..d2795e7 100644 --- a/gas/doc/c-mips.texi +++ b/gas/doc/c-mips.texi @@ -693,6 +693,20 @@ Traditional MIPS assemblers do not support this direct= ive. @node MIPS assembly options @section Directives to control code generation =20 +@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} diff --git a/gas/testsuite/gas/mips/mips-gp32-fp64.l b/gas/testsuite/gas/mi= ps/mips-gp32-fp64.l index de3f3b0..82b7b17 100644 --- a/gas/testsuite/gas/mips/mips-gp32-fp64.l +++ b/gas/testsuite/gas/mips/mips-gp32-fp64.l @@ -1,2 +1,2 @@ -Assembler messages: -Warning: -mfp64 used with a 32-bit ABI +.*Assembler messages: +.* Warning: `fp=3D64' used with a 32-bit ABI diff --git a/gas/testsuite/gas/mips/mips-gp64-fp32-pic.l b/gas/testsuite/ga= s/mips/mips-gp64-fp32-pic.l index 2d37303..a02481a 100644 --- a/gas/testsuite/gas/mips/mips-gp64-fp32-pic.l +++ b/gas/testsuite/gas/mips/mips-gp64-fp32-pic.l @@ -1,2 +1,2 @@ -Assembler messages: -Warning: -mfp32 used with a 64-bit ABI +.*Assembler messages: +.*:16: Warning: `fp=3D32' used with a 64-bit ABI diff --git a/gas/testsuite/gas/mips/mips-gp64-fp32.l b/gas/testsuite/gas/mi= ps/mips-gp64-fp32.l index e72f085..5fd9e34 100644 --- a/gas/testsuite/gas/mips/mips-gp64-fp32.l +++ b/gas/testsuite/gas/mips/mips-gp64-fp32.l @@ -1,5 +1,5 @@ -Assembler messages: -Warning: -mfp32 used with a 64-bit ABI +.*Assembler messages: +.* Warning: `fp=3D32' 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 diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.= exp index 7ccbed5..aaa9c4c 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -442,7 +442,7 @@ mips_arch_create mips64r5 64 mips64r3 { mips32r5 ror } \ mips_arch_create mips16 32 {} {} \ { -march=3Dmips1 -mips16 } { -mmips:16 } mips_arch_create micromips 64 mips64r2 {} \ - { -march=3Dmips64 -mmicromips } {} + { -march=3Dmips64r2 -mmicromips } {} mips_arch_create r3000 32 mips1 {} \ { -march=3Dr3000 -mtune=3Dr3000 } { -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 -64 -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*] } { =20 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 } diff --git a/gas/testsuite/gas/mips/module-defer-warn1.d b/gas/testsuite/ga= s/mips/module-defer-warn1.d new file mode 100644 index 0000000..d5ee70e --- /dev/null +++ b/gas/testsuite/gas/mips/module-defer-warn1.d @@ -0,0 +1,7 @@ +# name: .module deferred warnings +# source: module-defer-warn1.s +# objdump: -p +# as: -32 -march=3Dmips2 -mgp64 + +.*:.*file format.*elf.*mips.* +private flags =3D 1.......: .*\[mips2\].* diff --git a/gas/testsuite/gas/mips/module-defer-warn1.s b/gas/testsuite/ga= s/mips/module-defer-warn1.s new file mode 100644 index 0000000..d9cbf39 --- /dev/null +++ b/gas/testsuite/gas/mips/module-defer-warn1.s @@ -0,0 +1,2 @@ +.module gp=3D32 +addiu $2, $2, 1 diff --git a/gas/testsuite/gas/mips/module-defer-warn2.l b/gas/testsuite/ga= s/mips/module-defer-warn2.l new file mode 100644 index 0000000..f03ad48 --- /dev/null +++ b/gas/testsuite/gas/mips/module-defer-warn2.l @@ -0,0 +1,3 @@ +.*: Assembler messages: +.*:2: Error: `gp=3D64' used with a 32-bit processor +.*:2: Error: `fp=3D64' used with a 32-bit fpu diff --git a/gas/testsuite/gas/mips/module-defer-warn2.s b/gas/testsuite/ga= s/mips/module-defer-warn2.s new file mode 100644 index 0000000..f7353e5 --- /dev/null +++ b/gas/testsuite/gas/mips/module-defer-warn2.s @@ -0,0 +1,2 @@ +.module gp=3D64 +addiu $2, $2, 1 diff --git a/gas/testsuite/gas/mips/module-override.d b/gas/testsuite/gas/m= ips/module-override.d new file mode 100644 index 0000000..0305b02 --- /dev/null +++ b/gas/testsuite/gas/mips/module-override.d @@ -0,0 +1,7 @@ +# name: .module command line override +# source: module-override.s +# objdump: -p +# as: -32 -march=3Dmips32r2 + +.*:.*file format.*elf.*mips.* +private flags =3D 1.......: .*\[mips2\].* diff --git a/gas/testsuite/gas/mips/module-override.s b/gas/testsuite/gas/m= ips/module-override.s new file mode 100644 index 0000000..05f4a17 --- /dev/null +++ b/gas/testsuite/gas/mips/module-override.s @@ -0,0 +1 @@ +.module mips2 --=20 1.7.1