diff options
| -rw-r--r-- | libacc/acc.cpp | 138 | ||||
| -rw-r--r-- | libacc/tests/data/float.c | 24 |
2 files changed, 135 insertions, 27 deletions
diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 38c23d0..e4e5baa 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -360,7 +360,7 @@ class Compiler : public ErrorSink { * argument, addressed relative to FP. * else it is an absolute global address. */ - virtual void storeR0(int ea) = 0; + virtual void storeR0(int ea, Type* pType) = 0; /* load R0 from a variable. * If ea <= LOCAL, then this is a local variable, or an @@ -449,15 +449,20 @@ class Compiler : public ErrorSink { virtual int jumpOffset() = 0; /** - * Stack alignment (in bytes) for this type of data + * Memory alignment (in bytes) for this type of data */ - virtual size_t stackAlignment(Type* type) = 0; + virtual size_t alignment(Type* type) = 0; /** * Array element alignment (in bytes) for this type of data. */ virtual size_t sizeOf(Type* type) = 0; + /** + * Stack argument size of this data type. + */ + virtual size_t stackSizeOf(Type* pType) = 0; + virtual Type* getR0Type() { return mExpressionStack.back(); } @@ -823,7 +828,7 @@ class Compiler : public ErrorSink { setR0Type(pPointerType); } - virtual void storeR0(int ea) { + virtual void storeR0(int ea, Type* pType) { LOG_API("storeR0(%d);\n", ea); if (ea < LOCAL) { // Local, fp relative @@ -1056,9 +1061,9 @@ class Compiler : public ErrorSink { } /** - * Stack alignment (in bytes) for this type of data + * alignment (in bytes) for this type of data */ - virtual size_t stackAlignment(Type* pType){ + virtual size_t alignment(Type* pType){ switch(pType->tag) { case TY_DOUBLE: return 8; @@ -1086,6 +1091,16 @@ class Compiler : public ErrorSink { return 4; } } + + virtual size_t stackSizeOf(Type* pType) { + switch(pType->tag) { + case TY_DOUBLE: + return 8; + default: + return 4; + } + } + private: static FILE* disasmOut; @@ -1238,7 +1253,25 @@ class Compiler : public ErrorSink { } virtual void pushR0() { - o(0x50); /* push %eax */ + Type* pR0Type = getR0Type(); + TypeTag r0ct = collapseType(pR0Type->tag); + switch(r0ct) { + case TY_INT: + o(0x50); /* push %eax */ + break; + case TY_FLOAT: + o(0x50); /* push %eax */ + o(0x241cd9); // fstps 0(%esp) + break; + case TY_DOUBLE: + o(0x50); /* push %eax */ + o(0x50); /* push %eax */ + o(0x241cdd); // fstpl 0(%esp) + break; + default: + error("pushR0 %d", r0ct); + break; + } pushType(); } @@ -1253,6 +1286,12 @@ class Compiler : public ErrorSink { case TY_CHAR: o(0x0188); /* movl %eax/%al, (%ecx) */ break; + case TY_FLOAT: + o(0x19d9); /* fstps (%ecx) */ + break; + case TY_DOUBLE: + o(0x19dd); /* fstpl (%ecx) */ + break; default: error("storeR0ToTOS: unsupported type"); break; @@ -1281,8 +1320,30 @@ class Compiler : public ErrorSink { setR0Type(pPointerType); } - virtual void storeR0(int ea) { - gmov(6, ea); /* mov %eax, EA */ + virtual void storeR0(int ea, Type* pType) { + TypeTag tag = pType->tag; + switch (tag) { + case TY_INT: + gmov(6, ea); /* mov %eax, EA */ + break; + case TY_FLOAT: + if (ea < -LOCAL || ea > LOCAL) { + oad(0x1dd9, ea); // fstps ea + } else { + oad(0x9dd9, ea); // fstps ea(%ebp) + } + break; + case TY_DOUBLE: + if (ea < -LOCAL || ea > LOCAL) { + oad(0x1ddd, ea); // fstpl ea + } else { + oad(0x9ddd, ea); // fstpl ea(%ebp) + } + break; + default: + error("Unable to store to type %d", tag); + break; + } } virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) { @@ -1448,9 +1509,9 @@ class Compiler : public ErrorSink { } /** - * Stack alignment (in bytes) for this type of data + * Alignment (in bytes) for this type of data */ - virtual size_t stackAlignment(Type* pType){ + virtual size_t alignment(Type* pType){ switch(pType->tag) { case TY_DOUBLE: return 8; @@ -1479,6 +1540,15 @@ class Compiler : public ErrorSink { } } + virtual size_t stackSizeOf(Type* pType) { + switch(pType->tag) { + case TY_DOUBLE: + return 8; + default: + return 4; + } + } + private: /** Output 1 to 4 bytes. @@ -1626,9 +1696,9 @@ class Compiler : public ErrorSink { mpBase->leaR0(ea, pPointerType); } - virtual void storeR0(int ea) { - fprintf(stderr, "storeR0(%d)\n", ea); - mpBase->storeR0(ea); + virtual void storeR0(int ea, Type* pType) { + fprintf(stderr, "storeR0(%d, pType)\n", ea); + mpBase->storeR0(ea, pType); } virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) { @@ -1699,10 +1769,10 @@ class Compiler : public ErrorSink { } /** - * Stack alignment (in bytes) for this type of data + * Alignment (in bytes) for this type of data */ - virtual size_t stackAlignment(Type* pType){ - return mpBase->stackAlignment(pType); + virtual size_t alignment(Type* pType){ + return mpBase->alignment(pType); } /** @@ -1712,6 +1782,12 @@ class Compiler : public ErrorSink { return mpBase->sizeOf(pType); } + + virtual size_t stackSizeOf(Type* pType) { + return mpBase->stackSizeOf(pType); + } + + virtual Type* getR0Type() { return mpBase->getR0Type(); } @@ -2795,7 +2871,7 @@ class Compiler : public ErrorSink { // This while loop merges multiple adjacent string constants. while (tok == '"') { while (ch != '"' && ch != EOF) { - *allocGlobalSpace(1) = getq(); + *allocGlobalSpace(1,1) = getq(); } if (ch != '"') { error("Unterminated string constant."); @@ -2806,7 +2882,7 @@ class Compiler : public ErrorSink { /* Null terminate */ *glo = 0; /* align heap */ - allocGlobalSpace((char*) (((intptr_t) glo + 4) & -4) - glo); + allocGlobalSpace(1,(char*) (((intptr_t) glo + 4) & -4) - glo); return true; } @@ -2864,6 +2940,10 @@ class Compiler : public ErrorSink { t = TOK_INT; } else if (typeEqual(pCast, mkpCharPtr)) { t = TOK_CHAR; + } else if (typeEqual(pCast, mkpFloatPtr)) { + t = TOK_FLOAT; + } else if (typeEqual(pCast, mkpDoublePtr)) { + t = TOK_DOUBLE; } else if (typeEqual(pCast, mkpPtrIntFn)){ t = 0; } else { @@ -2914,7 +2994,7 @@ class Compiler : public ErrorSink { /* assignment */ next(); expr(); - pGen->storeR0(n); + pGen->storeR0(n, pVI->pType); } else if (tok != '(') { /* variable */ if (!n) { @@ -3445,7 +3525,7 @@ class Compiler : public ErrorSink { if (accept('=')) { /* assignment */ expr(); - pGen->storeR0(variableAddress); + pGen->storeR0(variableAddress, pDecl); } if (tok == ',') next(); @@ -3517,7 +3597,9 @@ class Compiler : public ErrorSink { // it's a variable declaration for(;;) { if (name && !name->pAddress) { - name->pAddress = (int*) allocGlobalSpace(4); + name->pAddress = (int*) allocGlobalSpace( + pGen->alignment(name->pType), + pGen->sizeOf(name->pType)); } if (accept('=')) { if (tok == TOK_NUM) { @@ -3563,7 +3645,7 @@ class Compiler : public ErrorSink { addLocalSymbol(pArg); /* read param name and compute offset */ VI(pArg->id)->pAddress = (void*) a; - a = a + 4; + a = a + pGen->stackSizeOf(pArg); argCount++; } rsym = loc = 0; @@ -3578,13 +3660,15 @@ class Compiler : public ErrorSink { } } - char* allocGlobalSpace(int bytes) { - if (glo - pGlobalBase + bytes > ALLOC_SIZE) { + char* allocGlobalSpace(size_t alignment, size_t bytes) { + size_t base = (((size_t) glo) + alignment - 1) & ~(alignment-1); + size_t end = base + bytes; + if ((end - (size_t) pGlobalBase) > ALLOC_SIZE) { error("Global space exhausted"); return NULL; } - char* result = glo; - glo += bytes; + char* result = (char*) base; + glo = (char*) end; return result; } diff --git a/libacc/tests/data/float.c b/libacc/tests/data/float.c index e53fefa..b955238 100644 --- a/libacc/tests/data/float.c +++ b/libacc/tests/data/float.c @@ -14,11 +14,35 @@ double itod(int i) { return i; } +float f0, f1; +double d0, d1; + +void testVars(float arg0, float arg1, double arg2, double arg3) { + float local0, local1; + double local2, local3; + f0 = arg0; + f1 = arg1; + d0 = arg2; + d1 = arg3; + local0 = arg0; + local1 = arg1; + local2 = arg2; + local3 = arg3; + printf("globals: %g %g %g %g\n", f0, f1, d0, d1); + printf("args: %g %g %g %g\n", arg0, arg1, arg2, arg3); + printf("locals: %g %g %g %g\n", local0, local1, local2, local3); + + * (float*) & f0 = 1.1f; + * (double*) & d0 = 3.3; + printf("pointer tests: %g %g %g %g\n", f0, f1, d0, d1); +} + int main() { printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3); printf(" ftoi(1.4f)=%d\n", ftoi(1.4f)); printf(" dtoi(2.4f)=%d\n", dtoi(2.4f)); printf(" itof(3)=%g\n", itof(3)); printf(" itod(4)=%g\n", itod(4)); + testVars(1.0f, 2.0f, 3.0, 4.0); return 0; } |
