From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19363 invoked by alias); 19 Aug 2005 21:31:32 -0000 Mailing-List: contact sid-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: sid-owner@sources.redhat.com Received: (qmail 19327 invoked by uid 22791); 19 Aug 2005 21:31:12 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Fri, 19 Aug 2005 21:31:12 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.11/8.12.11) with ESMTP id j7JLVBVQ028343 for ; Fri, 19 Aug 2005 17:31:11 -0400 Received: from potter.sfbay.redhat.com (potter.sfbay.redhat.com [172.16.27.15]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id j7JLV5V13408 for ; Fri, 19 Aug 2005 17:31:05 -0400 Received: from [127.0.0.1] (vpn50-118.rdu.redhat.com [172.16.50.118]) by potter.sfbay.redhat.com (8.12.8/8.12.8) with ESMTP id j7JLUwDO008230; Fri, 19 Aug 2005 17:31:01 -0400 Message-ID: <43064F8D.40008@redhat.com> Date: Fri, 19 Aug 2005 21:31:00 -0000 From: Dave Brolley User-Agent: Mozilla Thunderbird 1.0 (Windows/20041206) MIME-Version: 1.0 To: Dave Brolley CC: sid@sources.redhat.com Subject: Re: [patch][rfc] CGEN Accurate Floating Point Support for SID References: <42EFD5AB.303@redhat.com> In-Reply-To: <42EFD5AB.303@redhat.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-SW-Source: 2005-q3/txt/msg00020.txt.bz2 I've committed this patch. Dave Dave Brolley wrote: > Hi, > > I'm submitting this patch for approval to commit. > > fp.cxx and fp.h have existed in the sid/component/cgen-cpu directory > for a while, but as far as I can tell, they have not been used. I'm > working on an internal port which requires simulation of accurate > floating point support, and so, I've cleaned up these files and > created two new source files, cgen-fpu.cxx and cgen-fpu.h, in > sid/component/cgen-cpu which add support for the semantic code which > CGEN already generates to the cgen-cpu components. > > The two new sources are analogous to sim/common/cgen-accfp.c and > implement the fpu as a virtual class defining operations on objects of > type f as defined in fp.cxx and fp.h. Not all operations have been > implemented (only the ones I needed), but the remaining operations > have at least been prototyped and implementation should be straight > forward as the need for them arises (similar to cgen-ops.h). > > The changes to fp.cxx and fp.h were mainly to virtualize the class in > order to allow for implementation-defined and non-standard behaviors > (tested by my internal port). Some clean up was also done and several > bugs were fixed. > > Dave > >------------------------------------------------------------------------ > >2005-08-02 Dave Brolley > > * cgen-fpu.cxx: New file. > * cgen-fpu.h: New file. > * Contribute the following enhancements to floating point > support: > > 2005-06-14 Dave Brolley > > * fp.h (do_round,do_normal_round,do_normal_underflow,do_normal_overflow): > Now virtual. > * fp.cxx (do_normal_overflow): Round up to infinity only if > the result is positive. > (operator-): Don't apply 'neg' to a nan. > (neg): Return src if it is a qnan. > > 2005-05-20 Dave Brolley > > * fp.cxx (pack_any): Ensure that nan results have a positive sign. > (operator-): Simply call operator+ with the rhs negated. > * fp.h (is_negative): New method of fp. > > 2005-05-13 Dave Brolley > > * fp.h (fp): All arithmetic operator methods are now members > of class fp. > * fp.cxx (fp): Likewise. > > 2005-04-27 Dave Brolley > > * fp.cxx (fp::unpack): Only perform sanity check for non-nans. > > 2005-04-12 Dave Brolley > > * fp.h: Move static constants and functions to top of file for > visibility within the file. > (get_status): New method of fp. > (get_class): Likewise. > (qnan_fraction): Likewise. > (snan_fraction): Likewise. > (qnan_exponent): Likewise. > (snan_exponent): Likewise. > * fp.cxx (fp_to_int): throw fp::overflow for overflow. > (pack_any): Use [sq]nan_{exponent,fraction} to construct nans. > (unpack): Initialize status to 'ok'. Set class and status using > is_qnan_fraction and is_qnan respectively. > > 2005-03-18 Dave Brolley > > * fp.cxx: Move static items from here. > * fp.h: To here. Make some methods virtual. Make private members > protected. > (is_inexact): New method. > > > >------------------------------------------------------------------------ > >? sid/component/cgen-cpu/cgen-fpu.cxx >? sid/component/cgen-cpu/cgen-fpu.h >Index: sid/component/cgen-cpu/Makefile.am >=================================================================== >RCS file: /cvs/src/src/sid/component/cgen-cpu/Makefile.am,v >retrieving revision 1.12 >diff -c -p -r1.12 Makefile.am >*** sid/component/cgen-cpu/Makefile.am 4 Jun 2005 03:23:02 -0000 1.12 >--- sid/component/cgen-cpu/Makefile.am 2 Aug 2005 19:19:22 -0000 >*************** MAKEOVERRIDES= >*** 20,26 **** > > LIBIBERTY = -L../../../libiberty/pic -liberty > >! libcgencpu_la_SOURCES = compCGEN.cxx tracedis.cxx > libcgencpu_la_LDFLAGS = -module -no-undefined > libcgencpu_la_LIBADD = @cpu_libs@ $(INTLLIBS) $(LIBIBERTY) cgen-asm.lo cgen-dis.lo cgen-opc.lo dis-buf.lo dis-init.lo > libcgencpu_la_DEPENDENCIES = @cpu_libs@ cgen-asm.lo cgen-dis.lo cgen-opc.lo dis-buf.lo dis-init.lo >--- 20,26 ---- > > LIBIBERTY = -L../../../libiberty/pic -liberty > >! libcgencpu_la_SOURCES = compCGEN.cxx cgen-fpu.cxx fp.cxx tracedis.cxx > libcgencpu_la_LDFLAGS = -module -no-undefined > libcgencpu_la_LIBADD = @cpu_libs@ $(INTLLIBS) $(LIBIBERTY) cgen-asm.lo cgen-dis.lo cgen-opc.lo dis-buf.lo dis-init.lo > libcgencpu_la_DEPENDENCIES = @cpu_libs@ cgen-asm.lo cgen-dis.lo cgen-opc.lo dis-buf.lo dis-init.lo >Index: sid/component/cgen-cpu/fp.cxx >=================================================================== >RCS file: /cvs/src/src/sid/component/cgen-cpu/fp.cxx,v >retrieving revision 1.2 >diff -c -p -r1.2 fp.cxx >*** sid/component/cgen-cpu/fp.cxx 8 Jan 2003 10:36:49 -0000 1.2 >--- sid/component/cgen-cpu/fp.cxx 2 Aug 2005 19:19:22 -0000 >*************** >*** 1,6 **** > // fp.cxx - Floating point number class implementation. -*- C++ -*- > >! // Copyright 1997, 1998, 2002 Free Software Foundation, Inc. > // Copyright 2002 Red Hat, Inc. > // This file is part of SID. > >--- 1,6 ---- > // fp.cxx - Floating point number class implementation. -*- C++ -*- > >! // Copyright 1997, 1998, 2002, 2005 Free Software Foundation, Inc. > // Copyright 2002 Red Hat, Inc. > // This file is part of SID. > >*************** >*** 23,172 **** > > #include "fp.h" > >- using sid::host_int_4; >- using sid::host_int_8; >- using sid::signed_host_int_8; >- >- // XXX: more of this cruft should be C++-ed. >- >- #define FRAC32MASK LSMASK64 (63, NR_FRAC_GUARD - 32 + 1) >- #define MAX_UINT32 LSMASK64 (31, 0) >- #define MAX_UINT64 LSMASK64 (63, 0) >- #define MAX_INT (is_64bit ? MAX_INT64 () : MAX_INT32 ()) >- #define MIN_INT (is_64bit ? MIN_INT64 () : MIN_INT32 ()) >- #define MAX_UINT (is_64bit ? MAX_UINT64 () : MAX_UINT32 ()) >- #define QUIET_NAN LSBIT64 (NR_FRACBITS (double_p) - 1) >- #define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD) >- #define IMPLICIT_2 LSBIT64 (NR_FRAC_GUARD + 1) >- #define IMPLICIT_4 LSBIT64 (NR_FRAC_GUARD + 2) >- #define NORMAL_EXPMIN (-(EXPBIAS (double_p) )+1) >- #define NORMAL_EXPMAX (EXPBIAS (double_p)) >- >- #if (WITH_TARGET_WORD_MSB == 0) >- #define _LSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) >- #else >- #define _LSB_SHIFT(WIDTH, POS) (POS) >- #endif >- >- #if (WITH_TARGET_WORD_MSB == 0) >- #define _MSB_SHIFT(WIDTH, POS) (POS) >- #else >- #define _MSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) >- #endif >- >- #define _MASK64(WIDTH, START, STOP) (((static_cast(-1)) \ >- >> (_MSB_SHIFT (WIDTH, START) \ >- + _LSB_SHIFT (WIDTH, STOP))) \ >- << _LSB_SHIFT (WIDTH, STOP)) >- >- #if (WITH_TARGET_WORD_MSB == 0) >- #define _LSB_POS(WIDTH, SHIFT) (WIDTH - 1 - SHIFT) >- #else >- #define _LSB_POS(WIDTH, SHIFT) (SHIFT) >- #endif >- >- #define _LSMASK64(WIDTH, FIRST, LAST) _MASK64 (WIDTH, \ >- _LSB_POS (WIDTH, FIRST), \ >- _LSB_POS (WIDTH, LAST)) >- >- #define LSMASK64(FIRST, LAST) _LSMASK64 (64, (FIRST), (LAST)) >- >- #define GUARDMSB LSBIT64 (NR_GUARDS (double_p) - 1) >- #define GUARDLSB LSBIT64 (NR_PAD) >- #define GUARDMASK LSMASK64 (NR_GUARDS (double_p) - 1, 0) >- #define GUARDROUND LSMASK64 (NR_GUARDS (double_p) - 2, 0) >- >- static const int NR_SPARE = 2; >- static const int EXPMAX32 = 255; >- static const int EXPMAX64 = 2047; >- static const int NR_FRAC_GUARD = 60; >- static const int EXPBIAS32 = 127; >- static const int EXPBIAS64 = 1023; >- static const int NR_PAD32 = 30; >- static const int NR_PAD64 = 0; >- static const int NR_GUARDS32 = 7 + NR_PAD32; >- static const int NR_GUARDS64 = 8 + NR_PAD64; >- static const int NORMAL_EXPMAX32 = EXPBIAS32; >- static const int NORMAL_EXPMAX64 = EXPBIAS64; >- >- static inline >- signed_host_int_8 MAX_INT32 () >- { >- return LSMASK64 (30, 0); >- } >- >- static inline >- signed_host_int_8 MIN_INT32 () >- { >- return LSMASK64 (63, 31); >- } >- >- static inline >- signed_host_int_8 MAX_INT64 () >- { >- return LSMASK64 (62, 0); >- } >- >- static inline >- signed_host_int_8 MIN_INT64 () >- { >- return LSMASK64 (63, 63); >- } >- >- static inline >- unsigned EXPMAX (bool double_p) >- { >- return double_p ? EXPMAX64 : EXPMAX32; >- } >- >- static inline >- int EXPBIAS (bool double_p) >- { >- return double_p ? EXPBIAS64 : EXPBIAS32; >- } >- >- static inline >- int NR_GUARDS (bool double_p) >- { >- return double_p ? NR_GUARDS64 : NR_GUARDS32; >- } >- >- static inline >- int NR_EXPBITS (bool double_p) >- { >- return double_p ? 11 : 8; >- } >- >- static inline >- int NR_FRACBITS (bool double_p) >- { >- return double_p ? 52 : 23; >- } >- >- static inline >- int NR_INTBITS (bool is_64bit) >- { >- return is_64bit ? 64 : 32; >- } >- >- static inline >- host_int_8 LSBIT64 (int pos) >- { >- return host_int_8 (1) << pos; >- } >- >- static inline >- host_int_8 MSBIT64 (int pos) >- { >- return host_int_8 (1) << (64 - 1 - pos); >- } >- >- static inline >- host_int_8 SIGNBIT (bool double_p) >- { >- return double_p ? MSBIT64 (0) : MSBIT64 (32); >- } >- > static void > print_bits (std::ostream& out, host_int_8 x, int msbit, int digits) > { >--- 23,28 ---- >*************** namespace sidutil >*** 264,270 **** > if (fraction == IMPLICIT_1) > return; // exact > if (is_64bit) // can't round >! throw fp::error (fp::invalid_cvi); // must be overflow > > // For a 32bit with MAX_INT, rounding is possible. > switch (round) >--- 120,126 ---- > if (fraction == IMPLICIT_1) > return; // exact > if (is_64bit) // can't round >! throw fp::error (fp::overflow); // must be overflow > > // For a 32bit with MAX_INT, rounding is possible. > switch (round) >*************** namespace sidutil >*** 302,308 **** > if (normal_exp > (NR_INTBITS (is_64bit) - 2)) > { > i = sign ? MIN_INT : MAX_INT; >! throw fp::error (fp::invalid_cvi); > } > // Normal number shift it into place. > tmp = fraction; >--- 158,164 ---- > if (normal_exp > (NR_INTBITS (is_64bit) - 2)) > { > i = sign ? MIN_INT : MAX_INT; >! throw fp::error (fp::overflow); > } > // Normal number shift it into place. > tmp = fraction; >*************** namespace sidutil >*** 329,334 **** >--- 185,192 ---- > { > host_int_8 tmp; > int shift; >+ int is_64bit = (sizeof u == 8); >+ bool double_p = (sizeof u == 8); > > if (is_zero ()) > { >*************** namespace sidutil >*** 475,497 **** > host_int_8 exp; > host_int_8 frac; > host_int_8 packed; > > switch (fp_class) > { > // Create a NaN. > case fp::class_qnan: >! exp = EXPMAX (double_p); >! // Force fraction to correct class. >! frac = fraction; >! frac >>= NR_GUARDS (double_p); >! frac |= QUIET_NAN; > break; > case fp::class_snan: >! exp = EXPMAX (double_p); >! // Force fraction to correct class. >! frac = fraction; >! frac >>= NR_GUARDS (double_p); >! frac &= ~QUIET_NAN; > break; > case fp::class_infinity: > exp = EXPMAX (double_p); >--- 333,352 ---- > host_int_8 exp; > host_int_8 frac; > host_int_8 packed; >+ int sign_bit = sign; > > switch (fp_class) > { > // Create a NaN. > case fp::class_qnan: >! sign_bit = 0; >! exp = qnan_exponent (double_p); >! frac = qnan_fraction (double_p); > break; > case fp::class_snan: >! sign_bit = 0; >! exp = snan_exponent (double_p); >! frac = snan_fraction (double_p); > break; > case fp::class_infinity: > exp = EXPMAX (double_p); >*************** namespace sidutil >*** 570,576 **** > abort (); > } > >! packed = ((sign ? SIGNBIT (double_p) : 0) | > (exp << NR_FRACBITS (double_p)) | LSMASKED64 (frac, NR_FRACBITS (double_p) - 1, 0)); > t = packed; > } >--- 425,431 ---- > abort (); > } > >! packed = ((sign_bit ? SIGNBIT (double_p) : 0) | > (exp << NR_FRACBITS (double_p)) | LSMASKED64 (frac, NR_FRACBITS (double_p) - 1, 0)); > t = packed; > } >*************** namespace sidutil >*** 578,583 **** >--- 433,439 ---- > template void > fp::unpack (const T& packed) > { >+ status = ok; > // Unpack a 32/64 bit integer into an fp object. > bool double_p = (sizeof packed == 8); > >*************** namespace sidutil >*** 627,633 **** > // Non zero fraction, means NaN. > sign = signbit; > fraction = (frac << NR_GUARDS (double_p)); >! fp_class = (frac >= QUIET_NAN) ? fp::class_qnan : fp::class_snan; > } > } > else >--- 483,490 ---- > // Non zero fraction, means NaN. > sign = signbit; > fraction = (frac << NR_GUARDS (double_p)); >! fp_class = is_qnan_fraction (frac, double_p) ? fp::class_qnan : fp::class_snan; >! status = is_qnan () ? invalid_qnan : invalid_snan; > } > } > else >*************** namespace sidutil >*** 640,651 **** > } > > // Sanity checks. > { >- map_t val; >- pack (val.i); >- > if (double_p) >! assert (val.i == packed); > else > { > host_int_4 val; >--- 497,510 ---- > } > > // Sanity checks. >+ if (! is_nan ()) > { > if (double_p) >! { >! map_t val; >! pack (val.i); >! assert (val.i == packed); >! } > else > { > host_int_4 val; >*************** namespace sidutil >*** 811,817 **** > fp_class = fp::class_infinity; > break; > case fp::round_up: >! if (sign) > fp_class = fp::class_infinity; > break; > case fp::round_down: >--- 670,676 ---- > fp_class = fp::class_infinity; > break; > case fp::round_up: >! if (! sign) > fp_class = fp::class_infinity; > break; > case fp::round_down: >*************** namespace sidutil >*** 942,989 **** > } > > bool >! operator< (const fp& l, const fp& r) > { >! if (!l.is_nan () && !r.is_nan ()) > { > map_t lval, rval; >! l.pack (lval.i); > r.pack (rval.i); > return (lval.d < rval.d); > } >! else if (l.is_snan () || r.is_snan ()) > throw fp::error (fp::invalid_snan); > else > throw fp::error (fp::invalid_qnan); > } > > bool >! operator<= (const fp& l, const fp& r) > { >! if (!l.is_nan () && !r.is_nan ()) > { > map_t lval, rval; >! l.pack (lval.i); > r.pack (rval.i); > return (lval.d <= rval.d); > } >! else if (l.is_snan () || r.is_snan ()) > throw fp::error (fp::invalid_snan); > else > throw fp::error (fp::invalid_qnan); > } > > bool >! operator== (const fp& l, const fp& r) > { >! if (!l.is_nan () && !r.is_nan ()) > { > map_t lval, rval; >! l.pack (lval.i); > r.pack (rval.i); > return (lval.d == rval.d); > } >! else if (l.is_snan () || r.is_snan ()) > throw fp::error (fp::invalid_snan); > else > throw fp::error (fp::invalid_qnan); >--- 801,848 ---- > } > > bool >! fp::operator< (const fp& r) const > { >! if (!this->is_nan () && !r.is_nan ()) > { > map_t lval, rval; >! this->pack (lval.i); > r.pack (rval.i); > return (lval.d < rval.d); > } >! else if (this->is_snan () || r.is_snan ()) > throw fp::error (fp::invalid_snan); > else > throw fp::error (fp::invalid_qnan); > } > > bool >! fp::operator<= (const fp& r) const > { >! if (!this->is_nan () && !r.is_nan ()) > { > map_t lval, rval; >! this->pack (lval.i); > r.pack (rval.i); > return (lval.d <= rval.d); > } >! else if (this->is_snan () || r.is_snan ()) > throw fp::error (fp::invalid_snan); > else > throw fp::error (fp::invalid_qnan); > } > > bool >! fp::operator== (const fp& r) const > { >! if (!this->is_nan () && !r.is_nan ()) > { > map_t lval, rval; >! this->pack (lval.i); > r.pack (rval.i); > return (lval.d == rval.d); > } >! else if (this->is_snan () || r.is_snan ()) > throw fp::error (fp::invalid_snan); > else > throw fp::error (fp::invalid_qnan); >*************** namespace sidutil >*** 991,1031 **** > > > bool >! operator!= (const fp& l, const fp& r) > { >! if (!l.is_nan () && !r.is_nan ()) >! { >! map_t lval, rval; >! l.pack (lval.i); >! r.pack (rval.i); >! return (lval.d != rval.d); >! } >! else if (l.is_snan () || r.is_snan ()) >! throw fp::error (fp::invalid_snan); >! else >! throw fp::error (fp::invalid_qnan); > } > > bool >! operator>= (const fp& l, const fp& r) > { >! return r <= l; > } > > bool >! operator> (const fp& l, const fp& r) > { >! return r < l; > } > > fp >! operator+ (const fp& l, const fp& r) > { > fp f; > >! if (l.is_snan ()) > { >! f = l; > f.fp_class = fp::class_qnan; > f.status = fp::invalid_snan; > return f; >--- 850,880 ---- > > > bool >! fp::operator!= (const fp& r) const > { >! return !(*this == r); > } > > bool >! fp::operator>= (const fp& r) const > { >! return r <= *this; > } > > bool >! fp::operator> (const fp& r) const > { >! return r < *this; > } > > fp >! fp::operator+ (const fp& r) const > { > fp f; > >! if (this->is_snan ()) > { >! f = *this; > f.fp_class = fp::class_qnan; > f.status = fp::invalid_snan; > return f; >*************** namespace sidutil >*** 1039,1047 **** > return f; > } > >! if (l.is_qnan ()) > { >! f = l; > f.status = fp::ok; > return f; > } >--- 888,896 ---- > return f; > } > >! if (this->is_qnan ()) > { >! f = *this; > f.status = fp::ok; > return f; > } >*************** namespace sidutil >*** 1053,1067 **** > return f; > } > >! if (l.is_infinity ()) > { >! if (r.is_infinity () && l.sign != r.sign) > { > f = constant_qnan; > f.status = fp::invalid_isi; > return f; > } >! f = l; > f.status = fp::ok; > return f; > } >--- 902,916 ---- > return f; > } > >! if (this->is_infinity ()) > { >! if (r.is_infinity () && this->sign != r.sign) > { > f = constant_qnan; > f.status = fp::invalid_isi; > return f; > } >! f = *this; > f.status = fp::ok; > return f; > } >*************** namespace sidutil >*** 1073,1084 **** > return f; > } > >! if (l.is_zero ()) > { > if (r.is_zero ()) > { > f = constant_zero; >! f.sign = l.sign & r.sign; > } > else > f = r; >--- 922,933 ---- > return f; > } > >! if (this->is_zero ()) > { > if (r.is_zero ()) > { > f = constant_zero; >! f.sign = this->sign & r.sign; > } > else > f = r; >*************** namespace sidutil >*** 1088,1122 **** > > if (r.is_zero ()) > { >! f = l; > f.status = fp::ok; > return f; > } > > fp::status_t status = fp::ok; >! int shift = l.normal_exp - r.normal_exp; > host_int_8 lfraction; > host_int_8 rfraction; > // Use exp of larger. > if (shift >= NR_FRAC_GUARD) > { > // Left has much bigger magnitude. >! f = l; > f.status = fp::inexact; > return f; > } > if (shift <= - NR_FRAC_GUARD) > { >! // Right has much bigger magnitute. > f = r; > f.status = fp::inexact; > return f; > } >! lfraction = l.fraction; > rfraction = r.fraction; > if (shift > 0) > { >! f.normal_exp = l.normal_exp; > if (rfraction & LSMASK64 (shift - 1, 0)) > { > status |= fp::inexact; >--- 937,971 ---- > > if (r.is_zero ()) > { >! f = *this; > f.status = fp::ok; > return f; > } > > fp::status_t status = fp::ok; >! int shift = this->normal_exp - r.normal_exp; > host_int_8 lfraction; > host_int_8 rfraction; > // Use exp of larger. > if (shift >= NR_FRAC_GUARD) > { > // Left has much bigger magnitude. >! f = *this; > f.status = fp::inexact; > return f; > } > if (shift <= - NR_FRAC_GUARD) > { >! // Right has much bigger magnitude. > f = r; > f.status = fp::inexact; > return f; > } >! lfraction = this->fraction; > rfraction = r.fraction; > if (shift > 0) > { >! f.normal_exp = this->normal_exp; > if (rfraction & LSMASK64 (shift - 1, 0)) > { > status |= fp::inexact; >*************** namespace sidutil >*** 1138,1144 **** > f.normal_exp = r.normal_exp; > > // Perform the addition. >! if (l.sign) > lfraction = - lfraction; > if (r.sign) > rfraction = - rfraction; >--- 987,993 ---- > f.normal_exp = r.normal_exp; > > // Perform the addition. >! if (this->sign) > lfraction = - lfraction; > if (r.sign) > rfraction = - rfraction; >*************** namespace sidutil >*** 1183,1350 **** > } > > fp >! operator- (const fp& l, const fp& r) > { >! fp f; >! >! if (l.is_snan ()) >! { >! f = l; >! f.fp_class = fp::class_qnan; >! f.status = fp::invalid_snan; >! return f; >! } >! >! if (r.is_snan ()) >! { >! f = r; >! f.fp_class = fp::class_qnan; >! f.status = fp::invalid_snan; >! return f; >! } >! >! if (l.is_infinity ()) >! { >! if (r.is_infinity () && l.sign == r.sign) >! { >! f = constant_qnan; >! f.status = fp::invalid_isi; >! return f; >! } >! f = l; >! f.status = fp::ok; >! return f; >! } >! >! if (r.is_infinity ()) >! { >! f = r; >! f.sign = !r.sign; >! f.status = fp::ok; >! return f; >! } >! >! if (l.is_zero ()) >! { >! if (r.is_zero ()) >! { >! f = constant_zero; >! f.sign = l.sign & !r.sign; >! } >! else >! { >! f = r; >! f.sign = !r.sign; >! } >! f.status = fp::ok; >! return f; >! } >! if (r.is_zero ()) >! { >! f = l; >! f.status = fp::ok; >! return f; >! } >! >! fp::status_t status = fp::ok; >! int shift = l.normal_exp - r.normal_exp; >! host_int_8 lfraction; >! host_int_8 rfraction; >! // Use exp of larger. >! if (shift >= NR_FRAC_GUARD) >! { >! // Left has much bigger magnitude. >! f = l; >! f.status = fp::inexact; >! return f; >! } >! if (shift <= - NR_FRAC_GUARD) >! { >! // Right has much bigger magnitute. >! f = r; >! f.sign = !r.sign; >! f.status = fp::inexact; >! return f; >! } >! lfraction = l.fraction; >! rfraction = r.fraction; >! if (shift > 0) >! { >! f.normal_exp = l.normal_exp; >! if (rfraction & LSMASK64 (shift - 1, 0)) >! { >! status |= fp::inexact; >! rfraction |= LSBIT64 (shift); // Stick LSBit. >! } >! rfraction >>= shift; >! } >! else if (shift < 0) >! { >! f.normal_exp = r.normal_exp; >! if (lfraction & LSMASK64 (- shift - 1, 0)) >! { >! status |= fp::inexact; >! lfraction |= LSBIT64 (- shift); // Stick LSBit. >! } >! lfraction >>= -shift; >! } >! else >! { >! f.normal_exp = r.normal_exp; >! } >! >! // Perform the subtraction. >! if (l.sign) >! lfraction = - lfraction; >! if (!r.sign) >! rfraction = - rfraction; >! f.fraction = lfraction + rfraction; >! >! // Zero? >! if (f.fraction == 0) >! { >! f = constant_zero; >! return f; >! } >! >! // Sign? >! f.fp_class = fp::class_number; >! if (static_cast (f.fraction) >= 0) >! f.sign = 0; >! else >! { >! f.sign = 1; >! f.fraction = - f.fraction; >! } >! >! // Normalize it. >! if ((f.fraction & IMPLICIT_2)) >! { >! f.fraction = (f.fraction >> 1) | (f.fraction & 1); >! f.normal_exp ++; >! } >! else if (f.fraction < IMPLICIT_1) >! { >! do >! { >! f.fraction <<= 1; >! f.normal_exp --; >! } >! while (f.fraction < IMPLICIT_1); >! } >! >! assert (f.fraction >= IMPLICIT_1 && f.fraction < IMPLICIT_2); >! return f; > } > > fp >! operator* (const fp& l, const fp& r) > { > fp f; > >! if (l.is_snan ()) > { >! f = l; > f.fp_class = fp::class_qnan; > f.status = fp::invalid_snan; > return f; >--- 1032,1052 ---- > } > > fp >! fp::operator- (const fp& r) const > { >! if (! r.is_nan ()) >! return *this + neg (r); >! return *this + r; > } > > fp >! fp::operator* (const fp& r) const > { > fp f; > >! if (this->is_snan ()) > { >! f = *this; > f.fp_class = fp::class_qnan; > f.status = fp::invalid_snan; > return f; >*************** namespace sidutil >*** 1356,1364 **** > f.status = fp::invalid_snan; > return f; > } >! if (l.is_qnan ()) > { >! f = l; > f.status = fp::ok; > return f; > } >--- 1058,1066 ---- > f.status = fp::invalid_snan; > return f; > } >! if (this->is_qnan ()) > { >! f = *this; > f.status = fp::ok; > return f; > } >*************** namespace sidutil >*** 1368,1374 **** > f.status = fp::ok; > return f; > } >! if (l.is_infinity ()) > { > if (r.is_zero ()) > { >--- 1070,1076 ---- > f.status = fp::ok; > return f; > } >! if (this->is_infinity ()) > { > if (r.is_zero ()) > { >*************** namespace sidutil >*** 1376,1401 **** > f.status = fp::invalid_imz; > return f; > } >! f = l; >! f.sign = l.sign ^ r.sign; > return f; > } > if (r.is_infinity ()) > { >! if (l.is_zero ()) > { > f = constant_qnan; > f.status = fp::invalid_imz; > return f; > } > f = r; >! f.sign = l.sign ^ r.sign; > return f; > } >! if (l.is_zero () || r.is_zero ()) > { > f = constant_zero; >! f.sign = l.sign ^ r.sign; > return f; > } > >--- 1078,1103 ---- > f.status = fp::invalid_imz; > return f; > } >! f = *this; >! f.sign = this->sign ^ r.sign; > return f; > } > if (r.is_infinity ()) > { >! if (this->is_zero ()) > { > f = constant_qnan; > f.status = fp::invalid_imz; > return f; > } > f = r; >! f.sign = this->sign ^ r.sign; > return f; > } >! if (this->is_zero () || r.is_zero ()) > { > f = constant_zero; >! f.sign = this->sign ^ r.sign; > return f; > } > >*************** namespace sidutil >*** 1404,1411 **** > > host_int_8 low; > host_int_8 high; >! host_int_8 nl = l.fraction & 0xffffffff; >! host_int_8 nh = l.fraction >> 32; > host_int_8 ml = r.fraction & 0xffffffff; > host_int_8 mh = r.fraction >>32; > host_int_8 pp_ll = ml * nl; >--- 1106,1113 ---- > > host_int_8 low; > host_int_8 high; >! host_int_8 nl = this->fraction & 0xffffffff; >! host_int_8 nh = this->fraction >> 32; > host_int_8 ml = r.fraction & 0xffffffff; > host_int_8 mh = r.fraction >>32; > host_int_8 pp_ll = ml * nl; >*************** namespace sidutil >*** 1425,1432 **** > high = res2; > low = res0; > >! f.normal_exp = l.normal_exp + r.normal_exp; >! f.sign = l.sign ^ r.sign; > f.fp_class = fp::class_number; > > // Input is bounded by [1,2) ; [2^60,2^61) >--- 1127,1134 ---- > high = res2; > low = res0; > >! f.normal_exp = this->normal_exp + r.normal_exp; >! f.sign = this->sign ^ r.sign; > f.fp_class = fp::class_number; > > // Input is bounded by [1,2) ; [2^60,2^61) >*************** namespace sidutil >*** 1469,1481 **** > } > > fp >! operator/ (const fp& l, const fp& r) > { > fp f; > >! if (l.is_snan ()) > { >! f = l; > f.fp_class = fp::class_qnan; > f.status = fp::invalid_snan; > return f; >--- 1171,1183 ---- > } > > fp >! fp::operator/ (const fp& r) const > { > fp f; > >! if (this->is_snan ()) > { >! f = *this; > f.fp_class = fp::class_qnan; > f.status = fp::invalid_snan; > return f; >*************** namespace sidutil >*** 1487,1495 **** > f.status = fp::invalid_snan; > return f; > } >! if (l.is_qnan ()) > { >! f = l; > f.fp_class = fp::class_qnan; > return f; > } >--- 1189,1197 ---- > f.status = fp::invalid_snan; > return f; > } >! if (this->is_qnan ()) > { >! f = *this; > f.fp_class = fp::class_qnan; > return f; > } >*************** namespace sidutil >*** 1499,1505 **** > f.fp_class = fp::class_qnan; > return f; > } >! if (l.is_infinity ()) > { > if (r.is_infinity ()) > { >--- 1201,1207 ---- > f.fp_class = fp::class_qnan; > return f; > } >! if (this->is_infinity ()) > { > if (r.is_infinity ()) > { >*************** namespace sidutil >*** 1508,1520 **** > } > else > { >! f = l; >! f.sign = l.sign ^ r.sign; > } > return f; > } > >! if (l.is_zero ()) > { > if (r.is_zero ()) > { >--- 1210,1222 ---- > } > else > { >! f = *this; >! f.sign = this->sign ^ r.sign; > } > return f; > } > >! if (this->is_zero ()) > { > if (r.is_zero ()) > { >*************** namespace sidutil >*** 1523,1530 **** > } > else > { >! f = l; >! f.sign = l.sign ^ r.sign; > } > return f; > } >--- 1225,1232 ---- > } > else > { >! f = *this; >! f.sign = this->sign ^ r.sign; > } > return f; > } >*************** namespace sidutil >*** 1532,1545 **** > if (r.is_infinity ()) > { > f = constant_zero; >! f.sign = l.sign ^ r.sign; > return f; > } > > if (r.is_zero ()) > { > f.fp_class = fp::class_infinity; >! f.sign = l.sign ^ r.sign; > f.status = fp::invalid_div0; > return f; > } >--- 1234,1247 ---- > if (r.is_infinity ()) > { > f = constant_zero; >! f.sign = this->sign ^ r.sign; > return f; > } > > if (r.is_zero ()) > { > f.fp_class = fp::class_infinity; >! f.sign = this->sign ^ r.sign; > f.status = fp::invalid_div0; > return f; > } >*************** namespace sidutil >*** 1556,1565 **** > host_int_8 bit; > > f.fp_class = fp::class_number; >! f.sign = l.sign ^ r.sign; >! f.normal_exp = l.normal_exp - r.normal_exp; > >! numerator = l.fraction; > denominator = r.fraction; > > // Fraction will be less than 1.0. >--- 1258,1267 ---- > host_int_8 bit; > > f.fp_class = fp::class_number; >! f.sign = this->sign ^ r.sign; >! f.normal_exp = this->normal_exp - r.normal_exp; > >! numerator = this->fraction; > denominator = r.fraction; > > // Fraction will be less than 1.0. >*************** namespace sidutil >*** 1813,1819 **** > } > if (src.is_qnan()) > { >! return dest; > } > dest = src; > dest.sign = !src.sign; >--- 1515,1521 ---- > } > if (src.is_qnan()) > { >! return src; > } > dest = src; > dest.sign = !src.sign; >Index: sid/component/cgen-cpu/fp.h >=================================================================== >RCS file: /cvs/src/src/sid/component/cgen-cpu/fp.h,v >retrieving revision 1.2 >diff -c -p -r1.2 fp.h >*** sid/component/cgen-cpu/fp.h 8 Jan 2003 10:36:49 -0000 1.2 >--- sid/component/cgen-cpu/fp.h 2 Aug 2005 19:19:22 -0000 >*************** >*** 1,6 **** > // fp.h - Floating point number class using host integer ops. -*- C++ -*- > >! // Copyright 1997, 1998, 2002 Free Software Foundation, Inc. > // Copyright 2002 Red Hat, Inc. > // This file is part of SID. > >--- 1,6 ---- > // fp.h - Floating point number class using host integer ops. -*- C++ -*- > >! // Copyright 1997, 1998, 2002, 2005 Free Software Foundation, Inc. > // Copyright 2002 Red Hat, Inc. > // This file is part of SID. > >*************** >*** 28,33 **** >--- 28,185 ---- > #include "sidtypes.h" > #include "cgen-types.h" > >+ using sid::host_int_4; >+ using sid::host_int_8; >+ using sid::signed_host_int_8; >+ >+ // XXX: more of this cruft should be C++-ed. >+ >+ #define FRAC32MASK LSMASK64 (63, NR_FRAC_GUARD - 32 + 1) >+ #define MAX_UINT32() LSMASK64 (31, 0) >+ #define MAX_UINT64() LSMASK64 (63, 0) >+ #define MAX_INT (is_64bit ? MAX_INT64 () : MAX_INT32 ()) >+ #define MIN_INT (is_64bit ? MIN_INT64 () : MIN_INT32 ()) >+ #define MAX_UINT (is_64bit ? MAX_UINT64 () : MAX_UINT32 ()) >+ #define QUIET_NAN LSBIT64 (NR_FRACBITS (double_p) - 1) >+ #define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD) >+ #define IMPLICIT_2 LSBIT64 (NR_FRAC_GUARD + 1) >+ #define IMPLICIT_4 LSBIT64 (NR_FRAC_GUARD + 2) >+ #define NORMAL_EXPMIN (-(EXPBIAS (double_p) )+1) >+ #define NORMAL_EXPMAX (EXPBIAS (double_p)) >+ >+ #if (WITH_TARGET_WORD_MSB == 0) >+ #define _LSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) >+ #else >+ #define _LSB_SHIFT(WIDTH, POS) (POS) >+ #endif >+ >+ #if (WITH_TARGET_WORD_MSB == 0) >+ #define _MSB_SHIFT(WIDTH, POS) (POS) >+ #else >+ #define _MSB_SHIFT(WIDTH, POS) (WIDTH - 1 - POS) >+ #endif >+ >+ #define _MASK64(WIDTH, START, STOP) (((static_cast(-1)) \ >+ >> (_MSB_SHIFT (WIDTH, START) \ >+ + _LSB_SHIFT (WIDTH, STOP))) \ >+ << _LSB_SHIFT (WIDTH, STOP)) >+ >+ #if (WITH_TARGET_WORD_MSB == 0) >+ #define _LSB_POS(WIDTH, SHIFT) (WIDTH - 1 - SHIFT) >+ #else >+ #define _LSB_POS(WIDTH, SHIFT) (SHIFT) >+ #endif >+ >+ #define _LSMASK64(WIDTH, FIRST, LAST) _MASK64 (WIDTH, \ >+ _LSB_POS (WIDTH, FIRST), \ >+ _LSB_POS (WIDTH, LAST)) >+ >+ #define LSMASK64(FIRST, LAST) _LSMASK64 (64, (FIRST), (LAST)) >+ >+ #define GUARDMSB LSBIT64 (NR_GUARDS (double_p) - 1) >+ #define GUARDLSB LSBIT64 (NR_PADS (double_p)) >+ #define GUARDMASK LSMASK64 (NR_GUARDS (double_p) - 1, 0) >+ #define GUARDROUND LSMASK64 (NR_GUARDS (double_p) - 2, 0) >+ >+ #define PADMASK LSMASK64 (NR_PADS (double_p) - 1, 0) >+ >+ static const int NR_SPARE = 2; >+ static const int EXPMAX32 = 255; >+ static const int EXPMAX64 = 2047; >+ static const int NR_FRAC_GUARD = 60; >+ static const int EXPBIAS32 = 127; >+ static const int EXPBIAS64 = 1023; >+ static const int NR_PAD32 = 30; >+ static const int NR_PAD64 = 0; >+ static const int NR_GUARDS32 = 7 + NR_PAD32; >+ static const int NR_GUARDS64 = 8 + NR_PAD64; >+ static const int NORMAL_EXPMAX32 = EXPBIAS32; >+ static const int NORMAL_EXPMAX64 = EXPBIAS64; >+ >+ static inline >+ signed_host_int_8 MAX_INT32 () >+ { >+ return LSMASK64 (30, 0); >+ } >+ >+ static inline >+ signed_host_int_8 MIN_INT32 () >+ { >+ return LSMASK64 (63, 31); >+ } >+ >+ static inline >+ signed_host_int_8 MAX_INT64 () >+ { >+ return LSMASK64 (62, 0); >+ } >+ >+ static inline >+ signed_host_int_8 MIN_INT64 () >+ { >+ return LSMASK64 (63, 63); >+ } >+ >+ static inline >+ unsigned EXPMAX (bool double_p) >+ { >+ return double_p ? EXPMAX64 : EXPMAX32; >+ } >+ >+ static inline >+ int EXPBIAS (bool double_p) >+ { >+ return double_p ? EXPBIAS64 : EXPBIAS32; >+ } >+ >+ static inline >+ int NR_GUARDS (bool double_p) >+ { >+ return double_p ? NR_GUARDS64 : NR_GUARDS32; >+ } >+ >+ static inline >+ int NR_PADS (bool double_p) >+ { >+ return double_p ? NR_PAD64 : NR_PAD32; >+ } >+ >+ static inline >+ int NR_EXPBITS (bool double_p) >+ { >+ return double_p ? 11 : 8; >+ } >+ >+ static inline >+ int NR_FRACBITS (bool double_p) >+ { >+ return double_p ? 52 : 23; >+ } >+ >+ static inline >+ int NR_INTBITS (bool is_64bit) >+ { >+ return is_64bit ? 64 : 32; >+ } >+ >+ static inline >+ host_int_8 LSBIT64 (int pos) >+ { >+ return host_int_8 (1) << pos; >+ } >+ >+ static inline >+ host_int_8 MSBIT64 (int pos) >+ { >+ return host_int_8 (1) << (64 - 1 - pos); >+ } >+ >+ static inline >+ host_int_8 SIGNBIT (bool double_p) >+ { >+ return double_p ? MSBIT64 (0) : MSBIT64 (32); >+ } >+ > namespace sidutil > { > class fp >*************** namespace sidutil >*** 98,115 **** > bool is_zero () const; > bool is_infinity () const; > bool is_number () const; > > // Conversions to integers. >! void integer (int&, round_mode_t = round_default); >! void integer (long&, round_mode_t = round_default); >! void integer (unsigned int&, round_mode_t = round_default); >! void integer (unsigned long&, round_mode_t = round_default); > > // Pack an fp into registers of various sizes. > void pack (cgen::SF&) const; > void pack (cgen::DF&) const; > void pack (cgen::SF& upper, cgen::SF& lower) const; > > // Round an fp suitable for packing. > void round_32 (round_mode_t = round_default, enum denorm_t = denorm_default); > void round_64 (round_mode_t = round_default, enum denorm_t = denorm_default); >--- 250,302 ---- > bool is_zero () const; > bool is_infinity () const; > bool is_number () const; >+ bool is_inexact () const; >+ bool is_negative () const; >+ >+ status_t get_status () const { return status; } >+ class_t get_class () const { return fp_class; } > > // Conversions to integers. >! virtual void integer (int&, round_mode_t = round_default); >! virtual void integer (long&, round_mode_t = round_default); >! virtual void integer (unsigned int&, round_mode_t = round_default); >! virtual void integer (unsigned long&, round_mode_t = round_default); > > // Pack an fp into registers of various sizes. > void pack (cgen::SF&) const; > void pack (cgen::DF&) const; > void pack (cgen::SF& upper, cgen::SF& lower) const; > >+ virtual host_int_8 qnan_exponent (bool double_p) const >+ { >+ return EXPMAX (double_p); >+ } >+ >+ virtual host_int_8 qnan_fraction (bool double_p) const >+ { >+ // Force fraction to correct class. >+ host_int_8 frac = fraction; >+ frac >>= NR_GUARDS (double_p); >+ frac |= QUIET_NAN; >+ return frac; >+ } >+ >+ virtual host_int_8 snan_exponent (bool double_p) const >+ { >+ return EXPMAX (double_p); >+ } >+ >+ virtual host_int_8 snan_fraction (bool double_p) const >+ { >+ // Force fraction to correct class. >+ host_int_8 frac = fraction; >+ frac >>= NR_GUARDS (double_p); >+ frac &= ~QUIET_NAN; >+ return frac; >+ } >+ >+ virtual bool is_qnan_fraction (host_int_8 frac, bool double_p) const { return frac >= QUIET_NAN; } >+ > // Round an fp suitable for packing. > void round_32 (round_mode_t = round_default, enum denorm_t = denorm_default); > void round_64 (round_mode_t = round_default, enum denorm_t = denorm_default); >*************** namespace sidutil >*** 145,161 **** > denorm = 0x4000 > }; > >! private: > status_t status; > enum class_t fp_class; > int sign; > fraction_t fraction; > exp_t normal_exp; > >! void do_round (bool double_p, round_mode_t round, enum denorm_t denorm); >! status_t do_normal_round (int nr_guards, enum round_mode_t round); >! status_t do_normal_overflow (bool double_p, enum round_mode_t round); >! status_t do_normal_underflow (bool double_p, enum round_mode_t round); > > void int_to_fp (cgen::SI i); > void uint_to_fp (cgen::USI i); >--- 332,348 ---- > denorm = 0x4000 > }; > >! protected: > status_t status; > enum class_t fp_class; > int sign; > fraction_t fraction; > exp_t normal_exp; > >! virtual void do_round (bool double_p, round_mode_t round, enum denorm_t denorm); >! virtual status_t do_normal_round (int nr_guards, enum round_mode_t round); >! virtual status_t do_normal_overflow (bool double_p, enum round_mode_t round); >! virtual status_t do_normal_underflow (bool double_p, enum round_mode_t round); > > void int_to_fp (cgen::SI i); > void uint_to_fp (cgen::USI i); >*************** namespace sidutil >*** 164,188 **** > template void unpack (const T& t); > template void pack_any (T& t) const; > > friend std::ostream& operator<< (std::ostream& out, const fp& f); >- friend fp operator+ (const fp& l, const fp& r); >- friend fp operator- (const fp& l, const fp& r); >- friend fp operator* (const fp& l, const fp& r); >- friend fp operator/ (const fp& l, const fp& r); > }; > >- fp operator+ (const fp& l, const fp& r); >- fp operator- (const fp& l, const fp& r); >- fp operator* (const fp& l, const fp& r); >- fp operator/ (const fp& l, const fp& r); >- >- bool operator< (const fp& l, const fp& r); >- bool operator<= (const fp& l, const fp& r); >- bool operator== (const fp& l, const fp& r); >- bool operator!= (const fp& l, const fp& r); >- bool operator>= (const fp& l, const fp& r); >- bool operator> (const fp& l, const fp& r); >- > std::ostream& operator<< (std::ostream& op, const fp& f); > > // A number of useful constants. >--- 351,372 ---- > template void unpack (const T& t); > template void pack_any (T& t) const; > >+ public: >+ fp operator+ (const fp& r) const; >+ fp operator- (const fp& r) const; >+ fp operator* (const fp& r) const; >+ fp operator/ (const fp& r) const; >+ >+ bool operator< (const fp& r) const; >+ bool operator<= (const fp& r) const; >+ bool operator== (const fp& r) const; >+ bool operator!= (const fp& r) const; >+ bool operator>= (const fp& r) const; >+ bool operator> (const fp& r) const; >+ > friend std::ostream& operator<< (std::ostream& out, const fp& f); > }; > > std::ostream& operator<< (std::ostream& op, const fp& f); > > // A number of useful constants. >*************** namespace sidutil >*** 230,235 **** >--- 414,431 ---- > } > > inline bool >+ fp::is_negative () const >+ { >+ return (is_number () || is_zero ()) && sign; >+ } >+ >+ inline bool >+ fp::is_inexact () const >+ { >+ return status == inexact; >+ } >+ >+ inline bool > fp::is_denorm () const > { > return fp_class == class_denorm; > > >------------------------------------------------------------------------ > >// cgen-fpu.h - CPU components. -*- C++ -*- >// CGEN fpu support for SID >// >// Copyright (C) 2005 Red Hat. >// This file is part of SID and is licensed under the GPL. >// See the file COPYING.SID for conditions for redistribution. > >#ifndef CGEN_FPU_H >#define CGEN_FPU_H > >#include "cgen-cpu.h" >#include "fp.h" > >namespace cgen >{ >/* Floating point support is a little more complicated. > We want to support using either host fp insns or an accurate fp library. > We also want to support easily added variants (e.g. modified ieee). > This is done by using a virtual helper class 'cgen_fp_ops'. */ >class cgen_fpu; > >/* fpu operation class */ >class cgen_fp_ops { >public: > // default is no error checking > virtual void check_result (cgen_fpu*, fp &) {} > > /* basic SF ops */ > virtual SF addsf (cgen_fpu*, SF, SF); > virtual SF subsf (cgen_fpu*, SF, SF); > virtual SF mulsf (cgen_fpu*, SF, SF); > virtual SF divsf (cgen_fpu*, SF, SF); > virtual SF negsf (cgen_fpu*, SF); > virtual SF abssf (cgen_fpu*, SF); > virtual SF sqrtsf (cgen_fpu*, SF); >#if 0 > virtual SF invsf (cgen_fpu*, SF); > virtual SF cossf (cgen_fpu*, SF); > virtual SF sinsf (cgen_fpu*, SF); > virtual SF minsf (cgen_fpu*, SF, SF); > virtual SF maxsf (cgen_fpu*, SF, SF); >#endif > virtual int eqsf (cgen_fpu*, SF, SF); > virtual int nesf (cgen_fpu*, SF, SF); > virtual int ltsf (cgen_fpu*, SF, SF); > virtual int lesf (cgen_fpu*, SF, SF); > virtual int gtsf (cgen_fpu*, SF, SF); > virtual int gesf (cgen_fpu*, SF, SF); > >#if 0 > /* basic DF ops */ > virtual DF adddf (cgen_fpu*, DF, DF); > virtual DF subdf (cgen_fpu*, DF, DF); > virtual DF muldf (cgen_fpu*, DF, DF); > virtual DF divdf (cgen_fpu*, DF, DF); > virtual DF negdf (cgen_fpu*, DF); > virtual DF absdf (cgen_fpu*, DF); > virtual DF sqrtdf (cgen_fpu*, DF); > virtual DF invdf (cgen_fpu*, DF); > virtual DF cosdf (cgen_fpu*, DF); > virtual DF sindf (cgen_fpu*, DF); > virtual DF mindf (cgen_fpu*, DF, DF); > virtual DF maxdf (cgen_fpu*, DF, DF); > > virtual int eqdf (cgen_fpu*, DF, DF); > virtual int nedf (cgen_fpu*, DF, DF); > virtual int ltdf (cgen_fpu*, DF, DF); > virtual int ledf (cgen_fpu*, DF, DF); > virtual int gtdf (cgen_fpu*, DF, DF); > virtual int gedf (cgen_fpu*, DF, DF); > > /* SF/DF conversion ops */ > virtual DF fextsfdf (cgen_fpu*, SF); > virtual SF ftruncdfsf (cgen_fpu*, DF); >#endif // not implemented yet > > virtual SF floatsisf (cgen_fpu*, SI); >#if 0 // not implemented yet > virtual SF floatdisf (cgen_fpu*, DI); > virtual SF ufloatsisf (cgen_fpu*, USI); > virtual SF ufloatdisf (cgen_fpu*, UDI); >#endif // not implemented yet > > virtual SI fixsfsi (cgen_fpu*, SF); >#if 0 // not implemented yet > virtual DI fixsfdi (cgen_fpu*, SF); > virtual USI ufixsfsi (cgen_fpu*, SF); > virtual UDI ufixsfdi (cgen_fpu*, SF); > > virtual DF floatsidf (cgen_fpu*, SI); > virtual DF floatdidf (cgen_fpu*, DI); > virtual DF ufloatsidf (cgen_fpu*, USI); > virtual DF ufloatdidf (cgen_fpu*, UDI); > > virtual SI fixdfsi (cgen_fpu*, DF); > virtual DI fixdfdi (cgen_fpu*, DF); > virtual USI ufixdfsi (cgen_fpu*, DF); > virtual UDI ufixdfdi (cgen_fpu*, DF); > > /* XF mode support (kept separate 'cus not always present) */ > virtual XF addxf (cgen_fpu*, XF, XF); > virtual XF subxf (cgen_fpu*, XF, XF); > virtual XF mulxf (cgen_fpu*, XF, XF); > virtual XF divxf (cgen_fpu*, XF, XF); > virtual XF negxf (cgen_fpu*, XF); > virtual XF absxf (cgen_fpu*, XF); > virtual XF sqrtxf (cgen_fpu*, XF); > virtual XF invxf (cgen_fpu*, XF); > virtual XF cosxf (cgen_fpu*, XF); > virtual XF sinxf (cgen_fpu*, XF); > virtual XF minxf (cgen_fpu*, XF, XF); > virtual XF maxxf (cgen_fpu*, XF, XF); > > virtual int eqxf (cgen_fpu*, XF, XF); > virtual int nexf (cgen_fpu*, XF, XF); > virtual int ltxf (cgen_fpu*, XF, XF); > virtual int lexf (cgen_fpu*, XF, XF); > virtual int gtxf (cgen_fpu*, XF, XF); > virtual int gexf (cgen_fpu*, XF, XF); > > virtual XF extsfxf (cgen_fpu*, SF); > virtual XF extdfxf (cgen_fpu*, DF); > virtual SF truncxfsf (cgen_fpu*, XF); > virtual DF truncxfdf (cgen_fpu*, XF); > > virtual XF floatsixf (cgen_fpu*, SI); > virtual XF floatdixf (cgen_fpu*, DI); > virtual XF ufloatsixf (cgen_fpu*, USI); > virtual XF ufloatdixf (cgen_fpu*, UDI); > > virtual SI fixxfsi (cgen_fpu*, XF); > virtual DI fixxfdi (cgen_fpu*, XF); > virtual USI ufixxfsi (cgen_fpu*, XF); > virtual UDI ufixxfdi (cgen_fpu*, XF); > > /* TF mode support (kept separate 'cus not always present) */ > virtual TF addtf (cgen_fpu*, TF, TF); > virtual TF subtf (cgen_fpu*, TF, TF); > virtual TF multf (cgen_fpu*, TF, TF); > virtual TF divtf (cgen_fpu*, TF, TF); > virtual TF negtf (cgen_fpu*, TF); > virtual TF abstf (cgen_fpu*, TF); > virtual TF sqrttf (cgen_fpu*, TF); > virtual TF invtf (cgen_fpu*, TF); > virtual TF costf (cgen_fpu*, TF); > virtual TF sintf (cgen_fpu*, TF); > virtual TF mintf (cgen_fpu*, TF, TF); > virtual TF maxtf (cgen_fpu*, TF, TF); > > virtual int eqtf (cgen_fpu*, TF, TF); > virtual int netf (cgen_fpu*, TF, TF); > virtual int lttf (cgen_fpu*, TF, TF); > virtual int letf (cgen_fpu*, TF, TF); > virtual int gttf (cgen_fpu*, TF, TF); > virtual int getf (cgen_fpu*, TF, TF); > > virtual TF extsftf (cgen_fpu*, SF); > virtual TF extdftf (cgen_fpu*, DF); > virtual SF trunctfsf (cgen_fpu*, TF); > virtual DF trunctfdf (cgen_fpu*, TF); > > virtual TF floatsitf (cgen_fpu*, SI); > virtual TF floatditf (cgen_fpu*, DI); > virtual TF ufloatsitf (cgen_fpu*, USI); > virtual TF ufloatditf (cgen_fpu*, UDI); > > virtual SI fixtfsi (cgen_fpu*, TF); > virtual DI fixtfdi (cgen_fpu*, TF); > virtual USI ufixtfsi (cgen_fpu*, TF); > virtual UDI ufixtfdi (cgen_fpu*, TF); >#endif // not implemented yet >}; > >/* Instance of an fpu. */ >class cgen_fpu { > public: > cgen_fpu (cgen_bi_endian_cpu *c, cgen_fp_ops *o) : owner (c), ops (o) {} > cgen_bi_endian_cpu* owner; > cgen_fp_ops* ops; >}; > >}; // namespace cgen > >#endif /* CGEN_FPU_H */ > > >------------------------------------------------------------------------ > >// cgen-fpu.cxx - CPU components. -*- C++ -*- >// CGEN fpu support for SID >// >// Copyright (C) 2005 Red Hat. >// This file is part of SID and is licensed under the GPL. >// See the file COPYING.SID for conditions for redistribution. > >#include "cgen-fpu.h" >#include "fp.h" > >using namespace sidutil; > >namespace cgen >{ >/* basic SF ops */ >SF >cgen_fp_ops::addsf (cgen_fpu* fpu, SF x, SF y) >{ > fp r = fp (x) + fp (y); > check_result (fpu, r); > SF tmp; > r.pack (tmp); > return tmp; >} > >SF cgen_fp_ops::subsf (cgen_fpu* fpu, SF x, SF y) >{ > fp r = fp (x) - fp (y); > check_result (fpu, r); > SF tmp; > r.pack (tmp); > return tmp; >} > >SF cgen_fp_ops::mulsf (cgen_fpu* fpu, SF x, SF y) >{ > fp r = fp (x) * fp (y); > check_result (fpu, r); > SF tmp; > r.pack (tmp); > return tmp; >} > >SF cgen_fp_ops::divsf (cgen_fpu* fpu, SF x, SF y) >{ > fp r = fp (x) / fp (y); > check_result (fpu, r); > SF tmp; > r.pack (tmp); > return tmp; >} > >SF cgen_fp_ops::negsf (cgen_fpu* fpu, SF x) >{ > fp r (x); > r = fp::neg (r); > check_result (fpu, r); > SF tmp; > r.pack (tmp); > return tmp; >} > >SF cgen_fp_ops::abssf (cgen_fpu* fpu, SF x) >{ > fp r (x); > r = fp::abs (r); > check_result (fpu, r); > SF tmp; > r.pack (tmp); > return tmp; >} > >SF cgen_fp_ops::sqrtsf (cgen_fpu* fpu, SF x) >{ > fp r (x); > r = fp::sqrt (r); > check_result (fpu, r); > SF tmp; > r.pack (tmp); > return tmp; >} > > >#if 0 // not implemented yet >SF cgen_fp_ops::invsf (cgen_fpu*, SF); >SF cgen_fp_ops::cossf (cgen_fpu*, SF); >SF cgen_fp_ops::sinsf (cgen_fpu*, SF); >SF cgen_fp_ops::minsf (cgen_fpu*, SF, SF); >SF cgen_fp_ops::maxsf (cgen_fpu*, SF, SF); >#endif > >int cgen_fp_ops::eqsf (cgen_fpu*, SF x, SF y) >{ > return fp (x) == fp (y); >} >int cgen_fp_ops::nesf (cgen_fpu*, SF x, SF y) >{ > return fp (x) != fp (y); >} >int cgen_fp_ops::ltsf (cgen_fpu*, SF x, SF y) >{ > return fp (x) < fp (y); >} >int cgen_fp_ops::lesf (cgen_fpu*, SF x, SF y) >{ > return fp (x) <= fp (y); >} >int cgen_fp_ops::gtsf (cgen_fpu*, SF x, SF y) >{ > return fp (x) > fp (y); >} >int cgen_fp_ops::gesf (cgen_fpu*, SF x, SF y) >{ > return fp (x) >= fp (y); >} > >#if 0 >/* basic DF ops */ >DF cgen_fp_ops::adddf (cgen_fpu*, DF, DF); >DF cgen_fp_ops::subdf (cgen_fpu*, DF, DF); >DF cgen_fp_ops::muldf (cgen_fpu*, DF, DF); >DF cgen_fp_ops::divdf (cgen_fpu*, DF, DF); >DF cgen_fp_ops::negdf (cgen_fpu*, DF); >DF cgen_fp_ops::absdf (cgen_fpu*, DF); >DF cgen_fp_ops::sqrtdf (cgen_fpu*, DF); >DF cgen_fp_ops::invdf (cgen_fpu*, DF); >DF cgen_fp_ops::cosdf (cgen_fpu*, DF); >DF cgen_fp_ops::sindf (cgen_fpu*, DF); >DF cgen_fp_ops::mindf (cgen_fpu*, DF, DF); >DF cgen_fp_ops::maxdf (cgen_fpu*, DF, DF); > >int cgen_fp_ops::eqdf (cgen_fpu*, DF, DF); >int cgen_fp_ops::nedf (cgen_fpu*, DF, DF); >int cgen_fp_ops::ltdf (cgen_fpu*, DF, DF); >int cgen_fp_ops::ledf (cgen_fpu*, DF, DF); >int cgen_fp_ops::gtdf (cgen_fpu*, DF, DF); >int cgen_fp_ops::gedf (cgen_fpu*, DF, DF); > > /* SF/DF conversion ops */ >DF cgen_fp_ops::fextsfdf (cgen_fpu*, SF); >SF cgen_fp_ops::ftruncdfsf (cgen_fpu*, DF); > >#endif // not implemented yet >SF cgen_fp_ops::floatsisf (cgen_fpu* fpu, SI x) >{ > fp r = fp::from_int (x); > check_result (fpu, r); > SF tmp; > r.pack (tmp); > return tmp; >} >#if 0 // not implemented yet >SF cgen_fp_ops::floatdisf (cgen_fpu*, DI); >SF cgen_fp_ops::ufloatsisf (cgen_fpu*, USI); >SF cgen_fp_ops::ufloatdisf (cgen_fpu*, UDI); >#endif // not implemented yet > >SI cgen_fp_ops::fixsfsi (cgen_fpu*, SF x) >{ > fp r (x); > unsigned int tmp; > r.integer (tmp, fp::round_default); > return tmp; >} >#if 0 // not implemented yet >DI cgen_fp_ops::fixsfdi (cgen_fpu*, SF); >USI cgen_fp_ops::ufixsfsi (cgen_fpu*, SF) >UDI cgen_fp_ops::ufixsfdi (cgen_fpu*, SF); > >DF cgen_fp_ops::floatsidf (cgen_fpu*, SI); >DF cgen_fp_ops::floatdidf (cgen_fpu*, DI); >DF cgen_fp_ops::ufloatsidf (cgen_fpu*, USI); >DF cgen_fp_ops::ufloatdidf (cgen_fpu*, UDI); > >SI cgen_fp_ops::fixdfsi (cgen_fpu*, DF); >DI cgen_fp_ops::fixdfdi (cgen_fpu*, DF); >USI cgen_fp_ops::ufixdfsi (cgen_fpu*, DF); >UDI cgen_fp_ops::ufixdfdi (cgen_fpu*, DF); > >/* XF mode support (kept separate 'cus not always present) */ >XF cgen_fp_ops::addxf (cgen_fpu*, XF, XF); >XF cgen_fp_ops::subxf (cgen_fpu*, XF, XF); >XF cgen_fp_ops::mulxf (cgen_fpu*, XF, XF); >XF cgen_fp_ops::divxf (cgen_fpu*, XF, XF); >XF cgen_fp_ops::negxf (cgen_fpu*, XF); >XF cgen_fp_ops::absxf (cgen_fpu*, XF); >XF cgen_fp_ops::sqrtxf (cgen_fpu*, XF); >XF cgen_fp_ops::invxf (cgen_fpu*, XF); >XF cgen_fp_ops::cosxf (cgen_fpu*, XF); >XF cgen_fp_ops::sinxf (cgen_fpu*, XF); >XF cgen_fp_ops::minxf (cgen_fpu*, XF, XF); >XF cgen_fp_ops::maxxf (cgen_fpu*, XF, XF); > >int cgen_fp_ops::eqxf (cgen_fpu*, XF, XF); >int cgen_fp_ops::nexf (cgen_fpu*, XF, XF); >int cgen_fp_ops::ltxf (cgen_fpu*, XF, XF); >int cgen_fp_ops::lexf (cgen_fpu*, XF, XF); >int cgen_fp_ops::gtxf (cgen_fpu*, XF, XF); >int cgen_fp_ops::gexf (cgen_fpu*, XF, XF); > >XF cgen_fp_ops::extsfxf (cgen_fpu*, SF); >XF cgen_fp_ops::extdfxf (cgen_fpu*, DF); >SF cgen_fp_ops::truncxfsf (cgen_fpu*, XF); >DF cgen_fp_ops::truncxfdf (cgen_fpu*, XF); > >XF cgen_fp_ops::floatsixf (cgen_fpu*, SI); >XF cgen_fp_ops::floatdixf (cgen_fpu*, DI); >XF cgen_fp_ops::ufloatsixf (cgen_fpu*, USI); >XF cgen_fp_ops::ufloatdixf (cgen_fpu*, UDI); > >SI cgen_fp_ops::fixxfsi (cgen_fpu*, XF); >DI cgen_fp_ops::fixxfdi (cgen_fpu*, XF); >USI cgen_fp_ops::ufixxfsi (cgen_fpu*, XF); >UDI cgen_fp_ops::ufixxfdi (cgen_fpu*, XF); > >/* TF mode support (kept separate 'cus not always present) */ >TF cgen_fp_ops::addtf (cgen_fpu*, TF, TF); >TF cgen_fp_ops::subtf (cgen_fpu*, TF, TF); >TF cgen_fp_ops::multf (cgen_fpu*, TF, TF); >TF cgen_fp_ops::divtf (cgen_fpu*, TF, TF); >TF cgen_fp_ops::negtf (cgen_fpu*, TF); >TF cgen_fp_ops::abstf (cgen_fpu*, TF); >TF cgen_fp_ops::sqrttf (cgen_fpu*, TF); >TF cgen_fp_ops::invtf (cgen_fpu*, TF); >TF cgen_fp_ops::costf (cgen_fpu*, TF); >TF cgen_fp_ops::sintf (cgen_fpu*, TF); >TF cgen_fp_ops::mintf (cgen_fpu*, TF, TF); >TF cgen_fp_ops::maxtf (cgen_fpu*, TF, TF); > >int cgen_fp_ops::eqtf (cgen_fpu*, TF, TF); >int cgen_fp_ops::netf (cgen_fpu*, TF, TF); >int cgen_fp_ops::lttf (cgen_fpu*, TF, TF); >int cgen_fp_ops::letf (cgen_fpu*, TF, TF); >int cgen_fp_ops::gttf (cgen_fpu*, TF, TF); >int cgen_fp_ops::getf (cgen_fpu*, TF, TF); > >TF cgen_fp_ops::extsftf (cgen_fpu*, SF); >TF cgen_fp_ops::extdftf (cgen_fpu*, DF); >SF cgen_fp_ops::trunctfsf (cgen_fpu*, TF); >DF cgen_fp_ops::trunctfdf (cgen_fpu*, TF); > >TF cgen_fp_ops::floatsitf (cgen_fpu*, SI); >TF cgen_fp_ops::floatditf (cgen_fpu*, DI); >TF cgen_fp_ops::ufloatsitf (cgen_fpu*, USI); >TF cgen_fp_ops::ufloatditf (cgen_fpu*, UDI); > >SI cgen_fp_ops::fixtfsi (cgen_fpu*, TF); >DI cgen_fp_ops::fixtfdi (cgen_fpu*, TF); >USI cgen_fp_ops::ufixtfsi (cgen_fpu*, TF); >UDI cgen_fp_ops::ufixtfdi (cgen_fpu*, TF); >#endif // not implemented yet > >}; // namespace cgen > >