Remove semicolon from ARM comment chars list
[binutils-gdb.git] / gas / config / tc-arm.c
index 69d3d4f28f879c6a1c4759578b6d1e8e17609c5a..c6749958e4ee334871f5aec53b98e02fb87acbcf 100644 (file)
@@ -3,6 +3,7 @@
    Free Software Foundation, Inc.
    Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
        Modified by David Taylor (dtaylor@armltd.co.uk)
+       Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
 
    This file is part of GAS, the GNU Assembler.
 
    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    02111-1307, USA.  */
 
-#include <ctype.h>
 #include <string.h>
 #define  NO_RELOC 0
 #include "as.h"
+#include "safe-ctype.h"
 
 /* Need TARGET_CPU.  */
 #include "config.h"
@@ -56,6 +57,7 @@
 #define ARM_EXT_V5     0x00000080      /* Allow CLZ, etc.         */
 #define ARM_EXT_V5E    0x00000100      /* "El Segundo".           */
 #define ARM_EXT_XSCALE 0x00000200      /* Allow MIA etc.          */
+#define ARM_EXT_MAVERICK 0x00000400      /* Use Cirrus/DSP coprocessor.  */
 
 /* Architectures are the sum of the base and extensions.  */
 #define ARM_ARCH_V3M     ARM_EXT_LONGMUL
@@ -115,7 +117,7 @@ static boolean pic_code          = false;
 
 /* This array holds the chars that always start a comment.  If the
    pre-processor is disabled, these aren't very useful.  */
-CONST char comment_chars[] = "@";
+const char comment_chars[] = "@";
 
 /* This array holds the chars that only start a comment at the beginning of
    a line.  If the line seems to have the form '# 123 filename'
@@ -124,19 +126,19 @@ CONST char comment_chars[] = "@";
    first line of the input file.  This is because the compiler outputs
    #NO_APP at the beginning of its output.  */
 /* Also note that comments like this one will always work.  */
-CONST char line_comment_chars[] = "#";
+const char line_comment_chars[] = "#";
 
-CONST char line_separator_chars[] = ";";
+const char line_separator_chars[] = "|";
 
 /* Chars that can be used to separate mant
    from exp in floating point numbers.  */
-CONST char EXP_CHARS[] = "eE";
+const char EXP_CHARS[] = "eE";
 
 /* Chars that mean this number is a floating point constant.  */
 /* As in 0f12.456  */
 /* or    0d1.2345e12  */
 
-CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
+const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
 
 /* Prefix characters that indicate the start of an immediate
    value.  */
@@ -148,7 +150,7 @@ symbolS * GOT_symbol;
 #endif
 
 /* Size of relocation record.  */
-CONST int md_reloc_size = 8;
+const int md_reloc_size = 8;
 
 /* 0: assemble for ARM,
    1: assemble for Thumb,
@@ -163,7 +165,7 @@ typedef struct arm_fix
 
 struct arm_it
 {
-  CONST char *  error;
+  const char *  error;
   unsigned long instruction;
   int           suffix;
   int           size;
@@ -230,7 +232,7 @@ static const struct asm_shift_name shift_names [] =
 
 #define NUM_FLOAT_VALS 8
 
-CONST char * fp_const[] =
+const char * fp_const[] =
 {
   "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
 };
@@ -262,14 +264,14 @@ LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
 
 struct asm_cond
 {
-  CONST char *  template;
+  const char *  template;
   unsigned long value;
 };
 
 /* This is to save a hash look-up in the common case.  */
 #define COND_ALWAYS 0xe0000000
 
-static CONST struct asm_cond conds[] =
+static const struct asm_cond conds[] =
 {
   {"eq", 0x00000000},
   {"ne", 0x10000000},
@@ -294,17 +296,17 @@ static CONST struct asm_cond conds[] =
    the set_bits:  */
 struct asm_flg
 {
-  CONST char *  template;      /* Basic flag string.  */
+  const char *  template;      /* Basic flag string.  */
   unsigned long set_bits;      /* Bits to set.  */
 };
 
-static CONST struct asm_flg s_flag[] =
+static const struct asm_flg s_flag[] =
 {
   {"s", CONDS_BIT},
   {NULL, 0}
 };
 
-static CONST struct asm_flg ldr_flags[] =
+static const struct asm_flg ldr_flags[] =
 {
   {"d",  DOUBLE_LOAD_FLAG},
   {"b",  0x00400000},
@@ -316,7 +318,7 @@ static CONST struct asm_flg ldr_flags[] =
   {NULL, 0}
 };
 
-static CONST struct asm_flg str_flags[] =
+static const struct asm_flg str_flags[] =
 {
   {"d",  DOUBLE_LOAD_FLAG},
   {"b",  0x00400000},
@@ -326,20 +328,20 @@ static CONST struct asm_flg str_flags[] =
   {NULL, 0}
 };
 
-static CONST struct asm_flg byte_flag[] =
+static const struct asm_flg byte_flag[] =
 {
   {"b", 0x00400000},
   {NULL, 0}
 };
 
-static CONST struct asm_flg cmp_flags[] =
+static const struct asm_flg cmp_flags[] =
 {
   {"s", CONDS_BIT},
   {"p", 0x0010f000},
   {NULL, 0}
 };
 
-static CONST struct asm_flg ldm_flags[] =
+static const struct asm_flg ldm_flags[] =
 {
   {"ed", 0x01800000},
   {"fd", 0x00800000},
@@ -352,7 +354,7 @@ static CONST struct asm_flg ldm_flags[] =
   {NULL, 0}
 };
 
-static CONST struct asm_flg stm_flags[] =
+static const struct asm_flg stm_flags[] =
 {
   {"ed", 0x00000000},
   {"fd", 0x01000000},
@@ -365,21 +367,21 @@ static CONST struct asm_flg stm_flags[] =
   {NULL, 0}
 };
 
-static CONST struct asm_flg lfm_flags[] =
+static const struct asm_flg lfm_flags[] =
 {
   {"fd", 0x00800000},
   {"ea", 0x01000000},
   {NULL, 0}
 };
 
-static CONST struct asm_flg sfm_flags[] =
+static const struct asm_flg sfm_flags[] =
 {
   {"fd", 0x01000000},
   {"ea", 0x00800000},
   {NULL, 0}
 };
 
-static CONST struct asm_flg round_flags[] =
+static const struct asm_flg round_flags[] =
 {
   {"p", 0x00000020},
   {"m", 0x00000040},
@@ -391,7 +393,7 @@ static CONST struct asm_flg round_flags[] =
    in that it accepts a precision specifier as well as a rounding specifier,
    despite the fact that this is meaningless.  To be more compatible, we
    accept it as well, though of course it does not set any bits.  */
-static CONST struct asm_flg fix_flags[] =
+static const struct asm_flg fix_flags[] =
 {
   {"p", 0x00000020},
   {"m", 0x00000040},
@@ -408,13 +410,13 @@ static CONST struct asm_flg fix_flags[] =
   {NULL, 0}
 };
 
-static CONST struct asm_flg except_flag[] =
+static const struct asm_flg except_flag[] =
 {
   {"e", 0x00400000},
   {NULL, 0}
 };
 
-static CONST struct asm_flg cplong_flag[] =
+static const struct asm_flg long_flag[] =
 {
   {"l", 0x00400000},
   {NULL, 0}
@@ -422,7 +424,7 @@ static CONST struct asm_flg cplong_flag[] =
 
 struct asm_psr
 {
-  CONST char *  template;
+  const char *  template;
   boolean       cpsr;
   unsigned long field;
 };
@@ -438,7 +440,7 @@ struct asm_psr
 #define PSR_s   (1 << 2)
 #define PSR_f   (1 << 3)
 
-static CONST struct asm_psr psrs[] =
+static const struct asm_psr psrs[] =
 {
   {"CPSR",     true,  PSR_c | PSR_f},
   {"CPSR_all", true,  PSR_c | PSR_f},
@@ -579,6 +581,17 @@ static CONST struct asm_psr psrs[] =
   {"SPSR_cxsf",        false, PSR_c | PSR_x | PSR_s | PSR_f},
 };
 
+enum cirrus_regtype
+  {
+    CIRRUS_REGTYPE_MVF   = 1,
+    CIRRUS_REGTYPE_MVFX  = 2,
+    CIRRUS_REGTYPE_MVD   = 3,
+    CIRRUS_REGTYPE_MVDX  = 4,
+    CIRRUS_REGTYPE_MVAX  = 5,
+    CIRRUS_REGTYPE_DSPSC = 6,
+    CIRRUS_REGTYPE_ANY   = 7
+  };
+
 /* Functions called by parser.  */
 /* ARM instructions.  */
 static void do_arit            PARAMS ((char *, unsigned long));
@@ -590,7 +603,6 @@ static void do_branch               PARAMS ((char *, unsigned long));
 static void do_swi             PARAMS ((char *, unsigned long));
 /* Pseudo Op codes.  */
 static void do_adr             PARAMS ((char *, unsigned long));
-static void do_adrl            PARAMS ((char *, unsigned long));
 static void do_nop             PARAMS ((char *, unsigned long));
 /* ARM 2.  */
 static void do_mul             PARAMS ((char *, unsigned long));
@@ -643,10 +655,35 @@ static void do_fp_cmp             PARAMS ((char *, unsigned long));
 static void do_fp_from_reg     PARAMS ((char *, unsigned long));
 static void do_fp_to_reg       PARAMS ((char *, unsigned long));
 
+/* ARM_EXT_MAVERICK.  */
+static void do_c_binops                PARAMS ((char *, unsigned long, int));
+static void do_c_binops_1      PARAMS ((char *, unsigned long));
+static void do_c_binops_2      PARAMS ((char *, unsigned long));
+static void do_c_binops_3      PARAMS ((char *, unsigned long));
+static void do_c_triple                PARAMS ((char *, unsigned long, int));
+static void do_c_triple_4      PARAMS ((char *, unsigned long));
+static void do_c_triple_5      PARAMS ((char *, unsigned long));
+static void do_c_quad          PARAMS ((char *, unsigned long, int));
+static void do_c_quad_6                PARAMS ((char *, unsigned long));
+static void do_c_dspsc         PARAMS ((char *, unsigned long, int));
+static void do_c_dspsc_1       PARAMS ((char *, unsigned long));
+static void do_c_dspsc_2       PARAMS ((char *, unsigned long));
+static void do_c_shift         PARAMS ((char *, unsigned long, int));
+static void do_c_shift_1       PARAMS ((char *, unsigned long));
+static void do_c_shift_2       PARAMS ((char *, unsigned long));
+static void do_c_ldst          PARAMS ((char *, unsigned long, int));
+static void do_c_ldst_1                PARAMS ((char *, unsigned long));
+static void do_c_ldst_2                PARAMS ((char *, unsigned long));
+static void do_c_ldst_3                PARAMS ((char *, unsigned long));
+static void do_c_ldst_4                PARAMS ((char *, unsigned long));
+static int cirrus_reg_required_here    PARAMS ((char **, int, enum cirrus_regtype));
+static int cirrus_valid_reg    PARAMS ((int, enum cirrus_regtype));
+static int cirrus_parse_offset PARAMS ((char **, int *));
+
 static void fix_new_arm                PARAMS ((fragS *, int, short, expressionS *, int, int));
 static int arm_reg_parse       PARAMS ((char **));
-static CONST struct asm_psr * arm_psr_parse PARAMS ((char **));
-static void symbol_locate      PARAMS ((symbolS *, CONST char *, segT, valueT, fragS *));
+static const struct asm_psr * arm_psr_parse PARAMS ((char **));
+static void symbol_locate      PARAMS ((symbolS *, const char *, segT, valueT, fragS *));
 static int add_to_lit_pool     PARAMS ((void));
 static unsigned validate_immediate PARAMS ((unsigned));
 static unsigned validate_immediate_twopart PARAMS ((unsigned int, unsigned int *));
@@ -679,6 +716,10 @@ static void set_constant_flonums   PARAMS ((void));
 static valueT md_chars_to_number       PARAMS ((char *, int));
 static void insert_reg_alias   PARAMS ((char *, int));
 static void output_inst                PARAMS ((void));
+static int accum0_required_here PARAMS ((char **));
+static int ld_mode_required_here PARAMS ((char **));
+static void do_branch25         PARAMS ((char *, unsigned long));
+static symbolS * find_real_start PARAMS ((symbolS *));
 #ifdef OBJ_ELF
 static bfd_reloc_code_real_type        arm_parse_reloc PARAMS ((void));
 #endif
@@ -690,22 +731,40 @@ static bfd_reloc_code_real_type   arm_parse_reloc PARAMS ((void));
 /* LONGEST_INST is the longest basic instruction name without
    conditions or flags.  ARM7M has 4 of length 5.  El Segundo
    has one basic instruction name of length 7 (SMLALxy).  */
-#define LONGEST_INST 7
+#define LONGEST_INST 10
+
+/* "INSN<cond> X,Y" where X:bit12, Y:bit16.  */
+#define CIRRUS_MODE1   0x100c
+
+/* "INSN<cond> X,Y" where X:bit16, Y:bit12.  */
+#define CIRRUS_MODE2   0x0c10
+
+/* "INSN<cond> X,Y" where X:0, Y:bit16.  */
+#define CIRRUS_MODE3   0x1000
+
+/* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12.  */
+#define CIRRUS_MODE4   0x0c0010
+
+/* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0.  */
+#define CIRRUS_MODE5   0x00100c
+
+/* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0.  */
+#define CIRRUS_MODE6   0x00100c05
 
 struct asm_opcode
 {
   /* Basic string to match.  */
-  CONST char * template;
+  const char * template;
 
   /* Basic instruction code.  */
   unsigned long value;
 
   /* Compulsory suffix that must follow conds.  If "", then the
      instruction is not conditional and must have no suffix.  */
-  CONST char * comp_suffix;
+  const char * comp_suffix;
 
   /* Bits to toggle if flag 'n' set.  */
-  CONST struct asm_flg * flags;
+  const struct asm_flg * flags;
 
   /* Which CPU variants this exists for.  */
   unsigned long variants;
@@ -714,7 +773,7 @@ struct asm_opcode
   void (* parms) PARAMS ((char *, unsigned long));
 };
 
-static CONST struct asm_opcode insns[] =
+static const struct asm_opcode insns[] =
 {
 /* Intel XScale extensions to ARM V5 ISA.  */
   {"mia",   0x0e200010, NULL,   NULL,        ARM_EXT_XSCALE, do_mia},
@@ -760,8 +819,7 @@ static CONST struct asm_opcode insns[] =
 #endif
 
 /* Pseudo ops.  */
-  {"adr",   0x028f0000, NULL,   NULL,        ARM_ANY,      do_adr},
-  {"adrl",  0x028f0000, NULL,   NULL,        ARM_ANY,      do_adrl},
+  {"adr",   0x028f0000, NULL,   long_flag,   ARM_ANY,      do_adr},
   {"nop",   0x01a00000, NULL,   NULL,        ARM_ANY,      do_nop},
 
 /* ARM 2 multiplies.  */
@@ -837,8 +895,8 @@ static CONST struct asm_opcode insns[] =
 
 /* Generic copressor instructions.  */
   {"cdp",   0x0e000000, NULL,  NULL,         ARM_2UP,      do_cdp},
-  {"ldc",   0x0c100000, NULL,  cplong_flag,  ARM_2UP,      do_lstc},
-  {"stc",   0x0c000000, NULL,  cplong_flag,  ARM_2UP,      do_lstc},
+  {"ldc",   0x0c100000, NULL,  long_flag,    ARM_2UP,      do_lstc},
+  {"stc",   0x0c000000, NULL,  long_flag,    ARM_2UP,      do_lstc},
   {"mcr",   0x0e000010, NULL,  NULL,         ARM_2UP,      do_co_reg},
   {"mrc",   0x0e100010, NULL,  NULL,         ARM_2UP,      do_co_reg},
 
@@ -848,8 +906,8 @@ static CONST struct asm_opcode insns[] =
   {"blx",            0, NULL,   NULL,        ARM_EXT_V5, do_blx},
   {"clz",   0x016f0f10, NULL,   NULL,        ARM_EXT_V5, do_clz},
   {"bkpt",  0xe1200070, "",    NULL,        ARM_EXT_V5, do_bkpt},
-  {"ldc2",  0xfc100000, "",    cplong_flag, ARM_EXT_V5, do_lstc2},
-  {"stc2",  0xfc000000, "",    cplong_flag, ARM_EXT_V5, do_lstc2},
+  {"ldc2",  0xfc100000, "",    long_flag,   ARM_EXT_V5, do_lstc2},
+  {"stc2",  0xfc000000, "",    long_flag,   ARM_EXT_V5, do_lstc2},
   {"cdp2",  0xfe000000, "",    NULL,        ARM_EXT_V5, do_cdp2},
   {"mcr2",  0xfe000010, "",    NULL,        ARM_EXT_V5, do_co_reg2},
   {"mrc2",  0xfe100010, "",    NULL,        ARM_EXT_V5, do_co_reg2},
@@ -883,6 +941,84 @@ static CONST struct asm_opcode insns[] =
 
   {"mcrr",  0x0c400000, NULL,   NULL,         ARM_EXT_V5E, do_co_reg2c},
   {"mrrc",  0x0c500000, NULL,   NULL,         ARM_EXT_V5E, do_co_reg2c},
+
+  /* Cirrus DSP instructions.  */
+  {"cfldrs",   0x0c100400,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_ldst_1},
+  {"cfldrd",   0x0c500400,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_ldst_2},
+  {"cfldr32",  0x0c100500,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_ldst_3},
+  {"cfldr64",  0x0c500500,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_ldst_4},
+  {"cfstrs",   0x0c000400,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_ldst_1},
+  {"cfstrd",   0x0c400400,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_ldst_2},
+  {"cfstr32",  0x0c000500,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_ldst_3},
+  {"cfstr64",  0x0c400500,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_ldst_4},
+  {"cfmvsr",   0x0e000450,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_2},
+  {"cfmvrs",   0x0e100450,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfmvdlr",  0x0e000410,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_2},
+  {"cfmvrdl",  0x0e100410,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfmvdhr",  0x0e000430,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_2},
+  {"cfmvrdh",  0x0e100430,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfmv64lr", 0x0e000510,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_2},
+  {"cfmvr64l", 0x0e100510,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfmv64hr", 0x0e000530,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_2},
+  {"cfmvr64h", 0x0e100530,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfmval32", 0x0e100610,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmv32al", 0x0e000610,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmvam32", 0x0e100630,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmv32am", 0x0e000630,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmvah32", 0x0e100650,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmv32ah", 0x0e000650,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmv32a",  0x0e000670,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmva32",  0x0e100670,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmv64a",  0x0e000690,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmva64",  0x0e100690,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_3},
+  {"cfmvsc32", 0x0e1006b0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_dspsc_1},
+  {"cfmv32sc", 0x0e0006b0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_dspsc_2},
+  {"cfcpys",   0x0e000400,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfcpyd",   0x0e000420,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfcvtsd",  0x0e000460,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfcvtds",  0x0e000440,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfcvt32s", 0x0e000480,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfcvt32d", 0x0e0004a0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfcvt64s", 0x0e0004c0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfcvt64d", 0x0e0004e0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfcvts32", 0x0e100580,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfcvtd32", 0x0e1005a0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cftruncs32",0x0e1005c0,    NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cftruncd32",0x0e1005e0,    NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfrshl32", 0x0e000550,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_4},
+  {"cfrshl64", 0x0e000570,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_4},
+  {"cfsh32",   0x0e000500,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_shift_1},
+  {"cfsh64",   0x0e200500,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_shift_2},
+  {"cfcmps",   0x0e100490,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfcmpd",   0x0e1004b0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfcmp32",  0x0e100590,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfcmp64",  0x0e1005b0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfabss",   0x0e300400,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfabsd",   0x0e300420,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfnegs",   0x0e300440,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfnegd",   0x0e300460,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfadds",   0x0e300480,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfaddd",   0x0e3004a0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfsubs",   0x0e3004c0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfsubd",   0x0e3004e0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfmuls",   0x0e100400,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfmuld",   0x0e100420,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfabs32",  0x0e300500,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfabs64",  0x0e300520,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfneg32",  0x0e300540,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfneg64",  0x0e300560,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_binops_1},
+  {"cfadd32",  0x0e300580,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfadd64",  0x0e3005a0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfsub32",  0x0e3005c0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfsub64",  0x0e3005e0,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfmul32",  0x0e100500,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfmul64",  0x0e100520,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfmac32",  0x0e100540,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfmsc32",  0x0e100560,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_triple_5},
+  {"cfmadd32", 0x0e000600,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_quad_6},
+  {"cfmsub32", 0x0e100600,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_quad_6},
+  {"cfmadda32",        0x0e200600,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_quad_6},
+  {"cfmsuba32",        0x0e300600,     NULL,   NULL,   ARM_EXT_MAVERICK, do_c_quad_6},
 };
 
 /* Defines for various bits that we will want to toggle.  */
@@ -1025,7 +1161,7 @@ static int thumb_reg              PARAMS ((char ** str, int hi_lo));
 struct thumb_opcode
 {
   /* Basic string to match.  */
-  CONST char * template;
+  const char * template;
 
   /* Basic instruction code.  */
   unsigned long value;
@@ -1039,7 +1175,7 @@ struct thumb_opcode
   void (* parms) PARAMS ((char *));
 };
 
-static CONST struct thumb_opcode tinsns[] =
+static const struct thumb_opcode tinsns[] =
 {
   {"adc",      0x4140,         2,      ARM_EXT_THUMB, do_t_arit},
   {"add",      0x0000,         2,      ARM_EXT_THUMB, do_t_add},
@@ -1105,7 +1241,7 @@ static CONST struct thumb_opcode tinsns[] =
 
 struct reg_entry
 {
-  CONST char * name;
+  const char * name;
   int          number;
 };
 
@@ -1113,12 +1249,22 @@ struct reg_entry
 #define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
 #define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
 
+#define ARM_EXT_MAVERICKSC_REG 134
+
+#define cirrus_register(reg)           ((reg) >= 50 && (reg) <= 134)
+#define cirrus_mvf_register(reg)       ((reg) >= 50 && (reg) <= 65)
+#define cirrus_mvd_register(reg)       ((reg) >= 70 && (reg) <= 85)
+#define cirrus_mvfx_register(reg)      ((reg) >= 90 && (reg) <= 105)
+#define cirrus_mvdx_register(reg)      ((reg) >= 110 && (reg) <= 125)
+#define cirrus_mvax_register(reg)      ((reg) >= 130 && (reg) <= 133)
+#define ARM_EXT_MAVERICKsc_register(reg)       ((reg) == ARM_EXT_MAVERICKSC_REG)
+
 #define REG_PC 15
 #define REG_LR  14
 #define REG_SP  13
 
 /* These are the standard names.  Users can add aliases with .req.  */
-static CONST struct reg_entry reg_table[] =
+static const struct reg_entry reg_table[] =
 {
   /* Processor Register Numbers.  */
   {"r0", 0},    {"r1", 1},      {"r2", 2},      {"r3", 3},
@@ -1148,6 +1294,25 @@ static CONST struct reg_entry reg_table[] =
   {"s4",20},   {"s5",21},      {"s6",22},      {"s7",23},
   {"d0",16},   {"d1",17},      {"d2",18},      {"d3",19},
   {"d4",20},   {"d5",21},      {"d6",22},      {"d7",23},
+  /* Cirrus DSP coprocessor registers.  */
+  {"mvf0", 50},        {"mvf1", 51},   {"mvf2", 52},   {"mvf3", 53},
+  {"mvf4", 54},        {"mvf5", 55},   {"mvf6", 56},   {"mvf7", 57},
+  {"mvf8", 58},        {"mvf9", 59},   {"mvf10", 60},  {"mvf11", 61},
+  {"mvf12", 62},{"mvf13", 63}, {"mvf14", 64},  {"mvf15", 65},
+  {"mvd0", 70},        {"mvd1", 71},   {"mvd2", 72},   {"mvd3", 73},
+  {"mvd4", 74},        {"mvd5", 75},   {"mvd6", 76},   {"mvd7", 77},
+  {"mvd8", 78},        {"mvd9", 79},   {"mvd10", 80},  {"mvd11", 81},
+  {"mvd12", 82},{"mvd13", 83}, {"mvd14", 84},  {"mvd15", 85},
+  {"mvfx0", 90},{"mvfx1", 91}, {"mvfx2", 92},  {"mvfx3", 93},
+  {"mvfx4", 94},{"mvfx5", 95}, {"mvfx6", 96},  {"mvfx7", 97},
+  {"mvfx8", 98},{"mvfx9", 99}, {"mvfx10", 100},{"mvfx11", 101},
+  {"mvfx12", 102},{"mvfx13", 103},{"mvfx14", 104},{"mvfx15", 105},
+  {"mvdx0", 110}, {"mvdx1", 111}, {"mvdx2", 112}, {"mvdx3", 113},
+  {"mvdx4", 114}, {"mvdx5", 115}, {"mvdx6", 116}, {"mvdx7", 117},
+  {"mvdx8", 118}, {"mvdx9", 119}, {"mvdx10", 120},{"mvdx11", 121},
+  {"mvdx12", 122},{"mvdx13", 123},{"mvdx14", 124},{"mvdx15", 125},
+  {"mvax0", 130}, {"mvax1", 131}, {"mvax2", 132}, {"mvax3", 133},
+  {"dspsc", ARM_EXT_MAVERICKSC_REG},
   /* FIXME: At some point we need to add VFP register names.  */
   /* Array terminator.  */
   {NULL, 0}
@@ -1192,7 +1357,7 @@ static void s_arm_elf_cons PARAMS ((int));
 
 static int my_get_expression PARAMS ((expressionS *, char **));
 
-CONST pseudo_typeS md_pseudo_table[] =
+const pseudo_typeS md_pseudo_table[] =
 {
   /* Never called becasue '.req' does not start line.  */
   { "req",         s_req,         0 },
@@ -1279,12 +1444,23 @@ add_to_lit_pool ()
              == inst.reloc.exp.X_add_number)
          && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
        break;
+
+      if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
+          && inst.reloc.exp.X_op == O_symbol
+          && (literals[lit_count].exp.X_add_number
+             == inst.reloc.exp.X_add_number)
+          && (literals[lit_count].exp.X_add_symbol
+             == inst.reloc.exp.X_add_symbol)
+          && (literals[lit_count].exp.X_op_symbol
+             == inst.reloc.exp.X_op_symbol))
+        break;
+
       lit_count++;
     }
 
   if (lit_count == next_literal_pool_place) /* New entry.  */
     {
-      if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
+      if (next_literal_pool_place >= MAX_LITERAL_POOL_SIZE)
        {
          inst.error = _("Literal Pool Overflow");
          return FAIL;
@@ -1307,7 +1483,7 @@ add_to_lit_pool ()
 static void
 symbol_locate (symbolP, name, segment, valu, frag)
      symbolS *    symbolP;
-     CONST char * name;                /* It is copied, the caller can modify.  */
+     const char * name;                /* It is copied, the caller can modify.  */
      segT         segment;     /* Segment identifier (SEG_<something>).  */
      valueT       valu;                /* Symbol value.  */
      fragS *      frag;                /* Associated fragment.  */
@@ -1838,14 +2014,14 @@ reg_required_here (str, shift)
   return FAIL;
 }
 
-static CONST struct asm_psr *
+static const struct asm_psr *
 arm_psr_parse (ccp)
      register char ** ccp;
 {
   char * start = * ccp;
   char   c;
   char * p;
-  CONST struct asm_psr * psr;
+  const struct asm_psr * psr;
 
   p = start;
 
@@ -1854,7 +2030,7 @@ arm_psr_parse (ccp)
     {
       c = *p++;
     }
-  while (isalpha (c) || c == '_');
+  while (ISALPHA (c) || c == '_');
 
   /* Terminate the word.  */
   *--p = 0;
@@ -1867,7 +2043,7 @@ arm_psr_parse (ccp)
     strncpy (start, "SPSR", 4);
 
   /* Now locate the word in the psr hash table.  */
-  psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
+  psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
 
   /* Restore the input stream.  */
   *p = c;
@@ -1886,7 +2062,7 @@ psr_required_here (str)
      char ** str;
 {
   char * start = * str;
-  CONST struct asm_psr * psr;
+  const struct asm_psr * psr;
 
   psr = arm_psr_parse (str);
 
@@ -2278,12 +2454,17 @@ do_msr (str, flags)
       return;
     }
 
+#if 0  /* The first edition of the ARM architecture manual stated that
+         writing anything other than the flags with an immediate operation
+         had UNPREDICTABLE effects.  This constraint was removed in the
+         second edition of the specification.  */
   if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
       && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
     {
       inst.error = _("immediate value cannot be used to set this field");
       return;
     }
+#endif
 
   flags |= INST_IMMEDIATE;
 
@@ -2502,7 +2683,7 @@ accum0_required_here (str)
 
   *str = p;                    /* Advance caller's string pointer too.  */
   c = *p++;
-  while (isalnum (c))
+  while (ISALNUM (c))
     c = *p++;
 
   *--p = 0;                    /* Aap nul into input buffer at non-alnum.  */
@@ -3498,7 +3679,7 @@ do_ldrd (str, flags)
       static char buff[128];
 
       --str;
-      while (isspace (*str))
+      while (ISSPACE (*str))
        --str;
       str -= 4;
 
@@ -3695,7 +3876,7 @@ decode_shift (str, unrestrict)
 
   skip_whitespace (* str);
 
-  for (p = * str; isalpha (* p); p ++)
+  for (p = * str; ISALPHA (* p); p ++)
     ;
 
   if (p == * str)
@@ -4059,8 +4240,6 @@ do_adr (str, flags)
      char * str;
      unsigned long flags;
 {
-  /* This is a pseudo-op of the form "adr rd, label" to be converted
-     into a relative address of the form "add rd, pc, #label-.-8".  */
   skip_whitespace (str);
 
   if (reg_required_here (&str, 12) == FAIL
@@ -4072,48 +4251,33 @@ do_adr (str, flags)
       return;
     }
 
-  /* Frag hacking will turn this into a sub instruction if the offset turns
-     out to be negative.  */
-  inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
-  inst.reloc.exp.X_add_number -= 8; /* PC relative adjust.  */
-  inst.reloc.pc_rel = 1;
-  inst.instruction |= flags;
-
-  end_of_line (str);
-}
-
-static void
-do_adrl (str, flags)
-     char * str;
-     unsigned long flags;
-{
-  /* This is a pseudo-op of the form "adrl rd, label" to be converted
-     into a relative address of the form:
-       add rd, pc, #low(label-.-8)"
-       add rd, rd, #high(label-.-8)"  */
-
-  skip_whitespace (str);
-
-  if (reg_required_here (& str, 12) == FAIL
-      || skip_past_comma (& str) == FAIL
-      || my_get_expression (& inst.reloc.exp, & str))
+  if (flags & 0x00400000)
     {
-      if (!inst.error)
-       inst.error = BAD_ARGS;
-      return;
+      /* This is a pseudo-op of the form "adrl rd, label" to be converted
+        into a relative address of the form:
+        add rd, pc, #low(label-.-8)"
+        add rd, rd, #high(label-.-8)"  */
+      /* Frag hacking will turn this into a sub instruction if the offset turns
+        out to be negative.  */
+      inst.reloc.type              = BFD_RELOC_ARM_ADRL_IMMEDIATE;
+      inst.reloc.exp.X_add_number -= 8; /* PC relative adjust  */
+      inst.reloc.pc_rel            = 1;
+      inst.instruction            |= flags & ~0x00400000;
+      inst.size                    = INSN_SIZE * 2;
+    }
+  else
+    {
+      /* This is a pseudo-op of the form "adr rd, label" to be converted
+        into a relative address of the form "add rd, pc, #label-.-8".  */
+      /* Frag hacking will turn this into a sub instruction if the offset turns
+        out to be negative.  */
+      inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
+      inst.reloc.exp.X_add_number -= 8; /* PC relative adjust.  */
+      inst.reloc.pc_rel = 1;
+      inst.instruction |= flags;
     }
 
   end_of_line (str);
-
-  /* Frag hacking will turn this into a sub instruction if the offset turns
-     out to be negative.  */
-  inst.reloc.type              = BFD_RELOC_ARM_ADRL_IMMEDIATE;
-  inst.reloc.exp.X_add_number -= 8; /* PC relative adjust  */
-  inst.reloc.pc_rel            = 1;
-  inst.instruction            |= flags;
-  inst.size                    = INSN_SIZE * 2;
-
-  return;
 }
 
 static void
@@ -4415,38 +4579,53 @@ do_ldst (str, flags)
          return;
        }
 
-      if (inst.reloc.exp.X_op == O_constant
-         && (value = validate_immediate (inst.reloc.exp.X_add_number)) != FAIL)
-       {
-         /* This can be done with a mov instruction.  */
-         inst.instruction &= LITERAL_MASK;
-         inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
-         inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
-         end_of_line (str);
-         return;
-       }
-      else
+      if (inst.reloc.exp.X_op == O_constant)
        {
-         /* Insert into literal pool.  */
-         if (add_to_lit_pool () == FAIL)
+         value = validate_immediate (inst.reloc.exp.X_add_number);
+
+         if (value != FAIL)
            {
-             if (!inst.error)
-               inst.error = _("literal pool insertion failed");
+             /* This can be done with a mov instruction.  */
+             inst.instruction &= LITERAL_MASK;
+             inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
+             inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
+             end_of_line (str);
              return;
            }
+         
+         value = validate_immediate (~ inst.reloc.exp.X_add_number);
 
-         /* Change the instruction exp to point to the pool.  */
-         if (halfword)
+         if (value != FAIL)
            {
-             inst.instruction |= HWOFFSET_IMM;
-             inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
+             /* This can be done with a mvn instruction.  */
+             inst.instruction &= LITERAL_MASK;
+             inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
+             inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
+             end_of_line (str);
+             return;
            }
-         else
-           inst.reloc.type = BFD_RELOC_ARM_LITERAL;
-         inst.reloc.pc_rel = 1;
-         inst.instruction |= (REG_PC << 16);
-         pre_inc = 1;
        }
+
+      /* Insert into literal pool.  */
+      if (add_to_lit_pool () == FAIL)
+       {
+         if (!inst.error)
+           inst.error = _("literal pool insertion failed");
+         return;
+       }
+
+      /* Change the instruction exp to point to the pool.  */
+      if (halfword)
+       {
+         inst.instruction |= HWOFFSET_IMM;
+         inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
+       }
+      else
+       inst.reloc.type = BFD_RELOC_ARM_LITERAL;
+
+      inst.reloc.pc_rel = 1;
+      inst.instruction |= (REG_PC << 16);
+      pre_inc = 1;
     }
   else
     {
@@ -5966,6 +6145,581 @@ thumb_load_store (str, load_store, size)
   end_of_line (str);
 }
 
+/* Given a register and a register type, return 1 if
+   the register is of the given type, else return 0.  */
+
+static int
+cirrus_valid_reg (reg, regtype)
+     int reg;
+     enum cirrus_regtype regtype;
+{
+  switch (regtype)
+    {
+    case CIRRUS_REGTYPE_ANY:
+      return 1;
+
+    case CIRRUS_REGTYPE_MVF:
+      return cirrus_mvf_register (reg);
+
+    case CIRRUS_REGTYPE_MVFX:
+      return cirrus_mvfx_register (reg);
+
+    case CIRRUS_REGTYPE_MVD:
+      return cirrus_mvd_register (reg);
+
+    case CIRRUS_REGTYPE_MVDX:
+      return cirrus_mvdx_register (reg);
+
+    case CIRRUS_REGTYPE_MVAX:
+      return cirrus_mvax_register (reg);
+
+    case CIRRUS_REGTYPE_DSPSC:
+      return ARM_EXT_MAVERICKsc_register (reg);
+    }
+
+  return 0;
+}
+
+/* A register must be given at this point.
+
+   If the register is a Cirrus register, convert it's reg# appropriately.
+
+   Shift is the place to put it in inst.instruction.
+
+   regtype is type register type expected, and is:
+       CIRRUS_REGTYPE_MVF
+       CIRRUS_REGTYPE_MVFX
+       CIRRUS_REGTYPE_MVD
+       CIRRUS_REGTYPE_MVDX
+       CIRRUS_REGTYPE_MVAX
+       CIRRUS_REGTYPE_DSPSC
+
+   Restores input start point on err.
+   Returns the reg#, or FAIL.  */
+
+static int
+cirrus_reg_required_here (str, shift, regtype)
+     char ** str;
+     int shift;
+     enum cirrus_regtype regtype;
+{
+  static char buff [135]; /* XXX */
+  int         reg;
+  char *      start = * str;
+
+  if ((reg = arm_reg_parse (str)) != FAIL
+      && (int_register (reg)
+         || cirrus_register (reg)))
+    {
+      int orig_reg = reg;
+
+      /* Calculate actual register # for opcode.  */
+      if (cirrus_register (reg)
+         && !ARM_EXT_MAVERICKsc_register (reg)) /* Leave this one as is.  */
+       {
+         if (reg >= 130)
+           reg -= 130;
+         else if (reg >= 110)
+           reg -= 110;
+         else if (reg >= 90)
+           reg -= 90;
+         else if (reg >= 70)
+           reg -= 70;
+         else if (reg >= 50)
+           reg -= 50;
+       }
+
+      if (!cirrus_valid_reg (orig_reg, regtype))
+       {
+         sprintf (buff, _("invalid register type at '%.100s'"), start);
+         inst.error = buff;
+         return FAIL;
+       }
+
+      if (shift >= 0)
+       inst.instruction |= reg << shift;
+
+      return orig_reg;
+    }
+
+  /* Restore the start point, we may have got a reg of the wrong class.  */
+  *str = start;
+  
+  /* In the few cases where we might be able to accept something else
+     this error can be overridden.  */
+  sprintf (buff, _("Cirrus register expected, not '%.100s'"), start);
+  inst.error = buff;
+  
+  return FAIL;
+}
+
+/* Cirrus Instructions.  */
+
+/* Wrapper functions.  */
+
+static void
+do_c_binops_1 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_binops (str, flags, CIRRUS_MODE1);
+}
+
+static void
+do_c_binops_2 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_binops (str, flags, CIRRUS_MODE2);
+}
+
+static void
+do_c_binops_3 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_binops (str, flags, CIRRUS_MODE3);
+}
+
+static void
+do_c_triple_4 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_triple (str, flags, CIRRUS_MODE4);
+}
+
+static void
+do_c_triple_5 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_triple (str, flags, CIRRUS_MODE5);
+}
+
+static void
+do_c_quad_6 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_quad (str, flags, CIRRUS_MODE6);
+}
+
+static void
+do_c_dspsc_1 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_dspsc (str, flags, CIRRUS_MODE1);
+}
+
+static void
+do_c_dspsc_2 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_dspsc (str, flags, CIRRUS_MODE2);
+}
+
+static void
+do_c_shift_1 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_shift (str, flags, CIRRUS_MODE1);
+}
+
+static void
+do_c_shift_2 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_shift (str, flags, CIRRUS_MODE2);
+}
+
+static void
+do_c_ldst_1 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_ldst (str, flags, CIRRUS_MODE1);
+}
+
+static void
+do_c_ldst_2 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_ldst (str, flags, CIRRUS_MODE2);
+}
+
+static void
+do_c_ldst_3 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_ldst (str, flags, CIRRUS_MODE3);
+}
+
+static void
+do_c_ldst_4 (str, flags)
+     char * str;
+     unsigned long flags;
+{
+  do_c_ldst (str, flags, CIRRUS_MODE4);
+}
+
+/* Isnsn like "foo X,Y".  */
+
+static void
+do_c_binops (str, flags, mode)
+     char * str;
+     unsigned long flags;
+     int mode;
+{
+  int shift1, shift2;
+
+  shift1 = mode & 0xff;
+  shift2 = (mode >> 8) & 0xff;
+
+  skip_whitespace (str);
+
+  if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_ANY) == FAIL
+      || skip_past_comma (&str) == FAIL
+      || cirrus_reg_required_here (&str, shift2, CIRRUS_REGTYPE_ANY) == FAIL)
+    {
+      if (!inst.error)
+       inst.error = BAD_ARGS;
+    }
+  else
+    end_of_line (str);
+  
+  inst.instruction |= flags;
+  return;
+}
+
+/* Isnsn like "foo X,Y,Z".  */
+
+static void
+do_c_triple (str, flags, mode)
+     char * str;
+     unsigned long flags;
+     int mode;
+{
+  int shift1, shift2, shift3;
+
+  shift1 = mode & 0xff;
+  shift2 = (mode >> 8) & 0xff;
+  shift3 = (mode >> 16) & 0xff;
+
+  skip_whitespace (str);
+
+  if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_ANY) == FAIL
+      || skip_past_comma (&str) == FAIL
+      || cirrus_reg_required_here (&str, shift2, CIRRUS_REGTYPE_ANY) == FAIL
+      || skip_past_comma (&str) == FAIL
+      || cirrus_reg_required_here (&str, shift3, CIRRUS_REGTYPE_ANY) == FAIL)
+    {
+      if (!inst.error)
+       inst.error = BAD_ARGS;
+    }
+  else
+    end_of_line (str);
+  
+  inst.instruction |= flags;
+  return;
+}
+
+/* Isnsn like "foo W,X,Y,Z".
+    where W=MVAX[0:3] and X,Y,Z=MVFX[0:15].  */
+
+static void
+do_c_quad (str, flags, mode)
+     char * str;
+     unsigned long flags;
+     int mode;
+{
+  int shift1, shift2, shift3, shift4;
+  enum cirrus_regtype rt;
+
+  rt = (inst.instruction << 4 == 0xe2006000
+       || inst.instruction << 4 == 0xe3006000) ? CIRRUS_REGTYPE_MVAX
+    : CIRRUS_REGTYPE_MVFX;
+
+  shift1 = mode & 0xff;
+  shift2 = (mode >> 8) & 0xff;
+  shift3 = (mode >> 16) & 0xff;
+  shift4 = (mode >> 24) & 0xff;
+
+  skip_whitespace (str);
+
+  if (cirrus_reg_required_here (&str, shift1, CIRRUS_REGTYPE_MVAX) == FAIL
+      || skip_past_comma (&str) == FAIL
+      || cirrus_reg_required_here (&str, shift2, rt) == FAIL
+      || skip_past_comma (&str) == FAIL
+      || cirrus_reg_required_here (&str, shift3, CIRRUS_REGTYPE_MVFX) == FAIL
+      || skip_past_comma (&str) == FAIL
+      || cirrus_reg_required_here (&str, shift4, CIRRUS_REGTYPE_MVFX) == FAIL)
+    {
+      if (!inst.error)
+       inst.error = BAD_ARGS;
+    }
+  else
+    end_of_line (str);
+  
+  inst.instruction |= flags;
+  return;
+}
+
+/* cfmvsc32<cond> DSPSC,MVFX[15:0].
+   cfmv32sc<cond> MVFX[15:0],DSPSC.  */
+
+static void
+do_c_dspsc (str, flags, mode)
+     char * str;
+     unsigned long flags;
+     int mode;
+{
+  int error;
+
+  skip_whitespace (str);
+
+  error = 0;
+
+  if (mode == CIRRUS_MODE1)
+    {
+      /* cfmvsc32.  */
+      if (cirrus_reg_required_here (&str, -1, CIRRUS_REGTYPE_DSPSC) == FAIL
+         || skip_past_comma (&str) == FAIL
+         || cirrus_reg_required_here (&str, 16, CIRRUS_REGTYPE_MVFX) == FAIL)
+       error = 1;
+    }
+  else
+    {
+      /* cfmv32sc.  */
+      if (cirrus_reg_required_here (&str, 0, CIRRUS_REGTYPE_MVFX) == FAIL
+         || skip_past_comma (&str) == FAIL
+         || cirrus_reg_required_here (&str, -1, CIRRUS_REGTYPE_DSPSC) == FAIL)
+       error = 1;
+    }
+
+  if (error)
+    {
+      if (!inst.error)
+       inst.error = BAD_ARGS;
+    }
+  else
+    {
+      inst.instruction |= flags;
+      end_of_line (str);
+    }
+
+  return;
+}
+
+/* Cirrus shift immediate instructions.
+   cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
+   cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0].  */
+
+static void
+do_c_shift (str, flags, mode)
+     char * str;
+     unsigned long flags;
+     int mode;
+{
+  int error;
+  int imm, neg = 0;
+
+  skip_whitespace (str);
+
+  error = 0;
+
+  if (cirrus_reg_required_here (&str, 12,
+                               (mode == CIRRUS_MODE1)
+                               ? CIRRUS_REGTYPE_MVFX
+                               : CIRRUS_REGTYPE_MVDX) == FAIL
+      || skip_past_comma (&str) == FAIL
+      || cirrus_reg_required_here (&str, 16,
+                                  (mode == CIRRUS_MODE1)
+                                  ? CIRRUS_REGTYPE_MVFX
+                                  : CIRRUS_REGTYPE_MVDX) == FAIL
+      || skip_past_comma  (&str) == FAIL)
+    {
+      if (!inst.error)
+       inst.error = BAD_ARGS;
+      return;
+    }
+
+  /* Calculate the immediate operand.
+     The operand is a 7bit signed number.  */
+  skip_whitespace (str);
+
+  if (*str == '#')
+    ++str;
+
+  if (!isdigit (*str) && *str != '-')
+    {
+      inst.error = _("expecting immediate, 7bit operand");
+      return;
+    }
+
+  if (*str == '-')
+    {
+      neg = 1;
+      ++str;
+    }
+
+  for (imm = 0; *str && isdigit (*str); ++str)
+    imm = imm * 10 + *str - '0';
+
+  if (imm > 64)
+    {
+      inst.error = _("immediate out of range");
+      return;
+    }
+
+  /* Make negative imm's into 7bit signed numbers.  */
+  if (neg)
+    {
+      imm = -imm;
+      imm &= 0x0000007f;
+    }
+
+  /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
+     Bits 5-7 of the insn should have bits 4-6 of the immediate.
+     Bit 4 should be 0.  */
+  imm = (imm & 0xf) | ((imm & 0x70) << 1);
+
+  inst.instruction |= imm;
+  inst.instruction |= flags;
+
+  end_of_line (str);
+
+  return;
+}
+
+static int
+cirrus_parse_offset (str, negative)
+     char ** str;
+     int *negative;
+{
+  char * p = *str;
+  int offset;
+
+  *negative = 0;
+
+  skip_whitespace (p);
+
+  if (*p == '#')
+    ++p;
+
+  if (*p == '-')
+    {
+      *negative = 1;
+      ++p;
+    }
+
+  if (!isdigit (*p))
+    {
+      inst.error = _("offset expected");
+      return 0;
+    }
+
+  for (offset = 0; *p && isdigit (*p); ++p)
+    offset = offset * 10 + *p - '0';
+
+  if (offset > 0xff)
+    {
+      inst.error = _("offset out of range");
+      return 0;
+    }
+
+  *str = p;
+
+  return *negative ? -offset : offset;
+}
+
+/* Cirrus load/store instructions.
+  <insn><cond> CRd,[Rn,<offset>]{!}.
+  <insn><cond> CRd,[Rn],<offset>.  */
+
+static void
+do_c_ldst (str, flags, mode)
+     char * str;
+     unsigned long flags;
+     int mode;
+{
+  int offset, negative;
+  enum cirrus_regtype rt;
+
+  rt = mode == CIRRUS_MODE1 ? CIRRUS_REGTYPE_MVF
+    : mode == CIRRUS_MODE2 ? CIRRUS_REGTYPE_MVD
+    : mode == CIRRUS_MODE3 ? CIRRUS_REGTYPE_MVFX
+    : mode == CIRRUS_MODE4 ? CIRRUS_REGTYPE_MVDX : CIRRUS_REGTYPE_MVF;
+
+  skip_whitespace (str);
+
+  if (cirrus_reg_required_here (& str, 12, rt) == FAIL
+      || skip_past_comma (& str) == FAIL
+      || *str++ != '['
+      || reg_required_here (& str, 16) == FAIL)
+    goto fail_ldst;
+
+  if (skip_past_comma (& str) == SUCCESS)
+    {
+      /* You are here: "<offset>]{!}".  */
+      inst.instruction |= PRE_INDEX;
+
+      offset = cirrus_parse_offset (&str, &negative);
+
+      if (inst.error)
+       return;
+
+      if (*str++ != ']')
+       {
+         inst.error = _("missing ]");
+         return;
+       }
+
+      if (*str == '!')
+       {
+         inst.instruction |= WRITE_BACK;
+         ++str;
+       }
+    }
+  else
+    {
+      /* You are here: "], <offset>".  */
+      if (*str++ != ']')
+       {
+         inst.error = _("missing ]");
+         return;
+       }
+
+      if (skip_past_comma (&str) == FAIL
+         || (offset = cirrus_parse_offset (&str, &negative), inst.error))
+       goto fail_ldst;
+
+      inst.instruction |= CP_T_WB; /* Post indexed, set bit W.  */
+    }
+
+  if (negative)
+    offset = -offset;
+  else
+    inst.instruction |= CP_T_UD; /* Postive, so set bit U.  */
+
+  inst.instruction |= offset >> 2;
+  inst.instruction |= flags;
+
+  end_of_line (str);
+  return;
+
+fail_ldst:
+  if (!inst.error)
+     inst.error = BAD_ARGS;
+  return;
+}
+
 static void
 do_t_nop (str)
      char * str;
@@ -6014,7 +6768,7 @@ do_t_arit (str)
 
       if (Rs != Rd)
        {
-         inst.error = _("dest and source1 one must be the same register");
+         inst.error = _("dest and source1 must be the same register");
          return;
        }
       Rs = Rn;
@@ -6394,7 +7148,7 @@ insert_reg (entry)
   strcpy (buf + i, reg_table[entry].name);
 
   for (i = 0; buf[i]; i++)
-    buf2[i] = islower (buf[i]) ? toupper (buf[i]) : buf[i];
+    buf2[i] = TOUPPER (buf[i]);
 
   buf2[i] = '\0';
 
@@ -6762,11 +7516,11 @@ arm_reg_parse (ccp)
     p++, start++;
 #endif
 #endif
-  if (!isalpha (*p) || !is_name_beginner (*p))
+  if (!ISALPHA (*p) || !is_name_beginner (*p))
     return FAIL;
 
   c = *p++;
-  while (isalpha (c) || isdigit (c) || c == '_')
+  while (ISALPHA (c) || ISDIGIT (c) || c == '_')
     c = *p++;
 
   *--p = 0;
@@ -7634,11 +8388,11 @@ md_assemble (str)
 
   if (thumb_mode)
     {
-      CONST struct thumb_opcode * opcode;
+      const struct thumb_opcode * opcode;
 
       c = *p;
       *p = '\0';
-      opcode = (CONST struct thumb_opcode *) hash_find (arm_tops_hsh, str);
+      opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
       *p = c;
 
       if (opcode)
@@ -7659,7 +8413,7 @@ md_assemble (str)
     }
   else
     {
-      CONST struct asm_opcode * opcode;
+      const struct asm_opcode * opcode;
       unsigned long cond_code;
 
       inst.size = INSN_SIZE;
@@ -7674,7 +8428,7 @@ md_assemble (str)
          c = *q;
          *q = '\0';
 
-         opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
+         opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
          *q = c;
 
          if (opcode && opcode->template)
@@ -7713,11 +8467,11 @@ md_assemble (str)
              r = q;
              if (p - r >= 2)
                {
-                 CONST struct asm_cond *cond;
+                 const struct asm_cond *cond;
                  char d = *(r + 2);
 
                  *(r + 2) = '\0';
-                 cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r);
+                 cond = (const struct asm_cond *) hash_find (arm_cond_hsh, r);
                  *(r + 2) = d;
                  if (cond)
                    {
@@ -7752,7 +8506,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n"));
                 before any optional flags.  */
              if (opcode->comp_suffix && *opcode->comp_suffix != '\0')
                {
-                 CONST char *s = opcode->comp_suffix;
+                 const char *s = opcode->comp_suffix;
 
                  while (*s)
                    {
@@ -7777,7 +8531,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n"));
              if (r != p)
                {
                  char d;
-                 CONST struct asm_flg *flag = opcode->flags;
+                 const struct asm_flg *flag = opcode->flags;
 
                  if (flag)
                    {
@@ -7891,6 +8645,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n"));
               -m[arm]7[xx][t][[d]m]   Arm 7 processors
               -m[arm]8[10]            Arm 8 processors
               -m[arm]9[20][tdmi]      Arm 9 processors
+              -marm9e                 Allow Cirrus/DSP instructions
               -mstrongarm[110[0]]     StrongARM processors
               -mxscale                XScale processors
               -m[arm]v[2345[t[e]]]    Arm architectures
@@ -7911,7 +8666,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n"));
               -matpcs                 ARM/Thumb Procedure Call Standard
               -moabi                  Old ELF ABI  */
 
-CONST char * md_shortopts = "m:k";
+const char * md_shortopts = "m:k";
 
 struct option md_longopts[] =
 {
@@ -8173,6 +8928,9 @@ md_parse_option (c, arg)
              else if (streq (str, "9tdmi"))
                cpu_variant = (cpu_variant & ~ARM_ANY)
                  | ARM_9 | ARM_ARCH_V4T;
+             else if (streq (str, "9e"))
+               cpu_variant = (cpu_variant & ~ARM_ANY)
+                 | ARM_9 | ARM_ARCH_V4T | ARM_EXT_MAVERICK;
              else
                goto bad;
              break;
@@ -8288,6 +9046,7 @@ md_show_usage (fp)
  ARM Specific Assembler Options:\n\
   -m[arm][<processor name>] select processor variant\n\
   -m[arm]v[2|2a|3|3m|4|4t|5[t][e]] select architecture variant\n\
+  -marm9e                   allow Cirrus/DSP instructions\n\
   -mthumb                   only allow Thumb instructions\n\
   -mthumb-interwork         mark the assembled code as supporting interworking\n\
   -mall                     allow any instruction\n\
@@ -8711,9 +9470,9 @@ arm_parse_reloc ()
   };
 
   for (i = 0, ip = input_line_pointer;
-       i < sizeof (id) && (isalnum (*ip) || ispunct (*ip));
+       i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
        i++, ip++)
-    id[i] = tolower (*ip);
+    id[i] = TOLOWER (*ip);
 
   for (i = 0; reloc_map[i].str; i++)
     if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
@@ -8785,8 +9544,8 @@ s_arm_elf_cons (nbytes)
    of an rs_align_code fragment.  */
 
 void
-arm_handle_align (fragp)
-     fragS *fragp;
+arm_handle_align (fragP)
+     fragS *fragP;
 {
   static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
   static char const thumb_noop[2] = { 0xc0, 0x46 };
@@ -8797,14 +9556,17 @@ arm_handle_align (fragp)
   char * p;
   const char * noop;
   
-  if (fragp->fr_type != rs_align_code)
+  if (fragP->fr_type != rs_align_code)
     return;
 
-  bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
-  p = fragp->fr_literal + fragp->fr_fix;
+  bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
+  p = fragP->fr_literal + fragP->fr_fix;
   fix = 0;
   
-  if (fragp->tc_frag_data)
+  if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
+    bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
+  
+  if (fragP->tc_frag_data)
     {
       if (target_big_endian)
        noop = thumb_bigend_noop;
@@ -8837,8 +9599,8 @@ arm_handle_align (fragp)
       fix += noop_size;
     }
   
-  fragp->fr_fix += fix;
-  fragp->fr_var = noop_size;
+  fragP->fr_fix += fix;
+  fragP->fr_var = noop_size;
 }
 
 /* Called from md_do_align.  Used to create an alignment
@@ -8853,11 +9615,11 @@ arm_frag_align_code (n, max)
 
   /* We assume that there will never be a requirment
      to support alignments greater than 32 bytes.  */
-  if (max > 31)
+  if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
     as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
   
   p = frag_var (rs_align_code,
-               31,
+               MAX_MEM_FOR_RS_ALIGN_CODE,
                1,
                (relax_substateT) max,
                (symbolS *) NULL,
@@ -8870,9 +9632,9 @@ arm_frag_align_code (n, max)
 /* Perform target specific initialisation of a frag.  */
 
 void
-arm_init_frag (fragp)
-     fragS *fragp;
+arm_init_frag (fragP)
+     fragS *fragP;
 {
   /* Record whether this frag is in an ARM or a THUMB area.  */
-  fragp->tc_frag_data = thumb_mode;
+  fragP->tc_frag_data = thumb_mode;
 }