aboutsummaryrefslogtreecommitdiff
path: root/executor/x86_64/asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'executor/x86_64/asm.c')
-rw-r--r--executor/x86_64/asm.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/executor/x86_64/asm.c b/executor/x86_64/asm.c
index f032538..606e539 100644
--- a/executor/x86_64/asm.c
+++ b/executor/x86_64/asm.c
@@ -21,6 +21,7 @@ static usize ins_start_offset = 0;
static void asm_debug_str_append(const char *str) {
const usize len = strlen(str);
am_memcpy(asm_debug_str_buffer + asm_debug_str_buffer_index, str, len);
+ asm_debug_str_buffer[asm_debug_str_buffer_index + len + 1] = '\0';
asm_debug_str_buffer_index += len;
}
@@ -101,12 +102,14 @@ static const char* asm_ptr_to_string(AsmPtr *self) {
asm_debug_str_append(" * ");
asm_debug_str_append_num(1 << self->scale);
}
- if(self->disp < 0)
- asm_debug_str_append(" - ");
- else
- asm_debug_str_append(" + ");
- asm_debug_str_append_num(abs(self->disp));
- asm_debug_str_append("]\0");
+ if(self->disp != 0) {
+ if(self->disp < 0)
+ asm_debug_str_append(" - ");
+ else
+ asm_debug_str_append(" + ");
+ asm_debug_str_append_num(abs(self->disp));
+ }
+ asm_debug_str_append("]");
return buf;
}
#else
@@ -279,6 +282,9 @@ static void asm_rm(Asm *self, AsmPtr *mem, Reg64 reg) {
disp_bytes = 4;
}
+ /* Scale is not valid when index is RSP */
+ assert(mem->index != RSP || mem->scale == 0);
+
#ifdef DEBUG
if(mem->scale != 0 && mem->scale != 2 && mem->scale != 4 && mem->scale != 8) {
amal_log_error("Invalid scale %d, expected 0, 2, 4, or 8", mem->scale);
@@ -307,7 +313,11 @@ static void asm_rm(Asm *self, AsmPtr *mem, Reg64 reg) {
rm_byte = 0x80 + mem->base;
disp_bytes = 4;
}
+
*self->code_it++ = (reg << 3) | rm_byte;
+ /* RSP requires SIB byte when displacement is not 0 */
+ if(mem->base == RSP)
+ *self->code_it++ = 0x24;
}
am_memcpy(self->code_it, &mem->disp, disp_bytes);
@@ -444,6 +454,16 @@ int asm_popr(Asm *self, Reg64 reg) {
return 0;
}
+int asm_callr(Asm *self, Reg64 reg) {
+ ins_start(self);
+ return_if_error(asm_ensure_capacity(self, 3));
+ *self->code_it++ = REX_W;
+ *self->code_it++ = 0xFF;
+ asm_rr(self, reg, 0x2);
+ ins_end(self, "call %s", reg64_to_str(reg));
+ return 0;
+}
+
/*
Note: This is sometimes called with @relative 0 (will print call -5), in which case it's most likely a dummy call until the relative position
is later changed with @asm_override_call_rel32. TODO: Update the ins_end debug print to take that into account somehow