diff --git a/src/backend_x64/a32_emit_x64.h b/src/backend_x64/a32_emit_x64.h index 1ba10595..013d0222 100644 --- a/src/backend_x64/a32_emit_x64.h +++ b/src/backend_x64/a32_emit_x64.h @@ -34,7 +34,7 @@ struct A32EmitContext final : public EmitContext { bool FPSCR_DN() const override; }; -class A32EmitX64 final : public EmitX64 { +class A32EmitX64 final : public EmitX64 { public: A32EmitX64(BlockOfCode* code, UserCallbacks cb, Jit* jit_interface); ~A32EmitX64(); diff --git a/src/backend_x64/a32_jitstate.h b/src/backend_x64/a32_jitstate.h index 7fe6df63..9331b5d2 100644 --- a/src/backend_x64/a32_jitstate.h +++ b/src/backend_x64/a32_jitstate.h @@ -23,6 +23,8 @@ constexpr size_t SpillCount = 64; #endif struct A32JitState { + using ProgramCounterType = u32; + A32JitState() { ResetRSB(); } std::array Reg{}; // Current register file. diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index d1d8640b..ce945adf 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -49,41 +49,41 @@ void EmitContext::EraseInstruction(IR::Inst* inst) { inst->Invalidate(); } -template -EmitX64::EmitX64(BlockOfCode* code, UserCallbacks cb, Jit* jit_interface) +template +EmitX64::EmitX64(BlockOfCode* code, UserCallbacks cb, Jit* jit_interface) : code(code), cb(cb), jit_interface(jit_interface) { } -template -EmitX64::~EmitX64() {} +template +EmitX64::~EmitX64() {} -template -boost::optional::BlockDescriptor> EmitX64::GetBasicBlock(IR::LocationDescriptor descriptor) const { +template +boost::optional::BlockDescriptor> EmitX64::GetBasicBlock(IR::LocationDescriptor descriptor) const { auto iter = block_descriptors.find(descriptor); if (iter == block_descriptors.end()) return boost::none; return iter->second; } -template -void EmitX64::EmitVoid(EmitContext&, IR::Inst*) { +template +void EmitX64::EmitVoid(EmitContext&, IR::Inst*) { } -template -void EmitX64::EmitBreakpoint(EmitContext&, IR::Inst*) { +template +void EmitX64::EmitBreakpoint(EmitContext&, IR::Inst*) { code->int3(); } -template -void EmitX64::EmitIdentity(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitIdentity(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); if (!args[0].IsImmediate()) { ctx.reg_alloc.DefineValue(inst, args[0]); } } -template -void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target) { +template +void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target) { using namespace Xbyak::util; auto iter = block_descriptors.find(target); @@ -91,23 +91,23 @@ void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_r ? iter->second.entrypoint : code->GetReturnFromRunCodeAddress(); - code->mov(index_reg.cvt32(), dword[r15 + offsetof(A32JitState, rsb_ptr)]); + code->mov(index_reg.cvt32(), dword[r15 + offsetof(JST, rsb_ptr)]); code->mov(loc_desc_reg, target.Value()); patch_information[target].mov_rcx.emplace_back(code->getCurr()); EmitPatchMovRcx(target_code_ptr); - code->mov(qword[r15 + index_reg * 8 + offsetof(A32JitState, rsb_location_descriptors)], loc_desc_reg); - code->mov(qword[r15 + index_reg * 8 + offsetof(A32JitState, rsb_codeptrs)], rcx); + code->mov(qword[r15 + index_reg * 8 + offsetof(JST, rsb_location_descriptors)], loc_desc_reg); + code->mov(qword[r15 + index_reg * 8 + offsetof(JST, rsb_codeptrs)], rcx); code->add(index_reg.cvt32(), 1); - code->and_(index_reg.cvt32(), u32(A32JitState::RSBPtrMask)); - code->mov(dword[r15 + offsetof(A32JitState, rsb_ptr)], index_reg.cvt32()); + code->and_(index_reg.cvt32(), u32(JST::RSBPtrMask)); + code->mov(dword[r15 + offsetof(JST, rsb_ptr)], index_reg.cvt32()); } -template -void EmitX64::EmitPushRSB(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPushRSB(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ASSERT(args[0].IsImmediate()); u64 unique_hash_of_target = args[0].GetImmediateU64(); @@ -119,23 +119,23 @@ void EmitX64::EmitPushRSB(EmitContext& ctx, IR::Inst* inst) { PushRSBHelper(loc_desc_reg, index_reg, IR::LocationDescriptor{unique_hash_of_target}); } -template -void EmitX64::EmitGetCarryFromOp(EmitContext&, IR::Inst*) { +template +void EmitX64::EmitGetCarryFromOp(EmitContext&, IR::Inst*) { ASSERT_MSG(false, "should never happen"); } -template -void EmitX64::EmitGetOverflowFromOp(EmitContext&, IR::Inst*) { +template +void EmitX64::EmitGetOverflowFromOp(EmitContext&, IR::Inst*) { ASSERT_MSG(false, "should never happen"); } -template -void EmitX64::EmitGetGEFromOp(EmitContext&, IR::Inst*) { +template +void EmitX64::EmitGetGEFromOp(EmitContext&, IR::Inst*) { ASSERT_MSG(false, "should never happen"); } -template -void EmitX64::EmitPack2x32To1x64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPack2x32To1x64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 lo = ctx.reg_alloc.UseScratchGpr(args[0]); Xbyak::Reg64 hi = ctx.reg_alloc.UseScratchGpr(args[1]); @@ -147,14 +147,14 @@ void EmitX64::EmitPack2x32To1x64(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, lo); } -template -void EmitX64::EmitLeastSignificantWord(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitLeastSignificantWord(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.DefineValue(inst, args[0]); } -template -void EmitX64::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) { auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -171,20 +171,20 @@ void EmitX64::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitLeastSignificantHalf(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitLeastSignificantHalf(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.DefineValue(inst, args[0]); } -template -void EmitX64::EmitLeastSignificantByte(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitLeastSignificantByte(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.DefineValue(inst, args[0]); } -template -void EmitX64::EmitMostSignificantBit(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitMostSignificantBit(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); // TODO: Flag optimization @@ -192,8 +192,8 @@ void EmitX64::EmitMostSignificantBit(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitIsZero(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitIsZero(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); // TODO: Flag optimization @@ -203,8 +203,8 @@ void EmitX64::EmitIsZero(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitIsZero64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitIsZero64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); // TODO: Flag optimization @@ -214,8 +214,8 @@ void EmitX64::EmitIsZero64(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitLogicalShiftLeft(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitLogicalShiftLeft(EmitContext& ctx, IR::Inst* inst) { auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -315,8 +315,8 @@ void EmitX64::EmitLogicalShiftLeft(EmitContext& ctx, IR::Inst* inst) { } } -template -void EmitX64::EmitLogicalShiftRight(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitLogicalShiftRight(EmitContext& ctx, IR::Inst* inst) { auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -415,8 +415,8 @@ void EmitX64::EmitLogicalShiftRight(EmitContext& ctx, IR::Inst* inst) { } } -template -void EmitX64::EmitLogicalShiftRight64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitLogicalShiftRight64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto& operand_arg = args[0]; auto& shift_arg = args[1]; @@ -432,8 +432,8 @@ void EmitX64::EmitLogicalShiftRight64(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitArithmeticShiftRight(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitArithmeticShiftRight(EmitContext& ctx, IR::Inst* inst) { auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -521,8 +521,8 @@ void EmitX64::EmitArithmeticShiftRight(EmitContext& ctx, IR::Inst* inst) { } } -template -void EmitX64::EmitRotateRight(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitRotateRight(EmitContext& ctx, IR::Inst* inst) { auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -601,8 +601,8 @@ void EmitX64::EmitRotateRight(EmitContext& ctx, IR::Inst* inst) { } } -template -void EmitX64::EmitRotateRightExtended(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitRotateRightExtended(EmitContext& ctx, IR::Inst* inst) { auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -634,8 +634,8 @@ static Xbyak::Reg8 DoCarry(RegAlloc& reg_alloc, Argument& carry_in, IR::Inst* ca } } -template -void EmitX64::EmitAddWithCarry(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitAddWithCarry(EmitContext& ctx, IR::Inst* inst) { auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); @@ -691,8 +691,8 @@ void EmitX64::EmitAddWithCarry(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitAdd64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitAdd64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); @@ -703,8 +703,8 @@ void EmitX64::EmitAdd64(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitSubWithCarry(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitSubWithCarry(EmitContext& ctx, IR::Inst* inst) { auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp); auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); @@ -764,8 +764,8 @@ void EmitX64::EmitSubWithCarry(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitSub64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitSub64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); @@ -776,8 +776,8 @@ void EmitX64::EmitSub64(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitMul(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitMul(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); @@ -792,8 +792,8 @@ void EmitX64::EmitMul(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitMul64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitMul64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); @@ -804,8 +804,8 @@ void EmitX64::EmitMul64(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitAnd(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitAnd(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); @@ -824,8 +824,8 @@ void EmitX64::EmitAnd(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitEor(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitEor(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); @@ -844,8 +844,8 @@ void EmitX64::EmitEor(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitOr(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitOr(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); @@ -864,8 +864,8 @@ void EmitX64::EmitOr(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitNot(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitNot(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 result; @@ -879,80 +879,80 @@ void EmitX64::EmitNot(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitSignExtendWordToLong(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitSignExtendWordToLong(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); code->movsxd(result.cvt64(), result.cvt32()); ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitSignExtendHalfToWord(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitSignExtendHalfToWord(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); code->movsx(result.cvt32(), result.cvt16()); ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitSignExtendByteToWord(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitSignExtendByteToWord(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); code->movsx(result.cvt32(), result.cvt8()); ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitZeroExtendWordToLong(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitZeroExtendWordToLong(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); code->mov(result.cvt32(), result.cvt32()); // x64 zeros upper 32 bits on a 32-bit move ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitZeroExtendHalfToWord(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitZeroExtendHalfToWord(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); code->movzx(result.cvt32(), result.cvt16()); ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitZeroExtendByteToWord(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitZeroExtendByteToWord(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); code->movzx(result.cvt32(), result.cvt8()); ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitByteReverseWord(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitByteReverseWord(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); code->bswap(result); ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitByteReverseHalf(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitByteReverseHalf(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg16 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt16(); code->rol(result, 8); ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitByteReverseDual(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitByteReverseDual(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]); code->bswap(result); ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitCountLeadingZeros(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitCountLeadingZeros(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); if (code->DoesCpuSupport(Xbyak::util::Cpu::tLZCNT)) { Xbyak::Reg32 source = ctx.reg_alloc.UseGpr(args[0]).cvt32(); @@ -976,8 +976,8 @@ void EmitX64::EmitCountLeadingZeros(EmitContext& ctx, IR::Inst* inst) { } } -template -void EmitX64::EmitSignedSaturatedAdd(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitSignedSaturatedAdd(EmitContext& ctx, IR::Inst* inst) { auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -1004,8 +1004,8 @@ void EmitX64::EmitSignedSaturatedAdd(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitSignedSaturatedSub(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitSignedSaturatedSub(EmitContext& ctx, IR::Inst* inst) { auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -1032,8 +1032,8 @@ void EmitX64::EmitSignedSaturatedSub(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) { auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -1064,8 +1064,8 @@ void EmitX64::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) { auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp); auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -1115,8 +1115,8 @@ void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); @@ -1144,8 +1144,8 @@ void EmitX64::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); @@ -1173,8 +1173,8 @@ void EmitX64::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); @@ -1216,8 +1216,8 @@ void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); @@ -1245,8 +1245,8 @@ void EmitX64::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); @@ -1270,8 +1270,8 @@ void EmitX64::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); @@ -1299,8 +1299,8 @@ void EmitX64::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); @@ -1339,8 +1339,8 @@ void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp); @@ -1368,8 +1368,8 @@ void EmitX64::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedHalvingAddU8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingAddU8(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); if (args[0].IsInXmm() || args[1].IsInXmm()) { @@ -1412,8 +1412,8 @@ void EmitX64::EmitPackedHalvingAddU8(EmitContext& ctx, IR::Inst* inst) { } } -template -void EmitX64::EmitPackedHalvingAddU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingAddU16(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); if (args[0].IsInXmm() || args[1].IsInXmm()) { @@ -1451,8 +1451,8 @@ void EmitX64::EmitPackedHalvingAddU16(EmitContext& ctx, IR::Inst* inst) { } } -template -void EmitX64::EmitPackedHalvingAddS8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingAddS8(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 reg_a = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); @@ -1481,8 +1481,8 @@ void EmitX64::EmitPackedHalvingAddS8(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitPackedHalvingAddS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingAddS16(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]); @@ -1503,8 +1503,8 @@ void EmitX64::EmitPackedHalvingAddS16(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedHalvingSubU8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingSubU8(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 minuend = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); @@ -1534,8 +1534,8 @@ void EmitX64::EmitPackedHalvingSubU8(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, minuend); } -template -void EmitX64::EmitPackedHalvingSubS8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingSubS8(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 minuend = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32(); @@ -1571,8 +1571,8 @@ void EmitX64::EmitPackedHalvingSubS8(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, minuend); } -template -void EmitX64::EmitPackedHalvingSubU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingSubU16(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm minuend = ctx.reg_alloc.UseScratchXmm(args[0]); @@ -1595,8 +1595,8 @@ void EmitX64::EmitPackedHalvingSubU16(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, minuend); } -template -void EmitX64::EmitPackedHalvingSubS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingSubS16(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm minuend = ctx.reg_alloc.UseScratchXmm(args[0]); @@ -1693,43 +1693,43 @@ void EmitPackedSubAdd(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, bool ctx.reg_alloc.DefineValue(inst, reg_a_hi); } -template -void EmitX64::EmitPackedAddSubU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedAddSubU16(EmitContext& ctx, IR::Inst* inst) { EmitPackedSubAdd(code, ctx, inst, true, false, false); } -template -void EmitX64::EmitPackedAddSubS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedAddSubS16(EmitContext& ctx, IR::Inst* inst) { EmitPackedSubAdd(code, ctx, inst, true, true, false); } -template -void EmitX64::EmitPackedSubAddU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSubAddU16(EmitContext& ctx, IR::Inst* inst) { EmitPackedSubAdd(code, ctx, inst, false, false, false); } -template -void EmitX64::EmitPackedSubAddS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSubAddS16(EmitContext& ctx, IR::Inst* inst) { EmitPackedSubAdd(code, ctx, inst, false, true, false); } -template -void EmitX64::EmitPackedHalvingAddSubU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingAddSubU16(EmitContext& ctx, IR::Inst* inst) { EmitPackedSubAdd(code, ctx, inst, true, false, true); } -template -void EmitX64::EmitPackedHalvingAddSubS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingAddSubS16(EmitContext& ctx, IR::Inst* inst) { EmitPackedSubAdd(code, ctx, inst, true, true, true); } -template -void EmitX64::EmitPackedHalvingSubAddU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingSubAddU16(EmitContext& ctx, IR::Inst* inst) { EmitPackedSubAdd(code, ctx, inst, false, false, true); } -template -void EmitX64::EmitPackedHalvingSubAddS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedHalvingSubAddS16(EmitContext& ctx, IR::Inst* inst) { EmitPackedSubAdd(code, ctx, inst, false, true, true); } @@ -1744,53 +1744,53 @@ static void EmitPackedOperation(BlockOfCode* code, EmitContext& ctx, IR::Inst* i ctx.reg_alloc.DefineValue(inst, xmm_a); } -template -void EmitX64::EmitPackedSaturatedAddU8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSaturatedAddU8(EmitContext& ctx, IR::Inst* inst) { EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddusb); } -template -void EmitX64::EmitPackedSaturatedAddS8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSaturatedAddS8(EmitContext& ctx, IR::Inst* inst) { EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddsb); } -template -void EmitX64::EmitPackedSaturatedSubU8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSaturatedSubU8(EmitContext& ctx, IR::Inst* inst) { EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubusb); } -template -void EmitX64::EmitPackedSaturatedSubS8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSaturatedSubS8(EmitContext& ctx, IR::Inst* inst) { EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubsb); } -template -void EmitX64::EmitPackedSaturatedAddU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSaturatedAddU16(EmitContext& ctx, IR::Inst* inst) { EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddusw); } -template -void EmitX64::EmitPackedSaturatedAddS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSaturatedAddS16(EmitContext& ctx, IR::Inst* inst) { EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::paddsw); } -template -void EmitX64::EmitPackedSaturatedSubU16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSaturatedSubU16(EmitContext& ctx, IR::Inst* inst) { EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubusw); } -template -void EmitX64::EmitPackedSaturatedSubS16(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSaturatedSubS16(EmitContext& ctx, IR::Inst* inst) { EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psubsw); } -template -void EmitX64::EmitPackedAbsDiffSumS8(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedAbsDiffSumS8(EmitContext& ctx, IR::Inst* inst) { EmitPackedOperation(code, ctx, inst, &Xbyak::CodeGenerator::psadbw); } -template -void EmitX64::EmitPackedSelect(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitPackedSelect(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); size_t num_args_in_xmm = args[0].IsInXmm() + args[1].IsInXmm() + args[2].IsInXmm(); @@ -1829,6 +1829,7 @@ void EmitX64::EmitPackedSelect(EmitContext& ctx, IR::Inst* inst) { } } +template static void DenormalsAreZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg32 gpr_scratch) { Xbyak::Label end; @@ -1841,10 +1842,11 @@ static void DenormalsAreZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::R code->cmp(gpr_scratch, u32(0x007FFFFE)); code->ja(end); code->pxor(xmm_value, xmm_value); - code->mov(dword[r15 + offsetof(A32JitState, FPSCR_IDC)], u32(1 << 7)); + code->mov(dword[r15 + offsetof(JST, FPSCR_IDC)], u32(1 << 7)); code->L(end); } +template static void DenormalsAreZero64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg64 gpr_scratch) { Xbyak::Label end; @@ -1859,10 +1861,11 @@ static void DenormalsAreZero64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::R code->cmp(gpr_scratch, penult_denormal); code->ja(end); code->pxor(xmm_value, xmm_value); - code->mov(dword[r15 + offsetof(A32JitState, FPSCR_IDC)], u32(1 << 7)); + code->mov(dword[r15 + offsetof(JST, FPSCR_IDC)], u32(1 << 7)); code->L(end); } +template static void FlushToZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg32 gpr_scratch) { Xbyak::Label end; @@ -1872,10 +1875,11 @@ static void FlushToZero32(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg32 code->cmp(gpr_scratch, u32(0x007FFFFE)); code->ja(end); code->pxor(xmm_value, xmm_value); - code->mov(dword[r15 + offsetof(A32JitState, FPSCR_UFC)], u32(1 << 3)); + code->mov(dword[r15 + offsetof(JST, FPSCR_UFC)], u32(1 << 3)); code->L(end); } +template static void FlushToZero64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg64 gpr_scratch) { Xbyak::Label end; @@ -1890,7 +1894,7 @@ static void FlushToZero64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Reg64 code->cmp(gpr_scratch, penult_denormal); code->ja(end); code->pxor(xmm_value, xmm_value); - code->mov(dword[r15 + offsetof(A32JitState, FPSCR_UFC)], u32(1 << 3)); + code->mov(dword[r15 + offsetof(JST, FPSCR_UFC)], u32(1 << 3)); code->L(end); } @@ -1918,6 +1922,7 @@ static void ZeroIfNaN64(BlockOfCode* code, Xbyak::Xmm xmm_value, Xbyak::Xmm xmm_ code->pand(xmm_value, xmm_scratch); } +template static void FPThreeOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -1926,12 +1931,12 @@ static void FPThreeOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, voi Xbyak::Reg32 gpr_scratch = ctx.reg_alloc.ScratchGpr().cvt32(); if (ctx.FPSCR_FTZ()) { - DenormalsAreZero32(code, result, gpr_scratch); - DenormalsAreZero32(code, operand, gpr_scratch); + DenormalsAreZero32(code, result, gpr_scratch); + DenormalsAreZero32(code, operand, gpr_scratch); } (code->*fn)(result, operand); if (ctx.FPSCR_FTZ()) { - FlushToZero32(code, result, gpr_scratch); + FlushToZero32(code, result, gpr_scratch); } if (ctx.FPSCR_DN()) { DefaultNaN32(code, result); @@ -1940,6 +1945,7 @@ static void FPThreeOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, voi ctx.reg_alloc.DefineValue(inst, result); } +template static void FPThreeOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -1948,12 +1954,12 @@ static void FPThreeOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, voi Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr(); if (ctx.FPSCR_FTZ()) { - DenormalsAreZero64(code, result, gpr_scratch); - DenormalsAreZero64(code, operand, gpr_scratch); + DenormalsAreZero64(code, result, gpr_scratch); + DenormalsAreZero64(code, operand, gpr_scratch); } (code->*fn)(result, operand); if (ctx.FPSCR_FTZ()) { - FlushToZero64(code, result, gpr_scratch); + FlushToZero64(code, result, gpr_scratch); } if (ctx.FPSCR_DN()) { DefaultNaN64(code, result); @@ -1962,6 +1968,7 @@ static void FPThreeOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, voi ctx.reg_alloc.DefineValue(inst, result); } +template static void FPTwoOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -1969,12 +1976,12 @@ static void FPTwoOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void Xbyak::Reg32 gpr_scratch = ctx.reg_alloc.ScratchGpr().cvt32(); if (ctx.FPSCR_FTZ()) { - DenormalsAreZero32(code, result, gpr_scratch); + DenormalsAreZero32(code, result, gpr_scratch); } (code->*fn)(result, result); if (ctx.FPSCR_FTZ()) { - FlushToZero32(code, result, gpr_scratch); + FlushToZero32(code, result, gpr_scratch); } if (ctx.FPSCR_DN()) { DefaultNaN32(code, result); @@ -1983,6 +1990,7 @@ static void FPTwoOp32(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void ctx.reg_alloc.DefineValue(inst, result); } +template static void FPTwoOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void (Xbyak::CodeGenerator::*fn)(const Xbyak::Xmm&, const Xbyak::Operand&)) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); @@ -1990,12 +1998,12 @@ static void FPTwoOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr(); if (ctx.FPSCR_FTZ()) { - DenormalsAreZero64(code, result, gpr_scratch); + DenormalsAreZero64(code, result, gpr_scratch); } (code->*fn)(result, result); if (ctx.FPSCR_FTZ()) { - FlushToZero64(code, result, gpr_scratch); + FlushToZero64(code, result, gpr_scratch); } if (ctx.FPSCR_DN()) { DefaultNaN64(code, result); @@ -2004,20 +2012,20 @@ static void FPTwoOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitTransferFromFP32(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitTransferFromFP32(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.DefineValue(inst, args[0]); } -template -void EmitX64::EmitTransferFromFP64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitTransferFromFP64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.DefineValue(inst, args[0]); } -template -void EmitX64::EmitTransferToFP32(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitTransferToFP32(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); if (args[0].IsImmediate() && args[0].GetImmediateU32() == 0) { Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); @@ -2028,8 +2036,8 @@ void EmitX64::EmitTransferToFP32(EmitContext& ctx, IR::Inst* inst) { } } -template -void EmitX64::EmitTransferToFP64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitTransferToFP64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); if (args[0].IsImmediate() && args[0].GetImmediateU64() == 0) { Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); @@ -2040,8 +2048,8 @@ void EmitX64::EmitTransferToFP64(EmitContext& ctx, IR::Inst* inst) { } } -template -void EmitX64::EmitFPAbs32(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPAbs32(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); @@ -2050,8 +2058,8 @@ void EmitX64::EmitFPAbs32(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitFPAbs64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPAbs64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); @@ -2060,8 +2068,8 @@ void EmitX64::EmitFPAbs64(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitFPNeg32(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPNeg32(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); @@ -2070,8 +2078,8 @@ void EmitX64::EmitFPNeg32(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitFPNeg64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPNeg64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); @@ -2080,56 +2088,57 @@ void EmitX64::EmitFPNeg64(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitFPAdd32(EmitContext& ctx, IR::Inst* inst) { - FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::addss); +template +void EmitX64::EmitFPAdd32(EmitContext& ctx, IR::Inst* inst) { + FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::addss); } -template -void EmitX64::EmitFPAdd64(EmitContext& ctx, IR::Inst* inst) { - FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::addsd); +template +void EmitX64::EmitFPAdd64(EmitContext& ctx, IR::Inst* inst) { + FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::addsd); } -template -void EmitX64::EmitFPDiv32(EmitContext& ctx, IR::Inst* inst) { - FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::divss); +template +void EmitX64::EmitFPDiv32(EmitContext& ctx, IR::Inst* inst) { + FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::divss); } -template -void EmitX64::EmitFPDiv64(EmitContext& ctx, IR::Inst* inst) { - FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::divsd); +template +void EmitX64::EmitFPDiv64(EmitContext& ctx, IR::Inst* inst) { + FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::divsd); } -template -void EmitX64::EmitFPMul32(EmitContext& ctx, IR::Inst* inst) { - FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::mulss); +template +void EmitX64::EmitFPMul32(EmitContext& ctx, IR::Inst* inst) { + FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::mulss); } -template -void EmitX64::EmitFPMul64(EmitContext& ctx, IR::Inst* inst) { - FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::mulsd); +template +void EmitX64::EmitFPMul64(EmitContext& ctx, IR::Inst* inst) { + FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::mulsd); } -template -void EmitX64::EmitFPSqrt32(EmitContext& ctx, IR::Inst* inst) { - FPTwoOp32(code, ctx, inst, &Xbyak::CodeGenerator::sqrtss); +template +void EmitX64::EmitFPSqrt32(EmitContext& ctx, IR::Inst* inst) { + FPTwoOp32(code, ctx, inst, &Xbyak::CodeGenerator::sqrtss); } -template -void EmitX64::EmitFPSqrt64(EmitContext& ctx, IR::Inst* inst) { - FPTwoOp64(code, ctx, inst, &Xbyak::CodeGenerator::sqrtsd); +template +void EmitX64::EmitFPSqrt64(EmitContext& ctx, IR::Inst* inst) { + FPTwoOp64(code, ctx, inst, &Xbyak::CodeGenerator::sqrtsd); } -template -void EmitX64::EmitFPSub32(EmitContext& ctx, IR::Inst* inst) { - FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::subss); +template +void EmitX64::EmitFPSub32(EmitContext& ctx, IR::Inst* inst) { + FPThreeOp32(code, ctx, inst, &Xbyak::CodeGenerator::subss); } -template -void EmitX64::EmitFPSub64(EmitContext& ctx, IR::Inst* inst) { - FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::subsd); +template +void EmitX64::EmitFPSub64(EmitContext& ctx, IR::Inst* inst) { + FPThreeOp64(code, ctx, inst, &Xbyak::CodeGenerator::subsd); } +template static void SetFpscrNzcvFromFlags(BlockOfCode* code, EmitContext& ctx) { ctx.reg_alloc.ScratchGpr({HostLoc::RCX}); // shifting requires use of cl Xbyak::Reg32 nzcv = ctx.reg_alloc.ScratchGpr().cvt32(); @@ -2139,11 +2148,11 @@ static void SetFpscrNzcvFromFlags(BlockOfCode* code, EmitContext& ctx) { code->rcl(cl, 3); code->shl(nzcv, cl); code->and_(nzcv, 0xF0000000); - code->mov(dword[r15 + offsetof(A32JitState, FPSCR_nzcv)], nzcv); + code->mov(dword[r15 + offsetof(JST, FPSCR_nzcv)], nzcv); } -template -void EmitX64::EmitFPCompare32(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPCompare32(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm reg_a = ctx.reg_alloc.UseXmm(args[0]); Xbyak::Xmm reg_b = ctx.reg_alloc.UseXmm(args[1]); @@ -2155,11 +2164,11 @@ void EmitX64::EmitFPCompare32(EmitContext& ctx, IR::Inst* inst) { code->ucomiss(reg_a, reg_b); } - SetFpscrNzcvFromFlags(code, ctx); + SetFpscrNzcvFromFlags(code, ctx); } -template -void EmitX64::EmitFPCompare64(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPCompare64(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm reg_a = ctx.reg_alloc.UseXmm(args[0]); Xbyak::Xmm reg_b = ctx.reg_alloc.UseXmm(args[1]); @@ -2171,21 +2180,21 @@ void EmitX64::EmitFPCompare64(EmitContext& ctx, IR::Inst* inst) { code->ucomisd(reg_a, reg_b); } - SetFpscrNzcvFromFlags(code, ctx); + SetFpscrNzcvFromFlags(code, ctx); } -template -void EmitX64::EmitFPSingleToDouble(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPSingleToDouble(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr(); if (ctx.FPSCR_FTZ()) { - DenormalsAreZero32(code, result, gpr_scratch.cvt32()); + DenormalsAreZero32(code, result, gpr_scratch.cvt32()); } code->cvtss2sd(result, result); if (ctx.FPSCR_FTZ()) { - FlushToZero64(code, result, gpr_scratch); + FlushToZero64(code, result, gpr_scratch); } if (ctx.FPSCR_DN()) { DefaultNaN64(code, result); @@ -2194,18 +2203,18 @@ void EmitX64::EmitFPSingleToDouble(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Reg64 gpr_scratch = ctx.reg_alloc.ScratchGpr(); if (ctx.FPSCR_FTZ()) { - DenormalsAreZero64(code, result, gpr_scratch); + DenormalsAreZero64(code, result, gpr_scratch); } code->cvtsd2ss(result, result); if (ctx.FPSCR_FTZ()) { - FlushToZero32(code, result, gpr_scratch.cvt32()); + FlushToZero32(code, result, gpr_scratch.cvt32()); } if (ctx.FPSCR_DN()) { DefaultNaN32(code, result); @@ -2214,8 +2223,8 @@ void EmitX64::EmitFPDoubleToSingle(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, result); } -template -void EmitX64::EmitFPSingleToS32(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPSingleToS32(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32(); @@ -2226,7 +2235,7 @@ void EmitX64::EmitFPSingleToS32(EmitContext& ctx, IR::Inst* inst) { // Conversion to double is lossless, and allows for clamping. if (ctx.FPSCR_FTZ()) { - DenormalsAreZero32(code, from, to); + DenormalsAreZero32(code, from, to); } code->cvtss2sd(from, from); // First time is to set flags @@ -2249,8 +2258,8 @@ void EmitX64::EmitFPSingleToS32(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, to); } -template -void EmitX64::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32(); @@ -2266,7 +2275,7 @@ void EmitX64::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) { if (!ctx.FPSCR_RoundTowardsZero() && !round_towards_zero) { if (ctx.FPSCR_FTZ()) { - DenormalsAreZero32(code, from, to); + DenormalsAreZero32(code, from, to); } code->cvtss2sd(from, from); ZeroIfNaN64(code, from, xmm_scratch); @@ -2286,7 +2295,7 @@ void EmitX64::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) { Xbyak::Reg32 gpr_mask = ctx.reg_alloc.ScratchGpr().cvt32(); if (ctx.FPSCR_FTZ()) { - DenormalsAreZero32(code, from, to); + DenormalsAreZero32(code, from, to); } code->cvtss2sd(from, from); ZeroIfNaN64(code, from, xmm_scratch); @@ -2312,8 +2321,8 @@ void EmitX64::EmitFPSingleToU32(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, to); } -template -void EmitX64::EmitFPDoubleToS32(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPDoubleToS32(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32(); @@ -2324,7 +2333,7 @@ void EmitX64::EmitFPDoubleToS32(EmitContext& ctx, IR::Inst* inst) { // ARM saturates on conversion; this differs from x64 which returns a sentinel value. if (ctx.FPSCR_FTZ()) { - DenormalsAreZero64(code, from, gpr_scratch.cvt64()); + DenormalsAreZero64(code, from, gpr_scratch.cvt64()); } // First time is to set flags if (round_towards_zero) { @@ -2346,8 +2355,8 @@ void EmitX64::EmitFPDoubleToS32(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, to); } -template -void EmitX64::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Xmm from = ctx.reg_alloc.UseScratchXmm(args[0]); Xbyak::Reg32 to = ctx.reg_alloc.ScratchGpr().cvt32(); @@ -2361,7 +2370,7 @@ void EmitX64::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) { if (!ctx.FPSCR_RoundTowardsZero() && !round_towards_zero) { if (ctx.FPSCR_FTZ()) { - DenormalsAreZero64(code, from, gpr_scratch.cvt64()); + DenormalsAreZero64(code, from, gpr_scratch.cvt64()); } ZeroIfNaN64(code, from, xmm_scratch); // Bring into SSE range @@ -2380,7 +2389,7 @@ void EmitX64::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) { Xbyak::Reg32 gpr_mask = ctx.reg_alloc.ScratchGpr().cvt32(); if (ctx.FPSCR_FTZ()) { - DenormalsAreZero64(code, from, gpr_scratch.cvt64()); + DenormalsAreZero64(code, from, gpr_scratch.cvt64()); } ZeroIfNaN64(code, from, xmm_scratch); // Generate masks if out-of-signed-range @@ -2405,8 +2414,8 @@ void EmitX64::EmitFPDoubleToU32(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, to); } -template -void EmitX64::EmitFPS32ToSingle(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPS32ToSingle(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32(); Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); @@ -2418,8 +2427,8 @@ void EmitX64::EmitFPS32ToSingle(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, to); } -template -void EmitX64::EmitFPU32ToSingle(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPU32ToSingle(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); @@ -2433,8 +2442,8 @@ void EmitX64::EmitFPU32ToSingle(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, to); } -template -void EmitX64::EmitFPS32ToDouble(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPS32ToDouble(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32(); Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); @@ -2446,8 +2455,8 @@ void EmitX64::EmitFPS32ToDouble(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, to); } -template -void EmitX64::EmitFPU32ToDouble(EmitContext& ctx, IR::Inst* inst) { +template +void EmitX64::EmitFPU32ToDouble(EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); @@ -2461,18 +2470,18 @@ void EmitX64::EmitFPU32ToDouble(EmitContext& ctx, IR::Inst* inst) { ctx.reg_alloc.DefineValue(inst, to); } -template -void EmitX64::EmitAddCycles(size_t cycles) { +template +void EmitX64::EmitAddCycles(size_t cycles) { ASSERT(cycles < std::numeric_limits::max()); - code->sub(qword[r15 + offsetof(A32JitState, cycles_remaining)], static_cast(cycles)); + code->sub(qword[r15 + offsetof(JST, cycles_remaining)], static_cast(cycles)); } -template -Xbyak::Label EmitX64::EmitCond(IR::Cond cond) { +template +Xbyak::Label EmitX64::EmitCond(IR::Cond cond) { Xbyak::Label label; const Xbyak::Reg32 cpsr = eax; - code->mov(cpsr, dword[r15 + offsetof(A32JitState, CPSR_nzcv)]); + code->mov(cpsr, dword[r15 + offsetof(JST, CPSR_nzcv)]); constexpr size_t n_shift = 31; constexpr size_t z_shift = 30; @@ -2580,8 +2589,8 @@ Xbyak::Label EmitX64::EmitCond(IR::Cond cond) { return label; } -template -void EmitX64::EmitCondPrelude(const IR::Block& block) { +template +void EmitX64::EmitCondPrelude(const IR::Block& block) { if (block.GetCondition() == IR::Cond::AL) { ASSERT(!block.HasConditionFailedLocation()); return; @@ -2595,8 +2604,8 @@ void EmitX64::EmitCondPrelude(const IR::Block& block) { code->L(pass); } -template -void EmitX64::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location) { +template +void EmitX64::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location) { Common::VisitVariant(terminal, [this, &initial_location](auto x) { using T = std::decay_t; if constexpr (!std::is_same_v) { @@ -2607,8 +2616,8 @@ void EmitX64::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor in }); } -template -void EmitX64::Patch(const IR::LocationDescriptor& desc, CodePtr bb) { +template +void EmitX64::Patch(const IR::LocationDescriptor& desc, CodePtr bb) { const CodePtr save_code_ptr = code->getCurr(); const PatchInformation& patch_info = patch_information[desc]; @@ -2630,19 +2639,19 @@ void EmitX64::Patch(const IR::LocationDescriptor& desc, CodePtr bb) { code->SetCodePtr(save_code_ptr); } -template -void EmitX64::Unpatch(const IR::LocationDescriptor& desc) { +template +void EmitX64::Unpatch(const IR::LocationDescriptor& desc) { Patch(desc, nullptr); } -template -void EmitX64::ClearCache() { +template +void EmitX64::ClearCache() { block_descriptors.clear(); patch_information.clear(); } -template -void EmitX64::InvalidateCacheRanges(const boost::icl::interval_set& ranges) { +template +void EmitX64::InvalidateCacheRanges(const boost::icl::interval_set& ranges) { // Remove cached block descriptors and patch information overlapping with the given range. for (auto invalidate_interval : ranges) { auto pair = block_ranges.equal_range(invalidate_interval); @@ -2658,8 +2667,9 @@ void EmitX64::InvalidateCacheRanges(const boost::icl::interval_set& ra } } -template class EmitX64; -template class EmitX64; - } // namespace BackendX64 } // namespace Dynarmic + +#include "backend_x64/a32_jitstate.h" + +template class Dynarmic::BackendX64::EmitX64; diff --git a/src/backend_x64/emit_x64.h b/src/backend_x64/emit_x64.h index 2d413c96..e373c895 100644 --- a/src/backend_x64/emit_x64.h +++ b/src/backend_x64/emit_x64.h @@ -18,7 +18,7 @@ #include "backend_x64/reg_alloc.h" #include "common/address_range.h" #include "dynarmic/callbacks.h" -#include "frontend/A32/location_descriptor.h" +#include "frontend/ir/location_descriptor.h" #include "frontend/ir/terminal.h" namespace Dynarmic { @@ -47,14 +47,16 @@ struct EmitContext { IR::Block& block; }; -template +template class EmitX64 { public: + using ProgramCounterType = typename JitStateType::ProgramCounterType; + struct BlockDescriptor { CodePtr entrypoint; // Entrypoint of emitted code size_t size; // Length in bytes of emitted code - A32::LocationDescriptor start_location; + IR::LocationDescriptor start_location; boost::icl::discrete_interval range; };