@@ -246,6 +246,36 @@ typedef enum { CLZ, CTZ, POPCNT } BITCOUNT_OP;
246246/* Condition opcode */
247247typedef enum { EQ, NE, GTS, GES, LTS, LES, GTU, GEU, LTU, LEU } COND_OP;
248248
249+ typedef union _cast_float_to_integer {
250+ float f;
251+ uint32 i;
252+ } cast_float_to_integer;
253+
254+ typedef union _cast_double_to_integer {
255+ double d;
256+ uint64 i;
257+ } cast_double_to_integer;
258+
259+ static uint32
260+ local_log2 (uint32 data)
261+ {
262+ uint32 ret = 0 ;
263+ while (data >>= 1 ) {
264+ ret++;
265+ }
266+ return ret;
267+ }
268+
269+ static uint64
270+ local_log2l (uint64 data)
271+ {
272+ uint64 ret = 0 ;
273+ while (data >>= 1 ) {
274+ ret++;
275+ }
276+ return ret;
277+ }
278+
249279/* Jmp type */
250280typedef enum JmpType {
251281 JMP_DST_LABEL, /* jmp to dst label */
@@ -1157,7 +1187,8 @@ static bool
11571187mov_imm_to_r_f32 (x86::Assembler &a, int32 reg_no, float data)
11581188{
11591189 /* imm -> gp -> xmm */
1160- Imm imm (*(uint32 *)&data);
1190+ cast_float_to_integer v = { .f = data };
1191+ Imm imm (v.i );
11611192 a.mov (regs_i32[REG_I32_FREE_IDX], imm);
11621193 a.movd (regs_float[reg_no], regs_i32[REG_I32_FREE_IDX]);
11631194 return true ;
@@ -1193,7 +1224,8 @@ mov_r_to_r_f32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
11931224static bool
11941225mov_imm_to_r_f64 (x86::Assembler &a, int32 reg_no, double data)
11951226{
1196- Imm imm (*(uint64 *)&data);
1227+ cast_double_to_integer v = { .d = data };
1228+ Imm imm (v.i );
11971229 a.mov (regs_i64[REG_I32_FREE_IDX], imm);
11981230 /* REG_I32_FREE_IDX == REG_I64_FREE_IDX */
11991231 a.movq (regs_float[reg_no], regs_i64[REG_I64_FREE_IDX]);
@@ -2266,19 +2298,10 @@ alu_r_r_imm_i32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
22662298 else if (data == 1 ) {
22672299 mov_r_to_r (a, JIT_REG_KIND_I32, reg_no_dst, reg_no_src);
22682300 }
2269- else if (data == 2 ) {
2301+ else if (data > 0 && (data & (data - 1 )) == 0x0 ) {
22702302 mov_r_to_r (a, JIT_REG_KIND_I32, reg_no_dst, reg_no_src);
2271- imm.setValue (1 );
2272- a.shl (regs_i32[reg_no_dst], imm);
2273- }
2274- else if (data == 4 ) {
2275- mov_r_to_r (a, JIT_REG_KIND_I32, reg_no_dst, reg_no_src);
2276- imm.setValue (2 );
2277- a.shl (regs_i32[reg_no_dst], imm);
2278- }
2279- else if (data == 8 ) {
2280- mov_r_to_r (a, JIT_REG_KIND_I32, reg_no_dst, reg_no_src);
2281- imm.setValue (3 );
2303+ data = (int32)local_log2 (data);
2304+ imm.setValue (data);
22822305 a.shl (regs_i32[reg_no_dst], imm);
22832306 }
22842307 else {
@@ -2539,6 +2562,81 @@ alu_r_r_to_r_i32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
25392562 return alu_r_r_r_i32 (a, op, reg_no_dst, reg_no1_src, reg_no2_src);
25402563}
25412564
2565+ /* *
2566+ * Encode int64 alu operation of reg and reg, and save result to reg
2567+ *
2568+ * @param a the assembler to emit the code
2569+ * @param op the opcode of ALU operation
2570+ * @param reg_no_dst the no of register, as first operand, and save result
2571+ * @param reg_no_src the no of register, as the second operand
2572+ *
2573+ * @return true if success, false otherwise
2574+ */
2575+ static bool
2576+ alu_r_r_r_i64 (x86::Assembler &a, ALU_OP op, int32 reg_no_dst, int32 reg_no1_src,
2577+ int32 reg_no2_src)
2578+ {
2579+ switch (op) {
2580+ case ADD:
2581+ if (reg_no_dst != reg_no2_src) {
2582+ mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no1_src);
2583+ a.add (regs_i64[reg_no_dst], regs_i64[reg_no2_src]);
2584+ }
2585+ else
2586+ a.add (regs_i64[reg_no2_src], regs_i64[reg_no1_src]);
2587+ break ;
2588+ case SUB:
2589+ if (reg_no_dst != reg_no2_src) {
2590+ mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no1_src);
2591+ a.sub (regs_i64[reg_no_dst], regs_i64[reg_no2_src]);
2592+ }
2593+ else {
2594+ a.sub (regs_i64[reg_no2_src], regs_i64[reg_no1_src]);
2595+ a.neg (regs_i64[reg_no2_src]);
2596+ }
2597+ break ;
2598+ case MUL:
2599+ if (reg_no_dst != reg_no2_src) {
2600+ mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no1_src);
2601+ a.imul (regs_i64[reg_no_dst], regs_i64[reg_no2_src]);
2602+ }
2603+ else
2604+ a.imul (regs_i64[reg_no2_src], regs_i64[reg_no1_src]);
2605+ break ;
2606+ case DIV_S:
2607+ case REM_S:
2608+ bh_assert (reg_no1_src == REG_RAX_IDX);
2609+ if (op == DIV_S) {
2610+ bh_assert (reg_no_dst == REG_RAX_IDX);
2611+ }
2612+ else {
2613+ bh_assert (reg_no_dst == REG_RDX_IDX);
2614+ }
2615+ /* signed extend rax to rdx:rax */
2616+ a.cqo ();
2617+ a.idiv (regs_i64[reg_no2_src]);
2618+ break ;
2619+ case DIV_U:
2620+ case REM_U:
2621+ bh_assert (reg_no1_src == REG_RAX_IDX);
2622+ if (op == DIV_U) {
2623+ bh_assert (reg_no_dst == REG_RAX_IDX);
2624+ }
2625+ else {
2626+ bh_assert (reg_no_dst == REG_RDX_IDX);
2627+ }
2628+ /* unsigned extend rax to rdx:rax */
2629+ a.xor_ (regs_i64[REG_RDX_IDX], regs_i64[REG_RDX_IDX]);
2630+ a.div (regs_i64[reg_no2_src]);
2631+ break ;
2632+ default :
2633+ bh_assert (0 );
2634+ break ;
2635+ }
2636+
2637+ return true ;
2638+ }
2639+
25422640/* *
25432641 * Encode int64 alu operation of reg and data, and save result to reg
25442642 *
@@ -2600,23 +2698,23 @@ alu_r_r_imm_i64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
26002698 else if (data == 1 ) {
26012699 mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
26022700 }
2603- else if (data == 2 ) {
2604- mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
2605- imm.setValue (1 );
2606- a.shl (regs_i64[reg_no_dst], imm);
2607- }
2608- else if (data == 4 ) {
2701+ else if (data > 0 && (data & (data - 1 )) == 0x0 ) {
26092702 mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
2610- imm.setValue (2 );
2703+ data = (int64)local_log2l (data);
2704+ imm.setValue (data);
26112705 a.shl (regs_i64[reg_no_dst], imm);
26122706 }
2613- else if (data == 8 ) {
2614- mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no_src);
2615- imm.setValue (3 );
2616- a.shl (regs_i64[reg_no_dst], imm);
2707+ else if (INT32_MIN <= data && data <= INT32_MAX) {
2708+ a.imul (regs_i64[reg_no_dst], regs_i64[reg_no_src], imm);
26172709 }
26182710 else {
2619- a.imul (regs_i64[reg_no_dst], regs_i64[reg_no_src], imm);
2711+ mov_imm_to_r_i64 (
2712+ a, reg_no_dst == reg_no_src ? REG_I64_FREE_IDX : reg_no_dst,
2713+ data);
2714+ alu_r_r_r_i64 (a, op, reg_no_dst,
2715+ reg_no_dst == reg_no_src ? REG_I64_FREE_IDX
2716+ : reg_no_dst,
2717+ reg_no_src);
26202718 }
26212719 break ;
26222720 case DIV_S:
@@ -2655,81 +2753,6 @@ alu_r_r_imm_i64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
26552753 return true ;
26562754}
26572755
2658- /* *
2659- * Encode int64 alu operation of reg and reg, and save result to reg
2660- *
2661- * @param a the assembler to emit the code
2662- * @param op the opcode of ALU operation
2663- * @param reg_no_dst the no of register, as first operand, and save result
2664- * @param reg_no_src the no of register, as the second operand
2665- *
2666- * @return true if success, false otherwise
2667- */
2668- static bool
2669- alu_r_r_r_i64 (x86::Assembler &a, ALU_OP op, int32 reg_no_dst, int32 reg_no1_src,
2670- int32 reg_no2_src)
2671- {
2672- switch (op) {
2673- case ADD:
2674- if (reg_no_dst != reg_no2_src) {
2675- mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no1_src);
2676- a.add (regs_i64[reg_no_dst], regs_i64[reg_no2_src]);
2677- }
2678- else
2679- a.add (regs_i64[reg_no2_src], regs_i64[reg_no1_src]);
2680- break ;
2681- case SUB:
2682- if (reg_no_dst != reg_no2_src) {
2683- mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no1_src);
2684- a.sub (regs_i64[reg_no_dst], regs_i64[reg_no2_src]);
2685- }
2686- else {
2687- a.sub (regs_i64[reg_no2_src], regs_i64[reg_no1_src]);
2688- a.neg (regs_i64[reg_no2_src]);
2689- }
2690- break ;
2691- case MUL:
2692- if (reg_no_dst != reg_no2_src) {
2693- mov_r_to_r (a, JIT_REG_KIND_I64, reg_no_dst, reg_no1_src);
2694- a.imul (regs_i64[reg_no_dst], regs_i64[reg_no2_src]);
2695- }
2696- else
2697- a.imul (regs_i64[reg_no2_src], regs_i64[reg_no1_src]);
2698- break ;
2699- case DIV_S:
2700- case REM_S:
2701- bh_assert (reg_no1_src == REG_RAX_IDX);
2702- if (op == DIV_S) {
2703- bh_assert (reg_no_dst == REG_RAX_IDX);
2704- }
2705- else {
2706- bh_assert (reg_no_dst == REG_RDX_IDX);
2707- }
2708- /* signed extend rax to rdx:rax */
2709- a.cqo ();
2710- a.idiv (regs_i64[reg_no2_src]);
2711- break ;
2712- case DIV_U:
2713- case REM_U:
2714- bh_assert (reg_no1_src == REG_RAX_IDX);
2715- if (op == DIV_U) {
2716- bh_assert (reg_no_dst == REG_RAX_IDX);
2717- }
2718- else {
2719- bh_assert (reg_no_dst == REG_RDX_IDX);
2720- }
2721- /* unsigned extend rax to rdx:rax */
2722- a.xor_ (regs_i64[REG_RDX_IDX], regs_i64[REG_RDX_IDX]);
2723- a.div (regs_i64[reg_no2_src]);
2724- break ;
2725- default :
2726- bh_assert (0 );
2727- break ;
2728- }
2729-
2730- return true ;
2731- }
2732-
27332756/* *
27342757 * Encode int64 alu operation of imm and imm, and save result to reg
27352758 *
@@ -3025,7 +3048,8 @@ alu_r_imm_to_r_f32(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
30253048 /* imm -> m32 */
30263049 x86::Mem cache = x86::dword_ptr (regs_i64[hreg_info->exec_env_hreg_index ],
30273050 offsetof (WASMExecEnv, jit_cache));
3028- Imm imm (*(uint32 *)&data2_src);
3051+ cast_float_to_integer v = { .f = data2_src };
3052+ Imm imm (v.i );
30293053 mov_imm_to_m (a, cache, imm, 4 );
30303054
30313055 mov_r_to_r_f32 (a, reg_no_dst, reg_no1_src);
@@ -3214,7 +3238,8 @@ alu_r_imm_to_r_f64(x86::Assembler &a, ALU_OP op, int32 reg_no_dst,
32143238 /* imm -> m64 */
32153239 x86::Mem cache = x86::qword_ptr (regs_i64[hreg_info->exec_env_hreg_index ],
32163240 offsetof (WASMExecEnv, jit_cache));
3217- Imm imm (*(uint64 *)&data2_src);
3241+ cast_double_to_integer v = { .d = data2_src };
3242+ Imm imm (v.i );
32183243 mov_imm_to_m (a, cache, imm, 8 );
32193244
32203245 mov_r_to_r_f64 (a, reg_no_dst, reg_no1_src);
@@ -3822,7 +3847,8 @@ shift_r_r_to_r_i32(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
38223847 int32 reg_no1_src, int32 reg_no2_src)
38233848{
38243849 /* should be CL */
3825- bh_assert (reg_no2_src == REG_ECX_IDX);
3850+ if (reg_no2_src != REG_ECX_IDX)
3851+ return false ;
38263852
38273853 mov_r_to_r_i32 (a, reg_no_dst, reg_no1_src);
38283854
@@ -4019,7 +4045,8 @@ shift_r_r_to_r_i64(x86::Assembler &a, SHIFT_OP op, int32 reg_no_dst,
40194045 int32 reg_no1_src, int32 reg_no2_src)
40204046{
40214047 /* should be CL */
4022- bh_assert (reg_no2_src == REG_ECX_IDX);
4048+ if (reg_no2_src != REG_ECX_IDX)
4049+ return false ;
40234050
40244051 mov_r_to_r_i64 (a, reg_no_dst, reg_no1_src);
40254052
@@ -5845,7 +5872,8 @@ cast_r_i64_to_r_f64(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
58455872static bool
58465873cast_imm_f32_to_r_i32 (x86::Assembler &a, int32 reg_no, float data)
58475874{
5848- return mov_imm_to_r_i32 (a, reg_no, *(uint32 *)&data);
5875+ cast_float_to_integer v = { .f = data };
5876+ return mov_imm_to_r_i32 (a, reg_no, v.i );
58495877}
58505878
58515879/* *
@@ -5876,7 +5904,8 @@ cast_r_f32_to_r_i32(x86::Assembler &a, int32 reg_no_dst, int32 reg_no_src)
58765904static bool
58775905cast_imm_f64_to_r_i64 (x86::Assembler &a, int32 reg_no, double data)
58785906{
5879- return mov_imm_to_r_i64 (a, reg_no, *(uint64 *)&data);
5907+ cast_double_to_integer v = { .d = data };
5908+ return mov_imm_to_r_i64 (a, reg_no, v.i );
58805909}
58815910
58825911/* *
@@ -6475,6 +6504,9 @@ jit_codegen_dump_native(void *begin_addr, void *end_addr)
64756504 os_printf (" \n " );
64766505 dump_native ((char *)begin_addr, (char *)end_addr - (char *)begin_addr);
64776506 os_printf (" \n " );
6507+ #else
6508+ (void )begin_addr;
6509+ (void )end_addr;
64786510#endif
64796511}
64806512
0 commit comments