aboutsummaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-05-20 14:30:09 +1000
committerDamien George <damien@micropython.org>2022-05-23 14:21:14 +1000
commit94ae0231367fe9a63aed10564084ac7d84089216 (patch)
treeb4476edd881494d74d26698b9786304f67559fe8 /py
parent689138d484dce1e41720c73b1bba3f2758a39c57 (diff)
py/asmthumb: Add asm_thumb_ldrh_reg_reg_i12_optimised() helper func.
Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'py')
-rw-r--r--py/asmthumb.c80
-rw-r--r--py/asmthumb.h1
2 files changed, 53 insertions, 28 deletions
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 04fb82330..5257884b5 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -55,6 +55,9 @@
#define OP_LDR_W_HI(reg_base) (0xf8d0 | (reg_base))
#define OP_LDR_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12))
+
+#define OP_LDRH_W_HI(reg_base) (0xf8b0 | (reg_base))
+#define OP_LDRH_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12))
#endif
static inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) {
@@ -449,6 +452,35 @@ static inline void asm_thumb_ldr_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uin
}
#endif
+#if !MICROPY_EMIT_THUMB_ARMV7M
+// emits code for: reg_dest = reg_base + offset << offset_shift
+static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint offset_shift) {
+ if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8) {
+ if (offset << offset_shift < 256) {
+ if (reg_dest != reg_base) {
+ asm_thumb_mov_reg_reg(as, reg_dest, reg_base);
+ }
+ asm_thumb_add_rlo_i8(as, reg_dest, offset << offset_shift);
+ } else if (UNSIGNED_FIT8(offset) && reg_dest != reg_base) {
+ asm_thumb_mov_rlo_i8(as, reg_dest, offset);
+ asm_thumb_lsl_rlo_rlo_i5(as, reg_dest, reg_dest, offset_shift);
+ asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base);
+ } else if (reg_dest != reg_base) {
+ asm_thumb_mov_rlo_i16(as, reg_dest, offset << offset_shift);
+ asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_dest);
+ } else {
+ uint reg_other = reg_dest ^ 7;
+ asm_thumb_op16(as, OP_PUSH_RLIST((1 << reg_other)));
+ asm_thumb_mov_rlo_i16(as, reg_other, offset << offset_shift);
+ asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_other);
+ asm_thumb_op16(as, OP_POP_RLIST((1 << reg_other)));
+ }
+ } else {
+ assert(0); // should never be called for ARMV6M
+ }
+}
+#endif
+
void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) {
if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(word_offset)) {
asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_base, word_offset);
@@ -456,39 +488,31 @@ void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint re
#if MICROPY_EMIT_THUMB_ARMV7M
asm_thumb_ldr_reg_reg_i12(as, reg_dest, reg_base, word_offset);
#else
- word_offset -= 31;
- if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8) {
- if (UNSIGNED_FIT8(word_offset) && (word_offset < 64 || reg_dest != reg_base)) {
- if (word_offset < 64) {
- if (reg_dest != reg_base) {
- asm_thumb_mov_reg_reg(as, reg_dest, reg_base);
- }
- asm_thumb_add_rlo_i8(as, reg_dest, word_offset * 4);
- } else {
- asm_thumb_mov_rlo_i8(as, reg_dest, word_offset);
- asm_thumb_lsl_rlo_rlo_i5(as, reg_dest, reg_dest, 2);
- asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base);
- }
- } else {
- if (reg_dest != reg_base) {
- asm_thumb_mov_rlo_i16(as, reg_dest, word_offset * 4);
- asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_dest);
- } else {
- uint reg_other = reg_dest ^ 7;
- asm_thumb_op16(as, OP_PUSH_RLIST((1 << reg_other)));
- asm_thumb_mov_rlo_i16(as, reg_other, word_offset * 4);
- asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_other);
- asm_thumb_op16(as, OP_POP_RLIST((1 << reg_other)));
- }
- }
- } else {
- assert(0); // should never be called for ARMV6M
- }
+ asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, word_offset - 31, 2);
asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_dest, 31);
#endif
}
}
+#if MICROPY_EMIT_THUMB_ARMV7M
+static inline void asm_thumb_ldrh_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) {
+ asm_thumb_op32(as, OP_LDRH_W_HI(reg_base), OP_LDRH_W_LO(reg_dest, uint16_offset * 2));
+}
+#endif
+
+void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) {
+ if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(uint16_offset)) {
+ asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_base, uint16_offset);
+ } else {
+ #if MICROPY_EMIT_THUMB_ARMV7M
+ asm_thumb_ldrh_reg_reg_i12(as, reg_dest, reg_base, uint16_offset);
+ #else
+ asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, uint16_offset - 31, 1);
+ asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_dest, 31);
+ #endif
+ }
+}
+
// this could be wrong, because it should have a range of +/- 16MiB...
#define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))
#define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))
diff --git a/py/asmthumb.h b/py/asmthumb.h
index 6648a80fb..3ef0eb443 100644
--- a/py/asmthumb.h
+++ b/py/asmthumb.h
@@ -328,6 +328,7 @@ void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num)
void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label);
void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset); // convenience
+void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset); // convenience
void asm_thumb_b_label(asm_thumb_t *as, uint label); // convenience: picks narrow or wide branch
void asm_thumb_bcc_label(asm_thumb_t *as, int cc, uint label); // convenience: picks narrow or wide branch