blob: a9a41ccf675ffa758a8b5ba323338810b09d555d [file]
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;