IR: Implement IR instruction CallHostFunction

This commit is contained in:
MerryMage 2021-05-23 15:37:24 +01:00
parent 3c693f2576
commit 17ae7f9ce1
6 changed files with 35 additions and 5 deletions

View file

@ -59,10 +59,6 @@ std::optional<EmitX64::BlockDescriptor> EmitX64::GetBasicBlock(IR::LocationDescr
void EmitX64::EmitVoid(EmitContext&, IR::Inst*) {
}
void EmitX64::EmitBreakpoint(EmitContext&, IR::Inst*) {
code.int3();
}
void EmitX64::EmitIdentity(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
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) {
using namespace Xbyak::util;

View file

@ -408,7 +408,7 @@ void RegAlloc::HostCall(IR::Inst* result_def,
}
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]);
#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

View file

@ -6,6 +6,7 @@
#include "dynarmic/ir/ir_emitter.h"
#include "dynarmic/common/assert.h"
#include "dynarmic/common/cast_util.h"
#include "dynarmic/ir/opcodes.h"
namespace Dynarmic::IR {
@ -2652,6 +2653,22 @@ void IREmitter::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) {
block.SetTerminal(terminal);
}

View file

@ -393,6 +393,10 @@ public:
U128 FPVectorToUnsignedFixed(size_t esize, const U128& a, size_t fbits, FP::RoundingMode rounding, bool fpcr_controlled = true);
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);

View file

@ -526,6 +526,7 @@ bool Inst::IsSetCheckBitOperation() const {
bool Inst::MayHaveSideEffects() const {
return op == Opcode::PushRSB
|| op == Opcode::CallHostFunction
|| op == Opcode::A64DataCacheOperationRaised
|| op == Opcode::A64InstructionCacheOperationRaised
|| IsSetCheckBitOperation()

View file

@ -3,6 +3,7 @@
OPCODE(Void, Void, )
OPCODE(Identity, Opaque, Opaque )
OPCODE(Breakpoint, Void, )
OPCODE(CallHostFunction, Void, U64, Opaque, Opaque, Opaque )
// A32 Context getters/setters
A32OPC(SetCheckBit, Void, U1 )