Skip to content

Commit f52b0d0

Browse files
committed
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>
1 parent d92dff8 commit f52b0d0

8 files changed

Lines changed: 61 additions & 0 deletions

File tree

py/asmarm.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ static uint asm_arm_op_mvn_imm(uint rd, uint imm) {
7777
return 0x3e00000 | (rd << 12) | imm;
7878
}
7979

80+
static uint asm_arm_op_mvn_reg(uint rd, uint rm) {
81+
// mvn rd, rm
82+
return 0x1e00000 | (rd << 12) | rm;
83+
}
84+
8085
static uint asm_arm_op_add_imm(uint rd, uint rn, uint imm) {
8186
// add rd, rn, #imm
8287
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) {
97102
return 0x0400000 | (rn << 16) | (rd << 12) | rm;
98103
}
99104

105+
static uint asm_arm_op_rsb_imm(uint rd, uint rn, uint imm) {
106+
// rsb rd, rn, #imm
107+
return 0x2600000 | (rn << 16) | (rd << 12) | (imm & 0xFF);
108+
}
109+
100110
static uint asm_arm_op_mul_reg(uint rd, uint rm, uint rs) {
101111
// mul rd, rm, rs
102112
assert(rd != rm);
@@ -228,11 +238,23 @@ void asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond) {
228238
emit(as, asm_arm_op_mov_imm(rd, 0) | (cond ^ (1 << 28))); // mov!COND rd, #0
229239
}
230240

241+
void asm_arm_mvn_reg_reg(asm_arm_t *as, uint rd, uint rm) {
242+
// mvn rd, rm
243+
// computes: rd := ~rm
244+
emit_al(as, asm_arm_op_mvn_reg(rd, rm));
245+
}
246+
231247
void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
232248
// add rd, rn, rm
233249
emit_al(as, asm_arm_op_add_reg(rd, rn, rm));
234250
}
235251

252+
void asm_arm_rsb_reg_reg_imm(asm_arm_t *as, uint rd, uint rn, uint imm) {
253+
// rsb rd, rn, #imm
254+
// computes: rd := #imm - rn
255+
emit_al(as, asm_arm_op_rsb_imm(rd, rn, imm));
256+
}
257+
236258
void asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) {
237259
// sub rd, rn, rm
238260
emit_al(as, asm_arm_op_sub_reg(rd, rn, rm));

py/asmarm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,10 @@ void asm_arm_cmp_reg_i8(asm_arm_t *as, uint rd, int imm);
9494
void asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn);
9595

9696
// arithmetic
97+
void asm_arm_mvn_reg_reg(asm_arm_t *as, uint rd, uint rm);
9798
void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);
9899
void asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);
100+
void asm_arm_rsb_reg_reg_imm(asm_arm_t *as, uint rd, uint rn, uint imm);
99101
void asm_arm_mul_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);
100102
void asm_arm_and_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);
101103
void asm_arm_eor_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm);
@@ -188,6 +190,8 @@ void asm_arm_bx_reg(asm_arm_t *as, uint reg_src);
188190
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_arm_mov_reg_local_addr((as), (reg_dest), (local_num))
189191
#define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_arm_mov_reg_pcrel((as), (reg_dest), (label))
190192

193+
#define ASM_NOT_REG(as, reg_dest) asm_arm_mvn_reg_reg((as), (reg_dest), (reg_dest))
194+
#define ASM_NEG_REG(as, reg_dest) asm_arm_rsb_reg_reg_imm((as), (reg_dest), (reg_dest), 0)
191195
#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_reg_reg((as), (reg_dest), (reg_shift))
192196
#define ASM_LSR_REG_REG(as, reg_dest, reg_shift) asm_arm_lsr_reg_reg((as), (reg_dest), (reg_shift))
193197
#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_reg_reg((as), (reg_dest), (reg_shift))

py/asmthumb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,8 @@ void asm_thumb_b_rel12(asm_thumb_t *as, int rel);
406406
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_thumb_mov_reg_local_addr((as), (reg_dest), (local_num))
407407
#define ASM_MOV_REG_PCREL(as, rlo_dest, label) asm_thumb_mov_reg_pcrel((as), (rlo_dest), (label))
408408

409+
#define ASM_NOT_REG(as, reg_dest) asm_thumb_mvn_rlo_rlo((as), (reg_dest), (reg_dest))
410+
#define ASM_NEG_REG(as, reg_dest) asm_thumb_neg_rlo_rlo((as), (reg_dest), (reg_dest))
409411
#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSL, (reg_dest), (reg_shift))
410412
#define ASM_LSR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSR, (reg_dest), (reg_shift))
411413
#define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ASR, (reg_dest), (reg_shift))

py/asmx64.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
#define OPCODE_MOVZX_RM8_TO_R64 (0xb6) /* 0x0f 0xb6/r */
5555
#define OPCODE_MOVZX_RM16_TO_R64 (0xb7) /* 0x0f 0xb7/r */
5656
#define OPCODE_LEA_MEM_TO_R64 (0x8d) /* /r */
57+
#define OPCODE_NOT_RM64 (0xf7) /* /2 */
58+
#define OPCODE_NEG_RM64 (0xf7) /* /3 */
5759
#define OPCODE_AND_R64_TO_RM64 (0x21) /* /r */
5860
#define OPCODE_OR_R64_TO_RM64 (0x09) /* /r */
5961
#define OPCODE_XOR_R64_TO_RM64 (0x31) /* /r */
@@ -362,6 +364,14 @@ void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r
362364
}
363365
}
364366

367+
void asm_x64_not_r64(asm_x64_t *as, int dest_r64) {
368+
asm_x64_generic_r64_r64(as, dest_r64, 2, OPCODE_NOT_RM64);
369+
}
370+
371+
void asm_x64_neg_r64(asm_x64_t *as, int dest_r64) {
372+
asm_x64_generic_r64_r64(as, dest_r64, 3, OPCODE_NEG_RM64);
373+
}
374+
365375
void asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) {
366376
asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_AND_R64_TO_RM64);
367377
}

py/asmx64.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ void asm_x64_mov_mem8_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int des
9797
void asm_x64_mov_mem16_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);
9898
void asm_x64_mov_mem32_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);
9999
void asm_x64_mov_mem64_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64);
100+
void asm_x64_not_r64(asm_x64_t *as, int dest_r64);
101+
void asm_x64_neg_r64(asm_x64_t *as, int dest_r64);
100102
void asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);
101103
void asm_x64_or_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);
102104
void asm_x64_xor_r64_r64(asm_x64_t *as, int dest_r64, int src_r64);
@@ -191,6 +193,8 @@ void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r32);
191193
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x64_mov_local_addr_to_r64((as), (local_num), (reg_dest))
192194
#define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_x64_mov_reg_pcrel((as), (reg_dest), (label))
193195

196+
#define ASM_NOT_REG(as, reg) asm_x64_not_r64((as), (reg))
197+
#define ASM_NEG_REG(as, reg) asm_x64_neg_r64((as), (reg))
194198
#define ASM_LSL_REG(as, reg) asm_x64_shl_r64_cl((as), (reg))
195199
#define ASM_LSR_REG(as, reg) asm_x64_shr_r64_cl((as), (reg))
196200
#define ASM_ASR_REG(as, reg) asm_x64_sar_r64_cl((as), (reg))

py/asmx86.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
#define OPCODE_MOVZX_RM8_TO_R32 (0xb6) /* 0x0f 0xb6/r */
5555
#define OPCODE_MOVZX_RM16_TO_R32 (0xb7) /* 0x0f 0xb7/r */
5656
#define OPCODE_LEA_MEM_TO_R32 (0x8d) /* /r */
57+
#define OPCODE_NOT_RM32 (0xf7) /* /2 */
58+
#define OPCODE_NEG_RM32 (0xf7) /* /3 */
5759
#define OPCODE_AND_R32_TO_RM32 (0x21) /* /r */
5860
#define OPCODE_OR_R32_TO_RM32 (0x09) /* /r */
5961
#define OPCODE_XOR_R32_TO_RM32 (0x31) /* /r */
@@ -244,6 +246,14 @@ size_t asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32) {
244246
return loc;
245247
}
246248

249+
void asm_x86_not_r32(asm_x86_t *as, int dest_r32) {
250+
asm_x86_generic_r32_r32(as, dest_r32, 2, OPCODE_NOT_RM32);
251+
}
252+
253+
void asm_x86_neg_r32(asm_x86_t *as, int dest_r32) {
254+
asm_x86_generic_r32_r32(as, dest_r32, 3, OPCODE_NEG_RM32);
255+
}
256+
247257
void asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) {
248258
asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_AND_R32_TO_RM32);
249259
}

py/asmx86.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ void asm_x86_mov_r32_to_mem32(asm_x86_t *as, int src_r32, int dest_r32, int dest
9292
void asm_x86_mov_mem8_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32);
9393
void asm_x86_mov_mem16_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32);
9494
void asm_x86_mov_mem32_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32);
95+
void asm_x86_not_r32(asm_x86_t *as, int dest_r32);
96+
void asm_x86_neg_r32(asm_x86_t *as, int dest_r32);
9597
void asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32);
9698
void asm_x86_or_r32_r32(asm_x86_t *as, int dest_r32, int src_r32);
9799
void asm_x86_xor_r32_r32(asm_x86_t *as, int dest_r32, int src_r32);
@@ -186,6 +188,8 @@ void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r
186188
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x86_mov_local_addr_to_r32((as), (local_num), (reg_dest))
187189
#define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_x86_mov_reg_pcrel((as), (reg_dest), (label))
188190

191+
#define ASM_NOT_REG(as, reg) asm_x86_not_r32((as), (reg))
192+
#define ASM_NEG_REG(as, reg) asm_x86_neg_r32((as), (reg))
189193
#define ASM_LSL_REG(as, reg) asm_x86_shl_r32_cl((as), (reg))
190194
#define ASM_LSR_REG(as, reg) asm_x86_shr_r32_cl((as), (reg))
191195
#define ASM_ASR_REG(as, reg) asm_x86_sar_r32_cl((as), (reg))

py/asmxtensa.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ static inline void asm_xtensa_op_mull(asm_xtensa_t *as, uint reg_dest, uint reg_
211211
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 2, 8, reg_dest, reg_src_a, reg_src_b));
212212
}
213213

214+
static inline void asm_xtensa_op_neg(asm_xtensa_t *as, uint reg_dest, uint reg_src) {
215+
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 6, reg_dest, 0, reg_src));
216+
}
217+
214218
static inline void asm_xtensa_op_or(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) {
215219
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 2, reg_dest, reg_src_a, reg_src_b));
216220
}
@@ -371,6 +375,7 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx);
371375
#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_xtensa_mov_reg_local_addr((as), (reg_dest), ASM_NUM_REGS_SAVED + (local_num))
372376
#define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_xtensa_mov_reg_pcrel((as), (reg_dest), (label))
373377

378+
#define ASM_NEG_REG(as, reg_dest) asm_xtensa_op_neg((as), (reg_dest), (reg_dest))
374379
#define ASM_LSL_REG_REG(as, reg_dest, reg_shift) \
375380
do { \
376381
asm_xtensa_op_ssl((as), (reg_shift)); \

0 commit comments

Comments
 (0)