summaryrefslogtreecommitdiff
path: root/py/asmarm.c
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2024-03-18 12:29:11 +1100
committerDamien George <damien@micropython.org>2024-03-19 10:31:36 +1100
commitf52b0d0ff1788225fd61a748e0786aa90e953481 (patch)
tree61f99662e12760408831b85444477fe46212bbb9 /py/asmarm.c
parentd92dff881ca99281893b1d77eee4bf2eca25d0c8 (diff)
py/asm: Add ASM_NOT_REG and ASM_NEG_REG macros for unary ops.
ASM_NOT_REG is optional, it can be synthesised by xor(reg, -1). ASM_NEG_REG can also be synthesised with a subtraction, but most architectures have a dedicated instruction for it. Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'py/asmarm.c')
-rw-r--r--py/asmarm.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/py/asmarm.c b/py/asmarm.c
index cd346949e..600649070 100644
--- a/py/asmarm.c
+++ b/py/asmarm.c
@@ -77,6 +77,11 @@ static uint asm_arm_op_mvn_imm(uint rd, uint imm) {
return 0x3e00000 | (rd << 12) | imm;
}
+static uint asm_arm_op_mvn_reg(uint rd, uint rm) {
+ // mvn rd, rm
+ return 0x1e00000 | (rd << 12) | rm;
+}
+
static uint asm_arm_op_add_imm(uint rd, uint rn, uint imm) {
// add rd, rn, #imm
return 0x2800000 | (rn << 16) | (rd << 12) | (imm & 0xFF);
@@ -97,6 +102,11 @@ static uint asm_arm_op_sub_reg(uint rd, uint rn, uint rm) {
return 0x0400000 | (rn << 16) | (rd << 12) | rm;
}
+static uint asm_arm_op_rsb_imm(uint rd, uint rn, uint imm) {
+ // rsb rd, rn, #imm
+ return 0x2600000 | (rn << 16) | (rd << 12) | (imm & 0xFF);
+}
+
static uint asm_arm_op_mul_reg(uint rd, uint rm, uint rs) {
// mul rd, rm, rs
assert(rd != rm);
@@ -228,11 +238,23 @@ void asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond) {
emit(as, asm_arm_op_mov_imm(rd, 0) | (cond ^ (1 << 28))); // mov!COND rd, #0
}
+void asm_arm_mvn_reg_reg(asm_arm_t *as, uint rd, uint rm) {
+ // mvn rd, rm
+ // computes: rd := ~rm
+ emit_al(as, asm_arm_op_mvn_reg(rd, rm));
+}
+
void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
// add rd, rn, rm
emit_al(as, asm_arm_op_add_reg(rd, rn, rm));
}
+void asm_arm_rsb_reg_reg_imm(asm_arm_t *as, uint rd, uint rn, uint imm) {
+ // rsb rd, rn, #imm
+ // computes: rd := #imm - rn
+ emit_al(as, asm_arm_op_rsb_imm(rd, rn, imm));
+}
+
void asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
// sub rd, rn, rm
emit_al(as, asm_arm_op_sub_reg(rd, rn, rm));