xref: /freebsd-src/crypto/openssl/crypto/poly1305/asm/poly1305-mips.pl (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
1e71b7053SJung-uk Kim#! /usr/bin/env perl
217f01e99SJung-uk Kim# Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim#
4*b077aed3SPierre Pronchery# Licensed under the Apache License 2.0 (the "License").  You may not use
5e71b7053SJung-uk Kim# this file except in compliance with the License.  You can obtain a copy
6e71b7053SJung-uk Kim# in the file LICENSE in the source distribution or at
7e71b7053SJung-uk Kim# https://www.openssl.org/source/license.html
8e71b7053SJung-uk Kim
9e71b7053SJung-uk Kim
10e71b7053SJung-uk Kim# ====================================================================
11e71b7053SJung-uk Kim# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
12e71b7053SJung-uk Kim# project. The module is, however, dual licensed under OpenSSL and
13e71b7053SJung-uk Kim# CRYPTOGAMS licenses depending on where you obtain it. For further
14e71b7053SJung-uk Kim# details see http://www.openssl.org/~appro/cryptogams/.
15e71b7053SJung-uk Kim# ====================================================================
16e71b7053SJung-uk Kim
17e71b7053SJung-uk Kim# Poly1305 hash for MIPS64.
18e71b7053SJung-uk Kim#
19e71b7053SJung-uk Kim# May 2016
20e71b7053SJung-uk Kim#
21e71b7053SJung-uk Kim# Numbers are cycles per processed byte with poly1305_blocks alone.
22e71b7053SJung-uk Kim#
23e71b7053SJung-uk Kim#		IALU/gcc
24e71b7053SJung-uk Kim# R1x000	5.64/+120%	(big-endian)
25e71b7053SJung-uk Kim# Octeon II	3.80/+280%	(little-endian)
26e71b7053SJung-uk Kim
27e71b7053SJung-uk Kim######################################################################
28e71b7053SJung-uk Kim# There is a number of MIPS ABI in use, O32 and N32/64 are most
29e71b7053SJung-uk Kim# widely used. Then there is a new contender: NUBI. It appears that if
30e71b7053SJung-uk Kim# one picks the latter, it's possible to arrange code in ABI neutral
31e71b7053SJung-uk Kim# manner. Therefore let's stick to NUBI register layout:
32e71b7053SJung-uk Kim#
33e71b7053SJung-uk Kim($zero,$at,$t0,$t1,$t2)=map("\$$_",(0..2,24,25));
34e71b7053SJung-uk Kim($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11));
35e71b7053SJung-uk Kim($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7,$s8,$s9,$s10,$s11)=map("\$$_",(12..23));
36e71b7053SJung-uk Kim($gp,$tp,$sp,$fp,$ra)=map("\$$_",(3,28..31));
37e71b7053SJung-uk Kim#
38e71b7053SJung-uk Kim# The return value is placed in $a0. Following coding rules facilitate
39e71b7053SJung-uk Kim# interoperability:
40e71b7053SJung-uk Kim#
41e71b7053SJung-uk Kim# - never ever touch $tp, "thread pointer", former $gp [o32 can be
42e71b7053SJung-uk Kim#   excluded from the rule, because it's specified volatile];
43e71b7053SJung-uk Kim# - copy return value to $t0, former $v0 [or to $a0 if you're adapting
44e71b7053SJung-uk Kim#   old code];
45e71b7053SJung-uk Kim# - on O32 populate $a4-$a7 with 'lw $aN,4*N($sp)' if necessary;
46e71b7053SJung-uk Kim#
47e71b7053SJung-uk Kim# For reference here is register layout for N32/64 MIPS ABIs:
48e71b7053SJung-uk Kim#
49e71b7053SJung-uk Kim# ($zero,$at,$v0,$v1)=map("\$$_",(0..3));
50e71b7053SJung-uk Kim# ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11));
51e71b7053SJung-uk Kim# ($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25));
52e71b7053SJung-uk Kim# ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23));
53e71b7053SJung-uk Kim# ($gp,$sp,$fp,$ra)=map("\$$_",(28..31));
54e71b7053SJung-uk Kim#
55e71b7053SJung-uk Kim# <appro@openssl.org>
56e71b7053SJung-uk Kim#
57e71b7053SJung-uk Kim######################################################################
58e71b7053SJung-uk Kim
59*b077aed3SPierre Pronchery# $output is the last argument if it looks like a file (it has an extension)
60*b077aed3SPierre Pronchery# $flavour is the first argument if it doesn't look like a file
61*b077aed3SPierre Pronchery$output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef;
62*b077aed3SPierre Pronchery# supported flavours are o32,n32,64,nubi32,nubi64, default is o32
63*b077aed3SPierre Pronchery$flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : "o32";
64e71b7053SJung-uk Kim
65e71b7053SJung-uk Kimdie "MIPS64 only" unless ($flavour =~ /64|n32/i);
66e71b7053SJung-uk Kim
67e71b7053SJung-uk Kim$v0 = ($flavour =~ /nubi/i) ? $a0 : $t0;
68e71b7053SJung-uk Kim$SAVED_REGS_MASK = ($flavour =~ /nubi/i) ? "0x0003f000" : "0x00030000";
69e71b7053SJung-uk Kim
70e71b7053SJung-uk Kim($ctx,$inp,$len,$padbit) = ($a0,$a1,$a2,$a3);
71e71b7053SJung-uk Kim($in0,$in1,$tmp0,$tmp1,$tmp2,$tmp3,$tmp4) = ($a4,$a5,$a6,$a7,$at,$t0,$t1);
72e71b7053SJung-uk Kim
73e71b7053SJung-uk Kim$code.=<<___;
74e71b7053SJung-uk Kim#include "mips_arch.h"
75e71b7053SJung-uk Kim
76e71b7053SJung-uk Kim#ifdef MIPSEB
77e71b7053SJung-uk Kim# define MSB 0
78e71b7053SJung-uk Kim# define LSB 7
79e71b7053SJung-uk Kim#else
80e71b7053SJung-uk Kim# define MSB 7
81e71b7053SJung-uk Kim# define LSB 0
82e71b7053SJung-uk Kim#endif
83e71b7053SJung-uk Kim
84e71b7053SJung-uk Kim.text
85e71b7053SJung-uk Kim.set	noat
86e71b7053SJung-uk Kim.set	noreorder
87e71b7053SJung-uk Kim
88e71b7053SJung-uk Kim.align	5
89e71b7053SJung-uk Kim.globl	poly1305_init
90e71b7053SJung-uk Kim.ent	poly1305_init
91e71b7053SJung-uk Kimpoly1305_init:
92e71b7053SJung-uk Kim	.frame	$sp,0,$ra
93e71b7053SJung-uk Kim	.set	reorder
94e71b7053SJung-uk Kim
95e71b7053SJung-uk Kim	sd	$zero,0($ctx)
96e71b7053SJung-uk Kim	sd	$zero,8($ctx)
97e71b7053SJung-uk Kim	sd	$zero,16($ctx)
98e71b7053SJung-uk Kim
99e71b7053SJung-uk Kim	beqz	$inp,.Lno_key
100e71b7053SJung-uk Kim
101e71b7053SJung-uk Kim#if defined(_MIPS_ARCH_MIPS64R6)
102e71b7053SJung-uk Kim	ld	$in0,0($inp)
103e71b7053SJung-uk Kim	ld	$in1,8($inp)
104e71b7053SJung-uk Kim#else
105e71b7053SJung-uk Kim	ldl	$in0,0+MSB($inp)
106e71b7053SJung-uk Kim	ldl	$in1,8+MSB($inp)
107e71b7053SJung-uk Kim	ldr	$in0,0+LSB($inp)
108e71b7053SJung-uk Kim	ldr	$in1,8+LSB($inp)
109e71b7053SJung-uk Kim#endif
110e71b7053SJung-uk Kim#ifdef	MIPSEB
111e71b7053SJung-uk Kim# if defined(_MIPS_ARCH_MIPS64R2)
112e71b7053SJung-uk Kim	dsbh	$in0,$in0		# byte swap
113e71b7053SJung-uk Kim	 dsbh	$in1,$in1
114e71b7053SJung-uk Kim	dshd	$in0,$in0
115e71b7053SJung-uk Kim	 dshd	$in1,$in1
116e71b7053SJung-uk Kim# else
117e71b7053SJung-uk Kim	ori	$tmp0,$zero,0xFF
118e71b7053SJung-uk Kim	dsll	$tmp2,$tmp0,32
119e71b7053SJung-uk Kim	or	$tmp0,$tmp2		# 0x000000FF000000FF
120e71b7053SJung-uk Kim
121e71b7053SJung-uk Kim	and	$tmp1,$in0,$tmp0	# byte swap
122e71b7053SJung-uk Kim	 and	$tmp3,$in1,$tmp0
123e71b7053SJung-uk Kim	dsrl	$tmp2,$in0,24
124e71b7053SJung-uk Kim	 dsrl	$tmp4,$in1,24
125e71b7053SJung-uk Kim	dsll	$tmp1,24
126e71b7053SJung-uk Kim	 dsll	$tmp3,24
127e71b7053SJung-uk Kim	and	$tmp2,$tmp0
128e71b7053SJung-uk Kim	 and	$tmp4,$tmp0
129e71b7053SJung-uk Kim	dsll	$tmp0,8			# 0x0000FF000000FF00
130e71b7053SJung-uk Kim	or	$tmp1,$tmp2
131e71b7053SJung-uk Kim	 or	$tmp3,$tmp4
132e71b7053SJung-uk Kim	and	$tmp2,$in0,$tmp0
133e71b7053SJung-uk Kim	 and	$tmp4,$in1,$tmp0
134e71b7053SJung-uk Kim	dsrl	$in0,8
135e71b7053SJung-uk Kim	 dsrl	$in1,8
136e71b7053SJung-uk Kim	dsll	$tmp2,8
137e71b7053SJung-uk Kim	 dsll	$tmp4,8
138e71b7053SJung-uk Kim	and	$in0,$tmp0
139e71b7053SJung-uk Kim	 and	$in1,$tmp0
140e71b7053SJung-uk Kim	or	$tmp1,$tmp2
141e71b7053SJung-uk Kim	 or	$tmp3,$tmp4
142e71b7053SJung-uk Kim	or	$in0,$tmp1
143e71b7053SJung-uk Kim	 or	$in1,$tmp3
144e71b7053SJung-uk Kim	dsrl	$tmp1,$in0,32
145e71b7053SJung-uk Kim	 dsrl	$tmp3,$in1,32
146e71b7053SJung-uk Kim	dsll	$in0,32
147e71b7053SJung-uk Kim	 dsll	$in1,32
148e71b7053SJung-uk Kim	or	$in0,$tmp1
149e71b7053SJung-uk Kim	 or	$in1,$tmp3
150e71b7053SJung-uk Kim# endif
151e71b7053SJung-uk Kim#endif
152e71b7053SJung-uk Kim	li	$tmp0,1
153e71b7053SJung-uk Kim	dsll	$tmp0,32
154e71b7053SJung-uk Kim	daddiu	$tmp0,-63
155e71b7053SJung-uk Kim	dsll	$tmp0,28
156e71b7053SJung-uk Kim	daddiu	$tmp0,-1		# 0ffffffc0fffffff
157e71b7053SJung-uk Kim
158e71b7053SJung-uk Kim	and	$in0,$tmp0
159e71b7053SJung-uk Kim	daddiu	$tmp0,-3		# 0ffffffc0ffffffc
160e71b7053SJung-uk Kim	and	$in1,$tmp0
161e71b7053SJung-uk Kim
162e71b7053SJung-uk Kim	sd	$in0,24($ctx)
163e71b7053SJung-uk Kim	dsrl	$tmp0,$in1,2
164e71b7053SJung-uk Kim	sd	$in1,32($ctx)
165e71b7053SJung-uk Kim	daddu	$tmp0,$in1		# s1 = r1 + (r1 >> 2)
166e71b7053SJung-uk Kim	sd	$tmp0,40($ctx)
167e71b7053SJung-uk Kim
168e71b7053SJung-uk Kim.Lno_key:
169e71b7053SJung-uk Kim	li	$v0,0			# return 0
170e71b7053SJung-uk Kim	jr	$ra
171e71b7053SJung-uk Kim.end	poly1305_init
172e71b7053SJung-uk Kim___
173e71b7053SJung-uk Kim{
174e71b7053SJung-uk Kimmy ($h0,$h1,$h2,$r0,$r1,$s1,$d0,$d1,$d2) =
175e71b7053SJung-uk Kim   ($s0,$s1,$s2,$s3,$s4,$s5,$in0,$in1,$t2);
176e71b7053SJung-uk Kim
177e71b7053SJung-uk Kim$code.=<<___;
178e71b7053SJung-uk Kim.align	5
179e71b7053SJung-uk Kim.globl	poly1305_blocks
180e71b7053SJung-uk Kim.ent	poly1305_blocks
181e71b7053SJung-uk Kimpoly1305_blocks:
182e71b7053SJung-uk Kim	.set	noreorder
183e71b7053SJung-uk Kim	dsrl	$len,4			# number of complete blocks
184e71b7053SJung-uk Kim	bnez	$len,poly1305_blocks_internal
185e71b7053SJung-uk Kim	nop
186e71b7053SJung-uk Kim	jr	$ra
187e71b7053SJung-uk Kim	nop
188e71b7053SJung-uk Kim.end	poly1305_blocks
189e71b7053SJung-uk Kim
190e71b7053SJung-uk Kim.align	5
191e71b7053SJung-uk Kim.ent	poly1305_blocks_internal
192e71b7053SJung-uk Kimpoly1305_blocks_internal:
193e71b7053SJung-uk Kim	.frame	$sp,6*8,$ra
194e71b7053SJung-uk Kim	.mask	$SAVED_REGS_MASK,-8
195e71b7053SJung-uk Kim	.set	noreorder
196e71b7053SJung-uk Kim	dsubu	$sp,6*8
197e71b7053SJung-uk Kim	sd	$s5,40($sp)
198e71b7053SJung-uk Kim	sd	$s4,32($sp)
199e71b7053SJung-uk Kim___
200e71b7053SJung-uk Kim$code.=<<___ if ($flavour =~ /nubi/i);	# optimize non-nubi prologue
201e71b7053SJung-uk Kim	sd	$s3,24($sp)
202e71b7053SJung-uk Kim	sd	$s2,16($sp)
203e71b7053SJung-uk Kim	sd	$s1,8($sp)
204e71b7053SJung-uk Kim	sd	$s0,0($sp)
205e71b7053SJung-uk Kim___
206e71b7053SJung-uk Kim$code.=<<___;
207e71b7053SJung-uk Kim	.set	reorder
208e71b7053SJung-uk Kim
209e71b7053SJung-uk Kim	ld	$h0,0($ctx)		# load hash value
210e71b7053SJung-uk Kim	ld	$h1,8($ctx)
211e71b7053SJung-uk Kim	ld	$h2,16($ctx)
212e71b7053SJung-uk Kim
213e71b7053SJung-uk Kim	ld	$r0,24($ctx)		# load key
214e71b7053SJung-uk Kim	ld	$r1,32($ctx)
215e71b7053SJung-uk Kim	ld	$s1,40($ctx)
216e71b7053SJung-uk Kim
217e71b7053SJung-uk Kim.Loop:
218e71b7053SJung-uk Kim#if defined(_MIPS_ARCH_MIPS64R6)
219e71b7053SJung-uk Kim	ld	$in0,0($inp)		# load input
220e71b7053SJung-uk Kim	ld	$in1,8($inp)
221e71b7053SJung-uk Kim#else
222e71b7053SJung-uk Kim	ldl	$in0,0+MSB($inp)	# load input
223e71b7053SJung-uk Kim	ldl	$in1,8+MSB($inp)
224e71b7053SJung-uk Kim	ldr	$in0,0+LSB($inp)
225e71b7053SJung-uk Kim	ldr	$in1,8+LSB($inp)
226e71b7053SJung-uk Kim#endif
227e71b7053SJung-uk Kim	daddiu	$len,-1
228e71b7053SJung-uk Kim	daddiu	$inp,16
229e71b7053SJung-uk Kim#ifdef	MIPSEB
230e71b7053SJung-uk Kim# if defined(_MIPS_ARCH_MIPS64R2)
231e71b7053SJung-uk Kim	dsbh	$in0,$in0		# byte swap
232e71b7053SJung-uk Kim	 dsbh	$in1,$in1
233e71b7053SJung-uk Kim	dshd	$in0,$in0
234e71b7053SJung-uk Kim	 dshd	$in1,$in1
235e71b7053SJung-uk Kim# else
236e71b7053SJung-uk Kim	ori	$tmp0,$zero,0xFF
237e71b7053SJung-uk Kim	dsll	$tmp2,$tmp0,32
238e71b7053SJung-uk Kim	or	$tmp0,$tmp2		# 0x000000FF000000FF
239e71b7053SJung-uk Kim
240e71b7053SJung-uk Kim	and	$tmp1,$in0,$tmp0	# byte swap
241e71b7053SJung-uk Kim	 and	$tmp3,$in1,$tmp0
242e71b7053SJung-uk Kim	dsrl	$tmp2,$in0,24
243e71b7053SJung-uk Kim	 dsrl	$tmp4,$in1,24
244e71b7053SJung-uk Kim	dsll	$tmp1,24
245e71b7053SJung-uk Kim	 dsll	$tmp3,24
246e71b7053SJung-uk Kim	and	$tmp2,$tmp0
247e71b7053SJung-uk Kim	 and	$tmp4,$tmp0
248e71b7053SJung-uk Kim	dsll	$tmp0,8			# 0x0000FF000000FF00
249e71b7053SJung-uk Kim	or	$tmp1,$tmp2
250e71b7053SJung-uk Kim	 or	$tmp3,$tmp4
251e71b7053SJung-uk Kim	and	$tmp2,$in0,$tmp0
252e71b7053SJung-uk Kim	 and	$tmp4,$in1,$tmp0
253e71b7053SJung-uk Kim	dsrl	$in0,8
254e71b7053SJung-uk Kim	 dsrl	$in1,8
255e71b7053SJung-uk Kim	dsll	$tmp2,8
256e71b7053SJung-uk Kim	 dsll	$tmp4,8
257e71b7053SJung-uk Kim	and	$in0,$tmp0
258e71b7053SJung-uk Kim	 and	$in1,$tmp0
259e71b7053SJung-uk Kim	or	$tmp1,$tmp2
260e71b7053SJung-uk Kim	 or	$tmp3,$tmp4
261e71b7053SJung-uk Kim	or	$in0,$tmp1
262e71b7053SJung-uk Kim	 or	$in1,$tmp3
263e71b7053SJung-uk Kim	dsrl	$tmp1,$in0,32
264e71b7053SJung-uk Kim	 dsrl	$tmp3,$in1,32
265e71b7053SJung-uk Kim	dsll	$in0,32
266e71b7053SJung-uk Kim	 dsll	$in1,32
267e71b7053SJung-uk Kim	or	$in0,$tmp1
268e71b7053SJung-uk Kim	 or	$in1,$tmp3
269e71b7053SJung-uk Kim# endif
270e71b7053SJung-uk Kim#endif
271e71b7053SJung-uk Kim	daddu	$h0,$in0		# accumulate input
272e71b7053SJung-uk Kim	daddu	$h1,$in1
273e71b7053SJung-uk Kim	sltu	$tmp0,$h0,$in0
274e71b7053SJung-uk Kim	sltu	$tmp1,$h1,$in1
275e71b7053SJung-uk Kim	daddu	$h1,$tmp0
276e71b7053SJung-uk Kim
277e71b7053SJung-uk Kim	dmultu	($r0,$h0)		# h0*r0
278e71b7053SJung-uk Kim	 daddu	$h2,$padbit
279e71b7053SJung-uk Kim	 sltu	$tmp0,$h1,$tmp0
280e71b7053SJung-uk Kim	mflo	($d0,$r0,$h0)
281e71b7053SJung-uk Kim	mfhi	($d1,$r0,$h0)
282e71b7053SJung-uk Kim
283e71b7053SJung-uk Kim	dmultu	($s1,$h1)		# h1*5*r1
284e71b7053SJung-uk Kim	 daddu	$tmp0,$tmp1
285e71b7053SJung-uk Kim	 daddu	$h2,$tmp0
286e71b7053SJung-uk Kim	mflo	($tmp0,$s1,$h1)
287e71b7053SJung-uk Kim	mfhi	($tmp1,$s1,$h1)
288e71b7053SJung-uk Kim
289e71b7053SJung-uk Kim	dmultu	($r1,$h0)		# h0*r1
290e71b7053SJung-uk Kim	 daddu	$d0,$tmp0
291e71b7053SJung-uk Kim	 daddu	$d1,$tmp1
292e71b7053SJung-uk Kim	mflo	($tmp2,$r1,$h0)
293e71b7053SJung-uk Kim	mfhi	($d2,$r1,$h0)
294e71b7053SJung-uk Kim	 sltu	$tmp0,$d0,$tmp0
295e71b7053SJung-uk Kim	 daddu	$d1,$tmp0
296e71b7053SJung-uk Kim
297e71b7053SJung-uk Kim	dmultu	($r0,$h1)		# h1*r0
298e71b7053SJung-uk Kim	 daddu	$d1,$tmp2
299e71b7053SJung-uk Kim	 sltu	$tmp2,$d1,$tmp2
300e71b7053SJung-uk Kim	mflo	($tmp0,$r0,$h1)
301e71b7053SJung-uk Kim	mfhi	($tmp1,$r0,$h1)
302e71b7053SJung-uk Kim	 daddu	$d2,$tmp2
303e71b7053SJung-uk Kim
304e71b7053SJung-uk Kim	dmultu	($s1,$h2)		# h2*5*r1
305e71b7053SJung-uk Kim	 daddu	$d1,$tmp0
306e71b7053SJung-uk Kim	 daddu	$d2,$tmp1
307e71b7053SJung-uk Kim	mflo	($tmp2,$s1,$h2)
308e71b7053SJung-uk Kim
309e71b7053SJung-uk Kim	dmultu	($r0,$h2)		# h2*r0
310e71b7053SJung-uk Kim	 sltu	$tmp0,$d1,$tmp0
311e71b7053SJung-uk Kim	 daddu	$d2,$tmp0
312e71b7053SJung-uk Kim	mflo	($tmp3,$r0,$h2)
313e71b7053SJung-uk Kim
314e71b7053SJung-uk Kim	daddu	$d1,$tmp2
315e71b7053SJung-uk Kim	daddu	$d2,$tmp3
316e71b7053SJung-uk Kim	sltu	$tmp2,$d1,$tmp2
317e71b7053SJung-uk Kim	daddu	$d2,$tmp2
318e71b7053SJung-uk Kim
319e71b7053SJung-uk Kim	li	$tmp0,-4		# final reduction
320e71b7053SJung-uk Kim	and	$tmp0,$d2
321e71b7053SJung-uk Kim	dsrl	$tmp1,$d2,2
322e71b7053SJung-uk Kim	andi	$h2,$d2,3
323e71b7053SJung-uk Kim	daddu	$tmp0,$tmp1
324e71b7053SJung-uk Kim	daddu	$h0,$d0,$tmp0
325e71b7053SJung-uk Kim	sltu	$tmp0,$h0,$tmp0
326e71b7053SJung-uk Kim	daddu	$h1,$d1,$tmp0
327e71b7053SJung-uk Kim	sltu	$tmp0,$h1,$tmp0
328e71b7053SJung-uk Kim	daddu	$h2,$h2,$tmp0
329e71b7053SJung-uk Kim
330e71b7053SJung-uk Kim	bnez	$len,.Loop
331e71b7053SJung-uk Kim
332e71b7053SJung-uk Kim	sd	$h0,0($ctx)		# store hash value
333e71b7053SJung-uk Kim	sd	$h1,8($ctx)
334e71b7053SJung-uk Kim	sd	$h2,16($ctx)
335e71b7053SJung-uk Kim
336e71b7053SJung-uk Kim	.set	noreorder
337e71b7053SJung-uk Kim	ld	$s5,40($sp)		# epilogue
338e71b7053SJung-uk Kim	ld	$s4,32($sp)
339e71b7053SJung-uk Kim___
340e71b7053SJung-uk Kim$code.=<<___ if ($flavour =~ /nubi/i);	# optimize non-nubi epilogue
341e71b7053SJung-uk Kim	ld	$s3,24($sp)
342e71b7053SJung-uk Kim	ld	$s2,16($sp)
343e71b7053SJung-uk Kim	ld	$s1,8($sp)
344e71b7053SJung-uk Kim	ld	$s0,0($sp)
345e71b7053SJung-uk Kim___
346e71b7053SJung-uk Kim$code.=<<___;
347e71b7053SJung-uk Kim	jr	$ra
348e71b7053SJung-uk Kim	daddu	$sp,6*8
349e71b7053SJung-uk Kim.end	poly1305_blocks_internal
350e71b7053SJung-uk Kim___
351e71b7053SJung-uk Kim}
352e71b7053SJung-uk Kim{
353e71b7053SJung-uk Kimmy ($ctx,$mac,$nonce) = ($a0,$a1,$a2);
354e71b7053SJung-uk Kim
355e71b7053SJung-uk Kim$code.=<<___;
356e71b7053SJung-uk Kim.align	5
357e71b7053SJung-uk Kim.globl	poly1305_emit
358e71b7053SJung-uk Kim.ent	poly1305_emit
359e71b7053SJung-uk Kimpoly1305_emit:
360e71b7053SJung-uk Kim	.frame	$sp,0,$ra
361e71b7053SJung-uk Kim	.set	reorder
362e71b7053SJung-uk Kim
363e71b7053SJung-uk Kim	ld	$tmp0,0($ctx)
364e71b7053SJung-uk Kim	ld	$tmp1,8($ctx)
365e71b7053SJung-uk Kim	ld	$tmp2,16($ctx)
366e71b7053SJung-uk Kim
367e71b7053SJung-uk Kim	daddiu	$in0,$tmp0,5		# compare to modulus
368e71b7053SJung-uk Kim	sltiu	$tmp3,$in0,5
369e71b7053SJung-uk Kim	daddu	$in1,$tmp1,$tmp3
370e71b7053SJung-uk Kim	sltu	$tmp3,$in1,$tmp3
371e71b7053SJung-uk Kim	daddu	$tmp2,$tmp2,$tmp3
372e71b7053SJung-uk Kim
373e71b7053SJung-uk Kim	dsrl	$tmp2,2			# see if it carried/borrowed
374e71b7053SJung-uk Kim	dsubu	$tmp2,$zero,$tmp2
375e71b7053SJung-uk Kim	nor	$tmp3,$zero,$tmp2
376e71b7053SJung-uk Kim
377e71b7053SJung-uk Kim	and	$in0,$tmp2
378e71b7053SJung-uk Kim	and	$tmp0,$tmp3
379e71b7053SJung-uk Kim	and	$in1,$tmp2
380e71b7053SJung-uk Kim	and	$tmp1,$tmp3
381e71b7053SJung-uk Kim	or	$in0,$tmp0
382e71b7053SJung-uk Kim	or	$in1,$tmp1
383e71b7053SJung-uk Kim
384e71b7053SJung-uk Kim	lwu	$tmp0,0($nonce)		# load nonce
385e71b7053SJung-uk Kim	lwu	$tmp1,4($nonce)
386e71b7053SJung-uk Kim	lwu	$tmp2,8($nonce)
387e71b7053SJung-uk Kim	lwu	$tmp3,12($nonce)
388e71b7053SJung-uk Kim	dsll	$tmp1,32
389e71b7053SJung-uk Kim	dsll	$tmp3,32
390e71b7053SJung-uk Kim	or	$tmp0,$tmp1
391e71b7053SJung-uk Kim	or	$tmp2,$tmp3
392e71b7053SJung-uk Kim
393e71b7053SJung-uk Kim	daddu	$in0,$tmp0		# accumulate nonce
394e71b7053SJung-uk Kim	daddu	$in1,$tmp2
395e71b7053SJung-uk Kim	sltu	$tmp0,$in0,$tmp0
396e71b7053SJung-uk Kim	daddu	$in1,$tmp0
397e71b7053SJung-uk Kim
398e71b7053SJung-uk Kim	dsrl	$tmp0,$in0,8		# write mac value
399e71b7053SJung-uk Kim	dsrl	$tmp1,$in0,16
400e71b7053SJung-uk Kim	dsrl	$tmp2,$in0,24
401e71b7053SJung-uk Kim	sb	$in0,0($mac)
402e71b7053SJung-uk Kim	dsrl	$tmp3,$in0,32
403e71b7053SJung-uk Kim	sb	$tmp0,1($mac)
404e71b7053SJung-uk Kim	dsrl	$tmp0,$in0,40
405e71b7053SJung-uk Kim	sb	$tmp1,2($mac)
406e71b7053SJung-uk Kim	dsrl	$tmp1,$in0,48
407e71b7053SJung-uk Kim	sb	$tmp2,3($mac)
408e71b7053SJung-uk Kim	dsrl	$tmp2,$in0,56
409e71b7053SJung-uk Kim	sb	$tmp3,4($mac)
410e71b7053SJung-uk Kim	dsrl	$tmp3,$in1,8
411e71b7053SJung-uk Kim	sb	$tmp0,5($mac)
412e71b7053SJung-uk Kim	dsrl	$tmp0,$in1,16
413e71b7053SJung-uk Kim	sb	$tmp1,6($mac)
414e71b7053SJung-uk Kim	dsrl	$tmp1,$in1,24
415e71b7053SJung-uk Kim	sb	$tmp2,7($mac)
416e71b7053SJung-uk Kim
417e71b7053SJung-uk Kim	sb	$in1,8($mac)
418e71b7053SJung-uk Kim	dsrl	$tmp2,$in1,32
419e71b7053SJung-uk Kim	sb	$tmp3,9($mac)
420e71b7053SJung-uk Kim	dsrl	$tmp3,$in1,40
421e71b7053SJung-uk Kim	sb	$tmp0,10($mac)
422e71b7053SJung-uk Kim	dsrl	$tmp0,$in1,48
423e71b7053SJung-uk Kim	sb	$tmp1,11($mac)
424e71b7053SJung-uk Kim	dsrl	$tmp1,$in1,56
425e71b7053SJung-uk Kim	sb	$tmp2,12($mac)
426e71b7053SJung-uk Kim	sb	$tmp3,13($mac)
427e71b7053SJung-uk Kim	sb	$tmp0,14($mac)
428e71b7053SJung-uk Kim	sb	$tmp1,15($mac)
429e71b7053SJung-uk Kim
430e71b7053SJung-uk Kim	jr	$ra
431e71b7053SJung-uk Kim.end	poly1305_emit
432e71b7053SJung-uk Kim.rdata
433e71b7053SJung-uk Kim.asciiz	"Poly1305 for MIPS64, CRYPTOGAMS by <appro\@openssl.org>"
434e71b7053SJung-uk Kim.align	2
435e71b7053SJung-uk Kim___
436e71b7053SJung-uk Kim}
437e71b7053SJung-uk Kim
438*b077aed3SPierre Pronchery$output and open STDOUT,">$output";
439e71b7053SJung-uk Kimprint $code;
44017f01e99SJung-uk Kimclose STDOUT or die "error closing STDOUT: $!";
441e71b7053SJung-uk Kim
442