summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2019-12-22 23:10:55 +1100
committerDamien George <damien.p.george@gmail.com>2019-12-27 12:30:51 +1100
commitb97fb683d0923d29f55cf54fc2fd5cc19186536e (patch)
tree1e53efc3a6d4384c4d52051ac4ac122aa8b15a8b
parented2be79b4930f620083256fcb5b4faf9091c9ffc (diff)
py/asmx86: Fix stack to be 16-byte aligned for entry and sub-call.
-rw-r--r--py/asmx86.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/py/asmx86.c b/py/asmx86.c
index 23160c9c2..e4736251f 100644
--- a/py/asmx86.c
+++ b/py/asmx86.c
@@ -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);
}
}