commit b374c57b127d44eb594a2c2d74b9b4fd7bb9b9d2
parent 185f18ae490552cb8e16e23c6c9f145b55d2f101
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Mon, 10 Jan 2022 15:10:39 -0600
x64: remove unused functions and make instruction functions static
Diffstat:
M | x64.c | | | 486 | +++++++++++++++++++++++++++++++++++++------------------------------------------ |
M | x64.h | | | 44 | -------------------------------------------- |
2 files changed, 229 insertions(+), 301 deletions(-)
diff --git a/x64.c b/x64.c
@@ -29,223 +29,7 @@ unsigned short used_reg;
extern struct toplevel toplevel;
-#define NEXT ins++; assert(ins <= end);
-
static size_t
-emitsyscall(char *buf, uint8_t paramcount)
-{
- assert(paramcount < 8);
- size_t total = 0;
- total += push_r64(buf ? buf + total : NULL, RBP);
- total += mov_r64_r64(buf ? buf + total : NULL, RBP, RSP);
-
- for (size_t i = 0; i < paramcount; i++) {
- total += push_r64(buf ? buf + total : NULL, abi_arg[i]);
- total += mov_disp8_r64_m64(buf ? buf + total : NULL, abi_arg[i], RBP, 8*i + 16);
- }
-
- if (buf) {
- *(buf + total++) = 0x0f;
- *(buf + total++) = 0x05;
- } else {
- total += 2;
- }
-
- total += mov_disp8_r64_m64(buf ? buf + total : NULL, RDI, RBP, 8*paramcount + 16);
- total += mov_mr64_r64(buf ? buf + total : NULL, RDI, RAX);
-
- for (size_t i = paramcount - 1; i < paramcount; i--) {
- total += pop_r64(buf ? buf + total : NULL, abi_arg[i]);
- }
-
- total += pop_r64(buf ? buf + total : NULL, RBP);
- total += ret(buf ? buf + total : NULL);
-
- return total;
-}
-
-const struct target x64_target = {
- .reserved = (1 << RSP) | (1 << RBP),
- .emitsyscall = emitsyscall
-};
-
-size_t
-emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end, uint64_t end_label)
-{
- struct instr *ins = start ? start : proc->data;
- end = end ? end : &proc->data[proc->len];
-
- uint64_t dest, src, size, count, tmp, label;
- int64_t offset;
- uint64_t localalloc = 0;
-
- size_t total = 0;
- if (!start) {
- total += push_r64(buf ? buf + total : NULL, RBP);
- total += mov_r64_r64(buf ? buf + total : NULL, RBP, RSP);
- }
-
- while (ins < end) {
- switch (ins->op) {
- // FIXME: we don't handle jumps backward yet
- case IR_JUMP:
- total += jmp(buf ? buf + total : NULL, emitblock(NULL, proc, ins + 1, end, ins->id));
- NEXT;
- break;
- case IR_RETURN:
- total += add_r64_imm(buf ? buf + total : NULL, RSP, localalloc);
- total += pop_r64(buf ? buf + total : NULL, RBP);
- total += ret(buf ? buf + total : NULL);
- NEXT;
- break;
- case IR_SIZE:
- size = ins->id;
- NEXT;
-
- switch (ins->op) {
- case IR_STORE:
- src = proc->intervals.data[ins->id].reg;
- NEXT;
- assert(ins->op == IR_EXTRA);
- total += mov_mr64_r64(buf ? buf + total : NULL, proc->intervals.data[ins->id].reg, src);
- NEXT;
- break;
- default:
- die("x64 emitblock: unhandled size instruction");
- }
- break;
- case IR_ASSIGN:
- tmp = ins->id;
- dest = proc->intervals.data[ins->id].reg;
- NEXT;
-
- assert(ins->op == IR_SIZE);
- size = ins->id;
- NEXT;
-
- switch (ins->op) {
- case IR_CEQ:
- total += mov_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
- NEXT;
- total += cmp_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
- NEXT;
- if (ins->op == IR_CONDJUMP) {
- label = ins->id;
- NEXT;
- assert(ins->op == IR_EXTRA);
- if (ins->id == tmp) {
- total += jne(buf ? buf + total : NULL, emitblock(NULL, proc, ins + 1, end, label));
- }
- NEXT;
- }
- break;
- case IR_ADD:
- total += mov_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
- NEXT;
- total += add_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
- NEXT;
- break;
- case IR_IMM:
- total += mov_r64_imm(buf ? buf + total : NULL, dest, ins->id);
- NEXT;
- break;
- case IR_IN:
- total += mov_disp8_r64_m64(buf ? buf + total : NULL, dest, RBP, 8*ins->id + 16);
- NEXT;
- break;
- case IR_LOAD:
- total += mov_r64_mr64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
- NEXT;
- break;
- case IR_ALLOC:
- total += mov_r64_r64(buf ? buf + total : NULL, dest, RSP);
- total += sub_r64_imm(buf ? buf + total : NULL, RSP, 8); // FIXME: hardcoding
- localalloc += 8;
- NEXT;
- break;
- default:
- die("x64 emitblock: unhandled assign instruction");
- }
- break;
- case IR_CALL:
- count = 0;
- dest = ins->id;
-
- for (int i = 0; i < 16; i++) {
- total += push_r64(buf ? buf + total : NULL, i);
- }
-
- NEXT;
- while (ins->op == IR_CALLARG) {
- count++;
- total += push_r64(buf ? buf + total : NULL, proc->intervals.data[ins->id].reg);
- NEXT;
- }
-
- // we assume call is constant width - this should probably change
- offset = -(proc->addr + total - toplevel.code.data[dest].addr + call(NULL, 0));
- total += call(buf ? buf + total : NULL, offset);
- // FIXME: this won't work with non-64-bit things
- total += add_r64_imm(buf ? buf + total : NULL, RSP, 8*count);
- for (int i = 15; i >= 0; i--) {
- total += pop_r64(buf ? buf + total : NULL, i);
- }
- break;
- case IR_LABEL:
- if (ins->id == end_label)
- goto done;
-
- NEXT;
- break;
- case IR_STORE:
- case IR_IMM:
- case IR_ALLOC:
- die("x64 emitblock: invalid start of instruction");
- default:
- die("x64 emitproc: unknown instruction");
- }
- }
-
-done:
- return total;
-}
-
-// FIXME: use array_push
-size_t
-emitproc(char *buf, struct iproc *proc)
-{
- return emitblock(buf, proc, NULL, NULL, 0);
-}
-
-#undef NEXT
-
-void
-clearreg()
-{
- used_reg = (1 << RBP) | (1 << RSP);
-}
-
-enum reg
-getreg()
-{
- for (int i = 0; i < 16; i++) {
- if (!(used_reg & (1 << i))) {
- used_reg |= (1 << i);
- return i;
- }
- }
-
- die("out of registers!");
- return 0; // prevents warning
-}
-
-void
-freereg(enum reg reg)
-{
- used_reg &= ~(1 << reg);
-}
-
-size_t
add_r64_imm(char *buf, enum reg dest, uint64_t imm)
{
if (buf) {
@@ -261,7 +45,7 @@ add_r64_imm(char *buf, enum reg dest, uint64_t imm)
return 7;
}
-size_t
+static size_t
mov_r64_imm(char *buf, enum reg dest, uint64_t imm)
{
if (buf) {
@@ -280,7 +64,7 @@ mov_r64_imm(char *buf, enum reg dest, uint64_t imm)
return 10;
}
-size_t
+static size_t
mov_r32_imm(char *buf, enum reg dest, uint32_t imm)
{
if (buf) {
@@ -294,7 +78,7 @@ mov_r32_imm(char *buf, enum reg dest, uint32_t imm)
return 5;
}
-size_t
+static size_t
mov_r16_imm(char *buf, enum reg dest, uint16_t imm)
{
if (buf) {
@@ -307,7 +91,7 @@ mov_r16_imm(char *buf, enum reg dest, uint16_t imm)
return 4;
}
-size_t
+static size_t
mov_r8_imm(char *buf, enum reg dest, uint8_t imm)
{
if (buf) {
@@ -318,7 +102,7 @@ mov_r8_imm(char *buf, enum reg dest, uint8_t imm)
return 2;
}
-size_t
+static size_t
mov_r64_m64(char *buf, enum reg dest, uint64_t addr)
{
uint8_t sib = 0x25;
@@ -336,7 +120,7 @@ mov_r64_m64(char *buf, enum reg dest, uint64_t addr)
return 8;
}
-size_t
+static size_t
mov_r32_m32(char *buf, enum reg dest, uint32_t addr)
{
if (buf) {
@@ -353,7 +137,7 @@ mov_r32_m32(char *buf, enum reg dest, uint32_t addr)
return dest >= 8 ? 8 : 7;
}
-size_t
+static size_t
mov_r16_m16(char *buf, enum reg dest, uint32_t addr)
{
if (buf) {
@@ -371,7 +155,7 @@ mov_r16_m16(char *buf, enum reg dest, uint32_t addr)
return dest >= 8 ? 9 : 8;
}
-size_t
+static size_t
mov_r8_m8(char *buf, enum reg dest, uint32_t addr)
{
if (buf) {
@@ -388,7 +172,7 @@ mov_r8_m8(char *buf, enum reg dest, uint32_t addr)
return dest >= 8 ? 8 : 7;
}
-size_t
+static size_t
mov_m64_r64(char *buf, uint64_t addr, enum reg src)
{
if (buf) {
@@ -407,7 +191,7 @@ mov_m64_r64(char *buf, uint64_t addr, enum reg src)
return 10;
}
-size_t
+static size_t
mov_m32_r32(char *buf, uint64_t addr, enum reg src)
{
if (buf) {
@@ -425,7 +209,7 @@ mov_m32_r32(char *buf, uint64_t addr, enum reg src)
return 9;
}
-size_t
+static size_t
mov_mr64_r64(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -437,7 +221,7 @@ mov_mr64_r64(char *buf, enum reg dest, enum reg src)
return 3;
}
-size_t
+static size_t
mov_mr32_r32(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -448,7 +232,7 @@ mov_mr32_r32(char *buf, enum reg dest, enum reg src)
return 2;
}
-size_t
+static size_t
mov_mr16_r16(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -460,7 +244,7 @@ mov_mr16_r16(char *buf, enum reg dest, enum reg src)
return 3;
}
-size_t
+static size_t
mov_mr8_r8(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -471,7 +255,7 @@ mov_mr8_r8(char *buf, enum reg dest, enum reg src)
return 2;
}
-size_t
+static size_t
mov_r64_mr64(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -483,7 +267,7 @@ mov_r64_mr64(char *buf, enum reg dest, enum reg src)
return 3;
}
-size_t
+static size_t
mov_r32_mr32(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -494,7 +278,7 @@ mov_r32_mr32(char *buf, enum reg dest, enum reg src)
return 2;
}
-size_t
+static size_t
mov_r16_mr16(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -506,7 +290,7 @@ mov_r16_mr16(char *buf, enum reg dest, enum reg src)
return 3;
}
-size_t
+static size_t
mov_r8_mr8(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -517,7 +301,7 @@ mov_r8_mr8(char *buf, enum reg dest, enum reg src)
return 2;
}
-size_t
+static size_t
mov_r64_r64(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -529,7 +313,7 @@ mov_r64_r64(char *buf, enum reg dest, enum reg src)
return 3;
}
-size_t
+static size_t
mov_r32_r32(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -541,7 +325,7 @@ mov_r32_r32(char *buf, enum reg dest, enum reg src)
return (src >= 8 || dest >= 8) ? 3 : 2;
}
-size_t
+static size_t
mov_disp8_m64_r64(char *buf, enum reg dest, int8_t disp, enum reg src)
{
assert(src != 4);
@@ -556,7 +340,7 @@ mov_disp8_m64_r64(char *buf, enum reg dest, int8_t disp, enum reg src)
}
// FIXME: we don't handle r8-r15 properly in most of these
-size_t
+static size_t
mov_disp8_m32_r32(char *buf, enum reg dest, int8_t disp, enum reg src)
{
assert(src != 4);
@@ -570,7 +354,7 @@ mov_disp8_m32_r32(char *buf, enum reg dest, int8_t disp, enum reg src)
}
// FIXME: we don't handle r8-r15 properly in most of these
-size_t
+static size_t
mov_disp8_m16_r16(char *buf, enum reg dest, int8_t disp, enum reg src)
{
assert(src != 4);
@@ -585,7 +369,7 @@ mov_disp8_m16_r16(char *buf, enum reg dest, int8_t disp, enum reg src)
}
// FIXME: we don't handle r8-r15 properly in most of these
-size_t
+static size_t
mov_disp8_m8_r8(char *buf, enum reg dest, int8_t disp, enum reg src)
{
assert(src != 4);
@@ -598,7 +382,7 @@ mov_disp8_m8_r8(char *buf, enum reg dest, int8_t disp, enum reg src)
return 3;
}
-size_t
+static size_t
mov_disp8_r64_m64(char *buf, enum reg dest, enum reg src, int8_t disp)
{
assert(src != 4);
@@ -612,7 +396,7 @@ mov_disp8_r64_m64(char *buf, enum reg dest, enum reg src, int8_t disp)
return 4;
}
-size_t
+static size_t
mov_disp8_r32_m32(char *buf, enum reg dest, enum reg src, int8_t disp)
{
assert(src != 4);
@@ -625,7 +409,7 @@ mov_disp8_r32_m32(char *buf, enum reg dest, enum reg src, int8_t disp)
return 3;
}
-size_t
+static size_t
mov_disp8_r16_m16(char *buf, enum reg dest, enum reg src, int8_t disp)
{
assert(src != 4);
@@ -639,7 +423,7 @@ mov_disp8_r16_m16(char *buf, enum reg dest, enum reg src, int8_t disp)
return 4;
}
-size_t
+static size_t
mov_disp8_r8_m8(char *buf, enum reg dest, enum reg src, int8_t disp)
{
assert(src != 4);
@@ -652,7 +436,7 @@ mov_disp8_r8_m8(char *buf, enum reg dest, enum reg src, int8_t disp)
return 3;
}
-size_t
+static size_t
lea_disp8(char *buf, enum reg dest, enum reg src, int8_t disp)
{
assert(src != 4);
@@ -666,7 +450,7 @@ lea_disp8(char *buf, enum reg dest, enum reg src, int8_t disp)
return 4;
}
-size_t
+static size_t
add_r64_r64(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -678,7 +462,7 @@ add_r64_r64(char *buf, enum reg dest, enum reg src)
return 3;
}
-size_t
+static size_t
sub_r64_r64(char *buf, enum reg dest, enum reg src)
{
if (buf) {
@@ -690,7 +474,7 @@ sub_r64_r64(char *buf, enum reg dest, enum reg src)
return 3;
}
-size_t
+static size_t
sub_r64_imm(char *buf, enum reg dest, int32_t imm)
{
if (buf) {
@@ -706,7 +490,7 @@ sub_r64_imm(char *buf, enum reg dest, int32_t imm)
return 7;
}
-size_t
+static size_t
cmp_r64_r64(char *buf, enum reg reg1, enum reg reg2)
{
if (buf) {
@@ -718,7 +502,7 @@ cmp_r64_r64(char *buf, enum reg reg1, enum reg reg2)
return 3;
}
-size_t
+static size_t
jng(char *buf, int64_t offset)
{
if (-256 <= offset && offset <= 255) {
@@ -735,7 +519,7 @@ jng(char *buf, int64_t offset)
return 0; // prevents warning
}
-size_t
+static size_t
jg(char *buf, int64_t offset)
{
if (-256 <= offset && offset <= 255) {
@@ -752,7 +536,7 @@ jg(char *buf, int64_t offset)
return 0; // prevents warning
}
-size_t
+static size_t
jne(char *buf, int64_t offset)
{
if (-256 <= offset && offset <= 255) {
@@ -769,7 +553,7 @@ jne(char *buf, int64_t offset)
return 0; // prevents warning
}
-size_t
+static size_t
jmp(char *buf, int64_t offset)
{
if (-256 <= offset && offset <= 255) {
@@ -786,7 +570,7 @@ jmp(char *buf, int64_t offset)
return 0; // prevents warning
}
-size_t
+static size_t
call(char *buf, int32_t offset)
{
if (buf) {
@@ -800,7 +584,7 @@ call(char *buf, int32_t offset)
return 5;
}
-size_t
+static size_t
ret(char *buf)
{
if (buf)
@@ -809,7 +593,7 @@ ret(char *buf)
return 1;
}
-size_t
+static size_t
push_r64(char *buf, enum reg reg)
{
if (buf) {
@@ -822,7 +606,7 @@ push_r64(char *buf, enum reg reg)
return reg >= 8 ? 2 : 1;
}
-size_t
+static size_t
pop_r64(char *buf, enum reg reg)
{
if (buf) {
@@ -834,3 +618,191 @@ pop_r64(char *buf, enum reg reg)
return reg >= 8 ? 2 : 1;
}
+
+#define NEXT ins++; assert(ins <= end);
+
+static size_t
+emitsyscall(char *buf, uint8_t paramcount)
+{
+ assert(paramcount < 8);
+ size_t total = 0;
+ total += push_r64(buf ? buf + total : NULL, RBP);
+ total += mov_r64_r64(buf ? buf + total : NULL, RBP, RSP);
+
+ for (size_t i = 0; i < paramcount; i++) {
+ total += push_r64(buf ? buf + total : NULL, abi_arg[i]);
+ total += mov_disp8_r64_m64(buf ? buf + total : NULL, abi_arg[i], RBP, 8*i + 16);
+ }
+
+ if (buf) {
+ *(buf + total++) = 0x0f;
+ *(buf + total++) = 0x05;
+ } else {
+ total += 2;
+ }
+
+ total += mov_disp8_r64_m64(buf ? buf + total : NULL, RDI, RBP, 8*paramcount + 16);
+ total += mov_mr64_r64(buf ? buf + total : NULL, RDI, RAX);
+
+ for (size_t i = paramcount - 1; i < paramcount; i--) {
+ total += pop_r64(buf ? buf + total : NULL, abi_arg[i]);
+ }
+
+ total += pop_r64(buf ? buf + total : NULL, RBP);
+ total += ret(buf ? buf + total : NULL);
+
+ return total;
+}
+
+const struct target x64_target = {
+ .reserved = (1 << RSP) | (1 << RBP),
+ .emitsyscall = emitsyscall
+};
+
+size_t
+emitblock(char *buf, struct iproc *proc, struct instr *start, struct instr *end, uint64_t end_label)
+{
+ struct instr *ins = start ? start : proc->data;
+ end = end ? end : &proc->data[proc->len];
+
+ uint64_t dest, src, size, count, tmp, label;
+ int64_t offset;
+ uint64_t localalloc = 0;
+
+ size_t total = 0;
+ if (!start) {
+ total += push_r64(buf ? buf + total : NULL, RBP);
+ total += mov_r64_r64(buf ? buf + total : NULL, RBP, RSP);
+ }
+
+ while (ins < end) {
+ switch (ins->op) {
+ // FIXME: we don't handle jumps backward yet
+ case IR_JUMP:
+ total += jmp(buf ? buf + total : NULL, emitblock(NULL, proc, ins + 1, end, ins->id));
+ NEXT;
+ break;
+ case IR_RETURN:
+ total += add_r64_imm(buf ? buf + total : NULL, RSP, localalloc);
+ total += pop_r64(buf ? buf + total : NULL, RBP);
+ total += ret(buf ? buf + total : NULL);
+ NEXT;
+ break;
+ case IR_SIZE:
+ size = ins->id;
+ NEXT;
+
+ switch (ins->op) {
+ case IR_STORE:
+ src = proc->intervals.data[ins->id].reg;
+ NEXT;
+ assert(ins->op == IR_EXTRA);
+ total += mov_mr64_r64(buf ? buf + total : NULL, proc->intervals.data[ins->id].reg, src);
+ NEXT;
+ break;
+ default:
+ die("x64 emitblock: unhandled size instruction");
+ }
+ break;
+ case IR_ASSIGN:
+ tmp = ins->id;
+ dest = proc->intervals.data[ins->id].reg;
+ NEXT;
+
+ assert(ins->op == IR_SIZE);
+ size = ins->id;
+ NEXT;
+
+ switch (ins->op) {
+ case IR_CEQ:
+ total += mov_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ NEXT;
+ total += cmp_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ NEXT;
+ if (ins->op == IR_CONDJUMP) {
+ label = ins->id;
+ NEXT;
+ assert(ins->op == IR_EXTRA);
+ if (ins->id == tmp) {
+ total += jne(buf ? buf + total : NULL, emitblock(NULL, proc, ins + 1, end, label));
+ }
+ NEXT;
+ }
+ break;
+ case IR_ADD:
+ total += mov_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ NEXT;
+ total += add_r64_r64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ NEXT;
+ break;
+ case IR_IMM:
+ total += mov_r64_imm(buf ? buf + total : NULL, dest, ins->id);
+ NEXT;
+ break;
+ case IR_IN:
+ total += mov_disp8_r64_m64(buf ? buf + total : NULL, dest, RBP, 8*ins->id + 16);
+ NEXT;
+ break;
+ case IR_LOAD:
+ total += mov_r64_mr64(buf ? buf + total : NULL, dest, proc->intervals.data[ins->id].reg);
+ NEXT;
+ break;
+ case IR_ALLOC:
+ total += mov_r64_r64(buf ? buf + total : NULL, dest, RSP);
+ total += sub_r64_imm(buf ? buf + total : NULL, RSP, 8); // FIXME: hardcoding
+ localalloc += 8;
+ NEXT;
+ break;
+ default:
+ die("x64 emitblock: unhandled assign instruction");
+ }
+ break;
+ case IR_CALL:
+ count = 0;
+ dest = ins->id;
+
+ for (int i = 0; i < 16; i++) {
+ total += push_r64(buf ? buf + total : NULL, i);
+ }
+
+ NEXT;
+ while (ins->op == IR_CALLARG) {
+ count++;
+ total += push_r64(buf ? buf + total : NULL, proc->intervals.data[ins->id].reg);
+ NEXT;
+ }
+
+ // we assume call is constant width - this should probably change
+ offset = -(proc->addr + total - toplevel.code.data[dest].addr + call(NULL, 0));
+ total += call(buf ? buf + total : NULL, offset);
+ // FIXME: this won't work with non-64-bit things
+ total += add_r64_imm(buf ? buf + total : NULL, RSP, 8*count);
+ for (int i = 15; i >= 0; i--) {
+ total += pop_r64(buf ? buf + total : NULL, i);
+ }
+ break;
+ case IR_LABEL:
+ if (ins->id == end_label)
+ goto done;
+
+ NEXT;
+ break;
+ case IR_STORE:
+ case IR_IMM:
+ case IR_ALLOC:
+ die("x64 emitblock: invalid start of instruction");
+ default:
+ die("x64 emitproc: unknown instruction");
+ }
+ }
+
+done:
+ return total;
+}
+
+// FIXME: use array_push
+size_t
+emitproc(char *buf, struct iproc *proc)
+{
+ return emitblock(buf, proc, NULL, NULL, 0);
+}
diff --git a/x64.h b/x64.h
@@ -20,48 +20,4 @@ enum reg {
extern char abi_arg[];
extern unsigned short used_reg;
-void clearreg();
-enum reg getreg();
-void freereg(enum reg reg);
-
-size_t add_r64_imm(char *buf, enum reg reg, uint64_t imm);
-size_t mov_r64_imm(char *buf, enum reg reg, uint64_t imm);
-size_t mov_r64_m64(char *buf, enum reg reg, uint64_t addr);
-size_t mov_r32_m32(char *buf, enum reg dest, uint32_t addr);
-size_t mov_r16_m16(char *buf, enum reg dest, uint32_t addr);
-size_t mov_r8_m8(char *buf, enum reg dest, uint32_t addr);
-size_t mov_m64_r64(char *buf, uint64_t addr, enum reg reg);
-size_t mov_m32_r32(char *buf, uint64_t addr, enum reg src);
-size_t mov_m16_r16(char *buf, uint64_t addr, enum reg src);
-size_t mov_mr64_r64(char *buf, enum reg dest, enum reg src);
-size_t mov_mr32_r32(char *buf, enum reg dest, enum reg src);
-size_t mov_mr16_r16(char *buf, enum reg dest, enum reg src);
-size_t mov_mr8_r8(char *buf, enum reg dest, enum reg src);
-size_t mov_r64_mr64(char *buf, enum reg dest, enum reg src);
-size_t mov_r32_mr32(char *buf, enum reg dest, enum reg src);
-size_t mov_r16_mr16(char *buf, enum reg dest, enum reg src);
-size_t mov_r8_mr8(char *buf, enum reg dest, enum reg src);
-size_t mov_r64_r64(char *buf, enum reg dest, enum reg src);
-size_t mov_disp8_m64_r64(char *buf, enum reg dest, int8_t disp, enum reg src);
-size_t mov_disp8_m32_r32(char *buf, enum reg dest, int8_t disp, enum reg src);
-size_t mov_disp8_m16_r16(char *buf, enum reg dest, int8_t disp, enum reg src);
-size_t mov_disp8_m8_r8(char *buf, enum reg dest, int8_t disp, enum reg src);
-size_t mov_disp8_r64_m64(char *buf, enum reg dest, enum reg src, int8_t disp);
-size_t mov_disp8_r32_m32(char *buf, enum reg dest, enum reg src, int8_t disp);
-size_t mov_disp8_r16_m16(char *buf, enum reg dest, enum reg src, int8_t disp);
-size_t mov_disp8_r8_m8(char *buf, enum reg dest, enum reg src, int8_t disp);
-size_t lea_disp8(char *buf, enum reg dest, enum reg src, int8_t disp);
-size_t add_r64_r64(char *buf, enum reg reg1, enum reg reg2);
-size_t sub_r64_r64(char *buf, enum reg reg1, enum reg reg2);
-size_t sub_r64_imm(char *buf, enum reg reg1, int32_t imm);
-size_t cmp_r64_r64(char *buf, enum reg reg1, enum reg reg2);
-size_t jng(char *buf, int64_t offset);
-size_t jg(char *buf, int64_t offset);
-size_t jne(char *buf, int64_t offset);
-size_t jmp(char *buf, int64_t offset);
-size_t call(char *buf, int32_t offset);
-size_t ret(char *buf);
-size_t push_r64(char *buf, enum reg reg);
-size_t pop_r64(char *buf, enum reg reg);
-
size_t emitproc(char *buf, struct iproc *proc);