diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 51ab230..ff8505c 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -238,6 +238,8 @@ static const arm_feature_set fpu_neon_ext_armv8 = ARM_FEATURE (0, FPU_NEON_EXT_ARMV8); static const arm_feature_set fpu_crypto_ext_armv8 = ARM_FEATURE (0, FPU_CRYPTO_EXT_ARMV8); +static const arm_feature_set crc_ext_armv8 = + ARM_FEATURE (0, CRC_EXT_ARMV8); static int mfloat_abi_opt = -1; /* Record user cpu selection for object attributes. */ @@ -748,6 +750,7 @@ struct asm_opcode #define BAD_PC_WRITEBACK \ _("cannot use writeback with PC-relative addressing") #define BAD_RANGE _("branch out of range") +#define UNPRED_REG(R) _("using " R " results in unpredictable behaviour") static struct hash_control * arm_ops_hsh; static struct hash_control * arm_cond_hsh; @@ -16314,6 +16317,63 @@ do_sha256su0 (void) { do_crypto_2op_1 (N_32, 1); } + +static void +do_crc32_1 (unsigned int poly, unsigned int sz) +{ + unsigned int Rd = inst.operands[0].reg; + unsigned int Rn = inst.operands[1].reg; + unsigned int Rm = inst.operands[2].reg; + + set_it_insn_type (OUTSIDE_IT_INSN); + inst.instruction |= LOW4 (Rd) << (thumb_mode ? 8 : 12); + inst.instruction |= LOW4 (Rn) << 16; + inst.instruction |= LOW4 (Rm); + inst.instruction |= sz << (thumb_mode ? 4 : 21); + inst.instruction |= poly << (thumb_mode ? 20 : 9); + + if (Rd == REG_PC || Rn == REG_PC || Rm == REG_PC) + as_warn (UNPRED_REG ("r15")); + if (thumb_mode && (Rd == REG_SP || Rn == REG_SP || Rm == REG_SP)) + as_warn (UNPRED_REG ("r13")); +} + +static void +do_crc32b (void) +{ + do_crc32_1 (0, 0); +} + +static void +do_crc32h (void) +{ + do_crc32_1 (0, 1); +} + +static void +do_crc32w (void) +{ + do_crc32_1 (0, 2); +} + +static void +do_crc32cb (void) +{ + do_crc32_1 (1, 0); +} + +static void +do_crc32ch (void) +{ + do_crc32_1 (1, 1); +} + +static void +do_crc32cw (void) +{ + do_crc32_1 (1, 2); +} + /* Overall per-instruction processing. */ @@ -17799,6 +17859,13 @@ static struct asm_barrier_opt barrier_opt_names[] = { mnem, OPS##nops ops, OT_unconditional, 0x##op, 0x##top, ARM_VARIANT, \ THUMB_VARIANT, do_##ae, do_##te } +/* Same as TUE but the encoding function for ARM and Thumb modes is the same. + Used by mnemonics that have very minimal differences in the encoding for + ARM and Thumb variants and can be handled in a common function. */ +#define TUEc(mnem, op, top, nops, ops, en) \ + { mnem, OPS##nops ops, OT_unconditional, 0x##op, 0x##top, ARM_VARIANT, \ + THUMB_VARIANT, do_##en, do_##en } + /* Mnemonic that cannot be conditionalized, and bears 0xF in its ARM condition code field. */ #define TUF(mnem, op, top, nops, ops, ae, te) \ @@ -18537,6 +18604,17 @@ static const struct asm_opcode insns[] = nUF(sha256su0, _sha2op, 2, (RNQ, RNQ), sha256su0), #undef ARM_VARIANT +#define ARM_VARIANT & crc_ext_armv8 +#undef THUMB_VARIANT +#define THUMB_VARIANT & crc_ext_armv8 + TUEc("crc32b", 1000040, fac0f080, 3, (RR, oRR, RR), crc32b), + TUEc("crc32h", 1200040, fac0f090, 3, (RR, oRR, RR), crc32h), + TUEc("crc32w", 1400040, fac0f0a0, 3, (RR, oRR, RR), crc32w), + TUEc("crc32cb",1000240, fad0f080, 3, (RR, oRR, RR), crc32cb), + TUEc("crc32ch",1200240, fad0f090, 3, (RR, oRR, RR), crc32ch), + TUEc("crc32cw",1400240, fad0f0a0, 3, (RR, oRR, RR), crc32cw), + +#undef ARM_VARIANT #define ARM_VARIANT & fpu_fpa_ext_v1 /* Core FPA instruction set (V1). */ #undef THUMB_VARIANT #define THUMB_VARIANT NULL @@ -23991,6 +24069,7 @@ struct arm_option_extension_value_table #define ARM_EXT_OPT(N, V, AA) { N, sizeof (N) - 1, V, AA } static const struct arm_option_extension_value_table arm_extensions[] = { + ARM_EXT_OPT ("crc", ARCH_CRC_ARMV8, ARM_FEATURE (ARM_EXT_V8, 0)), ARM_EXT_OPT ("crypto", FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, ARM_FEATURE (ARM_EXT_V8, 0)), ARM_EXT_OPT ("fp", FPU_ARCH_VFP_ARMV8, diff --git a/gas/testsuite/gas/arm/crc32-bad.d b/gas/testsuite/gas/arm/crc32-bad.d new file mode 100644 index 0000000..34e0b6c --- /dev/null +++ b/gas/testsuite/gas/arm/crc32-bad.d @@ -0,0 +1,21 @@ +#objdump: -dr --prefix-addresses --show-raw-insn +#name: Unpredictable ARMv8 CRC32 instructions. +#as: -march=armv8-a+crc +#stderr: crc32-bad.l + +.*: +file format .*arm.* + + +Disassembly of section .text: +0+0 <[^>]*> e101f042 crc32b pc, r1, r2 ; +0+4 <[^>]*> e12f0042 crc32h r0, pc, r2 ; +0+8 <[^>]*> e141004f crc32w r0, r1, pc ; +0+c <[^>]*> e10f0242 crc32cb r0, pc, r2 ; +0+10 <[^>]*> e121f242 crc32ch pc, r1, r2 ; +0+14 <[^>]*> e14f0242 crc32cw r0, pc, r2 ; +0+18 <[^>]*> fac1 fd82 crc32b sp, r1, r2 ; +0+1c <[^>]*> facf f092 crc32h r0, pc, r2 ; +0+20 <[^>]*> fac1 f0ad crc32w r0, r1, sp ; +0+24 <[^>]*> fadf f082 crc32cb r0, pc, r2 ; +0+28 <[^>]*> fad1 fd92 crc32ch sp, r1, r2 ; +0+2c <[^>]*> fadf f0a2 crc32cw r0, pc, r2 ; diff --git a/gas/testsuite/gas/arm/crc32-bad.l b/gas/testsuite/gas/arm/crc32-bad.l new file mode 100644 index 0000000..ea520aa --- /dev/null +++ b/gas/testsuite/gas/arm/crc32-bad.l @@ -0,0 +1,13 @@ +[^:]*: Assembler messages: +[^:]*:4: Warning: using r15 results in unpredictable behaviour +[^:]*.s:5: Warning: using r15 results in unpredictable behaviour +[^:]*.s:6: Warning: using r15 results in unpredictable behaviour +[^:]*.s:7: Warning: using r15 results in unpredictable behaviour +[^:]*.s:8: Warning: using r15 results in unpredictable behaviour +[^:]*.s:9: Warning: using r15 results in unpredictable behaviour +[^:]*.s:12: Warning: using r13 results in unpredictable behaviour +[^:]*.s:13: Warning: using r15 results in unpredictable behaviour +[^:]*.s:14: Warning: using r13 results in unpredictable behaviour +[^:]*.s:15: Warning: using r15 results in unpredictable behaviour +[^:]*.s:16: Warning: using r13 results in unpredictable behaviour +[^:]*.s:17: Warning: using r15 results in unpredictable behaviour diff --git a/gas/testsuite/gas/arm/crc32-bad.s b/gas/testsuite/gas/arm/crc32-bad.s new file mode 100644 index 0000000..4e497e3 --- /dev/null +++ b/gas/testsuite/gas/arm/crc32-bad.s @@ -0,0 +1,17 @@ +.section .text +.syntax unified +.arm +crc32b r15, r1, r2 +crc32h r0, r15, r2 +crc32w r0, r1, r15 +crc32cb r0, r15, r2 +crc32ch r15, r1, r2 +crc32cw r0, r15, r2 + +.thumb +crc32b r13, r1, r2 +crc32h r0, r15, r2 +crc32w r0, r1, r13 +crc32cb r0, r15, r2 +crc32ch r13, r1, r2 +crc32cw r0, r15, r2 diff --git a/gas/testsuite/gas/arm/crc32.d b/gas/testsuite/gas/arm/crc32.d new file mode 100644 index 0000000..e511f5e --- /dev/null +++ b/gas/testsuite/gas/arm/crc32.d @@ -0,0 +1,21 @@ +#objdump: -dr --prefix-addresses --show-raw-insn +#name: ARMv8 CRC32 instructions +#as: -march=armv8-a+crc + +.*: *file format .*arm.* + + +Disassembly of section .text: +0+0 <[^>]*> e1010042 crc32b r0, r1, r2 +0+4 <[^>]*> e1210042 crc32h r0, r1, r2 +0+8 <[^>]*> e1410042 crc32w r0, r1, r2 +0+c <[^>]*> e1010242 crc32cb r0, r1, r2 +0+10 <[^>]*> e1210242 crc32ch r0, r1, r2 +0+14 <[^>]*> e1410242 crc32cw r0, r1, r2 +0+18 <[^>]*> fac1 f082 crc32b r0, r1, r2 +0+1c <[^>]*> fac1 f092 crc32h r0, r1, r2 +0+20 <[^>]*> fac1 f0a2 crc32w r0, r1, r2 +0+24 <[^>]*> fad1 f082 crc32cb r0, r1, r2 +0+28 <[^>]*> fad1 f092 crc32ch r0, r1, r2 +0+2c <[^>]*> fad1 f0a2 crc32cw r0, r1, r2 + diff --git a/gas/testsuite/gas/arm/crc32.s b/gas/testsuite/gas/arm/crc32.s new file mode 100644 index 0000000..63c1d68 --- /dev/null +++ b/gas/testsuite/gas/arm/crc32.s @@ -0,0 +1,17 @@ +.section .text +.syntax unified +.arm +crc32b r0, r1, r2 +crc32h r0, r1, r2 +crc32w r0, r1, r2 +crc32cb r0, r1, r2 +crc32ch r0, r1, r2 +crc32cw r0, r1, r2 + +.thumb +crc32b r0, r1, r2 +crc32h r0, r1, r2 +crc32w r0, r1, r2 +crc32cb r0, r1, r2 +crc32ch r0, r1, r2 +crc32cw r0, r1, r2 diff --git a/include/opcode/arm.h b/include/opcode/arm.h index 1ac38a0..851fd3c 100644 --- a/include/opcode/arm.h +++ b/include/opcode/arm.h @@ -81,6 +81,7 @@ #define FPU_VFP_EXT_ARMV8 0x00020000 /* FP for ARMv8. */ #define FPU_NEON_EXT_ARMV8 0x00010000 /* Neon for ARMv8. */ #define FPU_CRYPTO_EXT_ARMV8 0x00008000 /* Crypto for ARMv8. */ +#define CRC_EXT_ARMV8 0x00004000 /* CRC32 for ARMv8. */ /* Architectures are the sum of the base and extensions. The ARM ARM (rev E) defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T, @@ -189,6 +190,7 @@ #define FPU_ARCH_NEON_VFP_ARMV8 ARM_FEATURE(0, FPU_NEON_ARMV8 | FPU_VFP_ARMV8) #define FPU_ARCH_CRYPTO_NEON_VFP_ARMV8 \ ARM_FEATURE(0, FPU_CRYPTO_ARMV8 | FPU_NEON_ARMV8 | FPU_VFP_ARMV8) +#define ARCH_CRC_ARMV8 ARM_FEATURE(0, CRC_EXT_ARMV8) #define FPU_ARCH_ENDIAN_PURE ARM_FEATURE (0, FPU_ENDIAN_PURE) diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index ad7a67f..0b1ed1a 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -903,6 +903,13 @@ static const struct opcode32 arm_opcodes[] = {ARM_EXT_V8, 0x01d00c9f, 0x0ff00fff, "ldab%c\t%12-15r, [%16-19R]"}, {ARM_EXT_V8, 0x01e0fc90, 0x0ff0fff0, "stlh%c\t%0-3r, [%16-19R]"}, {ARM_EXT_V8, 0x01f00c9f, 0x0ff00fff, "ldaexh%c\t%12-15r, [%16-19R]"}, + /* CRC32 instructions. */ + {CRC_EXT_ARMV8, 0xe1000040, 0xfff00ff0, "crc32b\t%12-15R, %16-19R, %0-3R"}, + {CRC_EXT_ARMV8, 0xe1200040, 0xfff00ff0, "crc32h\t%12-15R, %16-19R, %0-3R"}, + {CRC_EXT_ARMV8, 0xe1400040, 0xfff00ff0, "crc32w\t%12-15R, %16-19R, %0-3R"}, + {CRC_EXT_ARMV8, 0xe1000240, 0xfff00ff0, "crc32cb\t%12-15R, %16-19R, %0-3R"}, + {CRC_EXT_ARMV8, 0xe1200240, 0xfff00ff0, "crc32ch\t%12-15R, %16-19R, %0-3R"}, + {CRC_EXT_ARMV8, 0xe1400240, 0xfff00ff0, "crc32cw\t%12-15R, %16-19R, %0-3R"}, /* Virtualization Extension instructions. */ {ARM_EXT_VIRT, 0x0160006e, 0x0fffffff, "eret%c"}, @@ -1455,7 +1462,8 @@ static const struct opcode16 thumb_opcodes[] = %d print bitfield in decimal %W print bitfield*4 in decimal %r print bitfield as an ARM register - %R as %<>r bit r15 is UNPREDICTABLE + %R as %<>r but r15 is UNPREDICTABLE + %S as %<>R but r13 is UNPREDICTABLE %c print bitfield as a condition code %'c print specified char iff bitfield is all ones @@ -1490,6 +1498,14 @@ static const struct opcode32 thumb32_opcodes[] = {ARM_EXT_V8, 0xe8d00fef, 0xfff00fff, "ldaex%c\t%12-15r, [%16-19R]"}, {ARM_EXT_V8, 0xe8d000ff, 0xfff000ff, "ldaexd%c\t%12-15r, %8-11r, [%16-19R]"}, + /* CRC32 instructions. */ + {CRC_EXT_ARMV8, 0xfac0f080, 0xfff0f0f0, "crc32b\t%8-11S, %16-19S, %0-3S"}, + {CRC_EXT_ARMV8, 0xfac0f090, 0xfff0f0f0, "crc32h\t%9-11S, %16-19S, %0-3S"}, + {CRC_EXT_ARMV8, 0xfac0f0a0, 0xfff0f0f0, "crc32w\t%8-11S, %16-19S, %0-3S"}, + {CRC_EXT_ARMV8, 0xfad0f080, 0xfff0f0f0, "crc32cb\t%8-11S, %16-19S, %0-3S"}, + {CRC_EXT_ARMV8, 0xfad0f090, 0xfff0f0f0, "crc32ch\t%8-11S, %16-19S, %0-3S"}, + {CRC_EXT_ARMV8, 0xfad0f0a0, 0xfff0f0f0, "crc32cw\t%8-11S, %16-19S, %0-3S"}, + /* V7 instructions. */ {ARM_EXT_V7, 0xf910f000, 0xff70f000, "pli%c\t%a"}, {ARM_EXT_V7, 0xf3af80f0, 0xfffffff0, "dbg%c\t#%0-3d"}, @@ -4427,6 +4443,10 @@ print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given) value_in_comment = val * 4; break; + case 'S': + if (val == 13) + is_unpredictable = TRUE; + /* Fall through. */ case 'R': if (val == 15) is_unpredictable = TRUE;