nooc

nooc programming language compiler
git clone git://git.nihaljere.xyz/nooc
Log | Files | Refs | LICENSE

commit 74a8da4a94daa636325fb3888499eff2044af250
parent b5563ea6c2c09b21761fc609adaf282fc2751dd1
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Sat, 15 Jan 2022 20:59:28 -0600

x64: use setcc for comparisons and use this for condjump

A few instructions are added, but we gain generality.

Diffstat:
Mx64.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 65 insertions(+), 31 deletions(-)

diff --git a/x64.c b/x64.c @@ -580,6 +580,21 @@ cmp_r8_r8(struct data *text, enum reg reg1, enum reg reg2) } static size_t +cmp_r8_imm(struct data *text, enum reg reg, uint8_t imm) +{ + uint8_t temp; + if (text) { + if (reg >= 8) + array_addlit(text, REX_B); + array_addlit(text, 0x80); + array_addlit(text, (MOD_DIRECT << 6) | (7 << 3) | (reg & 7)); + array_addlit(text, imm); + } + + return 3 + !(reg < 8); +} + +static size_t jng(struct data *text, int64_t offset) { uint8_t temp; @@ -627,13 +642,45 @@ jne(struct data *text, int64_t offset) } return 2; } else { - die("unimplemented jng offet!"); + die("unimplemented jne offet!"); + } + + return 0; // prevents warning +} + +static size_t +je(struct data *text, int64_t offset) +{ + uint8_t temp; + if (-256 <= offset && offset <= 255) { + int8_t i = offset; + if (text) { + array_addlit(text, 0x74); + array_addlit(text, i); + } + return 2; + } else { + die("unimplemented je offet!"); } return 0; // prevents warning } static size_t +sete_reg(struct data *text, enum reg reg) +{ + uint8_t temp; + if (text) { + if (reg >= 8) array_addlit(text, REX_B); + array_addlit(text, 0x0F); + array_addlit(text, 0x94); + array_addlit(text, (MOD_DIRECT << 6) | (reg & 7)); + } + + return 3 + !(reg < 8); +} + +static size_t jmp(struct data *text, int64_t offset) { uint8_t temp; @@ -779,6 +826,17 @@ emitblock(struct data *text, struct iproc *proc, struct instr *start, struct ins total += jmp(text, emitblock(NULL, proc, ins + 1, end, ins->val, active, curi)); NEXT; break; + case IR_CONDJUMP: + assert(ins->valtype == VT_LABEL); + curi++; + label = ins->val; + NEXT; + assert(ins->op == IR_EXTRA); + assert(ins->valtype == VT_TEMP); + total += cmp_r8_imm(text, proc->temps.data[ins->val].reg, 0); + total += je(text, emitblock(NULL, proc, ins + 1, end, label, active, curi)); + NEXT; + break; case IR_RETURN: assert(ins->valtype == VT_EMPTY); total += add_r64_imm(text, RSP, localalloc); @@ -803,48 +861,24 @@ emitblock(struct data *text, struct iproc *proc, struct instr *start, struct ins switch (ins->op) { case IR_CEQ: - // FIXME: use SETcc instructions to generalize - switch (size) { - case 8: - total += mov_r64_r64(text, dest, proc->temps.data[ins->val].reg); - break; - case 4: - total += mov_r32_r32(text, dest, proc->temps.data[ins->val].reg); - break; - case 2: - total += mov_r16_r16(text, dest, proc->temps.data[ins->val].reg); - break; - case 1: - total += mov_r8_r8(text, dest, proc->temps.data[ins->val].reg); - break; - } + src = proc->temps.data[ins->val].reg; NEXT; switch (size) { case 8: - total += cmp_r64_r64(text, dest, proc->temps.data[ins->val].reg); + total += cmp_r64_r64(text, src, proc->temps.data[ins->val].reg); break; case 4: - total += cmp_r32_r32(text, dest, proc->temps.data[ins->val].reg); + total += cmp_r32_r32(text, src, proc->temps.data[ins->val].reg); break; case 2: - total += cmp_r16_r16(text, dest, proc->temps.data[ins->val].reg); + total += cmp_r16_r16(text, src, proc->temps.data[ins->val].reg); break; case 1: - total += cmp_r8_r8(text, dest, proc->temps.data[ins->val].reg); + total += cmp_r8_r8(text, src, proc->temps.data[ins->val].reg); break; } + total += sete_reg(text, dest); NEXT; - if (ins->op == IR_CONDJUMP) { - assert(ins->valtype == VT_LABEL); - curi++; - label = ins->val; - NEXT; - assert(ins->op == IR_EXTRA); - if (ins->val == tmp) { - total += jne(text, emitblock(NULL, proc, ins + 1, end, label, active, curi)); - } - NEXT; - } break; case IR_ADD: assert(ins->valtype == VT_TEMP);