1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-09 06:29:38 +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 */
/* 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"

View File

@ -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)

View File

@ -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:

View File

@ -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 = '(';

View File

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

View File

@ -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)));
}
}

View File

@ -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 */

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 \
filetype.o \
fname.o \
fp.o \
hashstr.o \
hashtab.o \
intstack.o \

View File

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