From 5dc4496b54422853cb785fb2dcb0fbada28627f1 Mon Sep 17 00:00:00 2001 From: Yen-Fu Chen Date: Fri, 7 Jun 2024 23:32:07 +0800 Subject: [PATCH] asd --- src/jit.c | 73 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/src/jit.c b/src/jit.c index bdcdd0f1..adf97843 100644 --- a/src/jit.c +++ b/src/jit.c @@ -762,24 +762,6 @@ static inline void emit_alu64_imm32(struct jit_state *state, emit_alu64(state, op, src, dst); emit4(state, imm); } -#elif defined(__aarch64__) -static void divmod(struct jit_state *state, - uint8_t opcode, - int rd, - int rn, - int rm) -{ - bool mod = (opcode & JIT_ALU_OP_MASK) == (JIT_OP_MOD_IMM & JIT_ALU_OP_MASK); - bool is64 = (opcode & JIT_CLS_MASK) == JIT_CLS_ALU64; - int div_dest = mod ? temp_div_reg : rd; - - /* Do not need to treet divide by zero as special because the UDIV - * instruction already returns 0 when dividing by zero. - */ - emit_dataproc_2source(state, is64, DP2_UDIV, div_dest, rn, rm); - if (mod) - emit_dataproc_3source(state, is64, DP3_MSUB, rd, rm, div_dest, rn); -} #endif static inline void emit_cmp_imm32(struct jit_state *state, int dst, int32_t imm) @@ -1035,8 +1017,57 @@ static inline void emit_exit(struct jit_state *state) #endif } -/* TODO: muldivmod is incomplete, it does not handle imm or overflow now */ #if RV32_HAS(EXT_M) +#if defined(__aarch64__) +static void emit_conditional_move(struct jit_state *state, + int rd, + int rn, + int rm, + int cond) +{ + emit_a64(state, 0x1a800000 | (rm << 16) | (cond << 12) | (rn << 5) | rd); + set_dirty(rd, true); +} + +static void divmod(struct jit_state *state, + uint8_t opcode, + int rd, + int rn, + int rm, + bool sign) +{ + bool mod = (opcode & JIT_ALU_OP_MASK) == (JIT_OP_MOD_IMM & JIT_ALU_OP_MASK); + bool is64 = (opcode & JIT_CLS_MASK) == JIT_CLS_ALU64; + int div_dest = mod ? temp_div_reg : rd; + + if (sign) + emit_cmp_imm32(state, rd, 0x80000000); /* overflow checking */ + + emit_dataproc_2source(state, is64, DP2_UDIV, div_dest, rn, rm); + if (mod) + emit_dataproc_3source(state, is64, DP3_MSUB, rd, rm, div_dest, rn); + + if (sign) { + /* handle overflow */ + uint32_t jump_loc = state->offset; + emit_jcc_offset(state, 0x85); + emit_cmp_imm32(state, rm, -1); + if (mod) + emit_load_imm(state, R10, 0); + else + emit_load_imm(state, R10, 0x80000000); + emit_conditional_move(state, rd, R10, rd, COND_EQ); + emit_jump_target_offset(state, JUMP_LOC, state->offset); + } + if (!mod) { + /* handle dividing zero */ + emit_cmp_imm32(state, rm, 0); + emit_load_imm(state, temp_reg, -1); + emit_conditional_move(state, rd, temp_reg, rd, COND_EQ); + } +} +#endif + static void muldivmod(struct jit_state *state, uint8_t opcode, int src, @@ -1190,10 +1221,10 @@ static void muldivmod(struct jit_state *state, emit_dataproc_3source(state, true, DP3_MADD, dst, dst, src, RZ); break; case 0x38: - divmod(state, JIT_OP_DIV_REG, dst, dst, src); + divmod(state, JIT_OP_DIV_REG, dst, dst, src, sign); break; case 0x98: - divmod(state, JIT_OP_MOD_REG, dst, dst, src); + divmod(state, JIT_OP_MOD_REG, dst, dst, src, sign); break; default: __UNREACHABLE;