py/asmx86: Fix stack to be 16-byte aligned for entry and sub-call.
@@ -403,7 +403,7 @@ void asm_x86_entry(asm_x86_t *as, int num_locals) {
asm_x86_push_r32(as, ASM_X86_REG_EBX);
asm_x86_push_r32(as, ASM_X86_REG_ESI);
asm_x86_push_r32(as, ASM_X86_REG_EDI);
- num_locals |= 1; // make it odd so stack is aligned on 16 byte boundary
+ num_locals |= 3; // make it odd so stack is aligned on 16 byte boundary
asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, num_locals * WORD_SIZE);
as->num_locals = num_locals;
}
@@ -497,8 +497,14 @@ void asm_x86_push_local_addr(asm_x86_t *as, int local_num, int temp_r32)
#endif
void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r32) {
- // TODO align stack on 16-byte boundary before the call
assert(n_args <= 5);
+
+ // Align stack on 16-byte boundary during the call
+ unsigned int align = ((n_args + 3) & ~3) - n_args;
+ if (align) {
+ asm_x86_sub_r32_i32(as, ASM_X86_REG_ESP, align * WORD_SIZE);
+ }
+
if (n_args > 4) {
asm_x86_push_r32(as, ASM_X86_REG_ARG_5);
}
@@ -521,7 +527,7 @@ void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r
// the caller must clean up the stack
if (n_args > 0) {
- asm_x86_add_i32_to_r32(as, WORD_SIZE * n_args, ASM_X86_REG_ESP);
+ asm_x86_add_i32_to_r32(as, (n_args + align) * WORD_SIZE, ASM_X86_REG_ESP);
}
}
