2010-01-04 Daniel Gutson <dgutson@codesourcery.com>

gas/
        * config/tc-arm.c (do_neon_logic): Accept imm value
        in the third operand too.
        (operand_parse_code): OP_RNDQ_IMVNb renamed to
        OP_RNDQ_Ibig.
        (parse_operands): OP_NILO case removed, applied renaming.
        (insns): Neon shape changed for some logic instructions.

        gas/testsuite/
        * gas/arm/neon-logic.d: New test case.
        * gas/arm/neon-logic.s: New file.
This commit is contained in:
Daniel Gutson 2010-01-04 23:31:04 +00:00
parent 878c79795e
commit 4316f0d240
5 changed files with 68 additions and 51 deletions

View File

@ -1,3 +1,12 @@
2010-01-04 Daniel Gutson <dgutson@codesourcery.com>
* config/tc-arm.c (do_neon_logic): Accept imm value
in the third operand too.
(operand_parse_code): OP_RNDQ_IMVNb renamed to
OP_RNDQ_Ibig.
(parse_operands): OP_NILO case removed, applied renaming.
(insns): Neon shape changed for some logic instructions.
2010-01-04 Daniel Gutson <dgutson@codesourcery.com> 2010-01-04 Daniel Gutson <dgutson@codesourcery.com>
* config/tc-arm.c (do_neon_ldx_stx): Added * config/tc-arm.c (do_neon_ldx_stx): Added

View File

@ -5768,7 +5768,6 @@ enum operand_parse_code
OP_NRDLST, /* Neon double-precision register list (d0-d31, qN aliases) */ OP_NRDLST, /* Neon double-precision register list (d0-d31, qN aliases) */
OP_NSTRLST, /* Neon element/structure list */ OP_NSTRLST, /* Neon element/structure list */
OP_NILO, /* Neon immediate/logic operands 2 or 2+3. (VBIC, VORR...) */
OP_RNDQ_I0, /* Neon D or Q reg, or immediate zero. */ OP_RNDQ_I0, /* Neon D or Q reg, or immediate zero. */
OP_RVSD_I0, /* VFP S or D reg, or immediate zero. */ OP_RVSD_I0, /* VFP S or D reg, or immediate zero. */
OP_RR_RNSC, /* ARM reg or Neon scalar. */ OP_RR_RNSC, /* ARM reg or Neon scalar. */
@ -5776,7 +5775,7 @@ enum operand_parse_code
OP_RNDQ_RNSC, /* Neon D or Q reg, or Neon scalar. */ OP_RNDQ_RNSC, /* Neon D or Q reg, or Neon scalar. */
OP_RND_RNSC, /* Neon D reg, or Neon scalar. */ OP_RND_RNSC, /* Neon D reg, or Neon scalar. */
OP_VMOV, /* Neon VMOV operands. */ OP_VMOV, /* Neon VMOV operands. */
OP_RNDQ_IMVNb,/* Neon D or Q reg, or immediate good for VMVN. */ OP_RNDQ_Ibig, /* Neon D or Q reg, or big immediate for logic and VMVN. */
OP_RNDQ_I63b, /* Neon D or Q reg, or immediate for shift. */ OP_RNDQ_I63b, /* Neon D or Q reg, or immediate for shift. */
OP_RIWR_I32z, /* iWMMXt wR register, or immediate 0 .. 32 for iWMMXt2. */ OP_RIWR_I32z, /* iWMMXt wR register, or immediate 0 .. 32 for iWMMXt2. */
@ -6008,36 +6007,6 @@ parse_operands (char *str, const unsigned char *pattern)
scalars are accepted here, so deal with those in later code. */ scalars are accepted here, so deal with those in later code. */
case OP_RNSC: po_scalar_or_goto (8, failure); break; case OP_RNSC: po_scalar_or_goto (8, failure); break;
/* WARNING: We can expand to two operands here. This has the potential
to totally confuse the backtracking mechanism! It will be OK at
least as long as we don't try to use optional args as well,
though. */
case OP_NILO:
{
po_reg_or_goto (REG_TYPE_NDQ, try_imm);
inst.operands[i].present = 1;
i++;
skip_past_comma (&str);
po_reg_or_goto (REG_TYPE_NDQ, one_reg_only);
break;
one_reg_only:
/* Optional register operand was omitted. Unfortunately, it's in
operands[i-1] and we need it to be in inst.operands[i]. Fix that
here (this is a bit grotty). */
inst.operands[i] = inst.operands[i-1];
inst.operands[i-1].present = 0;
break;
try_imm:
/* There's a possibility of getting a 64-bit immediate here, so
we need special handling. */
if (parse_big_immediate (&str, i) == FAIL)
{
inst.error = _("immediate value is out of range");
goto failure;
}
}
break;
case OP_RNDQ_I0: case OP_RNDQ_I0:
{ {
po_reg_or_goto (REG_TYPE_NDQ, try_imm0); po_reg_or_goto (REG_TYPE_NDQ, try_imm0);
@ -6093,11 +6062,11 @@ parse_operands (char *str, const unsigned char *pattern)
po_misc_or_fail (parse_neon_mov (&str, &i) == FAIL); po_misc_or_fail (parse_neon_mov (&str, &i) == FAIL);
break; break;
case OP_RNDQ_IMVNb: case OP_RNDQ_Ibig:
{ {
po_reg_or_goto (REG_TYPE_NDQ, try_mvnimm); po_reg_or_goto (REG_TYPE_NDQ, try_immbig);
break; break;
try_mvnimm: try_immbig:
/* There's a possibility of getting a 64-bit immediate here, so /* There's a possibility of getting a 64-bit immediate here, so
we need special handling. */ we need special handling. */
if (parse_big_immediate (&str, i) == FAIL) if (parse_big_immediate (&str, i) == FAIL)
@ -12910,7 +12879,12 @@ do_neon_logic (void)
} }
else else
{ {
enum neon_shape rs = neon_select_shape (NS_DI, NS_QI, NS_NULL); const int three_ops_form = (inst.operands[2].present
&& !inst.operands[2].isreg);
const int immoperand = (three_ops_form ? 2 : 1);
enum neon_shape rs = (three_ops_form
? neon_select_shape (NS_DDI, NS_QQI, NS_NULL)
: neon_select_shape (NS_DI, NS_QI, NS_NULL));
struct neon_type_el et = neon_check_type (2, rs, struct neon_type_el et = neon_check_type (2, rs,
N_I8 | N_I16 | N_I32 | N_I64 | N_F32 | N_KEY, N_EQK); N_I8 | N_I16 | N_I32 | N_I64 | N_F32 | N_KEY, N_EQK);
enum neon_opc opcode = (enum neon_opc) inst.instruction & 0x0fffffff; enum neon_opc opcode = (enum neon_opc) inst.instruction & 0x0fffffff;
@ -12920,15 +12894,19 @@ do_neon_logic (void)
if (et.type == NT_invtype) if (et.type == NT_invtype)
return; return;
if (three_ops_form)
constraint (inst.operands[0].reg != inst.operands[1].reg,
_("first and second operands shall be the same register"));
NEON_ENCODE (IMMED, inst); NEON_ENCODE (IMMED, inst);
immbits = inst.operands[1].imm; immbits = inst.operands[immoperand].imm;
if (et.size == 64) if (et.size == 64)
{ {
/* .i64 is a pseudo-op, so the immediate must be a repeating /* .i64 is a pseudo-op, so the immediate must be a repeating
pattern. */ pattern. */
if (immbits != (inst.operands[1].regisimm ? if (immbits != (inst.operands[immoperand].regisimm ?
inst.operands[1].reg : 0)) inst.operands[immoperand].reg : 0))
{ {
/* Set immbits to an invalid constant. */ /* Set immbits to an invalid constant. */
immbits = 0xdeadbeef; immbits = 0xdeadbeef;
@ -17479,16 +17457,16 @@ static const struct asm_opcode insns[] =
nUF(vqshl, _vqshl, 3, (RNDQ, oRNDQ, RNDQ_I63b), neon_qshl_imm), nUF(vqshl, _vqshl, 3, (RNDQ, oRNDQ, RNDQ_I63b), neon_qshl_imm),
nUF(vqshlq, _vqshl, 3, (RNQ, oRNQ, RNDQ_I63b), neon_qshl_imm), nUF(vqshlq, _vqshl, 3, (RNQ, oRNQ, RNDQ_I63b), neon_qshl_imm),
/* Logic ops, types optional & ignored. */ /* Logic ops, types optional & ignored. */
nUF(vand, _vand, 2, (RNDQ, NILO), neon_logic), nUF(vand, _vand, 3, (RNDQ, oRNDQ, RNDQ_Ibig), neon_logic),
nUF(vandq, _vand, 2, (RNQ, NILO), neon_logic), nUF(vandq, _vand, 3, (RNQ, oRNQ, RNDQ_Ibig), neon_logic),
nUF(vbic, _vbic, 2, (RNDQ, NILO), neon_logic), nUF(vbic, _vbic, 3, (RNDQ, oRNDQ, RNDQ_Ibig), neon_logic),
nUF(vbicq, _vbic, 2, (RNQ, NILO), neon_logic), nUF(vbicq, _vbic, 3, (RNQ, oRNQ, RNDQ_Ibig), neon_logic),
nUF(vorr, _vorr, 2, (RNDQ, NILO), neon_logic), nUF(vorr, _vorr, 3, (RNDQ, oRNDQ, RNDQ_Ibig), neon_logic),
nUF(vorrq, _vorr, 2, (RNQ, NILO), neon_logic), nUF(vorrq, _vorr, 3, (RNQ, oRNQ, RNDQ_Ibig), neon_logic),
nUF(vorn, _vorn, 2, (RNDQ, NILO), neon_logic), nUF(vorn, _vorn, 3, (RNDQ, oRNDQ, RNDQ_Ibig), neon_logic),
nUF(vornq, _vorn, 2, (RNQ, NILO), neon_logic), nUF(vornq, _vorn, 3, (RNQ, oRNQ, RNDQ_Ibig), neon_logic),
nUF(veor, _veor, 3, (RNDQ, oRNDQ, RNDQ), neon_logic), nUF(veor, _veor, 3, (RNDQ, oRNDQ, RNDQ), neon_logic),
nUF(veorq, _veor, 3, (RNQ, oRNQ, RNQ), neon_logic), nUF(veorq, _veor, 3, (RNQ, oRNQ, RNQ), neon_logic),
/* Bitfield ops, untyped. */ /* Bitfield ops, untyped. */
NUF(vbsl, 1100110, 3, (RNDQ, RNDQ, RNDQ), neon_bitfield), NUF(vbsl, 1100110, 3, (RNDQ, RNDQ, RNDQ), neon_bitfield),
NUF(vbslq, 1100110, 3, (RNQ, RNQ, RNQ), neon_bitfield), NUF(vbslq, 1100110, 3, (RNQ, RNQ, RNQ), neon_bitfield),
@ -17587,8 +17565,8 @@ static const struct asm_opcode insns[] =
/* CVT with optional immediate for fixed-point variant. */ /* CVT with optional immediate for fixed-point variant. */
nUF(vcvtq, _vcvt, 3, (RNQ, RNQ, oI32b), neon_cvt), nUF(vcvtq, _vcvt, 3, (RNQ, RNQ, oI32b), neon_cvt),
nUF(vmvn, _vmvn, 2, (RNDQ, RNDQ_IMVNb), neon_mvn), nUF(vmvn, _vmvn, 2, (RNDQ, RNDQ_Ibig), neon_mvn),
nUF(vmvnq, _vmvn, 2, (RNQ, RNDQ_IMVNb), neon_mvn), nUF(vmvnq, _vmvn, 2, (RNQ, RNDQ_Ibig), neon_mvn),
/* Data processing, three registers of different lengths. */ /* Data processing, three registers of different lengths. */
/* Dyadic, long insns. Types S8 S16 S32 U8 U16 U32. */ /* Dyadic, long insns. Types S8 S16 S32 U8 U16 U32. */

View File

@ -1,3 +1,8 @@
2010-01-04 Daniel Gutson <dgutson@codesourcery.com>
* gas/arm/neon-logic.d: New test case.
* gas/arm/neon-logic.s: New file.
2010-01-04 Daniel Gutson <dgutson@codesourcery.com> 2010-01-04 Daniel Gutson <dgutson@codesourcery.com>
* gas/arm/neon-addressing-bad.d: New test case. * gas/arm/neon-addressing-bad.d: New test case.

View File

@ -0,0 +1,16 @@
# name: Neon logic insns with two and three operands including imm. values
# as: -mfpu=neon
# objdump: -dr --prefix-addresses --show-raw-insn
.*: +file format .*arm.*
Disassembly of section \.text:
00000000 <.text> f387015f vorr.i32 q0, #255 ; 0x000000ff
00000004 <.text\+0x4> f387015f vorr.i32 q0, #255 ; 0x000000ff
00000008 <.text\+0x8> f2220154 vorr q0, q1, q2
0000000c <.text\+0xc> f2200152 vorr q0, q0, q1
00000010 <.text\+0x10> f387011f vorr.i32 d0, #255 ; 0x000000ff
00000014 <.text\+0x14> f387011f vorr.i32 d0, #255 ; 0x000000ff
00000018 <.text\+0x18> f2210112 vorr d0, d1, d2
0000001c <.text\+0x1c> f2200111 vorr d0, d0, d1

View File

@ -0,0 +1,9 @@
.syntax unified
vorr.i32 q0, q0, #0xff
vorr.i32 q0, #0xff
vorr.i32 q0, q1, q2
vorr.i32 q0, q1
vorr.i32 d0, d0, #0xff
vorr.i32 d0, #0xff
vorr.i32 d0, d1, d2
vorr.i32 d0, d1