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.
This commit is contained in:
Chao-ying Fu 2013-10-14 18:50:54 +00:00
parent a9f581680f
commit 56d438b172
4 changed files with 181 additions and 43 deletions

View File

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

View File

@ -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, &regno))
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,
&regno))
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, &regno))
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, &regno))
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, _("\

View File

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

View File

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