;; Machine description for RISC-V Scalar Cryptography extensions. ;; Copyright (C) 2023-2024 Free Software Foundation, Inc. ;; This file is part of GCC. ;; GCC is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; GCC is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GCC; see the file COPYING3. If not see ;; . (define_c_enum "unspec" [ ;; Zbkb unspecs UNSPEC_BREV8 UNSPEC_ZIP UNSPEC_UNZIP UNSPEC_PACK UNSPEC_PACKH UNSPEC_PACKW ;; Zbkx unspecs UNSPEC_XPERM8 UNSPEC_XPERM4 ;; Zknd unspecs UNSPEC_AES_DSI UNSPEC_AES_DSMI UNSPEC_AES_DS UNSPEC_AES_DSM UNSPEC_AES_IM UNSPEC_AES_KS1I UNSPEC_AES_KS2 ;; Zkne unspecs UNSPEC_AES_ES UNSPEC_AES_ESM UNSPEC_AES_ESI UNSPEC_AES_ESMI ;; Zknh unspecs UNSPEC_SHA_256_SIG0 UNSPEC_SHA_256_SIG1 UNSPEC_SHA_256_SUM0 UNSPEC_SHA_256_SUM1 UNSPEC_SHA_512_SIG0 UNSPEC_SHA_512_SIG0H UNSPEC_SHA_512_SIG0L UNSPEC_SHA_512_SIG1 UNSPEC_SHA_512_SIG1H UNSPEC_SHA_512_SIG1L UNSPEC_SHA_512_SUM0 UNSPEC_SHA_512_SUM0R UNSPEC_SHA_512_SUM1 UNSPEC_SHA_512_SUM1R ;; Zksh unspecs UNSPEC_SM3_P0 UNSPEC_SM3_P1 ;; Zksed unspecs UNSPEC_SM4_ED UNSPEC_SM4_KS ]) ;; ZBKB extension (define_insn "riscv_brev8_" [(set (match_operand:GPR 0 "register_operand" "=r") (unspec:GPR [(match_operand:GPR 1 "register_operand" "r")] UNSPEC_BREV8))] "TARGET_ZBKB" "brev8\t%0,%1" [(set_attr "type" "crypto")]) (define_insn "riscv_zip" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_ZIP))] "TARGET_ZBKB && !TARGET_64BIT" "zip\t%0,%1" [(set_attr "type" "crypto")]) (define_insn "riscv_unzip" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_UNZIP))] "TARGET_ZBKB && !TARGET_64BIT" "unzip\t%0,%1" [(set_attr "type" "crypto")]) (define_insn "riscv_pack_" [(set (match_operand:X 0 "register_operand" "=r") (unspec:X [(match_operand:HISI 1 "register_operand" "r") (match_operand:HISI 2 "register_operand" "r")] UNSPEC_PACK))] "TARGET_ZBKB" "pack\t%0,%1,%2" [(set_attr "type" "crypto")]) ;; This is slightly more complex than the other pack patterns ;; that fully expose the RTL as it needs to self-adjust to ;; rv32 and rv64. But it's not that hard. (define_insn "riscv_xpack___2" [(set (match_operand:X 0 "register_operand" "=r") (ior:X (ashift:X (match_operand:X 1 "register_operand" "r") (match_operand 2 "immediate_operand" "n")) (zero_extend:X (match_operand:HX 3 "register_operand" "r"))))] "TARGET_ZBKB && INTVAL (operands[2]) == BITS_PER_WORD / 2" "pack\t%0,%3,%1" [(set_attr "type" "crypto")]) (define_insn "riscv_packh_" [(set (match_operand:X 0 "register_operand" "=r") (unspec:X [(match_operand:QI 1 "register_operand" "r") (match_operand:QI 2 "register_operand" "r")] UNSPEC_PACKH))] "TARGET_ZBKB" "packh\t%0,%1,%2" [(set_attr "type" "crypto")]) ;; So this is both a useful pattern unto itself and a bridge to the ;; general packh pattern below. (define_insn "*riscv_packh__2" [(set (match_operand:X 0 "register_operand" "=r") (and:X (ashift:X (match_operand:X 1 "register_operand" "r") (const_int 8)) (const_int 65280)))] "TARGET_ZBKB" "packh\t%0,x0,%1" [(set_attr "type" "crypto")]) ;; While the two operands of the IOR could be swapped, this appears ;; to be the canonical form. The other form doesn't seem to trigger. (define_insn "*riscv_packh__3" [(set (match_operand:X 0 "register_operand" "=r") (ior:X (and:X (ashift:X (match_operand:X 1 "register_operand" "r") (const_int 8)) (const_int 65280)) (zero_extend:X (match_operand:QI 2 "register_operand" "r"))))] "TARGET_ZBKB" "packh\t%0,%2,%1" [(set_attr "type" "crypto")]) (define_insn "riscv_packw" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:HI 1 "register_operand" "r") (match_operand:HI 2 "register_operand" "r")] UNSPEC_PACKW))] "TARGET_ZBKB && TARGET_64BIT" "packw\t%0,%1,%2" [(set_attr "type" "crypto")]) ;; Implemented as a splitter for initial recognition. It generates ;; new RTL with the extension moved to the outer position. This ;; allows later code to eliminate subsequent explicit sign extensions. (define_split [(set (match_operand:DI 0 "register_operand") (ior:DI (ashift:DI (sign_extend:DI (match_operand:HI 1 "register_operand")) (const_int 16)) (zero_extend:DI (match_operand:HI 2 "register_operand"))))] "TARGET_ZBKB && TARGET_64BIT" [(set (match_dup 0) (sign_extend:DI (ior:SI (ashift:SI (match_dup 1) (const_int 16)) (zero_extend:SI (match_dup 2)))))] "operands[1] = gen_lowpart (SImode, operands[1]);") ;; And this patches the result of the splitter above. (define_insn "*riscv_packw_2" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") (const_int 16)) (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))))] "TARGET_ZBKB && TARGET_64BIT" "packw\t%0,%2,%1" [(set_attr "type" "crypto")]) ;; ZBKX extension (define_insn "riscv_xperm4_" [(set (match_operand:X 0 "register_operand" "=r") (unspec:X [(match_operand:X 1 "register_operand" "r") (match_operand:X 2 "register_operand" "r")] UNSPEC_XPERM4))] "TARGET_ZBKX" "xperm4\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_xperm8_" [(set (match_operand:X 0 "register_operand" "=r") (unspec:X [(match_operand:X 1 "register_operand" "r") (match_operand:X 2 "register_operand" "r")] UNSPEC_XPERM8))] "TARGET_ZBKX" "xperm8\t%0,%1,%2" [(set_attr "type" "crypto")]) ;; ZKND extension (define_insn "riscv_aes32dsi" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "const_0_3_operand" "")] UNSPEC_AES_DSI))] "TARGET_ZKND && !TARGET_64BIT" "aes32dsi\t%0,%1,%2,%3" [(set_attr "type" "crypto")]) (define_insn "riscv_aes32dsmi" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "const_0_3_operand" "")] UNSPEC_AES_DSMI))] "TARGET_ZKND && !TARGET_64BIT" "aes32dsmi\t%0,%1,%2,%3" [(set_attr "type" "crypto")]) (define_insn "riscv_aes64ds" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r")] UNSPEC_AES_DS))] "TARGET_ZKND && TARGET_64BIT" "aes64ds\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_aes64dsm" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r")] UNSPEC_AES_DSM))] "TARGET_ZKND && TARGET_64BIT" "aes64dsm\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_aes64im" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_AES_IM))] "TARGET_ZKND && TARGET_64BIT" "aes64im\t%0,%1" [(set_attr "type" "crypto")]) (define_insn "riscv_aes64ks1i" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r") (match_operand:SI 2 "const_0_10_operand" "")] UNSPEC_AES_KS1I))] "(TARGET_ZKND || TARGET_ZKNE) && TARGET_64BIT" "aes64ks1i\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_aes64ks2" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r")] UNSPEC_AES_KS2))] "(TARGET_ZKND || TARGET_ZKNE) && TARGET_64BIT" "aes64ks2\t%0,%1,%2" [(set_attr "type" "crypto")]) ;; ZKNE extension (define_insn "riscv_aes32esi" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "const_0_3_operand" "")] UNSPEC_AES_ESI))] "TARGET_ZKNE && !TARGET_64BIT" "aes32esi\t%0,%1,%2,%3" [(set_attr "type" "crypto")]) (define_insn "riscv_aes32esmi" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "const_0_3_operand" "")] UNSPEC_AES_ESMI))] "TARGET_ZKNE && !TARGET_64BIT" "aes32esmi\t%0,%1,%2,%3" [(set_attr "type" "crypto")]) (define_insn "riscv_aes64es" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r")] UNSPEC_AES_ES))] "TARGET_ZKNE && TARGET_64BIT" "aes64es\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_aes64esm" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r")] UNSPEC_AES_ESM))] "TARGET_ZKNE && TARGET_64BIT" "aes64esm\t%0,%1,%2" [(set_attr "type" "crypto")]) ;; ZKNH - SHA256 (define_int_iterator SHA256_OP [ UNSPEC_SHA_256_SIG0 UNSPEC_SHA_256_SIG1 UNSPEC_SHA_256_SUM0 UNSPEC_SHA_256_SUM1]) (define_int_attr sha256_op [ (UNSPEC_SHA_256_SIG0 "sha256sig0") (UNSPEC_SHA_256_SIG1 "sha256sig1") (UNSPEC_SHA_256_SUM0 "sha256sum0") (UNSPEC_SHA_256_SUM1 "sha256sum1")]) (define_insn "*riscv__si" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r")] SHA256_OP))] "TARGET_ZKNH && !TARGET_64BIT" "\t%0,%1" [(set_attr "type" "crypto")]) (define_insn "riscv__di_extended" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (unspec:SI [(match_operand:SI 1 "register_operand" "r")] SHA256_OP)))] "TARGET_ZKNH && TARGET_64BIT" "\t%0,%1" [(set_attr "type" "crypto")]) (define_expand "riscv__si" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r")] SHA256_OP))] "TARGET_ZKNH" { if (TARGET_64BIT) { rtx t = gen_reg_rtx (DImode); emit_insn (gen_riscv__di_extended (t, operands[1])); t = gen_lowpart (SImode, t); SUBREG_PROMOTED_VAR_P (t) = 1; SUBREG_PROMOTED_SET (t, SRP_SIGNED); emit_move_insn (operands[0], t); DONE; } } [(set_attr "type" "crypto")]) ;; ZKNH - SHA512 (define_insn "riscv_sha512sig0h" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r")] UNSPEC_SHA_512_SIG0H))] "TARGET_ZKNH && !TARGET_64BIT" "sha512sig0h\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_sha512sig0l" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r")] UNSPEC_SHA_512_SIG0L))] "TARGET_ZKNH && !TARGET_64BIT" "sha512sig0l\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_sha512sig1h" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r")] UNSPEC_SHA_512_SIG1H))] "TARGET_ZKNH && !TARGET_64BIT" "sha512sig1h\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_sha512sig1l" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r")] UNSPEC_SHA_512_SIG1L))] "TARGET_ZKNH && !TARGET_64BIT" "sha512sig1l\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_sha512sum0r" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r")] UNSPEC_SHA_512_SUM0R))] "TARGET_ZKNH && !TARGET_64BIT" "sha512sum0r\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_sha512sum1r" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r")] UNSPEC_SHA_512_SUM1R))] "TARGET_ZKNH && !TARGET_64BIT" "sha512sum1r\t%0,%1,%2" [(set_attr "type" "crypto")]) (define_insn "riscv_sha512sig0" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_SHA_512_SIG0))] "TARGET_ZKNH && TARGET_64BIT" "sha512sig0\t%0,%1" [(set_attr "type" "crypto")]) (define_insn "riscv_sha512sig1" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_SHA_512_SIG1))] "TARGET_ZKNH && TARGET_64BIT" "sha512sig1\t%0,%1" [(set_attr "type" "crypto")]) (define_insn "riscv_sha512sum0" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_SHA_512_SUM0))] "TARGET_ZKNH && TARGET_64BIT" "sha512sum0\t%0,%1" [(set_attr "type" "crypto")]) (define_insn "riscv_sha512sum1" [(set (match_operand:DI 0 "register_operand" "=r") (unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_SHA_512_SUM1))] "TARGET_ZKNH && TARGET_64BIT" "sha512sum1\t%0,%1" [(set_attr "type" "crypto")]) ;; ZKSH (define_int_iterator SM3_OP [UNSPEC_SM3_P0 UNSPEC_SM3_P1]) (define_int_attr sm3_op [(UNSPEC_SM3_P0 "sm3p0") (UNSPEC_SM3_P1 "sm3p1")]) (define_insn "*riscv__si" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r")] SM3_OP))] "TARGET_ZKSH && !TARGET_64BIT" "\t%0,%1" [(set_attr "type" "crypto")]) (define_insn "riscv__di_extended" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (unspec:SI [(match_operand:SI 1 "register_operand" "r")] SM3_OP)))] "TARGET_ZKSH && TARGET_64BIT" "\t%0,%1" [(set_attr "type" "crypto")]) (define_expand "riscv__si" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r")] SM3_OP))] "TARGET_ZKSH" { if (TARGET_64BIT) { rtx t = gen_reg_rtx (DImode); emit_insn (gen_riscv__di_extended (t, operands[1])); t = gen_lowpart (SImode, t); SUBREG_PROMOTED_VAR_P (t) = 1; SUBREG_PROMOTED_SET (t, SRP_SIGNED); emit_move_insn (operands[0], t); DONE; } } [(set_attr "type" "crypto")]) ;; ZKSED (define_int_iterator SM4_OP [UNSPEC_SM4_ED UNSPEC_SM4_KS]) (define_int_attr sm4_op [(UNSPEC_SM4_ED "sm4ed") (UNSPEC_SM4_KS "sm4ks")]) (define_insn "*riscv__si" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "const_0_3_operand" "")] SM4_OP))] "TARGET_ZKSED && !TARGET_64BIT" "\t%0,%1,%2,%3" [(set_attr "type" "crypto")]) (define_insn "riscv__di_extended" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "const_0_3_operand" "")] SM4_OP)))] "TARGET_ZKSED && TARGET_64BIT" "\t%0,%1,%2,%3" [(set_attr "type" "crypto")]) (define_expand "riscv__si" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "const_0_3_operand" "")] SM4_OP))] "TARGET_ZKSED" { if (TARGET_64BIT) { rtx t = gen_reg_rtx (DImode); emit_insn (gen_riscv__di_extended (t, operands[1], operands[2], operands[3])); t = gen_lowpart (SImode, t); SUBREG_PROMOTED_VAR_P (t) = 1; SUBREG_PROMOTED_SET (t, SRP_SIGNED); emit_move_insn (operands[0], t); DONE; } } [(set_attr "type" "crypto")])