mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
x64 JIT: Allocate constant data outside of the guest heap.
This commit is contained in:
parent
784e6a7593
commit
e3fdb08ad7
|
|
@ -41,7 +41,7 @@ class X64ThunkEmitter : public X64Emitter {
|
||||||
};
|
};
|
||||||
|
|
||||||
X64Backend::X64Backend(Processor* processor)
|
X64Backend::X64Backend(Processor* processor)
|
||||||
: Backend(processor), code_cache_(nullptr), emitter_data_(0) {
|
: Backend(processor), code_cache_(nullptr) {
|
||||||
if (cs_open(CS_ARCH_X86, CS_MODE_64, &capstone_handle_) != CS_ERR_OK) {
|
if (cs_open(CS_ARCH_X86, CS_MODE_64, &capstone_handle_) != CS_ERR_OK) {
|
||||||
assert_always("Failed to initialize capstone");
|
assert_always("Failed to initialize capstone");
|
||||||
}
|
}
|
||||||
|
|
@ -51,14 +51,11 @@ X64Backend::X64Backend(Processor* processor)
|
||||||
}
|
}
|
||||||
|
|
||||||
X64Backend::~X64Backend() {
|
X64Backend::~X64Backend() {
|
||||||
if (emitter_data_) {
|
|
||||||
processor()->memory()->SystemHeapFree(emitter_data_);
|
|
||||||
emitter_data_ = 0;
|
|
||||||
}
|
|
||||||
if (capstone_handle_) {
|
if (capstone_handle_) {
|
||||||
cs_close(&capstone_handle_);
|
cs_close(&capstone_handle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X64Emitter::FreeConstData(emitter_data_);
|
||||||
ExceptionHandler::Uninstall(&ExceptionCallbackThunk, this);
|
ExceptionHandler::Uninstall(&ExceptionCallbackThunk, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,7 +111,7 @@ bool X64Backend::Initialize() {
|
||||||
code_cache_->CommitExecutableRange(0x9FFF0000, 0x9FFFFFFF);
|
code_cache_->CommitExecutableRange(0x9FFF0000, 0x9FFFFFFF);
|
||||||
|
|
||||||
// Allocate emitter constant data.
|
// Allocate emitter constant data.
|
||||||
emitter_data_ = X64Emitter::PlaceData(processor()->memory());
|
emitter_data_ = X64Emitter::PlaceConstData();
|
||||||
|
|
||||||
// Setup exception callback
|
// Setup exception callback
|
||||||
ExceptionHandler::Install(&ExceptionCallbackThunk, this);
|
ExceptionHandler::Install(&ExceptionCallbackThunk, this);
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class X64Backend : public Backend {
|
||||||
~X64Backend() override;
|
~X64Backend() override;
|
||||||
|
|
||||||
X64CodeCache* code_cache() const { return code_cache_.get(); }
|
X64CodeCache* code_cache() const { return code_cache_.get(); }
|
||||||
uint32_t emitter_data() const { return emitter_data_; }
|
uintptr_t emitter_data() const { return emitter_data_; }
|
||||||
|
|
||||||
// Call a generated function, saving all stack parameters.
|
// Call a generated function, saving all stack parameters.
|
||||||
HostToGuestThunk host_to_guest_thunk() const { return host_to_guest_thunk_; }
|
HostToGuestThunk host_to_guest_thunk() const { return host_to_guest_thunk_; }
|
||||||
|
|
@ -76,8 +76,7 @@ class X64Backend : public Backend {
|
||||||
uintptr_t capstone_handle_ = 0;
|
uintptr_t capstone_handle_ = 0;
|
||||||
|
|
||||||
std::unique_ptr<X64CodeCache> code_cache_;
|
std::unique_ptr<X64CodeCache> code_cache_;
|
||||||
|
uintptr_t emitter_data_ = 0;
|
||||||
uint32_t emitter_data_;
|
|
||||||
|
|
||||||
HostToGuestThunk host_to_guest_thunk_;
|
HostToGuestThunk host_to_guest_thunk_;
|
||||||
GuestToHostThunk guest_to_host_thunk_;
|
GuestToHostThunk guest_to_host_thunk_;
|
||||||
|
|
|
||||||
|
|
@ -296,7 +296,7 @@ uint64_t TrapDebugPrint(void* raw_context, uint64_t address) {
|
||||||
XELOGD("(DebugPrint) %s", str);
|
XELOGD("(DebugPrint) %s", str);
|
||||||
|
|
||||||
if (FLAGS_enable_debugprint_log) {
|
if (FLAGS_enable_debugprint_log) {
|
||||||
debugging::DebugPrint("(DebugPrint) %s\n", str);
|
debugging::DebugPrint("(DebugPrint) %s", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -556,6 +556,7 @@ void X64Emitter::ReloadEDX() {
|
||||||
|
|
||||||
// Len Assembly Byte Sequence
|
// Len Assembly Byte Sequence
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
// 1b NOP 90H
|
||||||
// 2b 66 NOP 66 90H
|
// 2b 66 NOP 66 90H
|
||||||
// 3b NOP DWORD ptr [EAX] 0F 1F 00H
|
// 3b NOP DWORD ptr [EAX] 0F 1F 00H
|
||||||
// 4b NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
|
// 4b NOP DWORD ptr [EAX + 00H] 0F 1F 40 00H
|
||||||
|
|
@ -602,90 +603,124 @@ void X64Emitter::MovMem64(const Xbyak::RegExp& addr, uint64_t v) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t X64Emitter::PlaceData(Memory* memory) {
|
|
||||||
static const vec128_t xmm_consts[] = {
|
static const vec128_t xmm_consts[] = {
|
||||||
/* XMMZero */ vec128f(0.0f),
|
/* XMMZero */ vec128f(0.0f),
|
||||||
/* XMMOne */ vec128f(1.0f),
|
/* XMMOne */ vec128f(1.0f),
|
||||||
/* XMMNegativeOne */ vec128f(-1.0f, -1.0f, -1.0f, -1.0f),
|
/* XMMNegativeOne */ vec128f(-1.0f, -1.0f, -1.0f, -1.0f),
|
||||||
/* XMMFFFF */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
/* XMMFFFF */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||||
0xFFFFFFFFu, 0xFFFFFFFFu),
|
0xFFFFFFFFu),
|
||||||
/* XMMMaskX16Y16 */ vec128i(0x0000FFFFu, 0xFFFF0000u,
|
/* XMMMaskX16Y16 */ vec128i(0x0000FFFFu, 0xFFFF0000u, 0x00000000u,
|
||||||
0x00000000u, 0x00000000u),
|
0x00000000u),
|
||||||
/* XMMFlipX16Y16 */ vec128i(0x00008000u, 0x00000000u,
|
/* XMMFlipX16Y16 */ vec128i(0x00008000u, 0x00000000u, 0x00000000u,
|
||||||
0x00000000u, 0x00000000u),
|
0x00000000u),
|
||||||
/* XMMFixX16Y16 */ vec128f(-32768.0f, 0.0f, 0.0f, 0.0f),
|
/* XMMFixX16Y16 */ vec128f(-32768.0f, 0.0f, 0.0f, 0.0f),
|
||||||
/* XMMNormalizeX16Y16 */ vec128f(
|
/* XMMNormalizeX16Y16 */ vec128f(
|
||||||
1.0f / 32767.0f, 1.0f / (32767.0f * 65536.0f), 0.0f, 0.0f),
|
1.0f / 32767.0f, 1.0f / (32767.0f * 65536.0f), 0.0f, 0.0f),
|
||||||
/* XMM0001 */ vec128f(0.0f, 0.0f, 0.0f, 1.0f),
|
/* XMM0001 */ vec128f(0.0f, 0.0f, 0.0f, 1.0f),
|
||||||
/* XMM3301 */ vec128f(3.0f, 3.0f, 0.0f, 1.0f),
|
/* XMM3301 */ vec128f(3.0f, 3.0f, 0.0f, 1.0f),
|
||||||
/* XMM3333 */ vec128f(3.0f, 3.0f, 3.0f, 3.0f),
|
/* XMM3333 */ vec128f(3.0f, 3.0f, 3.0f, 3.0f),
|
||||||
/* XMMSignMaskPS */ vec128i(0x80000000u, 0x80000000u,
|
/* XMMSignMaskPS */ vec128i(0x80000000u, 0x80000000u, 0x80000000u,
|
||||||
0x80000000u, 0x80000000u),
|
0x80000000u),
|
||||||
/* XMMSignMaskPD */ vec128i(0x00000000u, 0x80000000u,
|
/* XMMSignMaskPD */ vec128i(0x00000000u, 0x80000000u, 0x00000000u,
|
||||||
0x00000000u, 0x80000000u),
|
0x80000000u),
|
||||||
/* XMMAbsMaskPS */ vec128i(0x7FFFFFFFu, 0x7FFFFFFFu,
|
/* XMMAbsMaskPS */ vec128i(0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu,
|
||||||
0x7FFFFFFFu, 0x7FFFFFFFu),
|
0x7FFFFFFFu),
|
||||||
/* XMMAbsMaskPD */ vec128i(0xFFFFFFFFu, 0x7FFFFFFFu,
|
/* XMMAbsMaskPD */ vec128i(0xFFFFFFFFu, 0x7FFFFFFFu, 0xFFFFFFFFu,
|
||||||
0xFFFFFFFFu, 0x7FFFFFFFu),
|
0x7FFFFFFFu),
|
||||||
/* XMMByteSwapMask */ vec128i(0x00010203u, 0x04050607u,
|
/* XMMByteSwapMask */ vec128i(0x00010203u, 0x04050607u, 0x08090A0Bu,
|
||||||
0x08090A0Bu, 0x0C0D0E0Fu),
|
0x0C0D0E0Fu),
|
||||||
/* XMMByteOrderMask */ vec128i(0x01000302u, 0x05040706u,
|
/* XMMByteOrderMask */ vec128i(0x01000302u, 0x05040706u, 0x09080B0Au,
|
||||||
0x09080B0Au, 0x0D0C0F0Eu),
|
0x0D0C0F0Eu),
|
||||||
/* XMMPermuteControl15 */ vec128b(15),
|
/* XMMPermuteControl15 */ vec128b(15),
|
||||||
/* XMMPermuteByteMask */ vec128b(0x1F),
|
/* XMMPermuteByteMask */ vec128b(0x1F),
|
||||||
/* XMMPackD3DCOLORSat */ vec128i(0x404000FFu),
|
/* XMMPackD3DCOLORSat */ vec128i(0x404000FFu),
|
||||||
/* XMMPackD3DCOLOR */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
/* XMMPackD3DCOLOR */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||||
0xFFFFFFFFu, 0x0C000408u),
|
0x0C000408u),
|
||||||
/* XMMUnpackD3DCOLOR */ vec128i(0xFFFFFF0Eu, 0xFFFFFF0Du,
|
/* XMMUnpackD3DCOLOR */ vec128i(0xFFFFFF0Eu, 0xFFFFFF0Du, 0xFFFFFF0Cu,
|
||||||
0xFFFFFF0Cu, 0xFFFFFF0Fu),
|
0xFFFFFF0Fu),
|
||||||
/* XMMPackFLOAT16_2 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
/* XMMPackFLOAT16_2 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||||
0xFFFFFFFFu, 0x01000302u),
|
0x01000302u),
|
||||||
/* XMMUnpackFLOAT16_2 */ vec128i(0x0D0C0F0Eu, 0xFFFFFFFFu,
|
/* XMMUnpackFLOAT16_2 */ vec128i(0x0D0C0F0Eu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||||
0xFFFFFFFFu, 0xFFFFFFFFu),
|
0xFFFFFFFFu),
|
||||||
/* XMMPackFLOAT16_4 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
/* XMMPackFLOAT16_4 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0x05040706u,
|
||||||
0x05040706u, 0x01000302u),
|
0x01000302u),
|
||||||
/* XMMUnpackFLOAT16_4 */ vec128i(0x09080B0Au, 0x0D0C0F0Eu,
|
/* XMMUnpackFLOAT16_4 */ vec128i(0x09080B0Au, 0x0D0C0F0Eu, 0xFFFFFFFFu,
|
||||||
0xFFFFFFFFu, 0xFFFFFFFFu),
|
0xFFFFFFFFu),
|
||||||
/* XMMPackSHORT_2Min */ vec128i(0x403F8001u),
|
/* XMMPackSHORT_2Min */ vec128i(0x403F8001u),
|
||||||
/* XMMPackSHORT_2Max */ vec128i(0x40407FFFu),
|
/* XMMPackSHORT_2Max */ vec128i(0x40407FFFu),
|
||||||
/* XMMPackSHORT_2 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
/* XMMPackSHORT_2 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||||
0xFFFFFFFFu, 0x01000504u),
|
0x01000504u),
|
||||||
/* XMMUnpackSHORT_2 */ vec128i(0xFFFF0F0Eu, 0xFFFF0D0Cu,
|
/* XMMUnpackSHORT_2 */ vec128i(0xFFFF0F0Eu, 0xFFFF0D0Cu, 0xFFFFFFFFu,
|
||||||
0xFFFFFFFFu, 0xFFFFFFFFu),
|
0xFFFFFFFFu),
|
||||||
/* XMMOneOver255 */ vec128f(1.0f / 255.0f),
|
/* XMMOneOver255 */ vec128f(1.0f / 255.0f),
|
||||||
/* XMMMaskEvenPI16 */ vec128i(0x0000FFFFu, 0x0000FFFFu,
|
/* XMMMaskEvenPI16 */ vec128i(0x0000FFFFu, 0x0000FFFFu, 0x0000FFFFu,
|
||||||
0x0000FFFFu, 0x0000FFFFu),
|
0x0000FFFFu),
|
||||||
/* XMMShiftMaskEvenPI16 */ vec128i(0x0000000Fu, 0x0000000Fu,
|
/* XMMShiftMaskEvenPI16 */ vec128i(0x0000000Fu, 0x0000000Fu, 0x0000000Fu,
|
||||||
0x0000000Fu, 0x0000000Fu),
|
0x0000000Fu),
|
||||||
/* XMMShiftMaskPS */ vec128i(0x0000001Fu, 0x0000001Fu,
|
/* XMMShiftMaskPS */ vec128i(0x0000001Fu, 0x0000001Fu, 0x0000001Fu,
|
||||||
0x0000001Fu, 0x0000001Fu),
|
0x0000001Fu),
|
||||||
/* XMMShiftByteMask */ vec128i(0x000000FFu, 0x000000FFu,
|
/* XMMShiftByteMask */ vec128i(0x000000FFu, 0x000000FFu, 0x000000FFu,
|
||||||
0x000000FFu, 0x000000FFu),
|
0x000000FFu),
|
||||||
/* XMMSwapWordMask */ vec128i(0x03030303u, 0x03030303u,
|
/* XMMSwapWordMask */ vec128i(0x03030303u, 0x03030303u, 0x03030303u,
|
||||||
0x03030303u, 0x03030303u),
|
0x03030303u),
|
||||||
/* XMMUnsignedDwordMax */ vec128i(0xFFFFFFFFu, 0x00000000u,
|
/* XMMUnsignedDwordMax */ vec128i(0xFFFFFFFFu, 0x00000000u, 0xFFFFFFFFu,
|
||||||
0xFFFFFFFFu, 0x00000000u),
|
0x00000000u),
|
||||||
/* XMM255 */ vec128f(255.0f),
|
/* XMM255 */ vec128f(255.0f),
|
||||||
/* XMMPI32 */ vec128i(32),
|
/* XMMPI32 */ vec128i(32),
|
||||||
/* XMMSignMaskI8 */ vec128i(0x80808080u, 0x80808080u,
|
/* XMMSignMaskI8 */ vec128i(0x80808080u, 0x80808080u, 0x80808080u,
|
||||||
0x80808080u, 0x80808080u),
|
0x80808080u),
|
||||||
/* XMMSignMaskI16 */ vec128i(0x80008000u, 0x80008000u,
|
/* XMMSignMaskI16 */ vec128i(0x80008000u, 0x80008000u, 0x80008000u,
|
||||||
0x80008000u, 0x80008000u),
|
0x80008000u),
|
||||||
/* XMMSignMaskI32 */ vec128i(0x80000000u, 0x80000000u,
|
/* XMMSignMaskI32 */ vec128i(0x80000000u, 0x80000000u, 0x80000000u,
|
||||||
0x80000000u, 0x80000000u),
|
0x80000000u),
|
||||||
/* XMMSignMaskF32 */ vec128i(0x80000000u, 0x80000000u,
|
/* XMMSignMaskF32 */ vec128i(0x80000000u, 0x80000000u, 0x80000000u,
|
||||||
0x80000000u, 0x80000000u),
|
0x80000000u),
|
||||||
/* XMMShortMinPS */ vec128f(SHRT_MIN),
|
/* XMMShortMinPS */ vec128f(SHRT_MIN),
|
||||||
/* XMMShortMaxPS */ vec128f(SHRT_MAX),
|
/* XMMShortMaxPS */ vec128f(SHRT_MAX),
|
||||||
};
|
};
|
||||||
uint32_t ptr = memory->SystemHeapAlloc(sizeof(xmm_consts));
|
|
||||||
std::memcpy(memory->TranslateVirtual(ptr), xmm_consts, sizeof(xmm_consts));
|
// First location to try and place constants.
|
||||||
return ptr;
|
static const uintptr_t kConstDataLocation = 0x20000000;
|
||||||
|
static const uintptr_t kConstDataSize = sizeof(xmm_consts);
|
||||||
|
|
||||||
|
// Increment the location by this amount for every allocation failure.
|
||||||
|
static const uintptr_t kConstDataIncrement = 0x00010000;
|
||||||
|
|
||||||
|
// This function places constant data that is used by the emitter later on.
|
||||||
|
// Only called once and used by multiple instances of the emitter.
|
||||||
|
//
|
||||||
|
// TODO(DrChat): This should be placed in the code cache with the code, but
|
||||||
|
// doing so requires RIP-relative addressing, which is difficult to support
|
||||||
|
// given the current setup.
|
||||||
|
uintptr_t X64Emitter::PlaceConstData() {
|
||||||
|
uint8_t* ptr = reinterpret_cast<uint8_t*>(kConstDataLocation);
|
||||||
|
void* mem = nullptr;
|
||||||
|
while (!mem) {
|
||||||
|
mem = memory::AllocFixed(
|
||||||
|
ptr, xe::round_up(kConstDataSize, memory::page_size()),
|
||||||
|
memory::AllocationType::kReserveCommit, memory::PageAccess::kReadWrite);
|
||||||
|
|
||||||
|
ptr += kConstDataIncrement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The pointer must not be greater than 31 bits.
|
||||||
|
assert_zero(reinterpret_cast<uintptr_t>(mem) & ~0x7FFFFFFF);
|
||||||
|
std::memcpy(mem, xmm_consts, sizeof(xmm_consts));
|
||||||
|
memory::Protect(mem, kConstDataSize, memory::PageAccess::kReadOnly, nullptr);
|
||||||
|
|
||||||
|
return reinterpret_cast<uintptr_t>(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X64Emitter::FreeConstData(uintptr_t data) {
|
||||||
|
memory::DeallocFixed(reinterpret_cast<void*>(data), 0,
|
||||||
|
memory::DeallocationType::kDecommitRelease);
|
||||||
}
|
}
|
||||||
|
|
||||||
Xbyak::Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
Xbyak::Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
||||||
// Load through fixed constant table setup by PlaceData.
|
// Load through fixed constant table setup by PlaceConstData.
|
||||||
return ptr[rdx + backend_->emitter_data() + sizeof(vec128_t) * id];
|
// It's important that the pointer is not signed, as it will be sign-extended.
|
||||||
|
return ptr[reinterpret_cast<void*>(backend_->emitter_data() +
|
||||||
|
sizeof(vec128_t) * id)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, const vec128_t& v) {
|
void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, const vec128_t& v) {
|
||||||
|
|
|
||||||
|
|
@ -114,13 +114,14 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
||||||
Processor* processor() const { return processor_; }
|
Processor* processor() const { return processor_; }
|
||||||
X64Backend* backend() const { return backend_; }
|
X64Backend* backend() const { return backend_; }
|
||||||
|
|
||||||
|
static uintptr_t PlaceConstData();
|
||||||
|
static void FreeConstData(uintptr_t data);
|
||||||
|
|
||||||
bool Emit(GuestFunction* function, hir::HIRBuilder* builder,
|
bool Emit(GuestFunction* function, hir::HIRBuilder* builder,
|
||||||
uint32_t debug_info_flags, FunctionDebugInfo* debug_info,
|
uint32_t debug_info_flags, FunctionDebugInfo* debug_info,
|
||||||
void** out_code_address, size_t* out_code_size,
|
void** out_code_address, size_t* out_code_size,
|
||||||
std::vector<SourceMapEntry>* out_source_map);
|
std::vector<SourceMapEntry>* out_source_map);
|
||||||
|
|
||||||
static uint32_t PlaceData(Memory* memory);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Reserved: rsp
|
// Reserved: rsp
|
||||||
// Scratch: rax/rcx/rdx
|
// Scratch: rax/rcx/rdx
|
||||||
|
|
|
||||||
|
|
@ -610,6 +610,7 @@ struct Sequence {
|
||||||
reg_reg_fn(e, i.src2, temp);
|
reg_reg_fn(e, i.src2, temp);
|
||||||
}
|
}
|
||||||
} else if (i.src2.is_constant) {
|
} else if (i.src2.is_constant) {
|
||||||
|
assert_true(!i.src1.is_constant);
|
||||||
if (i.src2.ConstantFitsIn32Reg()) {
|
if (i.src2.ConstantFitsIn32Reg()) {
|
||||||
reg_const_fn(e, i.src1, static_cast<int32_t>(i.src2.constant()));
|
reg_const_fn(e, i.src1, static_cast<int32_t>(i.src2.constant()));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -636,6 +637,7 @@ struct Sequence {
|
||||||
reg_reg_fn(e, i.dest, i.src2, temp, true);
|
reg_reg_fn(e, i.dest, i.src2, temp, true);
|
||||||
}
|
}
|
||||||
} else if (i.src2.is_constant) {
|
} else if (i.src2.is_constant) {
|
||||||
|
assert_true(!i.src1.is_constant);
|
||||||
if (i.src2.ConstantFitsIn32Reg()) {
|
if (i.src2.ConstantFitsIn32Reg()) {
|
||||||
reg_const_fn(e, i.dest, i.src1, static_cast<int32_t>(i.src2.constant()),
|
reg_const_fn(e, i.dest, i.src1, static_cast<int32_t>(i.src2.constant()),
|
||||||
false);
|
false);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue