From 0b4f6426e25be1861a54647d0f015c4365db286f Mon Sep 17 00:00:00 2001 From: uz Date: Mon, 11 Aug 2008 17:51:00 +0000 Subject: [PATCH] Some more floating point support. git-svn-id: svn://svn.cc65.org/cc65/trunk@3886 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/datatype.c | 5 +- src/cc65/datatype.h | 12 +- src/cc65/declare.c | 36 +++--- src/cc65/exprdesc.c | 17 +-- src/cc65/exprdesc.h | 7 +- src/cc65/scanner.c | 36 ++---- src/cc65/scanner.h | 5 +- src/common/fp.c | 241 +++++++++++++++++++++++++++++++++++++ src/common/fp.h | 147 ++++++++++++++++++++++ src/common/make/gcc.mak | 1 + src/common/make/watcom.mak | 1 + 11 files changed, 448 insertions(+), 60 deletions(-) create mode 100644 src/common/fp.c create mode 100644 src/common/fp.h diff --git a/src/cc65/datatype.c b/src/cc65/datatype.c index 4c7e23ff0..738a8afaa 100644 --- a/src/cc65/datatype.c +++ b/src/cc65/datatype.c @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 1998-2006 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* (C) 1998-2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -43,6 +43,7 @@ #include "codegen.h" #include "datatype.h" #include "error.h" +#include "fp.h" #include "funcdesc.h" #include "global.h" #include "symtab.h" diff --git a/src/cc65/datatype.h b/src/cc65/datatype.h index c3467d0dc..3b5b99245 100644 --- a/src/cc65/datatype.h +++ b/src/cc65/datatype.h @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 1998-2006 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* (C) 1998-2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -159,14 +159,14 @@ struct Type { #define UNSPECIFIED -1L /* Element count was not specified */ #define FLEXIBLE 0L /* Flexible array struct member */ -/* Sizes */ +/* Sizes. Floating point sizes come from fp.h */ #define SIZEOF_CHAR 1 #define SIZEOF_SHORT 2 #define SIZEOF_INT 2 #define SIZEOF_LONG 4 #define SIZEOF_LONGLONG 8 -#define SIZEOF_FLOAT 4 -#define SIZEOF_DOUBLE 4 +#define SIZEOF_FLOAT (FP_F_Size()) +#define SIZEOF_DOUBLE (FP_D_Size()) #define SIZEOF_PTR 2 /* Predefined type strings */ @@ -507,7 +507,7 @@ INLINE int IsSignSigned (const Type* T) #endif TypeCode GetQualifier (const Type* T) attribute ((const)); -/* Get the qualifier from the given type string */ +/* Get the qualifier from the given type string */ #if defined(HAVE_INLINE) INLINE int IsQualConst (const Type* T) diff --git a/src/cc65/declare.c b/src/cc65/declare.c index 6cb45dada..cf3521f8f 100644 --- a/src/cc65/declare.c +++ b/src/cc65/declare.c @@ -1208,7 +1208,7 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode) /* For anthing that is not a function or typedef, check for an implicit * int declaration. */ - if ((D->StorageClass & SC_FUNC) != SC_FUNC && + if ((D->StorageClass & SC_FUNC) != SC_FUNC && (D->StorageClass & SC_TYPEDEF) != SC_TYPEDEF) { /* If the standard was not set explicitly to C89, print a warning * for variables with implicit int type. @@ -1612,11 +1612,11 @@ static unsigned ParseVoidInit (void) case T_SCHAR: case T_UCHAR: - if (ED_IsConstAbsInt (&Expr)) { - /* Make it byte sized */ - Expr.IVal &= 0xFF; - } - DefineData (&Expr); + if (ED_IsConstAbsInt (&Expr)) { + /* Make it byte sized */ + Expr.IVal &= 0xFF; + } + DefineData (&Expr); Size += SIZEOF_CHAR; break; @@ -1626,26 +1626,26 @@ static unsigned ParseVoidInit (void) case T_UINT: case T_PTR: case T_ARRAY: - if (ED_IsConstAbsInt (&Expr)) { + if (ED_IsConstAbsInt (&Expr)) { /* Make it word sized */ - Expr.IVal &= 0xFFFF; - } - DefineData (&Expr); - Size += SIZEOF_INT; + Expr.IVal &= 0xFFFF; + } + DefineData (&Expr); + Size += SIZEOF_INT; break; case T_LONG: case T_ULONG: - if (ED_IsConstAbsInt (&Expr)) { + if (ED_IsConstAbsInt (&Expr)) { /* Make it dword sized */ - Expr.IVal &= 0xFFFFFFFF; - } - DefineData (&Expr); - Size += SIZEOF_LONG; + Expr.IVal &= 0xFFFFFFFF; + } + DefineData (&Expr); + Size += SIZEOF_LONG; break; default: - Error ("Illegal type in initialization"); + Error ("Illegal type in initialization"); break; } @@ -1679,6 +1679,8 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers) case T_UINT: case T_LONG: case T_ULONG: + case T_FLOAT: + case T_DOUBLE: return ParseScalarInit (T); case T_PTR: diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index c99125550..0d282c94a 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 2002-2006 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* (C) 2002-2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -41,6 +41,7 @@ #include "asmlabel.h" #include "datatype.h" #include "error.h" +#include "exprdesc.h" #include "stackptr.h" #include "symentry.h" #include "exprdesc.h" @@ -61,7 +62,7 @@ ExprDesc* ED_Init (ExprDesc* Expr) Expr->Flags = 0; Expr->Name = 0; Expr->IVal = 0; - Expr->FVal = 0.0; + Expr->FVal = FP_D_Make (0.0); return Expr; } @@ -141,7 +142,7 @@ ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type) Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL; Expr->Name = 0; Expr->IVal = Value; - Expr->FVal = 0.0; + Expr->FVal = FP_D_Make (0.0); return Expr; } @@ -155,7 +156,7 @@ ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value) Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL; Expr->Name = 0; Expr->IVal = Value; - Expr->FVal = 0.0; + Expr->FVal = FP_D_Make (0.0); return Expr; } @@ -171,7 +172,7 @@ ExprDesc* ED_MakeRValExpr (ExprDesc* Expr) Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL); Expr->Name = 0; Expr->IVal = 0; /* No offset */ - Expr->FVal = 0.0; + Expr->FVal = FP_D_Make (0.0); return Expr; } @@ -187,7 +188,7 @@ ExprDesc* ED_MakeLValExpr (ExprDesc* Expr) Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL); Expr->Name = 0; Expr->IVal = 0; /* No offset */ - Expr->FVal = 0.0; + Expr->FVal = FP_D_Make (0.0); return Expr; } @@ -253,7 +254,7 @@ void PrintExprDesc (FILE* F, ExprDesc* E) "Raw type: (unknown)\n"); } fprintf (F, "IVal: 0x%08lX\n", E->IVal); - fprintf (F, "FVal: %f\n", E->FVal); + fprintf (F, "FVal: %f\n", FP_D_ToFloat (E->FVal)); Flags = E->Flags; Sep = '('; diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index bdf3662d0..6876bfd07 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 2002-2006 Ullrich von Bassewitz */ -/* Römerstraße 52 */ +/* (C) 2002-2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -41,6 +41,7 @@ #include /* common */ +#include "fp.h" #include "inline.h" /* cc65 */ @@ -89,7 +90,7 @@ struct ExprDesc { unsigned Flags; unsigned long Name; /* Name or label number */ long IVal; /* Integer value if expression constant */ - float FVal; /* Floating point value */ + Double FVal; /* Floating point value */ }; diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index cc073e373..2f5bfecb0 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -42,6 +42,7 @@ /* common */ #include "chartype.h" +#include "fp.h" #include "tgttrans.h" /* cc65 */ @@ -583,39 +584,28 @@ static void NumericConst (void) } else { /* Float constant */ - double FVal = IVal; /* Convert to float */ + Double FVal = FP_D_FromInt (IVal); /* Convert to double */ /* Check for a fractional part and read it */ if (CurC == '.') { - unsigned Digits; - unsigned long Frac; - unsigned long Scale; + Double Scale; /* Skip the dot */ NextChar (); - /* Read fractional digits. Since we support only 32 bit floats - * with a maximum of 7 fractional digits, we read the fractional - * part as integer with up to 8 digits and drop the remainder. - * This avoids an overflow of Frac and Scale. - */ - Digits = 0; - Frac = 0; - Scale = 1; + /* Read fractional digits */ + Scale = FP_D_Make (1.0); while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) { - if (Digits < 8) { - Frac = Frac * Base + DigitVal; - ++Digits; - Scale *= Base; - } + /* Get the value of this digit */ + Double FracVal = FP_D_Div (FP_D_FromInt (DigitVal * Base), Scale); + /* Add it to the float value */ + FVal = FP_D_Add (FVal, FracVal); + /* Scale base */ + Scale = FP_D_Mul (Scale, FP_D_FromInt (DigitVal)); + /* Skip the digit */ NextChar (); } - - /* Scale the fractional part and add it */ - if (Frac) { - FVal += ((double) Frac) / ((double) Scale); - } } /* Check for an exponent and read it */ @@ -664,7 +654,7 @@ static void NumericConst (void) /* Scale the exponent and adjust the value accordingly */ if (Exp) { - FVal *= pow (10, Exp); + FVal = FP_D_Mul (FVal, FP_D_Make (pow (10, Exp))); } } diff --git a/src/cc65/scanner.h b/src/cc65/scanner.h index b98170697..0b5b19a3e 100644 --- a/src/cc65/scanner.h +++ b/src/cc65/scanner.h @@ -38,6 +38,9 @@ +/* common */ +#include "fp.h" + /* cc65 */ #include "datatype.h" #include "ident.h" @@ -192,7 +195,7 @@ typedef struct Token Token; struct Token { token_t Tok; /* The token itself */ long IVal; /* The integer attribute */ - double FVal; /* The float attribute */ + Double FVal; /* The float attribute */ ident Ident; /* Identifier if IDENT */ LineInfo* LI; /* Source line where the token comes from */ Type* Type; /* Type if integer or float constant */ diff --git a/src/common/fp.c b/src/common/fp.c new file mode 100644 index 000000000..c9300c52d --- /dev/null +++ b/src/common/fp.c @@ -0,0 +1,241 @@ +/*****************************************************************************/ +/* */ +/* fp.c */ +/* */ +/* Floating point support */ +/* */ +/* */ +/* */ +/* (C) 2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +/* The compiler must use the same floating point arithmetic as the target + * platform, otherwise expressions will yield a different result when + * evaluated in the compiler or on the target platform. Since writing a target + * and source library is almost double the work, we will at least add the + * hooks here, and define functions for a plug in library that may be added + * at a later time. Currently we use the builtin data types of the compiler + * that translates cc65. + */ + + + +#include + +/* common */ +#include "fp.h" +#include "xmalloc.h" + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +#define F_SIZE sizeof(float) +#define D_SIZE sizeof(float) /* NOT double! */ + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +size_t FP_F_Size (void) +/* Return the size of the data type float */ +{ + return F_SIZE; +} + + + +unsigned char* FP_F_Data (Float Val) +/* Return the raw data of a float in a malloc'ed buffer. Free after use. */ +{ + return memcpy (xmalloc (F_SIZE), &Val.V, F_SIZE); +} + + + +Float FP_F_Make (float Val) +/* Make a floating point variable from a float value */ +{ + Float D; + D.V = Val; + return D; +} + + + +Float FP_F_FromInt (long Val) +/* Convert an integer into a floating point variable */ +{ + Float D; + D.V = Val; + return D; +} + + + +float FP_F_ToFloat (Float Val) +/* Convert a Float into a native float */ +{ + return Val.V; +} + + + +Float FP_F_Add (Float Left, Float Right) +/* Add two floats */ +{ + Float D; + D.V = Left.V + Right.V; + return D; +} + + + +Float FP_F_Sub (Float Left, Float Right) +/* Subtract two floats */ +{ + Float D; + D.V = Left.V - Right.V; + return D; +} + + + +Float FP_F_Mul (Float Left, Float Right) +/* Multiplicate two floats */ +{ + Float D; + D.V = Left.V * Right.V; + return D; +} + + + +Float FP_F_Div (Float Left, Float Right) +/* Divide two floats */ +{ + Float D; + D.V = Left.V / Right.V; + return D; +} + + + +size_t FP_D_Size (void) +/* Return the size of the data type double */ +{ + return D_SIZE; +} + + + +unsigned char* FP_D_Data (Double Val) +/* Return the raw data of a double in a malloc'ed buffer. Free after use. */ +{ + float F = Val.V; + return memcpy (xmalloc (F_SIZE), &F, F_SIZE); +} + + + +Double FP_D_Make (double Val) +/* Make a floating point variable from a float value */ +{ + Double D; + D.V = Val; + return D; +} + + + + +Double FP_D_FromInt (long Val) +/* Convert an integer into a floating point variable */ +{ + Double D; + D.V = Val; + return D; +} + + + +double FP_D_ToFloat (Double Val) +/* Convert a Double into a native double */ +{ + return Val.V; +} + + + +Double FP_D_Add (Double Left, Double Right) +/* Add two floats */ +{ + Double D; + D.V = Left.V + Right.V; + return D; +} + + + +Double FP_D_Sub (Double Left, Double Right) +/* Subtract two floats */ +{ + Double D; + D.V = Left.V - Right.V; + return D; +} + + + +Double FP_D_Mul (Double Left, Double Right) +/* Multiplicate two floats */ +{ + Double D; + D.V = Left.V * Right.V; + return D; +} + + + +Double FP_D_Div (Double Left, Double Right) +/* Divide two floats */ +{ + Double D; + D.V = Left.V / Right.V; + return D; +} + + + diff --git a/src/common/fp.h b/src/common/fp.h new file mode 100644 index 000000000..6886d51ac --- /dev/null +++ b/src/common/fp.h @@ -0,0 +1,147 @@ +/*****************************************************************************/ +/* */ +/* fp.h */ +/* */ +/* Floating point support */ +/* */ +/* */ +/* */ +/* (C) 2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +/* The compiler must use the same floating point arithmetic as the target + * platform, otherwise expressions will yield a different result when + * evaluated in the compiler or on the target platform. Since writing a target + * and source library is almost double the work, we will at least add the + * hooks here, and define functions for a plug in library that may be added + * at a later time. Currently we use the builtin data types of the compiler + * that translates cc65. + * + * BEWARE: This code will currently only work on little endian systems! + * + */ + + + +#ifndef FP_H +#define FP_H + + + +#include + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + +typedef union Float Float; +union Float { + float V; +}; + + + +typedef union Double Double; +union Double { + double V; +}; + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +size_t FP_F_Size (void); +/* Return the size of the data type float */ + +unsigned char* FP_F_Data (Float Val); +/* Return the raw data of a float in a malloc'ed buffer. Free after use. */ + +Float FP_F_Make (float Val); +/* Make a floating point variable from a float value */ + +Float FP_F_FromInt (long Val); +/* Convert an integer into a floating point variable */ + +float FP_F_ToFloat (Float Val); +/* Convert a Float into a native float */ + +Float FP_F_Add (Float Left, Float Right); +/* Add two floats */ + +Float FP_F_Sub (Float Left, Float Right); +/* Subtract two floats */ + +Float FP_F_Mul (Float Left, Float Right); +/* Multiplicate two floats */ + +Float FP_F_Div (Float Left, Float Right); +/* Divide two floats */ + +size_t FP_D_Size (void); +/* Return the size of the data type double */ + +unsigned char* FP_D_Data (Double Val); +/* Return the raw data of a double in a malloc'ed buffer. Free after use. */ + +Double FP_D_Make (double Val); +/* Make a floating point variable from a float value */ + +Double FP_D_FromInt (long Val); +/* Convert an integer into a floating point variable */ + +double FP_D_ToFloat (Double Val); +/* Convert a Double into a native double */ + +Double FP_D_Add (Double Left, Double Right); +/* Add two floats */ + +Double FP_D_Sub (Double Left, Double Right); +/* Subtract two floats */ + +Double FP_D_Mul (Double Left, Double Right); +/* Multiplicate two floats */ + +Double FP_D_Div (Double Left, Double Right); +/* Divide two floats */ + + + +/* End of fp.h */ + +#endif + + + + + diff --git a/src/common/make/gcc.mak b/src/common/make/gcc.mak index 56e90448a..f2118253e 100644 --- a/src/common/make/gcc.mak +++ b/src/common/make/gcc.mak @@ -22,6 +22,7 @@ OBJS = abend.o \ filepos.o \ filetype.o \ fname.o \ + fp.o \ hashstr.o \ hashtab.o \ intstack.o \ diff --git a/src/common/make/watcom.mak b/src/common/make/watcom.mak index 6d428d00d..db3c2863c 100644 --- a/src/common/make/watcom.mak +++ b/src/common/make/watcom.mak @@ -68,6 +68,7 @@ OBJS = abend.obj \ filepos.obj \ filetype.obj \ fname.obj \ + fp.obj \ hashstr.obj \ hashtab.obj \ intstack.obj \ -- 2.39.2