Module Name: src Committed By: matt Date: Wed Nov 21 08:52:09 UTC 2012
Modified Files: src/gnu/dist/binutils/gas/config [matt-nb6-plus]: tc-arm.c src/gnu/dist/binutils/include/opcode [matt-nb6-plus]: arm.h src/gnu/dist/binutils/opcodes [matt-nb6-plus]: arm-dis.c Log Message: Teach binutils (gas) just enough to handle some armv7 instructions (dsb, dmb, isb, bfc, bfi, sbfx, ubfx) and the .arch pseudo-op. To generate a diff of this commit: cvs rdiff -u -r1.6.6.2 -r1.6.6.3 src/gnu/dist/binutils/gas/config/tc-arm.c cvs rdiff -u -r1.2.6.2 -r1.2.6.3 src/gnu/dist/binutils/include/opcode/arm.h cvs rdiff -u -r1.2.6.2 -r1.2.6.3 src/gnu/dist/binutils/opcodes/arm-dis.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/gnu/dist/binutils/gas/config/tc-arm.c diff -u src/gnu/dist/binutils/gas/config/tc-arm.c:1.6.6.2 src/gnu/dist/binutils/gas/config/tc-arm.c:1.6.6.3 --- src/gnu/dist/binutils/gas/config/tc-arm.c:1.6.6.2 Tue Nov 20 18:41:50 2012 +++ src/gnu/dist/binutils/gas/config/tc-arm.c Wed Nov 21 08:52:09 2012 @@ -6746,6 +6746,186 @@ do_swi (char * str) } static void +do_dsb (char * str) +{ + skip_whitespace (str); + /* Allow optional leading '#'. */ + if (is_immediate_prefix (*str)) + str++; + + end_of_line (str); +} + +static void +do_bfci (char * str) +{ + expressionS expr; + unsigned long lsb; + unsigned long width; + int reg; + + skip_whitespace (str); + + if ((reg = reg_required_here (&str, 12)) == FAIL + || skip_past_comma (&str) == FAIL) + return; + + if (reg == REG_PC) + { + inst.error = BAD_PC; + return; + } + + if ((inst.instruction & 0xf) == 0) + { + if ((reg == reg_required_here (&str, 0)) == FAIL + || skip_past_comma (&str) == FAIL) + return; + + if (reg == REG_PC) + { + inst.error = BAD_PC; + return; + } + } + + if (is_immediate_prefix (*str)) + str++; + else + { + inst.error = _("immediate expression expected"); + return; + } + + if (my_get_expression (&expr, &str)) + return; + + if (expr.X_op != O_constant) + { + inst.error = _("constant expression expected"); + return FAIL; + } + + lsb = expr.X_add_number; + if (lsb > 31) + { + inst.error = _("invalid lsb"); + return; + } + + if (skip_past_comma (&str) == FAIL) + return; + + if (is_immediate_prefix (*str)) + str++; + else + { + inst.error = _("immediate expression expected"); + return; + } + + if (my_get_expression (&expr, &str)) + return; + + if (expr.X_op != O_constant) + { + inst.error = _("constant expression expected"); + return FAIL; + } + + width = expr.X_add_number; + if (lsb + width > 32 || width > 32 || width == 0) + { + if (!inst.error) + inst.error = _("invalid width"); + return; + } + + inst.instruction |= (lsb << 7); + inst.instruction |= (lsb + width - 1) << 16; + + end_of_line (str); +} + +static void +do_bfx (char * str) +{ + expressionS expr; + unsigned long lsb; + unsigned long width; + int rd, rn; + + skip_whitespace (str); + + if ((rd = reg_required_here (&str, 12)) == FAIL + || skip_past_comma (&str) == FAIL + || (rn = reg_required_here (&str, 0)) == FAIL + || skip_past_comma (&str) == FAIL) + { + inst.error = BAD_ARGS; + return; + } + else if (rd == REG_PC || rn == REG_PC) + { + inst.error = BAD_PC; + return; + } + + if (is_immediate_prefix (*str)) + str++; + else + { + inst.error = _("immediate expression expected"); + return; + } + + if (my_get_expression (&expr, &str)) + return; + + if (expr.X_op != O_constant) + { + inst.error = _("constant expression expected"); + return FAIL; + } + + lsb = expr.X_add_number; + if (lsb > 31) + { + inst.error = _("invalid lsb"); + return; + } + + if (skip_past_comma (&str) == FAIL) + { + inst.error = BAD_ARGS; + return; + } + + if (is_immediate_prefix (*str)) + str++; + else + { + inst.error = _("immediate expression expected"); + return; + } + + if (my_get_expression (&expr, &str)) + return; + + width = expr.X_add_number; + if (lsb + width > 32 || width > 32 || width == 0) + { + inst.error = _("invalid width"); + return; + } + + inst.instruction |= (lsb << 7); + inst.instruction |= (width - 1) << 16; + + end_of_line (str); +} + +static void do_swap (char * str) { int reg; @@ -10014,6 +10194,15 @@ static const struct asm_opcode insns[] = /* ARM V6Z. */ { "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi}, + /* ARM V7A. */ + { "dmb", 0xf57ff05f, 0, ARM_EXT_V7A, do_dsb}, + { "dsb", 0xf57ff04f, 0, ARM_EXT_V7A, do_dsb}, + { "isb", 0xf57ff06f, 0, ARM_EXT_V7A, do_dsb}, + { "sbfx", 0xe7a00050, 4, ARM_EXT_V7A, do_bfx}, + { "bfi", 0xe7c00010, 3, ARM_EXT_V7A, do_bfci}, + { "bfc", 0xe7c0001f, 3, ARM_EXT_V7A, do_bfci}, + { "ubfx", 0xe7e00050, 4, ARM_EXT_V7A, do_bfx}, + /* 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}, @@ -12714,6 +12903,8 @@ static struct arm_cpu_option_table arm_c {"mpcorenovfp", ARM_ARCH_V6K, FPU_NONE}, {"arm1176jz-s", ARM_ARCH_V6ZK, FPU_NONE}, {"arm1176jzf-s", ARM_ARCH_V6ZK, FPU_ARCH_VFP_V2}, + {"cortex-a8", ARM_ARCH_V7A, FPU_ARCH_VFP_V2}, + {"cortex-a9", ARM_ARCH_V7A, FPU_ARCH_VFP_V2}, /* ??? XSCALE is really an architecture. */ {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2}, /* ??? iwmmxt is not a processor. */ @@ -12757,6 +12948,8 @@ static struct arm_arch_option_table arm_ {"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP}, {"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP}, {"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP}, + {"armv7", ARM_ARCH_V7A, FPU_ARCH_VFP}, + {"armv7a", ARM_ARCH_V7A, FPU_ARCH_VFP}, {"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP}, {"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP}, {NULL, 0, 0} @@ -12965,6 +13158,20 @@ arm_parse_arch (char * str) return 0; } +static void +s_arch (int ignore ATTRIBUTE_UNUSED) +{ + char *name, *p, c; + SKIP_WHITESPACE (); + name = input_line_pointer; + c = get_symbol_end (); + p = input_line_pointer; + arm_parse_arch (name); + *p = c; + SKIP_WHITESPACE (); + demand_empty_rest_of_line (); +} + static int arm_parse_fpu (char * str) { @@ -14839,6 +15046,7 @@ const pseudo_typeS md_pseudo_table[] = { "unreq", s_unreq, 0 }, { "bss", s_bss, 0 }, { "align", s_align, 0 }, + { "arch", s_arch, 0 }, { "arm", s_arm, 0 }, { "thumb", s_thumb, 0 }, { "code", s_code, 0 }, Index: src/gnu/dist/binutils/include/opcode/arm.h diff -u src/gnu/dist/binutils/include/opcode/arm.h:1.2.6.2 src/gnu/dist/binutils/include/opcode/arm.h:1.2.6.3 --- src/gnu/dist/binutils/include/opcode/arm.h:1.2.6.2 Tue Nov 20 18:47:52 2012 +++ src/gnu/dist/binutils/include/opcode/arm.h Wed Nov 21 08:52:08 2012 @@ -34,6 +34,7 @@ #define ARM_EXT_V6 0x00001000 /* ARM V6. */ #define ARM_EXT_V6K 0x00002000 /* ARM V6K. */ #define ARM_EXT_V6Z 0x00004000 /* ARM V6Z. */ +#define ARM_EXT_V7A 0x00008000 /* ARM V7A. */ /* Co-processor space extensions. */ #define ARM_CEXT_XSCALE 0x00800000 /* Allow MIA etc. */ @@ -65,6 +66,7 @@ #define ARM_ARCH_V6K (ARM_ARCH_V6 | ARM_EXT_V6K) #define ARM_ARCH_V6Z (ARM_ARCH_V6 | ARM_EXT_V6Z) #define ARM_ARCH_V6ZK (ARM_ARCH_V6 | ARM_EXT_V6K | ARM_EXT_V6Z) +#define ARM_ARCH_V7A (ARM_ARCH_V6ZK | ARM_EXT_V7A) /* Processors with specific extensions in the co-processor space. */ #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE | ARM_CEXT_XSCALE) Index: src/gnu/dist/binutils/opcodes/arm-dis.c diff -u src/gnu/dist/binutils/opcodes/arm-dis.c:1.2.6.2 src/gnu/dist/binutils/opcodes/arm-dis.c:1.2.6.3 --- src/gnu/dist/binutils/opcodes/arm-dis.c:1.2.6.2 Tue Nov 20 18:51:40 2012 +++ src/gnu/dist/binutils/opcodes/arm-dis.c Wed Nov 21 08:52:09 2012 @@ -80,6 +80,7 @@ %A print address for ldc/stc/ldf/stf instruction %m print register mask for ldm/stm instruction %C print the PSR sub type. + %E print the LSB and WIDTH fields of a BFI or BFC instruction. %F print the COUNT field of a LFM/SFM instruction. IWMMXT specific format options: %<bitfield>g print as an iWMMXt 64-bit register @@ -118,6 +119,17 @@ static const struct arm_opcode arm_opcod {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"}, {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"}, + /* ARM V7 instructions. */ + {ARM_EXT_V7A, 0x07a00050, 0x0fa00070, "%22?usbfx%c\t%12-15r, %0-3r, #%7-11d, #%16-20W"}, + {ARM_EXT_V7A, 0x07c0001f, 0x0fa0007f, "bfc%c\t%12-15R, %E"}, + {ARM_EXT_V7A, 0x07c00010, 0x0fa00070, "bfi%c\t%12-15R, %0-3r, %E"}, + {ARM_EXT_V7A, 0xf57ff05f, 0xffffffff, "dmb"}, + {ARM_EXT_V7A, 0xf57ff050, 0xfffffff0, "dmb\t#%0-3d"}, + {ARM_EXT_V7A, 0xf57ff05f, 0xffffffff, "dsb"}, + {ARM_EXT_V7A, 0xf57ff050, 0xfffffff0, "dsb\t%#0-3d"}, + {ARM_EXT_V7A, 0xf57ff06f, 0xffffffff, "isb"}, + {ARM_EXT_V7A, 0xf57ff060, 0xfffffff0, "isb\t%#0-3d"}, + /* ARM V6Z instructions. */ {ARM_EXT_V6Z, 0x01600070, 0x0ff000f0, "smi%c\t%e"}, @@ -1234,6 +1246,19 @@ print_insn_arm (pc, info, given) func (stream, "c"); break; + case 'E': + { + long msb = (given >> 16) & 0x1f; + long lsb = (given >> 7) & 0x1f; + long width = msb - lsb + 1; + + if (width > 0) + func(stream, "#%lu, #%lu", lsb, width); + else + func(stream, "(invalid %lu:%lu)", lsb, msb); + } + break; + case 'F': switch (given & 0x00408000) {