Add GHASH x86_64 assembler.
[openssl.git] / crypto / modes / asm / ghash-x86_64.pl
1 #!/usr/bin/env perl
2 #
3 # ====================================================================
4 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
5 # project. The module is, however, dual licensed under OpenSSL and
6 # CRYPTOGAMS licenses depending on where you obtain it. For further
7 # details see http://www.openssl.org/~appro/cryptogams/.
8 # ====================================================================
9 #
10 # The module implements "4-bit" Galois field multiplication and
11 # streamed GHASH function. "4-bit" means that it uses 256 bytes
12 # per-key table [+128 bytes fixed table]. Performance results are for
13 # streamed GHASH subroutine and are expressed in cycles per processed
14 # byte, less is better:
15 #
16 #               gcc 3.4.x       assembler
17 #
18 # Opteron       18.5            10.2            +80%
19 # Core2         26.0            16.4            +58%
20
21 $flavour = shift;
22 $output  = shift;
23 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
24
25 $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
26
27 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
28 ( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
29 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
30 die "can't locate x86_64-xlate.pl";
31
32 open STDOUT,"| $^X $xlate $flavour $output";
33
34 # common register layout
35 $nlo="%rax";
36 $nhi="%rbx";
37 $Zlo="%r8";
38 $Zhi="%r9";
39 $tmp="%r10";
40 $rem_4bit = "%r11";
41
42 # per-function register layout
43 $Xi="%rdi";
44 $Htbl="%rsi";
45
46 $cnt="%rcx";
47 $rem="%rdx";
48
49 sub lo() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/;
50                         $r =~ s/%[er]([sd]i)/%\1l/;
51                         $r =~ s/%(r[0-9]+)[d]?/%\1b/;   $r; }
52
53 { my $N;
54   sub loop() {
55   my $inp = shift;
56
57         $N++;
58 $code.=<<___;
59         xor     $nlo,$nlo
60         xor     $nhi,$nhi
61         mov     `&lo("$Zlo")`,`&lo("$nlo")`
62         mov     `&lo("$Zlo")`,`&lo("$nhi")`
63         shl     \$4,`&lo("$nlo")`
64         mov     \$14,$cnt
65         mov     8($Htbl,$nlo),$Zlo
66         mov     ($Htbl,$nlo),$Zhi
67         and     \$0xf0,`&lo("$nhi")`
68         mov     $Zlo,$rem
69         jmp     .Loop$N
70
71 .align  16
72 .Loop$N:
73         shr     \$4,$Zlo
74         and     \$0xf,$rem
75         mov     $Zhi,$tmp
76         mov     ($inp,$cnt),`&lo("$nlo")`
77         shr     \$4,$Zhi
78         xor     8($Htbl,$nhi),$Zlo
79         shl     \$60,$tmp
80         xor     ($Htbl,$nhi),$Zhi
81         mov     `&lo("$nlo")`,`&lo("$nhi")`
82         xor     ($rem_4bit,$rem,8),$Zhi
83         mov     $Zlo,$rem
84         shl     \$4,`&lo("$nlo")`
85         xor     $tmp,$Zlo
86         dec     $cnt
87         js      .Lbreak$N
88
89         shr     \$4,$Zlo
90         and     \$0xf,$rem
91         mov     $Zhi,$tmp
92         shr     \$4,$Zhi
93         xor     8($Htbl,$nlo),$Zlo
94         shl     \$60,$tmp
95         xor     ($Htbl,$nlo),$Zhi
96         and     \$0xf0,`&lo("$nhi")`
97         xor     ($rem_4bit,$rem,8),$Zhi
98         mov     $Zlo,$rem
99         xor     $tmp,$Zlo
100         jmp     .Loop$N
101
102 .align  16
103 .Lbreak$N:
104         shr     \$4,$Zlo
105         and     \$0xf,$rem
106         mov     $Zhi,$tmp
107         shr     \$4,$Zhi
108         xor     8($Htbl,$nlo),$Zlo
109         shl     \$60,$tmp
110         xor     ($Htbl,$nlo),$Zhi
111         and     \$0xf0,`&lo("$nhi")`
112         xor     ($rem_4bit,$rem,8),$Zhi
113         mov     $Zlo,$rem
114         xor     $tmp,$Zlo
115
116         shr     \$4,$Zlo
117         and     \$0xf,$rem
118         mov     $Zhi,$tmp
119         shr     \$4,$Zhi
120         xor     8($Htbl,$nhi),$Zlo
121         shl     \$60,$tmp
122         xor     ($Htbl,$nhi),$Zhi
123         xor     $tmp,$Zlo
124         xor     ($rem_4bit,$rem,8),$Zhi
125
126         bswap   $Zlo
127         bswap   $Zhi
128 ___
129 }}
130
131 $code=<<___;
132 .text
133
134 .globl  gcm_gmult_4bit
135 .type   gcm_gmult_4bit,\@function,2
136 .align  16
137 gcm_gmult_4bit:
138         push    %rbx
139         push    %rbp
140         push    %r12
141         sub     \$16,%rsp
142 .Lgmult_prologue:
143
144         movzb   15($Xi),$Zlo
145         lea     .Lrem_4bit(%rip),$rem_4bit
146 ___
147         &loop   ($Xi);
148 $code.=<<___;
149         mov     $Zlo,8($Xi)
150         mov     $Zhi,($Xi)
151
152         mov     32(%rsp),%rbx
153         lea     40(%rsp),%rsp
154 .Lgmult_epilogue:
155         ret
156 .size   gcm_gmult_4bit,.-gcm_gmult_4bit
157 ___
158
159
160 # per-function register layout
161 $inp="%rdi";
162 $len="%rsi";
163 $Xi="%rdx";
164 $Htbl="%rcx";
165
166 $cnt="%rbp";
167 $rem="%r12";
168
169 $code.=<<___;
170 .globl  gcm_ghash_4bit
171 .type   gcm_ghash_4bit,\@function,4
172 .align  16
173 gcm_ghash_4bit:
174         push    %rbx
175         push    %rbp
176         push    %r12
177         sub     \$16,%rsp
178 .Lghash_prologue:
179
180         mov     8($Xi),$Zlo
181         mov     ($Xi),$Zhi
182         add     $inp,$len
183         lea     .Lrem_4bit(%rip),$rem_4bit
184 .align  4
185 .Louter_loop:
186         xor     8($inp),$Zlo
187         xor     ($inp),$Zhi
188         lea     16($inp),$inp
189         mov     $Zlo,8(%rsp)
190         mov     $Zhi,(%rsp)
191         shr     \$56,$Zlo
192 ___
193         &loop   ("%rsp");
194 $code.=<<___;
195         cmp     $len,$inp
196         jb      .Louter_loop
197
198         mov     $Zlo,8($Xi)
199         mov     $Zhi,($Xi)
200
201         mov     16(%rsp),%r12
202         mov     24(%rsp),%rbp
203         mov     32(%rsp),%rbx
204         lea     40(%rsp),%rsp
205 .Lghash_epilogue:
206         ret
207 .size   gcm_ghash_4bit,.-gcm_ghash_4bit
208
209 .align  64
210 .type   rem_4bit,\@object
211 .Lrem_4bit:
212         .long   0,`0x0000<<16`,0,`0x1C20<<16`,0,`0x3840<<16`,0,`0x2460<<16`
213         .long   0,`0x7080<<16`,0,`0x6CA0<<16`,0,`0x48C0<<16`,0,`0x54E0<<16`
214         .long   0,`0xE100<<16`,0,`0xFD20<<16`,0,`0xD940<<16`,0,`0xC560<<16`
215         .long   0,`0x9180<<16`,0,`0x8DA0<<16`,0,`0xA9C0<<16`,0,`0xB5E0<<16`
216 .asciz  "GHASH for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
217 .align  64
218 ___
219
220 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
221 #               CONTEXT *context,DISPATCHER_CONTEXT *disp)
222 if ($win64) {
223 $rec="%rcx";
224 $frame="%rdx";
225 $context="%r8";
226 $disp="%r9";
227
228 $code.=<<___;
229 .extern __imp_RtlVirtualUnwind
230 .type   se_handler,\@abi-omnipotent
231 .align  16
232 se_handler:
233         push    %rsi
234         push    %rdi
235         push    %rbx
236         push    %rbp
237         push    %r12
238         push    %r13
239         push    %r14
240         push    %r15
241         pushfq
242         sub     \$64,%rsp
243
244         mov     120($context),%rax      # pull context->Rax
245         mov     248($context),%rbx      # pull context->Rip
246
247         mov     8($disp),%rsi           # disp->ImageBase
248         mov     56($disp),%r11          # disp->HandlerData
249
250         mov     0(%r11),%r10d           # HandlerData[0]
251         lea     (%rsi,%r10),%r10        # prologue label
252         cmp     %r10,%rbx               # context->Rip<prologue label
253         jb      .Lin_prologue
254
255         mov     152($context),%rax      # pull context->Rsp
256
257         mov     4(%r11),%r10d           # HandlerData[1]
258         lea     (%rsi,%r10),%r10        # epilogue label
259         cmp     %r10,%rbx               # context->Rip>=epilogue label
260         jae     .Lin_prologue
261
262         lea     40(%rax),%rax           # adjust "rsp"
263
264         mov     -8(%rax),%rbx
265         mov     -16(%rax),%rbp
266         mov     -24(%rax),%r12
267         mov     %rbx,144($context)      # restore context->Rbx
268         mov     %rbp,160($context)      # restore context->Rbp
269         mov     %r12,216($context)      # restore context->R12
270
271 .Lin_prologue:
272         mov     8(%rax),%rdi
273         mov     16(%rax),%rsi
274         mov     %rax,152($context)      # restore context->Rsp
275         mov     %rsi,168($context)      # restore context->Rsi
276         mov     %rdi,176($context)      # restore context->Rdi
277
278         mov     40($disp),%rdi          # disp->ContextRecord
279         mov     $context,%rsi           # context
280         mov     \$`1232/8`,%ecx         # sizeof(CONTEXT)
281         .long   0xa548f3fc              # cld; rep movsq
282
283         mov     $disp,%rsi
284         xor     %rcx,%rcx               # arg1, UNW_FLAG_NHANDLER
285         mov     8(%rsi),%rdx            # arg2, disp->ImageBase
286         mov     0(%rsi),%r8             # arg3, disp->ControlPc
287         mov     16(%rsi),%r9            # arg4, disp->FunctionEntry
288         mov     40(%rsi),%r10           # disp->ContextRecord
289         lea     56(%rsi),%r11           # &disp->HandlerData
290         lea     24(%rsi),%r12           # &disp->EstablisherFrame
291         mov     %r10,32(%rsp)           # arg5
292         mov     %r11,40(%rsp)           # arg6
293         mov     %r12,48(%rsp)           # arg7
294         mov     %rcx,56(%rsp)           # arg8, (NULL)
295         call    *__imp_RtlVirtualUnwind(%rip)
296
297         mov     \$1,%eax                # ExceptionContinueSearch
298         add     \$64,%rsp
299         popfq
300         pop     %r15
301         pop     %r14
302         pop     %r13
303         pop     %r12
304         pop     %rbp
305         pop     %rbx
306         pop     %rdi
307         pop     %rsi
308         ret
309 .size   se_handler,.-se_handler
310
311 .section        .pdata
312 .align  4
313         .rva    .LSEH_begin_gcm_gmult_4bit
314         .rva    .LSEH_end_gcm_gmult_4bit
315         .rva    .LSEH_info_gcm_gmult_4bit
316
317         .rva    .LSEH_begin_gcm_ghash_4bit
318         .rva    .LSEH_end_gcm_ghash_4bit
319         .rva    .LSEH_info_gcm_ghash_4bit
320
321 .section        .xdata
322 .align  8
323 .LSEH_info_gcm_gmult_4bit:
324         .byte   9,0,0,0
325         .rva    se_handler
326         .rva    .Lgmult_prologue,.Lgmult_epilogue       # HandlerData
327 .LSEH_info_gcm_ghash_4bit:
328         .byte   9,0,0,0
329         .rva    se_handler
330         .rva    .Lghash_prologue,.Lghash_epilogue       # HandlerData
331 ___
332 }
333 $code =~ s/\`([^\`]*)\`/eval($1)/gem;
334
335 print $code;
336
337 close STDOUT;