diff --git a/integration_tests/bit_operations_i32.py b/integration_tests/bit_operations_i32.py index 859be4dd12..67934c8ce3 100644 --- a/integration_tests/bit_operations_i32.py +++ b/integration_tests/bit_operations_i32.py @@ -87,10 +87,38 @@ def test_bitxor(): assert(r == -1) assert(s == -2147483643) +def test_left_shift(): + a: i32 = 4 + shift_amount: i32 = 2 + b: i32 = a << shift_amount + print(b) + assert b == 16 + + a = -16 + shift_amount = 2 + b = a << shift_amount + print(b) + assert b == -64 + +def test_right_shift(): + a: i32 = 16 + shift_amount: i32 = 2 + b: i32 = a >> shift_amount + print(b) + assert b == 4 + + a = -16 + shift_amount = 2 + b = a >> shift_amount + print(b) + assert b == -4 + def main0(): test_bitnot() test_bitand() test_bitor() test_bitxor() + test_left_shift() + test_right_shift() main0() diff --git a/integration_tests/bit_operations_i64.py b/integration_tests/bit_operations_i64.py index 6b9eb2ef1c..c1ac77c413 100644 --- a/integration_tests/bit_operations_i64.py +++ b/integration_tests/bit_operations_i64.py @@ -84,10 +84,38 @@ def test_bitxor(): assert(r == i64(-1)) assert(s == i64(-115292150461418)) +def test_left_shift(): + a: i64 = i64(4294967296) + shift_amount: i64 = i64(2) + b: i64 = a << shift_amount + print(b) + assert b == i64(17179869184) + + a = i64(-4294967296) + shift_amount = i64(2) + b = a << shift_amount + print(b) + assert b == i64(-17179869184) + +def test_right_shift(): + a: i64 = i64(4294967296) + shift_amount: i64 = i64(2) + b: i64 = a >> shift_amount + print(b) + assert b == i64(1073741824) + + a = i64(-4294967296) + shift_amount = i64(2) + b = a >> shift_amount + print(b) + assert b == i64(-1073741824) + def main0(): test_bitnot() test_bitand() test_bitor() test_bitxor() + test_left_shift() + test_right_shift() main0() diff --git a/src/libasr/codegen/asr_to_wasm.cpp b/src/libasr/codegen/asr_to_wasm.cpp index 8b69eea222..49cfd90d6b 100644 --- a/src/libasr/codegen/asr_to_wasm.cpp +++ b/src/libasr/codegen/asr_to_wasm.cpp @@ -890,6 +890,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { wasm::emit_i32_xor(m_code_section, m_al); break; }; + case ASR::binopType::BitLShift: { + wasm::emit_i32_shl(m_code_section, m_al); + break; + }; + case ASR::binopType::BitRShift: { + wasm::emit_i32_shr_s(m_code_section, m_al); + break; + }; default: { throw CodeGenError( "ICE IntegerBinop kind 4: unknown operation"); @@ -947,6 +955,14 @@ class ASRToWASMVisitor : public ASR::BaseVisitor { wasm::emit_i64_xor(m_code_section, m_al); break; }; + case ASR::binopType::BitLShift: { + wasm::emit_i64_shl(m_code_section, m_al); + break; + }; + case ASR::binopType::BitRShift: { + wasm::emit_i64_shr_s(m_code_section, m_al); + break; + }; default: { throw CodeGenError( "ICE IntegerBinop kind 8: unknown operation"); diff --git a/src/libasr/codegen/wasm_to_x64.cpp b/src/libasr/codegen/wasm_to_x64.cpp index acad7b971e..8a531a4eac 100644 --- a/src/libasr/codegen/wasm_to_x64.cpp +++ b/src/libasr/codegen/wasm_to_x64.cpp @@ -309,6 +309,19 @@ class X64Visitor : public WASMDecoder, handleI32Opt([&](){ m_a.asm_xor_r64_r64(X64Reg::rax, X64Reg::rbx);}); } + void visit_I32Shl() { + m_a.asm_pop_r64(X64Reg::rcx); + m_a.asm_pop_r64(X64Reg::rax); + m_a.asm_shl_r64_cl(X64Reg::rax); + m_a.asm_push_r64(X64Reg::rax); + } + void visit_I32ShrS() { + m_a.asm_pop_r64(X64Reg::rcx); + m_a.asm_pop_r64(X64Reg::rax); + m_a.asm_sar_r64_cl(X64Reg::rax); + m_a.asm_push_r64(X64Reg::rax); + } + void visit_I32Eqz() { m_a.asm_mov_r64_imm64(X64Reg::rax, 0); m_a.asm_push_r64(X64Reg::rax); diff --git a/src/libasr/codegen/x86_assembler.h b/src/libasr/codegen/x86_assembler.h index 2f5925aa1b..2b2d37e5ff 100644 --- a/src/libasr/codegen/x86_assembler.h +++ b/src/libasr/codegen/x86_assembler.h @@ -1254,6 +1254,38 @@ class X86Assembler { EMIT("syscall"); } + // SHL - Shift Logical/Unsigned Left + void asm_shl_r64_cl(X64Reg r64) { + X86Reg r32 = X86Reg(r64 & 7); + m_code.push_back(m_al, rex(1, 0, 0, r64 >> 3)); + m_code.push_back(m_al, 0xD3); + modrm_sib_disp(m_code, m_al, X86Reg::esp, &r32, nullptr, 1, 0, false); + EMIT("shl " + r2s(r64) + ", cl"); + } + + // SHL - Shift Logical/Unsigned Left + void asm_shl_r32_cl(X86Reg r32) { + m_code.push_back(m_al, 0xD3); + modrm_sib_disp(m_code, m_al, X86Reg::esp, &r32, nullptr, 1, 0, false); + EMIT("shl " + r2s(r32) + ", cl"); + } + + // SAR - Shift Arithmetic/Signed Right + void asm_sar_r64_cl(X64Reg r64) { + X86Reg r32 = X86Reg(r64 & 7); + m_code.push_back(m_al, rex(1, 0, 0, r64 >> 3)); + m_code.push_back(m_al, 0xD3); + modrm_sib_disp(m_code, m_al, X86Reg::edi, &r32, nullptr, 1, 0, false); + EMIT("sar " + r2s(r64) + ", cl"); + } + + // SAR - Shift Arithmetic/Signed Right + void asm_sar_r32_cl(X86Reg r32) { + m_code.push_back(m_al, 0xD3); + modrm_sib_disp(m_code, m_al, X86Reg::edi, &r32, nullptr, 1, 0, false); + EMIT("sar " + r2s(r32) + ", cl"); + } + void asm_fld_m32(X86Reg *base, X86Reg *index, uint8_t scale, int32_t disp) { m_code.push_back(m_al, 0xd9);