Skip to content

Commit 94ae023

Browse files
committed
py/asmthumb: Add asm_thumb_ldrh_reg_reg_i12_optimised() helper func.
Signed-off-by: Damien George <[email protected]>
1 parent 689138d commit 94ae023

File tree

2 files changed

+53
-28
lines changed

2 files changed

+53
-28
lines changed

py/asmthumb.c

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555

5656
#define OP_LDR_W_HI(reg_base) (0xf8d0 | (reg_base))
5757
#define OP_LDR_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12))
58+
59+
#define OP_LDRH_W_HI(reg_base) (0xf8b0 | (reg_base))
60+
#define OP_LDRH_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12))
5861
#endif
5962

6063
static inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) {
@@ -449,46 +452,67 @@ static inline void asm_thumb_ldr_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uin
449452
}
450453
#endif
451454

455+
#if !MICROPY_EMIT_THUMB_ARMV7M
456+
// emits code for: reg_dest = reg_base + offset << offset_shift
457+
static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint offset_shift) {
458+
if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8) {
459+
if (offset << offset_shift < 256) {
460+
if (reg_dest != reg_base) {
461+
asm_thumb_mov_reg_reg(as, reg_dest, reg_base);
462+
}
463+
asm_thumb_add_rlo_i8(as, reg_dest, offset << offset_shift);
464+
} else if (UNSIGNED_FIT8(offset) && reg_dest != reg_base) {
465+
asm_thumb_mov_rlo_i8(as, reg_dest, offset);
466+
asm_thumb_lsl_rlo_rlo_i5(as, reg_dest, reg_dest, offset_shift);
467+
asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base);
468+
} else if (reg_dest != reg_base) {
469+
asm_thumb_mov_rlo_i16(as, reg_dest, offset << offset_shift);
470+
asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_dest);
471+
} else {
472+
uint reg_other = reg_dest ^ 7;
473+
asm_thumb_op16(as, OP_PUSH_RLIST((1 << reg_other)));
474+
asm_thumb_mov_rlo_i16(as, reg_other, offset << offset_shift);
475+
asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_other);
476+
asm_thumb_op16(as, OP_POP_RLIST((1 << reg_other)));
477+
}
478+
} else {
479+
assert(0); // should never be called for ARMV6M
480+
}
481+
}
482+
#endif
483+
452484
void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) {
453485
if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(word_offset)) {
454486
asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_base, word_offset);
455487
} else {
456488
#if MICROPY_EMIT_THUMB_ARMV7M
457489
asm_thumb_ldr_reg_reg_i12(as, reg_dest, reg_base, word_offset);
458490
#else
459-
word_offset -= 31;
460-
if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8) {
461-
if (UNSIGNED_FIT8(word_offset) && (word_offset < 64 || reg_dest != reg_base)) {
462-
if (word_offset < 64) {
463-
if (reg_dest != reg_base) {
464-
asm_thumb_mov_reg_reg(as, reg_dest, reg_base);
465-
}
466-
asm_thumb_add_rlo_i8(as, reg_dest, word_offset * 4);
467-
} else {
468-
asm_thumb_mov_rlo_i8(as, reg_dest, word_offset);
469-
asm_thumb_lsl_rlo_rlo_i5(as, reg_dest, reg_dest, 2);
470-
asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base);
471-
}
472-
} else {
473-
if (reg_dest != reg_base) {
474-
asm_thumb_mov_rlo_i16(as, reg_dest, word_offset * 4);
475-
asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_dest);
476-
} else {
477-
uint reg_other = reg_dest ^ 7;
478-
asm_thumb_op16(as, OP_PUSH_RLIST((1 << reg_other)));
479-
asm_thumb_mov_rlo_i16(as, reg_other, word_offset * 4);
480-
asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_other);
481-
asm_thumb_op16(as, OP_POP_RLIST((1 << reg_other)));
482-
}
483-
}
484-
} else {
485-
assert(0); // should never be called for ARMV6M
486-
}
491+
asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, word_offset - 31, 2);
487492
asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_dest, 31);
488493
#endif
489494
}
490495
}
491496

497+
#if MICROPY_EMIT_THUMB_ARMV7M
498+
static inline void asm_thumb_ldrh_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) {
499+
asm_thumb_op32(as, OP_LDRH_W_HI(reg_base), OP_LDRH_W_LO(reg_dest, uint16_offset * 2));
500+
}
501+
#endif
502+
503+
void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) {
504+
if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(uint16_offset)) {
505+
asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_base, uint16_offset);
506+
} else {
507+
#if MICROPY_EMIT_THUMB_ARMV7M
508+
asm_thumb_ldrh_reg_reg_i12(as, reg_dest, reg_base, uint16_offset);
509+
#else
510+
asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, uint16_offset - 31, 1);
511+
asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_dest, 31);
512+
#endif
513+
}
514+
}
515+
492516
// this could be wrong, because it should have a range of +/- 16MiB...
493517
#define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))
494518
#define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))

py/asmthumb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num)
328328
void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label);
329329

330330
void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset); // convenience
331+
void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset); // convenience
331332

332333
void asm_thumb_b_label(asm_thumb_t *as, uint label); // convenience: picks narrow or wide branch
333334
void asm_thumb_bcc_label(asm_thumb_t *as, int cc, uint label); // convenience: picks narrow or wide branch

0 commit comments

Comments
 (0)