X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-arm.c;h=a7ebc51ccd2b0cff4208c7818a7610e3dc0ed616;hb=7cc69913c20942a6f601bc2477fd881f1115df08;hp=85afdc28d7b6fe79944c1e6ba34e7d4cb1548868;hpb=33a392fb884c2f39101877c853ab5fb78c6f7d01;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 85afdc28d7..a7ebc51ccd 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -4,6 +4,8 @@ Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) Modified by David Taylor (dtaylor@armltd.co.uk) Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com) + Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com) + Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com) This file is part of GAS, the GNU Assembler. @@ -189,6 +191,9 @@ static int march_cpu_opt = -1; static int march_fpu_opt = -1; static int mfpu_opt = -1; static int mfloat_abi_opt = -1; +#ifdef OBJ_ELF +static int meabi_flags = EF_ARM_EABI_UNKNOWN; +#endif /* This array holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful. */ @@ -929,7 +934,8 @@ static void do_vfp_sp_dyadic PARAMS ((char *)); static void do_vfp_dp_dyadic PARAMS ((char *)); static void do_vfp_reg_from_sp PARAMS ((char *)); static void do_vfp_sp_from_reg PARAMS ((char *)); -static void do_vfp_sp_reg2 PARAMS ((char *)); +static void do_vfp_reg2_from_sp2 PARAMS ((char *)); +static void do_vfp_sp2_from_reg2 PARAMS ((char *)); static void do_vfp_reg_from_dp PARAMS ((char *)); static void do_vfp_reg2_from_dp PARAMS ((char *)); static void do_vfp_dp_from_reg PARAMS ((char *)); @@ -1110,8 +1116,8 @@ static int cp_byte_address_required_here PARAMS ((char **)); /* "INSN X,Y" where X:bit16, Y:bit12. */ #define MAV_MODE2 0x0c10 -/* "INSN X,Y" where X:0, Y:bit16. */ -#define MAV_MODE3 0x1000 +/* "INSN X,Y" where X:bit12, Y:bit16. */ +#define MAV_MODE3 0x100c /* "INSN X,Y,Z" where X:16, Y:0, Z:12. */ #define MAV_MODE4 0x0c0010 @@ -1976,8 +1982,8 @@ static const struct asm_opcode insns[] = {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1, do_vfp_dp_compare_z}, /* VFP V2. */ - {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2}, - {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_sp_reg2}, + {"fmsrr", 0xec400a10, 5, FPU_VFP_EXT_V2, do_vfp_sp2_from_reg2}, + {"fmrrs", 0xec500a10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_sp2}, {"fmdrr", 0xec400b10, 5, FPU_VFP_EXT_V2, do_vfp_dp_from_reg2}, {"fmrrd", 0xec500b10, 5, FPU_VFP_EXT_V2, do_vfp_reg2_from_dp}, @@ -2174,18 +2180,18 @@ static const struct asm_opcode insns[] = {"cfmvr64l", 0xee100510, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c}, {"cfmv64hr", 0xee000530, 8, ARM_CEXT_MAVERICK, do_mav_binops_2c}, {"cfmvr64h", 0xee100530, 8, ARM_CEXT_MAVERICK, do_mav_binops_1c}, - {"cfmval32", 0xee100610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a}, - {"cfmv32al", 0xee000610, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b}, - {"cfmvam32", 0xee100630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a}, - {"cfmv32am", 0xee000630, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b}, - {"cfmvah32", 0xee100650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a}, - {"cfmv32ah", 0xee000650, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b}, - {"cfmva32", 0xee100670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a}, - {"cfmv32a", 0xee000670, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b}, - {"cfmva64", 0xee100690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c}, - {"cfmv64a", 0xee000690, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d}, - {"cfmvsc32", 0xee1006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1}, - {"cfmv32sc", 0xee0006b0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2}, + {"cfmval32", 0xee200440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a}, + {"cfmv32al", 0xee100440, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b}, + {"cfmvam32", 0xee200460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a}, + {"cfmv32am", 0xee100460, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b}, + {"cfmvah32", 0xee200480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3a}, + {"cfmv32ah", 0xee100480, 8, ARM_CEXT_MAVERICK, do_mav_binops_3b}, + {"cfmva32", 0xee2004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3a}, + {"cfmv32a", 0xee1004a0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3b}, + {"cfmva64", 0xee2004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3c}, + {"cfmv64a", 0xee1004c0, 7, ARM_CEXT_MAVERICK, do_mav_binops_3d}, + {"cfmvsc32", 0xee2004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_1}, + {"cfmv32sc", 0xee1004e0, 8, ARM_CEXT_MAVERICK, do_mav_dspsc_2}, {"cfcpys", 0xee000400, 6, ARM_CEXT_MAVERICK, do_mav_binops_1d}, {"cfcpyd", 0xee000420, 6, ARM_CEXT_MAVERICK, do_mav_binops_1e}, {"cfcvtsd", 0xee000460, 7, ARM_CEXT_MAVERICK, do_mav_binops_1f}, @@ -2548,6 +2554,9 @@ static int arm_parse_cpu PARAMS ((char *)); static int arm_parse_arch PARAMS ((char *)); static int arm_parse_fpu PARAMS ((char *)); static int arm_parse_float_abi PARAMS ((char *)); +#ifdef OBJ_ELF +static int arm_parse_eabi PARAMS ((char *)); +#endif #if 0 /* Suppressed - for now. */ #if defined OBJ_COFF || defined OBJ_ELF static void arm_add_note PARAMS ((const char *, const char *, unsigned int)); @@ -7299,7 +7308,9 @@ do_adr (str) /* Frag hacking will turn this into a sub instruction if the offset turns out to be negative. */ inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE; +#ifndef TE_WINCE inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */ +#endif inst.reloc.pc_rel = 1; end_of_line (str); @@ -7330,7 +7341,9 @@ do_adrl (str) /* Frag hacking will turn this into a sub instruction if the offset turns out to be negative. */ inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE; +#ifndef TE_WINCE inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */ +#endif inst.reloc.pc_rel = 1; inst.size = INSN_SIZE * 2; } @@ -8950,15 +8963,13 @@ do_vfp_reg_from_sp (str) } static void -do_vfp_sp_reg2 (str) +do_vfp_reg2_from_sp2 (str) char *str; { skip_whitespace (str); - if (reg_required_here (&str, 12) == FAIL) - return; - - if (skip_past_comma (&str) == FAIL + if (reg_required_here (&str, 12) == FAIL + || skip_past_comma (&str) == FAIL || reg_required_here (&str, 16) == FAIL || skip_past_comma (&str) == FAIL) { @@ -8997,6 +9008,32 @@ do_vfp_sp_from_reg (str) end_of_line (str); } +static void +do_vfp_sp2_from_reg2 (str) + char *str; +{ + skip_whitespace (str); + + /* We require exactly two consecutive SP registers. */ + if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2) + { + if (! inst.error) + inst.error = _("only two consecutive VFP SP registers allowed here"); + } + + if (skip_past_comma (&str) == FAIL + || reg_required_here (&str, 12) == FAIL + || skip_past_comma (&str) == FAIL + || reg_required_here (&str, 16) == FAIL) + { + if (! inst.error) + inst.error = BAD_ARGS; + return; + } + + end_of_line (str); +} + static void do_vfp_reg_from_dp (str) char *str; @@ -9071,7 +9108,7 @@ do_vfp_dp_from_reg2 (str) if (skip_past_comma (&str) == FAIL || reg_required_here (&str, 12) == FAIL || skip_past_comma (&str) == FAIL - || reg_required_here (&str, 16)) + || reg_required_here (&str, 16) == FAIL) { if (! inst.error) inst.error = BAD_ARGS; @@ -10546,7 +10583,7 @@ do_mav_quad_6b (str) REG_TYPE_MVFX); } -/* cfmvsc32 DSPSC,MVFX[15:0]. */ +/* cfmvsc32 DSPSC,MVDX[15:0]. */ static void do_mav_dspsc_1 (str) char * str; @@ -10556,7 +10593,7 @@ do_mav_dspsc_1 (str) /* cfmvsc32. */ if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL || skip_past_comma (&str) == FAIL - || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL) + || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL) { if (!inst.error) inst.error = BAD_ARGS; @@ -10567,7 +10604,7 @@ do_mav_dspsc_1 (str) end_of_line (str); } -/* cfmv32sc MVFX[15:0],DSPSC. */ +/* cfmv32sc MVDX[15:0],DSPSC. */ static void do_mav_dspsc_2 (str) char * str; @@ -10575,7 +10612,7 @@ do_mav_dspsc_2 (str) skip_whitespace (str); /* cfmv32sc. */ - if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL + if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL || skip_past_comma (&str) == FAIL || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL) { @@ -11654,40 +11691,57 @@ md_begin () cpu_variant = mcpu_cpu_opt | mfpu_opt; -#if defined OBJ_COFF || defined OBJ_ELF { unsigned int flags = 0; - /* Set the flags in the private structure. */ - if (uses_apcs_26) flags |= F_APCS26; - if (support_interwork) flags |= F_INTERWORK; - if (uses_apcs_float) flags |= F_APCS_FLOAT; - if (pic_code) flags |= F_PIC; - if ((cpu_variant & FPU_ANY) == FPU_NONE - || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */ - { - flags |= F_SOFT_FLOAT; - } - switch (mfloat_abi_opt) +#if defined OBJ_ELF + flags = meabi_flags; + + switch (meabi_flags) { - case ARM_FLOAT_ABI_SOFT: - case ARM_FLOAT_ABI_SOFTFP: - flags |= F_SOFT_FLOAT; + case EF_ARM_EABI_UNKNOWN: +#endif +#if defined OBJ_COFF || defined OBJ_ELF + /* Set the flags in the private structure. */ + if (uses_apcs_26) flags |= F_APCS26; + if (support_interwork) flags |= F_INTERWORK; + if (uses_apcs_float) flags |= F_APCS_FLOAT; + if (pic_code) flags |= F_PIC; + if ((cpu_variant & FPU_ANY) == FPU_NONE + || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only. */ + flags |= F_SOFT_FLOAT; + + switch (mfloat_abi_opt) + { + case ARM_FLOAT_ABI_SOFT: + case ARM_FLOAT_ABI_SOFTFP: + flags |= F_SOFT_FLOAT; + break; + + case ARM_FLOAT_ABI_HARD: + if (flags & F_SOFT_FLOAT) + as_bad (_("hard-float conflicts with specified fpu")); + break; + } + + /* Using VFP conventions (even if soft-float). */ + if (cpu_variant & FPU_VFP_EXT_NONE) + flags |= F_VFP_FLOAT; +#endif +#if defined OBJ_ELF + if (cpu_variant & FPU_ARCH_MAVERICK) + flags |= EF_ARM_MAVERICK_FLOAT; break; - case ARM_FLOAT_ABI_HARD: - if (flags & F_SOFT_FLOAT) - as_bad (_("hard-float conflicts with specified fpu")); + case EF_ARM_EABI_VER3: + /* No additional flags to set. */ break; - } - /* Using VFP conventions (even if soft-float). */ - if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT; -#if defined OBJ_ELF - if (cpu_variant & FPU_ARCH_MAVERICK) - flags |= EF_ARM_MAVERICK_FLOAT; + default: + abort (); + } #endif - +#if defined OBJ_COFF || defined OBJ_ELF bfd_set_private_flags (stdoutput, flags); /* We have run out flags in the COFF header to encode the @@ -11707,8 +11761,8 @@ md_begin () bfd_set_section_contents (stdoutput, sec, NULL, 0, 0); } } - } #endif + } /* Record the CPU type as well. */ switch (cpu_variant & ARM_CPU_MASK) @@ -11780,6 +11834,9 @@ md_begin () bfd_set_section_flags (stdoutput, arm_arch, SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \ | SEC_HAS_CONTENTS); +#else + bfd_set_section_flags (stdoutput, arm_arch, + SEC_READONLY | SEC_HAS_CONTENTS); #endif arm_arch->output_section = arm_arch; subseg_set (arm_arch, 0); @@ -12794,6 +12851,16 @@ tc_gen_reloc (section, fixp) return NULL; case BFD_RELOC_ARM_OFFSET_IMM: + if (fixp->fx_addsy != NULL + && !S_IS_DEFINED (fixp->fx_addsy) + && S_IS_LOCAL (fixp->fx_addsy)) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + _("undefined local label `%s'"), + S_GET_NAME (fixp->fx_addsy)); + return NULL; + } + as_bad_where (fixp->fx_file, fixp->fx_line, _("internal_relocation (type: OFFSET_IMM) not fixed up")); return NULL; @@ -13287,6 +13354,7 @@ static struct arm_cpu_option_table arm_cpus[] = {"arm9e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2}, {"arm9e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, {"arm926ej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2}, + {"arm926ejs", ARM_ARCH_V5TEJ, FPU_ARCH_VFP_V2}, {"arm946e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2}, {"arm946e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, {"arm966e-r0", ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2}, @@ -13296,6 +13364,7 @@ static struct arm_cpu_option_table arm_cpus[] = {"arm1020", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, {"arm1020t", ARM_ARCH_V5T, FPU_ARCH_VFP_V1}, {"arm1020e", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, + {"arm1026ejs", ARM_ARCH_V5TE, FPU_ARCH_VFP_V2}, {"arm1136js", ARM_ARCH_V6, FPU_NONE}, {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2}, /* ??? XSCALE is really an architecture. */ @@ -13337,6 +13406,7 @@ static struct arm_arch_option_table arm_archs[] = {"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP}, {"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP}, {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP}, + {"armv6j", ARM_ARCH_V6, FPU_ARCH_VFP}, {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP}, {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP}, {NULL, 0, 0} @@ -13403,6 +13473,22 @@ static struct arm_float_abi_option_table arm_float_abis[] = {NULL, 0} }; +struct arm_eabi_option_table +{ + char *name; + unsigned int value; +}; + +#ifdef OBJ_ELF +/* We only know hot to output GNU and ver 3 (AAELF) formats. */ +static struct arm_eabi_option_table arm_eabis[] = +{ + {"gnu", EF_ARM_EABI_UNKNOWN}, + {"3", EF_ARM_EABI_VER3}, + {NULL, 0} +}; +#endif + struct arm_long_option_table { char *option; /* Substring to match. */ @@ -13566,6 +13652,24 @@ arm_parse_float_abi (str) return 0; } +#ifdef OBJ_ELF +static int +arm_parse_eabi (str) + char * str; +{ + struct arm_eabi_option_table *opt; + + for (opt = arm_eabis; opt->name != NULL; opt++) + if (strcmp (opt->name, str) == 0) + { + meabi_flags = opt->value; + return 1; + } + as_bad (_("unknown EABI `%s'\n"), str); + return 0; +} +#endif + struct arm_long_option_table arm_long_opts[] = { {"mcpu=", N_("\t assemble for CPU "), @@ -13576,6 +13680,10 @@ struct arm_long_option_table arm_long_opts[] = arm_parse_fpu, NULL}, {"mfloat-abi=", N_("\t assemble for floating point ABI "), arm_parse_float_abi, NULL}, +#ifdef OBJ_ELF + {"meabi=", N_("\t assemble for eabi version "), + arm_parse_eabi, NULL}, +#endif {NULL, NULL, 0, NULL} };