commit - f22e8bc636ee9525c1abed6c3a29505179154c5f
commit + f5b4351d0b7b927bdca9c46bd239eed63cdf1fac
blob - ef137958b619da006a9d229384f2c2202a7410a6
blob + 7feb311b05ea66737932a84ea795790d8a38e382
--- cc/irc/TODO
+++ cc/irc/TODO
- add `extern` functions
- add function pointers
- rename DT_FPTR to DT_PTR
+- implement builtin functions
blob - b0a2545ae11ab216f4c68e86025fb6478323bc7d
blob + 7c5d209c4bc5557d64aeb8ed69fda3eab96179a7
--- cc/irc/builtins.asm
+++ cc/irc/builtins.asm
global __sarq
__sarq:
ret
+
+global __muld
+; dx:ax val1, stack: val2
+__muld:
+ ret
+
+global __mulq
+; cx:bx:dx:ax: val1, stack: val2
+__mulq:
+ ret
+
+global __divd
+; same ABI as __muld
+__divd:
+ ret
+
+global __divq
+; same ABI as __mulq
+__divq:
+ ret
+
+global __idivd
+; same ABI as __muld
+__idivd:
+ ret
+
+global __idivq
+; same ABI as __mulq
+__idivq:
+ ret
blob - 922d87540be407302a051ee227727345961f366c
blob + d955cd56ace44687676d3abbf3a5fe8e0cb19a49
--- cc/irc/irc.c
+++ cc/irc/irc.c
EX_LSL, // .bin
EX_LSR, // .bin
EX_ASR, // .bin
+ EX_MUL, // .bin
+ EX_UDIV, // .bin
+ EX_SDIV, // .bin
};
struct call {
expr_bin (fn, dt, e, EX_OR);
} else if (strcmp (lval.s, "xor") == 0) {
expr_bin (fn, dt, e, EX_XOR);
+ } else if (strcmp (lval.s, "mul") == 0) {
+ expr_bin (fn, dt, e, EX_MUL);
+ } else if (strcmp (lval.s, "udiv") == 0) {
+ expr_bin (fn, dt, e, EX_UDIV);
+ } else if (strcmp (lval.s, "sdiv") == 0) {
+ expr_bin (fn, dt, e, EX_SDIV);
} else if (strcmp (lval.s, "lsl") == 0) {
expr_shift (fn, dt, e, EX_LSL);
} else if (strcmp (lval.s, "lsr") == 0) {
break;
case EX_XOR:
printf ("xor $%d, ", e->bin.l);
+ print_ri (&e->bin.r);
+ break;
+ case EX_MUL:
+ printf ("mul $%d, ", e->bin.l);
print_ri (&e->bin.r);
break;
+ case EX_UDIV:
+ printf ("udiv $%d, ", e->bin.l);
+ print_ri (&e->bin.r);
+ break;
+ case EX_SDIV:
+ printf ("sdiv $%d, ", e->bin.l);
+ print_ri (&e->bin.r);
+ break;
case EX_PTRADD:
printf ("ptradd $%d, ", e->bin.l);
print_ri (&e->bin.r);
// constant multiply
cmul (reg, i)
-enum x86_reg16 reg;
+char *reg;
{
- char *r;
- int x;
+ int x = ffs (i);
- r = reg16[reg];
-
- x = ffs (i);
if (x == 0) {
- printf ("\txor %s, %s\n", r, r);
+ printf ("\txor %s, %s\n", reg, reg);
return 0;
}
if (i == (1 << (x - 1))) {
- printf ("\tshr %s, %d\n", r, (x - 1));
+ printf ("\tshr %s, %d\n", reg, (x - 1));
return 0;
}
- error ("cmul() not implemented for arbitrary constants");
+ printf ("\timul %s, %d\n", reg, i);
return 0;
}
printf ("\tcall __%sq\n", instr);
break;
}
+
+ return 0;
+}
+
+call_muldiv (instr, fn, dt, e)
+char *instr;
+struct func *fn;
+struct dtype *dt;
+struct expr *e;
+{
+ struct reg *r = &fn->regs[e->bin.l];
+ struct regimm *ri = &e->bin.r;
+
+ switch (dt->type) {
+ case DT_DWORD:
+ if (ri->is_imm) {
+ printf ("\tpush %d\n", (int)((ri->imm >> 16) & 0xffff));
+ printf ("\tpush %d\n", (int)(ri->imm & 0xffff));
+ } else {
+ r = &fn->regs[ri->reg];
+ printf ("\tpush word [ss:bp + %d + 2]\n", r->off);
+ printf ("\tpush word [ss:bp + %d + 0]\n", r->off);
+ }
+ load ("mov", &fn->regs[e->bin.l]);
+ printf ("\tcall __%sd\n", instr);
+ puts ("\tadd sp, 4");
+ break;
+ case DT_QWORD:
+ if (ri->is_imm) {
+ printf ("\tpush %d\n", (int)((ri->imm >> 48) & 0xffff));
+ printf ("\tpush %d\n", (int)((ri->imm >> 32) & 0xffff));
+ printf ("\tpush %d\n", (int)((ri->imm >> 16) & 0xffff));
+ printf ("\tpush %d\n", (int)(ri->imm & 0xffff));
+ } else {
+ r = &fn->regs[ri->reg];
+ printf ("\tpush word [ss:bp + %d + 6]\n", r->off);
+ printf ("\tpush word [ss:bp + %d + 4]\n", r->off);
+ printf ("\tpush word [ss:bp + %d + 2]\n", r->off);
+ printf ("\tpush word [ss:bp + %d + 0]\n", r->off);
+ }
+ load ("mov", &fn->regs[e->bin.l]);
+ printf ("\tcall __%sq\n", instr);
+ puts ("\tadd sp, 8");
+ break;
+ default:
+ abort ();
+ }
+
+ return 0;
+}
+
+gen_div (fn, dt, e, sign)
+struct func *fn;
+struct dtype *dt;
+struct expr *e;
+{
+ struct reg *acc = &fn->regs[e->bin.l];
+ struct regimm *ri = &e->bin.r;
+ char *instr = sign ? "idiv" : "div";
+ switch (dt->type) {
+ case DT_NONE:
+ case DT_LABEL:
+ case DT_DPTR:
+ case DT_FPTR:
+ case DT_SPTR:
+ abort ();
+ break;
+ case DT_BYTE:
+ loadb ("mov", AL, acc);
+ if (sign) {
+ puts ("\tcbw");
+ } else {
+ puts ("\txor dl, dl");
+ }
+ if (ri->is_imm) {
+ loadimmr ("mov", "cl", (int)ri->imm);
+ printf ("\t%s cl\n", instr);
+ } else {
+ printf ("\t%s byte [ss:bp + %d]\n", instr, fn->regs[ri->reg].off);
+ }
+ break;
+ case DT_WORD:
+ loadw ("mov", AX, acc);
+ if (sign) {
+ puts ("\tcwd");
+ } else {
+ puts ("\txor dx, dx");
+ }
+ if (ri->is_imm) {
+ loadimmr ("mov", "cx", (int)ri->imm);
+ printf ("\t%s cx\n", instr);
+ } else {
+ printf ("\t%s word [ss:bp + %d]\n", instr, fn->regs[ri->reg].off);
+ }
+ break;
+ case DT_DWORD:
+ case DT_QWORD:
+ call_muldiv (instr, fn, dt, e);
+ break;
+ }
return 0;
}
case EX_XOR:
alu ("xor", fn, dt, e);
break;
+ case EX_MUL:
+ r = &fn->regs[e->bin.l];
+ ri = &e->bin.r;
+ switch (dt->type) {
+ case DT_NONE:
+ case DT_LABEL:
+ case DT_DPTR:
+ case DT_FPTR:
+ case DT_SPTR:
+ abort ();
+ break;
+ case DT_BYTE:
+ loadb ("mov", AL, r);
+ if (ri->is_imm) {
+ cmul ("al", (int)(ri->imm & 0xff));
+ } else {
+ loadb ("mul", AL, &fn->regs[ri->reg]);
+ }
+ break;
+ case DT_WORD:
+ loadw ("mov", AX, &fn->regs[e->bin.l]);
+ if (ri->is_imm) {
+ cmul ("ax", (int)(ri->imm & 0xffff));
+ } else {
+ loadw ("mul", AX, &fn->regs[ri->reg]);
+ }
+ break;
+ case DT_DWORD:
+ case DT_QWORD:
+ // TODO: multiply using FPU
+ call_muldiv ("mul", fn, dt, e);
+ break;
+ }
+ break;
+ case EX_UDIV:
+ gen_div (fn, dt, e, 0);
+ break;
+ case EX_SDIV:
+ gen_div (fn, dt, e, 1);
+ break;
case EX_PTRADD:
load ("mov", &fn->regs[e->bin.l]);
printf ("\tadd ax, %d\n", (int)(e->bin.r.imm & 0xffff) * sz);
} else {
loadw ("mov", CX, &fn->regs[e->bin.r.reg]);
- cmul (CX, sz);
+ cmul ("cx", sz);
puts ("\tadd ax, cx");
}
break;
puts ("[bits 16]");
puts ("[cpu 286]");
puts ("extern __shld, __shrd, __sard, __shlq, __shrq, __sarq");
+ puts ("extern __muld, __mulq, __divd, __divq, __idivd, __idivq");
puts ("");
parse ();
blob - 8b8808c5e9f1b5b8bc5cfb8027ccbb782ec2992b
blob + a40799c281aab31dd6a69cef7462f958a03f0ecd
--- cc/irc/test.ir
+++ cc/irc/test.ir
let $2: word = read $1;
ret $2;
}
+
+fn multiply ($0: dword, $1: dword): dword {
+ let $2: dword = mul $0, $1;
+ ret $2;
+}
+
+fn qmult ($0: qword, $1: qword): qword {
+ let $2: qword = mul $0, $1;
+ ret $2;
+}
+
+fn division ($0: word, $1: word): word {
+ let $2: word = udiv $0, $1;
+ let $3: word = sdiv $0, $1;
+ let $4: word = add $2, $3;
+ ret $4;
+}
+
+fn qdiv ($0: qword, $1: qword): qword {
+ let $2: qword = udiv $0, $1;
+ let $3: qword = sdiv $0, $1;
+ let $4: qword = add $2, $3;
+ ret $4;
+}