Blame crypto/bn/asm/sparct4-mont.pl

Packit c4476c
#! /usr/bin/env perl
Packit c4476c
# Copyright 2012-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 David S. Miller and Andy Polyakov
Packit c4476c
# The module is licensed under 2-clause BSD license.
Packit c4476c
# November 2012. All rights reserved.
Packit c4476c
# ====================================================================
Packit c4476c
Packit c4476c
######################################################################
Packit c4476c
# Montgomery squaring-n-multiplication module for SPARC T4.
Packit c4476c
#
Packit c4476c
# The module consists of three parts:
Packit c4476c
#
Packit c4476c
# 1) collection of "single-op" subroutines that perform single
Packit c4476c
#    operation, Montgomery squaring or multiplication, on 512-,
Packit c4476c
#    1024-, 1536- and 2048-bit operands;
Packit c4476c
# 2) collection of "multi-op" subroutines that perform 5 squaring and
Packit c4476c
#    1 multiplication operations on operands of above lengths;
Packit c4476c
# 3) fall-back and helper VIS3 subroutines.
Packit c4476c
#
Packit c4476c
# RSA sign is dominated by multi-op subroutine, while RSA verify and
Packit c4476c
# DSA - by single-op. Special note about 4096-bit RSA verify result.
Packit c4476c
# Operands are too long for dedicated hardware and it's handled by
Packit c4476c
# VIS3 code, which is why you don't see any improvement. It's surely
Packit c4476c
# possible to improve it [by deploying 'mpmul' instruction], maybe in
Packit c4476c
# the future...
Packit c4476c
#
Packit c4476c
# Performance improvement.
Packit c4476c
#
Packit c4476c
# 64-bit process, VIS3:
Packit c4476c
#                   sign    verify    sign/s verify/s
Packit c4476c
# rsa 1024 bits 0.000628s 0.000028s   1592.4  35434.4
Packit c4476c
# rsa 2048 bits 0.003282s 0.000106s    304.7   9438.3
Packit c4476c
# rsa 4096 bits 0.025866s 0.000340s     38.7   2940.9
Packit c4476c
# dsa 1024 bits 0.000301s 0.000332s   3323.7   3013.9
Packit c4476c
# dsa 2048 bits 0.001056s 0.001233s    946.9    810.8
Packit c4476c
#
Packit c4476c
# 64-bit process, this module:
Packit c4476c
#                   sign    verify    sign/s verify/s
Packit c4476c
# rsa 1024 bits 0.000256s 0.000016s   3904.4  61411.9
Packit c4476c
# rsa 2048 bits 0.000946s 0.000029s   1056.8  34292.7
Packit c4476c
# rsa 4096 bits 0.005061s 0.000340s    197.6   2940.5
Packit c4476c
# dsa 1024 bits 0.000176s 0.000195s   5674.7   5130.5
Packit c4476c
# dsa 2048 bits 0.000296s 0.000354s   3383.2   2827.6
Packit c4476c
#
Packit c4476c
######################################################################
Packit c4476c
# 32-bit process, VIS3:
Packit c4476c
#                   sign    verify    sign/s verify/s
Packit c4476c
# rsa 1024 bits 0.000665s 0.000028s   1504.8  35233.3
Packit c4476c
# rsa 2048 bits 0.003349s 0.000106s    298.6   9433.4
Packit c4476c
# rsa 4096 bits 0.025959s 0.000341s     38.5   2934.8
Packit c4476c
# dsa 1024 bits 0.000320s 0.000341s   3123.3   2929.6
Packit c4476c
# dsa 2048 bits 0.001101s 0.001260s    908.2    793.4
Packit c4476c
#
Packit c4476c
# 32-bit process, this module:
Packit c4476c
#                   sign    verify    sign/s verify/s
Packit c4476c
# rsa 1024 bits 0.000301s 0.000017s   3317.1  60240.0
Packit c4476c
# rsa 2048 bits 0.001034s 0.000030s    966.9  33812.7
Packit c4476c
# rsa 4096 bits 0.005244s 0.000341s    190.7   2935.4
Packit c4476c
# dsa 1024 bits 0.000201s 0.000205s   4976.1   4879.2
Packit c4476c
# dsa 2048 bits 0.000328s 0.000360s   3051.1   2774.2
Packit c4476c
#
Packit c4476c
# 32-bit code is prone to performance degradation as interrupt rate
Packit c4476c
# dispatched to CPU executing the code grows. This is because in
Packit c4476c
# standard process of handling interrupt in 32-bit process context
Packit c4476c
# upper halves of most integer registers used as input or output are
Packit c4476c
# zeroed. This renders result invalid, and operation has to be re-run.
Packit c4476c
# If CPU is "bothered" with timer interrupts only, the penalty is
Packit c4476c
# hardly measurable. But in order to mitigate this problem for higher
Packit c4476c
# interrupt rates contemporary Linux kernel recognizes biased stack
Packit c4476c
# even in 32-bit process context and preserves full register contents.
Packit c4476c
# See http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=517ffce4e1a03aea979fe3a18a3dd1761a24fafb
Packit c4476c
# for details.
Packit c4476c
Packit c4476c
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
Packit c4476c
push(@INC,"${dir}","${dir}../../perlasm");
Packit c4476c
require "sparcv9_modes.pl";
Packit c4476c
Packit c4476c
$output = pop;
Packit c4476c
open STDOUT,">$output";
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
#ifdef	__PIC__
Packit c4476c
SPARC_PIC_THUNK(%g1)
Packit c4476c
#endif
Packit c4476c
___
Packit c4476c
Packit c4476c
########################################################################
Packit c4476c
# Register layout for mont[mul|sqr] instructions.
Packit c4476c
# For details see "Oracle SPARC Architecture 2011" manual at
Packit c4476c
# http://www.oracle.com/technetwork/server-storage/sun-sparc-enterprise/documentation/.
Packit c4476c
#
Packit c4476c
my @R=map("%f".2*$_,(0..11,30,31,12..29));
Packit c4476c
my @N=(map("%l$_",(0..7)),map("%o$_",(0..5))); @N=(@N,@N,@N[0..3]);
Packit c4476c
my @A=(@N[0..13],@R[14..31]);
Packit c4476c
my @B=(map("%i$_",(0..5)),map("%l$_",(0..7))); @B=(@B,@B,map("%o$_",(0..3)));
Packit c4476c

Packit c4476c
########################################################################
Packit c4476c
# int bn_mul_mont_t4_$NUM(u64 *rp,const u64 *ap,const u64 *bp,
Packit c4476c
#			  const u64 *np,const BN_ULONG *n0);
Packit c4476c
#
Packit c4476c
sub generate_bn_mul_mont_t4() {
Packit c4476c
my $NUM=shift;
Packit c4476c
my ($rp,$ap,$bp,$np,$sentinel)=map("%g$_",(1..5));
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
.globl	bn_mul_mont_t4_$NUM
Packit c4476c
.align	32
Packit c4476c
bn_mul_mont_t4_$NUM:
Packit c4476c
#ifdef	__arch64__
Packit c4476c
	mov	0,$sentinel
Packit c4476c
	mov	-128,%g4
Packit c4476c
#elif defined(SPARCV9_64BIT_STACK)
Packit c4476c
	SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5)
Packit c4476c
	ld	[%g1+0],%g1	! OPENSSL_sparcv9_P[0]
Packit c4476c
	mov	-2047,%g4
Packit c4476c
	and	%g1,SPARCV9_64BIT_STACK,%g1
Packit c4476c
	movrz	%g1,0,%g4
Packit c4476c
	mov	-1,$sentinel
Packit c4476c
	add	%g4,-128,%g4
Packit c4476c
#else
Packit c4476c
	mov	-1,$sentinel
Packit c4476c
	mov	-128,%g4
Packit c4476c
#endif
Packit c4476c
	sllx	$sentinel,32,$sentinel
Packit c4476c
	save	%sp,%g4,%sp
Packit c4476c
#ifndef	__arch64__
Packit c4476c
	save	%sp,-128,%sp	! warm it up
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
#endif
Packit c4476c
	and	%sp,1,%g4
Packit c4476c
	or	$sentinel,%fp,%fp
Packit c4476c
	or	%g4,$sentinel,$sentinel
Packit c4476c
Packit c4476c
	! copy arguments to global registers
Packit c4476c
	mov	%i0,$rp
Packit c4476c
	mov	%i1,$ap
Packit c4476c
	mov	%i2,$bp
Packit c4476c
	mov	%i3,$np
Packit c4476c
	ld	[%i4+0],%f1	! load *n0
Packit c4476c
	ld	[%i4+4],%f0
Packit c4476c
	fsrc2	%f0,%f60
Packit c4476c
___
Packit c4476c

Packit c4476c
# load ap[$NUM] ########################################################
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for($i=0; $i<14 && $i<$NUM; $i++) {
Packit c4476c
my $lo=$i<13?@A[$i+1]:"%o7";
Packit c4476c
$code.=<<___;
Packit c4476c
	ld	[$ap+$i*8+0],$lo
Packit c4476c
	ld	[$ap+$i*8+4],@A[$i]
Packit c4476c
	sllx	@A[$i],32,@A[$i]
Packit c4476c
	or	$lo,@A[$i],@A[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
for(; $i<$NUM; $i++) {
Packit c4476c
my ($hi,$lo)=("%f".2*($i%4),"%f".(2*($i%4)+1));
Packit c4476c
$code.=<<___;
Packit c4476c
	ld	[$ap+$i*8+0],$lo
Packit c4476c
	ld	[$ap+$i*8+4],$hi
Packit c4476c
	fsrc2	$hi,@A[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
# load np[$NUM] ########################################################
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for($i=0; $i<14 && $i<$NUM; $i++) {
Packit c4476c
my $lo=$i<13?@N[$i+1]:"%o7";
Packit c4476c
$code.=<<___;
Packit c4476c
	ld	[$np+$i*8+0],$lo
Packit c4476c
	ld	[$np+$i*8+4],@N[$i]
Packit c4476c
	sllx	@N[$i],32,@N[$i]
Packit c4476c
	or	$lo,@N[$i],@N[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for(; $i<28 && $i<$NUM; $i++) {
Packit c4476c
my $lo=$i<27?@N[$i+1]:"%o7";
Packit c4476c
$code.=<<___;
Packit c4476c
	ld	[$np+$i*8+0],$lo
Packit c4476c
	ld	[$np+$i*8+4],@N[$i]
Packit c4476c
	sllx	@N[$i],32,@N[$i]
Packit c4476c
	or	$lo,@N[$i],@N[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for(; $i<$NUM; $i++) {
Packit c4476c
my $lo=($i<$NUM-1)?@N[$i+1]:"%o7";
Packit c4476c
$code.=<<___;
Packit c4476c
	ld	[$np+$i*8+0],$lo
Packit c4476c
	ld	[$np+$i*8+4],@N[$i]
Packit c4476c
	sllx	@N[$i],32,@N[$i]
Packit c4476c
	or	$lo,@N[$i],@N[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	cmp	$ap,$bp
Packit c4476c
	be	SIZE_T_CC,.Lmsquare_$NUM
Packit c4476c
	nop
Packit c4476c
___
Packit c4476c

Packit c4476c
# load bp[$NUM] ########################################################
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for($i=0; $i<14 && $i<$NUM; $i++) {
Packit c4476c
my $lo=$i<13?@B[$i+1]:"%o7";
Packit c4476c
$code.=<<___;
Packit c4476c
	ld	[$bp+$i*8+0],$lo
Packit c4476c
	ld	[$bp+$i*8+4],@B[$i]
Packit c4476c
	sllx	@B[$i],32,@B[$i]
Packit c4476c
	or	$lo,@B[$i],@B[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for(; $i<$NUM; $i++) {
Packit c4476c
my $lo=($i<$NUM-1)?@B[$i+1]:"%o7";
Packit c4476c
$code.=<<___;
Packit c4476c
	ld	[$bp+$i*8+0],$lo
Packit c4476c
	ld	[$bp+$i*8+4],@B[$i]
Packit c4476c
	sllx	@B[$i],32,@B[$i]
Packit c4476c
	or	$lo,@B[$i],@B[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
# magic ################################################################
Packit c4476c
$code.=<<___;
Packit c4476c
	.word	0x81b02920+$NUM-1	! montmul	$NUM-1
Packit c4476c
.Lmresume_$NUM:
Packit c4476c
	fbu,pn	%fcc3,.Lmabort_$NUM
Packit c4476c
#ifndef	__arch64__
Packit c4476c
	and	%fp,$sentinel,$sentinel
Packit c4476c
	brz,pn	$sentinel,.Lmabort_$NUM
Packit c4476c
#endif
Packit c4476c
	nop
Packit c4476c
#ifdef	__arch64__
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
#else
Packit c4476c
	restore;		and	%fp,$sentinel,$sentinel
Packit c4476c
	restore;		and	%fp,$sentinel,$sentinel
Packit c4476c
	restore;		and	%fp,$sentinel,$sentinel
Packit c4476c
	restore;		and	%fp,$sentinel,$sentinel
Packit c4476c
	 brz,pn	$sentinel,.Lmabort1_$NUM
Packit c4476c
	restore
Packit c4476c
#endif
Packit c4476c
___
Packit c4476c

Packit c4476c
# save tp[$NUM] ########################################################
Packit c4476c
for($i=0; $i<14 && $i<$NUM; $i++) {
Packit c4476c
$code.=<<___;
Packit c4476c
	movxtod	@A[$i],@R[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
#ifdef	__arch64__
Packit c4476c
	restore
Packit c4476c
#else
Packit c4476c
	 and	%fp,$sentinel,$sentinel
Packit c4476c
	restore
Packit c4476c
	 and	$sentinel,1,%o7
Packit c4476c
	 and	%fp,$sentinel,$sentinel
Packit c4476c
	 srl	%fp,0,%fp		! just in case?
Packit c4476c
	 or	%o7,$sentinel,$sentinel
Packit c4476c
	brz,a,pn $sentinel,.Lmdone_$NUM
Packit c4476c
	mov	0,%i0		! return failure
Packit c4476c
#endif
Packit c4476c
___
Packit c4476c
for($i=0; $i<12 && $i<$NUM; $i++) {
Packit c4476c
@R[$i] =~ /%f([0-9]+)/;
Packit c4476c
my $lo = "%f".($1+1);
Packit c4476c
$code.=<<___;
Packit c4476c
	st	$lo,[$rp+$i*8+0]
Packit c4476c
	st	@R[$i],[$rp+$i*8+4]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
for(; $i<$NUM; $i++) {
Packit c4476c
my ($hi,$lo)=("%f".2*($i%4),"%f".(2*($i%4)+1));
Packit c4476c
$code.=<<___;
Packit c4476c
	fsrc2	@R[$i],$hi
Packit c4476c
	st	$lo,[$rp+$i*8+0]
Packit c4476c
	st	$hi,[$rp+$i*8+4]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	mov	1,%i0		! return success
Packit c4476c
.Lmdone_$NUM:
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
Packit c4476c
.Lmabort_$NUM:
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
.Lmabort1_$NUM:
Packit c4476c
	restore
Packit c4476c
Packit c4476c
	mov	0,%i0		! return failure
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
Packit c4476c
.align	32
Packit c4476c
.Lmsquare_$NUM:
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
	.word   0x81b02940+$NUM-1	! montsqr	$NUM-1
Packit c4476c
	ba	.Lmresume_$NUM
Packit c4476c
	nop
Packit c4476c
.type	bn_mul_mont_t4_$NUM, #function
Packit c4476c
.size	bn_mul_mont_t4_$NUM, .-bn_mul_mont_t4_$NUM
Packit c4476c
___
Packit c4476c
}
Packit c4476c
Packit c4476c
for ($i=8;$i<=32;$i+=8) {
Packit c4476c
	&generate_bn_mul_mont_t4($i);
Packit c4476c
}
Packit c4476c

Packit c4476c
########################################################################
Packit c4476c
#
Packit c4476c
sub load_ccr {
Packit c4476c
my ($ptbl,$pwr,$ccr,$skip_wr)=@_;
Packit c4476c
$code.=<<___;
Packit c4476c
	srl	$pwr,	2,	%o4
Packit c4476c
	and	$pwr,	3,	%o5
Packit c4476c
	and	%o4,	7,	%o4
Packit c4476c
	sll	%o5,	3,	%o5	! offset within first cache line
Packit c4476c
	add	%o5,	$ptbl,	$ptbl	! of the pwrtbl
Packit c4476c
	or	%g0,	1,	%o5
Packit c4476c
	sll	%o5,	%o4,	$ccr
Packit c4476c
___
Packit c4476c
$code.=<<___	if (!$skip_wr);
Packit c4476c
	wr	$ccr,	%g0,	%ccr
Packit c4476c
___
Packit c4476c
}
Packit c4476c
sub load_b_pair {
Packit c4476c
my ($pwrtbl,$B0,$B1)=@_;
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
	ldx	[$pwrtbl+0*32],	$B0
Packit c4476c
	ldx	[$pwrtbl+8*32],	$B1
Packit c4476c
	ldx	[$pwrtbl+1*32],	%o4
Packit c4476c
	ldx	[$pwrtbl+9*32],	%o5
Packit c4476c
	movvs	%icc,	%o4,	$B0
Packit c4476c
	ldx	[$pwrtbl+2*32],	%o4
Packit c4476c
	movvs	%icc,	%o5,	$B1
Packit c4476c
	ldx	[$pwrtbl+10*32],%o5
Packit c4476c
	move	%icc,	%o4,	$B0
Packit c4476c
	ldx	[$pwrtbl+3*32],	%o4
Packit c4476c
	move	%icc,	%o5,	$B1
Packit c4476c
	ldx	[$pwrtbl+11*32],%o5
Packit c4476c
	movneg	%icc,	%o4,	$B0
Packit c4476c
	ldx	[$pwrtbl+4*32],	%o4
Packit c4476c
	movneg	%icc,	%o5,	$B1
Packit c4476c
	ldx	[$pwrtbl+12*32],%o5
Packit c4476c
	movcs	%xcc,	%o4,	$B0
Packit c4476c
	ldx	[$pwrtbl+5*32],%o4
Packit c4476c
	movcs	%xcc,	%o5,	$B1
Packit c4476c
	ldx	[$pwrtbl+13*32],%o5
Packit c4476c
	movvs	%xcc,	%o4,	$B0
Packit c4476c
	ldx	[$pwrtbl+6*32],	%o4
Packit c4476c
	movvs	%xcc,	%o5,	$B1
Packit c4476c
	ldx	[$pwrtbl+14*32],%o5
Packit c4476c
	move	%xcc,	%o4,	$B0
Packit c4476c
	ldx	[$pwrtbl+7*32],	%o4
Packit c4476c
	move	%xcc,	%o5,	$B1
Packit c4476c
	ldx	[$pwrtbl+15*32],%o5
Packit c4476c
	movneg	%xcc,	%o4,	$B0
Packit c4476c
	add	$pwrtbl,16*32,	$pwrtbl
Packit c4476c
	movneg	%xcc,	%o5,	$B1
Packit c4476c
___
Packit c4476c
}
Packit c4476c
sub load_b {
Packit c4476c
my ($pwrtbl,$Bi)=@_;
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
	ldx	[$pwrtbl+0*32],	$Bi
Packit c4476c
	ldx	[$pwrtbl+1*32],	%o4
Packit c4476c
	ldx	[$pwrtbl+2*32],	%o5
Packit c4476c
	movvs	%icc,	%o4,	$Bi
Packit c4476c
	ldx	[$pwrtbl+3*32],	%o4
Packit c4476c
	move	%icc,	%o5,	$Bi
Packit c4476c
	ldx	[$pwrtbl+4*32],	%o5
Packit c4476c
	movneg	%icc,	%o4,	$Bi
Packit c4476c
	ldx	[$pwrtbl+5*32],	%o4
Packit c4476c
	movcs	%xcc,	%o5,	$Bi
Packit c4476c
	ldx	[$pwrtbl+6*32],	%o5
Packit c4476c
	movvs	%xcc,	%o4,	$Bi
Packit c4476c
	ldx	[$pwrtbl+7*32],	%o4
Packit c4476c
	move	%xcc,	%o5,	$Bi
Packit c4476c
	add	$pwrtbl,8*32,	$pwrtbl
Packit c4476c
	movneg	%xcc,	%o4,	$Bi
Packit c4476c
___
Packit c4476c
}
Packit c4476c

Packit c4476c
########################################################################
Packit c4476c
# int bn_pwr5_mont_t4_$NUM(u64 *tp,const u64 *np,const BN_ULONG *n0,
Packit c4476c
#			   const u64 *pwrtbl,int pwr,int stride);
Packit c4476c
#
Packit c4476c
sub generate_bn_pwr5_mont_t4() {
Packit c4476c
my $NUM=shift;
Packit c4476c
my ($tp,$np,$pwrtbl,$pwr,$sentinel)=map("%g$_",(1..5));
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
.globl	bn_pwr5_mont_t4_$NUM
Packit c4476c
.align	32
Packit c4476c
bn_pwr5_mont_t4_$NUM:
Packit c4476c
#ifdef	__arch64__
Packit c4476c
	mov	0,$sentinel
Packit c4476c
	mov	-128,%g4
Packit c4476c
#elif defined(SPARCV9_64BIT_STACK)
Packit c4476c
	SPARC_LOAD_ADDRESS_LEAF(OPENSSL_sparcv9cap_P,%g1,%g5)
Packit c4476c
	ld	[%g1+0],%g1	! OPENSSL_sparcv9_P[0]
Packit c4476c
	mov	-2047,%g4
Packit c4476c
	and	%g1,SPARCV9_64BIT_STACK,%g1
Packit c4476c
	movrz	%g1,0,%g4
Packit c4476c
	mov	-1,$sentinel
Packit c4476c
	add	%g4,-128,%g4
Packit c4476c
#else
Packit c4476c
	mov	-1,$sentinel
Packit c4476c
	mov	-128,%g4
Packit c4476c
#endif
Packit c4476c
	sllx	$sentinel,32,$sentinel
Packit c4476c
	save	%sp,%g4,%sp
Packit c4476c
#ifndef	__arch64__
Packit c4476c
	save	%sp,-128,%sp	! warm it up
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	save	%sp,-128,%sp
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
#endif
Packit c4476c
	and	%sp,1,%g4
Packit c4476c
	or	$sentinel,%fp,%fp
Packit c4476c
	or	%g4,$sentinel,$sentinel
Packit c4476c
Packit c4476c
	! copy arguments to global registers
Packit c4476c
	mov	%i0,$tp
Packit c4476c
	mov	%i1,$np
Packit c4476c
	ld	[%i2+0],%f1	! load *n0
Packit c4476c
	ld	[%i2+4],%f0
Packit c4476c
	mov	%i3,$pwrtbl
Packit c4476c
	srl	%i4,%g0,%i4	! pack last arguments
Packit c4476c
	sllx	%i5,32,$pwr
Packit c4476c
	or	%i4,$pwr,$pwr
Packit c4476c
	fsrc2	%f0,%f60
Packit c4476c
___
Packit c4476c

Packit c4476c
# load tp[$NUM] ########################################################
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for($i=0; $i<14 && $i<$NUM; $i++) {
Packit c4476c
$code.=<<___;
Packit c4476c
	ldx	[$tp+$i*8],@A[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
for(; $i<$NUM; $i++) {
Packit c4476c
$code.=<<___;
Packit c4476c
	ldd	[$tp+$i*8],@A[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
# load np[$NUM] ########################################################
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for($i=0; $i<14 && $i<$NUM; $i++) {
Packit c4476c
$code.=<<___;
Packit c4476c
	ldx	[$np+$i*8],@N[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for(; $i<28 && $i<$NUM; $i++) {
Packit c4476c
$code.=<<___;
Packit c4476c
	ldx	[$np+$i*8],@N[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for(; $i<$NUM; $i++) {
Packit c4476c
$code.=<<___;
Packit c4476c
	ldx	[$np+$i*8],@N[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
# load pwrtbl[pwr] ########################################################
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
Packit c4476c
	srlx	$pwr,	32,	%o4		! unpack $pwr
Packit c4476c
	srl	$pwr,	%g0,	%o5
Packit c4476c
	sub	%o4,	5,	%o4
Packit c4476c
	mov	$pwrtbl,	%o7
Packit c4476c
	sllx	%o4,	32,	$pwr		! re-pack $pwr
Packit c4476c
	or	%o5,	$pwr,	$pwr
Packit c4476c
	srl	%o5,	%o4,	%o5
Packit c4476c
___
Packit c4476c
	&load_ccr("%o7","%o5","%o4");
Packit c4476c
$code.=<<___;
Packit c4476c
	b	.Lstride_$NUM
Packit c4476c
	nop
Packit c4476c
.align	16
Packit c4476c
.Lstride_$NUM:
Packit c4476c
___
Packit c4476c
for($i=0; $i<14 && $i<$NUM; $i+=2) {
Packit c4476c
	&load_b_pair("%o7",@B[$i],@B[$i+1]);
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	save	%sp,-128,%sp;		or	$sentinel,%fp,%fp
Packit c4476c
___
Packit c4476c
for(; $i<$NUM; $i+=2) {
Packit c4476c
	&load_b_pair("%i7",@B[$i],@B[$i+1]);
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	srax	$pwr,	32,	%o4		! unpack $pwr
Packit c4476c
	srl	$pwr,	%g0,	%o5
Packit c4476c
	sub	%o4,	5,	%o4
Packit c4476c
	mov	$pwrtbl,	%i7
Packit c4476c
	sllx	%o4,	32,	$pwr		! re-pack $pwr
Packit c4476c
	or	%o5,	$pwr,	$pwr
Packit c4476c
	srl	%o5,	%o4,	%o5
Packit c4476c
___
Packit c4476c
	&load_ccr("%i7","%o5","%o4",1);
Packit c4476c

Packit c4476c
# magic ################################################################
Packit c4476c
for($i=0; $i<5; $i++) {
Packit c4476c
$code.=<<___;
Packit c4476c
	.word	0x81b02940+$NUM-1	! montsqr	$NUM-1
Packit c4476c
	fbu,pn	%fcc3,.Labort_$NUM
Packit c4476c
#ifndef	__arch64__
Packit c4476c
	and	%fp,$sentinel,$sentinel
Packit c4476c
	brz,pn	$sentinel,.Labort_$NUM
Packit c4476c
#endif
Packit c4476c
	nop
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	wr	%o4,	%g0,	%ccr
Packit c4476c
	.word	0x81b02920+$NUM-1	! montmul	$NUM-1
Packit c4476c
	fbu,pn	%fcc3,.Labort_$NUM
Packit c4476c
#ifndef	__arch64__
Packit c4476c
	and	%fp,$sentinel,$sentinel
Packit c4476c
	brz,pn	$sentinel,.Labort_$NUM
Packit c4476c
#endif
Packit c4476c
Packit c4476c
	srax	$pwr,	32,	%o4
Packit c4476c
#ifdef	__arch64__
Packit c4476c
	brgez	%o4,.Lstride_$NUM
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
#else
Packit c4476c
	brgez	%o4,.Lstride_$NUM
Packit c4476c
	restore;		and	%fp,$sentinel,$sentinel
Packit c4476c
	restore;		and	%fp,$sentinel,$sentinel
Packit c4476c
	restore;		and	%fp,$sentinel,$sentinel
Packit c4476c
	restore;		and	%fp,$sentinel,$sentinel
Packit c4476c
	 brz,pn	$sentinel,.Labort1_$NUM
Packit c4476c
	restore
Packit c4476c
#endif
Packit c4476c
___
Packit c4476c

Packit c4476c
# save tp[$NUM] ########################################################
Packit c4476c
for($i=0; $i<14 && $i<$NUM; $i++) {
Packit c4476c
$code.=<<___;
Packit c4476c
	movxtod	@A[$i],@R[$i]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
#ifdef	__arch64__
Packit c4476c
	restore
Packit c4476c
#else
Packit c4476c
	 and	%fp,$sentinel,$sentinel
Packit c4476c
	restore
Packit c4476c
	 and	$sentinel,1,%o7
Packit c4476c
	 and	%fp,$sentinel,$sentinel
Packit c4476c
	 srl	%fp,0,%fp		! just in case?
Packit c4476c
	 or	%o7,$sentinel,$sentinel
Packit c4476c
	brz,a,pn $sentinel,.Ldone_$NUM
Packit c4476c
	mov	0,%i0		! return failure
Packit c4476c
#endif
Packit c4476c
___
Packit c4476c
for($i=0; $i<$NUM; $i++) {
Packit c4476c
$code.=<<___;
Packit c4476c
	std	@R[$i],[$tp+$i*8]
Packit c4476c
___
Packit c4476c
}
Packit c4476c
$code.=<<___;
Packit c4476c
	mov	1,%i0		! return success
Packit c4476c
.Ldone_$NUM:
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
Packit c4476c
.Labort_$NUM:
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
	restore
Packit c4476c
.Labort1_$NUM:
Packit c4476c
	restore
Packit c4476c
Packit c4476c
	mov	0,%i0		! return failure
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
.type	bn_pwr5_mont_t4_$NUM, #function
Packit c4476c
.size	bn_pwr5_mont_t4_$NUM, .-bn_pwr5_mont_t4_$NUM
Packit c4476c
___
Packit c4476c
}
Packit c4476c
Packit c4476c
for ($i=8;$i<=32;$i+=8) {
Packit c4476c
	&generate_bn_pwr5_mont_t4($i);
Packit c4476c
}
Packit c4476c

Packit c4476c
{
Packit c4476c
########################################################################
Packit c4476c
# Fall-back subroutines
Packit c4476c
#
Packit c4476c
# copy of bn_mul_mont_vis3 adjusted for vectors of 64-bit values
Packit c4476c
#
Packit c4476c
($n0,$m0,$m1,$lo0,$hi0, $lo1,$hi1,$aj,$alo,$nj,$nlo,$tj)=
Packit c4476c
	(map("%g$_",(1..5)),map("%o$_",(0..5,7)));
Packit c4476c
Packit c4476c
# int bn_mul_mont(
Packit c4476c
$rp="%o0";	# u64 *rp,
Packit c4476c
$ap="%o1";	# const u64 *ap,
Packit c4476c
$bp="%o2";	# const u64 *bp,
Packit c4476c
$np="%o3";	# const u64 *np,
Packit c4476c
$n0p="%o4";	# const BN_ULONG *n0,
Packit c4476c
$num="%o5";	# int num);	# caller ensures that num is >=3
Packit c4476c
$code.=<<___;
Packit c4476c
.globl	bn_mul_mont_t4
Packit c4476c
.align	32
Packit c4476c
bn_mul_mont_t4:
Packit c4476c
	add	%sp,	STACK_BIAS,	%g4	! real top of stack
Packit c4476c
	sll	$num,	3,	$num		! size in bytes
Packit c4476c
	add	$num,	63,	%g1
Packit c4476c
	andn	%g1,	63,	%g1		! buffer size rounded up to 64 bytes
Packit c4476c
	sub	%g4,	%g1,	%g1
Packit c4476c
	andn	%g1,	63,	%g1		! align at 64 byte
Packit c4476c
	sub	%g1,	STACK_FRAME,	%g1	! new top of stack
Packit c4476c
	sub	%g1,	%g4,	%g1
Packit c4476c
Packit c4476c
	save	%sp,	%g1,	%sp
Packit c4476c
___
Packit c4476c
#	+-------------------------------+<-----	%sp
Packit c4476c
#	.				.
Packit c4476c
#	+-------------------------------+<-----	aligned at 64 bytes
Packit c4476c
#	| __int64 tmp[0]		|
Packit c4476c
#	+-------------------------------+
Packit c4476c
#	.				.
Packit c4476c
#	.				.
Packit c4476c
#	+-------------------------------+<-----	aligned at 64 bytes
Packit c4476c
#	.				.
Packit c4476c
($rp,$ap,$bp,$np,$n0p,$num)=map("%i$_",(0..5));
Packit c4476c
($t0,$t1,$t2,$t3,$cnt,$tp,$bufsz)=map("%l$_",(0..7));
Packit c4476c
($ovf,$i)=($t0,$t1);
Packit c4476c
$code.=<<___;
Packit c4476c
	ld	[$n0p+0],	$t0	! pull n0[0..1] value
Packit c4476c
	ld	[$n0p+4],	$t1
Packit c4476c
	add	%sp, STACK_BIAS+STACK_FRAME, $tp
Packit c4476c
	ldx	[$bp+0],	$m0	! m0=bp[0]
Packit c4476c
	sllx	$t1,	32,	$n0
Packit c4476c
	add	$bp,	8,	$bp
Packit c4476c
	or	$t0,	$n0,	$n0
Packit c4476c

Packit c4476c
	ldx	[$ap+0],	$aj	! ap[0]
Packit c4476c
Packit c4476c
	mulx	$aj,	$m0,	$lo0	! ap[0]*bp[0]
Packit c4476c
	umulxhi	$aj,	$m0,	$hi0
Packit c4476c
Packit c4476c
	ldx	[$ap+8],	$aj	! ap[1]
Packit c4476c
	add	$ap,	16,	$ap
Packit c4476c
	ldx	[$np+0],	$nj	! np[0]
Packit c4476c
Packit c4476c
	mulx	$lo0,	$n0,	$m1	! "tp[0]"*n0
Packit c4476c
Packit c4476c
	mulx	$aj,	$m0,	$alo	! ap[1]*bp[0]
Packit c4476c
	umulxhi	$aj,	$m0,	$aj	! ahi=aj
Packit c4476c
Packit c4476c
	mulx	$nj,	$m1,	$lo1	! np[0]*m1
Packit c4476c
	umulxhi	$nj,	$m1,	$hi1
Packit c4476c
Packit c4476c
	ldx	[$np+8],	$nj	! np[1]
Packit c4476c
Packit c4476c
	addcc	$lo0,	$lo1,	$lo1
Packit c4476c
	add	$np,	16,	$np
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
Packit c4476c
	mulx	$nj,	$m1,	$nlo	! np[1]*m1
Packit c4476c
	umulxhi	$nj,	$m1,	$nj	! nhi=nj
Packit c4476c

Packit c4476c
	ba	.L1st
Packit c4476c
	sub	$num,	24,	$cnt	! cnt=num-3
Packit c4476c
Packit c4476c
.align	16
Packit c4476c
.L1st:
Packit c4476c
	addcc	$alo,	$hi0,	$lo0
Packit c4476c
	addxc	$aj,	%g0,	$hi0
Packit c4476c
Packit c4476c
	ldx	[$ap+0],	$aj	! ap[j]
Packit c4476c
	addcc	$nlo,	$hi1,	$lo1
Packit c4476c
	add	$ap,	8,	$ap
Packit c4476c
	addxc	$nj,	%g0,	$hi1	! nhi=nj
Packit c4476c
Packit c4476c
	ldx	[$np+0],	$nj	! np[j]
Packit c4476c
	mulx	$aj,	$m0,	$alo	! ap[j]*bp[0]
Packit c4476c
	add	$np,	8,	$np
Packit c4476c
	umulxhi	$aj,	$m0,	$aj	! ahi=aj
Packit c4476c
Packit c4476c
	mulx	$nj,	$m1,	$nlo	! np[j]*m1
Packit c4476c
	addcc	$lo0,	$lo1,	$lo1	! np[j]*m1+ap[j]*bp[0]
Packit c4476c
	umulxhi	$nj,	$m1,	$nj	! nhi=nj
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	stxa	$lo1,	[$tp]0xe2	! tp[j-1]
Packit c4476c
	add	$tp,	8,	$tp	! tp++
Packit c4476c
Packit c4476c
	brnz,pt	$cnt,	.L1st
Packit c4476c
	sub	$cnt,	8,	$cnt	! j--
Packit c4476c
!.L1st
Packit c4476c
	addcc	$alo,	$hi0,	$lo0
Packit c4476c
	addxc	$aj,	%g0,	$hi0	! ahi=aj
Packit c4476c
Packit c4476c
	addcc	$nlo,	$hi1,	$lo1
Packit c4476c
	addxc	$nj,	%g0,	$hi1
Packit c4476c
	addcc	$lo0,	$lo1,	$lo1	! np[j]*m1+ap[j]*bp[0]
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	stxa	$lo1,	[$tp]0xe2	! tp[j-1]
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c
Packit c4476c
	addcc	$hi0,	$hi1,	$hi1
Packit c4476c
	addxc	%g0,	%g0,	$ovf	! upmost overflow bit
Packit c4476c
	stxa	$hi1,	[$tp]0xe2
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c

Packit c4476c
	ba	.Louter
Packit c4476c
	sub	$num,	16,	$i	! i=num-2
Packit c4476c
Packit c4476c
.align	16
Packit c4476c
.Louter:
Packit c4476c
	ldx	[$bp+0],	$m0	! m0=bp[i]
Packit c4476c
	add	$bp,	8,	$bp
Packit c4476c
Packit c4476c
	sub	$ap,	$num,	$ap	! rewind
Packit c4476c
	sub	$np,	$num,	$np
Packit c4476c
	sub	$tp,	$num,	$tp
Packit c4476c
Packit c4476c
	ldx	[$ap+0],	$aj	! ap[0]
Packit c4476c
	ldx	[$np+0],	$nj	! np[0]
Packit c4476c
Packit c4476c
	mulx	$aj,	$m0,	$lo0	! ap[0]*bp[i]
Packit c4476c
	ldx	[$tp],		$tj	! tp[0]
Packit c4476c
	umulxhi	$aj,	$m0,	$hi0
Packit c4476c
	ldx	[$ap+8],	$aj	! ap[1]
Packit c4476c
	addcc	$lo0,	$tj,	$lo0	! ap[0]*bp[i]+tp[0]
Packit c4476c
	mulx	$aj,	$m0,	$alo	! ap[1]*bp[i]
Packit c4476c
	addxc	%g0,	$hi0,	$hi0
Packit c4476c
	mulx	$lo0,	$n0,	$m1	! tp[0]*n0
Packit c4476c
	umulxhi	$aj,	$m0,	$aj	! ahi=aj
Packit c4476c
	mulx	$nj,	$m1,	$lo1	! np[0]*m1
Packit c4476c
	add	$ap,	16,	$ap
Packit c4476c
	umulxhi	$nj,	$m1,	$hi1
Packit c4476c
	ldx	[$np+8],	$nj	! np[1]
Packit c4476c
	add	$np,	16,	$np
Packit c4476c
	addcc	$lo1,	$lo0,	$lo1
Packit c4476c
	mulx	$nj,	$m1,	$nlo	! np[1]*m1
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	umulxhi	$nj,	$m1,	$nj	! nhi=nj
Packit c4476c

Packit c4476c
	ba	.Linner
Packit c4476c
	sub	$num,	24,	$cnt	! cnt=num-3
Packit c4476c
.align	16
Packit c4476c
.Linner:
Packit c4476c
	addcc	$alo,	$hi0,	$lo0
Packit c4476c
	ldx	[$tp+8],	$tj	! tp[j]
Packit c4476c
	addxc	$aj,	%g0,	$hi0	! ahi=aj
Packit c4476c
	ldx	[$ap+0],	$aj	! ap[j]
Packit c4476c
	add	$ap,	8,	$ap
Packit c4476c
	addcc	$nlo,	$hi1,	$lo1
Packit c4476c
	mulx	$aj,	$m0,	$alo	! ap[j]*bp[i]
Packit c4476c
	addxc	$nj,	%g0,	$hi1	! nhi=nj
Packit c4476c
	ldx	[$np+0],	$nj	! np[j]
Packit c4476c
	add	$np,	8,	$np
Packit c4476c
	umulxhi	$aj,	$m0,	$aj	! ahi=aj
Packit c4476c
	addcc	$lo0,	$tj,	$lo0	! ap[j]*bp[i]+tp[j]
Packit c4476c
	mulx	$nj,	$m1,	$nlo	! np[j]*m1
Packit c4476c
	addxc	%g0,	$hi0,	$hi0
Packit c4476c
	umulxhi	$nj,	$m1,	$nj	! nhi=nj
Packit c4476c
	addcc	$lo1,	$lo0,	$lo1	! np[j]*m1+ap[j]*bp[i]+tp[j]
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	stx	$lo1,	[$tp]		! tp[j-1]
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c
	brnz,pt	$cnt,	.Linner
Packit c4476c
	sub	$cnt,	8,	$cnt
Packit c4476c
!.Linner
Packit c4476c
	ldx	[$tp+8],	$tj	! tp[j]
Packit c4476c
	addcc	$alo,	$hi0,	$lo0
Packit c4476c
	addxc	$aj,	%g0,	$hi0	! ahi=aj
Packit c4476c
	addcc	$lo0,	$tj,	$lo0	! ap[j]*bp[i]+tp[j]
Packit c4476c
	addxc	%g0,	$hi0,	$hi0
Packit c4476c
Packit c4476c
	addcc	$nlo,	$hi1,	$lo1
Packit c4476c
	addxc	$nj,	%g0,	$hi1	! nhi=nj
Packit c4476c
	addcc	$lo1,	$lo0,	$lo1	! np[j]*m1+ap[j]*bp[i]+tp[j]
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	stx	$lo1,	[$tp]		! tp[j-1]
Packit c4476c
Packit c4476c
	subcc	%g0,	$ovf,	%g0	! move upmost overflow to CCR.xcc
Packit c4476c
	addxccc	$hi1,	$hi0,	$hi1
Packit c4476c
	addxc	%g0,	%g0,	$ovf
Packit c4476c
	stx	$hi1,	[$tp+8]
Packit c4476c
	add	$tp,	16,	$tp
Packit c4476c
Packit c4476c
	brnz,pt	$i,	.Louter
Packit c4476c
	sub	$i,	8,	$i
Packit c4476c

Packit c4476c
	sub	$ap,	$num,	$ap	! rewind
Packit c4476c
	sub	$np,	$num,	$np
Packit c4476c
	sub	$tp,	$num,	$tp
Packit c4476c
	ba	.Lsub
Packit c4476c
	subcc	$num,	8,	$cnt	! cnt=num-1 and clear CCR.xcc
Packit c4476c
Packit c4476c
.align	16
Packit c4476c
.Lsub:
Packit c4476c
	ldx	[$tp],		$tj
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c
	ldx	[$np+0],	$nj
Packit c4476c
	add	$np,	8,	$np
Packit c4476c
	subccc	$tj,	$nj,	$t2	! tp[j]-np[j]
Packit c4476c
	srlx	$tj,	32,	$tj
Packit c4476c
	srlx	$nj,	32,	$nj
Packit c4476c
	subccc	$tj,	$nj,	$t3
Packit c4476c
	add	$rp,	8,	$rp
Packit c4476c
	st	$t2,	[$rp-4]		! reverse order
Packit c4476c
	st	$t3,	[$rp-8]
Packit c4476c
	brnz,pt	$cnt,	.Lsub
Packit c4476c
	sub	$cnt,	8,	$cnt
Packit c4476c
Packit c4476c
	sub	$np,	$num,	$np	! rewind
Packit c4476c
	sub	$tp,	$num,	$tp
Packit c4476c
	sub	$rp,	$num,	$rp
Packit c4476c
Packit c4476c
	subccc	$ovf,	%g0,	$ovf	! handle upmost overflow bit
Packit c4476c
	ba	.Lcopy
Packit c4476c
	sub	$num,	8,	$cnt
Packit c4476c
Packit c4476c
.align	16
Packit c4476c
.Lcopy:					! conditional copy
Packit c4476c
	ldx	[$tp],		$tj
Packit c4476c
	ldx	[$rp+0],	$t2
Packit c4476c
	stx	%g0,	[$tp]		! zap
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c
	movcs	%icc,	$tj,	$t2
Packit c4476c
	stx	$t2,	[$rp+0]
Packit c4476c
	add	$rp,	8,	$rp
Packit c4476c
	brnz	$cnt,	.Lcopy
Packit c4476c
	sub	$cnt,	8,	$cnt
Packit c4476c
Packit c4476c
	mov	1,	%o0
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
.type	bn_mul_mont_t4, #function
Packit c4476c
.size	bn_mul_mont_t4, .-bn_mul_mont_t4
Packit c4476c
___
Packit c4476c

Packit c4476c
# int bn_mul_mont_gather5(
Packit c4476c
$rp="%o0";	# u64 *rp,
Packit c4476c
$ap="%o1";	# const u64 *ap,
Packit c4476c
$bp="%o2";	# const u64 *pwrtbl,
Packit c4476c
$np="%o3";	# const u64 *np,
Packit c4476c
$n0p="%o4";	# const BN_ULONG *n0,
Packit c4476c
$num="%o5";	# int num,	# caller ensures that num is >=3
Packit c4476c
		# int power);
Packit c4476c
$code.=<<___;
Packit c4476c
.globl	bn_mul_mont_gather5_t4
Packit c4476c
.align	32
Packit c4476c
bn_mul_mont_gather5_t4:
Packit c4476c
	add	%sp,	STACK_BIAS,	%g4	! real top of stack
Packit c4476c
	sll	$num,	3,	$num		! size in bytes
Packit c4476c
	add	$num,	63,	%g1
Packit c4476c
	andn	%g1,	63,	%g1		! buffer size rounded up to 64 bytes
Packit c4476c
	sub	%g4,	%g1,	%g1
Packit c4476c
	andn	%g1,	63,	%g1		! align at 64 byte
Packit c4476c
	sub	%g1,	STACK_FRAME,	%g1	! new top of stack
Packit c4476c
	sub	%g1,	%g4,	%g1
Packit c4476c
	LDPTR	[%sp+STACK_7thARG],	%g4	! load power, 7th argument
Packit c4476c
Packit c4476c
	save	%sp,	%g1,	%sp
Packit c4476c
___
Packit c4476c
#	+-------------------------------+<-----	%sp
Packit c4476c
#	.				.
Packit c4476c
#	+-------------------------------+<-----	aligned at 64 bytes
Packit c4476c
#	| __int64 tmp[0]		|
Packit c4476c
#	+-------------------------------+
Packit c4476c
#	.				.
Packit c4476c
#	.				.
Packit c4476c
#	+-------------------------------+<-----	aligned at 64 bytes
Packit c4476c
#	.				.
Packit c4476c
($rp,$ap,$bp,$np,$n0p,$num)=map("%i$_",(0..5));
Packit c4476c
($t0,$t1,$t2,$t3,$cnt,$tp,$bufsz,$ccr)=map("%l$_",(0..7));
Packit c4476c
($ovf,$i)=($t0,$t1);
Packit c4476c
	&load_ccr($bp,"%g4",$ccr);
Packit c4476c
	&load_b($bp,$m0,"%o7");		# m0=bp[0]
Packit c4476c
Packit c4476c
$code.=<<___;
Packit c4476c
	ld	[$n0p+0],	$t0	! pull n0[0..1] value
Packit c4476c
	ld	[$n0p+4],	$t1
Packit c4476c
	add	%sp, STACK_BIAS+STACK_FRAME, $tp
Packit c4476c
	sllx	$t1,	32,	$n0
Packit c4476c
	or	$t0,	$n0,	$n0
Packit c4476c

Packit c4476c
	ldx	[$ap+0],	$aj	! ap[0]
Packit c4476c
Packit c4476c
	mulx	$aj,	$m0,	$lo0	! ap[0]*bp[0]
Packit c4476c
	umulxhi	$aj,	$m0,	$hi0
Packit c4476c
Packit c4476c
	ldx	[$ap+8],	$aj	! ap[1]
Packit c4476c
	add	$ap,	16,	$ap
Packit c4476c
	ldx	[$np+0],	$nj	! np[0]
Packit c4476c
Packit c4476c
	mulx	$lo0,	$n0,	$m1	! "tp[0]"*n0
Packit c4476c
Packit c4476c
	mulx	$aj,	$m0,	$alo	! ap[1]*bp[0]
Packit c4476c
	umulxhi	$aj,	$m0,	$aj	! ahi=aj
Packit c4476c
Packit c4476c
	mulx	$nj,	$m1,	$lo1	! np[0]*m1
Packit c4476c
	umulxhi	$nj,	$m1,	$hi1
Packit c4476c
Packit c4476c
	ldx	[$np+8],	$nj	! np[1]
Packit c4476c
Packit c4476c
	addcc	$lo0,	$lo1,	$lo1
Packit c4476c
	add	$np,	16,	$np
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
Packit c4476c
	mulx	$nj,	$m1,	$nlo	! np[1]*m1
Packit c4476c
	umulxhi	$nj,	$m1,	$nj	! nhi=nj
Packit c4476c

Packit c4476c
	ba	.L1st_g5
Packit c4476c
	sub	$num,	24,	$cnt	! cnt=num-3
Packit c4476c
Packit c4476c
.align	16
Packit c4476c
.L1st_g5:
Packit c4476c
	addcc	$alo,	$hi0,	$lo0
Packit c4476c
	addxc	$aj,	%g0,	$hi0
Packit c4476c
Packit c4476c
	ldx	[$ap+0],	$aj	! ap[j]
Packit c4476c
	addcc	$nlo,	$hi1,	$lo1
Packit c4476c
	add	$ap,	8,	$ap
Packit c4476c
	addxc	$nj,	%g0,	$hi1	! nhi=nj
Packit c4476c
Packit c4476c
	ldx	[$np+0],	$nj	! np[j]
Packit c4476c
	mulx	$aj,	$m0,	$alo	! ap[j]*bp[0]
Packit c4476c
	add	$np,	8,	$np
Packit c4476c
	umulxhi	$aj,	$m0,	$aj	! ahi=aj
Packit c4476c
Packit c4476c
	mulx	$nj,	$m1,	$nlo	! np[j]*m1
Packit c4476c
	addcc	$lo0,	$lo1,	$lo1	! np[j]*m1+ap[j]*bp[0]
Packit c4476c
	umulxhi	$nj,	$m1,	$nj	! nhi=nj
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	stxa	$lo1,	[$tp]0xe2	! tp[j-1]
Packit c4476c
	add	$tp,	8,	$tp	! tp++
Packit c4476c
Packit c4476c
	brnz,pt	$cnt,	.L1st_g5
Packit c4476c
	sub	$cnt,	8,	$cnt	! j--
Packit c4476c
!.L1st_g5
Packit c4476c
	addcc	$alo,	$hi0,	$lo0
Packit c4476c
	addxc	$aj,	%g0,	$hi0	! ahi=aj
Packit c4476c
Packit c4476c
	addcc	$nlo,	$hi1,	$lo1
Packit c4476c
	addxc	$nj,	%g0,	$hi1
Packit c4476c
	addcc	$lo0,	$lo1,	$lo1	! np[j]*m1+ap[j]*bp[0]
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	stxa	$lo1,	[$tp]0xe2	! tp[j-1]
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c
Packit c4476c
	addcc	$hi0,	$hi1,	$hi1
Packit c4476c
	addxc	%g0,	%g0,	$ovf	! upmost overflow bit
Packit c4476c
	stxa	$hi1,	[$tp]0xe2
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c

Packit c4476c
	ba	.Louter_g5
Packit c4476c
	sub	$num,	16,	$i	! i=num-2
Packit c4476c
Packit c4476c
.align	16
Packit c4476c
.Louter_g5:
Packit c4476c
	wr	$ccr,	%g0,	%ccr
Packit c4476c
___
Packit c4476c
	&load_b($bp,$m0);		# m0=bp[i]
Packit c4476c
$code.=<<___;
Packit c4476c
	sub	$ap,	$num,	$ap	! rewind
Packit c4476c
	sub	$np,	$num,	$np
Packit c4476c
	sub	$tp,	$num,	$tp
Packit c4476c
Packit c4476c
	ldx	[$ap+0],	$aj	! ap[0]
Packit c4476c
	ldx	[$np+0],	$nj	! np[0]
Packit c4476c
Packit c4476c
	mulx	$aj,	$m0,	$lo0	! ap[0]*bp[i]
Packit c4476c
	ldx	[$tp],		$tj	! tp[0]
Packit c4476c
	umulxhi	$aj,	$m0,	$hi0
Packit c4476c
	ldx	[$ap+8],	$aj	! ap[1]
Packit c4476c
	addcc	$lo0,	$tj,	$lo0	! ap[0]*bp[i]+tp[0]
Packit c4476c
	mulx	$aj,	$m0,	$alo	! ap[1]*bp[i]
Packit c4476c
	addxc	%g0,	$hi0,	$hi0
Packit c4476c
	mulx	$lo0,	$n0,	$m1	! tp[0]*n0
Packit c4476c
	umulxhi	$aj,	$m0,	$aj	! ahi=aj
Packit c4476c
	mulx	$nj,	$m1,	$lo1	! np[0]*m1
Packit c4476c
	add	$ap,	16,	$ap
Packit c4476c
	umulxhi	$nj,	$m1,	$hi1
Packit c4476c
	ldx	[$np+8],	$nj	! np[1]
Packit c4476c
	add	$np,	16,	$np
Packit c4476c
	addcc	$lo1,	$lo0,	$lo1
Packit c4476c
	mulx	$nj,	$m1,	$nlo	! np[1]*m1
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	umulxhi	$nj,	$m1,	$nj	! nhi=nj
Packit c4476c

Packit c4476c
	ba	.Linner_g5
Packit c4476c
	sub	$num,	24,	$cnt	! cnt=num-3
Packit c4476c
.align	16
Packit c4476c
.Linner_g5:
Packit c4476c
	addcc	$alo,	$hi0,	$lo0
Packit c4476c
	ldx	[$tp+8],	$tj	! tp[j]
Packit c4476c
	addxc	$aj,	%g0,	$hi0	! ahi=aj
Packit c4476c
	ldx	[$ap+0],	$aj	! ap[j]
Packit c4476c
	add	$ap,	8,	$ap
Packit c4476c
	addcc	$nlo,	$hi1,	$lo1
Packit c4476c
	mulx	$aj,	$m0,	$alo	! ap[j]*bp[i]
Packit c4476c
	addxc	$nj,	%g0,	$hi1	! nhi=nj
Packit c4476c
	ldx	[$np+0],	$nj	! np[j]
Packit c4476c
	add	$np,	8,	$np
Packit c4476c
	umulxhi	$aj,	$m0,	$aj	! ahi=aj
Packit c4476c
	addcc	$lo0,	$tj,	$lo0	! ap[j]*bp[i]+tp[j]
Packit c4476c
	mulx	$nj,	$m1,	$nlo	! np[j]*m1
Packit c4476c
	addxc	%g0,	$hi0,	$hi0
Packit c4476c
	umulxhi	$nj,	$m1,	$nj	! nhi=nj
Packit c4476c
	addcc	$lo1,	$lo0,	$lo1	! np[j]*m1+ap[j]*bp[i]+tp[j]
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	stx	$lo1,	[$tp]		! tp[j-1]
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c
	brnz,pt	$cnt,	.Linner_g5
Packit c4476c
	sub	$cnt,	8,	$cnt
Packit c4476c
!.Linner_g5
Packit c4476c
	ldx	[$tp+8],	$tj	! tp[j]
Packit c4476c
	addcc	$alo,	$hi0,	$lo0
Packit c4476c
	addxc	$aj,	%g0,	$hi0	! ahi=aj
Packit c4476c
	addcc	$lo0,	$tj,	$lo0	! ap[j]*bp[i]+tp[j]
Packit c4476c
	addxc	%g0,	$hi0,	$hi0
Packit c4476c
Packit c4476c
	addcc	$nlo,	$hi1,	$lo1
Packit c4476c
	addxc	$nj,	%g0,	$hi1	! nhi=nj
Packit c4476c
	addcc	$lo1,	$lo0,	$lo1	! np[j]*m1+ap[j]*bp[i]+tp[j]
Packit c4476c
	addxc	%g0,	$hi1,	$hi1
Packit c4476c
	stx	$lo1,	[$tp]		! tp[j-1]
Packit c4476c
Packit c4476c
	subcc	%g0,	$ovf,	%g0	! move upmost overflow to CCR.xcc
Packit c4476c
	addxccc	$hi1,	$hi0,	$hi1
Packit c4476c
	addxc	%g0,	%g0,	$ovf
Packit c4476c
	stx	$hi1,	[$tp+8]
Packit c4476c
	add	$tp,	16,	$tp
Packit c4476c
Packit c4476c
	brnz,pt	$i,	.Louter_g5
Packit c4476c
	sub	$i,	8,	$i
Packit c4476c

Packit c4476c
	sub	$ap,	$num,	$ap	! rewind
Packit c4476c
	sub	$np,	$num,	$np
Packit c4476c
	sub	$tp,	$num,	$tp
Packit c4476c
	ba	.Lsub_g5
Packit c4476c
	subcc	$num,	8,	$cnt	! cnt=num-1 and clear CCR.xcc
Packit c4476c
Packit c4476c
.align	16
Packit c4476c
.Lsub_g5:
Packit c4476c
	ldx	[$tp],		$tj
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c
	ldx	[$np+0],	$nj
Packit c4476c
	add	$np,	8,	$np
Packit c4476c
	subccc	$tj,	$nj,	$t2	! tp[j]-np[j]
Packit c4476c
	srlx	$tj,	32,	$tj
Packit c4476c
	srlx	$nj,	32,	$nj
Packit c4476c
	subccc	$tj,	$nj,	$t3
Packit c4476c
	add	$rp,	8,	$rp
Packit c4476c
	st	$t2,	[$rp-4]		! reverse order
Packit c4476c
	st	$t3,	[$rp-8]
Packit c4476c
	brnz,pt	$cnt,	.Lsub_g5
Packit c4476c
	sub	$cnt,	8,	$cnt
Packit c4476c
Packit c4476c
	sub	$np,	$num,	$np	! rewind
Packit c4476c
	sub	$tp,	$num,	$tp
Packit c4476c
	sub	$rp,	$num,	$rp
Packit c4476c
Packit c4476c
	subccc	$ovf,	%g0,	$ovf	! handle upmost overflow bit
Packit c4476c
	ba	.Lcopy_g5
Packit c4476c
	sub	$num,	8,	$cnt
Packit c4476c
Packit c4476c
.align	16
Packit c4476c
.Lcopy_g5:				! conditional copy
Packit c4476c
	ldx	[$tp],		$tj
Packit c4476c
	ldx	[$rp+0],	$t2
Packit c4476c
	stx	%g0,	[$tp]		! zap
Packit c4476c
	add	$tp,	8,	$tp
Packit c4476c
	movcs	%icc,	$tj,	$t2
Packit c4476c
	stx	$t2,	[$rp+0]
Packit c4476c
	add	$rp,	8,	$rp
Packit c4476c
	brnz	$cnt,	.Lcopy_g5
Packit c4476c
	sub	$cnt,	8,	$cnt
Packit c4476c
Packit c4476c
	mov	1,	%o0
Packit c4476c
	ret
Packit c4476c
	restore
Packit c4476c
.type	bn_mul_mont_gather5_t4, #function
Packit c4476c
.size	bn_mul_mont_gather5_t4, .-bn_mul_mont_gather5_t4
Packit c4476c
___
Packit c4476c
}
Packit c4476c

Packit c4476c
$code.=<<___;
Packit c4476c
.globl	bn_flip_t4
Packit c4476c
.align	32
Packit c4476c
bn_flip_t4:
Packit c4476c
.Loop_flip:
Packit c4476c
	ld	[%o1+0],	%o4
Packit c4476c
	sub	%o2,	1,	%o2
Packit c4476c
	ld	[%o1+4],	%o5
Packit c4476c
	add	%o1,	8,	%o1
Packit c4476c
	st	%o5,	[%o0+0]
Packit c4476c
	st	%o4,	[%o0+4]
Packit c4476c
	brnz	%o2,	.Loop_flip
Packit c4476c
	add	%o0,	8,	%o0
Packit c4476c
	retl
Packit c4476c
	nop
Packit c4476c
.type	bn_flip_t4, #function
Packit c4476c
.size	bn_flip_t4, .-bn_flip_t4
Packit c4476c
Packit c4476c
.globl	bn_flip_n_scatter5_t4
Packit c4476c
.align	32
Packit c4476c
bn_flip_n_scatter5_t4:
Packit c4476c
	sll	%o3,	3,	%o3
Packit c4476c
	srl	%o1,	1,	%o1
Packit c4476c
	add	%o3,	%o2,	%o2	! &pwrtbl[pwr]
Packit c4476c
	sub	%o1,	1,	%o1
Packit c4476c
.Loop_flip_n_scatter5:
Packit c4476c
	ld	[%o0+0],	%o4	! inp[i]
Packit c4476c
	ld	[%o0+4],	%o5
Packit c4476c
	add	%o0,	8,	%o0
Packit c4476c
	sllx	%o5,	32,	%o5
Packit c4476c
	or	%o4,	%o5,	%o5
Packit c4476c
	stx	%o5,	[%o2]
Packit c4476c
	add	%o2,	32*8,	%o2
Packit c4476c
	brnz	%o1,	.Loop_flip_n_scatter5
Packit c4476c
	sub	%o1,	1,	%o1
Packit c4476c
	retl
Packit c4476c
	nop
Packit c4476c
.type	bn_flip_n_scatter5_t4, #function
Packit c4476c
.size	bn_flip_n_scatter5_t4, .-bn_flip_n_scatter5_t4
Packit c4476c
Packit c4476c
.globl	bn_gather5_t4
Packit c4476c
.align	32
Packit c4476c
bn_gather5_t4:
Packit c4476c
___
Packit c4476c
	&load_ccr("%o2","%o3","%g1");
Packit c4476c
$code.=<<___;
Packit c4476c
	sub	%o1,	1,	%o1
Packit c4476c
.Loop_gather5:
Packit c4476c
___
Packit c4476c
	&load_b("%o2","%g1");
Packit c4476c
$code.=<<___;
Packit c4476c
	stx	%g1,	[%o0]
Packit c4476c
	add	%o0,	8,	%o0
Packit c4476c
	brnz	%o1,	.Loop_gather5
Packit c4476c
	sub	%o1,	1,	%o1
Packit c4476c
Packit c4476c
	retl
Packit c4476c
	nop
Packit c4476c
.type	bn_gather5_t4, #function
Packit c4476c
.size	bn_gather5_t4, .-bn_gather5_t4
Packit c4476c
Packit c4476c
.asciz	"Montgomery Multiplication for SPARC T4, David S. Miller, Andy Polyakov"
Packit c4476c
.align	4
Packit c4476c
___
Packit c4476c
Packit c4476c
&emit_assembler();
Packit c4476c
Packit c4476c
close STDOUT or die "error closing STDOUT: $!";