diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index f00b6ca8..2293f5a4 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -339,9 +339,19 @@ void EmitX64::EmitLeastSignificantWord(IR::Block&, IR::Inst* inst) { reg_alloc.RegisterAddDef(inst, inst->GetArg(0)); } -void EmitX64::EmitMostSignificantWord(IR::Block&, IR::Inst* inst) { - auto u64 = reg_alloc.UseDefRegister(inst->GetArg(0), inst, any_gpr); - code->SHR(64, R(u64), Imm8(32)); +void EmitX64::EmitMostSignificantWord(IR::Block& block, IR::Inst* inst) { + auto carry_inst = FindUseWithOpcode(inst, IR::Opcode::GetCarryFromOp); + auto result = reg_alloc.UseDefRegister(inst->GetArg(0), inst, any_gpr); + + code->SHR(64, R(result), Imm8(32)); + + if (carry_inst) { + EraseInstruction(block, carry_inst); + reg_alloc.DecrementRemainingUses(inst); + X64Reg carry = reg_alloc.DefRegister(carry_inst, any_gpr); + + code->SETcc(CC_C, R(carry)); + } } void EmitX64::EmitLeastSignificantHalf(IR::Block&, IR::Inst* inst) { diff --git a/src/frontend/ir/ir_emitter.cpp b/src/frontend/ir/ir_emitter.cpp index f00345af..b5315cca 100644 --- a/src/frontend/ir/ir_emitter.cpp +++ b/src/frontend/ir/ir_emitter.cpp @@ -127,8 +127,10 @@ IR::Value IREmitter::LeastSignificantWord(const IR::Value& value) { return Inst(IR::Opcode::LeastSignificantWord, {value}); } -IR::Value IREmitter::MostSignificantWord(const IR::Value& value) { - return Inst(IR::Opcode::MostSignificantWord, {value}); +IREmitter::ResultAndCarry IREmitter::MostSignificantWord(const IR::Value& value) { + auto result = Inst(IR::Opcode::MostSignificantWord, {value}); + auto carry_out = Inst(IR::Opcode::GetCarryFromOp, {result}); + return {result, carry_out}; } IR::Value IREmitter::LeastSignificantHalf(const IR::Value& value) { diff --git a/src/frontend/ir/ir_emitter.h b/src/frontend/ir/ir_emitter.h index 506a70e7..2a7a16e1 100644 --- a/src/frontend/ir/ir_emitter.h +++ b/src/frontend/ir/ir_emitter.h @@ -58,7 +58,7 @@ public: IR::Value Pack2x32To1x64(const IR::Value& lo, const IR::Value& hi); IR::Value LeastSignificantWord(const IR::Value& value); - IR::Value MostSignificantWord(const IR::Value& value); + ResultAndCarry MostSignificantWord(const IR::Value& value); IR::Value LeastSignificantHalf(const IR::Value& value); IR::Value LeastSignificantByte(const IR::Value& value); IR::Value MostSignificantBit(const IR::Value& value); diff --git a/src/frontend/translate/translate_arm/multiply.cpp b/src/frontend/translate/translate_arm/multiply.cpp index 4fefcc28..2ef8b70f 100644 --- a/src/frontend/translate/translate_arm/multiply.cpp +++ b/src/frontend/translate/translate_arm/multiply.cpp @@ -52,7 +52,7 @@ bool ArmTranslatorVisitor::arm_SMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, auto addend = ir.Pack2x32To1x64(ir.GetRegister(dLo), ir.GetRegister(dHi)); auto result = ir.Add64(product, addend); auto lo = ir.LeastSignificantWord(result); - auto hi = ir.MostSignificantWord(result); + auto hi = ir.MostSignificantWord(result).result; ir.SetRegister(dLo, lo); ir.SetRegister(dHi, hi); if (S) { @@ -73,7 +73,7 @@ bool ArmTranslatorVisitor::arm_SMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, auto m64 = ir.SignExtendWordToLong(ir.GetRegister(m)); auto result = ir.Mul64(n64, m64); auto lo = ir.LeastSignificantWord(result); - auto hi = ir.MostSignificantWord(result); + auto hi = ir.MostSignificantWord(result).result; ir.SetRegister(dLo, lo); ir.SetRegister(dHi, hi); if (S) { @@ -96,7 +96,7 @@ bool ArmTranslatorVisitor::arm_UMAAL(Cond cond, Reg dHi, Reg dLo, Reg m, Reg n) auto m64 = ir.ZeroExtendWordToLong(ir.GetRegister(m)); auto result = ir.Add64(ir.Add64(ir.Mul64(n64, m64), hi64), lo64); ir.SetRegister(dLo, ir.LeastSignificantWord(result)); - ir.SetRegister(dHi, ir.MostSignificantWord(result)); + ir.SetRegister(dHi, ir.MostSignificantWord(result).result); } return true; } @@ -112,7 +112,7 @@ bool ArmTranslatorVisitor::arm_UMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, auto m64 = ir.ZeroExtendWordToLong(ir.GetRegister(m)); auto result = ir.Add64(ir.Mul64(n64, m64), addend); auto lo = ir.LeastSignificantWord(result); - auto hi = ir.MostSignificantWord(result); + auto hi = ir.MostSignificantWord(result).result; ir.SetRegister(dLo, lo); ir.SetRegister(dHi, hi); if (S) { @@ -133,7 +133,7 @@ bool ArmTranslatorVisitor::arm_UMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, auto m64 = ir.ZeroExtendWordToLong(ir.GetRegister(m)); auto result = ir.Mul64(n64, m64); auto lo = ir.LeastSignificantWord(result); - auto hi = ir.MostSignificantWord(result); + auto hi = ir.MostSignificantWord(result).result; ir.SetRegister(dLo, lo); ir.SetRegister(dHi, hi); if (S) {