Index: include/llvm/IR/IntrinsicsARM.td =================================================================== --- include/llvm/IR/IntrinsicsARM.td +++ include/llvm/IR/IntrinsicsARM.td @@ -97,6 +97,22 @@ llvm_i32_ty, llvm_i32_ty], []>; //===----------------------------------------------------------------------===// +// CRC32 + +def int_arm_crc32b : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32cb : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32h : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32ch : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32w : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + +//===----------------------------------------------------------------------===// // Advanced SIMD (NEON) // The following classes do not correspond directly to GCC builtins. Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td +++ lib/Target/ARM/ARMInstrInfo.td @@ -4047,6 +4047,45 @@ (PKHTB GPRnopc:$src1, GPRnopc:$src2, imm1_15:$sh)>; //===----------------------------------------------------------------------===// +// CRC Instructions +// +// Polynomials: +// + CRC32{B,H,W} 0x04C11DB7 +// + CRC32C{B,H,W} 0x1EDC6F41 +// + +class AI_crc32 sz, string suffix, SDPatternOperator builtin> + : AInoP<(outs GPRnopc:$Rd), (ins GPRnopc:$Rn, GPRnopc:$Rm), MiscFrm, NoItinerary, + !strconcat("crc32", suffix), "\t$Rd, $Rn, $Rm", + [(set GPRnopc:$Rd, (builtin GPRnopc:$Rn, GPRnopc:$Rm))]>, + Requires<[IsARM, HasV8]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + + let Inst{31-28} = 0b1110; + let Inst{27-23} = 0b00010; + let Inst{22-21} = sz; + let Inst{20} = 0; + let Inst{19-16} = Rn; + let Inst{15-12} = Rd; + let Inst{11-10} = 0b00; + let Inst{9} = C; + let Inst{8} = 0; + let Inst{7-4} = 0b0100; + let Inst{3-0} = Rm; + + let Unpredictable{11-8} = 0b1101; +} + +def CRC32B : AI_crc32<0, 0b00, "b", int_arm_crc32b>; +def CRC32CB : AI_crc32<1, 0b00, "cb", int_arm_crc32cb>; +def CRC32H : AI_crc32<0, 0b01, "h", int_arm_crc32h>; +def CRC32CH : AI_crc32<1, 0b01, "ch", int_arm_crc32ch>; +def CRC32W : AI_crc32<0, 0b10, "w", int_arm_crc32w>; +def CRC32CW : AI_crc32<1, 0b10, "cw", int_arm_crc32cw>; + +//===----------------------------------------------------------------------===// // Comparison Instructions... // Index: lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- lib/Target/ARM/ARMInstrThumb2.td +++ lib/Target/ARM/ARMInstrThumb2.td @@ -465,6 +465,18 @@ let Inst{3-0} = Rm; } +class T2ThreeRegNoP pattern> + : T2XI { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; + + let Inst{11-8} = Rd; + let Inst{19-16} = Rn; + let Inst{3-0} = Rm; +} + class T2sThreeReg pattern> : T2sI { @@ -3004,6 +3016,34 @@ Requires<[HasT2ExtractPack, IsThumb2]>; //===----------------------------------------------------------------------===// +// CRC32 Instructions +// +// Polynomials: +// + CRC32{B,H,W} 0x04C11DB7 +// + CRC32C{B,H,W} 0x1EDC6F41 +// + +class T2I_crc32 sz, string suffix, SDPatternOperator builtin> + : T2ThreeRegNoP<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), NoItinerary, + !strconcat("crc32", suffix, "\t$Rd, $Rn, $Rm"), + [(set rGPR:$Rd, (builtin rGPR:$Rn, rGPR:$Rm))]>, + Requires<[IsThumb2, HasV8]> { + let Inst{31-27} = 0b11111; + let Inst{26-21} = 0b010110; + let Inst{20} = C; + let Inst{15-12} = 0b1111; + let Inst{7-6} = 0b10; + let Inst{5-4} = sz; +} + +def t2CRC32B : T2I_crc32<0, 0b00, "b", int_arm_crc32b>; +def t2CRC32CB : T2I_crc32<1, 0b00, "cb", int_arm_crc32cb>; +def t2CRC32H : T2I_crc32<0, 0b01, "h", int_arm_crc32h>; +def t2CRC32CH : T2I_crc32<1, 0b01, "ch", int_arm_crc32ch>; +def t2CRC32W : T2I_crc32<0, 0b10, "w", int_arm_crc32w>; +def t2CRC32CW : T2I_crc32<1, 0b10, "cw", int_arm_crc32cw>; + +//===----------------------------------------------------------------------===// // Comparison Instructions... // defm t2CMP : T2I_cmp_irs<0b1101, "cmp", Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4803,7 +4803,7 @@ if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" || - Mnemonic == "trap" || Mnemonic == "hlt" || + Mnemonic == "trap" || Mnemonic == "hlt" || Mnemonic.startswith("crc32") || Mnemonic.startswith("cps") || Mnemonic.startswith("vsel") || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" || Index: test/MC/ARM/crc32-thumb.s =================================================================== --- /dev/null +++ test/MC/ARM/crc32-thumb.s @@ -0,0 +1,23 @@ +@ RUN: llvm-mc -triple=thumbv8 -show-encoding < %s | FileCheck %s +@ RUN: not llvm-mc -triple=thumbv7 -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-V7 + crc32b r0, r1, r2 + crc32h r0, r1, r2 + crc32w r0, r1, r2 + +@ CHECK: crc32b r0, r1, r2 @ encoding: [0xc1,0xfa,0x82,0xf0] +@ CHECK: crc32h r0, r1, r2 @ encoding: [0xc1,0xfa,0x92,0xf0] +@ CHECK: crc32w r0, r1, r2 @ encoding: [0xc1,0xfa,0xa2,0xf0] +@ CHECK-V7: error: instruction requires: armv8 +@ CHECK-V7: error: instruction requires: armv8 +@ CHECK-V7: error: instruction requires: armv8 + + crc32cb r0, r1, r2 + crc32ch r0, r1, r2 + crc32cw r0, r1, r2 + +@ CHECK: crc32cb r0, r1, r2 @ encoding: [0xd1,0xfa,0x82,0xf0] +@ CHECK: crc32ch r0, r1, r2 @ encoding: [0xd1,0xfa,0x92,0xf0] +@ CHECK: crc32cw r0, r1, r2 @ encoding: [0xd1,0xfa,0xa2,0xf0] +@ CHECK-V7: error: instruction requires: armv8 +@ CHECK-V7: error: instruction requires: armv8 +@ CHECK-V7: error: instruction requires: armv8 Index: test/MC/ARM/crc32.s =================================================================== --- /dev/null +++ test/MC/ARM/crc32.s @@ -0,0 +1,23 @@ +@ RUN: llvm-mc -triple=armv8 -show-encoding < %s | FileCheck %s +@ RUN: not llvm-mc -triple=armv7 -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-V7 + crc32b r0, r1, r2 + crc32h r0, r1, r2 + crc32w r0, r1, r2 + +@ CHECK: crc32b r0, r1, r2 @ encoding: [0x42,0x00,0x01,0xe1] +@ CHECK: crc32h r0, r1, r2 @ encoding: [0x42,0x00,0x21,0xe1] +@ CHECK: crc32w r0, r1, r2 @ encoding: [0x42,0x00,0x41,0xe1] +@ CHECK-V7: error: instruction requires: armv8 +@ CHECK-V7: error: instruction requires: armv8 +@ CHECK-V7: error: instruction requires: armv8 + + crc32cb r0, r1, r2 + crc32ch r0, r1, r2 + crc32cw r0, r1, r2 + +@ CHECK: crc32cb r0, r1, r2 @ encoding: [0x42,0x02,0x01,0xe1] +@ CHECK: crc32ch r0, r1, r2 @ encoding: [0x42,0x02,0x21,0xe1] +@ CHECK: crc32cw r0, r1, r2 @ encoding: [0x42,0x02,0x41,0xe1] +@ CHECK-V7: error: instruction requires: armv8 +@ CHECK-V7: error: instruction requires: armv8 +@ CHECK-V7: error: instruction requires: armv8 Index: test/MC/ARM/invalid-crc32.s =================================================================== --- /dev/null +++ test/MC/ARM/invalid-crc32.s @@ -0,0 +1,16 @@ +@ RUN: not llvm-mc -triple=armv8 -show-encoding < %s 2>&1 | FileCheck %s +@ RUN: not llvm-mc -triple=thumbv8 -show-encoding < %s 2>&1 | FileCheck %s + + crc32cbeq r0, r1, r2 + crc32bne r0, r1, r2 + crc32chcc r0, r1, r2 + crc32hpl r0, r1, r2 + crc32cwgt r0, r1, r2 + crc32wle r0, r1, r2 + +@ CHECK: error: instruction 'crc32cb' is not predicable, but condition code specified +@ CHECK: error: instruction 'crc32b' is not predicable, but condition code specified +@ CHECK: error: instruction 'crc32ch' is not predicable, but condition code specified +@ CHECK: error: instruction 'crc32h' is not predicable, but condition code specified +@ CHECK: error: instruction 'crc32cw' is not predicable, but condition code specified +@ CHECK: error: instruction 'crc32w' is not predicable, but condition code specified Index: test/MC/Disassembler/ARM/crc32-thumb.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/ARM/crc32-thumb.txt @@ -0,0 +1,15 @@ +# RUN: llvm-mc --disassemble %s -triple=thumbv8 2>&1 | FileCheck %s + +# CHECK: crc32b r0, r1, r2 +# CHECK: crc32h r0, r1, r2 +# CHECK: crc32w r0, r1, r2 +# CHECK: crc32cb r0, r1, r2 +# CHECK: crc32ch r0, r1, r2 +# CHECK: crc32cw r0, r1, r2 + +0xc1 0xfa 0x82 0xf0 +0xc1 0xfa 0x92 0xf0 +0xc1 0xfa 0xa2 0xf0 +0xd1 0xfa 0x82 0xf0 +0xd1 0xfa 0x92 0xf0 +0xd1 0xfa 0xa2 0xf0 Index: test/MC/Disassembler/ARM/crc32.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/ARM/crc32.txt @@ -0,0 +1,15 @@ +# RUN: llvm-mc --disassemble %s -triple=armv8 2>&1 | FileCheck %s + +# CHECK: crc32b r0, r1, r2 +# CHECK: crc32h r0, r1, r2 +# CHECK: crc32w r0, r1, r2 +# CHECK: crc32cb r0, r1, r2 +# CHECK: crc32ch r0, r1, r2 +# CHECK: crc32cw r0, r1, r2 + +0x42 0x00 0x01 0xe1 +0x42 0x00 0x21 0xe1 +0x42 0x00 0x41 0xe1 +0x42 0x02 0x01 0xe1 +0x42 0x02 0x21 0xe1 +0x42 0x02 0x41 0xe1