Skip to content
Permalink
Browse files
Enable WasmLLInt on ARMv7
Patch by Geza Lore <glore@igalia.com> on 2022-06-10
Patch by Geza Lore <glore@igalia.com> on 2022-05-27
https://bugs.webkit.org/show_bug.cgi?id=221260

Reviewed by Saam Barati.

Patch by Geza Lore and Xan López.

Implement the LLInt tier of WebAssembly for ARMv7. A lot of the
work will be shared by any 32bit port, but the offlineassembler
has only been updated for ARMv7 so far.

Main highlights:

We have split the WebAssembly.asm file into three chunks,
following what LowLevelInterpreter.asm does. The common code
remains in WebAssembly.asm, and 32 and 64bit specific code (mostly
opcode implementations) goes into WebAssembly32_64.asm and
WebAssembly64.asm.

We have decided to use consecutive even/odd pairs of GPRs for every
type of wasm values, even if they are 32bit (i32/f32), with the odd
(higher) numbered GPR holding the more significant half. 32bit values
are held in the even (lower) numbered register. This makes the code
much simpler and allows us to share more code with the 64bit variant.
This is mostly relevant for argument passing, and given that every
value ends up in the stack anyway we do not think it is significant
from a performance POV.

We are reusing JSValueRegs to hold Wasm values too. Obviously they
are not really JSValues, so it might make sense to create a base
class that can be used for both JS and Wasm values.

We do not have enough registers to keep things like the memory
base pointer and size in pinned registers, so we are forced to
load them on each use.

We disable the 'Signaling' memory mode, since the current
implementation relies on being able to mprotect a 2^32 + redzone
region of memory. This can be changed in the future but it's not a
priority at the moment.

* stress/sampling-profiler-wasm-name-section.js:
* stress/sampling-profiler-wasm.js:
* wasm/regress/llint-callee-saves-with-fast-memory.js:
* CMakeLists.txt:
* assembler/ARMv7Assembler.h:
(JSC::ARMv7Assembler::vcvt_signedToFloatingPoint):
* assembler/MacroAssemblerARMv7.h:
(JSC::MacroAssemblerARMv7::convertInt32ToFloat):
(JSC::MacroAssemblerARMv7::threadSafePatchableNearCall):
(JSC::MacroAssemblerARMv7::callOperation):
* b3/B3ValueRep.h:
(JSC::B3::ValueRep::ValueRep):
* bytecode/BytecodeDumper.cpp:
(JSC::Wasm::BytecodeDumper::formatConstant const):
* interpreter/CallFrame.h: adapt to new callee tagging format.
(JSC::CallFrame::callee const):
(JSC::CallFrame::unsafeCallee const):
* interpreter/CalleeBits.h: add wasm tagging of callee values for
32bit.
(JSC::CalleeBits::CalleeBits):
(JSC::CalleeBits::operator=):
(JSC::CalleeBits::boxWasm):
(JSC::CalleeBits::isWasm const):
(JSC::CalleeBits::asWasmCallee const):
* interpreter/Register.h:
(JSC::Register::unboxedFloat const):
(JSC::Register::asanUnsafeUnboxedFloat const):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::unboxDouble):
* jit/RegisterAtOffsetList.cpp:
(JSC::RegisterAtOffsetList::RegisterAtOffsetList):
* jit/RegisterAtOffsetList.h:
(JSC::RegisterAtOffsetList::sizeOfAreaInBytes const):
* jit/RegisterSet.cpp:
(JSC::RegisterSet::macroScratchRegisters):
* llint/LowLevelInterpreter32_64.asm:
* llint/WebAssembly.asm:
* llint/WebAssembly32_64.asm: Added.
* llint/WebAssembly64.asm: Added.
* offlineasm/arm.rb:
* offlineasm/instructions.rb:
* offlineasm/registers.rb:
* offlineasm/risc.rb:
* runtime/JSCJSValue.h:
(JSC::wasmUnboxedFloat):
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::JSValue):
* wasm/WasmAirIRGenerator.cpp:
(JSC::Wasm::AirIRGenerator::useSignalingMemory const):
(JSC::Wasm::AirIRGenerator::AirIRGenerator):
(JSC::Wasm::AirIRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::AirIRGenerator::addCall):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::useSignalingMemory const):
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::addArguments):
(JSC::Wasm::B3IRGenerator::emitCheckAndPreparePointer):
(JSC::Wasm::B3IRGenerator::memoryKind):
(JSC::Wasm::B3IRGenerator::addCall):
* wasm/WasmBinding.cpp:
(JSC::Wasm::wasmToWasm):
* wasm/WasmCallee.cpp:
(JSC::Wasm::LLIntCallee::calleeSaveRegisters):
* wasm/WasmCalleeGroup.cpp:
(JSC::Wasm::CalleeGroup::isSafeToRun):
* wasm/WasmCallingConvention.cpp:
(JSC::Wasm::jsCallingConvention):
(JSC::Wasm::wasmCallingConvention):
* wasm/WasmCallingConvention.h:
(JSC::Wasm::CallInformation::computeResultsOffsetList):
(JSC::Wasm::WasmCallingConvention::WasmCallingConvention):
(JSC::Wasm::WasmCallingConvention::marshallLocationImpl const):
(JSC::Wasm::WasmCallingConvention::marshallLocation const):
(JSC::Wasm::JSCallingConvention::JSCallingConvention):
(JSC::Wasm::JSCallingConvention::marshallLocationImpl const):
(JSC::Wasm::JSCallingConvention::marshallLocation const):
(JSC::Wasm::JSCallingConvention::callInformationFor const):
* wasm/WasmFormat.h:
* wasm/WasmIndexOrName.cpp:
(JSC::Wasm::IndexOrName::IndexOrName):
(JSC::Wasm::makeString):
* wasm/WasmIndexOrName.h:
(JSC::Wasm::IndexOrName::IndexOrName):
(JSC::Wasm::IndexOrName::isEmpty const):
(JSC::Wasm::IndexOrName::isIndex const):
(JSC::Wasm::IndexOrName::isName const):
(JSC::Wasm::IndexOrName::index const):
(JSC::Wasm::IndexOrName::name const):
(JSC::Wasm::IndexOrName::nameSection const):
* wasm/WasmInstance.h:
(JSC::Wasm::Instance::updateCachedMemory):
* wasm/WasmLLIntGenerator.cpp:
(JSC::Wasm::LLIntGenerator::virtualRegisterForWasmLocal):
(JSC::Wasm::LLIntGenerator::callInformationForCaller):
(JSC::Wasm::LLIntGenerator::callInformationForCallee):
(JSC::Wasm::LLIntGenerator::addArguments):
(JSC::Wasm::LLIntGenerator::addLoop):
* wasm/WasmLLIntPlan.cpp:
(JSC::Wasm::LLIntPlan::didCompleteCompilation):
* wasm/WasmMemory.cpp:
(JSC::Wasm::MemoryHandle::~MemoryHandle):
(JSC::Wasm::Memory::tryCreate):
(JSC::Wasm::Memory::growShared):
(JSC::Wasm::Memory::grow):
(JSC::Wasm::Memory::copy):
* wasm/WasmMemory.h:
* wasm/WasmMemoryInformation.cpp:
(JSC::Wasm::PinnedRegisterInfo::get):
* wasm/WasmMemoryInformation.h:
(JSC::Wasm::PinnedRegisterInfo::toSave const):
* wasm/WasmMemoryMode.cpp:
(JSC::Wasm::makeString):
* wasm/WasmMemoryMode.h:
* wasm/WasmOpcodeOrigin.cpp:
* wasm/WasmOpcodeOrigin.h:
* wasm/WasmOperations.cpp:
(JSC::Wasm::JSC_DEFINE_JIT_OPERATION):
* wasm/WasmOperations.h:
* wasm/WasmPageCount.h:
* wasm/WasmParser.h:
(JSC::Wasm::Parser<SuccessType>::parseUInt32):
(JSC::Wasm::Parser<SuccessType>::parseUInt64):
* wasm/WasmSlowPaths.cpp:
(JSC::LLInt::WASM_SLOW_PATH_DECL):
(JSC::LLInt::slow_path_wasm_popcount):
(JSC::LLInt::slow_path_wasm_popcountll):
(JSC::LLInt::slow_path_wasm_i32_div_s):
(JSC::LLInt::slow_path_wasm_i32_div_u):
(JSC::LLInt::slow_path_wasm_i32_rem_s):
(JSC::LLInt::slow_path_wasm_i32_rem_u):
(JSC::LLInt::slow_path_wasm_i64_div_s):
(JSC::LLInt::slow_path_wasm_i64_div_u):
(JSC::LLInt::slow_path_wasm_i64_rem_s):
(JSC::LLInt::slow_path_wasm_i64_rem_u):
* wasm/WasmSlowPaths.h:
* wasm/WasmValueLocation.cpp:
(JSC::Wasm::ValueLocation::dump const):
(WTF::printInternal):
* wasm/WasmValueLocation.h:
(JSC::Wasm::ValueLocation::ValueLocation):
(JSC::Wasm::ValueLocation::isGPR const):
(JSC::Wasm::ValueLocation::isFPR const):
(JSC::Wasm::ValueLocation::isStack const):
(JSC::Wasm::ValueLocation::isStackArgument const):
(JSC::Wasm::ValueLocation::jsr const):
(JSC::Wasm::ValueLocation::fpr const):
(JSC::Wasm::ValueLocation::reg): Deleted.
(JSC::Wasm::ValueLocation::isReg const): Deleted.
(JSC::Wasm::ValueLocation::reg const): Deleted.
(JSC::Wasm::ValueLocation::gpr const): Deleted.
* wasm/js/JSToWasm.cpp:
(JSC::Wasm::marshallJSResult):
(JSC::Wasm::createJSToWasmWrapper):
* wasm/js/WasmToJS.cpp:
(JSC::Wasm::wasmToJS):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::WebAssemblyFunction::previousInstanceOffset const):
(JSC::WebAssemblyFunction::jsCallEntrypointSlow):
* wasm/js/WebAssemblyGlobalConstructor.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::initializeExports):
* wtf/PlatformEnable.h: enable WebAssembly on ARMv7.
* Scripts/run-jsc-stress-tests: allow to run the wasm tests on
armv7 even without jit support (for now).

Canonical link: https://commits.webkit.org/251455@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@295449 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
gezalore authored and webkit-commit-queue committed Jun 10, 2022
1 parent ed7fed1 commit b58fb7e9473cc9227e4d52d17e93f25a3970522e
Show file tree
Hide file tree
Showing 62 changed files with 4,050 additions and 1,697 deletions.
@@ -1,3 +1,8 @@
// This test is statistical, and without optimizing Wasm tiers the likelihood
// of hitting the deepest expected stack trace is very low, so disable.
// FIXME: remove when 32-bit platforms support optimizing Wasm tiers
//@ skip if ["arm", "mips"].include?($architecture)
//
//@ runDefault

/*
@@ -1,3 +1,4 @@
//@ skip if $architecture == "arm"
//@ runDefault

if (platformSupportsSamplingProfiler() && $vm.isWasmSupported()) {
@@ -1,2 +1,4 @@
//Growing a shared memory requires signal handlers, which are not yet ported to ARMv7
//@ skip if $architecture == "arm"
if (typeof WebAssembly !== 'undefined')
(new WebAssembly.Memory({initial: 0, maximum: 1, shared: true})).grow(1)
@@ -1,3 +1,4 @@
//@ skip if $architecture == "arm"
//@ requireOptions("--useWebAssemblyFastMemory=true")

import * as assert from '../assert.js';
@@ -1,3 +1,5 @@
//Growing a shared memory requires signal handlers, which are not yet ported to ARMv7
//@ skip if $architecture == "arm"
import * as assert from '../assert.js';

assert.throws(() => {
@@ -1,3 +1,5 @@
//Growing a shared memory requires signal handlers, which are not yet ported to ARMv7
//@ skip if $architecture == "arm"
import * as assert from '../assert.js'

let pageSize = 64 << 10;
@@ -200,6 +200,8 @@ set(LLINT_ASM
llint/LowLevelInterpreter32_64.asm
llint/LowLevelInterpreter64.asm
llint/WebAssembly.asm
llint/WebAssembly32_64.asm
llint/WebAssembly64.asm
)

set(OFFLINE_ASM
@@ -5732,6 +5732,8 @@
FE9FA7C4273C8B26005D9E70 /* DeferGCInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeferGCInlines.h; sourceTree = "<group>"; };
FEA0861E182B7A0400F6D851 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpoint.h; sourceTree = "<group>"; };
FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerPrimitives.h; sourceTree = "<group>"; };
FEA2168828500762002B3662 /* WebAssembly64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = WebAssembly64.asm; path = llint/WebAssembly64.asm; sourceTree = "<group>"; };
FEA21689285007E3002B3662 /* WebAssembly32_64.asm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.asm.asm; name = WebAssembly32_64.asm; path = llint/WebAssembly32_64.asm; sourceTree = "<group>"; };
FEA3BBA7212B655800E93AD1 /* CallFrameInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallFrameInlines.h; sourceTree = "<group>"; };
FEA3BBAB212C97CB00E93AD1 /* DFGCFG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFG.h; path = dfg/DFGCFG.h; sourceTree = "<group>"; };
FEB137561BB11EEE00CD5100 /* MacroAssemblerARM64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MacroAssemblerARM64.cpp; sourceTree = "<group>"; };
@@ -6027,6 +6029,8 @@
86A054471556451B00445157 /* LowLevelInterpreter32_64.asm */,
86A054481556451B00445157 /* LowLevelInterpreter64.asm */,
FE00262223F3AF33003A358F /* WebAssembly.asm */,
FEA2168828500762002B3662 /* WebAssembly64.asm */,
FEA21689285007E3002B3662 /* WebAssembly32_64.asm */,
);
name = llint;
sourceTree = "<group>";
@@ -1991,10 +1991,10 @@ class ARMv7Assembler {
m_formatter.vfpOp(OP_VCMP, OP_VCMPb, true, VFPOperand(5), rd, VFPOperand(0));
}

void vcvt_signedToFloatingPoint(FPDoubleRegisterID rd, FPSingleRegisterID rm)
void vcvt_signedToFloatingPoint(FPDoubleRegisterID rd, FPSingleRegisterID rm, bool toDouble = true)
{
// boolean values are 64bit (toInt, unsigned, roundZero)
m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, true, vcvtOp(false, false, false), rd, rm);
m_formatter.vfpOp(OP_VCVT_FPIVFP, OP_VCVT_FPIVFPb, toDouble, vcvtOp(false, false, false), rd, rm);
}

void vcvt_floatingPointToSigned(FPSingleRegisterID rd, FPDoubleRegisterID rm)
@@ -1467,6 +1467,12 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<Assembler> {
CRASH();
}

void convertInt32ToFloat(RegisterID src, FPRegisterID dest)
{
m_assembler.vmov(fpTempRegister, src, src);
m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle(), /* toDouble: */ false);
}

void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
{
m_assembler.vmov(fpTempRegister, src, src);
@@ -2298,6 +2304,14 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<Assembler> {
return Call(m_assembler.b(), Call::LinkableNearTail);
}

// FIXME: why is this the same than nearCall() in ARM64? is it right?
ALWAYS_INLINE Call threadSafePatchableNearCall()
{
invalidateAllTempRegisters();
moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
return Call(m_assembler.blx(dataTempRegister), Call::LinkableNear);
}

ALWAYS_INLINE Call call(PtrTag)
{
moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
@@ -2322,6 +2336,12 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<Assembler> {
ALWAYS_INLINE Call call(RegisterID target, RegisterID callTag) { return UNUSED_PARAM(callTag), call(target, NoPtrTag); }
ALWAYS_INLINE Call call(Address address, RegisterID callTag) { return UNUSED_PARAM(callTag), call(address, NoPtrTag); }

ALWAYS_INLINE void callOperation(const FunctionPtr<OperationPtrTag> operation)
{
move(TrustedImmPtr(operation.executableAddress()), addressTempRegister);
call(addressTempRegister, OperationPtrTag);
}

ALWAYS_INLINE void ret()
{
m_assembler.bx(linkRegister);
@@ -126,9 +126,13 @@ class ValueRep {
ValueRep(Wasm::ValueLocation location)
{
switch (location.kind()) {
case Wasm::ValueLocation::Kind::Register:
case Wasm::ValueLocation::Kind::GPRRegister:
m_kind = Register;
u.reg = location.reg();
u.reg = location.jsr().payloadGPR();
break;
case Wasm::ValueLocation::Kind::FPRRegister:
m_kind = Register;
u.reg = location.fpr();
break;
case Wasm::ValueLocation::Kind::Stack:
m_kind = Stack;
@@ -413,7 +413,7 @@ CString BytecodeDumper::formatConstant(Type type, uint64_t constant) const
if (isFuncref(type) || isExternref(type)) {
if (JSValue::decode(constant) == jsNull())
return "null";
return toCString(RawPointer(bitwise_cast<void*>(constant)));
return toCString(RawPointer(bitwise_cast<void*>(static_cast<uintptr_t>(constant))));
}

RELEASE_ASSERT_NOT_REACHED();
@@ -167,8 +167,8 @@ namespace JSC {
// to see if it's a cell, and if it's not, we throw an exception.
inline JSValue guaranteedJSValueCallee() const;
inline JSObject* jsCallee() const;
CalleeBits callee() const { return CalleeBits(this[static_cast<int>(CallFrameSlot::callee)].pointer()); }
SUPPRESS_ASAN CalleeBits unsafeCallee() const { return CalleeBits(this[static_cast<int>(CallFrameSlot::callee)].asanUnsafePointer()); }
CalleeBits callee() const { return CalleeBits(this[static_cast<int>(CallFrameSlot::callee)].unboxedInt64()); }
SUPPRESS_ASAN CalleeBits unsafeCallee() const { return CalleeBits(this[static_cast<int>(CallFrameSlot::callee)].asanUnsafeUnboxedInt64()); }
CodeBlock* codeBlock() const;
CodeBlock** addressOfCodeBlock() const { return bitwise_cast<CodeBlock**>(this + static_cast<int>(CallFrameSlot::codeBlock)); }
inline SUPPRESS_ASAN CodeBlock* unsafeCodeBlock() const;
@@ -39,30 +39,46 @@ class JSCell;
class CalleeBits {
public:
CalleeBits() = default;
CalleeBits(void* ptr) : m_ptr(ptr) { }
CalleeBits(int64_t value)
#if USE(JSVALUE64)
: m_ptr { reinterpret_cast<void*>(value) }
#elif USE(JSVALUE32_64)
: m_ptr { reinterpret_cast<void*>(JSValue::decode(value).payload()) }
, m_tag { JSValue::decode(value).tag() }
#endif
{ }

CalleeBits& operator=(JSCell* cell)
{
m_ptr = cell;
#if USE(JSVALUE32_64)
m_tag = JSValue::CellTag;
#endif
ASSERT(isCell());
return *this;
}

#if ENABLE(WEBASSEMBLY)
static void* boxWasm(Wasm::Callee* callee)
{
CalleeBits result(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(callee) | JSValue::WasmTag));
#if USE(JSVALUE64)
CalleeBits result { reinterpret_cast<int64_t>(callee) | JSValue::WasmTag };
ASSERT(result.isWasm());
return result.rawPtr();
#elif USE(JSVALUE32_64)
return callee; // The pointer is as is, but the corresponding tag field needs to be set to WasmTag separately.
#endif
}
#endif

bool isWasm() const
{
#if ENABLE(WEBASSEMBLY)
return (reinterpret_cast<uintptr_t>(m_ptr) & JSValue::WasmMask) == JSValue::WasmTag;
#else
#if !ENABLE(WEBASSEMBLY)
return false;
#elif USE(JSVALUE64)
return (reinterpret_cast<uintptr_t>(m_ptr) & JSValue::WasmMask) == JSValue::WasmTag;
#elif USE(JSVALUE32_64)
return m_tag == JSValue::WasmTag;
#endif
}
bool isCell() const { return !isWasm(); }
@@ -77,14 +93,21 @@ class CalleeBits {
Wasm::Callee* asWasmCallee() const
{
ASSERT(isWasm());
#if USE(JSVALUE64)
return reinterpret_cast<Wasm::Callee*>(reinterpret_cast<uintptr_t>(m_ptr) & ~JSValue::WasmTag);
#elif USE(JSVALUE32_64)
return reinterpret_cast<Wasm::Callee*>(m_ptr);
#endif
}
#endif

void* rawPtr() const { return m_ptr; }

private:
void* m_ptr { nullptr };
#if USE(JSVALUE32_64)
uint32_t m_tag { JSValue::EmptyValueTag };
#endif
};

} // namespace JSC
@@ -72,6 +72,10 @@ namespace JSC {
int64_t unboxedInt64() const;
int64_t asanUnsafeUnboxedInt64() const;
bool unboxedBoolean() const;
#if ENABLE(WEBASSEMBLY) && USE(JSVALUE32_64)
float unboxedFloat() const;
float asanUnsafeUnboxedFloat() const;
#endif
double unboxedDouble() const;
double asanUnsafeUnboxedDouble() const;
JSCell* unboxedCell() const;
@@ -188,6 +192,18 @@ namespace JSC {
return !!payload();
}

#if ENABLE(WEBASSEMBLY) && USE(JSVALUE32_64)
ALWAYS_INLINE float Register::unboxedFloat() const
{
return bitwise_cast<float>(payload());
}

SUPPRESS_ASAN ALWAYS_INLINE float Register::asanUnsafeUnboxedFloat() const
{
return bitwise_cast<float>(payload());
}
#endif

ALWAYS_INLINE double Register::unboxedDouble() const
{
return u.number;
@@ -1403,7 +1403,10 @@ class AssemblyHelpers : public MacroAssembler {
jitAssertIsJSDouble(gpr);
return unboxDoubleWithoutAssertions(gpr, resultGPR, fpr, mode);
}

void unboxDouble(JSValueRegs regs, FPRReg fpr)
{
unboxDouble(regs.tagGPR(), regs.payloadGPR(), fpr);
}
void boxDouble(FPRReg fpr, JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
{
boxDouble(fpr, regs.gpr(), mode);
@@ -38,18 +38,34 @@ macro getuOperandWide16JS(opcodeStruct, fieldName, dst)
loadh constexpr %opcodeStruct%_%fieldName%_index * 2 + OpcodeIDWide16SizeJS[PB, PC, 1], dst
end

macro getuOperandWide16Wasm(opcodeStruct, fieldName, dst)
loadh constexpr %opcodeStruct%_%fieldName%_index * 2 + OpcodeIDWide16SizeWasm[PB, PC, 1], dst
end

macro getOperandWide16JS(opcodeStruct, fieldName, dst)
loadhsi constexpr %opcodeStruct%_%fieldName%_index * 2 + OpcodeIDWide16SizeJS[PB, PC, 1], dst
end

macro getOperandWide16Wasm(opcodeStruct, fieldName, dst)
loadhsi constexpr %opcodeStruct%_%fieldName%_index * 2 + OpcodeIDWide16SizeWasm[PB, PC, 1], dst
end

macro getuOperandWide32JS(opcodeStruct, fieldName, dst)
loadi constexpr %opcodeStruct%_%fieldName%_index * 4 + OpcodeIDWide32SizeJS[PB, PC, 1], dst
end

macro getuOperandWide32Wasm(opcodeStruct, fieldName, dst)
loadi constexpr %opcodeStruct%_%fieldName%_index * 4 + OpcodeIDWide32SizeWasm[PB, PC, 1], dst
end

macro getOperandWide32JS(opcodeStruct, fieldName, dst)
loadis constexpr %opcodeStruct%_%fieldName%_index * 4 + OpcodeIDWide32SizeJS[PB, PC, 1], dst
end

macro getOperandWide32Wasm(opcodeStruct, fieldName, dst)
loadis constexpr %opcodeStruct%_%fieldName%_index * 4 + OpcodeIDWide32SizeWasm[PB, PC, 1], dst
end

macro makeReturn(get, dispatch, fn)
fn(macro(tag, payload)
move tag, t5

0 comments on commit b58fb7e

Please sign in to comment.