Skip to content

Commit 8941c63

Browse files
committed
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.
1 parent 11bc38d commit 8941c63

1 file changed

Lines changed: 33 additions & 30 deletions

File tree

py/asmx64.c

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -183,21 +183,22 @@ STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {
183183
*/
184184

185185
STATIC void asm_x64_write_r64_disp(asm_x64_t *as, int r64, int disp_r64, int disp_offset) {
186-
assert(disp_r64 != ASM_X64_REG_RSP);
187-
188-
if (disp_r64 == ASM_X64_REG_R12) {
189-
// special case for r12; not fully implemented
190-
assert(SIGNED_FIT8(disp_offset));
191-
asm_x64_write_byte_3(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), 0x24, IMM32_L0(disp_offset));
192-
return;
193-
}
194-
195-
if (disp_offset == 0 && disp_r64 != ASM_X64_REG_RBP && disp_r64 != ASM_X64_REG_R13) {
196-
asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP0 | MODRM_RM_R64(disp_r64));
186+
uint8_t rm_disp;
187+
if (disp_offset == 0 && (disp_r64 & 7) != ASM_X64_REG_RBP) {
188+
rm_disp = MODRM_RM_DISP0;
197189
} else if (SIGNED_FIT8(disp_offset)) {
198-
asm_x64_write_byte_2(as, MODRM_R64(r64) | MODRM_RM_DISP8 | MODRM_RM_R64(disp_r64), IMM32_L0(disp_offset));
190+
rm_disp = MODRM_RM_DISP8;
199191
} else {
200-
asm_x64_write_byte_1(as, MODRM_R64(r64) | MODRM_RM_DISP32 | MODRM_RM_R64(disp_r64));
192+
rm_disp = MODRM_RM_DISP32;
193+
}
194+
asm_x64_write_byte_1(as, MODRM_R64(r64) | rm_disp | MODRM_RM_R64(disp_r64));
195+
if ((disp_r64 & 7) == ASM_X64_REG_RSP) {
196+
// Special case for rsp and r12, they need a SIB byte
197+
asm_x64_write_byte_1(as, 0x24);
198+
}
199+
if (rm_disp == MODRM_RM_DISP8) {
200+
asm_x64_write_byte_1(as, IMM32_L0(disp_offset));
201+
} else if (rm_disp == MODRM_RM_DISP32) {
201202
asm_x64_write_word32(as, disp_offset);
202203
}
203204
}
@@ -529,52 +530,54 @@ void asm_x64_jcc_label(asm_x64_t *as, int jcc_type, mp_uint_t label) {
529530
void asm_x64_entry(asm_x64_t *as, int num_locals) {
530531
assert(num_locals >= 0);
531532
asm_x64_push_r64(as, ASM_X64_REG_RBP);
532-
asm_x64_mov_r64_r64(as, ASM_X64_REG_RBP, ASM_X64_REG_RSP);
533-
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
534-
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);
535533
asm_x64_push_r64(as, ASM_X64_REG_RBX);
536534
asm_x64_push_r64(as, ASM_X64_REG_R12);
537535
asm_x64_push_r64(as, ASM_X64_REG_R13);
536+
num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
537+
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, num_locals * WORD_SIZE);
538538
as->num_locals = num_locals;
539539
}
540540

541541
void asm_x64_exit(asm_x64_t *as) {
542+
asm_x64_sub_r64_i32(as, ASM_X64_REG_RSP, -as->num_locals * WORD_SIZE);
542543
asm_x64_pop_r64(as, ASM_X64_REG_R13);
543544
asm_x64_pop_r64(as, ASM_X64_REG_R12);
544545
asm_x64_pop_r64(as, ASM_X64_REG_RBX);
545-
asm_x64_write_byte_1(as, OPCODE_LEAVE);
546+
asm_x64_pop_r64(as, ASM_X64_REG_RBP);
546547
asm_x64_ret(as);
547548
}
548549

549550
// locals:
550551
// - stored on the stack in ascending order
551552
// - numbered 0 through as->num_locals-1
552-
// - RBP points above the last local
553+
// - RSP points to the first local
553554
//
554-
// | RBP
555-
// v
555+
// | RSP
556+
// v
556557
// l0 l1 l2 ... l(n-1)
557558
// ^ ^
558559
// | low address | high address in RAM
559560
//
560-
STATIC int asm_x64_local_offset_from_ebp(asm_x64_t *as, int local_num) {
561-
return (-as->num_locals + local_num) * WORD_SIZE;
561+
STATIC int asm_x64_local_offset_from_rsp(asm_x64_t *as, int local_num) {
562+
(void)as;
563+
// Stack is full descending, RSP points to local0
564+
return local_num * WORD_SIZE;
562565
}
563566

564567
void asm_x64_mov_local_to_r64(asm_x64_t *as, int src_local_num, int dest_r64) {
565-
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, src_local_num), dest_r64);
568+
asm_x64_mov_mem64_to_r64(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, src_local_num), dest_r64);
566569
}
567570

568571
void asm_x64_mov_r64_to_local(asm_x64_t *as, int src_r64, int dest_local_num) {
569-
asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, dest_local_num));
572+
asm_x64_mov_r64_to_mem64(as, src_r64, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, dest_local_num));
570573
}
571574

572575
void asm_x64_mov_local_addr_to_r64(asm_x64_t *as, int local_num, int dest_r64) {
573-
int offset = asm_x64_local_offset_from_ebp(as, local_num);
576+
int offset = asm_x64_local_offset_from_rsp(as, local_num);
574577
if (offset == 0) {
575-
asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RBP);
578+
asm_x64_mov_r64_r64(as, dest_r64, ASM_X64_REG_RSP);
576579
} else {
577-
asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RBP, offset, dest_r64);
580+
asm_x64_lea_disp_to_r64(as, ASM_X64_REG_RSP, offset, dest_r64);
578581
}
579582
}
580583

@@ -587,12 +590,12 @@ void asm_x64_mov_reg_pcrel(asm_x64_t *as, int dest_r64, mp_uint_t label) {
587590

588591
/*
589592
void asm_x64_push_local(asm_x64_t *as, int local_num) {
590-
asm_x64_push_disp(as, ASM_X64_REG_RBP, asm_x64_local_offset_from_ebp(as, local_num));
593+
asm_x64_push_disp(as, ASM_X64_REG_RSP, asm_x64_local_offset_from_rsp(as, local_num));
591594
}
592595
593596
void asm_x64_push_local_addr(asm_x64_t *as, int local_num, int temp_r64) {
594-
asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RBP);
595-
asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_ebp(as, local_num), temp_r64);
597+
asm_x64_mov_r64_r64(as, temp_r64, ASM_X64_REG_RSP);
598+
asm_x64_add_i32_to_r32(as, asm_x64_local_offset_from_rsp(as, local_num), temp_r64);
596599
asm_x64_push_r64(as, temp_r64);
597600
}
598601
*/

0 commit comments

Comments
 (0)