| package PQCodePackage; | |
| use strict; | |
| use warnings; | |
| # Function to adapt assembly code from pq-code-package to BoringSSL usage. | |
| # Should be kept as simple as possible, and maybe even become an identity | |
| # function to just mark the origin of an assembly string. | |
| sub asm { | |
| my ($asm) = @_; | |
| # BoringSSL does not promise alignment for the key data. | |
| $asm =~ s/\bvmovdqa\b/vmovdqu/g; | |
| return $asm; | |
| } | |
| # TODO(crbug.com/33072965): Replace by a common approach. | |
| # | |
| # Adapter to use pq-code-package asm functions (which are red zone less SysV | |
| # ABI) from BoringSSL. | |
| # | |
| # Handles register saving and argument remapping. | |
| # | |
| # Function must not call any non-SysV-ABI functions, and if it calls any | |
| # SysV-ABI functions, $num_xmms must include the xmm registers they clobber | |
| # too. | |
| # | |
| # Arguments: | |
| # $win64: Whether compiling for Windows. | |
| # $num_xmms: Number of xmm registers starting with xmm6 that get clobbered. | |
| # $num_args: Number of arguments the function takes (at most 4). | |
| sub abi_enter { | |
| my ($win64, $num_xmms, $num_args) = @_; | |
| my $out = ""; | |
| if ($win64) { | |
| $out .= " .seh_startproc\n"; | |
| # Stack layout: xmm6@rsp xmm7 xmm8 ... rdi rsi padding returnaddress. | |
| # Padding needed to align the xmm registers to 16 bytes boundaries. | |
| my $stack_alloc = 16 + $num_xmms * 16 + 8; | |
| $out .= " subq\t\$$stack_alloc, %rsp\n"; | |
| $out .= " .seh_stackalloc\t$stack_alloc\n"; | |
| my $rdi_off = $num_xmms * 16; | |
| my $rsi_off = $rdi_off + 8; | |
| $out .= " movq\t%rdi, $rdi_off(%rsp)\n"; | |
| $out .= " .seh_savereg\t%rdi, $rdi_off\n"; | |
| $out .= " movq\t%rsi, $rsi_off(%rsp)\n"; | |
| $out .= " .seh_savereg\t%rsi, $rsi_off\n"; | |
| for (my $i = 0; $i < $num_xmms; $i++) { | |
| my $reg = 6 + $i; | |
| my $off = $i * 16; | |
| $out .= " vmovdqa\t%xmm$reg, $off(%rsp)\n"; | |
| $out .= " .seh_savexmm\t%xmm$reg, $off\n"; | |
| } | |
| $out .= " .seh_endprologue\n"; | |
| # Map arguments. Funny ordering to spread out data dependencies. | |
| $out .= " movq\t%rdx, %rsi\n" | |
| if $num_args >= 2; | |
| $out .= " movq\t%rcx, %rdi\n" | |
| if $num_args >= 1; | |
| $out .= " movq\t%r8, %rdx\n" | |
| if $num_args >= 3; | |
| $out .= " movq\t%r9, %rcx\n" | |
| if $num_args >= 4; | |
| die "abi_enter with invalid argument count: got $num_args, want <= 4" | |
| if $num_args > 4; | |
| } | |
| return $out; | |
| } | |
| # TODO(crbug.com/33072965): Replace by a common approach. | |
| # | |
| # Adapter to use pq-code-package asm functions (which are red zone less SysV | |
| # ABI) from BoringSSL. | |
| # | |
| # Handles register restoring and AVX2 zeroing. | |
| # | |
| # Arguments: | |
| # $win64: Whether compiling for Windows. | |
| # $num_xmms: Number of xmm registers starting with xmm6 that get clobbered. | |
| # Must match the argument to `abi_enter`. | |
| sub abi_exit { | |
| my ($win64, $num_xmms) = @_; | |
| my $out = ""; | |
| $out .= " vzeroupper\n"; | |
| if ($win64) { | |
| my $stack_alloc = 16 + $num_xmms * 16 + 8; | |
| for (my $i = 0; $i < $num_xmms; $i++) { | |
| my $reg = 6 + $i; | |
| my $off = $i * 16; | |
| $out .= " vmovdqa\t$off(%rsp), %xmm$reg\n"; | |
| } | |
| my $rdi_off = $num_xmms * 16; | |
| my $rsi_off = $rdi_off + 8; | |
| $out .= " movq\t$rdi_off(%rsp), %rdi\n"; | |
| $out .= " movq\t$rsi_off(%rsp), %rsi\n"; | |
| $out .= " addq\t\$$stack_alloc, %rsp\n"; | |
| } | |
| $out .= " ret\n"; | |
| if ($win64) { | |
| $out .= " .seh_endproc\n"; | |
| } | |
| return $out; | |
| } | |
| 1; |