Lots of fixes for floating point handling; version now at 1.11.0.
authorShamus Hammons <jlhamm@acm.org>
Sun, 21 Jan 2018 14:25:06 +0000 (08:25 -0600)
committerShamus Hammons <jlhamm@acm.org>
Sun, 21 Jan 2018 14:25:06 +0000 (08:25 -0600)
Some of the following changes are ggn's, and some are mine:

 - When tokenizing floats we need to store them using a double pointer
 - PTR union needed a (double *)
 - Major changes to float depositing in eagen0.c
 - Reverted the changes in expr.c so at least floats are processed by
   expr() and friends
 - SYM svalue needs to be 64 bits
 - When EQUing a float symbol don't chop off the upper 32 bits from eval
 - Added fltpoint.{c,h} in order to properly create IEEE-754 floating
   point and Motorola extended numbers
 - Fixed float evaluations in evexpr()
 - Fixed floating point depositions in direct.c (in d_dc())
 - Upped the BSD image limit in object.c to 8MB for crazy people making
   6MB Jaguar ROMs (will need a real fix at some point)

16 files changed:
direct.c
eagen.c
eagen0.c
expr.c
fltpoint.c [new file with mode: 0644]
fltpoint.h [new file with mode: 0644]
mach.c
makefile
object.c
procln.c
rmac.h
sect.h
symbol.c
symbol.h
token.c
version.h

index 155fa3fb360821bc945bb0e8e3a79ffd6fe973a9..7447553694944895c62c5e94dd428ba34c62ca4f 100644 (file)
--- a/direct.c
+++ b/direct.c
@@ -11,6 +11,7 @@
 #include "amode.h"
 #include "error.h"
 #include "expr.h"
+#include "fltpoint.h"
 #include "listing.h"
 #include "mach.h"
 #include "macro.h"
@@ -20,8 +21,6 @@
 #include "sect.h"
 #include "symbol.h"
 #include "token.h"
-#include "math.h"
-#include "sect.h"
 
 #define DEF_KW
 #include "kwtab.h"
@@ -1149,43 +1148,46 @@ int d_dc(WORD siz)
                        D_quad(eval);
                        break;
                case SIZS:
+                       // 32-bit float size
                        if (m6502)
                                return error(in_6502mode);
 
                        if (!defined)
                        {
-                               float vv = 0;
                                AddFixup(FU_FLOATSING, sloc, exprbuf);
-
-                               D_single(vv);
+                               D_long(0);
                        }
                        else
                        {
                                if (tdb)
                                        MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL);
 
-                               D_single(eval);
+                               PTR ptr;
+                               ptr.u64 = &eval;
+                               uint32_t ieee754 = FloatToIEEE754((float)*ptr.dp);
+                               D_long(ieee754);
                        }
 
                        break;
                case SIZD:
+                       // 64-bit double size
                        if (m6502)
                                return error(in_6502mode);
 
                        if (!defined)
                        {
-                               double vv = 0;
                                AddFixup(FU_FLOATDOUB, sloc, exprbuf);
-
-                               D_double(vv);
+                               D_quad(0LL);
                        }
                        else
                        {
                                if (tdb)
                                        MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL);
 
-                               double vv = *(double *)&eval;
-                               D_double(vv);
+                               PTR ptr;
+                               ptr.u64 = &eval;
+                               uint64_t ieee754 = DoubleToIEEE754(*ptr.dp);
+                               D_quad(ieee754);
                        }
 
                        break;
@@ -1193,20 +1195,23 @@ int d_dc(WORD siz)
                        if (m6502)
                                return error(in_6502mode);
 
+                       uint8_t extDbl[12];
+                       memset(extDbl, 0, 12);
+
                        if (!defined)
                        {
-                               double vv = 0;
                                AddFixup(FU_FLOATEXT, sloc, exprbuf);
-
-                               D_extend(vv);
+                               D_extend(extDbl);
                        }
                        else
                        {
                                if (tdb)
                                        MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL);
 
-                               float vv = *(double *)&eval;
-                               D_extend(vv);
+                               PTR ptr;
+                               ptr.u64 = &eval;
+                               DoubleToExtended(*ptr.dp, extDbl);
+                               D_extend(extDbl);
                        }
 
                        break;
diff --git a/eagen.c b/eagen.c
index 1f18b8598df87c4629b680730428df3740b5d0b1..ae349b8d22eade09a446ed9cc7c2f28341c3844b 100644 (file)
--- a/eagen.c
+++ b/eagen.c
@@ -8,10 +8,10 @@
 
 #include "eagen.h"
 #include "amode.h"
-#include "sect.h"
-#include "mark.h"
 #include "error.h"
+#include "fltpoint.h"
 #include "mach.h"
+#include "mark.h"
 #include "riscasm.h"
 #include "sect.h"
 #include "token.h"
index 62e686c144859631a44d8f5026a84e9828d16300..b4b58861a24425c57f695a4f824a1bcd46887d2a 100644 (file)
--- a/eagen0.c
+++ b/eagen0.c
@@ -15,6 +15,7 @@ int eaNgen(WORD siz)
        vbd = (uint32_t)aNbdexval;
        wbd = (WORD)(aNbdexattr & DEFINED);
        tdbbd = (WORD)(aNbdexattr & TDB);
+       uint8_t extDbl[12];
 
        switch (amN)
        {
@@ -213,20 +214,23 @@ int eaNgen(WORD siz)
                        // 68881/68882/68040 only
                        if (w)
                        {
-                               float vv;
                                if (tdb)
                                        MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL);
 
-                               vv = (float)v;
-
-                               D_single(vv);
+                               // The value passed back from expr() is an internal C double;
+                               // so we have to access it as such then convert it to an
+                               // IEEE-754 float so we can store it as such in the instruction
+                               // stream here.
+                               PTR p;
+                               p.u64 = &aNexval;
+                               float f = (float)*p.dp;
+                               uint32_t ieee754 = FloatToIEEE754(f);
+                               D_long(ieee754);
                        }
                        else
                        {
-                               float vv = 0;
                                AddFixup(FU_FLOATSING, sloc, aNexpr);
-
-                               D_single(vv);
+                               D_long(0);      // IEEE-754 zero is all zeroes
                        }
 
                break;
@@ -234,26 +238,19 @@ int eaNgen(WORD siz)
                        // 68881/68882/68040 only
                        if (w)
                        {
-                               double vv;
-                               unsigned long long vvv;
                                if (tdb)
                                        MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL);
 
-                               // We want to store the IEE754 float into ram from a generic
-                               // 32-bit int. First, convert it to double float, then cast
-                               // that to 64-bit, then convert to big endian (if needed)
-                               // and then store it (phew!)
-                               vv = *(float *)&aNexval;
-                               vvv = BYTESWAP64(*(unsigned long long *)&vv);
-
-                               D_double(vvv);
+                               PTR p;
+                               p.u64 = &aNexval;
+                               double d = *p.dp;
+                               uint64_t ieee754 = DoubleToIEEE754(d);
+                               D_quad(ieee754);
                        }
                        else
                        {
-                               unsigned long long vvv = 0;
                                AddFixup(FU_FLOATDOUB, sloc, aNexpr);
-
-                               D_double(vvv);
+                               D_quad(0LL);    // IEEE-754 zero is all zeroes
                        }
 
                        break;
@@ -261,25 +258,19 @@ int eaNgen(WORD siz)
                        // 68881/68882/68040 only
                        if (w)
                        {
-                               long double vv;
                                if (tdb)
                                        MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL);
 
-                               // We want to store the IEE754 float into ram from a generic
-                               // 32-bit int. First, convert it to double float, then cast
-                               // that to 96-bit, then convert to big endian (if needed)
-                               // and then store it (phew!)
-                               vv = (double)aNexval;
-
-                               //*chptr++ = (char)((*(unsigned long long *)&vv) >> 32) | 0x80 /* assume that the number is normalised */;
-                               D_extend(vv);
+                               PTR p;
+                               p.u64 = &aNexval;
+                               DoubleToExtended(*p.dp, extDbl);
+                               D_extend(extDbl);
                        }
                        else
                        {
-                               long double vvv = 0;
                                AddFixup(FU_FLOATDOUB, sloc, aNexpr);
-
-                               D_extend(vvv);
+                               memset(extDbl, 0, 12);
+                               D_extend(extDbl);
                        }
 
                        break;
@@ -361,7 +352,7 @@ int eaNgen(WORD siz)
                        else
                        {
                                // Arrange for fixup later on
-                               AddFixup(FU_WORD|FU_SEXT, sloc, aNbexpr);
+                               AddFixup(FU_WORD | FU_SEXT, sloc, aNbexpr);
                                D_word(0);
                        }
                }
@@ -384,13 +375,13 @@ int eaNgen(WORD siz)
                        }
                }
                // Deposit od (if not suppressed)
-               if ((aNexten&7)==EXT_IISPRE0 || (aNexten&7)==EXT_IISPREN
-                       || (aNexten&7)==EXT_IISNOIN || (aNexten&7)==EXT_IISPOSN)
+               if ((aNexten & 7) == EXT_IISPRE0 || (aNexten & 7) == EXT_IISPREN
+                       || (aNexten & 7) == EXT_IISNOIN || (aNexten & 7) == EXT_IISPOSN)
                {
                        // Don't deposit anything (suppressed)
                }
-               else if ((aNexten&7)==EXT_IISPREW
-                       || (aNexten&7)==EXT_IISPOSW || (aNexten&7)==EXT_IISNOIW)
+               else if ((aNexten & 7) == EXT_IISPREW
+                       || (aNexten & 7) == EXT_IISPOSW || (aNexten & 7) == EXT_IISNOIW)
                {
                        // Deposit word od
                        if (w)
@@ -407,7 +398,7 @@ int eaNgen(WORD siz)
                        else
                        {
                                // Arrange for fixup later on
-                               AddFixup(FU_WORD|FU_SEXT, sloc, aNexpr);
+                               AddFixup(FU_WORD | FU_SEXT, sloc, aNexpr);
                                D_word(0);
                        }
                }
@@ -425,7 +416,7 @@ int eaNgen(WORD siz)
                        else
                        {
                                // Arrange for fixup later on
-                               AddFixup(FU_LONG|FU_SEXT, sloc, aNexpr);
+                               AddFixup(FU_LONG | FU_SEXT, sloc, aNexpr);
                                D_long(0);
                        }
                }
diff --git a/expr.c b/expr.c
index 5474af8c36fa9cec7fd7506e5d230641d47f1462..b86111bd579769168ecad264fb1d087f57b02ba8 100644 (file)
--- a/expr.c
+++ b/expr.c
@@ -1,4 +1,4 @@
-//
+
 // RMAC - Reboot's Macro Assembler for all Atari computers
 // EXPR.C - Expression Analyzer
 // Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
@@ -237,7 +237,7 @@ int expr2(void)
                break;
        case FCONST:
                ptk.u32 = tok;
-               *evalTokenBuffer.u32++ = CONST;
+               *evalTokenBuffer.u32++ = FCONST;
                *evalTokenBuffer.u64++ = *ptk.u64++;
                tok = ptk.u32;
                break;
@@ -558,28 +558,28 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
                        }
 
                        if (sy->sattr & DEFINED)
-                       {
                                *++sval = sy->svalue;           // Push symbol's value
-                       }
                        else
-                       {
                                *++sval = 0;                            // 0 for undefined symbols
-                       }
 
                        *++sattr = (WORD)(sy->sattr & ~GLOBAL); // Push attribs
                        sym_seg = (WORD)(sy->sattr & TDB);
                        break;
+
                case CONST:
                        *++sval = *tk.u64++;
 //printf("evexpr(): CONST = %lX\n", *sval);
                        *++sattr = ABS | DEFINED;               // Push simple attribs
                        break;
+
                case FCONST:
-//printf("evexpr(): FCONST = %i\n", *tk.u32);
-                       *((double *)sval) = *((double *)tk.u32);
-                       tk.u32 += 2;
+//printf("evexpr(): FCONST = %lf\n", *tk.dp);
+                       // Even though it's a double, we can treat it like a uint64_t since
+                       // we're just moving the bits around.
+                       *++sval = *tk.u64++;
                        *++sattr = ABS | DEFINED | FLOAT; // Push simple attribs
                        break;
+
                case ACONST:
 //printf("evexpr(): ACONST = %i\n", *tk.u32);
                        *++sval = *tk.u32++;                            // Push value
@@ -597,36 +597,26 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
                        //
                        //   [1] + : Error
                        //       - : ABS
+
                case '+':
 //printf("evexpr(): +\n");
                        --sval;                                                 // Pop value
                        --sattr;                                                // Pop attrib
 //printf("--> N+N: %i + %i = ", *sval, sval[1]);
-                       // Extract float attributes from both terms and pack them
-                       // into a single value
-                       attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
-                       attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
+                       // Get FLOAT attribute, if any
+                       attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                       if (attr == (FLOAT | (FLOAT >> 1)))
-                       {
-                               // Float + Float
-                               double * dst = (double *)sval;
-                               double * src = (double *)(sval + 1);
-                               *dst += *src;
-                       }
-                       else if (attr == FLOAT)
+                       // Since adding an int to a fp value promotes it to a fp value, we
+                       // don't care whether it's first or second; we cast to to a double
+                       // regardless.
+                       if (attr == FLOAT)
                        {
-                               // Float + Int
-                               double * dst = (double *)sval;
-                               uint64_t * src = (uint64_t *)(sval + 1);
-                               *dst += *src;
-                       }
-                       else if (attr == FLOAT >> 1)
-                       {
-                               // Int + Float
-                               uint64_t * dst = (uint64_t *)sval;
-                               double * src = (double *)(sval + 1);
-                               *(double *)dst = *src + *dst;
+                               PTR p;
+                               p.u64 = sval;
+                               double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                               p.u64++;
+                               double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+                               *(double *)sval = fpval1 + fpval2;
                        }
                        else
                        {
@@ -635,54 +625,43 @@ int evexpr(TOKEN * _tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym)
 //printf("%i\n", *sval);
 
                        if (!(*sattr & TDB))
-                               *sattr = sattr[1] | attr2;
+                               *sattr = sattr[1] | attr;
                        else if (sattr[1] & TDB)
                                return error(seg_error);
 
                        break;
+
                case '-':
 //printf("evexpr(): -\n");
                        --sval;                                                 // Pop value
                        --sattr;                                                // Pop attrib
 //printf("--> N-N: %i - %i = ", *sval, sval[1]);
-                       // Extract float attributes from both terms and pack them
-                       // into a single value
-                       attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
-                       attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
+                       // Get FLOAT attribute, if any
+                       attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                       if (attr == (FLOAT | (FLOAT >> 1)))
-                       {
-                               // Float - Float
-                               double * dst = (double *)sval;
-                               double * src = (double *)(sval + 1);
-                               *dst -= *src;
-                       }
-                       else if (attr == FLOAT)
-                       {
-                               // Float - Int
-                               double * dst = (double *)sval;
-                               uint64_t * src = (uint64_t *)(sval + 1);
-                               *dst -= *src;
-                       }
-                       else if (attr == FLOAT >> 1)
+                       // Since subtracting an int to a fp value promotes it to a fp
+                       // value, we don't care whether it's first or second; we cast to to
+                       // a double regardless.
+                       if (attr == FLOAT)
                        {
-                               // Int - Float
-                               uint64_t * dst = (uint64_t *)sval;
-                               double * src = (double *)(sval + 1);
-                               *(double *)dst = *dst - *src;
+                               PTR p;
+                               p.u64 = sval;
+                               double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                               p.u64++;
+                               double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+                               *(double *)sval = fpval1 - fpval2;
                        }
                        else
                        {
-                               *sval -= sval[1];                               // Compute value
+                               *sval -= sval[1];
                        }
-
 //printf("%i\n", *sval);
 
+                       *sattr |= attr;                                 // Inherit FLOAT attribute
                        attr = (WORD)(*sattr & TDB);
 #if 0
 printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
 #endif
-                       *sattr |= attr2;                // Inherit FLOAT attribute
                        // If symbol1 is ABS, take attributes from symbol2
                        if (!attr)
                                *sattr = sattr[1];
@@ -691,6 +670,7 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                                *sattr &= ~TDB;
 
                        break;
+
                // Unary operators only work on ABS items
                case UNMINUS:
 //printf("evexpr(): UNMINUS\n");
@@ -699,16 +679,18 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
 
                        if (*sattr & FLOAT)
                        {
-                               double *dst = (double *)sval;
+                               double * dst = (double *)sval;
                                *dst = -*dst;
                                *sattr = ABS | DEFINED | FLOAT; // Expr becomes absolute
                        }
                        else
                        {
-                               *sval = -(int)*sval;
+                               *sval = -(int64_t)*sval;
                                *sattr = ABS | DEFINED;                 // Expr becomes absolute
                        }
+
                        break;
+
                case '!':
 //printf("evexpr(): !\n");
                        if (*sattr & TDB)
@@ -720,6 +702,7 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        *sval = !*sval;
                        *sattr = ABS | DEFINED;                 // Expr becomes absolute
                        break;
+
                case '~':
 //printf("evexpr(): ~\n");
                        if (*sattr & TDB)
@@ -731,6 +714,7 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        *sval = ~*sval;
                        *sattr = ABS | DEFINED;                 // Expr becomes absolute
                        break;
+
                // Comparison operators must have two values that
                // are in the same segment, but that's the only requirement.
                case LE:
@@ -741,38 +725,28 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        if ((*sattr & TDB) != (sattr[1] & TDB))
                                return error(seg_error);
 
-                       // Extract float attributes from both terms and pack them
-                       // into a single value
-                       attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+                       // Get FLOAT attribute, if any
+                       attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                       if (attr == (FLOAT | (FLOAT >> 1)))
+                       // Cast any ints in the comparison to double, if there's at least
+                       // one double in the comparison.
+                       if (attr == FLOAT)
                        {
-                               // Float <= Float
-                               double * dst = (double *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *dst <= *src;
-                       }
-                       else if (attr == FLOAT)
-                       {
-                               // Float <= Int
-                               double * dst = (double *)sval;
-                               uint64_t * src = (uint64_t *)(sval + 1);
-                               *sval = *dst <= *src;
-                       }
-                       else if (attr == FLOAT >> 1)
-                       {
-                               // Int <= Float
-                               uint64_t * dst = (uint64_t *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *dst <= *src;
+                               PTR p;
+                               p.u64 = sval;
+                               double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                               p.u64++;
+                               double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+                               *sval = (fpval1 <= fpval2);
                        }
                        else
                        {
-                               *sval = *sval <= sval[1];
+                               *sval = (*sval <= sval[1]);
                        }
 
                        *sattr = ABS | DEFINED;
                        break;
+
                case GE:
 //printf("evexpr(): GE\n");
                        sattr--;
@@ -781,39 +755,28 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        if ((*sattr & TDB) != (sattr[1] & TDB))
                                return error(seg_error);
 
-                       // Extract float attributes from both terms and pack them
-                       // into a single value
-                       attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+                       // Get FLOAT attribute, if any
+                       attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                       if (attr == (FLOAT | (FLOAT >> 1)))
-                       {
-                               // Float >= Float
-                               double * dst = (double *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *dst >= *src;
-                       }
-                       else if (attr == FLOAT)
-                       {
-                               // Float >= Int
-                               double * dst = (double *)sval;
-                               uint64_t * src = (uint64_t *)(sval + 1);
-                               *sval = *dst >= *src;
-                       }
-                       else if (attr == FLOAT >> 1)
+                       // Cast any ints in the comparison to double, if there's at least
+                       // one double in the comparison.
+                       if (attr == FLOAT)
                        {
-                               // Int >= Float
-                               uint64_t * dst = (uint64_t *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *dst >= *src;
+                               PTR p;
+                               p.u64 = sval;
+                               double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                               p.u64++;
+                               double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+                               *sval = (fpval1 >= fpval2);
                        }
-                       else if (attr == 0)
+                       else
                        {
-                               *sval = *sval >= sval[1];
+                               *sval = (*sval >= sval[1]);
                        }
-                       else
-                               *sattr = ABS | DEFINED;
 
+                       *sattr = ABS | DEFINED;
                        break;
+
                case '>':
 //printf("evexpr(): >\n");
                        sattr--;
@@ -822,39 +785,28 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        if ((*sattr & TDB) != (sattr[1] & TDB))
                                return error(seg_error);
 
-                       // Extract float attributes from both terms and pack them
-                       // into a single value
-                       attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+                       // Get FLOAT attribute, if any
+                       attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                       if (attr == (FLOAT | (FLOAT >> 1)))
+                       // Cast any ints in the comparison to double, if there's at least
+                       // one double in the comparison.
+                       if (attr == FLOAT)
                        {
-                               // Float > Float
-                               double * dst = (double *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *dst > *src;
-                       }
-                       else if (attr == FLOAT)
-                       {
-                               // Float > Int
-                               double * dst = (double *)sval;
-                               uint64_t * src = (uint64_t *)(sval + 1);
-                               *sval = *dst > *src;
-                       }
-                       else if (attr == FLOAT >> 1)
-                       {
-                               // Int > Float
-                               uint64_t * dst = (uint64_t *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *dst > *src;
+                               PTR p;
+                               p.u64 = sval;
+                               double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                               p.u64++;
+                               double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+                               *sval = (fpval1 > fpval2);
                        }
                        else
                        {
-                               *sval = *sval > sval[1];
+                               *sval = (*sval > sval[1]);
                        }
 
                        *sattr = ABS | DEFINED;
-
                        break;
+
                case '<':
 //printf("evexpr(): <\n");
                        sattr--;
@@ -863,39 +815,28 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        if ((*sattr & TDB) != (sattr[1] & TDB))
                                return error(seg_error);
 
-                       // Extract float attributes from both terms and pack them
-                       // into a single value
-                       attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+                       // Get FLOAT attribute, if any
+                       attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                       if (attr == (FLOAT | (FLOAT >> 1)))
+                       // Cast any ints in the comparison to double, if there's at least
+                       // one double in the comparison.
+                       if (attr == FLOAT)
                        {
-                               // Float < Float
-                               double * dst = (double *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *dst < *src;
-                       }
-                       else if (attr == FLOAT)
-                       {
-                               // Float < Int
-                               double * dst = (double *)sval;
-                               uint64_t * src = (uint64_t *)(sval + 1);
-                               *sval = *dst < *src;
-                       }
-                       else if (attr == FLOAT >> 1)
-                       {
-                               // Int < Float
-                               uint64_t * dst = (uint64_t *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *dst < *src;
+                               PTR p;
+                               p.u64 = sval;
+                               double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                               p.u64++;
+                               double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+                               *sval = (fpval1 < fpval2);
                        }
                        else
                        {
-                               *sval = *sval < sval[1];
+                               *sval = (*sval < sval[1]);
                        }
 
-                       *sattr = ABS | DEFINED;
-
+                       *sattr = ABS | DEFINED;         // Expr forced to ABS
                        break;
+
                case NE:
 //printf("evexpr(): NE\n");
                        sattr--;
@@ -904,33 +845,28 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        if ((*sattr & TDB) != (sattr[1] & TDB))
                                return error(seg_error);
 
-                       // Extract float attributes from both terms and pack them
-                       // into a single value
-                       attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+                       // Get FLOAT attribute, if any
+                       attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                       if (attr == (FLOAT | (FLOAT >> 1)))
-                       {
-                               // Float <> Float
-                               return error("comparison for equality with float types not allowed.");
-                       }
-                       else if (attr == FLOAT)
-                       {
-                               // Float <> Int
-                               return error("comparison for equality with float types not allowed.");
-                       }
-                       else if (attr == FLOAT >> 1)
+                       // Cast any ints in the comparison to double, if there's at least
+                       // one double in the comparison.
+                       if (attr == FLOAT)
                        {
-                               // Int != Float
-                               return error("comparison for equality with float types not allowed.");
+                               PTR p;
+                               p.u64 = sval;
+                               double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                               p.u64++;
+                               double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+                               *sval = (fpval1 != fpval2);
                        }
                        else
                        {
-                               *sval = *sval != sval[1];
+                               *sval = (*sval != sval[1]);
                        }
 
-                       *sattr = ABS | DEFINED;
-
+                       *sattr = ABS | DEFINED;         // Expr forced to ABS
                        break;
+
                case '=':
 //printf("evexpr(): =\n");
                        sattr--;
@@ -939,37 +875,29 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        if ((*sattr & TDB) != (sattr[1] & TDB))
                                return error(seg_error);
 
-                       // Extract float attributes from both terms and pack them
-                       // into a single value
-                       attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
+                       // Get FLOAT attribute, if any
+                       attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                       if (attr == (FLOAT | (FLOAT >> 1)))
+                       // Cast any ints in the comparison to double, if there's at least
+                       // one double in the comparison.
+                       if (attr == FLOAT)
                        {
-                               // Float = Float
-                               double * dst = (double *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *src == *dst;
-                       }
-                       else if (attr == FLOAT)
-                       {
-                               // Float = Int
-                               return error("equality with float ");
-                       }
-                       else if (attr == FLOAT >> 1)
-                       {
-                               // Int == Float
-                               uint64_t * dst = (uint64_t *)sval;
-                               double * src = (double *)(sval + 1);
-                               *sval = *src == *dst;
+                               PTR p;
+                               p.u64 = sval;
+                               double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                               p.u64++;
+                               double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+                               *sval = (fpval1 == fpval2);
                        }
                        else
                        {
-                               *sval = *sval == sval[1];
+                               *sval = (*sval == sval[1]);
                        }
 
-                       *sattr = ABS | DEFINED;
+                       *sattr = ABS | DEFINED;         // Expr forced to ABS
 
                        break;
+
                // All other binary operators must have two ABS items to work with.
                // They all produce an ABS value.
                default:
@@ -982,33 +910,25 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                        {
                        case '*':
                                sval--;
-                               sattr--;                                        // Pop attrib
+                               sattr--;
 //printf("--> NxN: %i x %i = ", *sval, sval[1]);
-                               // Extract float attributes from both terms and pack them
-                               // into a single value
-                               attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
-                               attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
+                               // Get FLOAT attribute, if any
+                               attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                               if (attr == (FLOAT | (FLOAT >> 1)))
-                               {
-                                       // Float * Float
-                                       double * dst = (double *)sval;
-                                       double * src = (double *)(sval + 1);
-                                       *dst *= *src;
-                               }
-                               else if (attr == FLOAT)
-                               {
-                                       // Float * Int
-                                       double * dst = (double *)sval;
-                                       uint64_t * src = (uint64_t *)(sval + 1);
-                                       *dst *= *src;
-                               }
-                               else if (attr == FLOAT >> 1)
+                               // Since multiplying an int to a fp value promotes it to a fp
+                               // value, we don't care whether it's first or second; it will
+                               // be cast to a double regardless.
+/*
+An open question here is do we promote ints to floats as signed or unsigned? It makes a difference if, say, the int is put in as -1 but is promoted to a double as $FFFFFFFFFFFFFFFF--you get very different results that way! For now, we promote as signed until proven detrimental otherwise.
+*/
+                               if (attr == FLOAT)
                                {
-                                       // Int * Float
-                                       uint64_t * dst = (uint64_t *)sval;
-                                       double * src = (double *)(sval + 1);
-                                       *(double *)dst = *src * *dst;
+                                       PTR p;
+                                       p.u64 = sval;
+                                       double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                                       p.u64++;
+                                       double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
+                                       *(double *)sval = fpval1 * fpval2;
                                }
                                else
                                {
@@ -1016,53 +936,28 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                                }
 //printf("%i\n", *sval);
 
-                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
-                               *sattr |= attr2;
-
+                               *sattr = ABS | DEFINED | attr;          // Expr becomes absolute
                                break;
+
                        case '/':
                                sval--;
-                               sattr--;                                        // Pop attrib
-
-
+                               sattr--;
 //printf("--> N/N: %i / %i = ", sval[0], sval[1]);
-                               // Extract float attributes from both terms and pack them
-                               // into a single value
-                               attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1);
-                               attr2 = sattr[0] | sattr[1] & FLOAT; // Returns FLOAT if either of the two numbers are FLOAT
-
-                               if (attr == (FLOAT | (FLOAT >> 1)))
-                               {
-                                       // Float / Float
-                                       double * dst = (double *)sval;
-                                       double * src = (double *)(sval + 1);
-
-                                       if (*src == 0)
-                                               return error("divide by zero");
+                               // Get FLOAT attribute, if any
+                               attr = (sattr[0] | sattr[1]) & FLOAT;
 
-                                       *dst = *dst / *src;
-                               }
-                               else if (attr == FLOAT)
-                               {
-                                       // Float / Int
-                                       double * dst = (double *)sval;
-                                       uint64_t * src = (uint64_t *)(sval + 1);
-
-                                       if (*src == 0)
-                                               return error("divide by zero");
-
-                                       *dst = *dst / *src;
-                               }
-                               else if (attr == FLOAT >> 1)
+                               if (attr == FLOAT)
                                {
-                                       // Int / Float
-                                       uint64_t * dst=(uint64_t *)sval;
-                                       double * src=(double *)(sval + 1);
+                                       PTR p;
+                                       p.u64 = sval;
+                                       double fpval1 = (sattr[0] & FLOAT ? *p.dp : (double)*p.i64);
+                                       p.u64++;
+                                       double fpval2 = (sattr[1] & FLOAT ? *p.dp : (double)*p.i64);
 
-                                       if (*src == 0)
+                                       if (fpval2 == 0)
                                                return error("divide by zero");
 
-                                       *(double *)dst = *dst / *src;
+                                       *(double *)sval = fpval1 / fpval2;
                                }
                                else
                                {
@@ -1077,15 +972,14 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                                        // ints.
                                        *sval = (int32_t)sval[0] / (int32_t)sval[1];
                                }
-
-                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
-                               *sattr |= attr2;
-
 //printf("%i\n", *sval);
+
+                               *sattr = ABS | DEFINED | attr;          // Expr becomes absolute
                                break;
+
                        case '%':
                                sval--;
-                               sattr--;                                        // Pop attrib
+                               sattr--;
 
                                if ((*sattr | sattr[1]) & FLOAT)
                                        return error("floating point numbers not allowed with operator '%'.");
@@ -1093,9 +987,10 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                                if (sval[1] == 0)
                                        return error("mod (%) by zero");
 
-                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                *sval %= sval[1];
+                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                break;
+
                        case SHL:
                                sval--;
                                sattr--;                                        // Pop attrib
@@ -1103,9 +998,10 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                                if ((*sattr | sattr[1]) & FLOAT)
                                        return error("floating point numbers not allowed with operator '<<'.");
 
-                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                *sval <<= sval[1];
+                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                break;
+
                        case SHR:
                                sval--;
                                sattr--;                                        // Pop attrib
@@ -1113,9 +1009,10 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                                if ((*sattr | sattr[1]) & FLOAT)
                                        return error("floating point numbers not allowed with operator '>>'.");
 
-                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                *sval >>= sval[1];
+                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                break;
+
                        case '&':
                                sval--;
                                sattr--;                                        // Pop attrib
@@ -1123,9 +1020,10 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                                if ((*sattr | sattr[1]) & FLOAT)
                                        return error("floating point numbers not allowed with operator '&'.");
 
-                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                *sval &= sval[1];
+                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                break;
+
                        case '^':
                                sval--;
                                sattr--;                                        // Pop attrib
@@ -1133,21 +1031,24 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
                                if ((*sattr | sattr[1]) & FLOAT)
                                        return error("floating point numbers not allowed with operator '^'.");
 
-                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                *sval ^= sval[1];
+                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                break;
+
                        case '|':
                                sval--;
-                               sattr--;                                        // Pop attrib
+                               sattr--;
 
                                if ((*sattr | sattr[1]) & FLOAT)
                                        return error("floating point numbers not allowed with operator '|'.");
 
-                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                *sval |= sval[1];
+                               *sattr = ABS | DEFINED;                 // Expr becomes absolute
                                break;
+
                        default:
-                               interror(5);                            // Bad operator in expression stream
+                               // Bad operator in expression stream (this should never happen!)
+                               interror(5);
                        }
                }
        }
@@ -1158,13 +1059,9 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]);
        if (a_esym != NULL)
                *a_esym = esym;
 
-       // sym_seg added in 1.0.16 to solve a problem with forward symbols in
-       // expressions where absolute values also existed. The absolutes were
-       // overiding the symbol segments and not being included :(
-       //*a_attr = *sattr | sym_seg;           // Copy value + attrib
-
-       *a_attr = *sattr;                                               // Copy value + attrib
+       // Copy value + attrib into return variables
        *a_value = *sval;
+       *a_attr = *sattr;
 
        return OK;
 }
diff --git a/fltpoint.c b/fltpoint.c
new file mode 100644 (file)
index 0000000..38bd0b5
--- /dev/null
@@ -0,0 +1,170 @@
+//
+// Floating point to IEEE-754 conversion routines
+//
+// by James Hammons
+// (C) 2018 Underground Software
+//
+// Since there are no guarantees vis-a-vis floating point numbers in C, we have
+// to utilize routines like the following in order to guarantee that the thing
+// we get out of the C compiler is an honest-to-God IEEE-754 style floating
+// point number (since that's what the Motorola processors that we target
+// expect).
+//
+
+#include "fltpoint.h"
+#include <float.h>
+#include <math.h>
+
+//
+// Check for IEEE-754 conformance (C99 compilers should be OK here)
+//
+// The reason we do this is mainly to ensure consistency across all platforms,
+// even those that still haven't implemented C99 compliance after other
+// compilers have had them for decades. The long and the short of it is, there
+// are no guarantees for floating point implementations across platforms the
+// way there is for ints (in <stdint.h>, for example) and so we have to be
+// careful that bad assumptions vis-a-vis floating point numbers don't creep
+// into the codebase and cause problems similar to the ones we had when adding
+// proper 64-bit support. Hence, the following ugliness...
+//
+// IEEE-745 expects the following for floats and doubles:
+//  float: exponent is 8 bits, mantissa is 24 bits
+// double: exponent is 11 bits, mantissa is 53 bits
+// FLT_RADIX should be 2
+#ifdef FLT_RADIX
+       #if FLT_RADIX != 2
+       #error "FLT_RADIX: Your compiler sucks. Get a real one."
+       #endif
+#endif
+#ifdef FLT_MANT_DIG
+       #if FLT_MANT_DIG != 24
+       #error "FLT_MANT_DIG: Your compiler sucks. Get a real one."
+       #endif
+#endif
+#ifdef DBL_MANT_DIG
+       #if DBL_MANT_DIG != 53
+       #error "DBL_MANT_DIG: Your compiler sucks. Get a real one."
+       #endif
+#endif
+#ifdef FLT_MAX_EXP
+       #if FLT_MAX_EXP != 128
+       #error "FLT_MAX_EXP: Your compiler sucks. Get a real one."
+       #endif
+#endif
+#ifdef DBL_MAX_EXP
+       #if DBL_MAX_EXP != 1024
+       #error "DBL_MAX_EXP: Your compiler sucks. Get a real one."
+       #endif
+#endif
+//
+// So if we get here, we can be pretty sure that a float is 4 bytes and a
+// double is 8. IEEE-754? Maaaaaaaaybe. But we don't have to worry about that
+// so much, as long as the token stream is OK (floats are 4 bytes, doubles are
+// 8).
+//
+
+
+uint32_t FloatToIEEE754(float f)
+{
+       uint32_t sign = (f < 0 ? 0x80000000 : 0);
+
+       // Split the float into normalized mantissa (range: (-1, -0.5], 0,
+       // [+0.5, +1)) and base-2 exponent
+       // d = mantissa * (2 ^ exponent) *exactly* for FLT_RADIX=2
+       // Also, since we want the mantissa to be non-inverted (2's complemented),
+       // we make sure to pass in a positive number (floats/doubles are not 2's
+       // complemented) as we already captured the sign bit above.
+       int32_t exponent;
+       float mantissa = frexpf((f < 0 ? -f : f), &exponent);
+
+       // Set the exponent bias for IEEE-754 floats
+       exponent += 0x7E;
+
+       // Check for zero, set the proper exponent if so (zero exponent means no
+       // implied leading one)
+       if (f == 0)
+               exponent = 0;
+
+       // Extract most significant 24 bits of mantissa
+       mantissa = ldexpf(mantissa, 24);
+
+       // Convert to an unsigned int
+       uint32_t ieeeVal = truncf(mantissa);
+
+       // ieeeVal now has the mantissa in binary format, *including* the leading 1
+       // bit; so we have to strip that bit out, since in IEEE-754, it's implied.
+       ieeeVal &= 0x007FFFFF;
+
+       // Finally, add in the other parts to make a proper IEEE-754 float
+       ieeeVal |= sign | ((exponent & 0xFF) << 23);
+
+       return ieeeVal;
+}
+
+
+uint64_t DoubleToIEEE754(double d)
+{
+       uint64_t sign = (d < 0 ? 0x8000000000000000LL : 0);
+       int32_t exponent;
+
+       // Split double into normalized mantissa (range: (-1, -0.5], 0, [+0.5, +1))
+       // and base-2 exponent
+       // d = mantissa * (2 ^ exponent) *exactly* for FLT_RADIX=2
+       // Also, since we want the mantissa to be non-inverted (2's complemented),
+       // we make sure to pass in a positive number (floats/doubles are not 2's
+       // complemented) as we already captured the sign bit above.
+       double mantissa = frexp((d < 0 ? -d : d), &exponent);
+
+       // Set the exponent bias for IEEE-754 doubles
+       exponent += 0x3FE;
+
+       // Check for zero, set the proper exponent if so
+       if (d == 0)
+               exponent = 0;
+
+       // Extract most significant 53 bits of mantissa
+       mantissa = ldexp(mantissa, 53);
+
+       // Convert to an unsigned int
+       uint64_t ieeeVal = trunc(mantissa);
+
+       // ieeeVal now has the mantissa in binary format, *including* the leading 1
+       // bit; so we have to strip that bit out, since in IEEE-754, it's implied.
+       ieeeVal &= 0x000FFFFFFFFFFFFF;
+
+       // Finally, add in the other parts to make a proper IEEE-754 double
+       ieeeVal |= sign | ((uint64_t)(exponent & 0x7FF) << 52);
+
+       return ieeeVal;
+}
+
+
+void DoubleToExtended(double d, uint8_t out[])
+{
+       int32_t exponent;
+       double mantissa = frexp((d < 0 ? -d : d), &exponent);
+       exponent += 0x3FFF;
+
+       if (d == 0)
+               exponent = 0;
+
+       mantissa = ldexp(mantissa, 64);
+       uint64_t intMant = trunc(mantissa);
+
+       // Motorola extended floating point is 96 bits, so we pack it into the
+       // 12-byte array that's passed in. The format is as follows: 1 bit (sign),
+       // 15 bits (exponent w/$3FFF bias), 16 bits of zero, 64 bits of mantissa.
+       out[0] = (d < 0 ? 0x80 : 0x00) | ((exponent >> 8) & 0x7F);
+       out[1] = exponent & 0xFF;
+       out[2] = 0;
+       out[3] = 0;
+       out[4] = (intMant >> 56) & 0xFF;
+       out[5] = (intMant >> 48) & 0xFF;
+       out[6] = (intMant >> 40) & 0xFF;
+       out[7] = (intMant >> 32) & 0xFF;
+       out[8] = (intMant >> 24) & 0xFF;
+       out[9] = (intMant >> 16) & 0xFF;
+       out[10] = (intMant >> 8) & 0xFF;
+       out[11] = intMant & 0xFF;
+}
+
diff --git a/fltpoint.h b/fltpoint.h
new file mode 100644 (file)
index 0000000..20caa72
--- /dev/null
@@ -0,0 +1,10 @@
+//
+// Cross-platform floating point handling
+//
+
+#include <stdint.h>
+
+uint32_t FloatToIEEE754(float f);
+uint64_t DoubleToIEEE754(double d);
+void DoubleToExtended(double d, uint8_t out[]);
+
diff --git a/mach.c b/mach.c
index 15f818f35365d55d546af0986bf47041dbc3639e..2673aa9f5fb5063a44fb3831bf33cf033e13084d 100644 (file)
--- a/mach.c
+++ b/mach.c
 #include "direct.h"
 #include "eagen.h"
 #include "error.h"
+#include "expr.h"
 #include "procln.h"
 #include "riscasm.h"
 #include "sect.h"
 #include "token.h"
-#include "expr.h"
 
 #define DEF_KW
 #include "kwtab.h"
index c7c4ed5fa98de367891c42b7267593c8d39b8132..997e2bc19d3e5873873ac998394075c8ef215d47 100644 (file)
--- a/makefile
+++ b/makefile
@@ -27,9 +27,9 @@ HOSTCC = gcc
 #CFLAGS = -std=$(STD) -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2 -MMD
 CFLAGS = -std=$(STD) -D_DEFAULT_SOURCE -g -D__GCCUNIX__ -I. -O2
 
-SRCS = 6502.c amode.c debug.c direct.c eagen.c error.c expr.c listing.c mach.c macro.c mark.c object.c procln.c riscasm.c rmac.c sect.c symbol.c token.c
+SRCS = 6502.c amode.c debug.c direct.c eagen.c error.c expr.c fltpoint.c listing.c mach.c macro.c mark.c object.c procln.c riscasm.c rmac.c sect.c symbol.c token.c
 
-OBJS = 6502.o amode.o debug.o direct.o eagen.o error.o expr.o listing.o mach.o macro.o mark.o object.o procln.o riscasm.o rmac.o sect.o symbol.o token.o
+OBJS = 6502.o amode.o debug.o direct.o eagen.o error.o expr.o fltpoint.o listing.o mach.o macro.o mark.o object.o procln.o riscasm.o rmac.o sect.o symbol.o token.o
 
 #
 # Build everything
@@ -102,6 +102,9 @@ error.o : error.c error.h
 expr.o : expr.c expr.h
        $(CC) $(CFLAGS) -c expr.c
 
+fltpoint.o : fltpoint.c fltpoint.h
+       $(CC) $(CFLAGS) -c fltpoint.c
+
 listing.o : listing.c listing.h
        $(CC) $(CFLAGS) -c listing.c
 
@@ -136,7 +139,7 @@ token.o : token.c token.h
        $(CC) $(CFLAGS) -c token.c
 
 rmac : $(OBJS)
-       $(CC) $(CFLAGS) -o rmac $(OBJS)
+       $(CC) $(CFLAGS) -o rmac $(OBJS) -lm
 
 #
 # Clean build environment
@@ -157,9 +160,9 @@ debug.o: debug.c debug.h rmac.h symbol.h amode.h direct.h mark.h sect.h \
  token.h
 direct.o: direct.c direct.h rmac.h symbol.h 6502.h amode.h error.h expr.h \
  listing.h mach.h macro.h mark.h procln.h token.h riscasm.h sect.h \
- kwtab.h
+ kwtab.h fltpoint.h
 eagen.o: eagen.c eagen.h rmac.h symbol.h amode.h sect.h mark.h error.h \
- mach.h riscasm.h eagen0.c
+ mach.h riscasm.h eagen0.c fltpoint.h
 error.o: error.c error.h rmac.h symbol.h token.h listing.h
 expr.o: expr.c expr.h rmac.h symbol.h direct.h error.h listing.h mach.h \
  procln.h token.h riscasm.h sect.h kwtab.h
index 73614f2e9c2e5df211dec678f38a80037fa35c72..086d407eed73f6d436b6a607828db20e687ad9d5 100644 (file)
--- a/object.c
+++ b/object.c
@@ -312,7 +312,7 @@ int WriteObject(int fd)
 
                ssize = sy_assign(NULL, NULL);                          // Assign index numbers to the symbols
                tds = sect[TEXT].sloc + sect[DATA].sloc;        // Get size of TEXT and DATA segment
-               buf = malloc(0x600000);                                         // Allocate 6mb object file image memory
+               buf = malloc(0x800000);                                         // Allocate 8MB object file image memory
 
                if (buf == NULL)
                {
@@ -320,7 +320,7 @@ int WriteObject(int fd)
                        return ERROR;
                }
 
-               memset(buf, 0, 0x600000);               // Clear allocated memory
+               memset(buf, 0, 0x800000);               // Clear allocated memory
                objImage = buf;                                 // Set global object image pointer
                strtable = malloc(0x200000);    // Allocate 2MB string table buffer
 
index 2a8c0fdc093eddbdc6bc359f9855413f9bc573bb..8dd19c6371cb93192cbde7953b91786662e188e9 100644 (file)
--- a/procln.c
+++ b/procln.c
@@ -575,7 +575,7 @@ When checking to see if it's already been equated, issue a warning.
                }
 
                sy->sattr |= eattr | EQUATED;   // Symbol inherits value and attributes
-               sy->svalue = (uint32_t)eval;
+               sy->svalue = eval;
 
                if (list_flag)                                  // Put value in listing
                        listvalue((uint32_t)eval);
diff --git a/rmac.h b/rmac.h
index 61c7618071327a52ad990d483562a23be2fc372f..48317499ddf7114a71efdf67555b736a25b20ac6 100644 (file)
--- a/rmac.h
+++ b/rmac.h
@@ -19,7 +19,7 @@
 //
 // TARGET SPECIFIC BUILD SETTINGS
 //
-#if defined(WIN32) || defined (WIN64)
+#if defined(WIN32) || defined(WIN64)
        #include <io.h>
        #include <fcntl.h>
        // Release platform - windows
@@ -27,6 +27,7 @@
        #define _OPEN_FLAGS     _O_TRUNC|_O_CREAT|_O_BINARY|_O_RDWR
        #define _OPEN_INC       _O_RDONLY|_O_BINARY
        #define _PERM_MODE      _S_IREAD|_S_IWRITE
+
        #ifdef _MSC_VER
                #if _MSC_VER > 1000
                        #pragma warning(disable:4996)
@@ -58,8 +59,8 @@
 
        #include <sys/fcntl.h>
        #include <unistd.h>
-       // Release platform - mac OS-X or Linux
-       #define PLATFORM        "OSX/Linux"
+       // Release platform - Linux or mac OS-X
+       #define PLATFORM        "Linux/OSX"
        #define _OPEN_FLAGS     O_TRUNC|O_CREAT|O_RDWR
        #define _OPEN_INC       O_RDONLY
        #define _PERM_MODE      S_IRUSR|S_IWUSR
@@ -76,7 +77,9 @@
        // WARNING WARNING WARNING
        #define DO_PRAGMA(x) _Pragma (#x)
        #define WARNING(desc) DO_PRAGMA(message (#desc))
-#else
+
+       #else
+
        // Release platform - not specified
        #include <sys/fcntl.h>
        #define PLATFORM        "Unknown"
        #define DO_PRAGMA(x) _Pragma (#x)
        #define WARNING(desc) DO_PRAGMA(message (#desc))
        #endif
+
 #endif
 
+
 //
 // Endian related, for safe handling of endian-sensitive data
 // USAGE: GETBExx() is *always* an rvalue, a = pointer to a uint8_t,
@@ -189,7 +194,8 @@ PTR
        uint32_t   lw;                          // LONG (for some reason)
        SYM **     sy;                          // SYM pointer
        TOKEN *    tk;                          // TOKEN pointer
-       double *   dp;                          // Double pointer (temporary!)
+       double *   dp;                          // Double pointer
+       int64_t *  i64;                         // 64-bit signed int pointer
 };
 
 // Symbol spaces
diff --git a/sect.h b/sect.h
index 073d625d62779f2b6db06e1af063cbdff909026b..bae68ebecaaf1ef4ce986c39bf9282f5a18316a2 100644 (file)
--- a/sect.h
+++ b/sect.h
@@ -3,7 +3,7 @@
 // SECT.H - Code Generation, Fixups and Section Management
 // Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
-// Source utilised with the kind permission of Landon Dyer
+// Source utilized with the kind permission of Landon Dyer
 //
 
 #ifndef __SECT_H__
@@ -11,7 +11,7 @@
 
 #include "rmac.h"
 
-// Macros to deposit code in the current section
+// Macros to deposit code in the current section (in Big Endian)
 // D_rword deposits a "6502" format (low, high) word (01).
 #define D_byte(b)      {*chptr++=(uint8_t)(b); sloc++; ch_size++; \
                                                if(orgactive) orgaddr++;}
                                                sloc += 8; ch_size += 8; if(orgactive) orgaddr += 8;}
 #define D_rword(w)     {*chptr++=(uint8_t)(w); *chptr++=(uint8_t)((w)>>8); \
                                                sloc+=2; ch_size+=2;if(orgactive) orgaddr += 2;}
-#define D_single(w) {chcheck(4);*chptr++ = ((char *)&w)[3]; \
-                                               *chptr++ = ((char *)&w)[2]; \
-                                               *chptr++ = ((char *)&w)[1]; \
-                                               *chptr++=((char *)&w)[0]; \
-                                               sloc+=4; ch_size += 4; if(orgactive) orgaddr += 4;}
-#define D_double(w) {chcheck(8);*chptr++=(char)((*(unsigned long long *)&w)); \
-                                               *chptr++=(char)((*(unsigned long long *)&w)>>8); \
-                                               *chptr++=(char)((*(unsigned long long *)&w)>>16); \
-                                               *chptr++=(char)((*(unsigned long long *)&w)>>24); \
-                                               *chptr++=(char)((*(unsigned long long *)&w)>>32); \
-                                               *chptr++=(char)((*(unsigned long long *)&w)>>40); \
-                                               *chptr++=(char)((*(unsigned long long *)&w)>>48); \
-                                               *chptr++=(char)((*(unsigned long long *)&w)>>56); \
-                                               sloc+=8; ch_size += 8; if(orgactive) orgaddr += 8;}
-#ifdef _MSC_VER
-#define D_extend(w) {chcheck(12); *chptr++ = (char)((*(unsigned long long *)&w) >> 56); \
-*chptr++ = (char)(((*(unsigned long long *)&w) >> (52)) & 0xf); \
-*chptr++ = (char)(0); \
-*chptr++ = (char)(0); \
-*chptr++ = (char)(((*(unsigned long long *)&w) >> (48 - 3))|0x80 /* assume that the number is normalised */); \
-*chptr++ = (char)((*(unsigned long long *)&w) >> (40 - 3)); \
-*chptr++ = (char)((*(unsigned long long *)&w) >> (32 - 3)); \
-*chptr++ = (char)((*(unsigned long long *)&w) >> (24 - 3)); \
-*chptr++ = (char)((*(unsigned long long *)&w) >> (16 - 3)); \
-*chptr++ = (char)((*(unsigned long long *)&w) >> (8 - 3)); \
-*chptr++ = (char)((*(unsigned long long *)&w << 3)); \
-*chptr++=(char)(0); \
-       sloc+=12; ch_size += 12; if(orgactive) orgaddr += 12;}
-#elif defined(LITTLE_ENDIAN)
-#define D_extend(w) {chcheck(12);*chptr++=((char *)&w)[0]; \
-                                               *chptr++=((char *)&w)[1]; \
-                                               *chptr++=((char *)&w)[2]; \
-                                               *chptr++=((char *)&w)[3]; \
-                                               *chptr++=((char *)&w)[4]; \
-                                               *chptr++=((char *)&w)[5]; \
-                                               *chptr++=((char *)&w)[6]; \
-                                               *chptr++=((char *)&w)[7]; \
-                                               *chptr++=((char *)&w)[8]; \
-                                               *chptr++=((char *)&w)[9]; \
-                                               *chptr++=((char *)&w)[10]; \
-                                               *chptr++=((char *)&w)[11]; \
-                                               sloc+=12; ch_size += 12; if(orgactive) orgaddr += 12;}
-
-#else
-
-WARNING(Please implement a non-byte swapped D_extend!)
-//stopgap for now, until this can be implemented proppa-ly :-P
-#define D_extend(w) {chcheck(12); chptr+=12; sloc+=12; ch_size+=12; if(orgactive) orgaddr +=12;}
-
-#endif
+// This macro expects to get an array of uint8_ts with the hi bits in a[0] and
+// the low bits in a[11] (Big Endian).
+#define D_extend(a) {memcpy(chptr, a, 12); chptr+=12; sloc+=12, ch_size+=12;\
+                                       if (orgactive) orgaddr+=12;}
+
 // Fill n bytes with zeroes
 #define D_ZEROFILL(n)  {memset(chptr, 0, n); chptr+=n; sloc+=n; ch_size+=n;\
                                                if (orgactive) orgaddr+=n;}
index 80d2b3b52e13048f91f8c6f28cf579629659d95a..b66216b6d3b9caaec155ba913f9386e713a90330 100644 (file)
--- a/symbol.c
+++ b/symbol.c
@@ -482,7 +482,7 @@ int symtable(void)
                                        strcpy(ln2, "external");
                                else
                                {
-                                       sprintf(ln2, "%08X", q->svalue);
+                                       sprintf(ln2, "%016lX", q->svalue);
                                        ToUppercase(ln2);
                                }
 
index 63eda03352fc5a4b5ea88846aa11f0f8dc7ab06d..dfe6bdc7e6c172bcdffd0cbc6d6b1667a2b50a87 100644 (file)
--- a/symbol.h
+++ b/symbol.h
@@ -31,7 +31,7 @@ SYM
        uint16_t sattr;                 // Attribute bits
        uint32_t sattre;                // Extended attribute bits
        uint16_t senv;                  // Enviroment number
-       uint32_t svalue;                // Symbol value
+       uint64_t svalue;                // Symbol value (now 64-bit)
        uint8_t * sname;                // * -> Symbol's print-name
        LLIST * lineList;               // * -> Macro's linked list of lines
        LLIST * last;                   // * -> end of macro linked list
diff --git a/token.c b/token.c
index 34c4a52ceda455b030d7d9a4023d3c5d0ea15f07..f1f88caec4b81fa921993566eb4a8a3084fa49b7 100644 (file)
--- a/token.c
+++ b/token.c
@@ -1600,19 +1600,8 @@ dostring:
                                else if ((int)chrtab[*(ln + 1)] & DIGIT)
                                {
                                        // Hey, more digits after the dot, so we assume it's a
-                                       // floating point number of some kind
-#if 0
-                                       double fract = 10;
-                                       ln++;
-                                       f = (double)v;
-
-                                       while ((int)chrtab[*ln] & DIGIT)
-                                       {
-                                               f = f + (double)(*ln++ - '0') / fract;
-                                               fract *= 10;
-                                       }
-#else
-                                       // Here we parse the whole floating point number
+                                       // floating point number of some kind... numEnd will point
+                                       // to the first non-float character after it's done
                                        char * numEnd;
                                        errno = 0;
                                        double f = strtod(numStart, &numEnd);
@@ -1620,10 +1609,12 @@ dostring:
 
                                        if (errno != 0)
                                                return error("floating point parse error");
-#endif
 
+                                       // N.B.: We use the C compiler's internal double
+                                       //       representation for all internal float calcs and
+                                       //       are reasonably sure that the size of said double
+                                       //       is 8 bytes long (which we check for in fltpoint.c)
                                        *tk.u32++ = FCONST;
-// Shamus: Well, this is all kinds of icky--not the least of which is that unlike uintNN_t types, we have no guarantees of any kind when it comes to the size of floating point numbers in C (as far as I know of). If there is, we need to use those kinds here, or else figure out at runtime what sizes we're dealing with and act accordingly. To be fair, this is OK as long as the double type is less than 64 bits wide, but again, there's no guarantee that it isn't. :-/
                                        *tk.dp = f;
                                        tk.u64++;
                                        continue;
@@ -1728,6 +1719,8 @@ void DumpToken(TOKEN t)
                printf("[COLON]");
        else if (t == CONST)
                printf("[CONST]");
+       else if (t == FCONST)
+               printf("[FCONST]");
        else if (t == ACONST)
                printf("[ACONST]");
        else if (t == STRING)
@@ -1816,6 +1809,13 @@ void DumpTokenBuffer(void)
                        printf("[CONST: $%lX]", *tp.u64);
                        t += 2;
                }
+               else if (*t == FCONST)
+               {
+                       PTR tp;
+                       tp.u32 = t + 1;
+                       printf("[FCONST: $%lX]", *tp.u64);
+                       t += 2;
+               }
                else if (*t == ACONST)
                {
                        printf("[ACONST: $%X, $%X]", (uint32_t)t[1], (uint32_t)t[2]);
index edc8d0c8b54a69f758c9bb9447b16b8df9cc050b..8cb43f45f2d3a9f970856954b94dfee1f0152852 100644 (file)
--- a/version.h
+++ b/version.h
@@ -14,8 +14,8 @@
 // Release Information
 
 #define MAJOR   1              // Major version number
-#define MINOR   10             // Minor version number
-#define PATCH   2              // Patch release number
+#define MINOR   11             // Minor version number
+#define PATCH   0              // Patch release number
 
 #endif // __VERSION_H__