diff --git a/cranelift/filetests/filetests/runtests/iaddcarry.clif b/cranelift/filetests/filetests/runtests/iaddcarry.clif new file mode 100644 index 000000000000..51389ed60c6f --- /dev/null +++ b/cranelift/filetests/filetests/runtests/iaddcarry.clif @@ -0,0 +1,97 @@ +test interpret + +function %iaddcarry_i8_v(i8, i8, b1) -> i8 { +block0(v0: i8, v1: i8, v2: b1): + v3, v4 = iadd_carry v0, v1, v2 + return v3 +} +; run: %iaddcarry_i8_v(0, 1, true) == 2 +; run: %iaddcarry_i8_v(0, 1, false) == 1 +; run: %iaddcarry_i8_v(100, 27, true) == -128 +; run: %iaddcarry_i8_v(100, 27, false) == 127 +; run: %iaddcarry_i8_v(127, 127, true) == -1 +; run: %iaddcarry_i8_v(127, 127, false) == -2 + +function %iaddcarry_i8_c(i8, i8, b1) -> b1 { +block0(v0: i8, v1: i8, v2: b1): + v3, v4 = iadd_carry v0, v1, v2 + return v4 +} +; run: %iaddcarry_i8_c(0, 1, true) == false +; run: %iaddcarry_i8_c(0, 1, false) == false +; run: %iaddcarry_i8_c(100, 27, true) == true +; run: %iaddcarry_i8_c(100, 27, false) == false +; run: %iaddcarry_i8_c(127, 127, true) == true +; run: %iaddcarry_i8_c(127, 127, false) == true + +function %iaddcarry_i16_v(i16, i16, b1) -> i16 { +block0(v0: i16, v1: i16, v2: b1): + v3, v4 = iadd_carry v0, v1, v2 + return v3 +} +; run: %iaddcarry_i16_v(0, 1, true) == 2 +; run: %iaddcarry_i16_v(0, 1, false) == 1 +; run: %iaddcarry_i16_v(100, 27, true) == 128 +; run: %iaddcarry_i16_v(100, 27, false) == 127 +; run: %iaddcarry_i16_v(32000, 767, true) == -32768 +; run: %iaddcarry_i16_v(32000, 767, false) == 32767 + +function %iaddcarry_i16_c(i16, i16, b1) -> b1 { +block0(v0: i16, v1: i16, v2: b1): + v3, v4 = iadd_carry v0, v1, v2 + return v4 +} +; run: %iaddcarry_i16_c(0, 1, true) == false +; run: %iaddcarry_i16_c(0, 1, false) == false +; run: %iaddcarry_i16_c(100, 27, true) == false +; run: %iaddcarry_i16_c(100, 27, false) == false +; run: %iaddcarry_i16_c(32000, 767, true) == true +; run: %iaddcarry_i16_c(32000, 767, false) == false + +function %iaddcarry_i32_v(i32, i32, b1) -> i32 { +block0(v0: i32, v1: i32, v2: b1): + v3, v4 = iadd_carry v0, v1, v2 + return v3 +} +; run: %iaddcarry_i32_v(0, 1, true) == 2 +; run: %iaddcarry_i32_v(0, 1, false) == 1 +; run: %iaddcarry_i32_v(100, 27, true) == 128 +; run: %iaddcarry_i32_v(100, 27, false) == 127 +; run: %iaddcarry_i32_v(2000000000, 147483647, true) == -2147483648 +; run: %iaddcarry_i32_v(2000000000, 147483647, false) == 2147483647 + +function %iaddcarry_i32_c(i32, i32, b1) -> b1 { +block0(v0: i32, v1: i32, v2: b1): + v3, v4 = iadd_carry v0, v1, v2 + return v4 +} +; run: %iaddcarry_i32_c(0, 1, true) == false +; run: %iaddcarry_i32_c(0, 1, false) == false +; run: %iaddcarry_i32_c(100, 27, true) == false +; run: %iaddcarry_i32_c(100, 27, false) == false +; run: %iaddcarry_i32_c(2000000000, 147483647, true) == true +; run: %iaddcarry_i32_c(2000000000, 147483647, false) == false + +function %iaddcarry_i64_v(i64, i64, b1) -> i64 { +block0(v0: i64, v1: i64, v2: b1): + v3, v4 = iadd_carry v0, v1, v2 + return v3 +} +; run: %iaddcarry_i64_v(0, 1, true) == 2 +; run: %iaddcarry_i64_v(0, 1, false) == 1 +; run: %iaddcarry_i64_v(100, 27, true) == 128 +; run: %iaddcarry_i64_v(100, 27, false) == 127 +; run: %iaddcarry_i64_v(9000000000000000000, 223372036854775807, true) == -9223372036854775808 +; run: %iaddcarry_i64_v(9000000000000000000, 223372036854775807, false) == 9223372036854775807 + +function %iaddcarry_i64_c(i64, i64, b1) -> b1 { +block0(v0: i64, v1: i64, v2: b1): + v3, v4 = iadd_carry v0, v1, v2 + return v4 +} +; run: %iaddcarry_i64_c(0, 1, true) == false +; run: %iaddcarry_i64_c(0, 1, false) == false +; run: %iaddcarry_i64_c(100, 27, true) == false +; run: %iaddcarry_i64_c(100, 27, false) == false +; run: %iaddcarry_i64_c(9000000000000000000, 223372036854775807, true) == true +; run: %iaddcarry_i64_c(9000000000000000000, 223372036854775807, false) == false diff --git a/cranelift/filetests/filetests/runtests/iaddcin.clif b/cranelift/filetests/filetests/runtests/iaddcin.clif new file mode 100644 index 000000000000..8f36ee0d7001 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/iaddcin.clif @@ -0,0 +1,48 @@ +test interpret + +function %iaddcin_i8(i8, i8, b1) -> i8 { +block0(v0: i8, v1: i8, v2: b1): + v3 = iadd_cin v0, v1, v2 + return v3 +} +; run: %iaddcin_i8(0, 1, true) == 2 +; run: %iaddcin_i8(0, 1, false) == 1 +; run: %iaddcin_i8(100, 27, true) == -128 +; run: %iaddcin_i8(100, 27, false) == 127 + +function %iaddcin_i16(i16, i16, b1) -> i16 { +block0(v0: i16, v1: i16, v2: b1): + v3 = iadd_cin v0, v1, v2 + return v3 +} +; run: %iaddcin_i16(0, 1, true) == 2 +; run: %iaddcin_i16(0, 1, false) == 1 +; run: %iaddcin_i16(100, 27, true) == 128 +; run: %iaddcin_i16(100, 27, false) == 127 +; run: %iaddcin_i16(32000, 767, true) == -32768 +; run: %iaddcin_i16(32000, 767, false) == 32767 + +function %iaddcin_i32(i32, i32, b1) -> i32 { +block0(v0: i32, v1: i32, v2: b1): + v3 = iadd_cin v0, v1, v2 + return v3 +} +; run: %iaddcin_i32(0, 1, true) == 2 +; run: %iaddcin_i32(0, 1, false) == 1 +; run: %iaddcin_i32(100, 27, true) == 128 +; run: %iaddcin_i32(100, 27, false) == 127 +; run: %iaddcin_i32(2000000000, 147483647, true) == -2147483648 +; run: %iaddcin_i32(2000000000, 147483647, false) == 2147483647 + + +function %iaddcin_i64(i64, i64, b1) -> i64 { +block0(v0: i64, v1: i64, v2: b1): + v3 = iadd_cin v0, v1, v2 + return v3 +} +; run: %iaddcin_i64(0, 1, true) == 2 +; run: %iaddcin_i64(0, 1, false) == 1 +; run: %iaddcin_i64(100, 27, true) == 128 +; run: %iaddcin_i64(100, 27, false) == 127 +; run: %iaddcin_i64(2000000000, 147483647, true) == 2147483648 +; run: %iaddcin_i64(2000000000, 147483647, false) == 2147483647 diff --git a/cranelift/filetests/filetests/runtests/iaddcout.clif b/cranelift/filetests/filetests/runtests/iaddcout.clif new file mode 100644 index 000000000000..6f497b61e51d --- /dev/null +++ b/cranelift/filetests/filetests/runtests/iaddcout.clif @@ -0,0 +1,87 @@ +test interpret + +function %iaddcout_i8_v(i8, i8) -> i8 { +block0(v0: i8, v1: i8): + v2, v3 = iadd_cout v0, v1 + return v2 +} +; run: %iaddcout_i8_v(0, 1) == 1 +; run: %iaddcout_i8_v(100, 27) == 127 +; run: %iaddcout_i8_v(100, -20) == 80 +; run: %iaddcout_i8_v(100, 28) == -128 + +function %iaddcout_i8_c(i8, i8) -> b1 { +block0(v0: i8, v1: i8): + v2, v3 = iadd_cout v0, v1 + return v3 +} +; run: %iaddcout_i8_c(0, 1) == false +; run: %iaddcout_i8_c(100, 27) == false +; run: %iaddcout_i8_c(100, -20) == false +; run: %iaddcout_i8_c(100, 28) == true + +function %iaddcout_i16_v(i16, i16) -> i16 { +block0(v0: i16, v1: i16): + v2, v3 = iadd_cout v0, v1 + return v2 +} +; run: %iaddcout_i16_v(0, 1) == 1 +; run: %iaddcout_i16_v(100, 27) == 127 +; run: %iaddcout_i16_v(100, 28) == 128 +; run: %iaddcout_i16_v(32000, 767) == 32767 +; run: %iaddcout_i16_v(32000, 768) == -32768 + +function %iaddcout_i16_c(i16, i16) -> b1 { +block0(v0: i16, v1: i16): + v2, v3 = iadd_cout v0, v1 + return v3 +} +; run: %iaddcout_i16_c(0, 1) == false +; run: %iaddcout_i16_c(100, 27) == false +; run: %iaddcout_i16_c(100, 28) == false +; run: %iaddcout_i16_c(32000, 767) == false +; run: %iaddcout_i16_c(32000, 768) == true + +function %iaddcout_i32_v(i32, i32) -> i32 { +block0(v0: i32, v1: i32): + v2, v3 = iadd_cout v0, v1 + return v2 +} +; run: %iaddcout_i32_v(0, 1) == 1 +; run: %iaddcout_i32_v(100, 27) == 127 +; run: %iaddcout_i32_v(100, 28) == 128 +; run: %iaddcout_i32_v(2000000000, 147483647) == 2147483647 +; run: %iaddcout_i32_v(2000000000, 147483648) == -2147483648 + +function %iaddcout_i32_c(i32, i32) -> b1 { +block0(v0: i32, v1: i32): + v2, v3 = iadd_cout v0, v1 + return v3 +} +; run: %iaddcout_i32_c(0, 1) == false +; run: %iaddcout_i32_c(100, 27) == false +; run: %iaddcout_i32_c(100, 28) == false +; run: %iaddcout_i32_c(2000000000, 147483647) == false +; run: %iaddcout_i32_c(2000000000, 147483648) == true + +function %iaddcout_i64_v(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2, v3 = iadd_cout v0, v1 + return v2 +} +; run: %iaddcout_i64_v(0, 1) == 1 +; run: %iaddcout_i64_v(100, 27) == 127 +; run: %iaddcout_i64_v(100, 28) == 128 +; run: %iaddcout_i64_v(2000000000, 147483647) == 2147483647 +; run: %iaddcout_i64_v(2000000000, 147483648) == 2147483648 + +function %iaddcout_i64_c(i64, i64) -> b1 { +block0(v0: i64, v1: i64): + v2, v3 = iadd_cout v0, v1 + return v3 +} +; run: %iaddcout_i64_c(0, 1) == false +; run: %iaddcout_i64_c(100, 27) == false +; run: %iaddcout_i64_c(100, 28) == false +; run: %iaddcout_i64_c(2000000000, 147483647) == false +; run: %iaddcout_i64_c(2000000000, 147483648) == false diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index c9c03729809b..b199ef4d4866 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -454,11 +454,26 @@ where Opcode::UremImm => binary_unsigned_can_trap(Value::rem, arg(0)?, imm())?, Opcode::SremImm => binary_can_trap(Value::rem, arg(0)?, imm_as_ctrl_ty()?)?, Opcode::IrsubImm => binary(Value::sub, imm_as_ctrl_ty()?, arg(0)?)?, - Opcode::IaddCin => unimplemented!("IaddCin"), + Opcode::IaddCin => choose( + Value::into_bool(arg(2)?)?, + Value::add(Value::add(arg(0)?, arg(1)?)?, Value::int(1, ctrl_ty)?)?, + Value::add(arg(0)?, arg(1)?)?, + ), Opcode::IaddIfcin => unimplemented!("IaddIfcin"), - Opcode::IaddCout => unimplemented!("IaddCout"), + Opcode::IaddCout => { + let sum = Value::add(arg(0)?, arg(1)?)?; + let carry = Value::lt(&sum, &arg(0)?)? && Value::lt(&sum, &arg(1)?)?; + assign_multiple(&[sum, Value::bool(carry, types::B1)?]) + } Opcode::IaddIfcout => unimplemented!("IaddIfcout"), - Opcode::IaddCarry => unimplemented!("IaddCarry"), + Opcode::IaddCarry => { + let mut sum = Value::add(arg(0)?, arg(1)?)?; + if Value::into_bool(arg(2)?)? { + sum = Value::add(sum, Value::int(1, ctrl_ty)?)? + } + let carry = Value::lt(&sum, &arg(0)?)? && Value::lt(&sum, &arg(1)?)?; + assign_multiple(&[sum, Value::bool(carry, types::B1)?]) + } Opcode::IaddIfcarry => unimplemented!("IaddIfcarry"), Opcode::IsubBin => unimplemented!("IsubBin"), Opcode::IsubIfbin => unimplemented!("IsubIfbin"),