162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2000 Hewlett-Packard Co
462306a36Sopenharmony_ci * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * 32-bit integer division.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * This code is based on the application note entitled "Divide, Square Root
962306a36Sopenharmony_ci * and Remainder Algorithms for the IA-64 Architecture".  This document
1062306a36Sopenharmony_ci * is available as Intel document number 248725-002 or via the web at
1162306a36Sopenharmony_ci * http://developer.intel.com/software/opensource/numerics/
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * For more details on the theory behind these algorithms, see "IA-64
1462306a36Sopenharmony_ci * and Elementary Functions" by Peter Markstein; HP Professional Books
1562306a36Sopenharmony_ci * (http://www.goodreads.com/book/show/2019887.Ia_64_and_Elementary_Functions)
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <linux/export.h>
1962306a36Sopenharmony_ci#include <asm/asmmacro.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#ifdef MODULO
2262306a36Sopenharmony_ci# define OP	mod
2362306a36Sopenharmony_ci#else
2462306a36Sopenharmony_ci# define OP	div
2562306a36Sopenharmony_ci#endif
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#ifdef UNSIGNED
2862306a36Sopenharmony_ci# define SGN	u
2962306a36Sopenharmony_ci# define EXTEND	zxt4
3062306a36Sopenharmony_ci# define INT_TO_FP(a,b)	fcvt.xuf.s1 a=b
3162306a36Sopenharmony_ci# define FP_TO_INT(a,b)	fcvt.fxu.trunc.s1 a=b
3262306a36Sopenharmony_ci#else
3362306a36Sopenharmony_ci# define SGN
3462306a36Sopenharmony_ci# define EXTEND	sxt4
3562306a36Sopenharmony_ci# define INT_TO_FP(a,b)	fcvt.xf a=b
3662306a36Sopenharmony_ci# define FP_TO_INT(a,b)	fcvt.fx.trunc.s1 a=b
3762306a36Sopenharmony_ci#endif
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define PASTE1(a,b)	a##b
4062306a36Sopenharmony_ci#define PASTE(a,b)	PASTE1(a,b)
4162306a36Sopenharmony_ci#define NAME		PASTE(PASTE(__,SGN),PASTE(OP,si3))
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ciGLOBAL_ENTRY(NAME)
4462306a36Sopenharmony_ci	.regstk 2,0,0,0
4562306a36Sopenharmony_ci	// Transfer inputs to FP registers.
4662306a36Sopenharmony_ci	mov r2 = 0xffdd			// r2 = -34 + 65535 (fp reg format bias)
4762306a36Sopenharmony_ci	EXTEND in0 = in0		// in0 = a
4862306a36Sopenharmony_ci	EXTEND in1 = in1		// in1 = b
4962306a36Sopenharmony_ci	;;
5062306a36Sopenharmony_ci	setf.sig f8 = in0
5162306a36Sopenharmony_ci	setf.sig f9 = in1
5262306a36Sopenharmony_ci#ifdef MODULO
5362306a36Sopenharmony_ci	sub in1 = r0, in1		// in1 = -b
5462306a36Sopenharmony_ci#endif
5562306a36Sopenharmony_ci	;;
5662306a36Sopenharmony_ci	// Convert the inputs to FP, to avoid FP software-assist faults.
5762306a36Sopenharmony_ci	INT_TO_FP(f8, f8)
5862306a36Sopenharmony_ci	INT_TO_FP(f9, f9)
5962306a36Sopenharmony_ci	;;
6062306a36Sopenharmony_ci	setf.exp f7 = r2		// f7 = 2^-34
6162306a36Sopenharmony_ci	frcpa.s1 f6, p6 = f8, f9	// y0 = frcpa(b)
6262306a36Sopenharmony_ci	;;
6362306a36Sopenharmony_ci(p6)	fmpy.s1 f8 = f8, f6		// q0 = a*y0
6462306a36Sopenharmony_ci(p6)	fnma.s1 f6 = f9, f6, f1		// e0 = -b*y0 + 1
6562306a36Sopenharmony_ci	;;
6662306a36Sopenharmony_ci#ifdef MODULO
6762306a36Sopenharmony_ci	setf.sig f9 = in1		// f9 = -b
6862306a36Sopenharmony_ci#endif
6962306a36Sopenharmony_ci(p6)	fma.s1 f8 = f6, f8, f8		// q1 = e0*q0 + q0
7062306a36Sopenharmony_ci(p6)	fma.s1 f6 = f6, f6, f7		// e1 = e0*e0 + 2^-34
7162306a36Sopenharmony_ci	;;
7262306a36Sopenharmony_ci#ifdef MODULO
7362306a36Sopenharmony_ci	setf.sig f7 = in0
7462306a36Sopenharmony_ci#endif
7562306a36Sopenharmony_ci(p6)	fma.s1 f6 = f6, f8, f8		// q2 = e1*q1 + q1
7662306a36Sopenharmony_ci	;;
7762306a36Sopenharmony_ci	FP_TO_INT(f6, f6)		// q = trunc(q2)
7862306a36Sopenharmony_ci	;;
7962306a36Sopenharmony_ci#ifdef MODULO
8062306a36Sopenharmony_ci	xma.l f6 = f6, f9, f7		// r = q*(-b) + a
8162306a36Sopenharmony_ci	;;
8262306a36Sopenharmony_ci#endif
8362306a36Sopenharmony_ci	getf.sig r8 = f6		// transfer result to result register
8462306a36Sopenharmony_ci	br.ret.sptk.many rp
8562306a36Sopenharmony_ciEND(NAME)
8662306a36Sopenharmony_ciEXPORT_SYMBOL(NAME)
87