mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-01-07 06:58:15 +01:00
Add more IR opcodes for multiply instructions
Pack2x32To1x64, LeastSignificantWord, MostSignificantWord, IsZero64, Add64, Mul, Mul64, SignExtendWordToLong, ZeroExtendWordToLong
This commit is contained in:
parent
a97668ead4
commit
3fdc093d10
4 changed files with 144 additions and 0 deletions
|
|
@ -272,6 +272,23 @@ void EmitX64::EmitGetOverflowFromOp(IR::Block&, IR::Inst*) {
|
|||
ASSERT_MSG(0, "should never happen");
|
||||
}
|
||||
|
||||
void EmitX64::EmitPack2x32To1x64(IR::Block&, IR::Inst* inst) {
|
||||
auto lo = reg_alloc.UseRegister(inst->GetArg(0), any_gpr);
|
||||
auto hi = reg_alloc.UseDefRegister(inst->GetArg(1), inst, any_gpr);
|
||||
code->SHL(64, R(hi), Imm8(32));
|
||||
code->OR(64, R(hi), R(lo));
|
||||
}
|
||||
|
||||
void EmitX64::EmitLeastSignificantWord(IR::Block&, IR::Inst* inst) {
|
||||
// TODO: Optimize
|
||||
reg_alloc.UseDefRegister(inst->GetArg(0), inst, any_gpr);
|
||||
}
|
||||
|
||||
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::EmitLeastSignificantHalf(IR::Block&, IR::Inst* inst) {
|
||||
// TODO: Optimize
|
||||
|
||||
|
|
@ -302,6 +319,16 @@ void EmitX64::EmitIsZero(IR::Block&, IR::Inst* inst) {
|
|||
code->MOVZX(32, 8, result, R(result));
|
||||
}
|
||||
|
||||
void EmitX64::EmitIsZero64(IR::Block&, IR::Inst* inst) {
|
||||
X64Reg result = reg_alloc.UseDefRegister(inst->GetArg(0), inst, any_gpr);
|
||||
|
||||
// TODO: Flag optimization
|
||||
|
||||
code->TEST(64, R(result), R(result));
|
||||
code->SETcc(CCFlags::CC_E, R(result));
|
||||
code->MOVZX(32, 8, result, R(result));
|
||||
}
|
||||
|
||||
void EmitX64::EmitLogicalShiftLeft(IR::Block& block, IR::Inst* inst) {
|
||||
auto carry_inst = FindUseWithOpcode(inst, IR::Opcode::GetCarryFromOp);
|
||||
|
||||
|
|
@ -706,6 +733,16 @@ void EmitX64::EmitAddWithCarry(IR::Block& block, IR::Inst* inst) {
|
|||
}
|
||||
}
|
||||
|
||||
void EmitX64::EmitAdd64(IR::Block& block, IR::Inst* inst) {
|
||||
IR::Value a = inst->GetArg(0);
|
||||
IR::Value b = inst->GetArg(1);
|
||||
|
||||
X64Reg result = reg_alloc.UseDefRegister(a, inst, any_gpr);
|
||||
OpArg op_arg = R(reg_alloc.UseRegister(b, any_gpr));
|
||||
|
||||
code->ADD(64, R(result), op_arg);
|
||||
}
|
||||
|
||||
void EmitX64::EmitSubWithCarry(IR::Block& block, IR::Inst* inst) {
|
||||
auto carry_inst = FindUseWithOpcode(inst, IR::Opcode::GetCarryFromOp);
|
||||
auto overflow_inst = FindUseWithOpcode(inst, IR::Opcode::GetOverflowFromOp);
|
||||
|
|
@ -751,6 +788,28 @@ void EmitX64::EmitSubWithCarry(IR::Block& block, IR::Inst* inst) {
|
|||
}
|
||||
}
|
||||
|
||||
void EmitX64::EmitMul(IR::Block&, IR::Inst* inst) {
|
||||
IR::Value a = inst->GetArg(0);
|
||||
IR::Value b = inst->GetArg(1);
|
||||
if (a.IsImmediate())
|
||||
std::swap(a, b);
|
||||
X64Reg result = reg_alloc.UseDefRegister(a, inst, any_gpr);
|
||||
if (b.IsImmediate()) {
|
||||
code->IMUL(32, result, R(result), Imm32(b.GetU32()));
|
||||
} else {
|
||||
OpArg op_arg = R(reg_alloc.UseRegister(b.GetInst(), any_gpr));
|
||||
code->IMUL(32, result, op_arg);
|
||||
}
|
||||
}
|
||||
|
||||
void EmitX64::EmitMul64(IR::Block&, IR::Inst* inst) {
|
||||
IR::Value a = inst->GetArg(0);
|
||||
IR::Value b = inst->GetArg(1);
|
||||
X64Reg result = reg_alloc.UseDefRegister(a, inst, any_gpr);
|
||||
OpArg op_arg = R(reg_alloc.UseRegister(b.GetInst(), any_gpr));
|
||||
code->IMUL(64, result, op_arg);
|
||||
}
|
||||
|
||||
void EmitX64::EmitAnd(IR::Block&, IR::Inst* inst) {
|
||||
IR::Value a = inst->GetArg(0);
|
||||
IR::Value b = inst->GetArg(1);
|
||||
|
|
@ -801,6 +860,13 @@ void EmitX64::EmitNot(IR::Block&, IR::Inst* inst) {
|
|||
}
|
||||
}
|
||||
|
||||
void EmitX64::EmitSignExtendWordToLong(IR::Block&, IR::Inst* inst) {
|
||||
// TODO: Remove unnecessary mov that may occur here
|
||||
X64Reg result = reg_alloc.UseDefRegister(inst->GetArg(0), inst, any_gpr);
|
||||
|
||||
code->MOVSX(64, 32, result, R(result));
|
||||
}
|
||||
|
||||
void EmitX64::EmitSignExtendHalfToWord(IR::Block&, IR::Inst* inst) {
|
||||
// TODO: Remove unnecessary mov that may occur here
|
||||
X64Reg result = reg_alloc.UseDefRegister(inst->GetArg(0), inst, any_gpr);
|
||||
|
|
@ -815,6 +881,13 @@ void EmitX64::EmitSignExtendByteToWord(IR::Block&, IR::Inst* inst) {
|
|||
code->MOVSX(32, 8, result, R(result));
|
||||
}
|
||||
|
||||
void EmitX64::EmitZeroExtendWordToLong(IR::Block&, IR::Inst* inst) {
|
||||
// TODO: Remove unnecessary mov that may occur here
|
||||
X64Reg result = reg_alloc.UseDefRegister(inst->GetArg(0), inst, any_gpr);
|
||||
|
||||
code->MOVZX(64, 32, result, R(result));
|
||||
}
|
||||
|
||||
void EmitX64::EmitZeroExtendHalfToWord(IR::Block&, IR::Inst* inst) {
|
||||
// TODO: Remove unnecessary mov that may occur here
|
||||
X64Reg result = reg_alloc.UseDefRegister(inst->GetArg(0), inst, any_gpr);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue