Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 128ad2d2 authored by Jack Palevich's avatar Jack Palevich
Browse files

Implement x86 int <--> float.

parent 1a539db2
Loading
Loading
Loading
Loading
+65 −10
Original line number Diff line number Diff line
@@ -532,7 +532,10 @@ class Compiler : public ErrorSink {
        }

        bool isFloatType(Type* pType) {
            TypeTag tag = pType->tag;
            return isFloatTag(pType->tag);
        }

        bool isFloatTag(TypeTag tag) {
            return tag == TY_FLOAT || tag == TY_DOUBLE;
        }

@@ -1283,6 +1286,9 @@ class Compiler : public ErrorSink {
        }

        virtual void loadR0(int ea, bool isIncDec, int op, Type* pType) {
            TypeTag tag = collapseType(pType->tag);
            switch (tag) {
                case TY_INT:
                    gmov(8, ea); /* mov EA, %eax */
                    if (isIncDec) {
                        /* Implement post-increment or post decrement.
@@ -1290,13 +1296,38 @@ class Compiler : public ErrorSink {
                        gmov(0, ea); /* 83 ADD */
                        o(decodeOp(op));
                    }
                    break;
                case TY_FLOAT:
                    if (ea < -LOCAL || ea > LOCAL) {
                        oad(0x05d9, ea); // flds ea
                    } else {
                        oad(0x85d9, ea); // flds ea(%ebp)
                    }
                    if (isIncDec) {
                        error("inc/dec not implemented for float.");
                    }
                    break;
                case TY_DOUBLE:
                    if (ea < -LOCAL || ea > LOCAL) {
                        oad(0x05dd, ea); // fldl ea
                    } else {
                        oad(0x85dd, ea); // fldl ea(%ebp)
                    }
                    if (isIncDec) {
                        error("inc/dec not implemented for double.");
                    }
                    break;
                default:
                    error("Unable to load type %d", tag);
                    break;
            }
            setR0Type(pType);
        }

        virtual void convertR0(Type* pType){
            Type* pR0Type = getR0Type();
            if (pR0Type == NULL) {
                error("don't know R0Type");
                assert(false);
                setR0Type(pType);
                return;
            }
@@ -1304,10 +1335,34 @@ class Compiler : public ErrorSink {
                // do nothing special
            } else if (isFloatType(pType) && isFloatType(pR0Type)) {
                // do nothing special, both held in same register on x87.
            } else {
                TypeTag r0Tag = collapseType(pR0Type->tag);
                TypeTag destTag = collapseType(pType->tag);
                if (r0Tag == TY_INT && isFloatTag(destTag)) {
                    // Convert R0 from int to float
                    o(0x50);      // push %eax
                    o(0x2404DB);  // fildl 0(%esp)
                    o(0x58);      // pop %eax
                } else if (isFloatTag(r0Tag) && destTag == TY_INT) {
                    // Convert R0 from float to int. Complicated because
                    // need to save and restore the rounding mode.
                    o(0x50);       // push %eax
                    o(0x50);       // push %eax
                    o(0x02247cD9); // fnstcw 2(%esp)
                    o(0x2444b70f); // movzwl 2(%esp), %eax
                    o(0x02);
                    o(0x0cb4);     // movb $12, %ah
                    o(0x24048966); // movw %ax, 0(%esp)
                    o(0x242cd9);   // fldcw 0(%esp)
                    o(0x04245cdb); // fistpl 4(%esp)
                    o(0x02246cd9); // fldcw  2(%esp)
                    o(0x58); // pop %eax
                    o(0x58); // pop %eax
                } else {
                    error("Incompatible types old: %d new: %d",
                          pR0Type->tag, pType->tag);
                }
            }
            setR0Type(pType);
        }

+20 −2
Original line number Diff line number Diff line
int ftoi(float f) {
    return f;
}

int dtoi(double d) {
    return d;
}

float itof(int i) {
    return i;
}

double itod(int i) {
    return i;
}

int main() {
    printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3);

    return 42;
    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));
    return 0;
}