commit 89082e58f236c93cdcf2079dfe5cd3203972ace2 from: Benjamin Stürz date: Wed Oct 02 22:37:05 2024 UTC irc: add DT_{DOUBLE,LDOUBLE} commit - e2531862ff12c3ffabbcf078d1acdbd9525963ce commit + 89082e58f236c93cdcf2079dfe5cd3203972ace2 blob - 9fa22d6847539fb6f4804e72a79227997f44ad3a blob + 5afa9bfb442c1bcde3b90efb2d988e57958b2a01 --- cc/irc/TODO +++ cc/irc/TODO @@ -16,7 +16,7 @@ let $2 = add $0, $1; - fix line numbering (doesn't count '}' for some reason) - inline assembly -- direct registers (si, di) +- direct registers access (si, di) - EX_INT16 (int), EX_INT32 (long), EX_INT64 (llong) (for performance reasons) - register refcnt - optimize memory footprint of irc itself @@ -28,3 +28,4 @@ - implement builtin functions - support for double and long double - add conversion between int and float types +- combined cmp-br blob - b7d08527f09ed9cc03c721c9e4670513f1493dba blob + 16b670eaf3c178d6436b29425d3291f06dfff768 --- cc/irc/irc.c +++ cc/irc/irc.c @@ -251,6 +251,8 @@ enum dtype_type { DT_DWORD, DT_QWORD, DT_FLOAT, + DT_DOUBLE, + DT_LDOUBLE, }; struct dtype { @@ -425,7 +427,10 @@ struct dtype *dt; case DT_FLOAT: return 4; case DT_QWORD: + case DT_DOUBLE: return 8; + case DT_LDOUBLE: + return 10; } } @@ -477,6 +482,8 @@ struct dtype *dt; case DT_DWORD: case DT_QWORD: case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: return 0; case DT_NONE: case DT_LABEL: @@ -497,6 +504,8 @@ struct dtype *dt; case DT_QWORD: return 0; case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: case DT_NONE: case DT_LABEL: case DT_DPTR: @@ -506,25 +515,6 @@ struct dtype *dt; } } -assert_dt_is_float (dt) -struct dtype *dt; -{ - switch (dt->type) { - case DT_FLOAT: - return 0; - case DT_BYTE: - case DT_WORD: - case DT_DWORD: - case DT_QWORD: - case DT_NONE: - case DT_LABEL: - case DT_DPTR: - case DT_FPTR: - case DT_SPTR: - return error ("this operation is only supported for floats (float)"); - } -} - // PARSER #define new(T) ((T *)alloc (sizeof (T))) @@ -565,6 +555,10 @@ struct dtype *dt; dt->type = DT_QWORD; } else if (strcmp (lval.s, "float") == 0) { dt->type = DT_FLOAT; + } else if (strcmp (lval.s, "double") == 0) { + dt->type = DT_DOUBLE; + } else if (strcmp (lval.s, "ldouble") == 0) { + dt->type = DT_LDOUBLE; } else { err: error ("expected dtype"); @@ -1141,6 +1135,12 @@ struct dtype *dt; case DT_FLOAT: printf ("float"); break; + case DT_DOUBLE: + printf ("double"); + break; + case DT_LDOUBLE: + printf ("ldouble"); + break; case DT_DPTR: putchar ('*'); print_dt (dt->inner); @@ -1487,13 +1487,32 @@ struct reg *src; return 0; } +// TODO: use src->dt.type loadf (instr, src) char *instr; struct reg *src; { + char *size; + if (instr == NULL) instr = "fld"; - printf ("\t%s dword [ss:bp + %d]\n", instr, src->off); + + switch (src->dt.type) { + case DT_FLOAT: + size = "dword"; + break; + case DT_DOUBLE: + size = "qword"; + break; + case DT_LDOUBLE: + size = "tword"; + break; + default: + abort (); + break; + } + + printf ("\t%s %s [ss:bp + %d]\n", instr, size, src->off); return 0; } @@ -1518,6 +1537,8 @@ struct reg *src; case DT_QWORD: return loadqw (instr, src); case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: return loadf (instr, src); } } @@ -1588,6 +1609,8 @@ long imm; loadimmr (instr, "cx", (imm >> 48) & 0xffff); break; case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: error ("cannot use immediate values for floating-point operations"); break; } @@ -1670,6 +1693,8 @@ struct expr *e; loadpwri (fn, instrn, CX, &e->bin.r, 6); break; case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: loadri (fn, instrf, &e->bin.r); break; case DT_DPTR: @@ -1692,6 +1717,8 @@ struct expr *e; case DT_NONE: case DT_LABEL: case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: abort (); break; case DT_DPTR: @@ -1738,6 +1765,8 @@ struct regimm *shamt; case DT_FPTR: case DT_SPTR: case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: abort (); break; case DT_BYTE: @@ -1854,6 +1883,8 @@ struct expr *e; call_muldiv (instr, fn, dt, e); break; case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: if (ri->is_imm) error ("cannot use immediate values for floating-point operations"); load (NULL, acc); @@ -1887,6 +1918,8 @@ char *cmp, *cc; goto common; case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: // TODO: fix for floats load (NULL, &fn->regs[e->bin.l]); loadri (fn, cmp, &e->bin.r); goto common; @@ -1918,6 +1951,10 @@ struct expr *e; float f; int32_t i; } flint; + union { + double d; + int64_t l; + } dbint; struct regimm *ri; struct reg *r; char *s; @@ -1948,6 +1985,20 @@ struct expr *e; puts ("\tfild dword [ss:bx]"); puts ("\tadd sp, 4"); break; + + case DT_LDOUBLE: + fprintf (stderr, "%d: warning: loading an ldouble by immediate will cause the result to be truncated", linenum); + // fallthrough + + case DT_DOUBLE: + printf ("\tpush %d\n", (int)((e->i >> 48) & 0xffff)); + printf ("\tpush %d\n", (int)((e->i >> 32) & 0xffff)); + printf ("\tpush %d\n", (int)((e->i >> 16) & 0xffff)); + printf ("\tpush %d\n", (int)(e->i & 0xffff)); + puts ("\tmov bx, sp"); + puts ("\tfild qword [ss:bx]"); + puts ("\tadd sp, 4"); + break; } break; case EX_FLOAT: @@ -1960,6 +2011,19 @@ struct expr *e; puts ("\tfld dword [ss:bx]"); puts ("\tadd sp, 4"); break; + case DT_LDOUBLE: + fprintf (stderr, "%d: warning: loading an ldouble by immediate will cause the result to be truncated", linenum); + // fallthrough + case DT_DOUBLE: + dbint.d = e->f; + printf ("\tpush %d\n", (int)((dbint.l >> 48) & 0xffff)); + printf ("\tpush %d\n", (int)((dbint.l >> 32) & 0xffff)); + printf ("\tpush %d\n", (int)((dbint.l >> 16) & 0xffff)); + printf ("\tpush %d\n", (int)(dbint.l & 0xffff)); + puts ("\tmov bx, sp"); + puts ("\tfld dword [ss:bx]"); + puts ("\tadd sp, 4"); + break; case DT_NONE: case DT_LABEL: @@ -1975,12 +2039,18 @@ struct expr *e; } break; case EX_REG: - if (dt->type == DT_FLOAT) { - printf ("\tfld dword [ss:bp + %d]\n", fn->regs[e->reg].off); + switch (dt->type) { + case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: + loadf (NULL, &fn->regs[e->reg]); break; + default: + goto pcast; } - // fallthrough + break; case EX_PCAST: + pcast: load (NULL, &fn->regs[e->reg]); break; case EX_ALLOCA: @@ -2043,6 +2113,8 @@ struct expr *e; call_muldiv ("mul", fn, dt, e); break; case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: load (NULL, r); if (ri->is_imm) error ("cannot use immediate values for floating-point operations"); @@ -2117,7 +2189,6 @@ struct expr *e; break; case DT_DWORD: case DT_FPTR: - case DT_FLOAT: printf ("\tmov ax, word [%s + %d * 4 + 0]\n", s, e->read.off); printf ("\tmov dx, word [%s + %d * 4 + 2]\n", s, e->read.off); break; @@ -2127,6 +2198,11 @@ struct expr *e; printf ("\tmov bx, word [%s + %d * 8 + 4]\n", s, e->read.off); printf ("\tmov cx, word [%s + %d * 8 + 6]\n", s, e->read.off); break; + case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: + // TODO + error ("EX_READ not implemented for floats"); } break; case EX_CALL: @@ -2148,7 +2224,6 @@ struct expr *e; break; case DT_DWORD: case DT_FPTR: - case DT_FLOAT: puts ("\tpush dx"); puts ("\tpush ax"); break; @@ -2158,6 +2233,12 @@ struct expr *e; puts ("\tpush dx"); puts ("\tpush ax"); break; + case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: + // TODO + error ("call not implemented for float arguments"); + break; } cnt += sizeof_dt (ri->dt); @@ -2195,6 +2276,8 @@ struct expr *e; case DT_SPTR: case DT_BYTE: case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: abort (); break; case DT_WORD: @@ -2220,6 +2303,8 @@ struct expr *e; case DT_SPTR: case DT_BYTE: case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: abort (); break; case DT_WORD: @@ -2251,6 +2336,8 @@ struct expr *e; case DT_SPTR: case DT_QWORD: case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: abort (); break; case DT_DWORD: @@ -2371,8 +2458,9 @@ struct ir *ir; printf ("\tmov word [ss:bp + %d + 6], cx\n", r->off); break; case DT_FLOAT: - printf ("\tfstp dword [ss:bp + %d]\n", r->off); - break; + case DT_DOUBLE: + case DT_LDOUBLE: + loadf ("fstp", r); } break; case IR_WRITE: @@ -2394,7 +2482,6 @@ struct ir *ir; break; case DT_DWORD: case DT_FPTR: - case DT_FLOAT: printf ("\tmov word [%s + %d * 4 + 0], ax\n", reg, ir->write.off); printf ("\tmov word [%s + %d * 4 + 2], dx\n", reg, ir->write.off); break; @@ -2404,6 +2491,11 @@ struct ir *ir; printf ("\tmov word [%s + %d * 8 + 4], bx\n", reg, ir->write.off); printf ("\tmov word [%s + %d * 8 + 6], cx\n", reg, ir->write.off); break; + case DT_FLOAT: + case DT_DOUBLE: + case DT_LDOUBLE: + // TODO: floats + error ("IR_WRITE not implemented for floats"); } break; case IR_RET: @@ -2446,7 +2538,10 @@ struct ir *ir; puts ("\ttest ax, ax"); break; case DT_FLOAT: - error ("TODO: IR_BR for DT_FLOAT"); + case DT_DOUBLE: + case DT_LDOUBLE: + // TODO + error ("TODO: IR_BR for floats"); break; }