py: Fix stack access in thumb native emitter.
This commit is contained in:
parent
be6aa53cdb
commit
d509ac25f9
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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
15
tests/pybnative/for.py
Normal 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))
|
8
tests/pybnative/for.py.exp
Normal file
8
tests/pybnative/for.py.exp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
0
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
@ -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)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
0
|
||||||
1
|
1
|
||||||
2
|
0
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
4
|
|
||||||
|
Loading…
Reference in New Issue
Block a user