summaryrefslogtreecommitdiff
path: root/ujit_asm.c
diff options
context:
space:
mode:
authorMaxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>2020-09-08 16:45:35 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:22 -0400
commit8f40a62647cd7b961faac6b810053b87502d3994 (patch)
treec129b4ce77c324aa52392b8be8bcc459bcf59365 /ujit_asm.c
parent5cf7ccd24a9303b2a591bc0289159517cee6e851 (diff)
Progress on x86 assembler. Encode a few simple instructions.
Diffstat (limited to 'ujit_asm.c')
-rw-r--r--ujit_asm.c84
1 files changed, 68 insertions, 16 deletions
diff --git a/ujit_asm.c b/ujit_asm.c
index bb6ad29a5a..5afea1a0c2 100644
--- a/ujit_asm.c
+++ b/ujit_asm.c
@@ -11,6 +11,24 @@
// TODO: give ujit_examples.h some more meaningful file name
#include "ujit_examples.h"
+// 64-bit GP registers
+const x86opnd_t RAX = { OPND_REG, 64, .reg = { REG_GP, 0 }};
+const x86opnd_t RCX = { OPND_REG, 64, .reg = { REG_GP, 1 }};
+const x86opnd_t RDX = { OPND_REG, 64, .reg = { REG_GP, 2 }};
+const x86opnd_t RBX = { OPND_REG, 64, .reg = { REG_GP, 3 }};
+const x86opnd_t RSP = { OPND_REG, 64, .reg = { REG_GP, 4 }};
+const x86opnd_t RBP = { OPND_REG, 64, .reg = { REG_GP, 5 }};
+const x86opnd_t RSI = { OPND_REG, 64, .reg = { REG_GP, 6 }};
+const x86opnd_t RDI = { OPND_REG, 64, .reg = { REG_GP, 7 }};
+const x86opnd_t R8 = { OPND_REG, 64, .reg = { REG_GP, 8 }};
+const x86opnd_t R9 = { OPND_REG, 64, .reg = { REG_GP, 9 }};
+const x86opnd_t R10 = { OPND_REG, 64, .reg = { REG_GP, 10 }};
+const x86opnd_t R11 = { OPND_REG, 64, .reg = { REG_GP, 11 }};
+const x86opnd_t R12 = { OPND_REG, 64, .reg = { REG_GP, 12 }};
+const x86opnd_t R13 = { OPND_REG, 64, .reg = { REG_GP, 13 }};
+const x86opnd_t R14 = { OPND_REG, 64, .reg = { REG_GP, 14 }};
+const x86opnd_t R15 = { OPND_REG, 64, .reg = { REG_GP, 15 }};
+
void cb_init(codeblock_t* cb, size_t mem_size)
{
// Map the memory as executable
@@ -36,6 +54,15 @@ void cb_init(codeblock_t* cb, size_t mem_size)
cb->num_refs = 0;
}
+/**
+Set the current write position
+*/
+void cb_set_pos(codeblock_t* cb, size_t pos)
+{
+ assert (pos < cb->mem_size);
+ cb->write_pos = pos;
+}
+
// Get a direct pointer into the executable memory block
uint8_t* cb_get_ptr(codeblock_t* cb, size_t index)
{
@@ -128,8 +155,27 @@ void cb_write_epilogue(codeblock_t* cb)
cb_write_byte(cb, ujit_post_call_bytes[i]);
}
+// Check if an operand needs a rex byte to be encoded
+bool rex_needed(x86opnd_t opnd)
+{
+ if (opnd.type == OPND_REG)
+ {
+ return (
+ opnd.reg.reg_no > 7 ||
+ (opnd.num_bits == 8 && opnd.reg.reg_no >= 4 && opnd.reg.reg_no <= 7)
+ );
+ }
+
+ if (opnd.type == OPND_MEM)
+ {
+ return (opnd.mem.base_reg_no > 7) || (opnd.mem.has_idx && opnd.mem.idx_reg_no > 7);
+ }
+
+ assert (false);
+}
+
// Write the REX byte
-void writeREX(
+static void cb_write_rex(
codeblock_t* cb,
bool w_flag,
uint8_t reg_no,
@@ -153,13 +199,12 @@ void writeREX(
}
// Write an opcode byte with an embedded register operand
-/*static void cb_write_opcode(codeblock_t* cb, uint8_t opcode, X86Reg rOpnd)
+static void cb_write_opcode(codeblock_t* cb, uint8_t opcode, x86opnd_t reg)
{
// Write the reg field into the opcode byte
- uint8_t op_byte = opcode | (rOpnd.regNo & 7);
+ uint8_t op_byte = opcode | (reg.reg.reg_no & 7);
cb_write_byte(cb, op_byte);
}
-*/
// nop - Noop, one or multiple bytes long
void nop(codeblock_t* cb, size_t length)
@@ -228,28 +273,35 @@ void nop(codeblock_t* cb, size_t length)
}
}
-/*
/// push - Push a register on the stack
-void push(codeblock_t* cb, X86Reg reg)
+void push(codeblock_t* cb, x86opnd_t reg)
{
- assert (reg.size is 64, "can only push 64-bit registers");
+ assert (reg.num_bits == 64);
//cb.writeASM("push", reg);
- if (reg.rexNeeded)
- cb_write_rex(cb, false, 0, 0, reg.regNo);
- cb_write_byte(cb, 0x50, reg);
+ if (rex_needed(reg))
+ cb_write_rex(cb, false, 0, 0, reg.reg.reg_no);
+
+ cb_write_opcode(cb, 0x50, reg);
}
/// pop - Pop a register off the stack
-void pop(codeblock_t* cb, X86Reg reg)
+void pop(codeblock_t* cb, x86opnd_t reg)
{
- assert (reg.size is 64);
+ assert (reg.num_bits == 64);
//cb.writeASM("pop", reg);
- if (reg.rexNeeded)
- cb_write_rex(false, 0, 0, reg.regNo);
- cb_write_byte(cb, 0x58, reg);
+ if (rex_needed(reg))
+ cb_write_rex(cb, false, 0, 0, reg.reg.reg_no);
+
+ cb_write_opcode(cb, 0x58, reg);
+}
+
+/// ret - Return from call, popping only the return address
+void ret(codeblock_t* cb)
+{
+ //cb.writeASM("ret");
+ cb_write_byte(cb, 0xC3);
}
-*/