diff --git a/py/asmarm.c b/py/asmarm.c index 8dbd9ad20a..3fac94285b 100644 --- a/py/asmarm.c +++ b/py/asmarm.c @@ -297,10 +297,9 @@ void asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn) { emit_al(as, 0x1500000 | (rd << 16) | rn); } -void asm_arm_less_op(asm_arm_t *as, uint rd, uint rn, uint rm) { - asm_arm_cmp_reg_reg(as, rn, rm); // cmp rn, rm - emit(as, asm_arm_op_mov_imm(rd, 1) | ASM_ARM_CC_LT); // movlt rd, #1 - emit(as, asm_arm_op_mov_imm(rd, 0) | ASM_ARM_CC_GE); // movge rd, #0 +void asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond) { + emit(as, asm_arm_op_mov_imm(rd, 1) | cond); // movCOND rd, #1 + emit(as, asm_arm_op_mov_imm(rd, 0) | (cond ^ (1 << 28))); // mov!COND rd, #0 } void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { @@ -318,6 +317,47 @@ void asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num) { emit_al(as, asm_arm_op_add_imm(rd, ASM_ARM_REG_SP, local_num << 2)); } +void asm_arm_lsl_reg_reg(asm_arm_t *as, uint rd, uint rs) { + // mov rd, rd, lsl rs + emit_al(as, 0x1a00010 | (rd << 12) | (rs << 8) | rd); +} + +void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs) { + // mov rd, rd, asr rs + emit_al(as, 0x1a00050 | (rd << 12) | (rs << 8) | rd); +} + +void asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm) { + // str rd, [rm] + emit_al(as, 0x5800000 | (rm << 16) | (rd << 12)); +} + +void asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm) { + // strh rd, [rm] + emit_al(as, 0x1c000b0 | (rm << 16) | (rd << 12)); +} + +void asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm) { + // strb rd, [rm] + emit_al(as, 0x5c00000 | (rm << 16) | (rd << 12)); +} + +void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { + // str rd, [rm, rn, lsl #2] + emit_al(as, 0x7800100 | (rm << 16) | (rd << 12) | rn); +} + +void asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { + // strh doesn't support scaled register index + emit_al(as, 0x1a00080 | (ASM_ARM_REG_R8 << 12) | rn); // mov r8, rn, lsl #1 + emit_al(as, 0x18000b0 | (rm << 16) | (rd << 12) | ASM_ARM_REG_R8); // strh rd, [rm, r8] +} + +void asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { + // strb rd, [rm, rn] + emit_al(as, 0x7c00000 | (rm << 16) | (rd << 12) | rn); +} + void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label) { assert(label < as->max_num_labels); mp_uint_t dest = as->label_offsets[label]; diff --git a/py/asmarm.h b/py/asmarm.h index d977102ba8..3829938ae7 100644 --- a/py/asmarm.h +++ b/py/asmarm.h @@ -81,18 +81,35 @@ void asm_arm_align(asm_arm_t* as, uint align); void asm_arm_data(asm_arm_t* as, uint bytesize, uint val); void asm_arm_bkpt(asm_arm_t *as); + +// mov void asm_arm_mov_reg_reg(asm_arm_t *as, uint reg_dest, uint reg_src); void asm_arm_mov_reg_i32(asm_arm_t *as, uint rd, int imm); void asm_arm_mov_local_reg(asm_arm_t *as, int local_num, uint rd); void asm_arm_mov_reg_local(asm_arm_t *as, uint rd, int local_num); +void asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond); +// compare void asm_arm_cmp_reg_i8(asm_arm_t *as, uint rd, int imm); void asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn); -void asm_arm_less_op(asm_arm_t *as, uint rd, uint rn, uint rm); + +// arithmetic void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num); +void asm_arm_lsl_reg_reg(asm_arm_t *as, uint rd, uint rs); +void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs); +// memory +void asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm); +void asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm); +void asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm); +// store to array +void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); +void asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); +void asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); + +// control flow void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label); void asm_arm_b_label(asm_arm_t *as, uint label); void asm_arm_bl_ind(asm_arm_t *as, void *fun_ptr, uint fun_id, uint reg_temp); diff --git a/py/emitnative.c b/py/emitnative.c index 5d3e0f222e..f435117c41 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -420,16 +420,14 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { #define ASM_MOV_REG_REG(as, reg_dest, reg_src) asm_arm_mov_reg_reg((as), (reg_dest), (reg_src)) #define ASM_MOV_LOCAL_ADDR_TO_REG(as, local_num, reg) asm_arm_mov_reg_local_addr(as, (reg), (local_num)) -// TODO someone please implement lsl and asr -#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_((as), (reg_dest), (reg_shift)) -#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_((as), (reg_dest), (reg_shift)) +#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_reg_reg((as), (reg_dest), (reg_shift)) +#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_reg_reg((as), (reg_dest), (reg_shift)) #define ASM_ADD_REG_REG(as, reg_dest, reg_src) asm_arm_add_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_arm_sub_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) -// TODO someone please implement str -#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_arm_str_reg_reg_i5((as), (reg_src), (reg_base), 0) -#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_arm_strb_reg_reg_i5((as), (reg_src), (reg_base), 0) -#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_arm_strh_reg_reg_i5((as), (reg_src), (reg_base), 0) +#define ASM_STORE_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base)) +#define ASM_STORE8_REG_REG(as, reg_value, reg_base) asm_arm_strb_reg_reg((as), (reg_value), (reg_base)) +#define ASM_STORE16_REG_REG(as, reg_value, reg_base) asm_arm_strh_reg_reg((as), (reg_value), (reg_base)) #else @@ -1424,6 +1422,10 @@ STATIC void emit_native_store_subscr(emit_t *emit) { } #endif ASM_MOV_IMM_TO_REG(emit->as, index_value, reg_index); + #if N_ARM + asm_arm_strb_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); + return; + #endif ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base reg_base = reg_index; } @@ -1441,6 +1443,10 @@ STATIC void emit_native_store_subscr(emit_t *emit) { } #endif ASM_MOV_IMM_TO_REG(emit->as, index_value << 1, reg_index); + #if N_ARM + asm_arm_strh_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); + return; + #endif ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base reg_base = reg_index; } @@ -1468,6 +1474,10 @@ STATIC void emit_native_store_subscr(emit_t *emit) { // pointer to 8-bit memory // TODO optimise to use thumb strb r1, [r2, r3] assert(vtype_index == VTYPE_INT); + #if N_ARM + asm_arm_strb_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); + break; + #endif ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE8_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+index) break; @@ -1475,6 +1485,10 @@ STATIC void emit_native_store_subscr(emit_t *emit) { case VTYPE_PTR16: { // pointer to 16-bit memory assert(vtype_index == VTYPE_INT); + #if N_ARM + asm_arm_strh_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); + break; + #endif ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE16_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+2*index) @@ -1808,9 +1822,16 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { asm_thumb_mov_rlo_i8(emit->as, REG_RET, ret[op - MP_BINARY_OP_LESS]); asm_thumb_mov_rlo_i8(emit->as, REG_RET, ret[op - MP_BINARY_OP_LESS] ^ 1); #elif N_ARM - #error generic comparisons for ARM needs implementing - //asm_arm_less_op(emit->as, REG_RET, REG_ARG_2, reg_rhs); - //asm_arm_more_op(emit->as, REG_RET, REG_ARG_2, reg_rhs); + asm_arm_cmp_reg_reg(emit->as, REG_ARG_2, reg_rhs); + static uint ccs[6] = { + ASM_ARM_CC_LT, + ASM_ARM_CC_GT, + ASM_ARM_CC_EQ, + ASM_ARM_CC_LE, + ASM_ARM_CC_GE, + ASM_ARM_CC_NE, + }; + asm_arm_setcc_reg(emit->as, REG_RET, ccs[op - MP_BINARY_OP_LESS]); #else #error not implemented #endif