diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 5733d610..1cd25246 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -592,6 +592,17 @@ void EmitX64::EmitLogicalShiftRight(IR::Block& block, IR::Inst* inst) { } } +void EmitX64::EmitLogicalShiftRight64(IR::Block& block, IR::Inst* inst) { + X64Reg result = reg_alloc.UseDefRegister(inst->GetArg(0), inst, any_gpr); + + auto shift_arg = inst->GetArg(1); + ASSERT_MSG(shift_arg.IsImmediate(), "variable 64 bit shifts are not implemented"); + u8 shift = shift_arg.GetU8(); + ASSERT_MSG(shift < 64, "shift width clamping is not implemented"); + + code->SHR(64, R(result), Imm8(shift)); +} + void EmitX64::EmitArithmeticShiftRight(IR::Block& block, IR::Inst* inst) { auto carry_inst = FindUseWithOpcode(inst, IR::Opcode::GetCarryFromOp); diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index 716c6736..63e9b8fd 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -169,6 +169,10 @@ IREmitter::ResultAndCarry IREmitter::LogicalShiftRight(const IR::Value& value_in return {result, carry_out}; } +IR::Value IREmitter::LogicalShiftRight64(const IR::Value& value_in, const IR::Value& shift_amount) { + return Inst(IR::Opcode::LogicalShiftRight64, {value_in, shift_amount}); +} + IREmitter::ResultAndCarry IREmitter::ArithmeticShiftRight(const IR::Value& value_in, const IR::Value& shift_amount, const IR::Value& carry_in) { auto result = Inst(IR::Opcode::ArithmeticShiftRight, {value_in, shift_amount, carry_in}); auto carry_out = Inst(IR::Opcode::GetCarryFromOp, {result}); diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 544ab42d..0b7761cf 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -68,6 +68,7 @@ public: ResultAndCarry LogicalShiftLeft(const IR::Value& value_in, const IR::Value& shift_amount, const IR::Value& carry_in); ResultAndCarry LogicalShiftRight(const IR::Value& value_in, const IR::Value& shift_amount, const IR::Value& carry_in); + IR::Value LogicalShiftRight64(const IR::Value& value_in, const IR::Value& shift_amount); ResultAndCarry ArithmeticShiftRight(const IR::Value& value_in, const IR::Value& shift_amount, const IR::Value& carry_in); ResultAndCarry RotateRight(const IR::Value& value_in, const IR::Value& shift_amount, const IR::Value& carry_in); ResultAndCarry RotateRightExtended(const IR::Value& value_in, const IR::Value& carry_in); diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index ec45d734..95c410a3 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -37,6 +37,7 @@ OPCODE(IsZero, T::U1, T::U32 OPCODE(IsZero64, T::U1, T::U64 ) OPCODE(LogicalShiftLeft, T::U32, T::U32, T::U8, T::U1 ) OPCODE(LogicalShiftRight, T::U32, T::U32, T::U8, T::U1 ) +OPCODE(LogicalShiftRight64, T::U64, T::U64, T::U8 ) OPCODE(ArithmeticShiftRight, T::U32, T::U32, T::U8, T::U1 ) OPCODE(RotateRight, T::U32, T::U32, T::U8, T::U1 ) OPCODE(RotateRightExtended, T::U32, T::U32, T::U1 )