commit - e2531862ff12c3ffabbcf078d1acdbd9525963ce
commit + 89082e58f236c93cdcf2079dfe5cd3203972ace2
blob - 9fa22d6847539fb6f4804e72a79227997f44ad3a
blob + 5afa9bfb442c1bcde3b90efb2d988e57958b2a01
--- cc/irc/TODO
+++ cc/irc/TODO
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
- 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
DT_DWORD,
DT_QWORD,
DT_FLOAT,
+ DT_DOUBLE,
+ DT_LDOUBLE,
};
struct dtype {
case DT_FLOAT:
return 4;
case DT_QWORD:
+ case DT_DOUBLE:
return 8;
+ case DT_LDOUBLE:
+ return 10;
}
}
case DT_DWORD:
case DT_QWORD:
case DT_FLOAT:
+ case DT_DOUBLE:
+ case DT_LDOUBLE:
return 0;
case DT_NONE:
case DT_LABEL:
case DT_QWORD:
return 0;
case DT_FLOAT:
+ case DT_DOUBLE:
+ case DT_LDOUBLE:
case DT_NONE:
case DT_LABEL:
case DT_DPTR:
}
}
-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)))
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");
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);
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;
}
case DT_QWORD:
return loadqw (instr, src);
case DT_FLOAT:
+ case DT_DOUBLE:
+ case DT_LDOUBLE:
return loadf (instr, src);
}
}
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;
}
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:
case DT_NONE:
case DT_LABEL:
case DT_FLOAT:
+ case DT_DOUBLE:
+ case DT_LDOUBLE:
abort ();
break;
case DT_DPTR:
case DT_FPTR:
case DT_SPTR:
case DT_FLOAT:
+ case DT_DOUBLE:
+ case DT_LDOUBLE:
abort ();
break;
case DT_BYTE:
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);
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;
float f;
int32_t i;
} flint;
+ union {
+ double d;
+ int64_t l;
+ } dbint;
struct regimm *ri;
struct reg *r;
char *s;
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:
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:
}
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:
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");
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;
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:
break;
case DT_DWORD:
case DT_FPTR:
- case DT_FLOAT:
puts ("\tpush dx");
puts ("\tpush ax");
break;
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);
case DT_SPTR:
case DT_BYTE:
case DT_FLOAT:
+ case DT_DOUBLE:
+ case DT_LDOUBLE:
abort ();
break;
case DT_WORD:
case DT_SPTR:
case DT_BYTE:
case DT_FLOAT:
+ case DT_DOUBLE:
+ case DT_LDOUBLE:
abort ();
break;
case DT_WORD:
case DT_SPTR:
case DT_QWORD:
case DT_FLOAT:
+ case DT_DOUBLE:
+ case DT_LDOUBLE:
abort ();
break;
case DT_DWORD:
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:
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;
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:
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;
}