(define_insn "clmul<mode>3"
[(set (match_operand:X 0 "register_operand" "=r")
(clmul:X (match_operand:X 1 "register_operand" "r")
-(match_operand:X 2 "arith_operand" "r")))]
+(match_operand:X 2 "register_operand" "r")))]
"TARGET_ZBC"
"clmul\t%0,%1,%2"
[(set_attr "type" "bitmanip")])
(define_insn "clmulh<mode>3"
[(set (match_operand:X 0 "register_operand" "=r")
(plus:X (match_operand:X 1 "register_operand" " r")
-(match_operand:X 2 "arith_operand" " r")))]
+(match_operand:X 2 "register_operand" "r")))]
"TARGET_ZBC"
"clmulh\t%0,%1,%2"
[(set_attr "type" "bitmanip")])
(define_insn "clmulr<mode>3"
[(set (match_operand:X 0 "register_operand" "=r")
(clmulr:X (match_operand:X 1 "register_operand" "r")
-(match_operand:X 2 "arith_operand" "r")))]
+(match_operand:X 2 "register_operand" "r")))]
"TARGET_ZBC"
"clmulr\t%0,%1,%2"
[(set_attr "type" "bitmanip")])
if (TARGET_ZBC)
{
// Instruction sequence from slides. Sizes need to be fixed.
- rtx a0 = operands[0], a1 = operands[1];
+ rtx a0 = operands[1], a1 = operands[2];
unsigned HOST_WIDE_INT
q = gf2n_poly_long_div_quotient (UINTVAL (operands[3]));
rtx t0 = gen_rtx_CONST (SImode, GEN_INT (q));
return quotient;
}
+/* Calculates reciprocal CRC for initial CRC and given polynomial. */
+static uint16_t
+generate_crc_reciprocal (uint16_t crc,
+ uint16_t polynomial)
+{
+ for (int bits = 16; bits > 0; --bits)
+ {
+ int tmp = crc & 1;
+ crc >>= 1;
+ if (tmp)
+ crc ^= polynomial;
+ }
+ return crc;
+}
+
/* Calculates CRC for initial CRC and given polynomial. */
static uint16_t
generate_crc (uint16_t crc,
- uint16_t polynomial)
+ uint16_t polynomial)
{
for (int bits = 16; bits > 0; --bits)
{
if (crc & 0x8000)
- {
- crc = (crc << 1) ^ polynomial;
- }
+ crc = (crc << 1) ^ polynomial;
else
- {
- crc <<= 1;
- }
+ crc <<= 1;
}
return crc;
return lab;
}
+void reflect (rtx op1, machine_mode mode)
+{
+ // Reflect the bits
+ op1 = gen_rtx_BSWAP (mode, op1);
+
+// Adjust the position of the reflected bits
+ if (mode != Pmode)
+ op1 = gen_rtx_SUBREG (Pmode, op1, 0);
+
+// Shift the reflected bits to the least significant end
+ rtx shift_amt = gen_rtx_CONST_INT (Pmode, 8);
+ op1 = gen_rtx_LSHIFTRT (Pmode, op1, shift_amt);
+}
+
/* Generate table based CRC code. */
void
-expand_crc_table_based (rtx *operands, machine_mode data_mode)
+expand_crc_table_based_reflected (rtx *operands, machine_mode data_mode)
{
machine_mode mode = GET_MODE (operands[0]);
-
rtx in = force_reg (mode, gen_rtx_XOR (mode, operands[1], operands[2]));
rtx ix = gen_rtx_AND (mode, in, GEN_INT (GET_MODE_MASK (data_mode)));
if (mode != Pmode)
riscv_emit_move (operands[0], gen_rtx_SUBREG (mode, crc, 0));
}
+/* Generate table based CRC code. */
+void
+expand_crc_table_based (rtx *operands, machine_mode data_mode)
+{
+ machine_mode mode = GET_MODE (operands[0]);
+ rtx op1 = gen_rtx_ASHIFTRT (mode, operands[1],
+ GEN_INT (8));
+ rtx in = force_reg (mode, gen_rtx_XOR (mode, op1, operands[2]));
+ rtx ix = gen_rtx_AND (mode, in, GEN_INT (GET_MODE_MASK (data_mode)));
+ if (mode != Pmode)
+ ix = gen_rtx_SUBREG (Pmode, ix, 0);
+ ix = gen_rtx_ASHIFT (Pmode, ix, GEN_INT (exact_log2 (GET_MODE_SIZE (mode)
+ .to_constant ())));
+ ix = force_reg (Pmode, ix);
+ rtx tab = generate_crc16_table (UINTVAL (operands[3]));
+ tab = gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode, ix, tab));
+
+ rtx high = gen_rtx_ASHIFT (mode, operands[1],
+ GEN_INT (8));
+ high = force_reg (mode, gen_rtx_AND (mode, high, GEN_INT (65535)));
+ rtx crc = force_reg (mode, gen_rtx_XOR (mode, tab, high));
+ riscv_emit_move (operands[0], crc);
+}
+
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-crc-details" } */
+#include <stdio.h>
+unsigned short crc16(unsigned char newByte, unsigned short crcValue) {
+ unsigned char i;
+
+ for (i = 0; i < 8; i++) {
+
+ if (((crcValue & 0x8000) >> 8) ^ (newByte & 0x80)) {
+ crcValue = (crcValue << 1) ^ 0x102;
+ } else {
+ crcValue = (crcValue << 1);
+ }
+
+ newByte <<= 1;
+ }
+
+ return crcValue;
+}
+
+int main ()
+{
+ unsigned short crc = 0;
+
+ crc = crc16(0x12, crc);
+ printf("%04X\n", crc); // 1224
+
+ crc = crc16(0x34, crc);
+ printf("%04X\n", crc); // 024C
+
+ crc = crc16(0x35, crc);
+ printf("%04X\n", crc); // 7B6E
+
+}
+
+/* { dg-final { scan-tree-dump "crc16 function maybe calculates CRC and returns it." "crc"} } */
+/* { dg-final { scan-tree-dump "Return size is 16" "crc"} } */
+/* { dg-final { scan-tree-dump "Loop iteration number is 7" "crc"} } */
+/* { dg-final { scan-tree-dump "Bit forward" "crc"} } */
+/* { dg-final { scan-tree-dump "crc16 function calculates CRC!" "crc"} } */