diff options
| author | Andrew Chambers <[email protected]> | 2021-10-09 23:45:16 +1300 |
|---|---|---|
| committer | Andrew Chambers <[email protected]> | 2021-10-09 23:45:16 +1300 |
| commit | 5ccab989e58d0bb2d643dfaec51dbea0734ce05f (patch) | |
| tree | 3420b6192145b819c9832c50787b94eab856368b /main.c | |
| parent | a3edd52b53b236a2b88049e634981e8dc7b0bc4d (diff) | |
Add div/idiv.
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 32 |
1 files changed, 32 insertions, 0 deletions
@@ -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, |
