summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Gatti <a.gatti@frob.it>2025-06-26 20:25:09 +0200
committerDamien George <damien@micropython.org>2025-07-01 15:43:17 +1000
commit1b0cdc0794825fe147fc3bc8a717e83246640d2d (patch)
treee315f08efd0dadbd8d0a4a2ea0287e6fafde695a
parent6fd7422a8e5b6c8952f7b67713f0551992d247cc (diff)
py/asmthumb: Clean up integer-indexed load/store emitters.
This commit cleans up the single entry point integer-indexed load/store emitters that have been built by merging the single operand type load/store functions in 1f5ba6998bb1895354f5afcd7bb52d83a02733be. To follow the same convention found in RV32 and Xtensa emitters, the function operand size is not named after the left shift amount to apply to the initial offset to get its true byte offset, but by a generic "operand size". Also, those functions were updated to use the new MP_FIT_UNSIGNED macros to perform bit width checks when figuring out which opcode encoding is the best one to use. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
-rw-r--r--py/asmthumb.c36
-rw-r--r--py/asmthumb.h4
2 files changed, 21 insertions, 19 deletions
diff --git a/py/asmthumb.c b/py/asmthumb.c
index fda0f5270..18c3db9e4 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -37,10 +37,8 @@
#include "py/asmthumb.h"
#include "py/misc.h"
-#define UNSIGNED_FIT5(x) ((uint32_t)(x) < 32)
#define UNSIGNED_FIT7(x) ((uint32_t)(x) < 128)
#define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0)
-#define UNSIGNED_FIT12(x) (((x) & 0xfffff000) == 0)
#define UNSIGNED_FIT16(x) (((x) & 0xffff0000) == 0)
#define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)
#define SIGNED_FIT9(x) (((x) & 0xffffff00) == 0) || (((x) & 0xffffff00) == 0xffffff00)
@@ -454,7 +452,7 @@ static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint re
}
}
-#define OP_LDR_STR_W_HI(shift, reg) ((0xf880 | (shift) << 5) | (reg))
+#define OP_LDR_STR_W_HI(operation_size, reg) ((0xf880 | (operation_size) << 5) | (reg))
#define OP_LDR_STR_W_LO(reg, imm12) (((reg) << 12) | (imm12))
#define OP_LDR 0x01
@@ -467,31 +465,35 @@ static const uint8_t OP_LDR_STR_TABLE[3] = {
0x0E, 0x10, 0x0C
};
-void asm_thumb_load_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint shift) {
- if (UNSIGNED_FIT5(offset) && (reg_dest < ASM_THUMB_REG_R8) && (reg_base < ASM_THUMB_REG_R8)) {
+void asm_thumb_load_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size) {
+ assert(operation_size <= 2 && "Operation size out of range.");
+
+ if (MP_FIT_UNSIGNED(5, offset) && (reg_dest < ASM_THUMB_REG_R8) && (reg_base < ASM_THUMB_REG_R8)) {
// Can use T1 encoding
- asm_thumb_op16(as, ((OP_LDR_STR_TABLE[shift] | OP_LDR) << 11) | (offset << 6) | (reg_base << 3) | reg_dest);
- } else if (asm_thumb_allow_armv7m(as) && UNSIGNED_FIT12(offset << shift)) {
+ asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_LDR) << 11) | (offset << 6) | (reg_base << 3) | reg_dest);
+ } else if (asm_thumb_allow_armv7m(as) && MP_FIT_UNSIGNED(12, offset << operation_size)) {
// Can use T3 encoding
- asm_thumb_op32(as, (OP_LDR_STR_W_HI(shift, reg_base) | OP_LDR_W), OP_LDR_STR_W_LO(reg_dest, (offset << shift)));
+ asm_thumb_op32(as, (OP_LDR_STR_W_HI(operation_size, reg_base) | OP_LDR_W), OP_LDR_STR_W_LO(reg_dest, (offset << operation_size)));
} else {
// Must use the generic sequence
- asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, offset - 31, shift);
- asm_thumb_op16(as, ((OP_LDR_STR_TABLE[shift] | OP_LDR) << 11) | (31 << 6) | (reg_dest << 3) | (reg_dest));
+ asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, offset - 31, operation_size);
+ asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_LDR) << 11) | (31 << 6) | (reg_dest << 3) | (reg_dest));
}
}
-void asm_thumb_store_reg_reg_offset(asm_thumb_t *as, uint reg_src, uint reg_base, uint offset, uint shift) {
- if (UNSIGNED_FIT5(offset) && (reg_src < ASM_THUMB_REG_R8) && (reg_base < ASM_THUMB_REG_R8)) {
+void asm_thumb_store_reg_reg_offset(asm_thumb_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size) {
+ assert(operation_size <= 2 && "Operation size out of range.");
+
+ if (MP_FIT_UNSIGNED(5, offset) && (reg_src < ASM_THUMB_REG_R8) && (reg_base < ASM_THUMB_REG_R8)) {
// Can use T1 encoding
- asm_thumb_op16(as, ((OP_LDR_STR_TABLE[shift] | OP_STR) << 11) | (offset << 6) | (reg_base << 3) | reg_src);
- } else if (asm_thumb_allow_armv7m(as) && UNSIGNED_FIT12(offset << shift)) {
+ asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_STR) << 11) | (offset << 6) | (reg_base << 3) | reg_src);
+ } else if (asm_thumb_allow_armv7m(as) && MP_FIT_UNSIGNED(12, offset << operation_size)) {
// Can use T3 encoding
- asm_thumb_op32(as, (OP_LDR_STR_W_HI(shift, reg_base) | OP_STR_W), OP_LDR_STR_W_LO(reg_src, (offset << shift)));
+ asm_thumb_op32(as, (OP_LDR_STR_W_HI(operation_size, reg_base) | OP_STR_W), OP_LDR_STR_W_LO(reg_src, (offset << operation_size)));
} else {
// Must use the generic sequence
- asm_thumb_add_reg_reg_offset(as, reg_base, reg_base, offset - 31, shift);
- asm_thumb_op16(as, ((OP_LDR_STR_TABLE[shift] | OP_STR) << 11) | (31 << 6) | (reg_base << 3) | reg_src);
+ asm_thumb_add_reg_reg_offset(as, reg_base, reg_base, offset - 31, operation_size);
+ asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_STR) << 11) | (31 << 6) | (reg_base << 3) | reg_src);
}
}
diff --git a/py/asmthumb.h b/py/asmthumb.h
index b423ce7a4..9cd9d32d8 100644
--- a/py/asmthumb.h
+++ b/py/asmthumb.h
@@ -365,9 +365,9 @@ 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);
// Generate optimised load dest, [src, #offset] sequence
-void asm_thumb_load_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint shift);
+void asm_thumb_load_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size);
// Generate optimised store src, [dest, #offset] sequence
-void asm_thumb_store_reg_reg_offset(asm_thumb_t *as, uint reg_src, uint reg_base, uint offset, uint shift);
+void asm_thumb_store_reg_reg_offset(asm_thumb_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size);
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