/**************************************************************************/
/*                                                                        */
/*                                 Sources                                */
/*                                from  the                               */
/*                           XSC SOFTWARE PACKAGE                         */
/*                                                                        */
/*                Copyright (c) 1997 University of Karlsruhe              */
/*                     Institute for Appl. Mathematics                    */
/*                                                                        */
/* This program is free software for non-commercial use. For details, see */
/* the file LICENSE.XSC, distributed with this software package.          */
/*                                                                        */
/* This program is distributed WITHOUT ANY WARRANTY. For details, see the */
/* file LICENSE.XSC, distributed with this software package.              */
/*                                                                        */
/**************************************************************************/

/* RCS $Id: r_ari.c,v 1.3 1997/09/25 16:37:11 ae59 Exp $ */
/*
$Log: r_ari.c,v $
 * Revision 1.3  1997/09/25  16:37:11  ae59
 * Copyright-message
 *
 * Revision 1.2  1995/09/04  17:12:22  ae59
 * hardware support for ibm_emx_c similar to ibm_linux_c
 *
 * Revision 1.1  1995/08/17  12:26:40  ae59
 * Initial revision
 *
 */
/****************************************************************/
/*                                                              */
/*      Filename        : r_ari.c                               */
/*                                                              */
/*      Entries         : a_real r_addd(a,b)                    */
/*                        a_real r_addn(a,b)                    */
/*                        a_real r_addu(a,b)                    */
/*                        a_real r_subd(a,b)                    */
/*                        a_real r_subn(a,b)                    */
/*                        a_real r_subu(a,b)                    */
/*                        a_real r_muld(a,b)                    */
/*                        a_real r_muln(a,b)                    */
/*                        a_real r_mulu(a,b)                    */
/*                        a_real r_divd(a,b)                    */
/*                        a_real r_divn(a,b)                    */
/*                        a_real r_divu(a,b)                    */
/*                        a_real a,b;                           */
/*                        void   r_lfsr()                       */
/*                                                              */
/*      Arguments       : a = first IEEE operand of operation   */
/*                        b = second IEEE operand of operation  */
/*                                                              */
/*      Description     : Addition, Subtraction,                */
/*                        Multiplication, Division of IEEE      */
/*                        numbers. Result is rounded downwards, */
/*                        nearest or upwards according to the   */
/*                        suffix.                               */
/*                        Routines for i486 running Linux.      */
/*                                                              */
/*      Date            : 1992-07-08                            */
/*      1995-08-10 cb : initial version                         */
/****************************************************************/

#ifndef ALL_IN_ONE
#ifdef AIX
#include "/u/p88c/runtime/o_defs.h"
#else
#include "o_defs.h"
#endif
#define local
extern short e_cwdn, e_cwdu, e_cwdd;
#endif

#if IBM_LINUX_C+IBM_EMX_C
#ifdef IEEE_HARDWARE

#ifdef LINT_ARGS
#define _ARI_PRO	(a_real a, a_real b)
#else
#define _ARI_PRO	(a, b) a_real a, b;
#endif

local a_real r_addn _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdn));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("faddl %0" : /* no output */ : "m" (b));
	/* result (return value) in %st(0) */
}

local a_real r_addd _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdd));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("faddl %0" : /* no output */ : "m" (b));
}

local a_real r_addu _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdu));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("faddl %0" : /* no output */ : "m" (b));
}

local a_real r_subn _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdn));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("fsubl %0" : /* no output */ : "m" (b));
}

local a_real r_subd _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdd));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("fsubl %0" : /* no output */ : "m" (b));
}

local a_real r_subu _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdu));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("fsubl %0" : /* no output */ : "m" (b));
}

local a_real r_muln _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdn));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("fmull %0" : /* no output */ : "m" (b));
}

local a_real r_muld _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdd));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("fmull %0" : /* no output */ : "m" (b));
}

local a_real r_mulu _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdu));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("fmull %0" : /* no output */ : "m" (b));
}

local a_real r_divn _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdn));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("fdivl %0" : /* no output */ : "m" (b));
}

local a_real r_divd _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdd));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("fdivl %0" : /* no output */ : "m" (b));
}

local a_real r_divu _ARI_PRO
{
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdu));
	__asm__("fldl  %0" : /* no output */ : "m" (a));
	__asm__("fdivl %0" : /* no output */ : "m" (b));
}

#ifdef LINT_ARGS
local void r_lfsr(void)
#else
local void r_lfsr()
#endif
{
	__asm__("fclex");
	__asm__("fldcw %0" : /* no output */ : "m" (e_cwdn));
}

#endif /* IEEE_HARDWARE */
#endif /* IBM_LINUX_C */
