IR: Implement IR instruction CallHostFunction
This commit is contained in:
parent
3c693f2576
commit
17ae7f9ce1
6 changed files with 35 additions and 5 deletions
|
@ -59,10 +59,6 @@ std::optional<EmitX64::BlockDescriptor> EmitX64::GetBasicBlock(IR::LocationDescr
|
||||||
void EmitX64::EmitVoid(EmitContext&, IR::Inst*) {
|
void EmitX64::EmitVoid(EmitContext&, IR::Inst*) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitX64::EmitBreakpoint(EmitContext&, IR::Inst*) {
|
|
||||||
code.int3();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitX64::EmitIdentity(EmitContext& ctx, IR::Inst* inst) {
|
void EmitX64::EmitIdentity(EmitContext& ctx, IR::Inst* inst) {
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
if (!args[0].IsImmediate()) {
|
if (!args[0].IsImmediate()) {
|
||||||
|
@ -70,6 +66,17 @@ void EmitX64::EmitIdentity(EmitContext& ctx, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitBreakpoint(EmitContext&, IR::Inst*) {
|
||||||
|
code.int3();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitCallHostFunction(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
ctx.reg_alloc.HostCall(nullptr, args[1], args[2], args[3]);
|
||||||
|
code.mov(rax, args[0].GetImmediateU64());
|
||||||
|
code.call(rax);
|
||||||
|
}
|
||||||
|
|
||||||
void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target) {
|
void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target) {
|
||||||
using namespace Xbyak::util;
|
using namespace Xbyak::util;
|
||||||
|
|
||||||
|
|
|
@ -408,7 +408,7 @@ void RegAlloc::HostCall(IR::Inst* result_def,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < args_count; i++) {
|
for (size_t i = 0; i < args_count; i++) {
|
||||||
if (args[i]) {
|
if (args[i] && !args[i]->get().IsVoid()) {
|
||||||
UseScratch(*args[i], args_hostloc[i]);
|
UseScratch(*args[i], args_hostloc[i]);
|
||||||
#if defined(__llvm__) && !defined(_WIN32)
|
#if defined(__llvm__) && !defined(_WIN32)
|
||||||
// LLVM puts the burden of zero-extension of 8 and 16 bit values on the caller instead of the callee
|
// LLVM puts the burden of zero-extension of 8 and 16 bit values on the caller instead of the callee
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "dynarmic/ir/ir_emitter.h"
|
#include "dynarmic/ir/ir_emitter.h"
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
|
#include "dynarmic/common/cast_util.h"
|
||||||
#include "dynarmic/ir/opcodes.h"
|
#include "dynarmic/ir/opcodes.h"
|
||||||
|
|
||||||
namespace Dynarmic::IR {
|
namespace Dynarmic::IR {
|
||||||
|
@ -2652,6 +2653,22 @@ void IREmitter::Breakpoint() {
|
||||||
Inst(Opcode::Breakpoint);
|
Inst(Opcode::Breakpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IREmitter::CallHostFunction(void (*fn)(void)) {
|
||||||
|
Inst(Opcode::CallHostFunction, Imm64(Common::BitCast<u64>(fn)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::CallHostFunction(void (*fn)(u64), const U64& arg1) {
|
||||||
|
Inst(Opcode::CallHostFunction, Imm64(Common::BitCast<u64>(fn)), arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::CallHostFunction(void (*fn)(u64, u64), const U64& arg1, const U64& arg2) {
|
||||||
|
Inst(Opcode::CallHostFunction, Imm64(Common::BitCast<u64>(fn)), arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::CallHostFunction(void (*fn)(u64, u64, u64), const U64& arg1, const U64& arg2, const U64& arg3) {
|
||||||
|
Inst(Opcode::CallHostFunction, Imm64(Common::BitCast<u64>(fn)), arg1, arg2, arg3);
|
||||||
|
}
|
||||||
|
|
||||||
void IREmitter::SetTerm(const Terminal& terminal) {
|
void IREmitter::SetTerm(const Terminal& terminal) {
|
||||||
block.SetTerminal(terminal);
|
block.SetTerminal(terminal);
|
||||||
}
|
}
|
||||||
|
|
|
@ -393,6 +393,10 @@ public:
|
||||||
U128 FPVectorToUnsignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true);
|
U128 FPVectorToUnsignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true);
|
||||||
|
|
||||||
void Breakpoint();
|
void Breakpoint();
|
||||||
|
void CallHostFunction(void (*fn)(void));
|
||||||
|
void CallHostFunction(void (*fn)(u64), const U64& arg1);
|
||||||
|
void CallHostFunction(void (*fn)(u64, u64), const U64& arg1, const U64& arg2);
|
||||||
|
void CallHostFunction(void (*fn)(u64, u64, u64), const U64& arg1, const U64& arg2, const U64& arg3);
|
||||||
|
|
||||||
void SetTerm(const Terminal& terminal);
|
void SetTerm(const Terminal& terminal);
|
||||||
|
|
||||||
|
|
|
@ -526,6 +526,7 @@ bool Inst::IsSetCheckBitOperation() const {
|
||||||
|
|
||||||
bool Inst::MayHaveSideEffects() const {
|
bool Inst::MayHaveSideEffects() const {
|
||||||
return op == Opcode::PushRSB
|
return op == Opcode::PushRSB
|
||||||
|
|| op == Opcode::CallHostFunction
|
||||||
|| op == Opcode::A64DataCacheOperationRaised
|
|| op == Opcode::A64DataCacheOperationRaised
|
||||||
|| op == Opcode::A64InstructionCacheOperationRaised
|
|| op == Opcode::A64InstructionCacheOperationRaised
|
||||||
|| IsSetCheckBitOperation()
|
|| IsSetCheckBitOperation()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
OPCODE(Void, Void, )
|
OPCODE(Void, Void, )
|
||||||
OPCODE(Identity, Opaque, Opaque )
|
OPCODE(Identity, Opaque, Opaque )
|
||||||
OPCODE(Breakpoint, Void, )
|
OPCODE(Breakpoint, Void, )
|
||||||
|
OPCODE(CallHostFunction, Void, U64, Opaque, Opaque, Opaque )
|
||||||
|
|
||||||
// A32 Context getters/setters
|
// A32 Context getters/setters
|
||||||
A32OPC(SetCheckBit, Void, U1 )
|
A32OPC(SetCheckBit, Void, U1 )
|
||||||
|
|
Loading…
Reference in a new issue