diff --git a/src/rust/codegen.rs b/src/rust/codegen.rs index eb669312..139669ee 100644 --- a/src/rust/codegen.rs +++ b/src/rust/codegen.rs @@ -347,6 +347,11 @@ fn gen_get_last_result(builder: &mut WasmBuilder, previous_instruction: &Instruc opsize: OPSIZE_32, .. } + | Instruction::AdcSbb { + dest: InstructionOperandDest::WasmLocal(l), + opsize: OPSIZE_32, + .. + } | Instruction::Sub { dest: InstructionOperandDest::WasmLocal(l), opsize: OPSIZE_32, @@ -1646,6 +1651,7 @@ pub fn gen_getzf(ctx: &mut JitContext, negate: ConditionNegate) { Instruction::Cmp { .. } | Instruction::Sub { .. } | Instruction::Add { .. } + | Instruction::AdcSbb { .. } | Instruction::NonZeroShift { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); gen_get_last_result(ctx.builder, &ctx.previous_instruction); @@ -1763,7 +1769,7 @@ pub fn gen_getcf(ctx: &mut JitContext, negate: ConditionNegate) { ctx.builder .const_i32(if negate == ConditionNegate::True { 1 } else { 0 }); }, - Instruction::NonZeroShift { .. } => { + Instruction::NonZeroShift { .. } | Instruction::AdcSbb { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); gen_get_flags(ctx.builder); ctx.builder.const_i32(FLAG_CARRY); @@ -1817,6 +1823,7 @@ pub fn gen_getsf(ctx: &mut JitContext, negate: ConditionNegate) { Instruction::Cmp { opsize, .. } | Instruction::Sub { opsize, .. } | Instruction::Add { opsize, .. } + | Instruction::AdcSbb { opsize, .. } | Instruction::Bitwise { opsize, .. } | Instruction::NonZeroShift { opsize, .. } => { let &opsize = opsize; @@ -1926,7 +1933,7 @@ pub fn gen_getof(ctx: &mut JitContext) { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); ctx.builder.const_i32(0); }, - Instruction::NonZeroShift { .. } => { + Instruction::NonZeroShift { .. } | Instruction::AdcSbb { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); gen_get_flags(ctx.builder); ctx.builder.const_i32(FLAG_OVERFLOW); @@ -2078,7 +2085,7 @@ pub fn gen_test_be(ctx: &mut JitContext, negate: ConditionNegate) { ctx.builder.eqz_i32(); } }, - Instruction::Other | Instruction::NonZeroShift { .. } => { + Instruction::Other | Instruction::NonZeroShift { .. } | Instruction::AdcSbb { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_UNOPTIMISED); gen_getcf(ctx, ConditionNegate::False); gen_getzf(ctx, ConditionNegate::False); @@ -2194,7 +2201,10 @@ pub fn gen_test_l(ctx: &mut JitContext, negate: ConditionNegate) { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_OPTIMISED); gen_getsf(ctx, negate); }, - &Instruction::Other | Instruction::Add { .. } | Instruction::NonZeroShift { .. } => { + &Instruction::Other + | Instruction::Add { .. } + | Instruction::NonZeroShift { .. } + | Instruction::AdcSbb { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_UNOPTIMISED); if let Instruction::Add { .. } = ctx.previous_instruction { gen_profiler_stat_increment( @@ -2324,7 +2334,10 @@ pub fn gen_test_le(ctx: &mut JitContext, negate: ConditionNegate) { ctx.builder.eqz_i32(); } }, - Instruction::Other | Instruction::Add { .. } | Instruction::NonZeroShift { .. } => { + Instruction::Other + | Instruction::Add { .. } + | Instruction::NonZeroShift { .. } + | Instruction::AdcSbb { .. } => { gen_profiler_stat_increment(ctx.builder, profiler::stat::CONDITION_UNOPTIMISED); if let Instruction::Add { .. } = ctx.previous_instruction { gen_profiler_stat_increment( diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 532c4d1e..cb73bc07 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -274,6 +274,11 @@ pub enum Instruction { opsize: i32, is_inc: bool, }, + AdcSbb { + dest: InstructionOperandDest, + source: InstructionOperand, + opsize: i32, + }, NonZeroShift { dest: InstructionOperandDest, opsize: i32, diff --git a/src/rust/jit_instructions.rs b/src/rust/jit_instructions.rs index a1f0a14a..87ecdf66 100644 --- a/src/rust/jit_instructions.rs +++ b/src/rust/jit_instructions.rs @@ -1121,6 +1121,17 @@ fn gen_adc8(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &Loc ctx.builder.call_fn2_ret("adc8"); ctx.builder.const_i32(0xFF); ctx.builder.and_i32(); + + ctx.current_instruction = Instruction::AdcSbb { + opsize: OPSIZE_8, + dest: local_to_instruction_operand(ctx, dest_operand), + source: if source_operand.eq_local(dest_operand) { + InstructionOperand::Other // aliasing + } + else { + source_operand.to_instruction_operand(ctx) + }, + }; } fn gen_adc32(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &LocalOrImmediate) { ctx.builder.get_local(&dest_operand); @@ -1188,6 +1199,17 @@ fn gen_adc32(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &Lo ctx.builder.get_local(&res); ctx.builder.set_local(dest_operand); ctx.builder.free_local(res); + + ctx.current_instruction = Instruction::AdcSbb { + opsize: OPSIZE_32, + dest: local_to_instruction_operand(ctx, dest_operand), + source: if source_operand.eq_local(dest_operand) { + InstructionOperand::Other // aliasing + } + else { + source_operand.to_instruction_operand(ctx) + }, + }; } fn gen_sbb8(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &LocalOrImmediate) { @@ -1198,6 +1220,17 @@ fn gen_sbb8(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &Loc ctx.builder.call_fn2_ret("sbb8"); ctx.builder.const_i32(0xFF); ctx.builder.and_i32(); + + ctx.current_instruction = Instruction::AdcSbb { + opsize: OPSIZE_8, + dest: local_to_instruction_operand(ctx, dest_operand), + source: if source_operand.eq_local(dest_operand) { + InstructionOperand::Other // aliasing + } + else { + source_operand.to_instruction_operand(ctx) + }, + }; } fn gen_sbb32(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &LocalOrImmediate) { ctx.builder.get_local(&dest_operand); @@ -1265,6 +1298,17 @@ fn gen_sbb32(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &Lo ctx.builder.get_local(&res); ctx.builder.set_local(dest_operand); ctx.builder.free_local(res); + + ctx.current_instruction = Instruction::AdcSbb { + opsize: OPSIZE_32, + dest: local_to_instruction_operand(ctx, dest_operand), + source: if source_operand.eq_local(dest_operand) { + InstructionOperand::Other // aliasing + } + else { + source_operand.to_instruction_operand(ctx) + }, + }; } fn gen_and8(ctx: &mut JitContext, dest_operand: &WasmLocal, source_operand: &LocalOrImmediate) {