diff options
Diffstat (limited to 'executor/x86_64/asm.c')
-rw-r--r-- | executor/x86_64/asm.c | 32 |
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 |