195604Sjake/*- 295604Sjake * Copyright (c) 2002 Jake Burkholder. 395604Sjake * All rights reserved. 495604Sjake * 595604Sjake * Redistribution and use in source and binary forms, with or without 695604Sjake * modification, are permitted provided that the following conditions 795604Sjake * are met: 895604Sjake * 1. Redistributions of source code must retain the above copyright 995604Sjake * notice, this list of conditions and the following disclaimer. 1095604Sjake * 2. Redistributions in binary form must reproduce the above copyright 1195604Sjake * notice, this list of conditions and the following disclaimer in the 1295604Sjake * documentation and/or other materials provided with the distribution. 1395604Sjake * 1495604Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1595604Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1695604Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1795604Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1895604Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1995604Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2095604Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2195604Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2295604Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2395604Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2495604Sjake * SUCH DAMAGE. 2595604Sjake */ 2695604Sjake 2795604Sjake#include <sys/cdefs.h> 2895604Sjake__FBSDID("$FreeBSD: releng/10.3/lib/libc/sparc64/fpu/fpu_qp.c 178138 2008-04-12 03:09:51Z das $"); 2995604Sjake 3095604Sjake#include <sys/types.h> 3195604Sjake#include <machine/fsr.h> 3295604Sjake 3395604Sjake#include "fpu_emu.h" 3495604Sjake#include "fpu_extern.h" 3595604Sjake 3695604Sjake#define _QP_OP(op) \ 3795604Sjakevoid _Qp_ ## op(u_int *c, u_int *a, u_int *b); \ 3895604Sjakevoid \ 3995604Sjake_Qp_ ## op(u_int *c, u_int *a, u_int *b) \ 4095604Sjake{ \ 4195604Sjake struct fpemu fe; \ 4295604Sjake struct fpn *r; \ 4395604Sjake __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \ 44178138Sdas fe.fe_cx = 0; \ 4595604Sjake fe.fe_f1.fp_sign = a[0] >> 31; \ 4695604Sjake fe.fe_f1.fp_sticky = 0; \ 4795604Sjake fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]); \ 4895604Sjake fe.fe_f2.fp_sign = b[0] >> 31; \ 4995604Sjake fe.fe_f2.fp_sticky = 0; \ 5095604Sjake fe.fe_f2.fp_class = __fpu_qtof(&fe.fe_f2, b[0], b[1], b[2], b[3]); \ 5195604Sjake r = __fpu_ ## op(&fe); \ 5295604Sjake c[0] = __fpu_ftoq(&fe, r, c); \ 53178138Sdas fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \ 54178138Sdas __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \ 5595604Sjake} 5695604Sjake 57146673Sstefanf#define _QP_TTOQ(qname, fname, ntype, signpos, atype, ...) \ 5895604Sjakevoid _Qp_ ## qname ## toq(u_int *c, ntype n); \ 5995604Sjakevoid \ 6095604Sjake_Qp_ ## qname ## toq(u_int *c, ntype n) \ 6195604Sjake{ \ 6295604Sjake struct fpemu fe; \ 63127091Sdes union { atype a[2]; ntype n; } u = { .n = n }; \ 6495604Sjake __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \ 65178138Sdas fe.fe_cx = 0; \ 66146673Sstefanf fe.fe_f1.fp_sign = (signpos >= 0) ? u.a[0] >> signpos : 0; \ 6795604Sjake fe.fe_f1.fp_sticky = 0; \ 6895604Sjake fe.fe_f1.fp_class = __fpu_ ## fname ## tof(&fe.fe_f1, __VA_ARGS__); \ 6995604Sjake c[0] = __fpu_ftoq(&fe, &fe.fe_f1, c); \ 70178138Sdas fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \ 71178138Sdas __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \ 7295604Sjake} 7395604Sjake 7495604Sjake#define _QP_QTOT(qname, fname, type, ...) \ 7595604Sjaketype _Qp_qto ## qname(u_int *c); \ 7695604Sjaketype \ 7795604Sjake_Qp_qto ## qname(u_int *c) \ 7895604Sjake{ \ 7995604Sjake struct fpemu fe; \ 80127091Sdes union { u_int a; type n; } u; \ 8195604Sjake __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \ 82178138Sdas fe.fe_cx = 0; \ 8395604Sjake fe.fe_f1.fp_sign = c[0] >> 31; \ 8495604Sjake fe.fe_f1.fp_sticky = 0; \ 8595604Sjake fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, c[0], c[1], c[2], c[3]); \ 86127091Sdes u.a = __fpu_fto ## fname(&fe, &fe.fe_f1, ## __VA_ARGS__); \ 87178138Sdas fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \ 88178138Sdas __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \ 89127091Sdes return (u.n); \ 9095604Sjake} 9195604Sjake 9295604Sjake#define FCC_EQ(fcc) ((fcc) == FSR_CC_EQ) 9395604Sjake#define FCC_GE(fcc) ((fcc) == FSR_CC_EQ || (fcc) == FSR_CC_GT) 9495604Sjake#define FCC_GT(fcc) ((fcc) == FSR_CC_GT) 9595604Sjake#define FCC_LE(fcc) ((fcc) == FSR_CC_EQ || (fcc) == FSR_CC_LT) 9695604Sjake#define FCC_LT(fcc) ((fcc) == FSR_CC_LT) 9795604Sjake#define FCC_NE(fcc) ((fcc) != FSR_CC_EQ) 98147519Sstefanf#define FCC_ID(fcc) (fcc) 9995604Sjake 10095604Sjake#define _QP_CMP(name, cmpe, test) \ 101147519Sstefanfint _Qp_ ## name(u_int *a, u_int *b) ; \ 10295604Sjakeint \ 103147519Sstefanf_Qp_ ## name(u_int *a, u_int *b) \ 10495604Sjake{ \ 10595604Sjake struct fpemu fe; \ 10695604Sjake __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \ 107178138Sdas fe.fe_cx = 0; \ 10895604Sjake fe.fe_f1.fp_sign = a[0] >> 31; \ 10995604Sjake fe.fe_f1.fp_sticky = 0; \ 11095604Sjake fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]); \ 11195604Sjake fe.fe_f2.fp_sign = b[0] >> 31; \ 11295604Sjake fe.fe_f2.fp_sticky = 0; \ 11395604Sjake fe.fe_f2.fp_class = __fpu_qtof(&fe.fe_f2, b[0], b[1], b[2], b[3]); \ 11495604Sjake __fpu_compare(&fe, cmpe, 0); \ 115178138Sdas fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \ 116178138Sdas __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \ 11795604Sjake return (test(FSR_GET_FCC0(fe.fe_fsr))); \ 11895604Sjake} 11995604Sjake 12097823Sjakevoid _Qp_sqrt(u_int *c, u_int *a); 12197823Sjakevoid 12297823Sjake_Qp_sqrt(u_int *c, u_int *a) 12397823Sjake{ 12497823Sjake struct fpemu fe; 12597823Sjake struct fpn *r; 12697823Sjake __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); 127178138Sdas fe.fe_cx = 0; 12897823Sjake fe.fe_f1.fp_sign = a[0] >> 31; 12997823Sjake fe.fe_f1.fp_sticky = 0; 13097823Sjake fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]); 13197823Sjake r = __fpu_sqrt(&fe); 13297823Sjake c[0] = __fpu_ftoq(&fe, r, c); 133178138Sdas fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; 134178138Sdas __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); 13597823Sjake} 13697823Sjake 13795604Sjake_QP_OP(add) 13895604Sjake_QP_OP(div) 13995604Sjake_QP_OP(mul) 14095604Sjake_QP_OP(sub) 14195604Sjake 142146673Sstefanf_QP_TTOQ(d, d, double, 31, u_int, u.a[0], u.a[1]) 143146673Sstefanf_QP_TTOQ(i, i, int, 31, u_int, u.a[0]) 144146673Sstefanf_QP_TTOQ(s, s, float, 31, u_int, u.a[0]) 145146673Sstefanf_QP_TTOQ(x, x, long, 63, u_long, u.a[0]) 146146673Sstefanf_QP_TTOQ(ui, i, u_int, -1, u_int, u.a[0]) 147146673Sstefanf_QP_TTOQ(ux, x, u_long, -1, u_long, u.a[0]) 14895604Sjake 149127091Sdes_QP_QTOT(d, d, double, &u.a) 150102831Sjake_QP_QTOT(i, i, int) 151102831Sjake_QP_QTOT(s, s, float) 152127091Sdes_QP_QTOT(x, x, long, &u.a) 153102831Sjake_QP_QTOT(ui, i, u_int) 154127091Sdes_QP_QTOT(ux, x, u_long, &u.a) 15595604Sjake 156147519Sstefanf_QP_CMP(feq, 0, FCC_EQ) 157157791Smarius_QP_CMP(fge, 1, FCC_GE) 158157791Smarius_QP_CMP(fgt, 1, FCC_GT) 159157791Smarius_QP_CMP(fle, 1, FCC_LE) 160157791Smarius_QP_CMP(flt, 1, FCC_LT) 161147519Sstefanf_QP_CMP(fne, 0, FCC_NE) 162147519Sstefanf_QP_CMP(cmp, 0, FCC_ID) 163147519Sstefanf_QP_CMP(cmpe, 1, FCC_ID) 164