Blame crypto/modes/asm/ghash-sparcv9.pl

Packit c4476c
#! /usr/bin/env perl
Packit c4476c
# Copyright 2010-2020 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
#
Packit c4476c
# Licensed under the OpenSSL license (the "License").  You may not use
Packit c4476c
# this file except in compliance with the License.  You can obtain a copy
Packit c4476c
# in the file LICENSE in the source distribution or at
Packit c4476c
# https://www.openssl.org/source/license.html
Packit c4476c
Packit c4476c
Packit c4476c
# ====================================================================
Packit c4476c
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
Packit c4476c
# project. The module is, however, dual licensed under OpenSSL and
Packit c4476c
# CRYPTOGAMS licenses depending on where you obtain it. For further
Packit c4476c
# details see http://www.openssl.org/~appro/cryptogams/.
Packit c4476c
# ====================================================================
Packit c4476c
Packit c4476c
# March 2010
Packit c4476c
#
Packit c4476c
# The module implements "4-bit" GCM GHASH function and underlying
Packit c4476c
# single multiplication operation in GF(2^128). "4-bit" means that it
Packit c4476c
# uses 256 bytes per-key table [+128 bytes shared table]. Performance
Packit c4476c
# results are for streamed GHASH subroutine on UltraSPARC pre-Tx CPU
Packit c4476c
# and are expressed in cycles per processed byte, less is better:
Packit c4476c
#
Packit c4476c
#		gcc 3.3.x	cc 5.2		this assembler
Packit c4476c
#
Packit c4476c
# 32-bit build	81.4		43.3		12.6	(+546%/+244%)
Packit c4476c
# 64-bit build	20.2		21.2		12.6	(+60%/+68%)
Packit c4476c
#
Packit c4476c
# Here is data collected on UltraSPARC T1 system running Linux:
Packit c4476c
#
Packit c4476c
#		gcc 4.4.1			this assembler
Packit c4476c
#
Packit c4476c
# 32-bit build	566				50	(+1000%)
Packit c4476c
# 64-bit build	56				50	(+12%)
Packit c4476c
#
Packit c4476c
# I don't quite understand why difference between 32-bit and 64-bit
Packit c4476c
# compiler-generated code is so big. Compilers *were* instructed to
Packit c4476c
# generate code for UltraSPARC and should have used 64-bit registers
Packit c4476c
# for Z vector (see C code) even in 32-bit build... Oh well, it only
Packit c4476c
# means more impressive improvement coefficients for this assembler
Packit c4476c
# module;-) Loops are aggressively modulo-scheduled in respect to
Packit c4476c
# references to input data and Z.hi updates to achieve 12 cycles
Packit c4476c
# timing. To anchor to something else, sha1-sparcv9.pl spends 11.6
Packit c4476c
# cycles to process one byte on UltraSPARC pre-Tx CPU and ~24 on T1.
Packit c4476c
#
Packit c4476c
# October 2012
Packit c4476c
#
Packit c4476c
# Add VIS3 lookup-table-free implementation using polynomial
Packit c4476c
# multiplication xmulx[hi] and extended addition addxc[cc]
Packit c4476c
# instructions. 4.52/7.63x improvement on T3/T4 or in absolute
Packit c4476c
# terms 7.90/2.14 cycles per byte. On T4 multi-process benchmark
Packit c4476c
# saturates at ~15.5x single-process result on 8-core processor,
Packit c4476c
# or ~20.5GBps per 2.85GHz socket.
Packit c4476c
Packit c4476c
$output=pop;
Packit c4476c
open STDOUT,">$output";
Packit c4476c
Packit c4476c
$frame="STACK_FRAME";
Packit c4476c
$bias="STACK_BIAS";
Packit c4476c
Packit c4476c
$Zhi="%o0";	# 64-bit values
Packit c4476c
$Zlo="%o1";
Packit c4476c
$Thi="%o2";
Packit c4476c
$Tlo="%o3";
Packit c4476c
$rem="%o4";
Packit c4476c
$tmp="%o5";
Packit c4476c
Packit c4476c
$nhi="%l0";	# small values and pointers
Packit c4476c
$nlo="%l1";
Packit c4476c
$xi0="%l2";
Packit c4476c
$xi1="%l3";
Packit c4476c
$rem_4bit="%l4";
Packit c4476c
$remi="%l5";
Packit c4476c
$Htblo="%l6";
Packit c4476c
$cnt="%l7";
Packit c4476c
Packit c4476c
$Xi="%i0";	# input argument block
Packit c4476c
$Htbl="%i1";
Packit c4476c
$inp="%i2";
Packit c4476c
$len="%i3";
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
#include "sparc_arch.h"
Packit c4476c
Packit c4476c
#ifdef  __arch64__
Packit c4476c
.register	%g2,#scratch
Packit c4476c
.register	%g3,#scratch
Packit c4476c
#endif
Packit c4476c
Packit c4476c
.section	".text",#alloc,#execinstr
Packit c4476c
Packit c4476c
.align	64
Packit c4476c
rem_4bit:
Packit c4476c
	.long	`0x0000<<16`,0,`0x1C20<<16`,0,`0x3840<<16`,0,`0x2460<<16`,0
Packit c4476c
	.long	`0x7080<<16`,0,`0x6CA0<<16`,0,`0x48C0<<16`,0,`0x54E0<<16`,0
Packit c4476c
	.long	`0xE100<<16`,0,`0xFD20<<16`,0,`0xD940<<16`,0,`0xC560<<16`,0
Packit c4476c
	.long	`0x9180<<16`,0,`0x8DA0<<16`,0,`0xA9C0<<16`,0,`0xB5E0<<16`,0
Packit c4476c
.type	rem_4bit,#object
Packit c4476c
.size	rem_4bit,(.-rem_4bit)
Packit c4476c
Packit c4476c
.globl	gcm_ghash_4bit
Packit c4476c
.align	32
Packit c4476c
gcm_ghash_4bit:
Packit c4476c
	save	%sp,-$frame,%sp
Packit c4476c
	ldub	[$inp+15],$nlo
Packit c4476c
	ldub	[$Xi+15],$xi0
Packit c4476c
	ldub	[$Xi+14],$xi1
Packit c4476c
	add	$len,$inp,$len
Packit c4476c
	add	$Htbl,8,$Htblo
Packit c4476c
Packit c4476c
1:	call	.+8
Packit c4476c
	add	%o7,rem_4bit-1b,$rem_4bit
Packit c4476c
Packit c4476c
.Louter:
Packit c4476c
	xor	$xi0,$nlo,$nlo
Packit c4476c
	and	$nlo,0xf0,$nhi
Packit c4476c
	and	$nlo,0x0f,$nlo
Packit c4476c
	sll	$nlo,4,$nlo
Packit c4476c
	ldx	[$Htblo+$nlo],$Zlo
Packit c4476c
	ldx	[$Htbl+$nlo],$Zhi
Packit c4476c
Packit c4476c
	ldub	[$inp+14],$nlo
Packit c4476c
Packit c4476c
	ldx	[$Htblo+$nhi],$Tlo
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
	ldx	[$Htbl+$nhi],$Thi
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	mov	13,$cnt
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
Packit c4476c
	xor	$xi1,$nlo,$nlo
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
	and	$nlo,0xf0,$nhi
Packit c4476c
	and	$nlo,0x0f,$nlo
Packit c4476c
	ba	.Lghash_inner
Packit c4476c
	sll	$nlo,4,$nlo
Packit c4476c
.align	32
Packit c4476c
.Lghash_inner:
Packit c4476c
	ldx	[$Htblo+$nlo],$Tlo
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	ldx	[$Htbl+$nlo],$Thi
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	ldub	[$inp+$cnt],$nlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
	ldub	[$Xi+$cnt],$xi1
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
Packit c4476c
	ldx	[$Htblo+$nhi],$Tlo
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	ldx	[$Htbl+$nhi],$Thi
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$xi1,$nlo,$nlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	and	$nlo,0xf0,$nhi
Packit c4476c
	addcc	$cnt,-1,$cnt
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
	and	$nlo,0x0f,$nlo
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	sll	$nlo,4,$nlo
Packit c4476c
	blu	.Lghash_inner
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
Packit c4476c
	ldx	[$Htblo+$nlo],$Tlo
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	ldx	[$Htbl+$nlo],$Thi
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
Packit c4476c
	add	$inp,16,$inp
Packit c4476c
	cmp	$inp,$len
Packit c4476c
	be,pn	SIZE_T_CC,.Ldone
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
Packit c4476c
	ldx	[$Htblo+$nhi],$Tlo
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	ldx	[$Htbl+$nhi],$Thi
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	ldub	[$inp+15],$nlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	stx	$Zlo,[$Xi+8]
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	stx	$Zhi,[$Xi]
Packit c4476c
	srl	$Zlo,8,$xi1
Packit c4476c
	and	$Zlo,0xff,$xi0
Packit c4476c
	ba	.Louter
Packit c4476c
	and	$xi1,0xff,$xi1
Packit c4476c
.align	32
Packit c4476c
.Ldone:
Packit c4476c
	ldx	[$Htblo+$nhi],$Tlo
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	ldx	[$Htbl+$nhi],$Thi
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	stx	$Zlo,[$Xi+8]
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	stx	$Zhi,[$Xi]
Packit c4476c
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
.type	gcm_ghash_4bit,#function
Packit c4476c
.size	gcm_ghash_4bit,(.-gcm_ghash_4bit)
Packit c4476c
___
Packit c4476c
Packit c4476c
undef $inp;
Packit c4476c
undef $len;
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
.globl	gcm_gmult_4bit
Packit c4476c
.align	32
Packit c4476c
gcm_gmult_4bit:
Packit c4476c
	save	%sp,-$frame,%sp
Packit c4476c
	ldub	[$Xi+15],$nlo
Packit c4476c
	add	$Htbl,8,$Htblo
Packit c4476c
Packit c4476c
1:	call	.+8
Packit c4476c
	add	%o7,rem_4bit-1b,$rem_4bit
Packit c4476c
Packit c4476c
	and	$nlo,0xf0,$nhi
Packit c4476c
	and	$nlo,0x0f,$nlo
Packit c4476c
	sll	$nlo,4,$nlo
Packit c4476c
	ldx	[$Htblo+$nlo],$Zlo
Packit c4476c
	ldx	[$Htbl+$nlo],$Zhi
Packit c4476c
Packit c4476c
	ldub	[$Xi+14],$nlo
Packit c4476c
Packit c4476c
	ldx	[$Htblo+$nhi],$Tlo
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
	ldx	[$Htbl+$nhi],$Thi
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	mov	13,$cnt
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
	and	$nlo,0xf0,$nhi
Packit c4476c
	and	$nlo,0x0f,$nlo
Packit c4476c
	ba	.Lgmult_inner
Packit c4476c
	sll	$nlo,4,$nlo
Packit c4476c
.align	32
Packit c4476c
.Lgmult_inner:
Packit c4476c
	ldx	[$Htblo+$nlo],$Tlo
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	ldx	[$Htbl+$nlo],$Thi
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	ldub	[$Xi+$cnt],$nlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
Packit c4476c
	ldx	[$Htblo+$nhi],$Tlo
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	ldx	[$Htbl+$nhi],$Thi
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	and	$nlo,0xf0,$nhi
Packit c4476c
	addcc	$cnt,-1,$cnt
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
	and	$nlo,0x0f,$nlo
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	sll	$nlo,4,$nlo
Packit c4476c
	blu	.Lgmult_inner
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
Packit c4476c
	ldx	[$Htblo+$nlo],$Tlo
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	ldx	[$Htbl+$nlo],$Thi
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	and	$Zlo,0xf,$remi
Packit c4476c
Packit c4476c
	ldx	[$Htblo+$nhi],$Tlo
Packit c4476c
	sll	$remi,3,$remi
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	ldx	[$Htbl+$nhi],$Thi
Packit c4476c
	srlx	$Zlo,4,$Zlo
Packit c4476c
	ldx	[$rem_4bit+$remi],$rem
Packit c4476c
	sllx	$Zhi,60,$tmp
Packit c4476c
	xor	$Tlo,$Zlo,$Zlo
Packit c4476c
	srlx	$Zhi,4,$Zhi
Packit c4476c
	xor	$Zlo,$tmp,$Zlo
Packit c4476c
	xor	$Thi,$Zhi,$Zhi
Packit c4476c
	stx	$Zlo,[$Xi+8]
Packit c4476c
	xor	$rem,$Zhi,$Zhi
Packit c4476c
	stx	$Zhi,[$Xi]
Packit c4476c
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
.type	gcm_gmult_4bit,#function
Packit c4476c
.size	gcm_gmult_4bit,(.-gcm_gmult_4bit)
Packit c4476c
___
Packit c4476c

Packit c4476c
{{{
Packit c4476c
# Straightforward 128x128-bit multiplication using Karatsuba algorithm
Packit c4476c
# followed by pair of 64-bit reductions [with a shortcut in first one,
Packit c4476c
# which allowed to break dependency between reductions and remove one
Packit c4476c
# multiplication from critical path]. While it might be suboptimal
Packit c4476c
# with regard to sheer number of multiplications, other methods [such
Packit c4476c
# as aggregate reduction] would require more 64-bit registers, which
Packit c4476c
# we don't have in 32-bit application context.
Packit c4476c
Packit c4476c
($Xip,$Htable,$inp,$len)=map("%i$_",(0..3));
Packit c4476c
Packit c4476c
($Hhl,$Hlo,$Hhi,$Xlo,$Xhi,$xE1,$sqr, $C0,$C1,$C2,$C3,$V)=
Packit c4476c
	(map("%o$_",(0..5,7)),map("%g$_",(1..5)));
Packit c4476c
Packit c4476c
($shl,$shr)=map("%l$_",(0..7));
Packit c4476c
Packit c4476c
# For details regarding "twisted H" see ghash-x86.pl.
Packit c4476c
$code.=<<___;
Packit c4476c
.globl	gcm_init_vis3
Packit c4476c
.align	32
Packit c4476c
gcm_init_vis3:
Packit c4476c
	save	%sp,-$frame,%sp
Packit c4476c
Packit c4476c
	ldx	[%i1+0],$Hhi
Packit c4476c
	ldx	[%i1+8],$Hlo
Packit c4476c
	mov	0xE1,$Xhi
Packit c4476c
	mov	1,$Xlo
Packit c4476c
	sllx	$Xhi,57,$Xhi
Packit c4476c
	srax	$Hhi,63,$C0		! broadcast carry
Packit c4476c
	addcc	$Hlo,$Hlo,$Hlo		! H<<=1
Packit c4476c
	addxc	$Hhi,$Hhi,$Hhi
Packit c4476c
	and	$C0,$Xlo,$Xlo
Packit c4476c
	and	$C0,$Xhi,$Xhi
Packit c4476c
	xor	$Xlo,$Hlo,$Hlo
Packit c4476c
	xor	$Xhi,$Hhi,$Hhi
Packit c4476c
	stx	$Hlo,[%i0+8]		! save twisted H
Packit c4476c
	stx	$Hhi,[%i0+0]
Packit c4476c
Packit c4476c
	sethi	%hi(0xA0406080),$V
Packit c4476c
	sethi	%hi(0x20C0E000),%l0
Packit c4476c
	or	$V,%lo(0xA0406080),$V
Packit c4476c
	or	%l0,%lo(0x20C0E000),%l0
Packit c4476c
	sllx	$V,32,$V
Packit c4476c
	or	%l0,$V,$V		! (0xE0·i)&0xff=0xA040608020C0E000
Packit c4476c
	stx	$V,[%i0+16]
Packit c4476c
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
.type	gcm_init_vis3,#function
Packit c4476c
.size	gcm_init_vis3,.-gcm_init_vis3
Packit c4476c
Packit c4476c
.globl	gcm_gmult_vis3
Packit c4476c
.align	32
Packit c4476c
gcm_gmult_vis3:
Packit c4476c
	save	%sp,-$frame,%sp
Packit c4476c
Packit c4476c
	ldx	[$Xip+8],$Xlo		! load Xi
Packit c4476c
	ldx	[$Xip+0],$Xhi
Packit c4476c
	ldx	[$Htable+8],$Hlo	! load twisted H
Packit c4476c
	ldx	[$Htable+0],$Hhi
Packit c4476c
Packit c4476c
	mov	0xE1,%l7
Packit c4476c
	sllx	%l7,57,$xE1		! 57 is not a typo
Packit c4476c
	ldx	[$Htable+16],$V		! (0xE0·i)&0xff=0xA040608020C0E000
Packit c4476c
Packit c4476c
	xor	$Hhi,$Hlo,$Hhl		! Karatsuba pre-processing
Packit c4476c
	xmulx	$Xlo,$Hlo,$C0
Packit c4476c
	xor	$Xlo,$Xhi,$C2		! Karatsuba pre-processing
Packit c4476c
	xmulx	$C2,$Hhl,$C1
Packit c4476c
	xmulxhi	$Xlo,$Hlo,$Xlo
Packit c4476c
	xmulxhi	$C2,$Hhl,$C2
Packit c4476c
	xmulxhi	$Xhi,$Hhi,$C3
Packit c4476c
	xmulx	$Xhi,$Hhi,$Xhi
Packit c4476c
Packit c4476c
	sll	$C0,3,$sqr
Packit c4476c
	srlx	$V,$sqr,$sqr		! ·0xE0 [implicit &(7<<3)]
Packit c4476c
	xor	$C0,$sqr,$sqr
Packit c4476c
	sllx	$sqr,57,$sqr		! ($C0·0xE1)<<1<<56 [implicit &0x7f]
Packit c4476c
Packit c4476c
	xor	$C0,$C1,$C1		! Karatsuba post-processing
Packit c4476c
	xor	$Xlo,$C2,$C2
Packit c4476c
	 xor	$sqr,$Xlo,$Xlo		! real destination is $C1
Packit c4476c
	xor	$C3,$C2,$C2
Packit c4476c
	xor	$Xlo,$C1,$C1
Packit c4476c
	xor	$Xhi,$C2,$C2
Packit c4476c
	xor	$Xhi,$C1,$C1
Packit c4476c
Packit c4476c
	xmulxhi	$C0,$xE1,$Xlo		! ·0xE1<<1<<56
Packit c4476c
	 xor	$C0,$C2,$C2
Packit c4476c
	xmulx	$C1,$xE1,$C0
Packit c4476c
	 xor	$C1,$C3,$C3
Packit c4476c
	xmulxhi	$C1,$xE1,$C1
Packit c4476c
Packit c4476c
	xor	$Xlo,$C2,$C2
Packit c4476c
	xor	$C0,$C2,$C2
Packit c4476c
	xor	$C1,$C3,$C3
Packit c4476c
Packit c4476c
	stx	$C2,[$Xip+8]		! save Xi
Packit c4476c
	stx	$C3,[$Xip+0]
Packit c4476c
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
.type	gcm_gmult_vis3,#function
Packit c4476c
.size	gcm_gmult_vis3,.-gcm_gmult_vis3
Packit c4476c
Packit c4476c
.globl	gcm_ghash_vis3
Packit c4476c
.align	32
Packit c4476c
gcm_ghash_vis3:
Packit c4476c
	save	%sp,-$frame,%sp
Packit c4476c
	nop
Packit c4476c
	srln	$len,0,$len		! needed on v8+, "nop" on v9
Packit c4476c
Packit c4476c
	ldx	[$Xip+8],$C2		! load Xi
Packit c4476c
	ldx	[$Xip+0],$C3
Packit c4476c
	ldx	[$Htable+8],$Hlo	! load twisted H
Packit c4476c
	ldx	[$Htable+0],$Hhi
Packit c4476c
Packit c4476c
	mov	0xE1,%l7
Packit c4476c
	sllx	%l7,57,$xE1		! 57 is not a typo
Packit c4476c
	ldx	[$Htable+16],$V		! (0xE0·i)&0xff=0xA040608020C0E000
Packit c4476c
Packit c4476c
	and	$inp,7,$shl
Packit c4476c
	andn	$inp,7,$inp
Packit c4476c
	sll	$shl,3,$shl
Packit c4476c
	prefetch [$inp+63], 20
Packit c4476c
	sub	%g0,$shl,$shr
Packit c4476c
Packit c4476c
	xor	$Hhi,$Hlo,$Hhl		! Karatsuba pre-processing
Packit c4476c
.Loop:
Packit c4476c
	ldx	[$inp+8],$Xlo
Packit c4476c
	brz,pt	$shl,1f
Packit c4476c
	ldx	[$inp+0],$Xhi
Packit c4476c
Packit c4476c
	ldx	[$inp+16],$C1		! align data
Packit c4476c
	srlx	$Xlo,$shr,$C0
Packit c4476c
	sllx	$Xlo,$shl,$Xlo
Packit c4476c
	sllx	$Xhi,$shl,$Xhi
Packit c4476c
	srlx	$C1,$shr,$C1
Packit c4476c
	or	$C0,$Xhi,$Xhi
Packit c4476c
	or	$C1,$Xlo,$Xlo
Packit c4476c
1:
Packit c4476c
	add	$inp,16,$inp
Packit c4476c
	sub	$len,16,$len
Packit c4476c
	xor	$C2,$Xlo,$Xlo
Packit c4476c
	xor	$C3,$Xhi,$Xhi
Packit c4476c
	prefetch [$inp+63], 20
Packit c4476c
Packit c4476c
	xmulx	$Xlo,$Hlo,$C0
Packit c4476c
	xor	$Xlo,$Xhi,$C2		! Karatsuba pre-processing
Packit c4476c
	xmulx	$C2,$Hhl,$C1
Packit c4476c
	xmulxhi	$Xlo,$Hlo,$Xlo
Packit c4476c
	xmulxhi	$C2,$Hhl,$C2
Packit c4476c
	xmulxhi	$Xhi,$Hhi,$C3
Packit c4476c
	xmulx	$Xhi,$Hhi,$Xhi
Packit c4476c
Packit c4476c
	sll	$C0,3,$sqr
Packit c4476c
	srlx	$V,$sqr,$sqr		! ·0xE0 [implicit &(7<<3)]
Packit c4476c
	xor	$C0,$sqr,$sqr
Packit c4476c
	sllx	$sqr,57,$sqr		! ($C0·0xE1)<<1<<56 [implicit &0x7f]
Packit c4476c
Packit c4476c
	xor	$C0,$C1,$C1		! Karatsuba post-processing
Packit c4476c
	xor	$Xlo,$C2,$C2
Packit c4476c
	 xor	$sqr,$Xlo,$Xlo		! real destination is $C1
Packit c4476c
	xor	$C3,$C2,$C2
Packit c4476c
	xor	$Xlo,$C1,$C1
Packit c4476c
	xor	$Xhi,$C2,$C2
Packit c4476c
	xor	$Xhi,$C1,$C1
Packit c4476c
Packit c4476c
	xmulxhi	$C0,$xE1,$Xlo		! ·0xE1<<1<<56
Packit c4476c
	 xor	$C0,$C2,$C2
Packit c4476c
	xmulx	$C1,$xE1,$C0
Packit c4476c
	 xor	$C1,$C3,$C3
Packit c4476c
	xmulxhi	$C1,$xE1,$C1
Packit c4476c
Packit c4476c
	xor	$Xlo,$C2,$C2
Packit c4476c
	xor	$C0,$C2,$C2
Packit c4476c
	brnz,pt	$len,.Loop
Packit c4476c
	xor	$C1,$C3,$C3
Packit c4476c
Packit c4476c
	stx	$C2,[$Xip+8]		! save Xi
Packit c4476c
	stx	$C3,[$Xip+0]
Packit c4476c
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
.type	gcm_ghash_vis3,#function
Packit c4476c
.size	gcm_ghash_vis3,.-gcm_ghash_vis3
Packit c4476c
___
Packit c4476c
}}}
Packit c4476c
$code.=<<___;
Packit c4476c
.asciz	"GHASH for SPARCv9/VIS3, CRYPTOGAMS by <appro\@openssl.org>"
Packit c4476c
.align	4
Packit c4476c
___
Packit c4476c
Packit c4476c

Packit c4476c
# Purpose of these subroutines is to explicitly encode VIS instructions,
Packit c4476c
# so that one can compile the module without having to specify VIS
Packit c4476c
# extensions on compiler command line, e.g. -xarch=v9 vs. -xarch=v9a.
Packit c4476c
# Idea is to reserve for option to produce "universal" binary and let
Packit c4476c
# programmer detect if current CPU is VIS capable at run-time.
Packit c4476c
sub unvis3 {
Packit c4476c
my ($mnemonic,$rs1,$rs2,$rd)=@_;
Packit c4476c
my %bias = ( "g" => 0, "o" => 8, "l" => 16, "i" => 24 );
Packit c4476c
my ($ref,$opf);
Packit c4476c
my %visopf = (	"addxc"		=> 0x011,
Packit c4476c
		"addxccc"	=> 0x013,
Packit c4476c
		"xmulx"		=> 0x115,
Packit c4476c
		"xmulxhi"	=> 0x116	);
Packit c4476c
Packit c4476c
    $ref = "$mnemonic\t$rs1,$rs2,$rd";
Packit c4476c
Packit c4476c
    if ($opf=$visopf{$mnemonic}) {
Packit c4476c
	foreach ($rs1,$rs2,$rd) {
Packit c4476c
	    return $ref if (!/%([goli])([0-9])/);
Packit c4476c
	    $_=$bias{$1}+$2;
Packit c4476c
	}
Packit c4476c
Packit c4476c
	return	sprintf ".word\t0x%08x !%s",
Packit c4476c
			0x81b00000|$rd<<25|$rs1<<14|$opf<<5|$rs2,
Packit c4476c
			$ref;
Packit c4476c
    } else {
Packit c4476c
	return $ref;
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
foreach (split("\n",$code)) {
Packit c4476c
	s/\`([^\`]*)\`/eval $1/ge;
Packit c4476c
Packit c4476c
	s/\b(xmulx[hi]*|addxc[c]{0,2})\s+(%[goli][0-7]),\s*(%[goli][0-7]),\s*(%[goli][0-7])/
Packit c4476c
		&unvis3($1,$2,$3,$4)
Packit c4476c
	 /ge;
Packit c4476c
Packit c4476c
	print $_,"\n";
Packit c4476c
}
Packit c4476c
Packit c4476c
close STDOUT or die "error closing STDOUT: $!";