]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/perlasm/riscv.pm
riscv: Clarify dual-licensing wording for GCM and AES
[thirdparty/openssl.git] / crypto / perlasm / riscv.pm
CommitLineData
c8a641c3 1#! /usr/bin/env perl
3e76b388
HS
2# This file is dual-licensed, meaning that you can use it under your
3# choice of either of the following two licenses:
4#
c8a641c3
CM
5# Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
6#
3e76b388
HS
7# Licensed under the Apache License 2.0 (the "License"). You can obtain
8# a copy in the file LICENSE in the source distribution or at
c8a641c3 9# https://www.openssl.org/source/license.html
3e76b388
HS
10#
11# or
33523d6d
HS
12#
13# Copyright (c) 2023, Christoph Müllner <christoph.muellner@vrull.eu>
14# All rights reserved.
15#
16# Redistribution and use in source and binary forms, with or without
17# modification, are permitted provided that the following conditions
18# are met:
19# 1. Redistributions of source code must retain the above copyright
20# notice, this list of conditions and the following disclaimer.
21# 2. Redistributions in binary form must reproduce the above copyright
22# notice, this list of conditions and the following disclaimer in the
23# documentation and/or other materials provided with the distribution.
24#
25# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
c8a641c3
CM
37use strict;
38use warnings;
39
ac97cd60
CM
40# Set $have_stacktrace to 1 if we have Devel::StackTrace
41my $have_stacktrace = 0;
42if (eval {require Devel::StackTrace;1;}) {
43 $have_stacktrace = 1;
44}
45
c8a641c3 46my @regs = map("x$_",(0..31));
ac97cd60
CM
47# Mapping from the RISC-V psABI ABI mnemonic names to the register number.
48my @regaliases = ('zero','ra','sp','gp','tp','t0','t1','t2','s0','s1',
49 map("a$_",(0..7)),
50 map("s$_",(2..11)),
51 map("t$_",(3..6))
52);
53
c8a641c3
CM
54my %reglookup;
55@reglookup{@regs} = @regs;
ac97cd60 56@reglookup{@regaliases} = @regs;
c8a641c3
CM
57
58# Takes a register name, possibly an alias, and converts it to a register index
59# from 0 to 31
60sub read_reg {
61 my $reg = lc shift;
62 if (!exists($reglookup{$reg})) {
ac97cd60
CM
63 my $trace = "";
64 if ($have_stacktrace) {
65 $trace = Devel::StackTrace->new->as_string;
66 }
67 die("Unknown register ".$reg."\n".$trace);
c8a641c3
CM
68 }
69 my $regstr = $reglookup{$reg};
70 if (!($regstr =~ /^x([0-9]+)$/)) {
ac97cd60
CM
71 my $trace = "";
72 if ($have_stacktrace) {
73 $trace = Devel::StackTrace->new->as_string;
74 }
75 die("Could not process register ".$reg."\n".$trace);
c8a641c3
CM
76 }
77 return $1;
78}
79
b2468436
CM
80# Helper functions
81
82sub brev8_rv64i {
83 # brev8 without `brev8` instruction (only in Zbkb)
84 # Bit-reverses the first argument and needs two scratch registers
85 my $val = shift;
86 my $t0 = shift;
87 my $t1 = shift;
88 my $brev8_const = shift;
89 my $seq = <<___;
90 la $brev8_const, Lbrev8_const
91
92 ld $t0, 0($brev8_const) # 0xAAAAAAAAAAAAAAAA
93 slli $t1, $val, 1
94 and $t1, $t1, $t0
95 and $val, $val, $t0
96 srli $val, $val, 1
97 or $val, $t1, $val
98
99 ld $t0, 8($brev8_const) # 0xCCCCCCCCCCCCCCCC
100 slli $t1, $val, 2
101 and $t1, $t1, $t0
102 and $val, $val, $t0
103 srli $val, $val, 2
104 or $val, $t1, $val
105
106 ld $t0, 16($brev8_const) # 0xF0F0F0F0F0F0F0F0
107 slli $t1, $val, 4
108 and $t1, $t1, $t0
109 and $val, $val, $t0
110 srli $val, $val, 4
111 or $val, $t1, $val
112___
113 return $seq;
114}
115
116sub sd_rev8_rv64i {
117 # rev8 without `rev8` instruction (only in Zbb or Zbkb)
118 # Stores the given value byte-reversed and needs one scratch register
119 my $val = shift;
120 my $addr = shift;
121 my $off = shift;
122 my $tmp = shift;
123 my $off0 = ($off + 0);
124 my $off1 = ($off + 1);
125 my $off2 = ($off + 2);
126 my $off3 = ($off + 3);
127 my $off4 = ($off + 4);
128 my $off5 = ($off + 5);
129 my $off6 = ($off + 6);
130 my $off7 = ($off + 7);
131 my $seq = <<___;
132 sb $val, $off7($addr)
133 srli $tmp, $val, 8
134 sb $tmp, $off6($addr)
135 srli $tmp, $val, 16
136 sb $tmp, $off5($addr)
137 srli $tmp, $val, 24
138 sb $tmp, $off4($addr)
139 srli $tmp, $val, 32
140 sb $tmp, $off3($addr)
141 srli $tmp, $val, 40
142 sb $tmp, $off2($addr)
143 srli $tmp, $val, 48
144 sb $tmp, $off1($addr)
145 srli $tmp, $val, 56
146 sb $tmp, $off0($addr)
147___
148 return $seq;
149}
150
c8a641c3
CM
151# Scalar crypto instructions
152
153sub aes64ds {
154 # Encoding for aes64ds rd, rs1, rs2 instruction on RV64
155 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
156 my $template = 0b0011101_00000_00000_000_00000_0110011;
157 my $rd = read_reg shift;
158 my $rs1 = read_reg shift;
159 my $rs2 = read_reg shift;
160 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
161}
162
163sub aes64dsm {
164 # Encoding for aes64dsm rd, rs1, rs2 instruction on RV64
165 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
166 my $template = 0b0011111_00000_00000_000_00000_0110011;
167 my $rd = read_reg shift;
168 my $rs1 = read_reg shift;
169 my $rs2 = read_reg shift;
170 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
171}
172
173sub aes64es {
174 # Encoding for aes64es rd, rs1, rs2 instruction on RV64
175 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
176 my $template = 0b0011001_00000_00000_000_00000_0110011;
177 my $rd = read_reg shift;
178 my $rs1 = read_reg shift;
179 my $rs2 = read_reg shift;
180 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
181}
182
183sub aes64esm {
184 # Encoding for aes64esm rd, rs1, rs2 instruction on RV64
185 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
186 my $template = 0b0011011_00000_00000_000_00000_0110011;
187 my $rd = read_reg shift;
188 my $rs1 = read_reg shift;
189 my $rs2 = read_reg shift;
190 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
191}
192
193sub aes64im {
194 # Encoding for aes64im rd, rs1 instruction on RV64
195 # XXXXXXXXXXXX_ rs1 _XXX_ rd _XXXXXXX
196 my $template = 0b001100000000_00000_001_00000_0010011;
197 my $rd = read_reg shift;
198 my $rs1 = read_reg shift;
199 return ".word ".($template | ($rs1 << 15) | ($rd << 7));
200}
201
202sub aes64ks1i {
203 # Encoding for aes64ks1i rd, rs1, rnum instruction on RV64
204 # XXXXXXXX_rnum_ rs1 _XXX_ rd _XXXXXXX
205 my $template = 0b00110001_0000_00000_001_00000_0010011;
206 my $rd = read_reg shift;
207 my $rs1 = read_reg shift;
208 my $rnum = shift;
209 return ".word ".($template | ($rnum << 20) | ($rs1 << 15) | ($rd << 7));
210}
211
212sub aes64ks2 {
213 # Encoding for aes64ks2 rd, rs1, rs2 instruction on RV64
214 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
215 my $template = 0b0111111_00000_00000_000_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));
b2468436
CM
220}
221
222sub brev8 {
223 # brev8 rd, rs
224 my $template = 0b011010000111_00000_101_00000_0010011;
225 my $rd = read_reg shift;
226 my $rs = read_reg shift;
227 return ".word ".($template | ($rs << 15) | ($rd << 7));
c8a641c3
CM
228}
229
75623ed8
CM
230sub clmul {
231 # Encoding for clmul rd, rs1, rs2 instruction on RV64
232 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
233 my $template = 0b0000101_00000_00000_001_00000_0110011;
234 my $rd = read_reg shift;
235 my $rs1 = read_reg shift;
236 my $rs2 = read_reg shift;
237 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
238}
239
240sub clmulh {
241 # Encoding for clmulh rd, rs1, rs2 instruction on RV64
242 # XXXXXXX_ rs2 _ rs1 _XXX_ rd _XXXXXXX
243 my $template = 0b0000101_00000_00000_011_00000_0110011;
244 my $rd = read_reg shift;
245 my $rs1 = read_reg shift;
246 my $rs2 = read_reg shift;
247 return ".word ".($template | ($rs2 << 20) | ($rs1 << 15) | ($rd << 7));
248}
249
250sub rev8 {
251 # Encoding for rev8 rd, rs instruction on RV64
252 # XXXXXXXXXXXXX_ rs _XXX_ rd _XXXXXXX
253 my $template = 0b011010111000_00000_101_00000_0010011;
254 my $rd = read_reg shift;
255 my $rs = read_reg shift;
256 return ".word ".($template | ($rs << 15) | ($rd << 7));
257}
258
c8a641c3 2591;