diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 26 | ||||
-rw-r--r-- | gas/config/tc-mips.c | 177 | ||||
-rw-r--r-- | gas/doc/as.texinfo | 7 | ||||
-rw-r--r-- | gas/doc/c-mips.texi | 14 |
4 files changed, 181 insertions, 43 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 5d9cc80..344ee45 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,29 @@ +2013-10-14 Richard Sandiford <rdsandiford@googlemail.com> + Chao-ying Fu <Chao-ying.Fu@imgtec.com> + + * config/tc-mips.c (options): Add OPTION_MSA and OPTION_NO_MSA. + (md_longopts): Add mmsa and mno-msa. + (mips_ases): Add msa. + (RTYPE_MASK): Update. + (RTYPE_MSA): New define. + (OT_REG_ELEMENT): Replace with... + (OT_INTEGER_INDEX, OT_REG_INDEX): ...these new operand types. + (mips_operand_token): Replace reg_element with index. + (mips_parse_argument_token): Treat vector indices as separate tokens. + Handle register indices. + (md_begin): Add MSA register names. + (operand_reg_mask): Handle cases for OP_IMM_INDEX and OP_REG_INDEX. + (convert_reg_type): Handle cases for OP_REG_MSA and OP_REG_MSA_CTRL. + (match_mdmx_imm_reg_operand): Update accordingly. + (match_imm_index_operand): New function. + (match_reg_index_operand): New function. + (match_operand): Handle cases for OP_IMM_INDEX and OP_REG_INDEX. + (md_convert_frag): Convert bz.b/h/w/d, bnz.b/h/w/d, bz.v bnz.v. + (md_show_usage): Print -mmsa and -mno-msa. + * doc/as.texinfo: Document -mmsa and -mno-msa. + * doc/c-mips.texi: Document -mmsa and -mno-msa. + Document .set msa and .set nomsa. + 2013-10-14 Nick Clifton <nickc@redhat.com> * read.c (add_include_dir): Use xrealloc. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index dd61d72..5741d3e 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -1329,6 +1329,8 @@ enum options OPTION_NO_MT, OPTION_VIRT, OPTION_NO_VIRT, + OPTION_MSA, + OPTION_NO_MSA, OPTION_SMARTMIPS, OPTION_NO_SMARTMIPS, OPTION_DSPR2, @@ -1440,6 +1442,8 @@ struct option md_longopts[] = {"mno-mcu", no_argument, NULL, OPTION_NO_MCU}, {"mvirt", no_argument, NULL, OPTION_VIRT}, {"mno-virt", no_argument, NULL, OPTION_NO_VIRT}, + {"mmsa", no_argument, NULL, OPTION_MSA}, + {"mno-msa", no_argument, NULL, OPTION_NO_MSA}, /* Old-style architecture options. Don't add more of these. */ {"m4650", no_argument, NULL, OPTION_M4650}, @@ -1586,6 +1590,10 @@ static const struct mips_ase mips_ases[] = { { "virt", ASE_VIRT, ASE_VIRT64, OPTION_VIRT, OPTION_NO_VIRT, + 2, 2, 2, 2 }, + + { "msa", ASE_MSA, ASE_MSA64, + OPTION_MSA, OPTION_NO_MSA, 2, 2, 2, 2 } }; @@ -2347,7 +2355,7 @@ struct regname { }; #define RNUM_MASK 0x00000ff -#define RTYPE_MASK 0x0efff00 +#define RTYPE_MASK 0x0ffff00 #define RTYPE_NUM 0x0000100 #define RTYPE_FPU 0x0000200 #define RTYPE_FCC 0x0000400 @@ -2363,6 +2371,7 @@ struct regname { #define RTYPE_R5900_Q 0x0100000 #define RTYPE_R5900_R 0x0200000 #define RTYPE_R5900_ACC 0x0400000 +#define RTYPE_MSA 0x0800000 #define RWARN 0x8000000 #define GENERIC_REGISTER_NUMBERS \ @@ -2747,8 +2756,11 @@ enum mips_operand_token_type { /* A 4-bit XYZW channel mask. */ OT_CHANNELS, - /* An element of a vector, e.g. $v0[1]. */ - OT_REG_ELEMENT, + /* A constant vector index, e.g. [1]. */ + OT_INTEGER_INDEX, + + /* A register vector index, e.g. [$2]. */ + OT_REG_INDEX, /* A continuous range of registers, e.g. $s0-$s4. */ OT_REG_RANGE, @@ -2777,17 +2789,14 @@ struct mips_operand_token enum mips_operand_token_type type; union { - /* The register symbol value for an OT_REG. */ + /* The register symbol value for an OT_REG or OT_REG_INDEX. */ unsigned int regno; /* The 4-bit channel mask for an OT_CHANNEL_SUFFIX. */ unsigned int channels; - /* The register symbol value and index for an OT_REG_ELEMENT. */ - struct { - unsigned int regno; - addressT index; - } reg_element; + /* The integer value of an OT_INTEGER_INDEX. */ + addressT index; /* The two register symbol values involved in an OT_REG_RANGE. */ struct { @@ -2948,20 +2957,32 @@ mips_parse_argument_token (char *s, char float_format) mips_add_token (&token, OT_REG_RANGE); return s; } - else if (*s == '[') - { - /* A vector element. */ - expressionS element; + /* Add the register itself. */ + token.u.regno = regno1; + mips_add_token (&token, OT_REG); + + /* Check for a vector index. */ + if (*s == '[') + { ++s; SKIP_SPACE_TABS (s); - my_getExpression (&element, s); - if (element.X_op != O_constant) + if (mips_parse_register (&s, &token.u.regno, NULL)) + mips_add_token (&token, OT_REG_INDEX); + else { - set_insn_error (0, _("vector element must be constant")); - return 0; + expressionS element; + + my_getExpression (&element, s); + if (element.X_op != O_constant) + { + set_insn_error (0, _("vector element must be constant")); + return 0; + } + s = expr_end; + token.u.index = element.X_add_number; + mips_add_token (&token, OT_INTEGER_INDEX); } - s = expr_end; SKIP_SPACE_TABS (s); if (*s != ']') { @@ -2969,16 +2990,7 @@ mips_parse_argument_token (char *s, char float_format) return 0; } ++s; - - token.u.reg_element.regno = regno1; - token.u.reg_element.index = element.X_add_number; - mips_add_token (&token, OT_REG_ELEMENT); - return s; } - - /* Looks like just a plain register. */ - token.u.regno = regno1; - mips_add_token (&token, OT_REG); return s; } @@ -3460,6 +3472,10 @@ md_begin (void) symbol_table_insert (symbol_new (regname, reg_section, RTYPE_VI | i, &zero_address_frag)); + /* MSA register. */ + snprintf (regname, sizeof (regname) - 1, "$w%d", i); + symbol_table_insert (symbol_new (regname, reg_section, + RTYPE_MSA | i, &zero_address_frag)); } obstack_init (&mips_operand_tokens); @@ -4005,6 +4021,7 @@ operand_reg_mask (const struct mips_cl_insn *insn, case OP_PC: case OP_VU0_SUFFIX: case OP_VU0_MATCH_SUFFIX: + case OP_IMM_INDEX: abort (); case OP_REG: @@ -4050,6 +4067,11 @@ operand_reg_mask (const struct mips_cl_insn *insn, if ((vsel & 0x18) == 0x18) return 0; return 1 << (uval & 31); + + case OP_REG_INDEX: + if (!(type_mask & (1 << OP_REG_GP))) + return 0; + return 1 << insn_extract_operand (insn, operand); } abort (); } @@ -4408,6 +4430,12 @@ convert_reg_type (const struct mips_opcode *opcode, case OP_REG_R5900_ACC: return RTYPE_R5900_ACC; + + case OP_REG_MSA: + return RTYPE_MSA; + + case OP_REG_MSA_CTRL: + return RTYPE_NUM; } abort (); } @@ -5078,7 +5106,7 @@ match_mdmx_imm_reg_operand (struct mips_arg_info *arg, uval = mips_extract_operand (operand, opcode->match); is_qh = (uval != 0); - if (arg->token->type == OT_REG || arg->token->type == OT_REG_ELEMENT) + if (arg->token->type == OT_REG) { if ((opcode->membership & INSN_5400) && strcmp (opcode->name, "rzu.ob") == 0) @@ -5088,20 +5116,21 @@ match_mdmx_imm_reg_operand (struct mips_arg_info *arg, return FALSE; } + if (!match_regno (arg, OP_REG_VEC, arg->token->u.regno, ®no)) + return FALSE; + ++arg->token; + /* Check whether this is a vector register or a broadcast of a single element. */ - if (arg->token->type == OT_REG_ELEMENT) + if (arg->token->type == OT_INTEGER_INDEX) { - if (!match_regno (arg, OP_REG_VEC, arg->token->u.reg_element.regno, - ®no)) - return FALSE; - if (arg->token->u.reg_element.index > (is_qh ? 3 : 7)) + if (arg->token->u.index > (is_qh ? 3 : 7)) { set_insn_error (arg->argnum, _("invalid element selector")); return FALSE; } - else - uval |= arg->token->u.reg_element.index << (is_qh ? 2 : 1) << 5; + uval |= arg->token->u.index << (is_qh ? 2 : 1) << 5; + ++arg->token; } else { @@ -5115,15 +5144,12 @@ match_mdmx_imm_reg_operand (struct mips_arg_info *arg, return FALSE; } - if (!match_regno (arg, OP_REG_VEC, arg->token->u.regno, ®no)) - return FALSE; if (is_qh) uval |= MDMX_FMTSEL_VEC_QH << 5; else uval |= MDMX_FMTSEL_VEC_OB << 5; } uval |= regno; - ++arg->token; } else { @@ -5146,6 +5172,47 @@ match_mdmx_imm_reg_operand (struct mips_arg_info *arg, return TRUE; } +/* OP_IMM_INDEX matcher. */ + +static bfd_boolean +match_imm_index_operand (struct mips_arg_info *arg, + const struct mips_operand *operand) +{ + unsigned int max_val; + + if (arg->token->type != OT_INTEGER_INDEX) + return FALSE; + + max_val = (1 << operand->size) - 1; + if (arg->token->u.index > max_val) + { + match_out_of_range (arg); + return FALSE; + } + insn_insert_operand (arg->insn, operand, arg->token->u.index); + ++arg->token; + return TRUE; +} + +/* OP_REG_INDEX matcher. */ + +static bfd_boolean +match_reg_index_operand (struct mips_arg_info *arg, + const struct mips_operand *operand) +{ + unsigned int regno; + + if (arg->token->type != OT_REG_INDEX) + return FALSE; + + if (!match_regno (arg, OP_REG_GP, arg->token->u.regno, ®no)) + return FALSE; + + insn_insert_operand (arg->insn, operand, regno); + ++arg->token; + return TRUE; +} + /* OP_PC matcher. */ static bfd_boolean @@ -5426,6 +5493,12 @@ match_operand (struct mips_arg_info *arg, case OP_VU0_MATCH_SUFFIX: return match_vu0_suffix_operand (arg, operand, TRUE); + + case OP_IMM_INDEX: + return match_imm_index_operand (arg, operand); + + case OP_REG_INDEX: + return match_reg_index_operand (arg, operand); } abort (); } @@ -16539,11 +16612,21 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) switch ((insn >> 28) & 0xf) { case 4: - /* bc[0-3][tf]l? instructions can have the condition - reversed by tweaking a single TF bit, and their - opcodes all have 0x4???????. */ - gas_assert ((insn & 0xf3e00000) == 0x41000000); - insn ^= 0x00010000; + if ((insn & 0xff000000) == 0x47000000 + || (insn & 0xff600000) == 0x45600000) + { + /* BZ.df/BNZ.df, BZ.V/BNZ.V can have the condition + reversed by tweaking bit 23. */ + insn ^= 0x00800000; + } + else + { + /* bc[0-3][tf]l? instructions can have the condition + reversed by tweaking a single TF bit, and their + opcodes all have 0x4???????. */ + gas_assert ((insn & 0xf3e00000) == 0x41000000); + insn ^= 0x00010000; + } break; case 0: @@ -16810,6 +16893,11 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) || (insn & 0xffe30000) == 0x42800000 /* bc2f */ || (insn & 0xffe30000) == 0x42a00000) /* bc2t */ insn ^= 0x00200000; + else if ((insn & 0xff000000) == 0x83000000 /* BZ.df + BNZ.df */ + || (insn & 0xff600000) == 0x81600000) /* BZ.V + BNZ.V */ + insn ^= 0x00800000; else abort (); @@ -18021,6 +18109,9 @@ MIPS options:\n\ -mmcu generate MCU instructions\n\ -mno-mcu do not generate MCU instructions\n")); fprintf (stream, _("\ +-mmsa generate MSA instructions\n\ +-mno-msa do not generate MSA instructions\n")); + fprintf (stream, _("\ -mvirt generate Virtualization instructions\n\ -mno-virt do not generate Virtualization instructions\n")); fprintf (stream, _("\ diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index de6b5b0..9843574 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -412,6 +412,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}. [@b{-mdmx}] [@b{-no-mdmx}] [@b{-mdsp}] [@b{-mno-dsp}] [@b{-mdspr2}] [@b{-mno-dspr2}] + [@b{-mmsa}] [@b{-mno-msa}] [@b{-mmt}] [@b{-mno-mt}] [@b{-mmcu}] [@b{-mno-mcu}] [@b{-minsn32}] [@b{-mno-insn32}] @@ -1329,6 +1330,12 @@ This option implies -mdsp. This tells the assembler to accept DSP Release 2 instructions. @samp{-mno-dspr2} turns off this option. +@item -mmsa +@itemx -mno-msa +Generate code for the MIPS SIMD Architecture Extension. +This tells the assembler to accept MSA instructions. +@samp{-mno-msa} turns off this option. + @item -mmt @itemx -mno-mt Generate code for the MT Application Specific Extension. diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi index 8a25a76..7927893 100644 --- a/gas/doc/c-mips.texi +++ b/gas/doc/c-mips.texi @@ -179,6 +179,12 @@ Generate code for the MCU Application Specific Extension. This tells the assembler to accept MCU instructions. @samp{-mno-mcu} turns off this option. +@item -mmsa +@itemx -mno-msa +Generate code for the MIPS SIMD Architecture Extension. +This tells the assembler to accept MSA instructions. +@samp{-mno-msa} turns off this option. + @item -mvirt @itemx -mno-virt Generate code for the Virtualization Application Specific Extension. @@ -853,6 +859,14 @@ from the MCU Application Specific Extension from that point on in the assembly. The @code{.set nomcu} directive prevents MCU instructions from being accepted. +@cindex MIPS SIMD Architecture instruction generation override +@kindex @code{.set msa} +@kindex @code{.set nomsa} +The directive @code{.set msa} makes the assembler accept instructions +from the MIPS SIMD Architecture Extension from that point on +in the assembly. The @code{.set nomsa} directive prevents MSA +instructions from being accepted. + @cindex Virtualization instruction generation override @kindex @code{.set virt} @kindex @code{.set novirt} |