1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-25 17:29:50 +00:00

Some more floating point support.

git-svn-id: svn://svn.cc65.org/cc65/trunk@3886 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz 2008-08-11 17:51:00 +00:00
parent 0b60ac4716
commit 0b4f6426e2
11 changed files with 448 additions and 60 deletions

View File

@ -6,8 +6,8 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2006 Ullrich von Bassewitz */ /* (C) 1998-2008 Ullrich von Bassewitz */
/* Römerstraße 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
@ -43,6 +43,7 @@
#include "codegen.h" #include "codegen.h"
#include "datatype.h" #include "datatype.h"
#include "error.h" #include "error.h"
#include "fp.h"
#include "funcdesc.h" #include "funcdesc.h"
#include "global.h" #include "global.h"
#include "symtab.h" #include "symtab.h"

View File

@ -6,8 +6,8 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 1998-2006 Ullrich von Bassewitz */ /* (C) 1998-2008 Ullrich von Bassewitz */
/* Römerstrasse 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
@ -159,14 +159,14 @@ struct Type {
#define UNSPECIFIED -1L /* Element count was not specified */ #define UNSPECIFIED -1L /* Element count was not specified */
#define FLEXIBLE 0L /* Flexible array struct member */ #define FLEXIBLE 0L /* Flexible array struct member */
/* Sizes */ /* Sizes. Floating point sizes come from fp.h */
#define SIZEOF_CHAR 1 #define SIZEOF_CHAR 1
#define SIZEOF_SHORT 2 #define SIZEOF_SHORT 2
#define SIZEOF_INT 2 #define SIZEOF_INT 2
#define SIZEOF_LONG 4 #define SIZEOF_LONG 4
#define SIZEOF_LONGLONG 8 #define SIZEOF_LONGLONG 8
#define SIZEOF_FLOAT 4 #define SIZEOF_FLOAT (FP_F_Size())
#define SIZEOF_DOUBLE 4 #define SIZEOF_DOUBLE (FP_D_Size())
#define SIZEOF_PTR 2 #define SIZEOF_PTR 2
/* Predefined type strings */ /* Predefined type strings */

View File

@ -1679,6 +1679,8 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers)
case T_UINT: case T_UINT:
case T_LONG: case T_LONG:
case T_ULONG: case T_ULONG:
case T_FLOAT:
case T_DOUBLE:
return ParseScalarInit (T); return ParseScalarInit (T);
case T_PTR: case T_PTR:

View File

@ -6,8 +6,8 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2002-2006 Ullrich von Bassewitz */ /* (C) 2002-2008 Ullrich von Bassewitz */
/* Römerstraße 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
@ -41,6 +41,7 @@
#include "asmlabel.h" #include "asmlabel.h"
#include "datatype.h" #include "datatype.h"
#include "error.h" #include "error.h"
#include "exprdesc.h"
#include "stackptr.h" #include "stackptr.h"
#include "symentry.h" #include "symentry.h"
#include "exprdesc.h" #include "exprdesc.h"
@ -61,7 +62,7 @@ ExprDesc* ED_Init (ExprDesc* Expr)
Expr->Flags = 0; Expr->Flags = 0;
Expr->Name = 0; Expr->Name = 0;
Expr->IVal = 0; Expr->IVal = 0;
Expr->FVal = 0.0; Expr->FVal = FP_D_Make (0.0);
return Expr; return Expr;
} }
@ -141,7 +142,7 @@ ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type)
Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL; Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
Expr->Name = 0; Expr->Name = 0;
Expr->IVal = Value; Expr->IVal = Value;
Expr->FVal = 0.0; Expr->FVal = FP_D_Make (0.0);
return Expr; return Expr;
} }
@ -155,7 +156,7 @@ ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value)
Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL; Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL;
Expr->Name = 0; Expr->Name = 0;
Expr->IVal = Value; Expr->IVal = Value;
Expr->FVal = 0.0; Expr->FVal = FP_D_Make (0.0);
return Expr; return Expr;
} }
@ -171,7 +172,7 @@ ExprDesc* ED_MakeRValExpr (ExprDesc* Expr)
Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL); Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL);
Expr->Name = 0; Expr->Name = 0;
Expr->IVal = 0; /* No offset */ Expr->IVal = 0; /* No offset */
Expr->FVal = 0.0; Expr->FVal = FP_D_Make (0.0);
return Expr; return Expr;
} }
@ -187,7 +188,7 @@ ExprDesc* ED_MakeLValExpr (ExprDesc* Expr)
Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL); Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL);
Expr->Name = 0; Expr->Name = 0;
Expr->IVal = 0; /* No offset */ Expr->IVal = 0; /* No offset */
Expr->FVal = 0.0; Expr->FVal = FP_D_Make (0.0);
return Expr; return Expr;
} }
@ -253,7 +254,7 @@ void PrintExprDesc (FILE* F, ExprDesc* E)
"Raw type: (unknown)\n"); "Raw type: (unknown)\n");
} }
fprintf (F, "IVal: 0x%08lX\n", E->IVal); 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; Flags = E->Flags;
Sep = '('; Sep = '(';

View File

@ -6,8 +6,8 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2002-2006 Ullrich von Bassewitz */ /* (C) 2002-2008 Ullrich von Bassewitz */
/* Römerstraße 52 */ /* Roemerstrasse 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
/* */ /* */
@ -41,6 +41,7 @@
#include <string.h> #include <string.h>
/* common */ /* common */
#include "fp.h"
#include "inline.h" #include "inline.h"
/* cc65 */ /* cc65 */
@ -89,7 +90,7 @@ struct ExprDesc {
unsigned Flags; unsigned Flags;
unsigned long Name; /* Name or label number */ unsigned long Name; /* Name or label number */
long IVal; /* Integer value if expression constant */ long IVal; /* Integer value if expression constant */
float FVal; /* Floating point value */ Double FVal; /* Floating point value */
}; };

View File

@ -42,6 +42,7 @@
/* common */ /* common */
#include "chartype.h" #include "chartype.h"
#include "fp.h"
#include "tgttrans.h" #include "tgttrans.h"
/* cc65 */ /* cc65 */
@ -583,39 +584,28 @@ static void NumericConst (void)
} else { } else {
/* Float constant */ /* 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 */ /* Check for a fractional part and read it */
if (CurC == '.') { if (CurC == '.') {
unsigned Digits; Double Scale;
unsigned long Frac;
unsigned long Scale;
/* Skip the dot */ /* Skip the dot */
NextChar (); NextChar ();
/* Read fractional digits. Since we support only 32 bit floats /* Read fractional digits */
* with a maximum of 7 fractional digits, we read the fractional Scale = FP_D_Make (1.0);
* 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;
while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) { while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) {
if (Digits < 8) { /* Get the value of this digit */
Frac = Frac * Base + DigitVal; Double FracVal = FP_D_Div (FP_D_FromInt (DigitVal * Base), Scale);
++Digits; /* Add it to the float value */
Scale *= Base; FVal = FP_D_Add (FVal, FracVal);
} /* Scale base */
Scale = FP_D_Mul (Scale, FP_D_FromInt (DigitVal));
/* Skip the digit */
NextChar (); NextChar ();
} }
/* Scale the fractional part and add it */
if (Frac) {
FVal += ((double) Frac) / ((double) Scale);
}
} }
/* Check for an exponent and read it */ /* Check for an exponent and read it */
@ -664,7 +654,7 @@ static void NumericConst (void)
/* Scale the exponent and adjust the value accordingly */ /* Scale the exponent and adjust the value accordingly */
if (Exp) { if (Exp) {
FVal *= pow (10, Exp); FVal = FP_D_Mul (FVal, FP_D_Make (pow (10, Exp)));
} }
} }

View File

@ -38,6 +38,9 @@
/* common */
#include "fp.h"
/* cc65 */ /* cc65 */
#include "datatype.h" #include "datatype.h"
#include "ident.h" #include "ident.h"
@ -192,7 +195,7 @@ typedef struct Token Token;
struct Token { struct Token {
token_t Tok; /* The token itself */ token_t Tok; /* The token itself */
long IVal; /* The integer attribute */ long IVal; /* The integer attribute */
double FVal; /* The float attribute */ Double FVal; /* The float attribute */
ident Ident; /* Identifier if IDENT */ ident Ident; /* Identifier if IDENT */
LineInfo* LI; /* Source line where the token comes from */ LineInfo* LI; /* Source line where the token comes from */
Type* Type; /* Type if integer or float constant */ Type* Type; /* Type if integer or float constant */

241
src/common/fp.c Normal file
View File

@ -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 <string.h>
/* 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;
}

147
src/common/fp.h Normal file
View File

@ -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 <stddef.h>
/*****************************************************************************/
/* 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

View File

@ -22,6 +22,7 @@ OBJS = abend.o \
filepos.o \ filepos.o \
filetype.o \ filetype.o \
fname.o \ fname.o \
fp.o \
hashstr.o \ hashstr.o \
hashtab.o \ hashtab.o \
intstack.o \ intstack.o \

View File

@ -68,6 +68,7 @@ OBJS = abend.obj \
filepos.obj \ filepos.obj \
filetype.obj \ filetype.obj \
fname.obj \ fname.obj \
fp.obj \
hashstr.obj \ hashstr.obj \
hashtab.obj \ hashtab.obj \
intstack.obj \ intstack.obj \