From b7fc27694485aabb8c3b175c4672483d07534453 Mon Sep 17 00:00:00 2001 From: Julian Brown Date: Fri, 5 May 2006 18:54:44 +0000 Subject: [PATCH] * config/tc-arm.c (parse_vfp_reg_list): Improve register bounds checking. (do_neon_mov): Enable several VMOV variants for VFP. Add suitable architecture version checks. (insns): Allow overlapping instructions to be used in VFP mode. --- gas/ChangeLog | 8 ++++++ gas/config/tc-arm.c | 60 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 59ca0f8ccb5..76386d751f7 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +2006-05-05 Julian Brown + + * config/tc-arm.c (parse_vfp_reg_list): Improve register bounds + checking. + (do_neon_mov): Enable several VMOV variants for VFP. Add suitable + architecture version checks. + (insns): Allow overlapping instructions to be used in VFP mode. + 2006-05-05 H.J. Lu PR gas/2598 diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 243fc1a3739..47f39a8f409 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -1553,6 +1553,15 @@ parse_vfp_reg_list (char **str, unsigned int *pbase, enum reg_list_els etype) case REGLIST_VFP_D: regtype = REG_TYPE_VFD; + break; + + case REGLIST_NEON_D: + regtype = REG_TYPE_NDQ; + break; + } + + if (etype != REGLIST_VFP_S) + { /* VFPv3 allows 32 D registers. */ if (ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v3)) { @@ -1566,12 +1575,6 @@ parse_vfp_reg_list (char **str, unsigned int *pbase, enum reg_list_els etype) } else max_regs = 16; - break; - - case REGLIST_NEON_D: - regtype = REG_TYPE_NDQ; - max_regs = 32; - break; } base_reg = max_regs; @@ -1588,6 +1591,12 @@ parse_vfp_reg_list (char **str, unsigned int *pbase, enum reg_list_els etype) return FAIL; } + if (new_base >= max_regs) + { + first_error (_("register out of range in list")); + return FAIL; + } + /* Note: a value of 2 * n is returned for the register Q. */ if (regtype == REG_TYPE_NQ) { @@ -1626,6 +1635,12 @@ parse_vfp_reg_list (char **str, unsigned int *pbase, enum reg_list_els etype) return FAIL; } + if (high_range >= max_regs) + { + first_error (_("register out of range in list")); + return FAIL; + } + if (regtype == REG_TYPE_NQ) high_range = high_range + 1; @@ -11303,6 +11318,9 @@ do_neon_dup (void) All the encoded bits are hardcoded by this function. + Cases 4, 6 may be used with VFPv1 and above (only 32-bit transfers!). + Cases 5, 7 may be used with VFPv2 and above. + FIXME: Some of the checking may be a bit sloppy (in a couple of cases you can specify a type where it doesn't make sense to, and is ignored). */ @@ -11313,6 +11331,7 @@ do_neon_mov (void) int nargs = inst.operands[0].present + inst.operands[1].present + inst.operands[2].present; unsigned save_cond = thumb_mode ? 0xe0000000 : inst.instruction & 0xf0000000; + const char *vfp_vers = "selected FPU does not support instruction"; switch (nargs) { @@ -11328,6 +11347,10 @@ do_neon_mov (void) unsigned x = NEON_SCALAR_INDEX (inst.operands[1].reg); unsigned abcdebits = 0; + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1), + _(vfp_vers)); + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_neon_ext_v1) + && et.size != 32, _(vfp_vers)); constraint (et.type == NT_invtype, _("bad type for scalar")); constraint (x >= 64 / et.size, _("scalar index out of range")); @@ -11361,6 +11384,10 @@ do_neon_mov (void) unsigned dn = NEON_SCALAR_REG (inst.operands[0].reg); unsigned x = NEON_SCALAR_INDEX (inst.operands[0].reg); + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v1), + _(vfp_vers)); + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_neon_ext_v1) + && et.size != 32, _(vfp_vers)); constraint (et.type == NT_invtype, _("bad type for scalar")); constraint (x >= 64 / et.size, _("scalar index out of range")); @@ -11411,6 +11438,9 @@ do_neon_mov (void) case 3: /* Cases 5, 7. */ + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v2), + _(vfp_vers)); + if (inst.operands[0].regisimm) { /* Case 5. */ @@ -14155,7 +14185,16 @@ static const struct asm_opcode insns[] = nUF(vcvtq, vcvt, 3, (RNQ, RNQ, oI32b), neon_cvt), /* One register and an immediate value. All encoding special-cased! */ +#undef THUMB_VARIANT +#define THUMB_VARIANT &fpu_vfp_ext_v1 +#undef ARM_VARIANT +#define ARM_VARIANT &fpu_vfp_ext_v1 NCE(vmov, 0, 1, (VMOV), neon_mov), + +#undef THUMB_VARIANT +#define THUMB_VARIANT &fpu_neon_ext_v1 +#undef ARM_VARIANT +#define ARM_VARIANT &fpu_neon_ext_v1 NCE(vmovq, 0, 1, (VMOV), neon_mov), nUF(vmvn, vmvn, 2, (RNDQ, RNDQ_IMVNb), neon_mvn), nUF(vmvnq, vmvn, 2, (RNQ, RNDQ_IMVNb), neon_mvn), @@ -14250,9 +14289,9 @@ static const struct asm_opcode insns[] = NUF(vtbx, 1b00840, 3, (RND, NRDLST, RND), neon_tbl_tbx), #undef THUMB_VARIANT -#define THUMB_VARIANT &fpu_vfp_v3_or_neon_ext +#define THUMB_VARIANT &fpu_vfp_ext_v1xd #undef ARM_VARIANT -#define ARM_VARIANT &fpu_vfp_v3_or_neon_ext +#define ARM_VARIANT &fpu_vfp_ext_v1xd /* Load/store instructions. Available in Neon or VFPv3. */ NCE(vldm, c900b00, 2, (RRw, NRDLST), neon_ldm_stm), @@ -14264,6 +14303,11 @@ static const struct asm_opcode insns[] = NCE(vldr, d100b00, 2, (RND, ADDR), neon_ldr_str), NCE(vstr, d000b00, 2, (RND, ADDR), neon_ldr_str), +#undef THUMB_VARIANT +#define THUMB_VARIANT &fpu_vfp_v3_or_neon_ext +#undef ARM_VARIANT +#define ARM_VARIANT &fpu_vfp_v3_or_neon_ext + /* Neon element/structure load/store. */ nUF(vld1, vld1, 2, (NSTRLST, ADDR), neon_ldx_stx), nUF(vst1, vst1, 2, (NSTRLST, ADDR), neon_ldx_stx), -- 2.30.2