py: Fix stack access in thumb native emitter.

This commit is contained in:
Damien George 2014-05-07 23:27:45 +01:00
parent be6aa53cdb
commit d509ac25f9
6 changed files with 58 additions and 20 deletions

View File

@ -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_ADD_SP(num_words) (0xb000 | (num_words))
#define OP_SUB_SP(num_words) (0xb080 | (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) { 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 // 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 reglist;
uint stack_adjust; uint stack_adjust;
if (num_locals < 0) { if (num_locals < 0) {
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) { switch (num_locals) {
case 0: case 0:
reglist = 0xf2; 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) { void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num, uint rlo_src) {
assert(rlo_src < REG_R8); 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); assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
asm_thumb_op16(as, OP_STR_TO_SP_OFFSET(rlo_src, word_offset)); 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) { void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num) {
assert(rlo_dest < REG_R8); 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); assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
asm_thumb_op16(as, OP_LDR_FROM_SP_OFFSET(rlo_dest, word_offset)); 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) { void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num) {
assert(rlo_dest < REG_R8); 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); assert(as->pass < ASM_THUMB_PASS_EMIT || word_offset >= 0);
asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset)); asm_thumb_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset));
} }

View File

@ -260,9 +260,9 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
if (i == 0) { if (i == 0) {
asm_x64_mov_r64_to_r64(emit->as, REG_ARG_1, REG_LOCAL_1); asm_x64_mov_r64_to_r64(emit->as, REG_ARG_1, REG_LOCAL_1);
} else if (i == 1) { } else if (i == 1) {
asm_x64_mov_r64_to_local(emit->as, REG_ARG_2, i - 1); asm_x64_mov_r64_to_local(emit->as, REG_ARG_2, i - REG_LOCAL_NUM);
} else if (i == 2) { } else if (i == 2) {
asm_x64_mov_r64_to_local(emit->as, REG_ARG_3, i - 1); asm_x64_mov_r64_to_local(emit->as, REG_ARG_3, i - REG_LOCAL_NUM);
} else { } else {
// TODO not implemented // TODO not implemented
assert(0); assert(0);
@ -739,7 +739,7 @@ STATIC void emit_native_load_fast(emit_t *emit, qstr qstr, uint id_flags, int lo
emit_post_push_reg(emit, vtype, REG_LOCAL_1); emit_post_push_reg(emit, vtype, REG_LOCAL_1);
} else { } else {
need_reg_single(emit, REG_RAX, 0); need_reg_single(emit, REG_RAX, 0);
asm_x64_mov_local_to_r64(emit->as, local_num - 1, REG_RAX); asm_x64_mov_local_to_r64(emit->as, local_num - REG_LOCAL_NUM, REG_RAX);
emit_post_push_reg(emit, vtype, REG_RAX); emit_post_push_reg(emit, vtype, REG_RAX);
} }
#elif N_THUMB #elif N_THUMB
@ -751,7 +751,7 @@ STATIC void emit_native_load_fast(emit_t *emit, qstr qstr, uint id_flags, int lo
emit_post_push_reg(emit, vtype, REG_LOCAL_3); emit_post_push_reg(emit, vtype, REG_LOCAL_3);
} else { } else {
need_reg_single(emit, REG_R0, 0); need_reg_single(emit, REG_R0, 0);
asm_thumb_mov_reg_local(emit->as, REG_R0, local_num - 1); asm_thumb_mov_reg_local(emit->as, REG_R0, local_num - REG_LOCAL_NUM);
emit_post_push_reg(emit, vtype, REG_R0); emit_post_push_reg(emit, vtype, REG_R0);
} }
#endif #endif
@ -820,7 +820,7 @@ STATIC void emit_native_store_fast(emit_t *emit, qstr qstr, int local_num) {
emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1); emit_pre_pop_reg(emit, &vtype, REG_LOCAL_1);
} else { } else {
emit_pre_pop_reg(emit, &vtype, REG_RAX); emit_pre_pop_reg(emit, &vtype, REG_RAX);
asm_x64_mov_r64_to_local(emit->as, REG_RAX, local_num - 1); asm_x64_mov_r64_to_local(emit->as, REG_RAX, local_num - REG_LOCAL_NUM);
} }
#elif N_THUMB #elif N_THUMB
if (local_num == 0) { if (local_num == 0) {
@ -831,7 +831,7 @@ STATIC void emit_native_store_fast(emit_t *emit, qstr qstr, int local_num) {
emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3); emit_pre_pop_reg(emit, &vtype, REG_LOCAL_3);
} else { } else {
emit_pre_pop_reg(emit, &vtype, REG_R0); emit_pre_pop_reg(emit, &vtype, REG_R0);
asm_thumb_mov_local_reg(emit->as, local_num - 1, REG_R0); asm_thumb_mov_local_reg(emit->as, local_num - REG_LOCAL_NUM, REG_R0);
} }
#endif #endif

15
tests/pybnative/for.py Normal file
View File

@ -0,0 +1,15 @@
import pyb
@micropython.native
def f1(n):
for i in range(n):
print(i)
f1(4)
@micropython.native
def f2(r):
for i in r:
print(i)
f2(range(4))

View File

@ -0,0 +1,8 @@
0
1
2
3
0
1
2
3

View File

@ -1,14 +1,15 @@
import pyb
@micropython.native @micropython.native
def f(led, n): def f(led, n, d):
led.off() led.off()
i = 0 i = 0
while i < n: while i < n:
led.toggle()
d = pyb.delay
d(50) # pyb.delay(50) doesn't work!
i += 1
print(i) print(i)
led.toggle()
pyb.delay(d)
i += 1
led.off() led.off()
f(pyb.LED(1), 2) f(pyb.LED(1), 2, 150)
f(pyb.LED(2), 4) f(pyb.LED(2), 4, 50)

View File

@ -1,6 +1,6 @@
0
1 1
2 0
1 1
2 2
3 3
4