@@ -238,6 +238,8 @@ typedef enum { ADD, SUB, MUL, DIV_S, REM_S, DIV_U, REM_U, MIN, MAX } ALU_OP;
238238typedef enum { OR, XOR, AND } BIT_OP;
239239/* Shift opcode */
240240typedef enum { SHL, SHRS, SHRU, ROTL, ROTR } SHIFT_OP;
241+ /* Bitcount opcode */
242+ typedef enum { CLZ, CTZ, POPCNT } BITCOUNT_OP;
241243/* Condition opcode */
242244typedef enum { EQ, NE, GTS, GES, LTS, LES, GTU, GEU, LTU, LEU } COND_OP;
243245
@@ -2339,17 +2341,33 @@ alu_r_r_imm_i64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
23392341 a.inc (regs_i64[reg_no_dst]);
23402342 else if (data == -1 )
23412343 a.dec (regs_i64[reg_no_dst]);
2342- else if (data != 0 )
2343- a.add (regs_i64[reg_no_dst], imm);
2344+ else if (data != 0 ) {
2345+ if (data >= INT32_MIN && data <= INT32_MAX) {
2346+ imm.setValue ((int32)data);
2347+ a.add (regs_i64[reg_no_dst], imm);
2348+ }
2349+ else {
2350+ a.mov (regs_i64[REG_I64_FREE_IDX], imm);
2351+ a.add (regs_i64[reg_no_dst], regs_i64[REG_I64_FREE_IDX]);
2352+ }
2353+ }
23442354 break ;
23452355 case SUB:
23462356 mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
23472357 if (data == -1 )
23482358 a.inc (regs_i64[reg_no_dst]);
23492359 else if (data == 1 )
23502360 a.dec (regs_i64[reg_no_dst]);
2351- else if (data != 0 )
2352- a.sub (regs_i64[reg_no_dst], imm);
2361+ else if (data != 0 ) {
2362+ if (data >= INT32_MIN && data <= INT32_MAX) {
2363+ imm.setValue ((int32)data);
2364+ a.sub (regs_i64[reg_no_dst], imm);
2365+ }
2366+ else {
2367+ a.mov (regs_i64[REG_I64_FREE_IDX], imm);
2368+ a.sub (regs_i64[reg_no_dst], regs_i64[REG_I64_FREE_IDX]);
2369+ }
2370+ }
23532371 break ;
23542372 case MUL:
23552373 if (data == 0 )
@@ -3696,44 +3714,6 @@ shift_r_r_to_r_i64(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
36963714 return false ;
36973715}
36983716
3699- /* *
3700- * Encode int32 cmp operation of reg and data, and save result to reg
3701- *
3702- * @param a the assembler to emit the code
3703- * @param op the opcode of cmp operation
3704- * @param reg_no_dst the no of dst register
3705- * @param reg_no_src the no of src register, as first operand
3706- * @param data the immediate data, as the second operand
3707- *
3708- * @return true if success, false otherwise
3709- */
3710- static bool
3711- cmp_r_imm_i32 (x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src, int32 data)
3712- {
3713- Imm imm (data);
3714- a.cmp (regs_i32[reg_no_src], imm);
3715- return true ;
3716- }
3717-
3718- /* *
3719- * Encode int32 cmp operation of reg and reg, and save result to reg
3720- *
3721- * @param a the assembler to emit the code
3722- * @param op the opcode of cmp operation
3723- * @param reg_no_dst the no of dst register
3724- * @param reg_no1_src the no of src register, as first operand
3725- * @param reg_no2_src the no of src register, as second operand
3726- *
3727- * @return true if success, false otherwise
3728- */
3729- static bool
3730- cmp_r_r_i32 (x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
3731- int32 reg_no2_src)
3732- {
3733- a.cmp (regs_i32[reg_no1_src], regs_i32[reg_no2_src]);
3734- return true ;
3735- }
3736-
37373717/* *
37383718 * Encode int32 cmp operation of imm and imm, and save result to reg
37393719 *
@@ -3816,44 +3796,6 @@ cmp_r_r_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
38163796 return true ;
38173797}
38183798
3819- /* *
3820- * Encode int64 cmp operation of reg and data, and save result to reg
3821- *
3822- * @param a the assembler to emit the code
3823- * @param op the opcode of cmp operation
3824- * @param reg_no_dst the no of dst register
3825- * @param reg_no_src the no of src register, as first operand
3826- * @param data the immediate data, as the second operand
3827- *
3828- * @return true if success, false otherwise
3829- */
3830- static bool
3831- cmp_r_imm_i64 (x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src, int64 data)
3832- {
3833- Imm imm (data);
3834- a.cmp (regs_i64[reg_no_src], imm);
3835- return true ;
3836- }
3837-
3838- /* *
3839- * Encode int64 cmp operation of reg and reg, and save result to reg
3840- *
3841- * @param a the assembler to emit the code
3842- * @param op the opcode of cmp operation
3843- * @param reg_no_dst the no of dst register
3844- * @param reg_no1_src the no of src register, as first operand
3845- * @param reg_no2_src the no of src register, as second operand
3846- *
3847- * @return true if success, false otherwise
3848- */
3849- static bool
3850- cmp_r_r_i64 (x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
3851- int32 reg_no2_src)
3852- {
3853- a.cmp (regs_i64[reg_no1_src], regs_i64[reg_no2_src]);
3854- return true ;
3855- }
3856-
38573799/* *
38583800 * Encode int64 cmp operation of imm and imm, and save result to reg
38593801 *
@@ -3913,7 +3855,15 @@ cmp_r_imm_to_r_i64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no1_src,
39133855 int64 data2_src)
39143856{
39153857 Imm imm (data2_src);
3916- a.cmp (regs_i64[reg_no1_src], imm);
3858+
3859+ if (data2_src >= INT32_MIN && data2_src <= INT32_MAX) {
3860+ imm.setValue ((int32)data2_src);
3861+ a.cmp (regs_i64[reg_no1_src], imm);
3862+ }
3863+ else {
3864+ a.mov (regs_i64[REG_I64_FREE_IDX], imm);
3865+ a.cmp (regs_i64[reg_no1_src], regs_i64[REG_I64_FREE_IDX]);
3866+ }
39173867 return true ;
39183868}
39193869
@@ -4621,6 +4571,120 @@ lower_shift(JitCompContext *cc, x86::Assembler &a, SHIFT_OP op, JitReg r0,
46214571 return false ;
46224572}
46234573
4574+ /* *
4575+ * Encode int32 bitcount operation of reg, and save result to reg
4576+ *
4577+ * @param a the assembler to emit the code
4578+ * @param op the opcode of BITCOUNT operation
4579+ * @param reg_no_dst the no of register
4580+ * @param reg_no_src the reg no of first src register data
4581+ *
4582+ * @return true if success, false otherwise
4583+ */
4584+ static bool
4585+ bitcount_r_to_r_i32 (x86::Assembler &a, BITCOUNT_OP op, int32 reg_no_dst,
4586+ int32 reg_no_src)
4587+ {
4588+ switch (op) {
4589+ case CLZ:
4590+ a.lzcnt (regs_i32[reg_no_dst], regs_i32[reg_no_src]);
4591+ break ;
4592+ case CTZ:
4593+ a.tzcnt (regs_i32[reg_no_dst], regs_i32[reg_no_src]);
4594+ break ;
4595+ case POPCNT:
4596+ a.popcnt (regs_i32[reg_no_dst], regs_i32[reg_no_src]);
4597+ break ;
4598+ default :
4599+ bh_assert (0 );
4600+ return false ;
4601+ }
4602+ return true ;
4603+ }
4604+
4605+ /* *
4606+ * Encode int64 bitcount operation of reg, and save result to reg
4607+ *
4608+ * @param a the assembler to emit the code
4609+ * @param op the opcode of BITCOUNT operation
4610+ * @param reg_no_dst the no of register
4611+ * @param reg_no_src the reg no of first src register data
4612+ *
4613+ * @return true if success, false otherwise
4614+ */
4615+ static bool
4616+ bitcount_r_to_r_i64 (x86::Assembler &a, BITCOUNT_OP op, int32 reg_no_dst,
4617+ int32 reg_no_src)
4618+ {
4619+ switch (op) {
4620+ case CLZ:
4621+ a.lzcnt (regs_i64[reg_no_dst], regs_i64[reg_no_src]);
4622+ break ;
4623+ case CTZ:
4624+ a.tzcnt (regs_i64[reg_no_dst], regs_i64[reg_no_src]);
4625+ break ;
4626+ case POPCNT:
4627+ a.popcnt (regs_i64[reg_no_dst], regs_i64[reg_no_src]);
4628+ break ;
4629+ default :
4630+ bh_assert (0 );
4631+ return false ;
4632+ }
4633+ return true ;
4634+ }
4635+
4636+ /* *
4637+ * Encode insn bitcount: CLZ/CTZ/POPCNT r0, r1
4638+ * @param kind the data kind, such as I32, I64
4639+ * @param Type the data type, such as int32, int64
4640+ * @param type the abbreviation of data type, such as i32, i64
4641+ * @param op the opcode of bit operation
4642+ */
4643+ #define BITCOUNT_R_R (kind, Type, type, op ) \
4644+ do { \
4645+ int32 reg_no_dst; \
4646+ bool _ret = false ; \
4647+ \
4648+ CHECK_EQKIND (r0, r1); \
4649+ CHECK_NCONST (r1); \
4650+ \
4651+ reg_no_dst = jit_reg_no (r0); \
4652+ if (!bitcount_r_to_r_##type (a, op, reg_no_dst, jit_reg_no (r1))) \
4653+ GOTO_FAIL; \
4654+ } while (0 )
4655+
4656+ /* *
4657+ * Encode bitcount insn, CLZ/CTZ/POPCNT r0, r1
4658+ *
4659+ * @param cc the compiler context
4660+ * @param a the assembler to emit the code
4661+ * @param op the opcode of bitcount operations
4662+ * @param r0 dst jit register that contains the dst operand info
4663+ * @param r1 src jit register that contains the src operand info
4664+ *
4665+ * @return true if success, false if failed
4666+ */
4667+ static bool
4668+ lower_bitcount (JitCompContext *cc, x86::Assembler &a, BITCOUNT_OP op, JitReg r0,
4669+ JitReg r1)
4670+ {
4671+ switch (jit_reg_kind (r0)) {
4672+ case JIT_REG_KIND_I32:
4673+ BITCOUNT_R_R (I32, int32, i32 , op);
4674+ break ;
4675+ case JIT_REG_KIND_I64:
4676+ BITCOUNT_R_R (I64, int64, i64 , op);
4677+ break ;
4678+ default :
4679+ LOG_VERBOSE (" Invalid reg type of bit: %d\n " , jit_reg_kind (r0));
4680+ GOTO_FAIL;
4681+ }
4682+
4683+ return true ;
4684+ fail:
4685+ return false ;
4686+ }
4687+
46244688/* *
46254689 * Encode insn cmp: CMP r0, r1, r2
46264690 * @param kind the data kind, such as I32, I64, F32 and F64
@@ -5151,6 +5215,8 @@ lower_callnative(JitCompContext *cc, x86::Assembler &a, bh_list *jmp_info_list,
51515215 if (ret_reg) {
51525216 bh_assert ((jit_reg_kind (ret_reg) == JIT_REG_KIND_I32
51535217 && jit_reg_no (ret_reg) == REG_EAX_IDX)
5218+ || (jit_reg_kind (ret_reg) == JIT_REG_KIND_I64
5219+ && jit_reg_no (ret_reg) == REG_RAX_IDX)
51545220 || (jit_reg_kind (ret_reg) == JIT_REG_KIND_F32
51555221 || jit_reg_kind (ret_reg) == JIT_REG_KIND_F64
51565222 && jit_reg_no (ret_reg) == 0 ));
@@ -5705,6 +5771,17 @@ jit_codegen_gen_native(JitCompContext *cc)
57055771 GOTO_FAIL;
57065772 break ;
57075773
5774+ case JIT_OP_CLZ:
5775+ case JIT_OP_CTZ:
5776+ case JIT_OP_POPCNT:
5777+ LOAD_2ARGS ();
5778+ if (!lower_bitcount (
5779+ cc, a,
5780+ (BITCOUNT_OP)(CLZ + (insn->opcode - JIT_OP_CLZ)),
5781+ r0, r1))
5782+ GOTO_FAIL;
5783+ break ;
5784+
57085785 case JIT_OP_CMP:
57095786 LOAD_3ARGS ();
57105787 if (!lower_cmp (cc, a, r0, r1, r2))
0 commit comments