aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorAndrew Chambers <[email protected]>2021-10-09 23:45:16 +1300
committerAndrew Chambers <[email protected]>2021-10-09 23:45:16 +1300
commit5ccab989e58d0bb2d643dfaec51dbea0734ce05f (patch)
tree3420b6192145b819c9832c50787b94eab856368b /main.c
parenta3edd52b53b236a2b88049e634981e8dc7b0bc4d (diff)
Add div/idiv.
Diffstat (limited to 'main.c')
-rw-r--r--main.c32
1 files changed, 32 insertions, 0 deletions
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,