@@ -183,21 +183,22 @@ STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) {
183183*/
184184
185185STATIC 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) {
529530void 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
541541void 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
564567void 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
568571void 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
572575void 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/*
589592void 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
593596void 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