Skip to content
Snippets Groups Projects
Commit 8941c632 authored by Damien George's avatar Damien George
Browse files

py/asmx64: Change stack management to reference locals by rsp not rbp.

The rsp register is always a fixed distance below rbp, and using rsp to
reference locals on the stack frees up the rbp register for general purpose
use.
parent 11bc38d5
No related branches found
No related tags found
No related merge requests found
......@@ -183,21 +183,22 @@ STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {
*/
STATIC void asm_x64_write_r64_disp(asm_x64_t *as, int r64, int disp_r64, int disp_offset) {
assert(disp_r64 != ASM_X64_REG_RSP);
if (disp_r64 == ASM_X64_REG_R12) {
// special case for r12; not fully implemented
assert(SIGNED_FIT8(disp_offset));
asm_x64_write_byte_3(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), 0x24, IMM32_L0(disp_offset));
return;
}
if (disp_offset == 0 && disp_r64 != ASM_X64_REG_RBP && disp_r64 != ASM_X64_REG_R13) {
asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP0 | MODRM_RM_R64(disp_r64));
uint8_t rm_disp;
if (disp_offset == 0 && (disp_r64 & 7) != ASM_X64_REG_RBP) {
rm_disp = MODRM_RM_DISP0;
} else if (SIGNED_FIT8(disp_offset)) {
asm_x64_write_byte_2(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), IMM32_L0(disp_offset));
rm_disp = MODRM_RM_DISP8;
} else {
asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP32 | MODRM_RM_R64(disp_r64));
rm_disp = MODRM_RM_DISP32;
}
asm_x64_write_byte_1(as, MODRM_R64(r64) | rm_disp | MODRM_RM_R64(disp_r64));
if ((disp_r64 & 7) == ASM_X64_REG_RSP) {
// Special case for rsp and r12, they need a SIB byte
asm_x64_write_byte_1(as, 0x24);
}
if (rm_disp == MODRM_RM_DISP8) {
asm_x64_write_byte_1(as, IMM32_L0(disp_offset));
} else if (rm_disp == MODRM_RM_DISP32) {
asm_x64_write_word32(as, disp_offset);
}
}
......@@ -529,52 +530,54 @@ void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label) {
void asm_x64_entry(asm_x64_t *as, int num_locals) {
assert(num_locals >= 0);
asm_x64_push_r64(as, ASM_X64_REG_RBP);
asm_x64_mov_r64_r64(as, ASM_X64_REG_RBP, ASM_X64_REG_RSP);
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);
asm_x64_push_r64(as, ASM_X64_REG_RBX);
asm_x64_push_r64(as, ASM_X64_REG_R12);
asm_x64_push_r64(as, ASM_X64_REG_R13);
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);
as->num_locals = num_locals;
}
void asm_x64_exit(asm_x64_t *as) {
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, -as->num_locals * WORD_SIZE);
asm_x64_pop_r64(as, ASM_X64_REG_R13);
asm_x64_pop_r64(as, ASM_X64_REG_R12);
asm_x64_pop_r64(as, ASM_X64_REG_RBX);
asm_x64_write_byte_1(as, OPCODE_LEAVE);
asm_x64_pop_r64(as, ASM_X64_REG_RBP);
asm_x64_ret(as);
}
// locals:
// - stored on the stack in ascending order
// - numbered 0 through as->num_locals-1
// - RBP points above the last local
// - RSP points to the first local
//
// | RBP
// v
// | RSP
// v
// l0 l1 l2 ... l(n-1)
// ^ ^
// | low address | high address in RAM
//
STATIC int asm_x64_local_offset_from_ebp(asm_x64_t *as, int local_num) {
return (-as->num_locals + local_num) * WORD_SIZE;
STATIC int asm_x64_local_offset_from_rsp(asm_x64_t *as, int local_num) {
(void)as;
// Stack is full descending, RSP points to local0
return local_num * WORD_SIZE;
}
void asm_x64_mov_local_to_r64(asm_x64_t *as, int src_local_num, int dest_r64) {
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, src_local_num), dest_r64);
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, src_local_num), dest_r64);
}
void asm_x64_mov_r64_to_local(asm_x64_t *as, int src_r64, int dest_local_num) {
asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, dest_local_num));
asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, dest_local_num));
}
void asm_x64_mov_local_addr_to_r64(asm_x64_t *as, int local_num, int dest_r64) {
int offset = asm_x64_local_offset_from_ebp(as, local_num);
int offset = asm_x64_local_offset_from_rsp(as, local_num);
if (offset == 0) {
asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RBP);
asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RSP);
} else {
asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RBP, offset, dest_r64);
asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RSP, offset, dest_r64);
}
}
......@@ -587,12 +590,12 @@ void asm_x64_mov_reg_pcrel(asm_x64_t *as, int dest_r64, mp_uint_t label) {
/*
void asm_x64_push_local(asm_x64_t *as, int local_num) {
asm_x64_push_disp(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, local_num));
asm_x64_push_disp(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, local_num));
}
void asm_x64_push_local_addr(asm_x64_t *as, int local_num, int temp_r64) {
asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RBP);
asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_ebp(as, local_num), temp_r64);
asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RSP);
asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_rsp(as, local_num), temp_r64);
asm_x64_push_r64(as, temp_r64);
}
*/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment