From 5ccab989e58d0bb2d643dfaec51dbea0734ce05f Mon Sep 17 00:00:00 2001 From: Andrew Chambers Date: Sat, 9 Oct 2021 23:45:16 +1300 Subject: Add div/idiv. --- main.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'main.c') diff --git a/main.c b/main.c index 8e3da68..a7d0f4c 100644 --- a/main.c +++ b/main.c @@ -528,6 +528,30 @@ static void assemblemov(Instr2 *mov) { } } +static void assemblediv(Instr1 *div, uint8_t reg) { + uint8_t opcode, opsz, rex, mod, rm; + + opsz = 1 << (div->variant % 4); + opcode = opsz == 1 ? 0xf6 : 0xf7; + + if (div->variant < 4) { + if (div->arg->memarg.reg == ASM_RIP) { + assembleriprel(&div->arg->memarg, opsz == 8, opcode, reg, opsz); + } else { + assemblemem(&div->arg->memarg, opsz == 8, opcode, reg, opsz); + } + } else { + mod = 0x03; + rm = regbits(div->arg->kind); + if (opsz == 2) + sb(0x66); + rex = rexbyte(isreg64(div->arg->kind), reg & (1 << 3), 0, rm & (1 << 3)); + if (rex != rexbyte(0, 0, 0, 0)) + sb(rex); + sb2(opcode, modregrm(0x03, reg, rm)); + } +} + static void assemble(void) { Symbol *sym; Parsev *v; @@ -669,6 +693,14 @@ static void assemble(void) { assemblebasicop(&v->instr2, variant2op[v->instr2.variant], 0x04); break; } + case ASM_DIV: { + assemblediv(&v->instr1, 0x06); + break; + } + case ASM_IDIV: { + assemblediv(&v->instr1, 0x07); + break; + } case ASM_OR: { static uint8_t variant2op[24] = { 0x0c, 0x0d, 0x0d, 0x0d, 0x80, 0x81, 0x81, 0x81, -- cgit v1.2.3