From: Shamus Hammons Date: Sun, 21 Jan 2018 14:25:06 +0000 (-0600) Subject: Lots of fixes for floating point handling; version now at 1.11.0. X-Git-Tag: v2.1.0~95 X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=commitdiff_plain;h=29b32d134bc12831a8ddd098bf9aeeda26dcfe7c Lots of fixes for floating point handling; version now at 1.11.0. 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) --- diff --git a/direct.c b/direct.c index 155fa3f..7447553 100644 --- 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 1f18b85..ae349b8 100644 --- 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" diff --git a/eagen0.c b/eagen0.c index 62e686c..b4b5886 100644 --- 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 5474af8..b86111b 100644 --- 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 index 0000000..38bd0b5 --- /dev/null +++ b/fltpoint.c @@ -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 +#include + +// +// 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 , 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 index 0000000..20caa72 --- /dev/null +++ b/fltpoint.h @@ -0,0 +1,10 @@ +// +// Cross-platform floating point handling +// + +#include + +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 15f818f..2673aa9 100644 --- a/mach.c +++ b/mach.c @@ -11,11 +11,11 @@ #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" diff --git a/makefile b/makefile index c7c4ed5..997e2bc 100644 --- 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 diff --git a/object.c b/object.c index 73614f2..086d407 100644 --- 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 diff --git a/procln.c b/procln.c index 2a8c0fd..8dd19c6 100644 --- 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 61c7618..4831749 100644 --- 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 #include // 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 #include - // 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 #define PLATFORM "Unknown" @@ -87,8 +90,10 @@ #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 073d625..bae68eb 100644 --- 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++;} @@ -34,56 +34,11 @@ 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;} diff --git a/symbol.c b/symbol.c index 80d2b3b..b66216b 100644 --- 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); } diff --git a/symbol.h b/symbol.h index 63eda03..dfe6bdc 100644 --- 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 34c4a52..f1f88ca 100644 --- 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]); diff --git a/version.h b/version.h index edc8d0c..8cb43f4 100644 --- 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__