aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-12-06 01:25:29 +0000
committerMark Mitchell <mark@codesourcery.com>2003-12-06 01:25:29 +0000
commit09d92015d3d22d8191e795fe1fc09efdb7488c48 (patch)
tree142992246a6995eb9ba2182fad79bb1061fc7999 /gas/config
parent32edc941e1fb0863accee2ad345616f0d6af9517 (diff)
downloadfsf-binutils-gdb-09d92015d3d22d8191e795fe1fc09efdb7488c48.zip
fsf-binutils-gdb-09d92015d3d22d8191e795fe1fc09efdb7488c48.tar.gz
fsf-binutils-gdb-09d92015d3d22d8191e795fe1fc09efdb7488c48.tar.bz2
* gas/arm/arm.exp: Add archv6 and thumbv6.
* gas/arm/archv6.d: New file. * gas/arm/archv6.s: Likewise. * gas/arm/thumbv6.d: Likewise. * gas/arm/thumbv6.s: Likewise. Add V6 support. * config/tc-arm.c (ARM_EXT_V6): New macro. (ARM_ARCH_V6): Likewise. (SHIFT_IMMEDIATE): Likewise. (SHIFT_LSL_OR_ASR_IMMEDIATE): Likewise. (SHIFT_ASR_IMMEDIATE): Likewise. (SHIFT_LSL_IMMMEDIATE): Likewise. (do_cps): New function. (do_cpsi): Likewise. (do_ldrex): Likewise. (do_pkhbt): Likewise. (do_pkhtb): Likewise. (do_qadd16): Likewise. (do_rev): Likewise. (do_rfe): Likewise. (do_sxtah): Likewise. (do_sxth): Likewise. (do_setend): Likewise. (do_smlad): Likewise. (do_smlald): Likewise. (do_smmul): Likewise. (do_ssat): Likewise. (do_usat): Likewise. (do_srs): Likewise. (do_ssat16): Likewise. (do_usat16): Likewise. (do_strex): Likewise. (do_umaal): Likewise. (do_cps_mode): Likewise. (do_cps_flags): Likewise. (do_endian_specifier): Likewise. (do_pkh_core): Likewise. (do_sat): Likewise. (do_sat16): Likewise. (insns): Add V6 instructions. (do_t_cps): New function. (do_t_cpy): Likewise. (do_t_setend): Likewise. (THUMB_CPY): New macro. (tinsns): Add V6 instructions. (decode_shift): Handle V6 restricted-shift options. (thumb_mov_compare): Support CPY. (arm_cores): Add arm1136js and arm1136jfs. (arm_archs): Add armv6. (arm_fpus): Add arm1136jfs. * doc/c-arm.texi (ARM Options): Mention arm1136js, arm1136jfs, and armv6 options. * gas/arm/arm.exp: Add archv6 and thumbv6. * gas/arm/archv6.d: New file. * gas/arm/archv6.s: Likewise. * gas/arm/thumbv6.d: Likewise. * gas/arm/thumbv6.s: Likewise. * arm-dis.c (print_arm_insn): Add 'W' macro. * arm-opc.h (arm_opcodes): Add V6 instructions. (thumb_opcodes): Likewise.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-arm.c1179
1 files changed, 1168 insertions, 11 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index a684350..a08b024 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -55,6 +55,7 @@
#define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */
#define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */
#define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */
+#define ARM_EXT_V6 0x00001000 /* ARM V6. */
/* Co-processor space extensions. */
#define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */
@@ -82,6 +83,7 @@
#define ARM_ARCH_V5TExP (ARM_ARCH_V5T | ARM_EXT_V5ExP)
#define ARM_ARCH_V5TE (ARM_ARCH_V5TExP | ARM_EXT_V5E)
#define ARM_ARCH_V5TEJ (ARM_ARCH_V5TE | ARM_EXT_V5J)
+#define ARM_ARCH_V6 (ARM_ARCH_V5TEJ | ARM_EXT_V6)
/* Processors with specific extensions in the co-processor space. */
#define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE)
@@ -288,8 +290,16 @@ static const struct asm_shift_name shift_names [] =
{ "RRX", shift_properties + SHIFT_RRX }
};
+/* Any kind of shift is accepted. */
#define NO_SHIFT_RESTRICT 1
-#define SHIFT_RESTRICT 0
+/* The shift operand must be an immediate value, not a register. */
+#define SHIFT_IMMEDIATE 0
+/* The shift must be LSL or ASR and the operand must be an immediate. */
+#define SHIFT_LSL_OR_ASR_IMMEDIATE 2
+/* The shift must be ASR and the operand must be an immediate. */
+#define SHIFT_ASR_IMMEDIATE 3
+/* The shift must be LSL and the operand must be an immediate. */
+#define SHIFT_LSL_IMMEDIATE 4
#define NUM_FLOAT_VALS 8
@@ -856,6 +866,36 @@ static void do_co_reg2c PARAMS ((char *));
/* ARM v5TEJ. */
static void do_bxj PARAMS ((char *));
+/* ARM V6. */
+static void do_cps PARAMS ((char *));
+static void do_cpsi PARAMS ((char *));
+static void do_ldrex PARAMS ((char *));
+static void do_pkhbt PARAMS ((char *));
+static void do_pkhtb PARAMS ((char *));
+static void do_qadd16 PARAMS ((char *));
+static void do_rev PARAMS ((char *));
+static void do_rfe PARAMS ((char *));
+static void do_sxtah PARAMS ((char *));
+static void do_sxth PARAMS ((char *));
+static void do_setend PARAMS ((char *));
+static void do_smlad PARAMS ((char *));
+static void do_smlald PARAMS ((char *));
+static void do_smmul PARAMS ((char *));
+static void do_ssat PARAMS ((char *));
+static void do_usat PARAMS ((char *));
+static void do_srs PARAMS ((char *));
+static void do_ssat16 PARAMS ((char *));
+static void do_usat16 PARAMS ((char *));
+static void do_strex PARAMS ((char *));
+static void do_umaal PARAMS ((char *));
+
+static void do_cps_mode PARAMS ((char **));
+static void do_cps_flags PARAMS ((char **, int));
+static int do_endian_specifier PARAMS ((char *));
+static void do_pkh_core PARAMS ((char *, int));
+static void do_sat PARAMS ((char **, int));
+static void do_sat16 PARAMS ((char **, int));
+
/* Coprocessor Instructions. */
static void do_cdp PARAMS ((char *));
static void do_lstc PARAMS ((char *));
@@ -1273,6 +1313,107 @@ static const struct asm_opcode insns[] =
/* ARM Architecture 5TEJ. */
{"bxj", 0xe12fff20, 3, ARM_EXT_V5J, do_bxj},
+ /* ARM V6. */
+ { "cps", 0xf1020000, 0, ARM_EXT_V6, do_cps},
+ { "cpsie", 0xf1080000, 0, ARM_EXT_V6, do_cpsi},
+ { "cpsid", 0xf10C0000, 0, ARM_EXT_V6, do_cpsi},
+ { "ldrex", 0xe1900f9f, 5, ARM_EXT_V6, do_ldrex},
+ { "mcrr2", 0xfc400000, 0, ARM_EXT_V6, do_co_reg2c},
+ { "mrrc2", 0xfc500000, 0, ARM_EXT_V6, do_co_reg2c},
+ { "pkhbt", 0xe6800010, 5, ARM_EXT_V6, do_pkhbt},
+ { "pkhtb", 0xe6800050, 5, ARM_EXT_V6, do_pkhtb},
+ { "qadd16", 0xe6200f10, 6, ARM_EXT_V6, do_qadd16},
+ { "qadd8", 0xe6200f90, 5, ARM_EXT_V6, do_qadd16},
+ { "qaddsubx", 0xe6200f30, 8, ARM_EXT_V6, do_qadd16},
+ { "qsub16", 0xe6200f70, 6, ARM_EXT_V6, do_qadd16},
+ { "qsub8", 0xe6200ff0, 5, ARM_EXT_V6, do_qadd16},
+ { "qsubaddx", 0xe6200f50, 8, ARM_EXT_V6, do_qadd16},
+ { "sadd16", 0xe6100f10, 6, ARM_EXT_V6, do_qadd16},
+ { "sadd8", 0xe6100f90, 5, ARM_EXT_V6, do_qadd16},
+ { "saddsubx", 0xe6100f30, 8, ARM_EXT_V6, do_qadd16},
+ { "shadd16", 0xe6300f10, 7, ARM_EXT_V6, do_qadd16},
+ { "shadd8", 0xe6300f90, 6, ARM_EXT_V6, do_qadd16},
+ { "shaddsubx", 0xe6300f30, 9, ARM_EXT_V6, do_qadd16},
+ { "shsub16", 0xe6300f70, 7, ARM_EXT_V6, do_qadd16},
+ { "shsub8", 0xe6300ff0, 6, ARM_EXT_V6, do_qadd16},
+ { "shsubaddx", 0xe6300f50, 9, ARM_EXT_V6, do_qadd16},
+ { "ssub16", 0xe6100f70, 6, ARM_EXT_V6, do_qadd16},
+ { "ssub8", 0xe6100ff0, 5, ARM_EXT_V6, do_qadd16},
+ { "ssubaddx", 0xe6100f50, 8, ARM_EXT_V6, do_qadd16},
+ { "uadd16", 0xe6500f10, 6, ARM_EXT_V6, do_qadd16},
+ { "uadd8", 0xe6500f90, 5, ARM_EXT_V6, do_qadd16},
+ { "uaddsubx", 0xe6500f30, 8, ARM_EXT_V6, do_qadd16},
+ { "uhadd16", 0xe6700f10, 7, ARM_EXT_V6, do_qadd16},
+ { "uhadd8", 0xe6700f90, 6, ARM_EXT_V6, do_qadd16},
+ { "uhaddsubx", 0xe6700f30, 9, ARM_EXT_V6, do_qadd16},
+ { "uhsub16", 0xe6700f70, 7, ARM_EXT_V6, do_qadd16},
+ { "uhsub8", 0xe6700ff0, 6, ARM_EXT_V6, do_qadd16},
+ { "uhsubaddx", 0xe6700f50, 9, ARM_EXT_V6, do_qadd16},
+ { "uqadd16", 0xe6600f10, 7, ARM_EXT_V6, do_qadd16},
+ { "uqadd8", 0xe6600f90, 6, ARM_EXT_V6, do_qadd16},
+ { "uqaddsubx", 0xe6600f30, 9, ARM_EXT_V6, do_qadd16},
+ { "uqsub16", 0xe6600f70, 7, ARM_EXT_V6, do_qadd16},
+ { "uqsub8", 0xe6600ff0, 6, ARM_EXT_V6, do_qadd16},
+ { "uqsubaddx", 0xe6600f50, 9, ARM_EXT_V6, do_qadd16},
+ { "usub16", 0xe6500f70, 6, ARM_EXT_V6, do_qadd16},
+ { "usub8", 0xe6500ff0, 5, ARM_EXT_V6, do_qadd16},
+ { "usubaddx", 0xe6500f50, 8, ARM_EXT_V6, do_qadd16},
+ { "rev", 0xe6bf0f30, 3, ARM_EXT_V6, do_rev},
+ { "rev16", 0xe6bf0fb0, 5, ARM_EXT_V6, do_rev},
+ { "revsh", 0xe6ff0fb0, 5, ARM_EXT_V6, do_rev},
+ { "rfeia", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
+ { "rfeib", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
+ { "rfeda", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
+ { "rfedb", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
+ { "rfefd", 0xf8900a00, 0, ARM_EXT_V6, do_rfe},
+ { "rfefa", 0xf9900a00, 0, ARM_EXT_V6, do_rfe},
+ { "rfeea", 0xf8100a00, 0, ARM_EXT_V6, do_rfe},
+ { "rfeed", 0xf9100a00, 0, ARM_EXT_V6, do_rfe},
+ { "sxtah", 0xe6b00070, 5, ARM_EXT_V6, do_sxtah},
+ { "sxtab16", 0xe6800070, 7, ARM_EXT_V6, do_sxtah},
+ { "sxtab", 0xe6a00070, 5, ARM_EXT_V6, do_sxtah},
+ { "sxth", 0xe6bf0070, 4, ARM_EXT_V6, do_sxth},
+ { "sxtb16", 0xe68f0070, 6, ARM_EXT_V6, do_sxth},
+ { "sxtb", 0xe6af0070, 4, ARM_EXT_V6, do_sxth},
+ { "uxtah", 0xe6f00070, 5, ARM_EXT_V6, do_sxtah},
+ { "uxtab16", 0xe6c00070, 7, ARM_EXT_V6, do_sxtah},
+ { "uxtab", 0xe6e00070, 5, ARM_EXT_V6, do_sxtah},
+ { "uxth", 0xe6ff0070, 4, ARM_EXT_V6, do_sxth},
+ { "uxtb16", 0xe6cf0070, 6, ARM_EXT_V6, do_sxth},
+ { "uxtb", 0xe6ef0070, 4, ARM_EXT_V6, do_sxth},
+ { "sel", 0xe68000b0, 3, ARM_EXT_V6, do_qadd16},
+ { "setend", 0xf1010000, 0, ARM_EXT_V6, do_setend},
+ { "smlad", 0xe7000010, 5, ARM_EXT_V6, do_smlad},
+ { "smladx", 0xe7000030, 6, ARM_EXT_V6, do_smlad},
+ { "smlald", 0xe7400010, 6, ARM_EXT_V6, do_smlald},
+ { "smlaldx", 0xe7400030, 7, ARM_EXT_V6, do_smlald},
+ { "smlsd", 0xe7000050, 5, ARM_EXT_V6, do_smlad},
+ { "smlsdx", 0xe7000070, 6, ARM_EXT_V6, do_smlad},
+ { "smlsld", 0xe7400050, 6, ARM_EXT_V6, do_smlald},
+ { "smlsldx", 0xe7400070, 7, ARM_EXT_V6, do_smlald},
+ { "smmla", 0xe7500010, 5, ARM_EXT_V6, do_smlad},
+ { "smmlar", 0xe7500030, 6, ARM_EXT_V6, do_smlad},
+ { "smmls", 0xe75000d0, 5, ARM_EXT_V6, do_smlad},
+ { "smmlsr", 0xe75000f0, 6, ARM_EXT_V6, do_smlad},
+ { "smmul", 0xe750f010, 5, ARM_EXT_V6, do_smmul},
+ { "smmulr", 0xe750f030, 6, ARM_EXT_V6, do_smmul},
+ { "smuad", 0xe700f010, 5, ARM_EXT_V6, do_smmul},
+ { "smuadx", 0xe700f030, 6, ARM_EXT_V6, do_smmul},
+ { "smusd", 0xe700f050, 5, ARM_EXT_V6, do_smmul},
+ { "smusdx", 0xe700f070, 6, ARM_EXT_V6, do_smmul},
+ { "srsia", 0xf8cd0500, 0, ARM_EXT_V6, do_srs},
+ { "srsib", 0xf9cd0500, 0, ARM_EXT_V6, do_srs},
+ { "srsda", 0xf84d0500, 0, ARM_EXT_V6, do_srs},
+ { "srsdb", 0xf94d0500, 0, ARM_EXT_V6, do_srs},
+ { "ssat", 0xe6a00010, 4, ARM_EXT_V6, do_ssat},
+ { "ssat16", 0xe6a00f30, 6, ARM_EXT_V6, do_ssat16},
+ { "strex", 0xe1800f90, 5, ARM_EXT_V6, do_strex},
+ { "umaal", 0xe0400090, 5, ARM_EXT_V6, do_umaal},
+ { "usad8", 0xe780f010, 5, ARM_EXT_V6, do_smmul},
+ { "usada8", 0xe7800010, 6, ARM_EXT_V6, do_smlad},
+ { "usat", 0xe6e00010, 4, ARM_EXT_V6, do_usat},
+ { "usat16", 0xe6e00f30, 6, ARM_EXT_V6, do_usat16},
+
/* Core FPA instruction set (V1). */
{"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
{"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
@@ -2146,6 +2287,11 @@ static void do_t_adr PARAMS ((char *));
static void do_t_blx PARAMS ((char *));
static void do_t_bkpt PARAMS ((char *));
+/* ARM V6. */
+static void do_t_cps PARAMS ((char *));
+static void do_t_cpy PARAMS ((char *));
+static void do_t_setend PARAMS ((char *));;
+
#define T_OPCODE_MUL 0x4340
#define T_OPCODE_TST 0x4200
#define T_OPCODE_CMN 0x42c0
@@ -2214,6 +2360,7 @@ static int thumb_reg PARAMS ((char ** str, int hi_lo));
#define THUMB_MOVE 0
#define THUMB_COMPARE 1
+#define THUMB_CPY 2
#define THUMB_LOAD 0
#define THUMB_STORE 1
@@ -2306,6 +2453,19 @@ static const struct thumb_opcode tinsns[] =
/* Thumb v2 (ARMv5T). */
{"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
{"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
+
+ /* ARM V6. */
+ {"cpsie", 0xb660, 2, ARM_EXT_V6, do_t_cps},
+ {"cpsid", 0xb670, 2, ARM_EXT_V6, do_t_cps},
+ {"cpy", 0x4600, 2, ARM_EXT_V6, do_t_cpy},
+ {"rev", 0xba00, 2, ARM_EXT_V6, do_t_arit},
+ {"rev16", 0xba40, 2, ARM_EXT_V6, do_t_arit},
+ {"revsh", 0xbac0, 2, ARM_EXT_V6, do_t_arit},
+ {"setend", 0xb650, 2, ARM_EXT_V6, do_t_setend},
+ {"sxth", 0xb200, 2, ARM_EXT_V6, do_t_arit},
+ {"sxtb", 0xb240, 2, ARM_EXT_V6, do_t_arit},
+ {"uxth", 0xb280, 2, ARM_EXT_V6, do_t_arit},
+ {"uxtb", 0xb2c0, 2, ARM_EXT_V6, do_t_arit},
};
#define BAD_ARGS _("bad arguments to instruction")
@@ -4701,6 +4861,951 @@ do_bxj (str)
end_of_line (str);
}
+/* ARM V6 umaal (argument parse). */
+
+static void
+do_umaal (str)
+ char *str;
+{
+
+ int rdlo, rdhi, rm, rs;
+
+ skip_whitespace (str);
+ if ((rdlo = reg_required_here (& str, 12)) == FAIL
+ || skip_past_comma (& str) == FAIL
+ || (rdhi = reg_required_here (& str, 16)) == FAIL
+ || skip_past_comma (& str) == FAIL
+ || (rm = reg_required_here (& str, 0)) == FAIL
+ || skip_past_comma (& str) == FAIL
+ || (rm = reg_required_here (& str, 8)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ end_of_line (str);
+}
+
+/* ARM V6 strex (argument parse). */
+
+static void
+do_strex (str)
+ char *str;
+{
+ int rd, rm, rn;
+
+ /* Parse Rd, Rm,. */
+ skip_whitespace (str);
+ if ((rd = reg_required_here (& str, 12)) == FAIL
+ || skip_past_comma (& str) == FAIL
+ || (rm = reg_required_here (& str, 0)) == FAIL
+ || skip_past_comma (& str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ if (rd == REG_PC || rm == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+ if (rd == rm)
+ {
+ inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
+ return;
+ }
+
+ /* Skip past '['. */
+ if ((strlen (str) >= 1)
+ && strncmp (str, "[", 1) == 0)
+ str+=1;
+ skip_whitespace (str);
+
+ /* Parse Rn. */
+ if ((rn = reg_required_here (& str, 16)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ else if (rn == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+ if (rd == rn)
+ {
+ inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
+ return;
+ }
+ skip_whitespace (str);
+
+ /* Skip past ']'. */
+ if ((strlen (str) >= 1)
+ && strncmp (str, "]", 1) == 0)
+ str+=1;
+
+ end_of_line (str);
+}
+
+/* ARM V6 ssat (argument parse). */
+
+static void
+do_ssat (str)
+ char* str;
+{
+ do_sat (&str, /*bias=*/-1);
+ end_of_line (str);
+}
+
+/* ARM V6 usat (argument parse). */
+
+static void
+do_usat (str)
+ char* str;
+{
+ do_sat (&str, /*bias=*/0);
+ end_of_line (str);
+}
+
+static void
+do_sat (str, bias)
+ char **str;
+ int bias;
+{
+ int rd, rm;
+ expressionS expr;
+
+ skip_whitespace (*str);
+
+ /* Parse <Rd>, field. */
+ if ((rd = reg_required_here (str, 12)) == FAIL
+ || skip_past_comma (str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ if (rd == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ /* Parse #<immed>, field. */
+ if (is_immediate_prefix (**str))
+ (*str)++;
+ else
+ {
+ inst.error = _("immediate expression expected");
+ return;
+ }
+ if (my_get_expression (&expr, str))
+ {
+ inst.error = _("bad expression");
+ return;
+ }
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("constant expression expected");
+ return;
+ }
+ if (expr.X_add_number + bias < 0
+ || expr.X_add_number + bias > 31)
+ {
+ inst.error = _("immediate value out of range");
+ return;
+ }
+ inst.instruction |= (expr.X_add_number + bias) << 16;
+ if (skip_past_comma (str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ /* Parse <Rm> field. */
+ if ((rm = reg_required_here (str, 0)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ if (rm == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ if (skip_past_comma (str) == SUCCESS)
+ decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
+}
+
+/* ARM V6 ssat16 (argument parse). */
+
+static void
+do_ssat16 (str)
+ char *str;
+{
+ do_sat16 (&str, /*bias=*/-1);
+ end_of_line (str);
+}
+
+static void
+do_usat16 (str)
+ char *str;
+{
+ do_sat16 (&str, /*bias=*/0);
+ end_of_line (str);
+}
+
+static void
+do_sat16 (str, bias)
+ char **str;
+ int bias;
+{
+ int rd, rm;
+ expressionS expr;
+
+ skip_whitespace (*str);
+
+ /* Parse the <Rd> field. */
+ if ((rd = reg_required_here (str, 12)) == FAIL
+ || skip_past_comma (str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ if (rd == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ /* Parse #<immed>, field. */
+ if (is_immediate_prefix (**str))
+ (*str)++;
+ else
+ {
+ inst.error = _("immediate expression expected");
+ return;
+ }
+ if (my_get_expression (&expr, str))
+ {
+ inst.error = _("bad expression");
+ return;
+ }
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("constant expression expected");
+ return;
+ }
+ if (expr.X_add_number + bias < 0
+ || expr.X_add_number + bias > 15)
+ {
+ inst.error = _("immediate value out of range");
+ return;
+ }
+ inst.instruction |= (expr.X_add_number + bias) << 16;
+ if (skip_past_comma (str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ /* Parse <Rm> field. */
+ if ((rm = reg_required_here (str, 0)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ if (rm == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+}
+
+/* ARM V6 srs (argument parse). */
+
+static void
+do_srs (str)
+ char* str;
+{
+ char *exclam;
+ skip_whitespace (str);
+ exclam = strchr (str, '!');
+ if (exclam)
+ *exclam = '\0';
+ do_cps_mode (&str);
+ if (exclam)
+ *exclam = '!';
+ if (*str == '!')
+ {
+ inst.instruction |= WRITE_BACK;
+ str++;
+ }
+ end_of_line (str);
+}
+
+/* ARM V6 SMMUL (argument parse). */
+
+static void
+do_smmul (str)
+ char* str;
+{
+ int rd, rm, rs;
+
+ skip_whitespace (str);
+ if ((rd = reg_required_here (&str, 16)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rs = reg_required_here (&str, 8)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ if (rd == REG_PC
+ || rm == REG_PC
+ || rs == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ end_of_line (str);
+
+}
+
+/* ARM V6 SMLALD (argument parse). */
+
+static void
+do_smlald (str)
+ char* str;
+{
+ int rdlo, rdhi, rm, rs;
+ skip_whitespace (str);
+ if ((rdlo = reg_required_here (&str, 12)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rdhi = reg_required_here (&str, 16)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rs = reg_required_here (&str, 8)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ if (rdlo == REG_PC
+ || rdhi == REG_PC
+ || rm == REG_PC
+ || rs == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ end_of_line (str);
+}
+
+/* ARM V6 SMLAD (argument parse). Signed multiply accumulate dual.
+ smlad{x}{<cond>} Rd, Rm, Rs, Rn */
+
+static void
+do_smlad (str)
+ char *str;
+{
+ int rd, rm, rs, rn;
+
+ skip_whitespace (str);
+ if ((rd = reg_required_here (&str, 16)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rs = reg_required_here (&str, 8)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rn = reg_required_here (&str, 12)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ if (rd == REG_PC
+ || rn == REG_PC
+ || rs == REG_PC
+ || rm == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ end_of_line (str);
+}
+
+/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
+ preserving the other bits.
+
+ setend <endian_specifier>, where <endian_specifier> is either
+ BE or LE. */
+
+static void
+do_setend (str)
+ char *str;
+{
+ if (do_endian_specifier (str))
+ inst.instruction |= 0x200;
+}
+
+/* Returns true if the endian-specifier indicates big-endianness. */
+
+static int
+do_endian_specifier (str)
+ char *str;
+{
+ int big_endian = 0;
+
+ skip_whitespace (str);
+ if (strlen (str) < 2)
+ inst.error = _("missing endian specifier");
+ else if (strncasecmp (str, "BE", 2) == 0)
+ {
+ str += 2;
+ big_endian = 1;
+ }
+ else if (strncasecmp (str, "LE", 2) == 0)
+ str += 2;
+ else
+ inst.error = _("valid endian specifiers are be or le");
+
+ end_of_line (str);
+
+ return big_endian;
+}
+
+/* ARM V6 SXTH.
+
+ SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
+ Condition defaults to COND_ALWAYS.
+ Error if any register uses R15. */
+
+static void
+do_sxth (str)
+ char *str;
+{
+ int rd, rm;
+ expressionS expr;
+ int rotation_clear_mask = 0xfffff3ff;
+ int rotation_eight_mask = 0x00000400;
+ int rotation_sixteen_mask = 0x00000800;
+ int rotation_twenty_four_mask = 0x00000c00;
+
+ skip_whitespace (str);
+ if ((rd = reg_required_here (&str, 12)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ else if (rd == REG_PC || rm == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ /* Zero out the rotation field. */
+ inst.instruction &= rotation_clear_mask;
+
+ /* Check for lack of optional rotation field. */
+ if (skip_past_comma (&str) == FAIL)
+ {
+ end_of_line (str);
+ return;
+ }
+
+ /* Move past 'ROR'. */
+ skip_whitespace (str);
+ if (strncasecmp (str, "ROR", 3) == 0)
+ str+=3;
+ else
+ {
+ inst.error = _("missing rotation field after comma");
+ return;
+ }
+
+ /* Get the immediate constant. */
+ skip_whitespace (str);
+ if (is_immediate_prefix (* str))
+ str++;
+ else
+ {
+ inst.error = _("immediate expression expected");
+ return;
+ }
+
+ if (my_get_expression (&expr, &str))
+ {
+ inst.error = _("bad expression");
+ return;
+ }
+
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("constant expression expected");
+ return;
+ }
+
+ switch (expr.X_add_number)
+ {
+ case 0:
+ /* Rotation field has already been zeroed. */
+ break;
+ case 8:
+ inst.instruction |= rotation_eight_mask;
+ break;
+
+ case 16:
+ inst.instruction |= rotation_sixteen_mask;
+ break;
+
+ case 24:
+ inst.instruction |= rotation_twenty_four_mask;
+ break;
+
+ default:
+ inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
+ break;
+ }
+
+ end_of_line (str);
+
+}
+
+/* ARM V6 SXTAH extracts a 16-bit value from a register, sign
+ extends it to 32-bits, and adds the result to a value in another
+ register. You can specify a rotation by 0, 8, 16, or 24 bits
+ before extracting the 16-bit value.
+ SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
+ Condition defaults to COND_ALWAYS.
+ Error if any register uses R15. */
+
+static void
+do_sxtah (str)
+ char *str;
+{
+ int rd, rn, rm;
+ expressionS expr;
+ int rotation_clear_mask = 0xfffff3ff;
+ int rotation_eight_mask = 0x00000400;
+ int rotation_sixteen_mask = 0x00000800;
+ int rotation_twenty_four_mask = 0x00000c00;
+
+ skip_whitespace (str);
+ if ((rd = reg_required_here (&str, 12)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rn = reg_required_here (&str, 16)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ /* Zero out the rotation field. */
+ inst.instruction &= rotation_clear_mask;
+
+ /* Check for lack of optional rotation field. */
+ if (skip_past_comma (&str) == FAIL)
+ {
+ end_of_line (str);
+ return;
+ }
+
+ /* Move past 'ROR'. */
+ skip_whitespace (str);
+ if (strncasecmp (str, "ROR", 3) == 0)
+ str+=3;
+ else
+ {
+ inst.error = _("missing rotation field after comma");
+ return;
+ }
+
+ /* Get the immediate constant. */
+ skip_whitespace (str);
+ if (is_immediate_prefix (* str))
+ str++;
+ else
+ {
+ inst.error = _("immediate expression expected");
+ return;
+ }
+
+ if (my_get_expression (&expr, &str))
+ {
+ inst.error = _("bad expression");
+ return;
+ }
+
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("constant expression expected");
+ return;
+ }
+
+ switch (expr.X_add_number)
+ {
+ case 0:
+ /* Rotation field has already been zeroed. */
+ break;
+
+ case 8:
+ inst.instruction |= rotation_eight_mask;
+ break;
+
+ case 16:
+ inst.instruction |= rotation_sixteen_mask;
+ break;
+
+ case 24:
+ inst.instruction |= rotation_twenty_four_mask;
+ break;
+
+ default:
+ inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
+ break;
+ }
+
+ end_of_line (str);
+
+}
+
+
+/* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
+ word at the specified address and the following word
+ respectively.
+ Unconditionally executed.
+ Error if Rn is R15.
+*/
+
+static void
+do_rfe (str)
+ char *str;
+{
+ int rn;
+
+ skip_whitespace (str);
+
+ if ((rn = reg_required_here (&str, 16)) == FAIL)
+ return;
+
+ if (rn == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ skip_whitespace (str);
+
+ if (*str == '!')
+ {
+ inst.instruction |= WRITE_BACK;
+ str++;
+ }
+ end_of_line (str);
+}
+
+/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
+ register (argument parse).
+ REV{<cond>} Rd, Rm.
+ Condition defaults to COND_ALWAYS.
+ Error if Rd or Rm are R15. */
+
+static void
+do_rev (str)
+ char* str;
+{
+ int rd, rm;
+
+ skip_whitespace (str);
+
+ if ((rd = reg_required_here (&str, 12)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL)
+ inst.error = BAD_ARGS;
+
+ else if (rd == REG_PC || rm == REG_PC)
+ inst.error = BAD_PC;
+
+ else
+ end_of_line (str);
+}
+
+/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
+ QADD16{<cond>} <Rd>, <Rn>, <Rm>
+ Condition defaults to COND_ALWAYS.
+ Error if Rd, Rn or Rm are R15. */
+
+static void
+do_qadd16 (str)
+ char* str;
+{
+ int rd, rm, rn;
+
+ skip_whitespace (str);
+
+ if ((rd = reg_required_here (&str, 12)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rn = reg_required_here (&str, 16)) == FAIL
+ || skip_past_comma (&str) == FAIL
+ || (rm = reg_required_here (&str, 0)) == FAIL)
+ inst.error = BAD_ARGS;
+
+ else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
+ inst.error = BAD_PC;
+
+ else
+ end_of_line (str);
+}
+
+/* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
+ PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
+ Condition defaults to COND_ALWAYS.
+ Error if Rd, Rn or Rm are R15. */
+
+static void
+do_pkhbt (str)
+ char* str;
+{
+ do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
+}
+
+/* ARM V6 PKHTB (Argument Parse). */
+
+static void
+do_pkhtb (str)
+ char* str;
+{
+ do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
+}
+
+static void
+do_pkh_core (str, shift)
+ char* str;
+ int shift;
+{
+ int rd, rn, rm;
+
+ skip_whitespace (str);
+ if (((rd = reg_required_here (&str, 12)) == FAIL)
+ || (skip_past_comma (&str) == FAIL)
+ || ((rn = reg_required_here (&str, 16)) == FAIL)
+ || (skip_past_comma (&str) == FAIL)
+ || ((rm = reg_required_here (&str, 0)) == FAIL))
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ /* Check for optional shift immediate constant. */
+ if (skip_past_comma (&str) == FAIL)
+ {
+ if (shift == SHIFT_ASR_IMMEDIATE)
+ {
+ /* If the shift specifier is ommited, turn the instruction
+ into pkhbt rd, rm, rn. First, switch the instruction
+ code, and clear the rn and rm fields. */
+ inst.instruction &= 0xfff0f010;
+ /* Now, re-encode the registers. */
+ inst.instruction |= (rm << 16) | rn;
+ }
+ return;
+ }
+
+ decode_shift (&str, shift);
+}
+
+/* ARM V6 Load Register Exclusive instruction (argument parse).
+ LDREX{<cond>} <Rd, [<Rn>]
+ Condition defaults to COND_ALWAYS.
+ Error if Rd or Rn are R15.
+ See ARMARMv6 A4.1.27: LDREX. */
+
+
+static void
+do_ldrex (str)
+ char * str;
+{
+ int rd, rn;
+
+ skip_whitespace (str);
+
+ /* Parse Rd. */
+ if (((rd = reg_required_here (&str, 12)) == FAIL)
+ || (skip_past_comma (&str) == FAIL))
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ else if (rd == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+ skip_whitespace (str);
+
+ /* Skip past '['. */
+ if ((strlen (str) >= 1)
+ &&strncmp (str, "[", 1) == 0)
+ str+=1;
+ skip_whitespace (str);
+
+ /* Parse Rn. */
+ if ((rn = reg_required_here (&str, 16)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ else if (rn == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+ skip_whitespace (str);
+
+ /* Skip past ']'. */
+ if ((strlen (str) >= 1)
+ && strncmp (str, "]", 1) == 0)
+ str+=1;
+
+ end_of_line (str);
+}
+
+/* ARM V6 change processor state instruction (argument parse)
+ CPS, CPSIE, CSPID . */
+
+static void
+do_cps (str)
+ char * str;
+{
+ do_cps_mode (&str);
+ end_of_line (str);
+}
+
+static void
+do_cpsi (str)
+ char * str;
+{
+ do_cps_flags (&str, /*thumb_p=*/0);
+
+ if (skip_past_comma (&str) == SUCCESS)
+ {
+ skip_whitespace (str);
+ do_cps_mode (&str);
+ }
+ end_of_line (str);
+}
+
+static void
+do_cps_mode (str)
+ char **str;
+{
+ expressionS expr;
+
+ skip_whitespace (*str);
+
+ if (! is_immediate_prefix (**str))
+ {
+ inst.error = _("immediate expression expected");
+ return;
+ }
+
+ (*str)++; /* Strip off the immediate signifier. */
+ if (my_get_expression (&expr, str))
+ {
+ inst.error = _("bad expression");
+ return;
+ }
+
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("constant expression expected");
+ return;
+ }
+
+ /* The mode is a 5 bit field. Valid values are 0-31. */
+ if (((unsigned) expr.X_add_number) > 31
+ || (inst.reloc.exp.X_add_number) < 0)
+ {
+ inst.error = _("invalid constant");
+ return;
+ }
+
+ inst.instruction |= expr.X_add_number;
+ return;
+}
+
+static void
+do_cps_flags (str, thumb_p)
+ char **str;
+ int thumb_p;
+{
+ struct cps_flag {
+ char character;
+ unsigned long arm_value;
+ unsigned long thumb_value;
+ };
+ static struct cps_flag flag_table[] = {
+ {'a', 0x100, 0x4 },
+ {'i', 0x080, 0x2 },
+ {'f', 0x040, 0x1 }
+ };
+
+ int saw_a_flag = 0;
+
+ skip_whitespace (*str);
+
+ /* Get the a, f and i flags. */
+ while (**str && **str != ',')
+ {
+ struct cps_flag *p;
+ struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
+ for (p = flag_table; p < q; ++p)
+ if (strncasecmp (*str, &p->character, 1) == 0)
+ {
+ inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
+ saw_a_flag = 1;
+ break;
+ }
+ if (p == q)
+ {
+ inst.error = _("unrecognized flag");
+ return;
+ }
+ (*str)++;
+ }
+ if (!saw_a_flag)
+ inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
+}
+
/* THUMB V5 breakpoint instruction (argument parse)
BKPT <immed_8>. */
@@ -4930,6 +6035,35 @@ do_bkpt (str)
end_of_line (str);
}
+/* THUMB CPS instruction (argument parse). */
+
+static void
+do_t_cps (str)
+ char *str;
+{
+ do_cps_flags (&str, /*thumb_p=*/1);
+ end_of_line (str);
+}
+
+/* THUMB CPY instruction (argument parse). */
+
+static void
+do_t_cpy (str)
+ char *str;
+{
+ thumb_mov_compare (str, THUMB_CPY);
+}
+
+/* THUMB SETEND instruction (argument parse). */
+
+static void
+do_t_setend (str)
+ char *str;
+{
+ if (do_endian_specifier (str))
+ inst.instruction |= 0x8;
+}
+
static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
/* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate. */
@@ -5777,13 +6911,12 @@ md_operand (expr)
}
}
-/* UNRESTRICT should be one if <shift> <register> is permitted for this
- instruction. */
+/* KIND indicates what kind of shifts are accepted. */
static int
-decode_shift (str, unrestrict)
+decode_shift (str, kind)
char ** str;
- int unrestrict;
+ int kind;
{
const struct asm_shift_name * shift;
char * p;
@@ -5813,6 +6946,26 @@ decode_shift (str, unrestrict)
assert (shift->properties->index == shift_properties[shift->properties->index].index);
+ if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
+ && shift->properties->index != SHIFT_LSL
+ && shift->properties->index != SHIFT_ASR)
+ {
+ inst.error = _("'LSL' or 'ASR' required");
+ return FAIL;
+ }
+ else if (kind == SHIFT_LSL_IMMEDIATE
+ && shift->properties->index != SHIFT_LSL)
+ {
+ inst.error = _("'LSL' required");
+ return FAIL;
+ }
+ else if (kind == SHIFT_ASR_IMMEDIATE
+ && shift->properties->index != SHIFT_ASR)
+ {
+ inst.error = _("'ASR' required");
+ return FAIL;
+ }
+
if (shift->properties->index == SHIFT_RRX)
{
* str = p;
@@ -5822,7 +6975,7 @@ decode_shift (str, unrestrict)
skip_whitespace (p);
- if (unrestrict && reg_required_here (& p, 8) != FAIL)
+ if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
{
inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
* str = p;
@@ -5830,7 +6983,7 @@ decode_shift (str, unrestrict)
}
else if (! is_immediate_prefix (* p))
{
- inst.error = (unrestrict
+ inst.error = (NO_SHIFT_RESTRICT
? _("shift requires register or #expression")
: _("shift requires #expression"));
* str = p;
@@ -6309,7 +7462,7 @@ ldst_extend (str)
inst.instruction |= add | OFFSET_REG;
if (skip_past_comma (str) == SUCCESS)
- return decode_shift (str, SHIFT_RESTRICT);
+ return decode_shift (str, SHIFT_IMMEDIATE);
return SUCCESS;
}
@@ -8900,7 +10053,7 @@ thumb_mov_compare (str, move)
return;
}
- if (is_immediate_prefix (*str))
+ if (move != THUMB_CPY && is_immediate_prefix (*str))
{
str++;
if (my_get_expression (&inst.reloc.exp, &str))
@@ -8911,7 +10064,7 @@ thumb_mov_compare (str, move)
if (Rs != FAIL)
{
- if (Rs < 8 && Rd < 8)
+ if (move != THUMB_CPY && Rs < 8 && Rd < 8)
{
if (move == THUMB_MOVE)
/* A move of two lowregs is encoded as ADD Rd, Rs, #0
@@ -8925,7 +10078,7 @@ thumb_mov_compare (str, move)
{
if (move == THUMB_MOVE)
inst.instruction = T_OPCODE_MOV_HR;
- else
+ else if (move != THUMB_CPY)
inst.instruction = T_OPCODE_CMP_HR;
if (Rd > 7)
@@ -12197,6 +13350,8 @@ 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},
+ {"arm1136js", ARM_ARCH_V6, FPU_NONE},
+ {"arm1136jfs", ARM_ARCH_V6, FPU_ARCH_VFP_V2},
/* ??? XSCALE is really an architecture. */
{"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
/* ??? iwmmxt is not a processor. */
@@ -12235,6 +13390,7 @@ static struct arm_arch_option_table arm_archs[] =
{"armv5te", ARM_ARCH_V5TE, FPU_ARCH_VFP},
{"armv5texp", ARM_ARCH_V5TExP, FPU_ARCH_VFP},
{"armv5tej", ARM_ARCH_V5TEJ, FPU_ARCH_VFP},
+ {"armv6", ARM_ARCH_V6, FPU_ARCH_VFP},
{"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
{"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
{NULL, 0, 0}
@@ -12282,6 +13438,7 @@ static struct arm_fpu_option_table arm_fpus[] =
{"vfpxd", FPU_ARCH_VFP_V1xD},
{"arm1020t", FPU_ARCH_VFP_V1},
{"arm1020e", FPU_ARCH_VFP_V2},
+ {"arm1136jfs", FPU_ARCH_VFP_V2},
{NULL, 0}
};