From: ggn Date: Thu, 26 Oct 2017 12:24:25 +0000 (+0300) Subject: Added floating point support to expression evaluator, introduced FLOAT token, fixup... X-Git-Tag: v2.1.0~101 X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=commitdiff_plain;h=582df8950c285e1746d0c4a9e3ead6545c962dc8;ds=inline Added floating point support to expression evaluator, introduced FLOAT token, fixup FU_ equates, fixed a load of casting warnings that (some) led to codegen bugs. --- diff --git a/amode.c b/amode.c index 70b30e1..73f2bda 100644 --- a/amode.c +++ b/amode.c @@ -32,7 +32,7 @@ WORD a0exattr; // Expression's attribute int a0ixreg; // Index register int a0ixsiz; // Index register size (and scale) TOKEN a0oexpr[EXPRSIZE]; // Outer displacement expression -uint32_t a0oexval; // Outer displacement value +uint64_t a0oexval; // Outer displacement value WORD a0oexattr; // Outer displacement attribute SYM * a0esym; // External symbol involved in expr TOKEN a0bexpr[EXPRSIZE]; // Base displacement expression @@ -50,7 +50,7 @@ WORD a1exattr; // Expression's attribute int a1ixreg; // Index register int a1ixsiz; // Index register size (and scale) TOKEN a1oexpr[EXPRSIZE]; // Outer displacement expression -uint32_t a1oexval; // Outer displacement value +uint64_t a1oexval; // Outer displacement value WORD a1oexattr; // Outer displacement attribute SYM * a1esym; // External symbol involved in expr TOKEN a1bexpr[EXPRSIZE]; // Base displacement expression @@ -88,7 +88,8 @@ int amode(int acount) a0exattr = a0oexattr = a1exattr = a1oexattr = 0; a0esym = a1esym = NULL; a0bexpr[0] = a1bexpr[0] = ENDEXPR; - a0bexval = a0bsize = a0extension = a1bexval = a1bsize = a1extension = 0; + a0bexval = a1bexval = 0; + a0bsize = a0extension = a1bsize = a1extension = 0; am0_030 = am1_030 = 0; bfparam1 = bfparam2 = 0; bf0expr[0] = ENDEXPR; @@ -388,13 +389,13 @@ int check030bf(void) if (*tok == CONST) { - tok++; // Skip the HI LONG tok++; - bfval1 = *(int *)tok; + bfval1 = (int)*(uint64_t *)tok; // Do=0, offset=immediate - shift it to place bfparam1 = (0 << 11); tok++; + tok++; } else if (*tok == SYMBOL) { @@ -404,7 +405,7 @@ int check030bf(void) if (!(bf0exattr & DEFINED)) return error("bfxxx offset: immediate value must evaluate"); - bfval1 = bf0exval; + bfval1 = (int)bf0exval; // Do=0, offset=immediate - shift it to place bfparam1 = (0 << 11); @@ -431,20 +432,20 @@ int check030bf(void) if (*tok == CONST) { - tok++; // Skip the HI LONG tok++; - bfval2 = *(int *)tok; + bfval2 = (int)*(uint64_t *)tok; // Do=0, offset=immediate - shift it to place bfparam2 = (0 << 5); tok++; + tok++; } else if (*tok == SYMBOL) { if (expr(bf0expr, &bf0exval, &bf0exattr, &bf0esym) != OK) return ERROR; - bfval2 = bf0exval; + bfval2 = (int)bf0exval; if (!(bf0exattr & DEFINED)) return error("bfxxx width: immediate value must evaluate"); diff --git a/amode.h b/amode.h index 76501f7..3da2321 100644 --- a/amode.h +++ b/amode.h @@ -142,7 +142,7 @@ extern WORD a0exattr, a1exattr; extern int a0ixreg, a1ixreg; extern int a0ixsiz, a1ixsiz; extern TOKEN a0oexpr[], a1oexpr[]; -extern uint32_t a0oexval, a1oexval; +extern uint64_t a0oexval, a1oexval; extern WORD a0oexattr, a1oexattr; extern SYM * a0esym, * a1esym; extern uint64_t a0bexval, a1bexval; diff --git a/direct.c b/direct.c index 770fcf9..7c48035 100644 --- a/direct.c +++ b/direct.c @@ -20,6 +20,8 @@ #include "sect.h" #include "symbol.h" #include "token.h" +#include "math.h" +#include "sect.h" #define DEF_KW #include "kwtab.h" @@ -859,7 +861,7 @@ int d_prgflags(void) return error("PRGFLAGS requires value"); else if (abs_expr(&eval) == OK) { - PRGFLAGS=eval; + PRGFLAGS = (uint32_t)eval; return 0; } else @@ -887,7 +889,7 @@ int d_abs(void) return 0; SwitchSection(ABS); - sloc = eval; + sloc = (uint32_t)eval; return 0; } @@ -976,9 +978,9 @@ int d_ds(WORD siz) // of zeroed memory.... if ((scattr & SBSS) || cursect == M6502) { - listvalue(eval); + listvalue((uint32_t)eval); eval *= siz; - sloc += eval; + sloc += (uint32_t)eval; if (cursect == M6502) chptr += eval; @@ -1002,6 +1004,9 @@ int d_dc(WORD siz) { WORD eattr; uint64_t eval; + WORD tdb; + WORD defined; + uint64_t val64; uint8_t * p; if ((scattr & SBSS) != 0) @@ -1056,14 +1061,26 @@ int d_dc(WORD siz) siz = SIZL; } + if (siz != SIZQ) + { // dc.x SYM * esym = 0; if (expr(exprbuf, &eval, &eattr, &esym) != OK) return 0; + } + else + { + val64 = *(uint64_t *)(tok); + tok = tok + 2; + D_long((uint32_t)(val64 >> 32)); + D_long((uint32_t)val64); + + goto comma; + } - uint16_t tdb = eattr & TDB; - uint16_t defined = eattr & DEFINED; + tdb = (WORD)(eattr & TDB); + defined = (WORD)(eattr & DEFINED); if ((challoc - ch_size) < 4) chcheck(4); @@ -1136,15 +1153,70 @@ int d_dc(WORD siz) D_long(eval); } break; + case SIZS: + if (m6502) + return error(in_6502mode); + + if (!defined) + { + float vv = 0; + AddFixup(FU_FLOATSING, sloc, exprbuf); + + D_single(vv); + } + else + { + if (tdb) + MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL); + + D_single(eval); + } + break; case SIZD: - // 64-bit size - // N.B.: May have to come up with section/fixup markers for this; - // ATM it's only used in dc.d statements... - D_long(eval >> 32); - D_long(eval & 0xFFFFFFFF); + if (m6502) + return error(in_6502mode); + + if (!defined) + { + double vv = 0; + AddFixup(FU_FLOATDOUB, sloc, exprbuf); + + D_double(vv); + } + else + { + double vv; + if (tdb) + MarkRelocatable(cursect, sloc, tdb, MDOUBLE, NULL); + + vv = *(double *)&eval; + D_double(vv); + } + break; + case SIZX: + if (m6502) + return error(in_6502mode); + + if (!defined) + { + double vv = 0; + AddFixup(FU_FLOATEXT, sloc, exprbuf); + + D_extend(vv); + } + else + { + float vv; + if (tdb) + MarkRelocatable(cursect, sloc, tdb, MEXTEND, NULL); + + vv = *(double *)&eval; + D_extend(vv); + } break; } + comma: if (*tok != ',') break; @@ -1180,7 +1252,7 @@ int d_dcb(WORD siz) if (cursect != M6502 && (siz != SIZB) && (sloc & 1)) auto_even(); - dep_block(evalc, siz, eval, eattr, exprbuf); + dep_block((uint32_t)evalc, siz, (uint32_t)eval, eattr, exprbuf); return 0; } @@ -1239,7 +1311,7 @@ int d_init(WORD def_siz) break; } - dep_block(count, siz, eval, eattr, exprbuf); + dep_block((uint32_t)count, siz, (uint32_t)eval, eattr, exprbuf); switch ((int)*tok) { @@ -1377,7 +1449,7 @@ int d_comm(void) if (abs_expr(&eval) != OK) // Parse size of common region return 0; - sym->svalue = eval; // Install common symbol's size + sym->svalue = (uint32_t)eval; // Install common symbol's size at_eol(); return 0; } @@ -1619,7 +1691,7 @@ int d_cargs(void) AddToSymbolDeclarationList(symbol); symbol->sattr |= (ABS | DEFINED | EQUATED); - symbol->svalue = eval; + symbol->svalue = (uint32_t)eval; tok += 2; // What this does is eat any dot suffixes attached to a symbol. If @@ -1746,7 +1818,7 @@ int d_cstruct(void) } symbol->sattr |= (ABS | DEFINED | EQUATED); - symbol->svalue = eval; + symbol->svalue = (uint32_t)eval; // Check for dot suffixes and adjust space accordingly (longs and // words on an odd boundary get bumped to the next word aligned diff --git a/eagen0.c b/eagen0.c index e7f3885..62e686c 100644 --- a/eagen0.c +++ b/eagen0.c @@ -9,10 +9,10 @@ int eaNgen(WORD siz) { - uint32_t vbd, v = aNexval; + uint32_t vbd, v = (uint32_t)aNexval; WORD wbd, w = (WORD)(aNexattr & DEFINED); WORD tdbbd, tdb = (WORD)(aNexattr & TDB); - vbd = aNbdexval; + vbd = (uint32_t)aNbdexval; wbd = (WORD)(aNbdexattr & DEFINED); tdbbd = (WORD)(aNbdexattr & TDB); @@ -208,6 +208,80 @@ int eaNgen(WORD siz) D_long(0); } + break; + case SIZS: + // 68881/68882/68040 only + if (w) + { + float vv; + if (tdb) + MarkRelocatable(cursect, sloc, tdb, MSINGLE, NULL); + + vv = (float)v; + + D_single(vv); + } + else + { + float vv = 0; + AddFixup(FU_FLOATSING, sloc, aNexpr); + + D_single(vv); + } + + break; + case SIZD: + // 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); + } + else + { + unsigned long long vvv = 0; + AddFixup(FU_FLOATDOUB, sloc, aNexpr); + + D_double(vvv); + } + + break; + case SIZX: + // 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); + } + else + { + long double vvv = 0; + AddFixup(FU_FLOATDOUB, sloc, aNexpr); + + D_extend(vvv); + } + break; default: // IMMED size problem diff --git a/expr.c b/expr.c index dea1de9..a0f6f9f 100644 --- a/expr.c +++ b/expr.c @@ -29,7 +29,7 @@ static WORD evattr[EVSTACKSIZE]; // Evaluator attribute stack // Token-class initialization list char itokcl[] = { 0, // END - CONST, SYMBOL, 0, // ID + CONST, FCONST, SYMBOL, 0, // ID '(', '[', '{', 0, // OPAR ')', ']', '}', 0, // CPAR CR_DEFINED, CR_REFERENCED, // SUNARY (special unary) @@ -133,6 +133,7 @@ int expr1(void) char * p, * p2; WORD w; int j; + uint64_t * evalTokenBuffer64; class = tokenClass[*tok]; @@ -146,6 +147,10 @@ int expr1(void) if (t == '-') t = UNMINUS; + // With leading + we don't have to deposit + // anything to the buffer because there's + // no unary '+' nor we have to do anything about it + if (t != '+') *evalTokenBuffer++ = t; } else if (class == SUNARY) @@ -154,18 +159,21 @@ int expr1(void) { case CR_ABSCOUNT: *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = 0; // Set HI LONG to zero - *evalTokenBuffer++ = (LONG)sect[ABS].sloc; + evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + *evalTokenBuffer64++ = (LONG)sect[ABS].sloc; + evalTokenBuffer = (uint32_t *)evalTokenBuffer64; break; case CR_TIME: *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = 0; // Set HI LONG to zero - *evalTokenBuffer++ = dos_time(); + evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + *evalTokenBuffer64++ = dos_time(); + evalTokenBuffer = (uint32_t *)evalTokenBuffer64; break; case CR_DATE: *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = 0; // Set HI LONG to zero - *evalTokenBuffer++ = dos_date(); + evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + *evalTokenBuffer64++ = dos_date(); + evalTokenBuffer = (uint32_t *)evalTokenBuffer64; break; case CR_MACDEF: // ^^macdef if (*tok++ != SYMBOL) @@ -173,8 +181,9 @@ int expr1(void) p = string[*tok++]; w = (lookup(p, MACRO, 0) == NULL ? 0 : 1); - *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = 0; // Set HI LONG to zero + evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + *evalTokenBuffer64++ = (TOKEN)w; + evalTokenBuffer = (uint32_t *)evalTokenBuffer64; *evalTokenBuffer++ = (TOKEN)w; break; case CR_DEFINED: @@ -190,8 +199,9 @@ getsym: j = (*p == '.' ? curenv : 0); w = ((sy = lookup(p, LABEL, j)) != NULL && (sy->sattr & w) ? 1 : 0); *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = 0; // Set HI LONG to zero - *evalTokenBuffer++ = (TOKEN)w; + uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + *evalTokenBuffer64++ = (TOKEN)w; + evalTokenBuffer = (uint32_t *)evalTokenBuffer64; break; case CR_STREQ: if (*tok != SYMBOL && *tok != STRING) @@ -211,8 +221,9 @@ getsym: w = (WORD)(!strcmp(p, p2)); *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = 0; // Set HI LONG to zero - *evalTokenBuffer++ = (TOKEN)w; + evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + *evalTokenBuffer64++ = (TOKEN)w; + evalTokenBuffer = (uint32_t *)evalTokenBuffer64; break; } } @@ -231,13 +242,26 @@ int expr2(void) char * p; SYM * sy; int j; + uint64_t * evalTokenBuffer64; + uint64_t * tok64; switch ((int)*tok++) { case CONST: *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = *tok++; // HI LONG of constant - *evalTokenBuffer++ = *tok++; // LO LONG of constant + evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + tok64 = (uint64_t *)tok; + *evalTokenBuffer64++ = *tok64++; + tok = (TOKEN *)tok64; + evalTokenBuffer = (TOKEN *)evalTokenBuffer64; + break; + case FCONST: + *evalTokenBuffer++ = FCONST; + evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + tok64 = (uint64_t *)tok; + *evalTokenBuffer64++ = *tok64++; + tok = (TOKEN *)tok64; + evalTokenBuffer = (TOKEN *)evalTokenBuffer64; break; case SYMBOL: p = string[*tok++]; @@ -264,8 +288,9 @@ int expr2(void) break; case STRING: *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = 0; // Set HI LONG to zero - *evalTokenBuffer++ = str_value(string[*tok++]); + uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + *evalTokenBuffer64++ = str_value(string[*tok++]); + evalTokenBuffer = (uint32_t *)evalTokenBuffer64; break; case '(': if (expr0() != OK) @@ -343,19 +368,20 @@ int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) // (assuming tok[1] == EOL is a single token that is) // Seems that even other tokens (SUNARY type) can fuck this up too. // if ((tok[1] == EOL) - if ((tok[1] == EOL && (tok[0] != CONST && tokenClass[tok[0]] != SUNARY)) -// || (((*tok == CONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31)) + if ((tok[1] == EOL && ((tok[0] != CONST || tok[0] != FCONST) && tokenClass[tok[0]] != SUNARY)) +// || (((*tok == CONST || *tok == FCONST || *tok == SYMBOL) || (*tok >= KW_R0 && *tok <= KW_R31)) // && (tokenClass[tok[2]] < UNARY))) || (((tok[0] == SYMBOL) || (tok[0] >= KW_R0 && tok[0] <= KW_R31)) && (tokenClass[tok[2]] < UNARY)) - || ((tok[0] == CONST) && (tokenClass[tok[3]] < UNARY)) + || ((tok[0] == CONST || tok[0] == FCONST) && (tokenClass[tok[3]] < UNARY)) ) { if (*tok >= KW_R0 && *tok <= KW_R31) { *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = 0; // Set HI LONG to zero - *evalTokenBuffer++ = *a_value = (*tok - KW_R0); + uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + *evalTokenBuffer64++ = *a_value = (*tok - KW_R0); + evalTokenBuffer = (uint32_t *)evalTokenBuffer64; *a_attr = ABS | DEFINED; if (a_esym != NULL) @@ -366,9 +392,11 @@ int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) else if (*tok == CONST) { *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = tok[1]; - *evalTokenBuffer++ = tok[2]; - *a_value = (((uint64_t)tok[1]) << 32) | tok[2]; + uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; + uint64_t *tok64 = (uint64_t *)&tok[1]; + *evalTokenBuffer64++ = *tok64++; + evalTokenBuffer = (TOKEN *)evalTokenBuffer64; + *a_value = tok[1]; *a_attr = ABS | DEFINED; if (a_esym != NULL) @@ -376,16 +404,32 @@ int expr(TOKEN * otk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) tok += 3; //printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]); + } + else if (*tok == FCONST) + { + *evalTokenBuffer++ = FCONST; + *((double *)evalTokenBuffer) = *((double *)&tok[1]); + evalTokenBuffer += 2; + //*(double *)evalTokenBuffer++ = tok[2]; + *a_value = *((uint64_t *)&tok[1]); + *a_attr = ABS | DEFINED | FLOAT; + + if (a_esym != NULL) + *a_esym = NULL; + + tok += 3; +//printf("Quick eval in expr(): CONST = %i, tokenClass[tok[2]] = %i\n", *a_value, tokenClass[*tok]); } else if (*tok == '*') { *evalTokenBuffer++ = CONST; - *evalTokenBuffer++ = 0; // Set HI LONG to zero + uint64_t *evalTokenBuffer64 = (uint64_t *)evalTokenBuffer; if (orgactive) - *evalTokenBuffer++ = *a_value = orgaddr; + *evalTokenBuffer64++ = *a_value = orgaddr; else - *evalTokenBuffer++ = *a_value = pcloc; + *evalTokenBuffer64++ = *a_value = pcloc; + evalTokenBuffer = (uint32_t *)evalTokenBuffer64; // '*' takes attributes of current section, not ABS! *a_attr = cursect | DEFINED; @@ -495,12 +539,13 @@ thrown away right here. What the hell is it for? // int evexpr(TOKEN * tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) { - WORD attr; + WORD attr, attr2; SYM * sy; uint64_t * sval = evstk; // (Empty) initial stack WORD * sattr = evattr; SYM * esym = NULL; // No external symbol involved WORD sym_seg = 0; + uint64_t *tk64; while (*tk != ENDEXPR) { @@ -540,11 +585,18 @@ int evexpr(TOKEN * tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) sym_seg = (WORD)(sy->sattr & TDB); break; case CONST: - *++sval = ((uint64_t)*tk++) << 32; // Push value - *sval |= *tk++; // & LO LONG (will this work???--should) + tk64 = (uint64_t *)tk; + *++sval = *tk64++; + tk = (TOKEN *)tk64; //printf("evexpr(): CONST = %lX\n", *sval); *++sattr = ABS | DEFINED; // Push simple attribs break; + case FCONST: +//printf("evexpr(): CONST = %i\n", *tk); + *((double *)sval) = *((double *)tk); + tk += 2; + *++sattr = ABS | DEFINED | FLOAT; // Push simple attribs + break; case ACONST: //printf("evexpr(): ACONST = %i\n", *tk); *++sval = *tk++; // Push value @@ -567,11 +619,40 @@ int evexpr(TOKEN * tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) --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 + + 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) + { + // Int + Float + uint64_t * dst = (uint64_t *)sval; + double * src = (double *)(sval + 1); + *(double *)dst = *src + *dst; + } + else + { *sval += sval[1]; // Compute value + } //printf("%i\n", *sval); if (!(*sattr & TDB)) - *sattr = sattr[1]; + *sattr = sattr[1] | attr2; else if (sattr[1] & TDB) return error(seg_error); @@ -581,13 +662,44 @@ int evexpr(TOKEN * tk, uint64_t * a_value, WORD * a_attr, SYM ** a_esym) --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 + + 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) + { + // Int - Float + uint64_t * dst = (uint64_t *)sval; + double * src = (double *)(sval + 1); + *(double *)dst = *dst - *src; + } + else + { *sval -= sval[1]; // Compute value + } + //printf("%i\n", *sval); 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]; @@ -600,15 +712,27 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); case UNMINUS: //printf("evexpr(): UNMINUS\n"); if (*sattr & TDB) - error(seg_error); + return error(seg_error); + if (*sattr & FLOAT) + { + double *dst = (double *)sval; + *dst = -*dst; + *sattr = ABS | DEFINED | FLOAT; // Expr becomes absolute + } + else + { *sval = -(int)*sval; *sattr = ABS | DEFINED; // Expr becomes absolute + } break; case '!': //printf("evexpr(): !\n"); if (*sattr & TDB) - error(seg_error); + return error(seg_error); + + if (*sattr & FLOAT) + return error("floating point numbers not allowed with operator '!'."); *sval = !*sval; *sattr = ABS | DEFINED; // Expr becomes absolute @@ -616,7 +740,10 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); case '~': //printf("evexpr(): ~\n"); if (*sattr & TDB) - error(seg_error); + return error(seg_error); + + if (*sattr & FLOAT) + return error("floating point numbers not allowed with operator '~'."); *sval = ~*sval; *sattr = ABS | DEFINED; // Expr becomes absolute @@ -629,10 +756,39 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) - error(seg_error); + return error(seg_error); - *sattr = ABS | DEFINED; + // Extract float attributes from both terms and pack them + // into a single value + attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1); + + 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) + { + // Int <= Float + uint64_t * dst = (uint64_t *)sval; + double * src = (double *)(sval + 1); + *sval = *dst <= *src; + } + else + { *sval = *sval <= sval[1]; + } + + *sattr = ABS | DEFINED; break; case GE: //printf("evexpr(): GE\n"); @@ -640,10 +796,41 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) - error(seg_error); + return error(seg_error); - *sattr = ABS | DEFINED; + // Extract float attributes from both terms and pack them + // into a single value + attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1); + + 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) + { + // Int >= Float + uint64_t * dst = (uint64_t *)sval; + double * src = (double *)(sval + 1); + *sval = *dst >= *src; + } + else if (attr == 0) + { *sval = *sval >= sval[1]; + } + else + + *sattr = ABS | DEFINED; + break; case '>': //printf("evexpr(): >\n"); @@ -651,10 +838,40 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) - error(seg_error); + return error(seg_error); - *sattr = ABS | DEFINED; + // Extract float attributes from both terms and pack them + // into a single value + attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1); + + 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) + { + // Int > Float + uint64_t * dst = (uint64_t *)sval; + double * src = (double *)(sval + 1); + *sval = *dst > *src; + } + else += { *sval = *sval > sval[1]; + } + + *sattr = ABS | DEFINED; + break; case '<': //printf("evexpr(): <\n"); @@ -662,10 +879,40 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) - error(seg_error); + return error(seg_error); - *sattr = ABS | DEFINED; + // Extract float attributes from both terms and pack them + // into a single value + attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) > >1); + + 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) + { + // Int < Float + uint64_t * dst = (uint64_t *)sval; + double * src = (double *)(sval + 1); + *sval = *dst < *src; + } + else + { *sval = *sval < sval[1]; + } + + *sattr = ABS | DEFINED; + break; case NE: //printf("evexpr(): NE\n"); @@ -673,10 +920,34 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) - error(seg_error); + return error(seg_error); - *sattr = ABS | DEFINED; + // Extract float attributes from both terms and pack them + // into a single value + attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1); + + 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) + { + // Int != Float + return error("comparison for equality with float types not allowed."); + } + else + { *sval = *sval != sval[1]; + } + + *sattr = ABS | DEFINED; + break; case '=': //printf("evexpr(): =\n"); @@ -684,10 +955,38 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); sval--; if ((*sattr & TDB) != (sattr[1] & TDB)) - error(seg_error); + return error(seg_error); - *sattr = ABS | DEFINED; + // Extract float attributes from both terms and pack them + // into a single value + attr = sattr[0] & FLOAT | ((sattr[1] & FLOAT) >> 1); + + if (attr == (FLOAT | (FLOAT >> 1))) + { + // 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; + } + else + { *sval = *sval == sval[1]; + } + + *sattr = ABS | DEFINED; + break; // All other binary operators must have two ABS items // to work with. They all produce an ABS value. @@ -696,7 +995,6 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); // GH - Removed for v1.0.15 as part of the fix for indexed loads. //if ((*sattr & (TEXT|DATA|BSS)) || (*--sattr & (TEXT|DATA|BSS))) //error(seg_error); - *sattr = ABS | DEFINED; // Expr becomes absolute switch ((int)tk[-1]) { @@ -704,56 +1002,147 @@ printf("EVEXPR (-): sym1 = %X, sym2 = %X\n", attr, sattr[1]); sval--; sattr--; // Pop attrib //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 + + 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) + { + // Int * Float + uint64_t * dst = (uint64_t *)sval; + double * src = (double *)(sval + 1); + *(double *)dst = *src * *dst; + } + else + { *sval *= sval[1]; + } //printf("%i\n", *sval); + + *sattr = ABS | DEFINED; // Expr becomes absolute + *sattr |= attr2; + break; case '/': sval--; sattr--; // Pop attrib - if (sval[1] == 0) - return error("division by zero"); +//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"); + *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) + { + // Int / Float + uint64_t * dst=(uint64_t *)sval; + double * src=(double *)(sval + 1); + if (*src == 0) + return error("divide by zero"); + *(double *)dst = *dst / *src; + } + else + { + if (sval[1] == 0) + return error("divide by zero"); //printf("--> N/N: %i / %i = ", sval[0], sval[1]); // Compiler is picky here: Without casting these, it discards // the sign if dividing a negative # by a positive one, // creating a bad result. :-/ // Definitely a side effect of using uint32_ts intead of ints. *sval = (int32_t)sval[0] / (int32_t)sval[1]; + } + + *sattr = ABS | DEFINED; // Expr becomes absolute + *sattr |= attr2; + //printf("%i\n", *sval); break; case '%': sval--; sattr--; // Pop attrib + if ((*sattr | sattr[1]) & FLOAT) + return error("floating point numbers not allowed with operator '%'."); if (sval[1] == 0) return error("mod (%) by zero"); + *sattr = ABS | DEFINED; // Expr becomes absolute *sval %= sval[1]; break; case SHL: sval--; sattr--; // Pop attrib + if ((*sattr | sattr[1]) & FLOAT) + return error("floating point numbers not allowed with operator '<<'."); + *sattr = ABS | DEFINED; // Expr becomes absolute *sval <<= sval[1]; break; case SHR: sval--; sattr--; // Pop attrib + if ((*sattr | sattr[1]) & FLOAT) + return error("floating point numbers not allowed with operator '>>'."); + *sattr = ABS | DEFINED; // Expr becomes absolute *sval >>= sval[1]; break; case '&': sval--; sattr--; // Pop attrib + if ((*sattr | sattr[1]) & FLOAT) + return error("floating point numbers not allowed with operator '&'."); + *sattr = ABS | DEFINED; // Expr becomes absolute *sval &= sval[1]; break; case '^': sval--; sattr--; // Pop attrib + if ((*sattr | sattr[1]) & FLOAT) + return error("floating point numbers not allowed with operator '^'."); + *sattr = ABS | DEFINED; // Expr becomes absolute *sval ^= sval[1]; break; case '|': sval--; sattr--; // Pop attrib + if ((*sattr | sattr[1]) & FLOAT) + return error("floating point numbers not allowed with operator '|'."); + *sattr = ABS | DEFINED; // Expr becomes absolute *sval |= sval[1]; break; default: diff --git a/mach.c b/mach.c index edb5dea..4e106da 100644 --- a/mach.c +++ b/mach.c @@ -475,7 +475,7 @@ int m_lea(WORD inst, WORD siz) && ((am0 == ADISP) && (a0reg == a1reg) && (a0exattr & DEFINED)) && ((a0exval > 0) && (a0exval <= 8))) { - inst = B16(01010000, 01001000) | ((a0exval & 7) << 9) | (a0reg); + inst = B16(01010000, 01001000) | (((uint16_t)a0exval & 7) << 9) | (a0reg); D_word(inst); warn("lea size(An),An converted to addq #size,An"); return OK; @@ -1227,7 +1227,7 @@ int m_br30(WORD inst, WORD siz) if ((a0exattr & TDB) != cursect) return error(rel_error); - uint32_t v = a0exval - (sloc + 2); + uint32_t v = (uint32_t)a0exval - (sloc + 2); D_word(inst); D_long(v); @@ -1339,7 +1339,7 @@ int m_callm(WORD inst, WORD siz) if (a0exval > 255) return error(range_error); - inst = a0exval; + inst = (uint16_t)a0exval; D_word(inst); } else @@ -1625,7 +1625,7 @@ int m_cpbr(WORD inst, WORD siz) if ((a0exattr & TDB) != cursect) return error(rel_error); - uint32_t v = a0exval - (sloc + 2); + uint32_t v = (uint32_t)a0exval - (sloc + 2); // Optimize branch instr. size if (siz == SIZL) @@ -1695,7 +1695,7 @@ int m_cpdbr(WORD inst, WORD siz) if ((a1exattr & TDB) != cursect) return error(rel_error); - v = a1exval - sloc; + v = (uint32_t)a1exval - sloc; if (v + 0x8000 > 0x10000) return error(range_error); @@ -2092,7 +2092,7 @@ int m_move16b(WORD inst, WORD siz) { //move16 (ax)+,(xxx).L inst |= 0 << 3; - v = a1exval; + v = (int)a1exval; } } else if (am0 == ABSL) @@ -2101,20 +2101,20 @@ int m_move16b(WORD inst, WORD siz) { //move16 (xxx).L,(ax)+ inst |= 1 << 3; - v = a0exval; + v = (int)a0exval; } else //APOSTINC { //move16 (xxx).L,(ax) inst |= 3 << 3; - v = a0exval; + v = (int)a0exval; } } else if (am0 == AIND) { //move16 (ax),(xxx).L inst |= 2 << 3; - v = a1exval; + v = (int)a1exval; } D_word(inst); @@ -2483,7 +2483,7 @@ int m_pflush(WORD inst, WORD siz) return error("function code immediate should be defined"); if (a0exval > 7 && a0exval < 0) return error("function code out of range (0-7)"); - fc = a0exval; + fc = (uint16_t)a0exval; break; case KW_D0: case KW_D1: @@ -2520,7 +2520,7 @@ int m_pflush(WORD inst, WORD siz) return error("mask immediate value should be defined"); if (a0exval > 7 && a0exval < 0) return error("function code out of range (0-7)"); - mask = a0exval << 5; + mask = (uint16_t)a0exval << 5; if (*tok == EOL) { @@ -2673,7 +2673,7 @@ int m_pload(WORD inst, WORD siz, WORD extension) case IMMED: if ((a0exattr & DEFINED) == 0) return error("constant value must be defined"); - inst = (2 << 3) | a0exval; + inst = (2 << 3) | (uint16_t)a0exval; break; } @@ -2802,7 +2802,6 @@ int m_pmovefd(WORD inst, WORD siz) return m_pmove(inst | (1 << 8), siz); } - // // ptrapcc (68851) // @@ -3103,7 +3102,7 @@ int m_fdbcc(WORD inst, WORD siz) if ((a1exattr & TDB) != cursect) return error(rel_error); - uint32_t v = a1exval - sloc; + uint32_t v = (uint32_t)a1exval - sloc; if ((v + 0x8000) > 0x10000) return error(range_error); diff --git a/macro.c b/macro.c index ccc93dc..54d34c4 100644 --- a/macro.c +++ b/macro.c @@ -264,7 +264,7 @@ int HandleRept(void) IREPT * irept = inobj->inobj.irept; irept->ir_firstln = firstrpt; irept->ir_nextln = NULL; - irept->ir_count = eval; + irept->ir_count = (uint32_t)eval; } return 0; @@ -413,8 +413,11 @@ int InvokeMacro(SYM * mac, WORD siz) else if (*tok == CONST) // Constants are 64-bits { *p++ = *tok++; // Token - *p++ = *tok++; // Hi LONG - *p++ = *tok++; // Lo LONG + uint64_t *p64 = (uint64_t *)p; + uint64_t *tok64 = (uint64_t *)tok; + *p64++ = *tok64++; + tok = (TOKEN *)tok64; + p = (uint32_t *)p64; } else if ((*tok == STRING) || (*tok == SYMBOL)) { diff --git a/mark.c b/mark.c index 955fcab..7378c8a 100644 --- a/mark.c +++ b/mark.c @@ -483,6 +483,7 @@ uint32_t CreateELFRelocationRecord(uint8_t * buf, uint8_t * secBuf, uint16_t sec // Setup pointer for D_long/word/byte macros chptr = buf; + ch_size = 0; for(MCHUNK * mch=firstmch; mch!=NULL; mch=mch->mcnext) { diff --git a/mark.h b/mark.h index 895d6b0..3b2aa53 100644 --- a/mark.h +++ b/mark.h @@ -27,6 +27,9 @@ MCHUNK { #define MWORD 0x0000 // Marked word #define MLONG 0x0100 // Marked long #define MMOVEI 0x0200 // Mark RISC MOVEI instruction +#define MDOUBLE 0x0400 // Marked double float +#define MEXTEND 0x0800 // Marked extended float +#define MSINGLE 0x0880 // Marked single float (TODO: merge with MLONG?) #define MGLOBAL 0x0800 // Mark contains global #define MPCREL 0x1000 // Mark is PC-relative #define MCHEND 0x2000 // Indicates end of mark chunk diff --git a/object.c b/object.c index 9294abe..73614f2 100644 --- a/object.c +++ b/object.c @@ -477,7 +477,7 @@ int WriteObject(int fd) if (buf == NULL) { - error("cannot allocate object file memory (in BSD mode)"); + error("cannot allocate object file memory (in ELF mode)"); return ERROR; } @@ -487,7 +487,7 @@ int WriteObject(int fd) if (strtable == NULL) { - error("cannot allocate string table memory (in BSD mode)"); + error("cannot allocate string table memory (in ELF mode)"); return ERROR; } diff --git a/parmode.h b/parmode.h index 4b6c7ea..e5e0b91 100644 --- a/parmode.h +++ b/parmode.h @@ -186,6 +186,7 @@ // It might be (Dn[.wl][*scale],od) // Maybe this is wrong and we have to write some code here // instead of reusing that path... + AnEXTEN |= EXT_BDSIZE0; // Base displacement null - suppressed goto CHECKODn; } else @@ -279,7 +280,11 @@ if (*tok == ',') { + // If we got here we didn't get any [] stuff + // so let's suppress base displacement before + // branching off tok++; + AnEXTEN |= EXT_BDSIZE0; // Base displacement null - suppressed goto CHECKODn; } if (*tok++ != ')') // final ")" @@ -365,6 +370,7 @@ tok++; // Check for size + { // ([bd,An/PC],Xn.W/L...) switch ((int)*tok) { @@ -382,6 +388,7 @@ // .B not allowed here... goto badmode; } + } // Check for scale if (*tok == '*') // ([bd,An/PC],Xn*...) @@ -616,7 +623,9 @@ // Is .W forced here? if (*tok == DOTW) + { tok++; + } } // Check for final closing parenthesis @@ -717,6 +726,7 @@ IS_SUPPRESSEDn: } // Check for size + { // ([bd,An/PC],Xn.W/L...) switch ((int)*tok) { @@ -734,6 +744,7 @@ IS_SUPPRESSEDn: // .B not allowed here... goto badmode; } + } // Check for scale if (*tok == '*') // ([bd,An/PC],Xn*...) diff --git a/procln.c b/procln.c index f5a806b..37066c4 100644 --- a/procln.c +++ b/procln.c @@ -465,12 +465,11 @@ When checking to see if it's already been equated, issue a warning. { // Advance token pointer to the constant tok += 3; - tok++; // Skip the hi LONG, so pointing at lo LONG // Anything other than a 0 or a 1 will result in "No Bank" - if (*tok == 0) + if (*(uint64_t *)tok == 0) registerbank = BANK_0; - else if (*tok == 1) + else if (*(uint64_t *)tok == 1) registerbank = BANK_1; } @@ -577,10 +576,10 @@ When checking to see if it's already been equated, issue a warning. } sy->sattr |= eattr | EQUATED; // Symbol inherits value and attributes - sy->svalue = eval; + sy->svalue = (uint32_t)eval; if (list_flag) // Put value in listing - listvalue(eval); + listvalue((uint32_t)eval); at_eol(); // Must be at EOL now goto loop; diff --git a/riscasm.c b/riscasm.c index 6346671..533eca7 100644 --- a/riscasm.c +++ b/riscasm.c @@ -194,7 +194,7 @@ int GetRegister(WORD rattr) // If we got a register in range (0-31), return it if ((eval >= 0) && (eval <= 31)) - return eval; + return (int)eval; // Otherwise, it's out of range & we flag an error return error(reg_err); @@ -321,11 +321,11 @@ int GenerateRISCCode(int state) return error("constant out of range"); if (parm & SUB32) - reg1 = 32 - eval; + reg1 = 32 - (int)eval; else if (type == RI_NUM_32) - reg1 = (reg1 == 32 ? 0 : eval); + reg1 = (reg1 == 32 ? 0 : (int)eval); else - reg1 = eval; + reg1 = (int)eval; } CHECK_COMMA; @@ -503,7 +503,7 @@ int GenerateRISCCode(int state) if (!(eattr & DEFINED)) return error("constant expected after '+'"); - reg1 = eval; + reg1 = (int)eval; if (reg1 == 0) { @@ -626,7 +626,7 @@ int GenerateRISCCode(int state) } else { - reg2 = eval; + reg2 = (int)eval; if (reg2 == 0) { @@ -722,9 +722,9 @@ int GenerateRISCCode(int state) { // CC using a constant number tok++; - tok++; // Toss hi LONG, as most likely not 64-bit number - val = *tok; // Use lo LONG - tok++; + uint64_t *tok64 = (uint64_t *)tok; + val = (int)*tok64++; + tok = (uint32_t *)tok64; CHECK_COMMA; } else if (*tok == SYMBOL) diff --git a/rmac.h b/rmac.h index d5775cc..0f92d79 100644 --- a/rmac.h +++ b/rmac.h @@ -135,6 +135,7 @@ // Byteswap crap #define BYTESWAP16(x) ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8)) #define BYTESWAP32(x) ((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | (((x) & 0x00FF0000) >> 8) | (((x) & 0xFF000000) >> 24)) +#define BYTESWAP64(x) (BYTESWAP32(x>>32)|BYTESWAP32((x&0xffffffff)<<32)) #define WORDSWAP32(x) ((((x) & 0x0000FFFF) << 16) | (((x) & 0xFFFF0000) >> 16)) // @@ -163,11 +164,16 @@ #define CREATMASK 0 // Object code formats -#define ALCYON 0 // Alcyon/DRI C object format -#define MWC 1 // Mark Williams object format -#define BSD 2 // BSD object format -#define ELF 3 // ELF object format -#define XEX 4 // COM/EXE/XEX/whatever a8 object format +enum +{ +ALCYON, // Alcyon/DRI C object format +MWC, // Mark Williams object format +BSD, // BSD object format +ELF, // ELF object format +LOD, // DSP 56001 object format +P56, // DSP 56001 object format +XEX, // COM/EXE/XEX/whatever a8 object format +}; // Pointer type that can point to (almost) anything #define PTR union _ptr @@ -194,6 +200,7 @@ PTR #define REFERENCED 0x1000 // Symbol has been referenced #define EQUATED 0x0800 // Symbol was equated #define SDECLLIST 0x0400 // Symbol is on 'sdecl'-order list +#define FLOAT 0x0200 // Symbol is a floating point value // Expression spaces, ORed with symbol and expression attributes above #define ABS 0x0000 // In absolute space @@ -212,7 +219,7 @@ PTR #define SIZS 0x0020 // .s (FPU single precision real) #define SIZX 0x0040 // .x (FPU extended precision real) #define SIZP 0x0080 // .p (FPU pakced decimal real) -#define SIZQ SIZD +#define SIZQ 0x0100 // .q // RISC register bank definitions (used in extended symbol attributes also) #define BANK_N 0x0000 // No register bank specified diff --git a/sect.h b/sect.h index 3cfbf6a..f2aee8d 100644 --- a/sect.h +++ b/sect.h @@ -25,6 +25,54 @@ sloc += 4; ch_size += 4; if(orgactive) orgaddr += 4;} #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 + +#error Please implement a non-byte swapped D_extend! + +#endif // Fill n bytes with zeroes #define D_ZEROFILL(n) {memset(chptr, 0, n); chptr+=n; sloc+=n; ch_size+=n;\ if (orgactive) orgaddr+=n;} @@ -86,6 +134,12 @@ #define FU_LBRA 0x4000 // Long branch, for short branch detect #define FU_DONE 0x8000 // Fixup has been done +// FPU fixups +// TODO: these are obviously bogus for now! +#define FU_FLOATSING 0x0D0B // Fixup 32-bit float +#define FU_FLOATDOUB 0x0E0B // Fixup 64-bit float +#define FU_FLOATEXT 0x0F0B // Fixup 96-bit float + // Chunks are used to hold generated code and fixup records #define CHUNK struct _chunk CHUNK { diff --git a/symbol.c b/symbol.c index 6700f14..80d2b3b 100644 --- a/symbol.c +++ b/symbol.c @@ -260,22 +260,6 @@ uint32_t sy_assign(uint8_t * buf, uint8_t *(* construct)()) } } - // For ELF object mode run through all symbols in reference order - // and export all global-referenced labels. Not sure if this is - // required but it's here nonetheless -/* why?? when you have sy_assign_ELF ??? - if (obj_format == ELF) - { - for(sy=sdecl; sy!=NULL; sy=sy->sorder) - { - if ((sy->sattr == (GLOBAL | REFERENCED)) && (buf != NULL)) - { - buf = (*construct)(buf, sy, 0); - scount++; - } - } - }*/ - return scount; } @@ -305,27 +289,12 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)()) // them. We also pick which symbols should be global or not here. for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl) { - // Export or import external references, and export COMMON blocks. - //if ((sy->stype == LABEL) - // && ((sy->sattr & (GLOBAL | DEFINED)) == (GLOBAL | DEFINED) - // || (sy->sattr & (GLOBAL | REFERENCED)) == (GLOBAL | REFERENCED)) - // || (sy->sattr & COMMON)) - //{ - // sy->senv = (WORD)scount++; - // - // if (buf != NULL) - // buf = (*construct)(buf, sy, 1); - //} // Export vanilla labels (but don't make them global). An exception is // made for equates, which are not exported unless they are referenced. if (sy->stype == LABEL && lsym_flag && (sy->sattr & (DEFINED | REFERENCED)) != 0 && (*sy->sname != '.') && (sy->sattr & GLOBAL) == 0) - //if (sy->stype == 0) - // if (lsym_flag) - // if ((sy->sattr & (DEFINED | REFERENCED)) != 0) - // if ((!as68_flag || *sy->sname != 'L')) { sy->senv = scount++; diff --git a/token.c b/token.c index 4ceaa57..f719dc3 100644 --- a/token.c +++ b/token.c @@ -568,8 +568,8 @@ DEBUG { printf("ExM: SYMBOL=\"%s\"", d); } // to choke on legitimate code... Need to investigate this further // before changing anything else here! case CONST: - tk++; // Skip the hi LONG... sprintf(numbuf, "$%lx", (uint64_t)*tk++); + tk++; d = numbuf; break; case DEQUALS: @@ -951,10 +951,13 @@ int TokenizeLine(void) int j = 0; // Var for keyword detector uint8_t c; // Random char uint64_t v; // Random value + uint32_t cursize = 0; // Current line's size (.b, .w, .l, .s, .q, .d) + double f; // Random float uint8_t * nullspot = NULL; // Spot to clobber for SYMBOL termination int stuffnull; // 1:terminate SYMBOL '\0' at *nullspot uint8_t c1; int stringNum = 0; // Pointer to string locations in tokenized line + uint64_t * tk64; retry: @@ -1135,6 +1138,7 @@ DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n"); } return error("[bwsl] must follow '.' in symbol"); v = (uint32_t)dotxtab[*ln++]; + cursize = (uint32_t)v; if (chrtab[*ln] & CTSYM) return error("misuse of '.'; not allowed in symbols"); @@ -1316,6 +1320,19 @@ dostring: case '$': // $, hex constant if (chrtab[*ln] & HDIGIT) { + if (cursize == 'q' || cursize == 'Q') + { + // Parse 64-bit integer + uint64_t v64 = 0; + + while (hextab[*ln] >= 0) + v64 = (v64 << 4) + (int)hextab[*ln++]; + + *(uint64_t *)tk = v64; + tk = tk + 2; + + continue; + } v = 0; // Parse the hex value @@ -1345,8 +1362,9 @@ dostring: } *tk++ = CONST; - *tk++ = v >> 32; // High LONG of 64-bit value - *tk++ = v & 0xFFFFFFFF; // Low LONG of 64-bit value + tk64 = (uint64_t *)tk; + *tk64++ = v; + tk = (TOKEN *)tk64; if (obj_format == ALCYON) { @@ -1457,8 +1475,9 @@ dostring: } *tk++ = CONST; - *tk++ = v >> 32; // High LONG of 64-bit value - *tk++ = v & 0xFFFFFFFF; // Low LONG of 64-bit value + tk64 = (uint64_t *)tk; + *tk64++ = v; + tk = (TOKEN *)tk64; continue; case '@': // @ or octal constant if (*ln < '0' || *ln > '7') @@ -1494,8 +1513,9 @@ dostring: } *tk++ = CONST; - *tk++ = v >> 32; // High LONG of 64-bit value - *tk++ = v & 0xFFFFFFFF; // Low LONG of 64-bit value + tk64 = (uint64_t *)tk; + *tk64++ = v; + tk = (TOKEN *)tk64; continue; case '^': // ^ or ^^ if (*ln != '^') @@ -1570,8 +1590,9 @@ dostring: v &= 0x000000FF; ln += 2; *tk++ = CONST; - *tk++ = 0; // Hi LONG of 64-bits - *tk++ = v; + tk64 = (uint64_t *)tk; + *tk64++ = v; + tk = (uint32_t *)tk64; *tk++ = DOTB; } else if ((*(ln + 1) == 'w') || (*(ln + 1) == 'W')) @@ -1579,8 +1600,10 @@ dostring: v &= 0x0000FFFF; ln += 2; *tk++ = CONST; - *tk++ = 0; // Hi LONG of 64-bits - *tk++ = v; + tk64 = (uint64_t *)tk; + *tk64++ = v; + tk = (uint32_t *)tk64; + *tk++ = DOTW; } else if ((*(ln + 1) == 'l') || (*(ln + 1) == 'L')) @@ -1588,16 +1611,38 @@ dostring: v &= 0xFFFFFFFF; ln += 2; *tk++ = CONST; - *tk++ = 0; // Hi LONG of 64-bits - *tk++ = v; + tk64 = (uint64_t *)tk; + *tk64++ = v; + tk = (uint32_t *)tk64; + *tk++ = DOTL; } + else if ((int)chrtab[*(ln + 1)] & DIGIT) + { + // Hey, more digits after the dot, so assume it's a + // fractional number + double fract = 10; + ln++; + f = (double)v; + + while ((int)chrtab[*ln] & DIGIT) + { + f = f + (double)(*ln++ - '0') / fract; + fract *= 10; + } + + *tk++ = FCONST; + *((double *)tk) = f; + tk += 2; + continue; + } } else { *tk++ = CONST; - *tk++ = v >> 32; // High LONG of 64-bit value - *tk++ = v & 0xFFFFFFFF; // Low LONG of 64-bit value + tk64 = (uint64_t *)tk; + *tk64++ = v; + tk = (TOKEN *)tk64; } //printf("CONST: %i\n", v); diff --git a/token.h b/token.h index cbacccf..cedaa03 100644 --- a/token.h +++ b/token.h @@ -34,6 +34,7 @@ // (Normally) non-printable tokens #define COLON ':' // : (grumble: GNUmacs hates ':') #define CONST 'a' // CONST +#define FCONST 'r' // Floating CONST #define ACONST 'A' // ACONST #define STRING 'b' // STRING
#define STRINGA8 'S' // Atari 800 internal STRING