From 9a90c996a48a22238f3e801ddad32efbab273722 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 6 Dec 2003 01:25:29 +0000 Subject: [PATCH] * 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. --- gas/ChangeLog | 52 ++ gas/NEWS | 2 + gas/config/tc-arm.c | 1433 +++++++++++++++++++++++++++++++++++---- gas/doc/c-arm.texi | 10 +- gas/testsuite/ChangeLog | 10 + gas/testsuite/gas/arm/archv6.d | 219 ++++++ gas/testsuite/gas/arm/archv6.s | 216 ++++++ gas/testsuite/gas/arm/arm.exp | 4 + gas/testsuite/gas/arm/thumbv6.d | 19 + gas/testsuite/gas/arm/thumbv6.s | 17 + opcodes/ChangeLog | 8 + opcodes/arm-dis.c | 10 + opcodes/arm-opc.h | 140 ++++ 13 files changed, 1999 insertions(+), 141 deletions(-) create mode 100644 gas/testsuite/gas/arm/archv6.d create mode 100644 gas/testsuite/gas/arm/archv6.s create mode 100644 gas/testsuite/gas/arm/thumbv6.d create mode 100644 gas/testsuite/gas/arm/thumbv6.s diff --git a/gas/ChangeLog b/gas/ChangeLog index 8ce8aecfc..679864c4f 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,55 @@ +2003-12-05 Ricardo Anguiano + Mark Mitchell + Richard Earnshaw + + 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. + 2003-12-06 Christian Groessler * config/tc-z8k.c (parse_reg): Be case insensitive when checking diff --git a/gas/NEWS b/gas/NEWS index 1f704d2a3..66c15c923 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -1,5 +1,7 @@ -*- text -*- +* Added support for ARM V6. + * Added support for sh4a and variants. * Support for Renesas M32R2 added. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index a68435046..a08b024e9 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") @@ -4483,222 +4643,1167 @@ do_co_reg2c (str) as_tsktsk (_("Warning: instruction unpredictable when using r15")); - if (skip_past_comma (& str) == FAIL - || cp_reg_required_here (& str, 0) == FAIL) + if (skip_past_comma (& str) == FAIL + || cp_reg_required_here (& str, 0) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + end_of_line (str); +} + +/* ARM V5 count-leading-zeroes instruction (argument parse) + CLZ{} , + Condition defaults to COND_ALWAYS. + Error if Rd or Rm are R15. */ + +static void +do_clz (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 V5 (argument parse) + LDC2{L} , , + STC2{L} , , + Instruction is not conditional, and has 0xf in the condition field. + Otherwise, it's the same as LDC/STC. */ + +static void +do_lstc2 (str) + char * str; +{ + skip_whitespace (str); + + if (co_proc_number (& str) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + } + else if (skip_past_comma (& str) == FAIL + || cp_reg_required_here (& str, 12) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + } + else if (skip_past_comma (& str) == FAIL + || cp_address_required_here (&str, CP_WB_OK) == FAIL) + { + if (! inst.error) + inst.error = BAD_ARGS; + } + else + end_of_line (str); +} + +/* ARM V5 (argument parse) + CDP2 , , , , , + Instruction is not conditional, and has 0xf in the condition field. + Otherwise, it's the same as CDP. */ + +static void +do_cdp2 (str) + char * str; +{ + skip_whitespace (str); + + if (co_proc_number (& str) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == FAIL + || cp_opc_expr (& str, 20,4) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == FAIL + || cp_reg_required_here (& str, 12) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == FAIL + || cp_reg_required_here (& str, 16) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == FAIL + || cp_reg_required_here (& str, 0) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == SUCCESS) + { + if (cp_opc_expr (& str, 5, 3) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + } + + end_of_line (str); +} + +/* ARM V5 (argument parse) + MCR2 , , , , , + MRC2 , , , , , + Instruction is not conditional, and has 0xf in the condition field. + Otherwise, it's the same as MCR/MRC. */ + +static void +do_co_reg2 (str) + char * str; +{ + skip_whitespace (str); + + if (co_proc_number (& str) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == FAIL + || cp_opc_expr (& str, 21, 3) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == FAIL + || reg_required_here (& str, 12) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == FAIL + || cp_reg_required_here (& str, 16) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == FAIL + || cp_reg_required_here (& str, 0) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + + if (skip_past_comma (& str) == SUCCESS) + { + if (cp_opc_expr (& str, 5, 3) == FAIL) + { + if (!inst.error) + inst.error = BAD_ARGS; + return; + } + } + + end_of_line (str); +} + +/* ARM v5TEJ. Jump to Jazelle code. */ +static void +do_bxj (str) + char * str; +{ + int reg; + + skip_whitespace (str); + + if ((reg = reg_required_here (&str, 0)) == FAIL) + { + inst.error = BAD_ARGS; + return; + } + + /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */ + if (reg == REG_PC) + as_tsktsk (_("use of r15 in bxj is not really useful")); + + 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 , 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 #, 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 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 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 #, 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 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}{} 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 , where 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 {} , {, } + 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{} , , {, } + 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) { - if (!inst.error) - inst.error = BAD_ARGS; + inst.error = BAD_PC; return; } + skip_whitespace (str); + + if (*str == '!') + { + inst.instruction |= WRITE_BACK; + str++; + } end_of_line (str); } -/* ARM V5 count-leading-zeroes instruction (argument parse) - CLZ{} , - Condition defaults to COND_ALWAYS. - Error if Rd or Rm are R15. */ +/* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit + register (argument parse). + REV{} Rd, Rm. + Condition defaults to COND_ALWAYS. + Error if Rd or Rm are R15. */ static void -do_clz (str) - char * str; +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)) + 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 ) + else if (rd == REG_PC || rm == REG_PC) inst.error = BAD_PC; else end_of_line (str); } -/* ARM V5 (argument parse) - LDC2{L} , , - STC2{L} , , - Instruction is not conditional, and has 0xf in the condition field. - Otherwise, it's the same as LDC/STC. */ +/* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse). + QADD16{} , , + Condition defaults to COND_ALWAYS. + Error if Rd, Rn or Rm are R15. */ static void -do_lstc2 (str) - char * str; +do_qadd16 (str) + char* str; { + int rd, rm, rn; + skip_whitespace (str); - if (co_proc_number (& str) == FAIL) - { - if (!inst.error) - inst.error = BAD_ARGS; - } - else if (skip_past_comma (& str) == FAIL - || cp_reg_required_here (& str, 12) == FAIL) - { - if (!inst.error) - inst.error = BAD_ARGS; - } - else if (skip_past_comma (& str) == FAIL - || cp_address_required_here (&str, CP_WB_OK) == FAIL) - { - if (! inst.error) - inst.error = BAD_ARGS; - } + 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 V5 (argument parse) - CDP2 , , , , , - Instruction is not conditional, and has 0xf in the condition field. - Otherwise, it's the same as CDP. */ +/* ARM V6 Pack Halfword Bottom Top instruction (argument parse). + PKHBT {} , , {, LSL #} + 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_cdp2 (str) - char * str; +do_pkh_core (str, shift) + char* str; + int shift; { - skip_whitespace (str); + int rd, rn, rm; - if (co_proc_number (& str) == FAIL) + 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)) { - if (!inst.error) - inst.error = BAD_ARGS; + inst.error = BAD_ARGS; return; } - if (skip_past_comma (& str) == FAIL - || cp_opc_expr (& str, 20,4) == FAIL) + else if (rd == REG_PC || rn == REG_PC || rm == REG_PC) { - if (!inst.error) - inst.error = BAD_ARGS; + inst.error = BAD_PC; return; } - if (skip_past_comma (& str) == FAIL - || cp_reg_required_here (& str, 12) == FAIL) + /* Check for optional shift immediate constant. */ + if (skip_past_comma (&str) == FAIL) { - if (!inst.error) - inst.error = BAD_ARGS; + 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; } - if (skip_past_comma (& str) == FAIL - || cp_reg_required_here (& str, 16) == FAIL) + decode_shift (&str, shift); +} + +/* ARM V6 Load Register Exclusive instruction (argument parse). + LDREX{} ] + 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)) { - if (!inst.error) - inst.error = BAD_ARGS; + inst.error = BAD_ARGS; return; } - - if (skip_past_comma (& str) == FAIL - || cp_reg_required_here (& str, 0) == FAIL) + else if (rd == REG_PC) { - if (!inst.error) - inst.error = BAD_ARGS; + inst.error = BAD_PC; return; } + skip_whitespace (str); - if (skip_past_comma (& str) == SUCCESS) + /* 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) { - if (cp_opc_expr (& str, 5, 3) == FAIL) - { - if (!inst.error) - inst.error = BAD_ARGS; - return; - } + 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 V5 (argument parse) - MCR2 , , , , , - MRC2 , , , , , - Instruction is not conditional, and has 0xf in the condition field. - Otherwise, it's the same as MCR/MRC. */ +/* ARM V6 change processor state instruction (argument parse) + CPS, CPSIE, CSPID . */ static void -do_co_reg2 (str) - char * str; +do_cps (str) + char * str; { - skip_whitespace (str); + do_cps_mode (&str); + end_of_line (str); +} - if (co_proc_number (& str) == FAIL) - { - if (!inst.error) - inst.error = BAD_ARGS; - return; - } +static void +do_cpsi (str) + char * str; +{ + do_cps_flags (&str, /*thumb_p=*/0); - if (skip_past_comma (& str) == FAIL - || cp_opc_expr (& str, 21, 3) == FAIL) + if (skip_past_comma (&str) == SUCCESS) { - if (!inst.error) - inst.error = BAD_ARGS; - return; + skip_whitespace (str); + do_cps_mode (&str); } + end_of_line (str); +} - if (skip_past_comma (& str) == FAIL - || reg_required_here (& str, 12) == FAIL) +static void +do_cps_mode (str) + char **str; +{ + expressionS expr; + + skip_whitespace (*str); + + if (! is_immediate_prefix (**str)) { - if (!inst.error) - inst.error = BAD_ARGS; + inst.error = _("immediate expression expected"); return; } - if (skip_past_comma (& str) == FAIL - || cp_reg_required_here (& str, 16) == FAIL) + (*str)++; /* Strip off the immediate signifier. */ + if (my_get_expression (&expr, str)) { - if (!inst.error) - inst.error = BAD_ARGS; + inst.error = _("bad expression"); return; } - if (skip_past_comma (& str) == FAIL - || cp_reg_required_here (& str, 0) == FAIL) + if (expr.X_op != O_constant) { - if (!inst.error) - inst.error = BAD_ARGS; + inst.error = _("constant expression expected"); return; } - - if (skip_past_comma (& str) == SUCCESS) + + /* 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) { - if (cp_opc_expr (& str, 5, 3) == FAIL) - { - if (!inst.error) - inst.error = BAD_ARGS; - return; - } + inst.error = _("invalid constant"); + return; } - - end_of_line (str); + + inst.instruction |= expr.X_add_number; + return; } -/* ARM v5TEJ. Jump to Jazelle code. */ static void -do_bxj (str) - char * str; +do_cps_flags (str, thumb_p) + char **str; + int thumb_p; { - int reg; + 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 } + }; - skip_whitespace (str); + int saw_a_flag = 0; - if ((reg = reg_required_here (&str, 0)) == FAIL) + skip_whitespace (*str); + + /* Get the a, f and i flags. */ + while (**str && **str != ',') { - inst.error = BAD_ARGS; - return; + 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)++; } - - /* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */ - if (reg == REG_PC) - as_tsktsk (_("use of r15 in bxj is not really useful")); - - end_of_line (str); + if (!saw_a_flag) + inst.error = _("no 'a', 'i', or 'f' flags for 'cps'"); } /* THUMB V5 breakpoint instruction (argument parse) @@ -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 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} }; diff --git a/gas/doc/c-arm.texi b/gas/doc/c-arm.texi index dfb5f8653..1e010bfb7 100644 --- a/gas/doc/c-arm.texi +++ b/gas/doc/c-arm.texi @@ -90,6 +90,8 @@ recognized: @code{arm1020}, @code{arm1020t}, @code{arm1020e}, +@code{arm1136js}, +@code{arm1136jfs}, @code{ep9312} (ARM920 with Cirrus Maverick coprocessor), @code{i80200} (Intel XScale processor) @code{iwmmxt} (Intel(r) XScale processor with Wireless MMX(tm) technology coprocessor) @@ -128,7 +130,8 @@ names are recognized: @code{armv5t}, @code{armv5txm}, @code{armv5te}, -@code{armv5texp} +@code{armv5texp}, +@code{armv6}, @code{iwmmxt} and @code{xscale}. @@ -161,9 +164,10 @@ The following format options are recognized: @code{vfp10-r0}, @code{vfp9}, @code{vfpxd}, -@code{arm1020t} +@code{arm1020t}, +@code{arm1020e}, and -@code{arm1020e}. +@code{arm1136jfs}. In addition to determining which instructions are assembled, this option also affects the way in which the @code{.double} assembler directive behaves diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 84052ea99..274770dc6 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2003-12-05 Ricardo Anguiano + Mark Mitchell + Richard Earnshaw + + * 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. + 2003-12-06 Christian Groessler * gas/z8k/ctrl-names.d: New file. diff --git a/gas/testsuite/gas/arm/archv6.d b/gas/testsuite/gas/arm/archv6.d new file mode 100644 index 000000000..73de75de2 --- /dev/null +++ b/gas/testsuite/gas/arm/archv6.d @@ -0,0 +1,219 @@ +#name: ARM V6 instructions +#as: -march=armv6 +#objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section .text: +0+000 <[^>]*> f102000f ? cps #15 +0+004 <[^>]*> f10c00c0 ? cpsid if +0+008 <[^>]*> f10800c0 ? cpsie if +0+00c <[^>]*> e1942f9f ? ldrex r2, \[r4\] +0+010 <[^>]*> 11984f9f ? ldrexne r4, \[r8\] +0+014 <[^>]*> fc4570c3 ? mcrr2 0, 12, r7, r5, cr3 +0+018 <[^>]*> fc5570c3 ? mrrc2 0, 12, r7, r5, cr3 +0+01c <[^>]*> e6852018 ? pkhbt r2, r5, r8 +0+020 <[^>]*> e6852198 ? pkhbt r2, r5, r8, LSL #3 +0+024 <[^>]*> e6852198 ? pkhbt r2, r5, r8, LSL #3 +0+028 <[^>]*> 06852198 ? pkhbteq r2, r5, r8, LSL #3 +0+02c <[^>]*> e6882015 ? pkhbt r2, r8, r5 +0+030 <[^>]*> e68521d8 ? pkhtb r2, r5, r8, ASR #3 +0+034 <[^>]*> e68521d8 ? pkhtb r2, r5, r8, ASR #3 +0+038 <[^>]*> 068521d8 ? pkhtbeq r2, r5, r8, ASR #3 +0+03c <[^>]*> e6242f17 ? qadd16 r2, r4, r7 +0+040 <[^>]*> 16242f17 ? qadd16ne r2, r4, r7 +0+044 <[^>]*> e6242f97 ? qadd8 r2, r4, r7 +0+048 <[^>]*> 16242f97 ? qadd8ne r2, r4, r7 +0+04c <[^>]*> e6242f37 ? qaddsubx r2, r4, r7 +0+050 <[^>]*> 16242f37 ? qaddsubxne r2, r4, r7 +0+054 <[^>]*> e6242f77 ? qsub16 r2, r4, r7 +0+058 <[^>]*> 16242f77 ? qsub16ne r2, r4, r7 +0+05c <[^>]*> e6242ff7 ? qsub8 r2, r4, r7 +0+060 <[^>]*> 16242ff7 ? qsub8ne r2, r4, r7 +0+064 <[^>]*> e6242f57 ? qsubaddx r2, r4, r7 +0+068 <[^>]*> e6242f57 ? qsubaddx r2, r4, r7 +0+06c <[^>]*> e6bf2f34 ? rev r2, r4 +0+070 <[^>]*> e6bf2fb4 ? rev16 r2, r4 +0+074 <[^>]*> 16bf3fb5 ? rev16ne r3, r5 +0+078 <[^>]*> 16bf3f35 ? revne r3, r5 +0+07c <[^>]*> e6ff2fb4 ? revsh r2, r4 +0+080 <[^>]*> 16ff3fb5 ? revshne r3, r5 +0+084 <[^>]*> f8120a00 ? rfeda r2 +0+088 <[^>]*> f9320a00 ? rfedb r2! +0+08c <[^>]*> f8120a00 ? rfeda r2 +0+090 <[^>]*> f9320a00 ? rfedb r2! +0+094 <[^>]*> f9b20a00 ? rfeib r2! +0+098 <[^>]*> f8920a00 ? rfeia r2 +0+09c <[^>]*> f8920a00 ? rfeia r2 +0+0a0 <[^>]*> f9b20a00 ? rfeib r2! +0+0a4 <[^>]*> e6142f17 ? sadd16 r2, r4, r7 +0+0a8 <[^>]*> 16142f17 ? sadd16ne r2, r4, r7 +0+0ac <[^>]*> e6b42075 ? sxtah r2, r4, r5 +0+0b0 <[^>]*> e6b42475 ? sxtah r2, r4, r5, ROR #8 +0+0b4 <[^>]*> 16b42075 ? sxtahne r2, r4, r5 +0+0b8 <[^>]*> 16b42475 ? sxtahne r2, r4, r5, ROR #8 +0+0bc <[^>]*> e6142f97 ? sadd8 r2, r4, r7 +0+0c0 <[^>]*> 16142f97 ? sadd8ne r2, r4, r7 +0+0c4 <[^>]*> e6842075 ? sxtab16 r2, r4, r5 +0+0c8 <[^>]*> e6842475 ? sxtab16 r2, r4, r5, ROR #8 +0+0cc <[^>]*> 16842075 ? sxtab16ne r2, r4, r5 +0+0d0 <[^>]*> 16842475 ? sxtab16ne r2, r4, r5, ROR #8 +0+0d4 <[^>]*> e6a42075 ? sxtab r2, r4, r5 +0+0d8 <[^>]*> e6a42475 ? sxtab r2, r4, r5, ROR #8 +0+0dc <[^>]*> 16a42075 ? sxtabne r2, r4, r5 +0+0e0 <[^>]*> 16a42475 ? sxtabne r2, r4, r5, ROR #8 +0+0e4 <[^>]*> e6142f37 ? saddaddx r2, r4, r7 +0+0e8 <[^>]*> 16142f37 ? saddaddxne r2, r4, r7 +0+0ec <[^>]*> e68210b3 ? sel r1, r2, r3 +0+0f0 <[^>]*> 168210b3 ? selne r1, r2, r3 +0+0f4 <[^>]*> f1010200 ? setend be +0+0f8 <[^>]*> f1010000 ? setend le +0+0fc <[^>]*> e6342f17 ? shadd16 r2, r4, r7 +0+100 <[^>]*> 16342f17 ? shadd16ne r2, r4, r7 +0+104 <[^>]*> e6342f97 ? shadd8 r2, r4, r7 +0+108 <[^>]*> 16342f97 ? shadd8ne r2, r4, r7 +0+10c <[^>]*> e6342f37 ? shaddsubx r2, r4, r7 +0+110 <[^>]*> 16342f37 ? shaddsubxne r2, r4, r7 +0+114 <[^>]*> e6342f77 ? shsub16 r2, r4, r7 +0+118 <[^>]*> 16342f77 ? shsub16ne r2, r4, r7 +0+11c <[^>]*> e6342ff7 ? shsub8 r2, r4, r7 +0+120 <[^>]*> 16342ff7 ? shsub8ne r2, r4, r7 +0+124 <[^>]*> e6342f57 ? shsubaddx r2, r4, r7 +0+128 <[^>]*> 16342f57 ? shsubaddxne r2, r4, r7 +0+12c <[^>]*> e7014312 ? smlad r1, r2, r3, r4 +0+130 <[^>]*> d7014312 ? smladle r1, r2, r3, r4 +0+134 <[^>]*> e7014332 ? smladx r1, r2, r3, r4 +0+138 <[^>]*> d7014332 ? smladxle r1, r2, r3, r4 +0+13c <[^>]*> e7421413 ? smlald r1, r2, r3, r4 +0+140 <[^>]*> d7421413 ? smlaldle r1, r2, r3, r4 +0+144 <[^>]*> e7421433 ? smlaldx r1, r2, r3, r4 +0+148 <[^>]*> d7421433 ? smlaldxle r1, r2, r3, r4 +0+14c <[^>]*> e7014352 ? smlsd r1, r2, r3, r4 +0+150 <[^>]*> d7014352 ? smlsdle r1, r2, r3, r4 +0+154 <[^>]*> e7014372 ? smlsdx r1, r2, r3, r4 +0+158 <[^>]*> d7014372 ? smlsdxle r1, r2, r3, r4 +0+15c <[^>]*> e7421453 ? smlsld r1, r2, r3, r4 +0+160 <[^>]*> d7421453 ? smlsldle r1, r2, r3, r4 +0+164 <[^>]*> e7421473 ? smlsldx r1, r2, r3, r4 +0+168 <[^>]*> d7421473 ? smlsldxle r1, r2, r3, r4 +0+16c <[^>]*> e7514312 ? smmla r1, r2, r3, r4 +0+170 <[^>]*> d7514312 ? smmlale r1, r2, r3, r4 +0+174 <[^>]*> e7514332 ? smmlar r1, r2, r3, r4 +0+178 <[^>]*> d7514332 ? smmlarle r1, r2, r3, r4 +0+17c <[^>]*> e75143d2 ? smmls r1, r2, r3, r4 +0+180 <[^>]*> d75143d2 ? smmlsle r1, r2, r3, r4 +0+184 <[^>]*> e75143f2 ? smmlsr r1, r2, r3, r4 +0+188 <[^>]*> d75143f2 ? smmlsrle r1, r2, r3, r4 +0+18c <[^>]*> e751f312 ? smmul r1, r2, r3 +0+190 <[^>]*> d751f312 ? smmulle r1, r2, r3 +0+194 <[^>]*> e751f332 ? smmulr r1, r2, r3 +0+198 <[^>]*> d751f332 ? smmulrle r1, r2, r3 +0+19c <[^>]*> e701f312 ? smuad r1, r2, r3 +0+1a0 <[^>]*> d701f312 ? smuadle r1, r2, r3 +0+1a4 <[^>]*> e701f332 ? smuadx r1, r2, r3 +0+1a8 <[^>]*> d701f332 ? smuadxle r1, r2, r3 +0+1ac <[^>]*> e701f352 ? smusd r1, r2, r3 +0+1b0 <[^>]*> d701f352 ? smusdle r1, r2, r3 +0+1b4 <[^>]*> e701f372 ? smusdx r1, r2, r3 +0+1b8 <[^>]*> d701f372 ? smusdxle r1, r2, r3 +0+1bc <[^>]*> f8cd0510 ? srsia #16 +0+1c0 <[^>]*> f9ed0510 ? srsib #16! +0+1c4 <[^>]*> e6a01012 ? ssat r1, #1, r2 +0+1c8 <[^>]*> e6a01152 ? ssat r1, #1, r2, ASR #2 +0+1cc <[^>]*> e6a01112 ? ssat r1, #1, r2, LSL #2 +0+1d0 <[^>]*> e6a01f31 ? ssat16 r1, #1, r1 +0+1d4 <[^>]*> d6a01f31 ? ssat16le r1, #1, r1 +0+1d8 <[^>]*> e6142f77 ? ssub16 r2, r4, r7 +0+1dc <[^>]*> 16142f77 ? ssub16ne r2, r4, r7 +0+1e0 <[^>]*> e6142ff7 ? ssub8 r2, r4, r7 +0+1e4 <[^>]*> 16142ff7 ? ssub8ne r2, r4, r7 +0+1e8 <[^>]*> e6142f57 ? ssubaddx r2, r4, r7 +0+1ec <[^>]*> 16142f57 ? ssubaddxne r2, r4, r7 +0+1f0 <[^>]*> e1831f92 ? strex r1, r2, \[r3\] +0+1f4 <[^>]*> 11831f92 ? strexne r1, r2, \[r3\] +0+1f8 <[^>]*> e6bf2075 ? sxth r2,r5 +0+1fc <[^>]*> e6bf2475 ? sxth r2,r5, ROR #8 +0+200 <[^>]*> 16bf2075 ? sxthne r2,r5 +0+204 <[^>]*> 16bf2475 ? sxthne r2,r5, ROR #8 +0+208 <[^>]*> e68f2075 ? sxtb16 r2,r5 +0+20c <[^>]*> e68f2475 ? sxtb16 r2,r5, ROR #8 +0+210 <[^>]*> 168f2075 ? sxtb16ne r2,r5 +0+214 <[^>]*> 168f2475 ? sxtb16ne r2,r5, ROR #8 +0+218 <[^>]*> e6af2075 ? sxtb r2,r5 +0+21c <[^>]*> e6af2475 ? sxtb r2,r5, ROR #8 +0+220 <[^>]*> 16af2075 ? sxtbne r2,r5 +0+224 <[^>]*> 16af2475 ? sxtbne r2,r5, ROR #8 +0+228 <[^>]*> e6542f17 ? uadd16 r2, r4, r7 +0+22c <[^>]*> 16542f17 ? uadd16ne r2, r4, r7 +0+230 <[^>]*> e6f32075 ? uxtah r2, r3, r5 +0+234 <[^>]*> e6f32475 ? uxtah r2, r3, r5, ROR #8 +0+238 <[^>]*> 16f32075 ? uxtahne r2, r3, r5 +0+23c <[^>]*> 16f32475 ? uxtahne r2, r3, r5, ROR #8 +0+240 <[^>]*> e6542f97 ? uadd8 r2, r4, r7 +0+244 <[^>]*> 16542f97 ? uadd8ne r2, r4, r7 +0+248 <[^>]*> e6c32075 ? uxtab16 r2, r3, r5 +0+24c <[^>]*> e6c32475 ? uxtab16 r2, r3, r5, ROR #8 +0+250 <[^>]*> 16c32075 ? uxtab16ne r2, r3, r5 +0+254 <[^>]*> 16c32475 ? uxtab16ne r2, r3, r5, ROR #8 +0+258 <[^>]*> e6e32075 ? uxtab r2, r3, r5 +0+25c <[^>]*> e6e32475 ? uxtab r2, r3, r5, ROR #8 +0+260 <[^>]*> 16e32075 ? uxtabne r2, r3, r5 +0+264 <[^>]*> 16e32475 ? uxtabne r2, r3, r5, ROR #8 +0+268 <[^>]*> e6542f37 ? uaddsubx r2, r4, r7 +0+26c <[^>]*> 16542f37 ? uaddsubxne r2, r4, r7 +0+270 <[^>]*> e6742f17 ? uhadd16 r2, r4, r7 +0+274 <[^>]*> 16742f17 ? uhadd16ne r2, r4, r7 +0+278 <[^>]*> e6742f97 ? uhadd8 r2, r4, r7 +0+27c <[^>]*> 16742f97 ? uhadd8ne r2, r4, r7 +0+280 <[^>]*> e6742f37 ? uhaddsubx r2, r4, r7 +0+284 <[^>]*> 16742f37 ? uhaddsubxne r2, r4, r7 +0+288 <[^>]*> e6742f77 ? uhsub16 r2, r4, r7 +0+28c <[^>]*> 16742f77 ? uhsub16ne r2, r4, r7 +0+290 <[^>]*> e6742ff7 ? uhsub8 r2, r4, r7 +0+294 <[^>]*> 16742ff7 ? uhsub8ne r2, r4, r7 +0+298 <[^>]*> e6742f57 ? uhsubaddx r2, r4, r7 +0+29c <[^>]*> 16742f57 ? uhsubaddxne r2, r4, r7 +0+2a0 <[^>]*> e0421493 ? umaal r1, r2, r3, r4 +0+2a4 <[^>]*> d0421493 ? umaalle r1, r2, r3, r4 +0+2a8 <[^>]*> e6642f17 ? uqadd16 r2, r4, r7 +0+2ac <[^>]*> 16642f17 ? uqadd16ne r2, r4, r7 +0+2b0 <[^>]*> e6642f97 ? uqadd8 r2, r4, r7 +0+2b4 <[^>]*> 16642f97 ? uqadd8ne r2, r4, r7 +0+2b8 <[^>]*> e6642f37 ? uqaddsubx r2, r4, r7 +0+2bc <[^>]*> 16642f37 ? uqaddsubxne r2, r4, r7 +0+2c0 <[^>]*> e6642f77 ? uqsub16 r2, r4, r7 +0+2c4 <[^>]*> 16642f77 ? uqsub16ne r2, r4, r7 +0+2c8 <[^>]*> e6642ff7 ? uqsub8 r2, r4, r7 +0+2cc <[^>]*> 16642ff7 ? uqsub8ne r2, r4, r7 +0+2d0 <[^>]*> e6642f57 ? uqsubaddx r2, r4, r7 +0+2d4 <[^>]*> 16642f57 ? uqsubaddxne r2, r4, r7 +0+2d8 <[^>]*> e781f312 ? usad8 r1, r2, r3 +0+2dc <[^>]*> 1781f312 ? usad8ne r1, r2, r3 +0+2e0 <[^>]*> e7814312 ? usada8 r1, r2, r3, r4 +0+2e4 <[^>]*> 17814312 ? usada8ne r1, r2, r3, r4 +0+2e8 <[^>]*> e6ef1012 ? usat r1, #15, r2 +0+2ec <[^>]*> e6ef1252 ? usat r1, #15, r2, ASR #4 +0+2f0 <[^>]*> e6ef1212 ? usat r1, #15, r2, LSL #4 +0+2f4 <[^>]*> e6ef1f32 ? usat16 r1, #15, r2 +0+2f8 <[^>]*> d6ef1f32 ? usat16le r1, #15, r2 +0+2fc <[^>]*> d6ef1012 ? usatle r1, #15, r2 +0+300 <[^>]*> d6ef1252 ? usatle r1, #15, r2, ASR #4 +0+304 <[^>]*> d6ef1212 ? usatle r1, #15, r2, LSL #4 +0+308 <[^>]*> e6542f77 ? usub16 r2, r4, r7 +0+30c <[^>]*> 16542f77 ? usub16ne r2, r4, r7 +0+310 <[^>]*> e6542ff7 ? usub8 r2, r4, r7 +0+314 <[^>]*> 16542ff7 ? usub8ne r2, r4, r7 +0+318 <[^>]*> e6542f57 ? usubaddx r2, r4, r7 +0+31c <[^>]*> 16542f57 ? usubaddxne r2, r4, r7 +0+320 <[^>]*> e6ff2075 ? uxth r2,r5 +0+324 <[^>]*> e6ff2475 ? uxth r2,r5, ROR #8 +0+328 <[^>]*> 16ff2075 ? uxthne r2,r5 +0+32c <[^>]*> 16ff2475 ? uxthne r2,r5, ROR #8 +0+330 <[^>]*> e6cf2075 ? uxtb16 r2,r5 +0+334 <[^>]*> e6cf2475 ? uxtb16 r2,r5, ROR #8 +0+338 <[^>]*> 16cf2075 ? uxtb16ne r2,r5 +0+33c <[^>]*> 16cf2475 ? uxtb16ne r2,r5, ROR #8 +0+340 <[^>]*> e6ef2075 ? uxtb r2,r5 +0+344 <[^>]*> e6ef2475 ? uxtb r2,r5, ROR #8 +0+348 <[^>]*> 16ef2075 ? uxtbne r2,r5 +0+34c <[^>]*> 16ef2475 ? uxtbne r2,r5, ROR #8 diff --git a/gas/testsuite/gas/arm/archv6.s b/gas/testsuite/gas/arm/archv6.s new file mode 100644 index 000000000..50378b7c3 --- /dev/null +++ b/gas/testsuite/gas/arm/archv6.s @@ -0,0 +1,216 @@ +.text +.align 0 + +label: + cps #15 + cpsid if + cpsie if + ldrex r2, [r4] + ldrexne r4, [r8] + mcrr2 p0, 12, r7, r5, c3 + mrrc2 p0, 12, r7, r5, c3 + pkhbt r2, r5, r8 + pkhbt r2, r5, r8, LSL #3 + pkhbtal r2, r5, r8, LSL #3 + pkhbteq r2, r5, r8, LSL #3 + pkhtb r2, r5, r8 @ Equivalent to pkhbt r2, r8, r5. + pkhtb r2, r5, r8, ASR #3 + pkhtbal r2, r5, r8, ASR #3 + pkhtbeq r2, r5, r8, ASR #3 + qadd16 r2, r4, r7 + qadd16ne r2, r4, r7 + qadd8 r2, r4, r7 + qadd8ne r2, r4, r7 + qaddsubx r2, r4, r7 + qaddsubxne r2, r4, r7 + qsub16 r2, r4, r7 + qsub16ne r2, r4, r7 + qsub8 r2, r4, r7 + qsub8ne r2, r4, r7 + qsubaddx r2, r4, r7 + qsubaddx r2, r4, r7 + rev r2, r4 + rev16 r2, r4 + rev16ne r3, r5 + revne r3, r5 + revsh r2, r4 + revshne r3, r5 + rfeda r2 + rfedb r2! + rfeea r2 + rfeed r2! + rfefa r2! + rfefd r2 + rfeia r2 + rfeib r2! + sadd16 r2, r4, r7 + sadd16ne r2, r4, r7 + sxtah r2, r4, r5 + sxtah r2, r4, r5, ROR #8 + sxtahne r2, r4, r5 + sxtahne r2, r4, r5, ROR #8 + sadd8 r2, r4, r7 + sadd8ne r2, r4, r7 + sxtab16 r2, r4, r5 + sxtab16 r2, r4, r5, ROR #8 + sxtab16ne r2, r4, r5 + sxtab16ne r2, r4, r5, ROR #8 + sxtab r2, r4, r5 + sxtab r2, r4, r5, ROR #8 + sxtabne r2, r4, r5 + sxtabne r2, r4, r5, ROR #8 + saddsubx r2, r4, r7 + saddsubxne r2, r4, r7 + sel r1, r2, r3 + selne r1, r2, r3 + setend be + setend le + shadd16 r2, r4, r7 + shadd16ne r2, r4, r7 + shadd8 r2, r4, r7 + shadd8ne r2, r4, r7 + shaddsubx r2, r4, r7 + shaddsubxne r2, r4, r7 + shsub16 r2, r4, r7 + shsub16ne r2, r4, r7 + shsub8 r2, r4, r7 + shsub8ne r2, r4, r7 + shsubaddx r2, r4, r7 + shsubaddxne r2, r4, r7 + smlad r1,r2,r3,r4 + smladle r1,r2,r3,r4 + smladx r1,r2,r3,r4 + smladxle r1,r2,r3,r4 + smlald r1,r2,r3,r4 + smlaldle r1,r2,r3,r4 + smlaldx r1,r2,r3,r4 + smlaldxle r1,r2,r3,r4 + smlsd r1,r2,r3,r4 + smlsdle r1,r2,r3,r4 + smlsdx r1,r2,r3,r4 + smlsdxle r1,r2,r3,r4 + smlsld r1,r2,r3,r4 + smlsldle r1,r2,r3,r4 + smlsldx r1,r2,r3,r4 + smlsldxle r1,r2,r3,r4 + smmla r1,r2,r3,r4 + smmlale r1,r2,r3,r4 + smmlar r1,r2,r3,r4 + smmlarle r1,r2,r3,r4 + smmls r1,r2,r3,r4 + smmlsle r1,r2,r3,r4 + smmlsr r1,r2,r3,r4 + smmlsrle r1,r2,r3,r4 + smmul r1,r2,r3 + smmulle r1,r2,r3 + smmulr r1,r2,r3 + smmulrle r1,r2,r3 + smuad r1,r2,r3 + smuadle r1,r2,r3 + smuadx r1,r2,r3 + smuadxle r1,r2,r3 + smusd r1,r2,r3 + smusdle r1,r2,r3 + smusdx r1,r2,r3 + smusdxle r1,r2,r3 + srsia #16 + srsib #16! + ssat r1, #1, r2 + ssat r1, #1, r2, ASR #2 + ssat r1, #1, r2, LSL #2 + ssat16 r1, #1, r1 + ssat16le r1, #1, r1 + ssub16 r2, r4, r7 + ssub16ne r2, r4, r7 + ssub8 r2, r4, r7 + ssub8ne r2, r4, r7 + ssubaddx r2, r4, r7 + ssubaddxne r2, r4, r7 + strex r1, r2, [r3] + strexne r1, r2, [r3] + sxth r2, r5 + sxth r2, r5, ROR #8 + sxthne r2, r5 + sxthne r2, r5, ROR #8 + sxtb16 r2, r5 + sxtb16 r2, r5, ROR #8 + sxtb16ne r2, r5 + sxtb16ne r2, r5, ROR #8 + sxtb r2, r5 + sxtb r2, r5, ROR #8 + sxtbne r2, r5 + sxtbne r2, r5, ROR #8 + uadd16 r2, r4, r7 + uadd16ne r2, r4, r7 + uxtah r2, r3, r5 + uxtah r2, r3, r5, ROR #8 + uxtahne r2, r3, r5 + uxtahne r2, r3, r5, ROR #8 + uadd8 r2, r4, r7 + uadd8ne r2, r4, r7 + uxtab16 r2, r3, r5 + uxtab16 r2, r3, r5, ROR #8 + uxtab16ne r2, r3, r5 + uxtab16ne r2, r3, r5, ROR #8 + uxtab r2, r3, r5 + uxtab r2, r3, r5, ROR #8 + uxtabne r2, r3, r5 + uxtabne r2, r3, r5, ROR #8 + uaddsubx r2, r4, r7 + uaddsubxne r2, r4, r7 + uhadd16 r2, r4, r7 + uhadd16ne r2, r4, r7 + uhadd8 r2, r4, r7 + uhadd8ne r2, r4, r7 + uhaddsubx r2, r4, r7 + uhaddsubxne r2, r4, r7 + uhsub16 r2, r4, r7 + uhsub16ne r2, r4, r7 + uhsub8 r2, r4, r7 + uhsub8ne r2, r4, r7 + uhsubaddx r2, r4, r7 + uhsubaddxne r2, r4, r7 + umaal r1, r2, r3, r4 + umaalle r1, r2, r3, r4 + uqadd16 r2, r4, r7 + uqadd16ne r2, r4, r7 + uqadd8 r2, r4, r7 + uqadd8ne r2, r4, r7 + uqaddsubx r2, r4, r7 + uqaddsubxne r2, r4, r7 + uqsub16 r2, r4, r7 + uqsub16ne r2, r4, r7 + uqsub8 r2, r4, r7 + uqsub8ne r2, r4, r7 + uqsubaddx r2, r4, r7 + uqsubaddxne r2, r4, r7 + usad8 r1, r2, r3 + usad8ne r1, r2, r3 + usada8 r1, r2, r3, r4 + usada8ne r1, r2, r3, r4 + usat r1, #15, r2 + usat r1, #15, r2, ASR #4 + usat r1, #15, r2, LSL #4 + usat16 r1, #15, r2 + usat16le r1, #15, r2 + usatle r1, #15, r2 + usatle r1, #15, r2, ASR #4 + usatle r1, #15, r2, LSL #4 + usub16 r2, r4, r7 + usub16ne r2, r4, r7 + usub8 r2, r4, r7 + usub8ne r2, r4, r7 + usubaddx r2, r4, r7 + usubaddxne r2, r4, r7 + uxth r2, r5 + uxth r2, r5, ROR #8 + uxthne r2, r5 + uxthne r2, r5, ROR #8 + uxtb16 r2, r5 + uxtb16 r2, r5, ROR #8 + uxtb16ne r2, r5 + uxtb16ne r2, r5, ROR #8 + uxtb r2, r5 + uxtb r2, r5, ROR #8 + uxtbne r2, r5 + uxtbne r2, r5, ROR #8 diff --git a/gas/testsuite/gas/arm/arm.exp b/gas/testsuite/gas/arm/arm.exp index 3d9685db9..05c4f7027 100644 --- a/gas/testsuite/gas/arm/arm.exp +++ b/gas/testsuite/gas/arm/arm.exp @@ -66,6 +66,10 @@ if {[istarget *arm*-*-*] || [istarget "xscale-*-*"]} then { run_dump_test "maverick" + run_dump_test "archv6" + + run_dump_test "thumbv6" + if {[istarget *-*-elf*] || [istarget *-*-linux*]} then { run_dump_test "pic" diff --git a/gas/testsuite/gas/arm/thumbv6.d b/gas/testsuite/gas/arm/thumbv6.d new file mode 100644 index 000000000..e8f54f523 --- /dev/null +++ b/gas/testsuite/gas/arm/thumbv6.d @@ -0,0 +1,19 @@ +#name: THUMB V6 instructions +#as: -march=armv6 -mthumb +#objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*arm.* + +Disassembly of section .text: +0+000 <[^>]*> b666 * cpsie ai +0+002 <[^>]*> b675 * cpsid af +0+004 <[^>]*> 4623 * cpy r3, r4 +0+006 <[^>]*> ba3a * rev r2, r7 +0+008 <[^>]*> ba4d * rev16 r5, r1 +0+00a <[^>]*> baf3 * revsh r3, r6 +0+00c <[^>]*> b658 * setend be +0+00e <[^>]*> b650 * setend le +0+010 <[^>]*> b208 * sxth r0, r1 +0+012 <[^>]*> b251 * sxtb r1, r2 +0+014 <[^>]*> b2a3 * uxth r3, r4 +0+016 <[^>]*> b2f5 * uxtb r5, r6 diff --git a/gas/testsuite/gas/arm/thumbv6.s b/gas/testsuite/gas/arm/thumbv6.s new file mode 100644 index 000000000..b02d60c29 --- /dev/null +++ b/gas/testsuite/gas/arm/thumbv6.s @@ -0,0 +1,17 @@ +.text +.align 0 + +.thumb +label: + cpsie ia + cpsid af + cpy r3, r4 + rev r2, r7 + rev16 r5, r1 + revsh r3, r6 + setend be + setend le + sxth r0, r1 + sxtb r1, r2 + uxth r3, r4 + uxtb r5, r6 diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 389fb76ef..1d181fd0b 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,11 @@ +2003-12-05 Ricardo Anguiano + Mark Mitchell + Richard Earnshaw + + * arm-dis.c (print_arm_insn): Add 'W' macro. + * arm-opc.h (arm_opcodes): Add V6 instructions. + (thumb_opcodes): Likewise. + 2003-12-04 Alan Modra * openrisc-asm.c: Regenerate. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index d4ba196b8..e918dafa2 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -639,6 +639,16 @@ print_insn_arm (pc, info, given) func (stream, "%d", reg); } break; + case 'W': + { + long reg; + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + + func (stream, "%d", reg + 1); + } + break; case 'x': { long reg; diff --git a/opcodes/arm-opc.h b/opcodes/arm-opc.h index 22313cb1a..b59f2d30f 100644 --- a/opcodes/arm-opc.h +++ b/opcodes/arm-opc.h @@ -35,6 +35,7 @@ struct thumb_opcode %d print the bitfield in decimal %x print the bitfield in hex %X print the bitfield as 1 hex digit without leading "0x" + %w print the bitfield plus one in decimal %r print as an ARM register %f print a floating point constant if >7 else a floating point register @@ -161,6 +162,132 @@ static const struct arm_opcode arm_opcodes[] = {0x0e1000e0, 0x0f300ff0, "wunpckil%22-23w%c\t%12-15g, %16-19g, %0-3g"}, {0x0e100000, 0x0ff00ff0, "wxor%c\t%12-15g, %16-19g, %0-3g"}, + /* ARM V6 instructions. */ + {0xfc500000, 0xfff00000, "mrrc2\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, + {0xfc400000, 0xfff00000, "mcrr2\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, + {0xf1080000, 0xfffdfe3f, "cpsie\t%8'a%7'i%6'f"}, + {0xf1080000, 0xfffdfe20, "cpsie\t%8'a%7'i%6'f,#%0-4d"}, + {0xf10C0000, 0xfffdfe3f, "cpsid\t%8'a%7'i%6'f"}, + {0xf10C0000, 0xfffdfe20, "cpsid\t%8'a%7'i%6'f,#%0-4d"}, + {0xf1000000, 0xfff1fe20, "cps\t#%0-4d"}, + {0x06800010, 0x0ff00ff0, "pkhbt%c\t%12-15r, %16-19r, %0-3r"}, + {0x06800010, 0x0ff00070, "pkhbt%c\t%12-15r, %16-19r, %0-3r, LSL #%7-11d"}, + {0x06800050, 0x0ff00ff0, "pkhtb%c\t%12-15r, %16-19r, %0-3r, ASR #32"}, + {0x06800050, 0x0ff00070, "pkhtb%c\t%12-15r, %16-19r, %0-3r, ASR #%7-11d"}, + {0x01900f9f, 0x0ff00fff, "ldrex%c\tr%12-15d, [%16-19r]"}, + {0x06200f10, 0x0ff00ff0, "qadd16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06200f90, 0x0ff00ff0, "qadd8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06200f30, 0x0ff00ff0, "qaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06200f70, 0x0ff00ff0, "qsub16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06200ff0, 0x0ff00ff0, "qsub8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06200f50, 0x0ff00ff0, "qsubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06100f10, 0x0ff00ff0, "sadd16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06100f90, 0x0ff00ff0, "sadd8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06100f30, 0x0ff00ff0, "saddaddx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06300f10, 0x0ff00ff0, "shadd16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06300f90, 0x0ff00ff0, "shadd8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06300f30, 0x0ff00ff0, "shaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06300f70, 0x0ff00ff0, "shsub16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06300ff0, 0x0ff00ff0, "shsub8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06300f50, 0x0ff00ff0, "shsubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06100f70, 0x0ff00ff0, "ssub16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06100ff0, 0x0ff00ff0, "ssub8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06100f50, 0x0ff00ff0, "ssubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06500f10, 0x0ff00ff0, "uadd16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06500f90, 0x0ff00ff0, "uadd8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06500f30, 0x0ff00ff0, "uaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06700f10, 0x0ff00ff0, "uhadd16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06700f90, 0x0ff00ff0, "uhadd8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06700f30, 0x0ff00ff0, "uhaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06700f70, 0x0ff00ff0, "uhsub16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06700ff0, 0x0ff00ff0, "uhsub8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06700f50, 0x0ff00ff0, "uhsubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06600f10, 0x0ff00ff0, "uqadd16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06600f90, 0x0ff00ff0, "uqadd8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06600f30, 0x0ff00ff0, "uqaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06600f70, 0x0ff00ff0, "uqsub16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06600ff0, 0x0ff00ff0, "uqsub8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06600f50, 0x0ff00ff0, "uqsubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06500f70, 0x0ff00ff0, "usub16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06500ff0, 0x0ff00ff0, "usub8%c\t%12-15r, %16-19r, %0-3r"}, + {0x06500f50, 0x0ff00ff0, "usubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {0x06bf0f30, 0x0fff0ff0, "rev%c\t\%12-15r, %0-3r"}, + {0x06bf0fb0, 0x0fff0ff0, "rev16%c\t\%12-15r, %0-3r"}, + {0x06ff0fb0, 0x0fff0ff0, "revsh%c\t\%12-15r, %0-3r"}, + {0xf8100a00, 0xfe50ffff, "rfe%23?id%24?ba\t\%16-19r%21'!"}, + {0x06bf0070, 0x0fff0ff0, "sxth%c %12-15r,%0-3r"}, + {0x06bf0470, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #8"}, + {0x06bf0870, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #16"}, + {0x06bf0c70, 0x0fff0ff0, "sxth%c %12-15r,%0-3r, ROR #24"}, + {0x068f0070, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r"}, + {0x068f0470, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #8"}, + {0x068f0870, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #16"}, + {0x068f0c70, 0x0fff0ff0, "sxtb16%c %12-15r,%0-3r, ROR #24"}, + {0x06af0070, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r"}, + {0x06af0470, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #8"}, + {0x06af0870, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #16"}, + {0x06af0c70, 0x0fff0ff0, "sxtb%c %12-15r,%0-3r, ROR #24"}, + {0x06ff0070, 0x0fff0ff0, "uxth%c %12-15r,%0-3r"}, + {0x06ff0470, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #8"}, + {0x06ff0870, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #16"}, + {0x06ff0c70, 0x0fff0ff0, "uxth%c %12-15r,%0-3r, ROR #24"}, + {0x06cf0070, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r"}, + {0x06cf0470, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #8"}, + {0x06cf0870, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #16"}, + {0x06cf0c70, 0x0fff0ff0, "uxtb16%c %12-15r,%0-3r, ROR #24"}, + {0x06ef0070, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r"}, + {0x06ef0470, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #8"}, + {0x06ef0870, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #16"}, + {0x06ef0c70, 0x0fff0ff0, "uxtb%c %12-15r,%0-3r, ROR #24"}, + {0x06b00070, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r"}, + {0x06b00470, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #8"}, + {0x06b00870, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #16"}, + {0x06b00c70, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ROR #24"}, + {0x06800070, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06800470, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #8"}, + {0x06800870, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #16"}, + {0x06800c70, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"}, + {0x06a00070, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r"}, + {0x06a00470, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #8"}, + {0x06a00870, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #16"}, + {0x06a00c70, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ROR #24"}, + {0x06f00070, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r"}, + {0x06f00470, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #8"}, + {0x06f00870, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #16"}, + {0x06f00c70, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ROR #24"}, + {0x06c00070, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r"}, + {0x06c00470, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #8"}, + {0x06c00870, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #16"}, + {0x06c00c70, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"}, + {0x06e00070, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r"}, + {0x06e00470, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #8"}, + {0x06e00870, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #16"}, + {0x06e00c70, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ROR #24"}, + {0x068000b0, 0x0ff00ff0, "sel%c\t%12-15r, %16-19r, %0-3r"}, + {0xf1010000, 0xfffffc00, "setend\t%9?ble"}, + {0x0700f010, 0x0ff0f0d0, "smuad%5'x%c\t%16-19r, %0-3r, %8-11r"}, + {0x0700f050, 0x0ff0f0d0, "smusd%5'x%c\t%16-19r, %0-3r, %8-11r"}, + {0x07000010, 0x0ff000d0, "smlad%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {0x07400010, 0x0ff000d0, "smlald%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {0x07000050, 0x0ff000d0, "smlsd%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {0x07400050, 0x0ff000d0, "smlsld%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {0x0750f010, 0x0ff0f0d0, "smmul%5'r%c\t%16-19r, %0-3r, %8-11r"}, + {0x07500010, 0x0ff000d0, "smmla%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {0x075000d0, 0x0ff000d0, "smmls%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {0xf84d0500, 0xfe5fffe0, "srs%23?id%24?ba\t#%0-4d%21'!"}, + {0x06a00010, 0x0fe00ff0, "ssat%c\t%12-15r, #%16-20W, %0-3r"}, + {0x06a00010, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, LSL #%7-11d"}, + {0x06a00050, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, ASR #%7-11d"}, + {0x06a00f30, 0x0ff00ff0, "ssat16%c\t%12-15r, #%16-19W, %0-3r"}, + {0x01800f90, 0x0ff00ff0, "strex%c\t%12-15r, %0-3r, [%16-19r]"}, + {0x00400090, 0x0ff000f0, "umaal%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {0x0780f010, 0x0ff0f0f0, "usad8%c\t%16-19r, %0-3r, %8-11r"}, + {0x07800010, 0x0ff000f0, "usada8%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {0x06e00010, 0x0fe00ff0, "usat%c\t%12-15r, #%16-20d, %0-3r"}, + {0x06e00010, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, LSL #%7-11d"}, + {0x06e00050, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, ASR #%7-11d"}, + {0x06e00f30, 0x0ff00ff0, "usat16%c\t%12-15r, #%16-19d, %0-3r"}, + /* V5 Instructions. */ {0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"}, {0xfa000000, 0xfe000000, "blx\t%B"}, @@ -459,6 +586,19 @@ static const struct thumb_opcode thumb_opcodes[] = { /* Thumb instructions. */ + /* ARM V6. */ + {0xb660, 0xfff8, "cpsie\t%2'a%1'i%0'f"}, + {0xb670, 0xfff8, "cpsid\t%2'a%1'i%0'f"}, + {0x4600, 0xffc0, "cpy\t%0-2r, %3-5r"}, + {0xba00, 0xffc0, "rev\t%0-2r, %3-5r"}, + {0xba40, 0xffc0, "rev16\t%0-2r, %3-5r"}, + {0xbac0, 0xffc0, "revsh\t%0-2r, %3-5r"}, + {0xb650, 0xfff7, "setend\t%3?ble\t"}, + {0xb200, 0xffc0, "sxth\t%0-2r, %3-5r"}, + {0xb240, 0xffc0, "sxtb\t%0-2r, %3-5r"}, + {0xb280, 0xffc0, "uxth\t%0-2r, %3-5r"}, + {0xb2c0, 0xffc0, "uxtb\t%0-2r, %3-5r"}, + /* ARM V5 ISA extends Thumb. */ {0xbe00, 0xff00, "bkpt\t%0-7x"}, {0x4780, 0xff87, "blx\t%3-6r"}, /* note: 4 bit register number. */ -- 2.11.4.GIT