diff options
author | Damien George <damien.p.george@gmail.com> | 2014-05-07 23:27:45 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2014-05-07 23:27:45 +0100 |
commit | d509ac25f9f387c5690126c49893d3da142971c2 (patch) | |
tree | 73c188e7ae137e28740d28d42cfdcbc939cc4df4 /py/asmthumb.c | |
parent | be6aa53cdb18359e5c7e51caac2ca0ea7160962d (diff) |
py: Fix stack access in thumb native emitter.
Diffstat (limited to 'py/asmthumb.c')
-rw-r--r-- | py/asmthumb.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/py/asmthumb.c b/py/asmthumb.c index a21a3da30..9e3a9abe2 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -166,15 +166,29 @@ STATIC void asm_thumb_write_word32(asm_thumb_t *as, int w32) { #define OP_ADD_SP(num_words) (0xb000 | (num_words)) #define OP_SUB_SP(num_words) (0xb080 | (num_words)) +// locals: +// - stored on the stack in ascending order +// - numbered 0 through as->num_locals-1 +// - SP points to first local +// +// | SP +// v +// l0 l1 l2 ... l(n-1) +// ^ ^ +// | low address | high address in RAM + void asm_thumb_entry(asm_thumb_t *as, int num_locals) { - // work out what to push and how many extra space to reserve on stack + // work out what to push and how many extra spaces to reserve on stack // so that we have enough for all locals and it's aligned an 8-byte boundary + // we push extra regs (r1, r2, r3) to help do the stack adjustment + // we probably should just always subtract from sp, since this would be more efficient + // for push rlist, lowest numbered register at the lowest address uint reglist; uint stack_adjust; if (num_locals < 0) { num_locals = 0; } - // don't ppop r0 because it's used for return value + // don't pop r0 because it's used for return value switch (num_locals) { case 0: reglist = 0xf2; @@ -398,14 +412,14 @@ void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32) { void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num, uint rlo_src) { assert(rlo_src < REG_R8); - int word_offset = as->num_locals - local_num - 1; + int word_offset = local_num; assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0); asm_thumb_op16(as, OP_STR_TO_SP_OFFSET(rlo_src, word_offset)); } void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) { assert(rlo_dest < REG_R8); - int word_offset = as->num_locals - local_num - 1; + int word_offset = local_num; assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0); asm_thumb_op16(as, OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset)); } @@ -414,7 +428,7 @@ void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) { void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num) { assert(rlo_dest < REG_R8); - int word_offset = as->num_locals - local_num - 1; + int word_offset = local_num; assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0); asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset)); } |