+ return 0;
+}
+\f
+/* ARC instructions.
+
+ Longer versions of insns must appear before shorter ones (if gas sees
+ "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
+ junk). This isn't necessary for `ld' because of the trailing ']'.
+
+ Instructions that are really macros based on other insns must appear
+ before the real insn so they're chosen when disassembling. Eg: The `mov'
+ insn is really the `and' insn. */
+
+struct arc_opcode arc_opcodes[] =
+{
+ /* Base case instruction set (core versions 5-8). */
+
+ /* "mov" is really an "and". */
+ { "mov%.q%.f %a,%b%F%S%L%U", I(-1), I(12), ARC_MACH_5, 0, 0 },
+ /* "asl" is really an "add". */
+ { "asl%.q%.f %a,%b%F%S%L%U", I(-1), I(8), ARC_MACH_5, 0, 0 },
+ /* "lsl" is really an "add". */
+ { "lsl%.q%.f %a,%b%F%S%L%U", I(-1), I(8), ARC_MACH_5, 0, 0 },
+ /* "nop" is really an "xor". */
+ { "nop", 0x7fffffff, 0x7fffffff, ARC_MACH_5, 0, 0 },
+ /* "rlc" is really an "adc". */
+ { "rlc%.q%.f %a,%b%F%S%L%U", I(-1), I(9), ARC_MACH_5, 0, 0 },
+ { "adc%.q%.f %a,%b,%c%F%S%L", I(-1), I(9), ARC_MACH_5, 0, 0 },
+ { "add%.q%.f %a,%b,%c%F%S%L", I(-1), I(8), ARC_MACH_5, 0, 0 },
+ { "and%.q%.f %a,%b,%c%F%S%L", I(-1), I(12), ARC_MACH_5, 0, 0 },
+ { "asr%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(1), ARC_MACH_5, 0, 0 },
+ { "bic%.q%.f %a,%b,%c%F%S%L", I(-1), I(14), ARC_MACH_5, 0, 0 },
+ { "b%q%.n %B", I(-1), I(4), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 },
+ { "bl%q%.n %B", I(-1), I(5), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 },
+ { "extb%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(7), ARC_MACH_5, 0, 0 },
+ { "extw%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(8), ARC_MACH_5, 0, 0 },
+ { "flag%.q %b%G%S%L", I(-1)|A(-1)|C(-1), I(3)|A(ARC_REG_SHIMM_UPDATE)|C(0), ARC_MACH_5, 0, 0 },
+ { "brk", 0x1ffffe00, 0x1ffffe00, ARC_MACH_7, 0, 0 },
+ { "sleep", 0x1ffffe01, 0x1ffffe01, ARC_MACH_7, 0, 0 },
+ { "swi", 0x1ffffe02, 0x1ffffe02, ARC_MACH_8, 0, 0 },
+ /* %Q: force cond_p=1 -> no shimm values. This insn allows an
+ optional flags spec. */
+ { "j%q%Q%.n%.f %b%F%J,%j", I(-1)|A(-1)|C(-1)|R(-1,7,1), I(7)|A(0)|C(0)|R(0,7,1), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 },
+ { "j%q%Q%.n%.f %b%F%J", I(-1)|A(-1)|C(-1)|R(-1,7,1), I(7)|A(0)|C(0)|R(0,7,1), ARC_MACH_5 | ARC_OPCODE_COND_BRANCH, 0, 0 },
+ /* This insn allows an optional flags spec. */
+ { "jl%q%Q%.n%.f %b%F%J,%j", I(-1)|A(-1)|C(-1)|R(-1,7,1)|R(-1,9,1), I(7)|A(0)|C(0)|R(0,7,1)|R(1,9,1), ARC_MACH_6 | ARC_OPCODE_COND_BRANCH, 0, 0 },
+ { "jl%q%Q%.n%.f %b%F%J", I(-1)|A(-1)|C(-1)|R(-1,7,1)|R(-1,9,1), I(7)|A(0)|C(0)|R(0,7,1)|R(1,9,1), ARC_MACH_6 | ARC_OPCODE_COND_BRANCH, 0, 0 },
+ /* Put opcode 1 ld insns first so shimm gets prefered over limm.
+ "[%b]" is before "[%b,%o]" so 0 offsets don't get printed. */
+ { "ld%Z%.X%.W%.E %a,[%s]%S%L%1", I(-1)|R(-1,13,1)|R(-1,0,511), I(1)|R(0,13,1)|R(0,0,511), ARC_MACH_5, 0, 0 },
+ { "ld%z%.x%.w%.e %a,[%s]%S%L%1", I(-1)|R(-1,4,1)|R(-1,6,7), I(0)|R(0,4,1)|R(0,6,7), ARC_MACH_5, 0, 0 },
+ { "ld%z%.x%.w%.e %a,[%s,%O]%S%L%1", I(-1)|R(-1,4,1)|R(-1,6,7), I(0)|R(0,4,1)|R(0,6,7), ARC_MACH_5, 0, 0 },
+ { "ld%Z%.X%.W%.E %a,[%s,%O]%S%L%3", I(-1)|R(-1,13,1), I(1)|R(0,13,1), ARC_MACH_5, 0, 0 },
+ { "lp%q%.n %B", I(-1), I(6), ARC_MACH_5, 0, 0 },
+ { "lr %a,[%Ab]%S%L", I(-1)|C(-1), I(1)|C(0x10), ARC_MACH_5, 0, 0 },
+ { "lsr%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(2), ARC_MACH_5, 0, 0 },
+ { "or%.q%.f %a,%b,%c%F%S%L", I(-1), I(13), ARC_MACH_5, 0, 0 },
+ { "ror%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(3), ARC_MACH_5, 0, 0 },
+ { "rrc%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(4), ARC_MACH_5, 0, 0 },
+ { "sbc%.q%.f %a,%b,%c%F%S%L", I(-1), I(11), ARC_MACH_5, 0, 0 },
+ { "sexb%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(5), ARC_MACH_5, 0, 0 },
+ { "sexw%.q%.f %a,%b%F%S%L", I(-1)|C(-1), I(3)|C(6), ARC_MACH_5, 0, 0 },
+ { "sr %c,[%Ab]%S%L", I(-1)|A(-1), I(2)|A(0x10), ARC_MACH_5, 0, 0 },
+ /* "[%b]" is before "[%b,%o]" so 0 offsets don't get printed. */
+ { "st%y%.v%.D %c,[%s]%L%S%0", I(-1)|R(-1,25,1)|R(-1,21,1), I(2)|R(0,25,1)|R(0,21,1), ARC_MACH_5, 0, 0 },
+ { "st%y%.v%.D %c,[%s,%o]%S%L%2", I(-1)|R(-1,25,1)|R(-1,21,1), I(2)|R(0,25,1)|R(0,21,1), ARC_MACH_5, 0, 0 },
+ { "sub%.q%.f %a,%b,%c%F%S%L", I(-1), I(10), ARC_MACH_5, 0, 0 },
+ { "xor%.q%.f %a,%b,%c%F%S%L", I(-1), I(15), ARC_MACH_5, 0, 0 }
+};
+
+const int arc_opcodes_count = sizeof (arc_opcodes) / sizeof (arc_opcodes[0]);
+
+const struct arc_operand_value arc_reg_names[] =
+{
+ /* Core register set r0-r63. */
+
+ /* r0-r28 - general purpose registers. */
+ { "r0", 0, REG, 0 }, { "r1", 1, REG, 0 }, { "r2", 2, REG, 0 },
+ { "r3", 3, REG, 0 }, { "r4", 4, REG, 0 }, { "r5", 5, REG, 0 },
+ { "r6", 6, REG, 0 }, { "r7", 7, REG, 0 }, { "r8", 8, REG, 0 },
+ { "r9", 9, REG, 0 }, { "r10", 10, REG, 0 }, { "r11", 11, REG, 0 },
+ { "r12", 12, REG, 0 }, { "r13", 13, REG, 0 }, { "r14", 14, REG, 0 },
+ { "r15", 15, REG, 0 }, { "r16", 16, REG, 0 }, { "r17", 17, REG, 0 },
+ { "r18", 18, REG, 0 }, { "r19", 19, REG, 0 }, { "r20", 20, REG, 0 },
+ { "r21", 21, REG, 0 }, { "r22", 22, REG, 0 }, { "r23", 23, REG, 0 },
+ { "r24", 24, REG, 0 }, { "r25", 25, REG, 0 }, { "r26", 26, REG, 0 },
+ { "r27", 27, REG, 0 }, { "r28", 28, REG, 0 },
+ /* Maskable interrupt link register. */
+ { "ilink1", 29, REG, 0 },
+ /* Maskable interrupt link register. */
+ { "ilink2", 30, REG, 0 },
+ /* Branch-link register. */
+ { "blink", 31, REG, 0 },
+
+ /* r32-r59 reserved for extensions. */
+ { "r32", 32, REG, 0 }, { "r33", 33, REG, 0 }, { "r34", 34, REG, 0 },
+ { "r35", 35, REG, 0 }, { "r36", 36, REG, 0 }, { "r37", 37, REG, 0 },
+ { "r38", 38, REG, 0 }, { "r39", 39, REG, 0 }, { "r40", 40, REG, 0 },
+ { "r41", 41, REG, 0 }, { "r42", 42, REG, 0 }, { "r43", 43, REG, 0 },
+ { "r44", 44, REG, 0 }, { "r45", 45, REG, 0 }, { "r46", 46, REG, 0 },
+ { "r47", 47, REG, 0 }, { "r48", 48, REG, 0 }, { "r49", 49, REG, 0 },
+ { "r50", 50, REG, 0 }, { "r51", 51, REG, 0 }, { "r52", 52, REG, 0 },
+ { "r53", 53, REG, 0 }, { "r54", 54, REG, 0 }, { "r55", 55, REG, 0 },
+ { "r56", 56, REG, 0 }, { "r57", 57, REG, 0 }, { "r58", 58, REG, 0 },
+ { "r59", 59, REG, 0 },
+
+ /* Loop count register (24 bits). */
+ { "lp_count", 60, REG, 0 },
+ /* Short immediate data indicator setting flags. */
+ { "r61", 61, REG, ARC_REGISTER_READONLY },
+ /* Long immediate data indicator setting flags. */
+ { "r62", 62, REG, ARC_REGISTER_READONLY },
+ /* Short immediate data indicator not setting flags. */
+ { "r63", 63, REG, ARC_REGISTER_READONLY },
+
+ /* Small-data base register. */
+ { "gp", 26, REG, 0 },
+ /* Frame pointer. */
+ { "fp", 27, REG, 0 },
+ /* Stack pointer. */
+ { "sp", 28, REG, 0 },
+
+ { "r29", 29, REG, 0 },
+ { "r30", 30, REG, 0 },
+ { "r31", 31, REG, 0 },
+ { "r60", 60, REG, 0 },
+
+ /* Auxiliary register set. */
+
+ /* Auxiliary register address map:
+ 0xffffffff-0xffffff00 (-1..-256) - customer shimm allocation
+ 0xfffffeff-0x80000000 - customer limm allocation
+ 0x7fffffff-0x00000100 - ARC limm allocation
+ 0x000000ff-0x00000000 - ARC shimm allocation */
+
+ /* Base case auxiliary registers (shimm address). */
+ { "status", 0x00, AUXREG, 0 },
+ { "semaphore", 0x01, AUXREG, 0 },
+ { "lp_start", 0x02, AUXREG, 0 },
+ { "lp_end", 0x03, AUXREG, 0 },
+ { "identity", 0x04, AUXREG, ARC_REGISTER_READONLY },
+ { "debug", 0x05, AUXREG, 0 },
+};
+
+const int arc_reg_names_count =
+ sizeof (arc_reg_names) / sizeof (arc_reg_names[0]);
+
+/* The suffix table.
+ Operands with the same name must be stored together. */
+
+const struct arc_operand_value arc_suffixes[] =
+{
+ /* Entry 0 is special, default values aren't printed by the disassembler. */
+ { "", 0, -1, 0 },
+
+ /* Base case condition codes. */
+ { "al", 0, COND, 0 },
+ { "ra", 0, COND, 0 },
+ { "eq", 1, COND, 0 },
+ { "z", 1, COND, 0 },
+ { "ne", 2, COND, 0 },
+ { "nz", 2, COND, 0 },
+ { "pl", 3, COND, 0 },
+ { "p", 3, COND, 0 },
+ { "mi", 4, COND, 0 },
+ { "n", 4, COND, 0 },
+ { "cs", 5, COND, 0 },
+ { "c", 5, COND, 0 },
+ { "lo", 5, COND, 0 },
+ { "cc", 6, COND, 0 },
+ { "nc", 6, COND, 0 },
+ { "hs", 6, COND, 0 },
+ { "vs", 7, COND, 0 },
+ { "v", 7, COND, 0 },
+ { "vc", 8, COND, 0 },
+ { "nv", 8, COND, 0 },
+ { "gt", 9, COND, 0 },
+ { "ge", 10, COND, 0 },
+ { "lt", 11, COND, 0 },
+ { "le", 12, COND, 0 },
+ { "hi", 13, COND, 0 },
+ { "ls", 14, COND, 0 },
+ { "pnz", 15, COND, 0 },
+
+ /* Condition codes 16-31 reserved for extensions. */
+
+ { "f", 1, FLAG, 0 },
+
+ { "nd", ARC_DELAY_NONE, DELAY, 0 },
+ { "d", ARC_DELAY_NORMAL, DELAY, 0 },
+ { "jd", ARC_DELAY_JUMP, DELAY, 0 },
+
+ { "b", 1, SIZE1, 0 },
+ { "b", 1, SIZE10, 0 },
+ { "b", 1, SIZE22, 0 },
+ { "w", 2, SIZE1, 0 },
+ { "w", 2, SIZE10, 0 },
+ { "w", 2, SIZE22, 0 },
+ { "x", 1, SIGN0, 0 },
+ { "x", 1, SIGN9, 0 },
+ { "a", 1, ADDRESS3, 0 },
+ { "a", 1, ADDRESS12, 0 },
+ { "a", 1, ADDRESS24, 0 },
+
+ { "di", 1, CACHEBYPASS5, 0 },
+ { "di", 1, CACHEBYPASS14, 0 },
+ { "di", 1, CACHEBYPASS26, 0 },
+};
+
+const int arc_suffixes_count =
+ sizeof (arc_suffixes) / sizeof (arc_suffixes[0]);
+
+/* Indexed by first letter of opcode. Points to chain of opcodes with same
+ first letter. */
+static struct arc_opcode *opcode_map[26 + 1];