]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/perlasm/riscv.pm
riscv: GCM: Simplify GCM calculation
[thirdparty/openssl.git] / crypto / perlasm / riscv.pm
CommitLineData
c8a641c3
CM
1#! /usr/bin/env perl
2# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
3#
4# Licensed under the Apache License 2.0 (the "License"). You may not use
5# this file except in compliance with the License. You can obtain a copy
6# in the file LICENSE in the source distribution or at
7# https://www.openssl.org/source/license.html
8
9use strict;
10use warnings;
11
ac97cd60
CM
12# Set $have_stacktrace to 1 if we have Devel::StackTrace
13my $have_stacktrace = 0;
14if (eval {require Devel::StackTrace;1;}) {
15 $have_stacktrace = 1;
16}
17
c8a641c3 18my @regs = map("x$_",(0..31));
ac97cd60
CM
19# Mapping from the RISC-V psABI ABI mnemonic names to the register number.
20my @regaliases = ('zero','ra','sp','gp','tp','t0','t1','t2','s0','s1',
21 map("a$_",(0..7)),
22 map("s$_",(2..11)),
23 map("t$_",(3..6))
24);
25
c8a641c3
CM
26my %reglookup;
27@reglookup{@regs} = @regs;
ac97cd60 28@reglookup{@regaliases} = @regs;
c8a641c3
CM
29
30# Takes a register name, possibly an alias, and converts it to a register index
31# from 0 to 31
32sub read_reg {
33 my $reg = lc shift;
34 if (!exists($reglookup{$reg})) {
ac97cd60
CM
35 my $trace = "";
36 if ($have_stacktrace) {
37 $trace = Devel::StackTrace->new->as_string;
38 }
39 die("Unknown register ".$reg."\n".$trace);
c8a641c3
CM
40 }
41 my $regstr = $reglookup{$reg};
42 if (!($regstr =~ /^x([0-9]+)$/)) {
ac97cd60
CM
43 my $trace = "";
44 if ($have_stacktrace) {
45 $trace = Devel::StackTrace->new->as_string;
46 }
47 die("Could not process register ".$reg."\n".$trace);
c8a641c3
CM
48 }
49 return $1;
50}
51
b2468436
CM
52# Helper functions
53
54sub brev8_rv64i {
55 # brev8 without `brev8` instruction (only in Zbkb)
56 # Bit-reverses the first argument and needs two scratch registers
57 my $val = shift;
58 my $t0 = shift;
59 my $t1 = shift;
60 my $brev8_const = shift;
61 my $seq = <<___;
62 la $brev8_const, Lbrev8_const
63
64 ld $t0, 0($brev8_const) # 0xAAAAAAAAAAAAAAAA
65 slli $t1, $val, 1
66 and $t1, $t1, $t0
67 and $val, $val, $t0
68 srli $val, $val, 1
69 or $val, $t1, $val
70
71 ld $t0, 8($brev8_const) # 0xCCCCCCCCCCCCCCCC
72 slli $t1, $val, 2
73 and $t1, $t1, $t0
74 and $val, $val, $t0
75 srli $val, $val, 2
76 or $val, $t1, $val
77
78 ld $t0, 16($brev8_const) # 0xF0F0F0F0F0F0F0F0
79 slli $t1, $val, 4
80 and $t1, $t1, $t0
81 and $val, $val, $t0
82 srli $val, $val, 4
83 or $val, $t1, $val
84___
85 return $seq;
86}
87
88sub sd_rev8_rv64i {
89 # rev8 without `rev8` instruction (only in Zbb or Zbkb)
90 # Stores the given value byte-reversed and needs one scratch register
91 my $val = shift;
92 my $addr = shift;
93 my $off = shift;
94 my $tmp = shift;
95 my $off0 = ($off + 0);
96 my $off1 = ($off + 1);
97 my $off2 = ($off + 2);
98 my $off3 = ($off + 3);
99 my $off4 = ($off + 4);
100 my $off5 = ($off + 5);
101 my $off6 = ($off + 6);
102 my $off7 = ($off + 7);
103 my $seq = <<___;
104 sb $val, $off7($addr)
105 srli $tmp, $val, 8
106 sb $tmp, $off6($addr)
107 srli $tmp, $val, 16
108 sb $tmp, $off5($addr)
109 srli $tmp, $val, 24
110 sb $tmp, $off4($addr)
111 srli $tmp, $val, 32
112 sb $tmp, $off3($addr)
113 srli $tmp, $val, 40
114 sb $tmp, $off2($addr)
115 srli $tmp, $val, 48
116 sb $tmp, $off1($addr)
117 srli $tmp, $val, 56
118 sb $tmp, $off0($addr)
119___
120 return $seq;
121}
122
c8a641c3
CM
123# Scalar crypto instructions
124
125sub aes64ds {
126 # Encoding for aes64ds rd, rs1, rs2 instruction on RV64
127 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
128 my $template = 0b0011101_00000_00000_000_00000_0110011;
129 my $rd = read_reg shift;
130 my $rs1 = read_reg shift;
131 my $rs2 = read_reg shift;
132 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
133}
134
135sub aes64dsm {
136 # Encoding for aes64dsm rd, rs1, rs2 instruction on RV64
137 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
138 my $template = 0b0011111_00000_00000_000_00000_0110011;
139 my $rd = read_reg shift;
140 my $rs1 = read_reg shift;
141 my $rs2 = read_reg shift;
142 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
143}
144
145sub aes64es {
146 # Encoding for aes64es rd, rs1, rs2 instruction on RV64
147 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
148 my $template = 0b0011001_00000_00000_000_00000_0110011;
149 my $rd = read_reg shift;
150 my $rs1 = read_reg shift;
151 my $rs2 = read_reg shift;
152 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
153}
154
155sub aes64esm {
156 # Encoding for aes64esm rd, rs1, rs2 instruction on RV64
157 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
158 my $template = 0b0011011_00000_00000_000_00000_0110011;
159 my $rd = read_reg shift;
160 my $rs1 = read_reg shift;
161 my $rs2 = read_reg shift;
162 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
163}
164
165sub aes64im {
166 # Encoding for aes64im rd, rs1 instruction on RV64
167 # XXXXXXXXXXXX_ rs1 _XXX_ rd _XXXXXXX
168 my $template = 0b001100000000_00000_001_00000_0010011;
169 my $rd = read_reg shift;
170 my $rs1 = read_reg shift;
171 return ".word ".($template | ($rs1 << 15) | ($rd << 7));
172}
173
174sub aes64ks1i {
175 # Encoding for aes64ks1i rd, rs1, rnum instruction on RV64
176 # XXXXXXXX_rnum_ rs1 _XXX_ rd _XXXXXXX
177 my $template = 0b00110001_0000_00000_001_00000_0010011;
178 my $rd = read_reg shift;
179 my $rs1 = read_reg shift;
180 my $rnum = shift;
181 return ".word ".($template | ($rnum << 20) | ($rs1 << 15) | ($rd << 7));
182}
183
184sub aes64ks2 {
185 # Encoding for aes64ks2 rd, rs1, rs2 instruction on RV64
186 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
187 my $template = 0b0111111_00000_00000_000_00000_0110011;
188 my $rd = read_reg shift;
189 my $rs1 = read_reg shift;
190 my $rs2 = read_reg shift;
191 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
b2468436
CM
192}
193
194sub brev8 {
195 # brev8 rd, rs
196 my $template = 0b011010000111_00000_101_00000_0010011;
197 my $rd = read_reg shift;
198 my $rs = read_reg shift;
199 return ".word ".($template | ($rs << 15) | ($rd << 7));
c8a641c3
CM
200}
201
75623ed8
CM
202sub clmul {
203 # Encoding for clmul rd, rs1, rs2 instruction on RV64
204 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
205 my $template = 0b0000101_00000_00000_001_00000_0110011;
206 my $rd = read_reg shift;
207 my $rs1 = read_reg shift;
208 my $rs2 = read_reg shift;
209 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
210}
211
212sub clmulh {
213 # Encoding for clmulh rd, rs1, rs2 instruction on RV64
214 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
215 my $template = 0b0000101_00000_00000_011_00000_0110011;
216 my $rd = read_reg shift;
217 my $rs1 = read_reg shift;
218 my $rs2 = read_reg shift;
219 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
220}
221
222sub rev8 {
223 # Encoding for rev8 rd, rs instruction on RV64
224 # XXXXXXXXXXXXX_ rs _XXX_ rd _XXXXXXX
225 my $template = 0b011010111000_00000_101_00000_0010011;
226 my $rd = read_reg shift;
227 my $rs = read_reg shift;
228 return ".word ".($template | ($rs << 15) | ($rd << 7));
229}
230
c8a641c3 2311;