From ef2e4d86d6823ab027adcbe57ba3ffaf38a550c2 Mon Sep 17 00:00:00 2001 From: Chao-ying Fu Date: Tue, 6 Sep 2005 18:53:03 +0000 Subject: [PATCH] * config/tc-mips.c (mips_set_options): Add ase_mt for MT instructions. (mips_opts): Add -1 to initialize ase_mt. (file_ase_mt): New variable for -mmt. (CPU_HAS_MT): New define. (validate_mips_insn): Add supports for +t, +T, !, $, *, &, g operand formats. (mips_ip): Check ase_mt to enable MT instructions. Handle !, $, *, &, +T, +t, g operand formats. For "mftc1", "mfthc1", "cftc1", "mttc1", "mtthc1", "cttc1", we allow odd float registers. (OPTION_MT, OPTION_NO_MT): New define. (OPTION_COMPAT_ARCH_BASE): Change because of inserting MT define. (md_parse_option): Parse OPTION_MT and OPTION_NO_MT. (mips_after_parse_args): Set ase_mt based on CPU. (s_mipsset): Handle ".set mt" and ".set nomt". (mips_elf_final_processing): Remind of adding new flag for MT ASE. (md_show_usage): Show usage of -mmt and -mno-mt. * doc/as.texinfo: Document -mmt and -mno-mt options. * doc/c-mips.texi: Likewise, and document ".set mt" and ".set nomt" directives. --- gas/ChangeLog | 23 +++++++++ gas/config/tc-mips.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++-- gas/doc/as.texinfo | 7 +++ gas/doc/c-mips.texi | 14 ++++++ 4 files changed, 179 insertions(+), 3 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 7e37abc..55fff2e 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,26 @@ +2005-09-06 Chao-ying Fu + + * config/tc-mips.c (mips_set_options): Add ase_mt for MT instructions. + (mips_opts): Add -1 to initialize ase_mt. + (file_ase_mt): New variable for -mmt. + (CPU_HAS_MT): New define. + (validate_mips_insn): Add supports for +t, +T, !, $, *, &, g operand + formats. + (mips_ip): Check ase_mt to enable MT instructions. + Handle !, $, *, &, +T, +t, g operand formats. + For "mftc1", "mfthc1", "cftc1", "mttc1", "mtthc1", "cttc1", we allow + odd float registers. + (OPTION_MT, OPTION_NO_MT): New define. + (OPTION_COMPAT_ARCH_BASE): Change because of inserting MT define. + (md_parse_option): Parse OPTION_MT and OPTION_NO_MT. + (mips_after_parse_args): Set ase_mt based on CPU. + (s_mipsset): Handle ".set mt" and ".set nomt". + (mips_elf_final_processing): Remind of adding new flag for MT ASE. + (md_show_usage): Show usage of -mmt and -mno-mt. + * doc/as.texinfo: Document -mmt and -mno-mt options. + * doc/c-mips.texi: Likewise, and document ".set mt" and ".set nomt" + directives. + 2005-09-06 Paul Brook * config/tc-arm.c (arm_it): Add relax field. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index a2879b1..db1fec5 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -194,6 +194,7 @@ struct mips_set_options int ase_mips3d; int ase_mdmx; int ase_dsp; + int ase_mt; /* Whether we are assembling for the mips16 processor. 0 if we are not, 1 if we are, and -1 if the value has not been initialized. Changed by `.set mips16' and `.set nomips16', and the -mips16 and @@ -244,7 +245,7 @@ static int file_mips_fp32 = -1; static struct mips_set_options mips_opts = { - ISA_UNKNOWN, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, CPU_UNKNOWN, FALSE + ISA_UNKNOWN, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, CPU_UNKNOWN, FALSE }; /* These variables are filled in with the masks of registers used. @@ -272,6 +273,10 @@ static int file_ase_mdmx; command line (e.g., by -march). */ static int file_ase_dsp; +/* True if -mmt was passed or implied by arguments passed on the + command line (e.g., by -march). */ +static int file_ase_mt; + /* The argument of the -march= flag. The architecture we are assembling. */ static int file_mips_arch = CPU_UNKNOWN; static const char *mips_arch_string; @@ -374,6 +379,10 @@ static int mips_32bitmode = 0; #define CPU_HAS_DSP(cpu) (FALSE \ ) +/* Return true if the given CPU supports the MT ASE. */ +#define CPU_HAS_MT(cpu) (FALSE \ + ) + /* True if CPU has a dror instruction. */ #define CPU_HAS_DROR(CPU) ((CPU) == CPU_VR5400 || (CPU) == CPU_VR5500) @@ -7778,6 +7787,9 @@ validate_mips_insn (const struct mips_opcode *opc) case 'G': USE_BITS (OP_MASK_EXTMSBD, OP_SH_EXTMSBD); break; case 'H': USE_BITS (OP_MASK_EXTMSBD, OP_SH_EXTMSBD); break; case 'I': break; + case 't': USE_BITS (OP_MASK_RT, OP_SH_RT); break; + case 'T': USE_BITS (OP_MASK_RT, OP_SH_RT); + USE_BITS (OP_MASK_SEL, OP_SH_SEL); break; default: as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"), c, opc->name, opc->args); @@ -7850,6 +7862,11 @@ validate_mips_insn (const struct mips_opcode *opc) case '\'': USE_BITS (OP_MASK_RDDSP, OP_SH_RDDSP); break; case ':': USE_BITS (OP_MASK_DSPSFT_7, OP_SH_DSPSFT_7);break; case '@': USE_BITS (OP_MASK_IMM10, OP_SH_IMM10); break; + case '!': USE_BITS (OP_MASK_MT_U, OP_SH_MT_U); break; + case '$': USE_BITS (OP_MASK_MT_H, OP_SH_MT_H); break; + case '*': USE_BITS (OP_MASK_MTACC_T, OP_SH_MTACC_T); break; + case '&': USE_BITS (OP_MASK_MTACC_D, OP_SH_MTACC_D); break; + case 'g': USE_BITS (OP_MASK_RD, OP_SH_RD); break; default: as_bad (_("internal: bad mips opcode (unknown operand type `%c'): %s %s"), c, opc->name, opc->args); @@ -7948,6 +7965,7 @@ mips_ip (char *str, struct mips_cl_insn *ip) | (file_ase_mips16 ? INSN_MIPS16 : 0) | (mips_opts.ase_mdmx ? INSN_MDMX : 0) | (mips_opts.ase_dsp ? INSN_DSP : 0) + | (mips_opts.ase_mt ? INSN_MT : 0) | (mips_opts.ase_mips3d ? INSN_MIPS3D : 0)), mips_opts.arch)) ok = TRUE; @@ -8169,6 +8187,60 @@ mips_ip (char *str, struct mips_cl_insn *ip) s = expr_end; continue; + case '!': /* mt 1-bit unsigned immediate in bit 5 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_MT_U) + { + as_warn (_("MT immediate not in range 0..%d (%lu)"), + OP_MASK_MT_U, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_MT_U; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_MT_U; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '$': /* mt 1-bit unsigned immediate in bit 4 */ + my_getExpression (&imm_expr, s); + check_absolute_expr (ip, &imm_expr); + if (imm_expr.X_add_number & ~OP_MASK_MT_H) + { + as_warn (_("MT immediate not in range 0..%d (%lu)"), + OP_MASK_MT_H, (unsigned long) imm_expr.X_add_number); + imm_expr.X_add_number &= OP_MASK_MT_H; + } + ip->insn_opcode |= imm_expr.X_add_number << OP_SH_MT_H; + imm_expr.X_op = O_absent; + s = expr_end; + continue; + + case '*': /* four dsp accumulators in bits 18,19 */ + if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && + s[3] >= '0' && s[3] <= '3') + { + regno = s[3] - '0'; + s += 4; + ip->insn_opcode |= regno << OP_SH_MTACC_T; + continue; + } + else + as_bad (_("Invalid dsp/smartmips acc register")); + break; + + case '&': /* four dsp accumulators in bits 13,14 */ + if (s[0] == '$' && s[1] == 'a' && s[2] == 'c' && + s[3] >= '0' && s[3] <= '3') + { + regno = s[3] - '0'; + s += 4; + ip->insn_opcode |= regno << OP_SH_MTACC_D; + continue; + } + else + as_bad (_("Invalid dsp/smartmips acc register")); + break; + case ',': if (*s++ == *args) continue; @@ -8321,6 +8393,34 @@ do_msbd: s = expr_end; continue; + case 'T': /* Coprocessor register */ + /* +T is for disassembly only; never match. */ + break; + + case 't': /* Coprocessor register number */ + if (s[0] == '$' && ISDIGIT (s[1])) + { + ++s; + regno = 0; + do + { + regno *= 10; + regno += *s - '0'; + ++s; + } + while (ISDIGIT (*s)); + if (regno > 31) + as_bad (_("Invalid register number (%d)"), regno); + else + { + ip->insn_opcode |= regno << OP_SH_RT; + continue; + } + } + else + as_bad (_("Invalid coprocessor 0 register number")); + break; + default: as_bad (_("internal: bad mips opcode (unknown extension operand type `+%c'): %s %s"), *args, insn->name, insn->args); @@ -8455,6 +8555,7 @@ do_msbd: case 'x': /* ignore register name */ case 'z': /* must be zero register */ case 'U': /* destination register (clo/clz). */ + case 'g': /* coprocessor destination register */ s_reset = s; if (s[0] == '$') { @@ -8579,6 +8680,7 @@ do_msbd: case 'd': case 'G': case 'K': + case 'g': INSERT_OPERAND (RD, *ip, regno); break; case 'U': @@ -8694,7 +8796,13 @@ do_msbd: || strcmp (str, "lwc1") == 0 || strcmp (str, "swc1") == 0 || strcmp (str, "l.s") == 0 - || strcmp (str, "s.s") == 0)) + || strcmp (str, "s.s") == 0 + || strcmp (str, "mftc1") == 0 + || strcmp (str, "mfthc1") == 0 + || strcmp (str, "cftc1") == 0 + || strcmp (str, "mttc1") == 0 + || strcmp (str, "mtthc1") == 0 + || strcmp (str, "cttc1") == 0)) as_warn (_("Float register should be even, was %d"), regno); @@ -10235,9 +10343,13 @@ struct option md_longopts[] = {"mdsp", no_argument, NULL, OPTION_DSP}, #define OPTION_NO_DSP (OPTION_ASE_BASE + 7) {"mno-dsp", no_argument, NULL, OPTION_NO_DSP}, +#define OPTION_MT (OPTION_ASE_BASE + 8) + {"mmt", no_argument, NULL, OPTION_MT}, +#define OPTION_NO_MT (OPTION_ASE_BASE + 9) + {"mno-mt", no_argument, NULL, OPTION_NO_MT}, /* Old-style architecture options. Don't add more of these. */ -#define OPTION_COMPAT_ARCH_BASE (OPTION_ASE_BASE + 8) +#define OPTION_COMPAT_ARCH_BASE (OPTION_ASE_BASE + 10) #define OPTION_M4650 (OPTION_COMPAT_ARCH_BASE + 0) {"m4650", no_argument, NULL, OPTION_M4650}, #define OPTION_NO_M4650 (OPTION_COMPAT_ARCH_BASE + 1) @@ -10497,6 +10609,14 @@ md_parse_option (int c, char *arg) mips_opts.ase_dsp = 0; break; + case OPTION_MT: + mips_opts.ase_mt = 1; + break; + + case OPTION_NO_MT: + mips_opts.ase_mt = 0; + break; + case OPTION_MIPS16: mips_opts.mips16 = 1; mips_no_prev_insn (); @@ -10853,12 +10973,15 @@ mips_after_parse_args (void) mips_opts.ase_mdmx = (CPU_HAS_MDMX (file_mips_arch)) ? 1 : 0; if (mips_opts.ase_dsp == -1) mips_opts.ase_dsp = (CPU_HAS_DSP (file_mips_arch)) ? 1 : 0; + if (mips_opts.ase_mt == -1) + mips_opts.ase_mt = (CPU_HAS_MT (file_mips_arch)) ? 1 : 0; file_mips_isa = mips_opts.isa; file_ase_mips16 = mips_opts.mips16; file_ase_mips3d = mips_opts.ase_mips3d; file_ase_mdmx = mips_opts.ase_mdmx; file_ase_dsp = mips_opts.ase_dsp; + file_ase_mt = mips_opts.ase_mt; mips_opts.gp32 = file_mips_gp32; mips_opts.fp32 = file_mips_fp32; @@ -11800,6 +11923,10 @@ s_mipsset (int x ATTRIBUTE_UNUSED) mips_opts.ase_dsp = 1; else if (strcmp (name, "nodsp") == 0) mips_opts.ase_dsp = 0; + else if (strcmp (name, "mt") == 0) + mips_opts.ase_mt = 1; + else if (strcmp (name, "nomt") == 0) + mips_opts.ase_mt = 0; else if (strncmp (name, "mips", 4) == 0 || strncmp (name, "arch=", 5) == 0) { int reset = 0; @@ -13536,6 +13663,8 @@ mips_elf_final_processing (void) /* Set MIPS ELF flags for ASEs. */ /* We may need to define a new flag for DSP ASE, and set this flag when file_ase_dsp is true. */ + /* We may need to define a new flag for MT ASE, and set this flag when + file_ase_mt is true. */ if (file_ase_mips16) elf_elfheader (stdoutput)->e_flags |= EF_MIPS_ARCH_ASE_M16; #if 0 /* XXX FIXME */ @@ -14243,6 +14372,9 @@ MIPS options:\n\ -mdsp generate DSP instructions\n\ -mno-dsp do not generate DSP instructions\n")); fprintf (stream, _("\ +-mmt generate MT instructions\n\ +-mno-mt do not generate MT instructions\n")); + fprintf (stream, _("\ -mfix-vr4120 work around certain VR4120 errata\n\ -mfix-vr4130 work around VR4130 mflo/mfhi errata\n\ -mgp32 use 32-bit GPRs, regardless of the chosen ISA\n\ diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index a68a35c..0721631 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -368,6 +368,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}. [@b{-mips16}] [@b{-no-mips16}] [@b{-mips3d}] [@b{-no-mips3d}] [@b{-mdmx}] [@b{-no-mdmx}] + [@b{-mmt}] [@b{-mno-mt}] [@b{-mdebug}] [@b{-no-mdebug}] [@b{-mpdr}] [@b{-mno-pdr}] @end ifset @@ -1000,6 +1001,12 @@ Generate code for the MDMX Application Specific Extension. This tells the assembler to accept MDMX instructions. @samp{-no-mdmx} turns off this option. +@item -mmt +@itemx -mno-mt +Generate code for the MT Application Specific Extension. +This tells the assembler to accept MT instructions. +@samp{-mno-mt} turns off this option. + @item --construct-floats @itemx --no-construct-floats The @samp{--no-construct-floats} option disables the construction of diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi index 97469fe..40be0fb 100644 --- a/gas/doc/c-mips.texi +++ b/gas/doc/c-mips.texi @@ -118,6 +118,12 @@ Generate code for the MDMX Application Specific Extension. This tells the assembler to accept MDMX instructions. @samp{-no-mdmx} turns off this option. +@item -mmt +@itemx -mno-mt +Generate code for the MT Application Specific Extension. +This tells the assembler to accept MT instructions. +@samp{-mno-mt} turns off this option. + @item -mfix7000 @itemx -mno-fix7000 Cause nops to be inserted if the read of the destination register @@ -451,4 +457,12 @@ from the MDMX Application Specific Extension from that point on in the assembly. The @code{.set nomdmx} directive prevents MDMX instructions from being accepted. +@cindex MIPS MT instruction generation override +@kindex @code{.set mt} +@kindex @code{.set nomt} +The directive @code{.set mt} makes the assembler accept instructions +from the MT Application Specific Extension from that point on +in the assembly. The @code{.set nomt} directive prevents MT +instructions from being accepted. + Traditional @sc{mips} assemblers do not support these directives. -- 2.7.4