@typeberry/lib 0.2.0-c96e8ef → 0.2.0-eae807e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +2500 -1911
- package/index.d.ts +1956 -1864
- package/index.js +2498 -1909
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,50 +1,47 @@
|
|
|
1
1
|
import assert from 'node:assert';
|
|
2
|
-
import fs from 'node:fs';
|
|
2
|
+
import fs, { readFileSync } from 'node:fs';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
4
5
|
|
|
5
6
|
var GpVersion;
|
|
6
7
|
(function (GpVersion) {
|
|
7
8
|
GpVersion["V0_6_7"] = "0.6.7";
|
|
8
9
|
GpVersion["V0_7_0"] = "0.7.0";
|
|
9
10
|
GpVersion["V0_7_1"] = "0.7.1";
|
|
10
|
-
GpVersion["V0_7_2"] = "0.7.2
|
|
11
|
+
GpVersion["V0_7_2"] = "0.7.2";
|
|
11
12
|
})(GpVersion || (GpVersion = {}));
|
|
12
13
|
var TestSuite;
|
|
13
14
|
(function (TestSuite) {
|
|
14
15
|
TestSuite["W3F_DAVXY"] = "w3f-davxy";
|
|
15
16
|
TestSuite["JAMDUNA"] = "jamduna";
|
|
16
17
|
})(TestSuite || (TestSuite = {}));
|
|
18
|
+
const ALL_VERSIONS_IN_ORDER = [GpVersion.V0_6_7, GpVersion.V0_7_0, GpVersion.V0_7_1, GpVersion.V0_7_2];
|
|
17
19
|
const DEFAULT_SUITE = TestSuite.W3F_DAVXY;
|
|
18
|
-
const DEFAULT_VERSION = GpVersion.
|
|
20
|
+
const DEFAULT_VERSION = GpVersion.V0_7_2;
|
|
19
21
|
const env$1 = typeof process === "undefined" ? {} : process.env;
|
|
20
22
|
let CURRENT_VERSION = parseCurrentVersion(env$1.GP_VERSION) ?? DEFAULT_VERSION;
|
|
21
23
|
let CURRENT_SUITE = parseCurrentSuite(env$1.TEST_SUITE) ?? DEFAULT_SUITE;
|
|
22
|
-
const ALL_VERSIONS_IN_ORDER = [GpVersion.V0_6_7, GpVersion.V0_7_0, GpVersion.V0_7_1, GpVersion.V0_7_2];
|
|
23
24
|
function parseCurrentVersion(env) {
|
|
24
25
|
if (env === undefined) {
|
|
25
26
|
return undefined;
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
case GpVersion.V0_7_2:
|
|
32
|
-
return env;
|
|
33
|
-
default:
|
|
34
|
-
throw new Error(`Configured environment variable GP_VERSION is unknown: '${env}'. Use one of: ${ALL_VERSIONS_IN_ORDER}`);
|
|
28
|
+
for (const v of Object.values(GpVersion)) {
|
|
29
|
+
if (env === v) {
|
|
30
|
+
return v;
|
|
31
|
+
}
|
|
35
32
|
}
|
|
33
|
+
throw new Error(`Configured environment variable GP_VERSION is unknown: '${env}'. Use one of: ${ALL_VERSIONS_IN_ORDER}`);
|
|
36
34
|
}
|
|
37
35
|
function parseCurrentSuite(env) {
|
|
38
36
|
if (env === undefined) {
|
|
39
37
|
return undefined;
|
|
40
38
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
default:
|
|
46
|
-
throw new Error(`Configured environment variable TEST_SUITE is unknown: '${env}'. Use one of: ${Object.values(TestSuite)}`);
|
|
39
|
+
for (const s of Object.values(TestSuite)) {
|
|
40
|
+
if (env === s) {
|
|
41
|
+
return s;
|
|
42
|
+
}
|
|
47
43
|
}
|
|
44
|
+
throw new Error(`Configured environment variable TEST_SUITE is unknown: '${env}'. Use one of: ${Object.values(TestSuite)}`);
|
|
48
45
|
}
|
|
49
46
|
class Compatibility {
|
|
50
47
|
static override(version) {
|
|
@@ -5171,6 +5168,17 @@ class Bootnode {
|
|
|
5171
5168
|
}
|
|
5172
5169
|
}
|
|
5173
5170
|
|
|
5171
|
+
/** Implemented PVM Backends names in THE SAME ORDER as enum. */
|
|
5172
|
+
const PvmBackendNames = ["built-in", "ananas"];
|
|
5173
|
+
/** Implemented PVM Backends to choose from. */
|
|
5174
|
+
var PvmBackend;
|
|
5175
|
+
(function (PvmBackend) {
|
|
5176
|
+
/** Built-in aka. Typeberry 🫐 interpreter. */
|
|
5177
|
+
PvmBackend[PvmBackend["BuiltIn"] = 0] = "BuiltIn";
|
|
5178
|
+
/** Ananas 🍍 interpreter. */
|
|
5179
|
+
PvmBackend[PvmBackend["Ananas"] = 1] = "Ananas";
|
|
5180
|
+
})(PvmBackend || (PvmBackend = {}));
|
|
5181
|
+
|
|
5174
5182
|
var index$m = /*#__PURE__*/Object.freeze({
|
|
5175
5183
|
__proto__: null,
|
|
5176
5184
|
Bootnode: Bootnode,
|
|
@@ -5180,6 +5188,8 @@ var index$m = /*#__PURE__*/Object.freeze({
|
|
|
5180
5188
|
EST_EPOCH_LENGTH: EST_EPOCH_LENGTH,
|
|
5181
5189
|
EST_VALIDATORS: EST_VALIDATORS,
|
|
5182
5190
|
EST_VALIDATORS_SUPER_MAJORITY: EST_VALIDATORS_SUPER_MAJORITY,
|
|
5191
|
+
get PvmBackend () { return PvmBackend; },
|
|
5192
|
+
PvmBackendNames: PvmBackendNames,
|
|
5183
5193
|
fullChainSpec: fullChainSpec,
|
|
5184
5194
|
tinyChainSpec: tinyChainSpec
|
|
5185
5195
|
});
|
|
@@ -7728,6 +7738,7 @@ const DEFAULT_CONFIG = "default";
|
|
|
7728
7738
|
const NODE_DEFAULTS = {
|
|
7729
7739
|
name: isBrowser() ? "browser" : os.hostname(),
|
|
7730
7740
|
config: DEFAULT_CONFIG,
|
|
7741
|
+
pvm: PvmBackend.BuiltIn,
|
|
7731
7742
|
};
|
|
7732
7743
|
/** Chain spec chooser. */
|
|
7733
7744
|
var KnownChainSpec;
|
|
@@ -10927,6 +10938,13 @@ class StateEntries {
|
|
|
10927
10938
|
[TEST_COMPARE_USING]() {
|
|
10928
10939
|
return Object.fromEntries(this.entries);
|
|
10929
10940
|
}
|
|
10941
|
+
/** Dump state entries to JSON string (format compatible with stf vectors). */
|
|
10942
|
+
toString() {
|
|
10943
|
+
return JSON.stringify(Array.from(this.entries.entries()).map(([key, value]) => ({
|
|
10944
|
+
key,
|
|
10945
|
+
value,
|
|
10946
|
+
})), null, 2);
|
|
10947
|
+
}
|
|
10930
10948
|
[Symbol.iterator]() {
|
|
10931
10949
|
return this.entries[Symbol.iterator]();
|
|
10932
10950
|
}
|
|
@@ -12270,18 +12288,41 @@ class PendingTransfer {
|
|
|
12270
12288
|
}
|
|
12271
12289
|
}
|
|
12272
12290
|
|
|
12291
|
+
/** Attempt to convert given number into U32 gas representation. */
|
|
12292
|
+
const tryAsSmallGas = (v) => asOpaqueType(tryAsU32(v));
|
|
12293
|
+
/** Attempt to convert given number into U64 gas representation. */
|
|
12294
|
+
const tryAsBigGas = (v) => asOpaqueType(tryAsU64(v));
|
|
12295
|
+
/** Attempt to convert given number into gas. */
|
|
12296
|
+
const tryAsGas = (v) => typeof v === "number" && v < 2 ** 32 ? tryAsSmallGas(v) : tryAsBigGas(v);
|
|
12297
|
+
|
|
12298
|
+
const MAX_MEMORY_INDEX = 0xffff_ffff;
|
|
12299
|
+
const MEMORY_SIZE = MAX_MEMORY_INDEX + 1;
|
|
12300
|
+
const PAGE_SIZE_SHIFT$1 = 12;
|
|
12301
|
+
function getPageStartAddress(address) {
|
|
12302
|
+
return tryAsU32(((address >>> PAGE_SIZE_SHIFT$1) << PAGE_SIZE_SHIFT$1) >>> 0);
|
|
12303
|
+
}
|
|
12304
|
+
|
|
12305
|
+
const NO_OF_REGISTERS$1 = 13;
|
|
12306
|
+
const REGISTER_BYTE_SIZE = 8;
|
|
12307
|
+
|
|
12273
12308
|
/**
|
|
12274
|
-
*
|
|
12309
|
+
* Result codes for the PVM execution.
|
|
12275
12310
|
*
|
|
12276
|
-
* https://graypaper.fluffylabs.dev/#/
|
|
12311
|
+
* https://graypaper.fluffylabs.dev/#/ab2cdbd/2e43002e4300?v=0.7.2
|
|
12277
12312
|
*/
|
|
12278
12313
|
var Status;
|
|
12279
12314
|
(function (Status) {
|
|
12315
|
+
/** Continue */
|
|
12280
12316
|
Status[Status["OK"] = 255] = "OK";
|
|
12317
|
+
/** Finished */
|
|
12281
12318
|
Status[Status["HALT"] = 0] = "HALT";
|
|
12319
|
+
/** Panic */
|
|
12282
12320
|
Status[Status["PANIC"] = 1] = "PANIC";
|
|
12321
|
+
/** Page-fault */
|
|
12283
12322
|
Status[Status["FAULT"] = 2] = "FAULT";
|
|
12323
|
+
/** Host-call */
|
|
12284
12324
|
Status[Status["HOST"] = 3] = "HOST";
|
|
12325
|
+
/** Out of gas */
|
|
12285
12326
|
Status[Status["OOG"] = 4] = "OOG";
|
|
12286
12327
|
})(Status || (Status = {}));
|
|
12287
12328
|
|
|
@@ -12678,6 +12719,9 @@ function writeServiceIdAsLeBytes(serviceId, destination) {
|
|
|
12678
12719
|
function clampU64ToU32(value) {
|
|
12679
12720
|
return value > MAX_U32_BIG_INT ? MAX_U32 : tryAsU32(Number(value));
|
|
12680
12721
|
}
|
|
12722
|
+
function emptyRegistersBuffer() {
|
|
12723
|
+
return safeAllocUint8Array(NO_OF_REGISTERS$1 * REGISTER_BYTE_SIZE);
|
|
12724
|
+
}
|
|
12681
12725
|
|
|
12682
12726
|
var index$9 = /*#__PURE__*/Object.freeze({
|
|
12683
12727
|
__proto__: null,
|
|
@@ -12706,6 +12750,7 @@ var index$9 = /*#__PURE__*/Object.freeze({
|
|
|
12706
12750
|
get UpdatePrivilegesError () { return UpdatePrivilegesError; },
|
|
12707
12751
|
get ZeroVoidError () { return ZeroVoidError; },
|
|
12708
12752
|
clampU64ToU32: clampU64ToU32,
|
|
12753
|
+
emptyRegistersBuffer: emptyRegistersBuffer,
|
|
12709
12754
|
getServiceId: getServiceId,
|
|
12710
12755
|
getServiceIdOrCurrent: getServiceIdOrCurrent,
|
|
12711
12756
|
slotsToPreimageStatus: slotsToPreimageStatus,
|
|
@@ -12837,8 +12882,7 @@ var index$8 = /*#__PURE__*/Object.freeze({
|
|
|
12837
12882
|
MerkleMountainRange: MerkleMountainRange
|
|
12838
12883
|
});
|
|
12839
12884
|
|
|
12840
|
-
const
|
|
12841
|
-
const REGISTER_SIZE_SHIFT = 3;
|
|
12885
|
+
const REGISTER_SIZE_SHIFT = 3; // x << 3 === x * 8
|
|
12842
12886
|
const tryAsRegisterIndex = (index) => {
|
|
12843
12887
|
check `${index >= 0 && index < NO_OF_REGISTERS$1} Incorrect register index: ${index}!`;
|
|
12844
12888
|
return asOpaqueType(index);
|
|
@@ -12853,6 +12897,13 @@ class Registers {
|
|
|
12853
12897
|
this.asSigned = new BigInt64Array(bytes.buffer, bytes.byteOffset);
|
|
12854
12898
|
this.asUnsigned = new BigUint64Array(bytes.buffer, bytes.byteOffset);
|
|
12855
12899
|
}
|
|
12900
|
+
getAllEncoded() {
|
|
12901
|
+
return this.bytes;
|
|
12902
|
+
}
|
|
12903
|
+
setAllEncoded(bytes) {
|
|
12904
|
+
check `${bytes.length === this.bytes.length} Incorrect size of input registers. Got: ${bytes.length}, need: ${this.bytes.length}`;
|
|
12905
|
+
this.bytes.set(bytes, 0);
|
|
12906
|
+
}
|
|
12856
12907
|
static fromBytes(bytes) {
|
|
12857
12908
|
check `${bytes.length === NO_OF_REGISTERS$1 << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
|
|
12858
12909
|
return new Registers(bytes);
|
|
@@ -12861,9 +12912,6 @@ class Registers {
|
|
|
12861
12912
|
const offset = index << REGISTER_SIZE_SHIFT;
|
|
12862
12913
|
return this.bytes.subarray(offset, offset + len);
|
|
12863
12914
|
}
|
|
12864
|
-
getAllBytesAsLittleEndian() {
|
|
12865
|
-
return this.bytes;
|
|
12866
|
-
}
|
|
12867
12915
|
copyFrom(regs) {
|
|
12868
12916
|
const array = regs instanceof BigUint64Array ? regs : regs.asUnsigned;
|
|
12869
12917
|
this.asUnsigned.set(array);
|
|
@@ -12935,20 +12983,222 @@ function traceRegisters(...regs) {
|
|
|
12935
12983
|
return regs.map(tryAsRegisterIndex);
|
|
12936
12984
|
}
|
|
12937
12985
|
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12986
|
+
class HostCallMemory {
|
|
12987
|
+
memory;
|
|
12988
|
+
constructor(memory) {
|
|
12989
|
+
this.memory = memory;
|
|
12990
|
+
}
|
|
12991
|
+
/**
|
|
12992
|
+
* Save some bytes into memory under given address.
|
|
12993
|
+
*
|
|
12994
|
+
* NOTE: Given address is U64 (pure register value),
|
|
12995
|
+
* but we use only lower 32-bits.
|
|
12996
|
+
*/
|
|
12997
|
+
storeFrom(regAddress, bytes) {
|
|
12998
|
+
if (bytes.length === 0) {
|
|
12999
|
+
return Result$1.ok(OK);
|
|
13000
|
+
}
|
|
13001
|
+
// NOTE: We always take lower 32 bits from register value.
|
|
13002
|
+
//
|
|
13003
|
+
// https://graypaper.fluffylabs.dev/#/ab2cdbd/25ed0025ed00?v=0.7.2
|
|
13004
|
+
const address = tryAsU32(Number(regAddress & 0xffffffffn));
|
|
13005
|
+
return this.memory.store(address, bytes);
|
|
13006
|
+
}
|
|
13007
|
+
/**
|
|
13008
|
+
* Read some bytes from memory under given address.
|
|
13009
|
+
*
|
|
13010
|
+
* NOTE: Given address is U64 (pure register value),
|
|
13011
|
+
* but we use only lower 32-bits.
|
|
13012
|
+
*/
|
|
13013
|
+
loadInto(output, regAddress) {
|
|
13014
|
+
if (output.length === 0) {
|
|
13015
|
+
return Result$1.ok(OK);
|
|
13016
|
+
}
|
|
13017
|
+
// https://graypaper.fluffylabs.dev/#/ab2cdbd/25ed0025ed00?v=0.7.2
|
|
13018
|
+
//
|
|
13019
|
+
// NOTE we are taking the the lower U32 part of the register, hence it's safe.
|
|
13020
|
+
const address = tryAsU32(Number(regAddress & 0xffffffffn));
|
|
13021
|
+
return this.memory.read(address, output);
|
|
13022
|
+
}
|
|
13023
|
+
}
|
|
13024
|
+
|
|
13025
|
+
class HostCallRegisters {
|
|
13026
|
+
bytes;
|
|
13027
|
+
registers;
|
|
13028
|
+
constructor(bytes) {
|
|
13029
|
+
this.bytes = bytes;
|
|
13030
|
+
this.registers = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
13031
|
+
}
|
|
13032
|
+
/** Get U64 register value. */
|
|
13033
|
+
get(registerIndex) {
|
|
13034
|
+
return tryAsU64(this.registers.getBigUint64(registerIndex * REGISTER_BYTE_SIZE, true));
|
|
13035
|
+
}
|
|
13036
|
+
/** Set U64 register value. */
|
|
13037
|
+
set(registerIndex, value) {
|
|
13038
|
+
this.registers.setBigUint64(registerIndex * REGISTER_BYTE_SIZE, value, true);
|
|
13039
|
+
}
|
|
13040
|
+
/** Get all registers encoded into little-endian bytes. */
|
|
13041
|
+
getEncoded() {
|
|
13042
|
+
return this.bytes;
|
|
13043
|
+
}
|
|
13044
|
+
}
|
|
13045
|
+
|
|
13046
|
+
class ReturnValue {
|
|
13047
|
+
consumedGas;
|
|
13048
|
+
status;
|
|
13049
|
+
memorySlice;
|
|
13050
|
+
constructor(consumedGas, status, memorySlice) {
|
|
13051
|
+
this.consumedGas = consumedGas;
|
|
13052
|
+
this.status = status;
|
|
13053
|
+
this.memorySlice = memorySlice;
|
|
13054
|
+
check `
|
|
13055
|
+
${(status === null && memorySlice !== null) || (status !== null && memorySlice === null)}
|
|
13056
|
+
'status' and 'memorySlice' must not both be null or both be non-null — exactly one must be provided
|
|
13057
|
+
`;
|
|
13058
|
+
}
|
|
13059
|
+
static fromStatus(consumedGas, status) {
|
|
13060
|
+
return new ReturnValue(consumedGas, status, null);
|
|
13061
|
+
}
|
|
13062
|
+
static fromMemorySlice(consumedGas, memorySlice) {
|
|
13063
|
+
return new ReturnValue(consumedGas, null, memorySlice);
|
|
13064
|
+
}
|
|
13065
|
+
hasMemorySlice() {
|
|
13066
|
+
return this.memorySlice instanceof Uint8Array && this.status === null;
|
|
13067
|
+
}
|
|
13068
|
+
hasStatus() {
|
|
13069
|
+
return !this.hasMemorySlice();
|
|
13070
|
+
}
|
|
13071
|
+
}
|
|
13072
|
+
class HostCalls {
|
|
13073
|
+
pvmInstanceManager;
|
|
13074
|
+
hostCalls;
|
|
13075
|
+
constructor(pvmInstanceManager, hostCalls) {
|
|
13076
|
+
this.pvmInstanceManager = pvmInstanceManager;
|
|
13077
|
+
this.hostCalls = hostCalls;
|
|
13078
|
+
}
|
|
13079
|
+
getReturnValue(status, pvmInstance) {
|
|
13080
|
+
const gasConsumed = pvmInstance.gas.used();
|
|
13081
|
+
if (status === Status.OOG) {
|
|
13082
|
+
return ReturnValue.fromStatus(gasConsumed, status);
|
|
13083
|
+
}
|
|
13084
|
+
if (status === Status.HALT) {
|
|
13085
|
+
const regs = new HostCallRegisters(pvmInstance.registers.getAllEncoded());
|
|
13086
|
+
const memory = new HostCallMemory(pvmInstance.memory);
|
|
13087
|
+
const address = regs.get(7);
|
|
13088
|
+
// NOTE we are taking the the lower U32 part of the register, hence it's safe.
|
|
13089
|
+
const length = Number(regs.get(8) & 0xffffffffn);
|
|
13090
|
+
const result = safeAllocUint8Array(length);
|
|
13091
|
+
const loadResult = memory.loadInto(result, address);
|
|
13092
|
+
if (loadResult.isError) {
|
|
13093
|
+
return ReturnValue.fromMemorySlice(gasConsumed, new Uint8Array());
|
|
13094
|
+
}
|
|
13095
|
+
return ReturnValue.fromMemorySlice(gasConsumed, result);
|
|
13096
|
+
}
|
|
13097
|
+
return ReturnValue.fromStatus(gasConsumed, Status.PANIC);
|
|
13098
|
+
}
|
|
13099
|
+
async execute(pvmInstance) {
|
|
13100
|
+
pvmInstance.runProgram();
|
|
13101
|
+
for (;;) {
|
|
13102
|
+
let status = pvmInstance.getStatus();
|
|
13103
|
+
if (status !== Status.HOST) {
|
|
13104
|
+
return this.getReturnValue(status, pvmInstance);
|
|
13105
|
+
}
|
|
13106
|
+
check `
|
|
13107
|
+
${pvmInstance.getExitParam() !== null}
|
|
13108
|
+
"We know that the exit param is not null, because the status is 'Status.HOST'
|
|
13109
|
+
`;
|
|
13110
|
+
const hostCallIndex = pvmInstance.getExitParam() ?? -1;
|
|
13111
|
+
const gas = pvmInstance.gas;
|
|
13112
|
+
const regs = new HostCallRegisters(pvmInstance.registers.getAllEncoded());
|
|
13113
|
+
const memory = new HostCallMemory(pvmInstance.memory);
|
|
13114
|
+
const index = tryAsHostCallIndex(hostCallIndex);
|
|
13115
|
+
const hostCall = this.hostCalls.get(index);
|
|
13116
|
+
const gasBefore = gas.get();
|
|
13117
|
+
// NOTE: `basicGasCost(regs)` function is for compatibility reasons: pre GP 0.7.2
|
|
13118
|
+
const basicGasCost = typeof hostCall.basicGasCost === "number" ? hostCall.basicGasCost : hostCall.basicGasCost(regs);
|
|
13119
|
+
const underflow = gas.sub(basicGasCost);
|
|
13120
|
+
const pcLog = `[PC: ${pvmInstance.getPC()}]`;
|
|
13121
|
+
if (underflow) {
|
|
13122
|
+
this.hostCalls.traceHostCall(`${pcLog} OOG`, index, hostCall, regs, gas.get());
|
|
13123
|
+
return ReturnValue.fromStatus(gas.used(), Status.OOG);
|
|
13124
|
+
}
|
|
13125
|
+
this.hostCalls.traceHostCall(`${pcLog} Invoking`, index, hostCall, regs, gasBefore);
|
|
13126
|
+
const result = await hostCall.execute(gas, regs, memory);
|
|
13127
|
+
this.hostCalls.traceHostCall(result === undefined ? `${pcLog} Result` : `${pcLog} Status(${PvmExecution[result]})`, index, hostCall, regs, gas.get());
|
|
13128
|
+
pvmInstance.registers.setAllEncoded(regs.getEncoded());
|
|
13129
|
+
if (result === PvmExecution.Halt) {
|
|
13130
|
+
status = Status.HALT;
|
|
13131
|
+
return this.getReturnValue(status, pvmInstance);
|
|
13132
|
+
}
|
|
13133
|
+
if (result === PvmExecution.Panic) {
|
|
13134
|
+
status = Status.PANIC;
|
|
13135
|
+
return this.getReturnValue(status, pvmInstance);
|
|
13136
|
+
}
|
|
13137
|
+
if (result === PvmExecution.OOG) {
|
|
13138
|
+
status = Status.OOG;
|
|
13139
|
+
return this.getReturnValue(status, pvmInstance);
|
|
13140
|
+
}
|
|
13141
|
+
if (result === undefined) {
|
|
13142
|
+
pvmInstance.runProgram();
|
|
13143
|
+
status = pvmInstance.getStatus();
|
|
13144
|
+
continue;
|
|
13145
|
+
}
|
|
13146
|
+
assertNever(result);
|
|
13147
|
+
}
|
|
13148
|
+
}
|
|
13149
|
+
async runProgram(program, args, initialPc, initialGas) {
|
|
13150
|
+
const pvmInstance = await this.pvmInstanceManager.getInstance();
|
|
13151
|
+
pvmInstance.resetJam(program, args, initialPc, initialGas);
|
|
13152
|
+
try {
|
|
13153
|
+
return await this.execute(pvmInstance);
|
|
13154
|
+
}
|
|
13155
|
+
finally {
|
|
13156
|
+
this.pvmInstanceManager.releaseInstance(pvmInstance);
|
|
13157
|
+
}
|
|
13158
|
+
}
|
|
13159
|
+
}
|
|
13160
|
+
|
|
13161
|
+
const logger$3 = Logger.new(import.meta.filename, "host-calls-pvm");
|
|
13162
|
+
/** Container for all available host calls. */
|
|
13163
|
+
class HostCallsManager {
|
|
13164
|
+
hostCalls = new Map();
|
|
13165
|
+
missing;
|
|
13166
|
+
constructor({ missing, handlers = [], }) {
|
|
13167
|
+
this.missing = missing;
|
|
13168
|
+
for (const handler of handlers) {
|
|
13169
|
+
check `${this.hostCalls.get(handler.index) === undefined} Overwriting host call handler at index ${handler.index}`;
|
|
13170
|
+
this.hostCalls.set(handler.index, handler);
|
|
13171
|
+
}
|
|
13172
|
+
}
|
|
13173
|
+
/** Get a host call by index. */
|
|
13174
|
+
get(hostCallIndex) {
|
|
13175
|
+
return this.hostCalls.get(hostCallIndex) ?? this.missing;
|
|
13176
|
+
}
|
|
13177
|
+
traceHostCall(context, hostCallIndex, hostCallHandler, registers, gas) {
|
|
13178
|
+
const { currentServiceId } = hostCallHandler;
|
|
13179
|
+
const requested = hostCallIndex !== hostCallHandler.index ? ` (${hostCallIndex})` : "";
|
|
13180
|
+
const name = `${hostCallHandler.constructor.name}:${hostCallHandler.index}`;
|
|
13181
|
+
const registerValues = hostCallHandler.tracedRegisters
|
|
13182
|
+
.map((idx) => [idx.toString().padStart(2, "0"), registers.get(idx)])
|
|
13183
|
+
.filter((v) => v[1] !== 0n)
|
|
13184
|
+
.map(([idx, value]) => {
|
|
13185
|
+
return `r${idx}=${value} (0x${value.toString(16)})`;
|
|
13186
|
+
})
|
|
13187
|
+
.join(", ");
|
|
13188
|
+
logger$3.insane `[${currentServiceId}] ${context} ${name}${requested}. Gas: ${gas}. Regs: ${registerValues}.`;
|
|
13189
|
+
}
|
|
13190
|
+
}
|
|
13191
|
+
|
|
12944
13192
|
/** Create a new gas counter instance depending on the gas value. */
|
|
12945
13193
|
function gasCounter(gas) {
|
|
12946
13194
|
return new GasCounterU64(tryAsU64(gas));
|
|
12947
13195
|
}
|
|
12948
13196
|
class GasCounterU64 {
|
|
12949
13197
|
gas;
|
|
13198
|
+
initialGas;
|
|
12950
13199
|
constructor(gas) {
|
|
12951
13200
|
this.gas = gas;
|
|
13201
|
+
this.initialGas = tryAsGas(gas);
|
|
12952
13202
|
}
|
|
12953
13203
|
set(g) {
|
|
12954
13204
|
this.gas = tryAsU64(g);
|
|
@@ -12965,1593 +13215,1788 @@ class GasCounterU64 {
|
|
|
12965
13215
|
this.gas = tryAsU64(0n);
|
|
12966
13216
|
return true;
|
|
12967
13217
|
}
|
|
13218
|
+
used() {
|
|
13219
|
+
const gasConsumed = tryAsU64(this.initialGas) - this.gas;
|
|
13220
|
+
// In we have less than zero left we assume that all gas has been consumed.
|
|
13221
|
+
if (gasConsumed < 0) {
|
|
13222
|
+
return this.initialGas;
|
|
13223
|
+
}
|
|
13224
|
+
return tryAsGas(gasConsumed);
|
|
13225
|
+
}
|
|
12968
13226
|
}
|
|
12969
13227
|
|
|
13228
|
+
const tryAsMemoryIndex = (index) => {
|
|
13229
|
+
check `${index >= 0 && index <= MAX_MEMORY_INDEX} Incorrect memory index: ${index}!`;
|
|
13230
|
+
return asOpaqueType(index);
|
|
13231
|
+
};
|
|
13232
|
+
const tryAsSbrkIndex = (index) => {
|
|
13233
|
+
check `${index >= 0 && index <= MAX_MEMORY_INDEX + 1} Incorrect sbrk index: ${index}!`;
|
|
13234
|
+
return asOpaqueType(index);
|
|
13235
|
+
};
|
|
13236
|
+
|
|
13237
|
+
const PAGE_SIZE_SHIFT = 12;
|
|
13238
|
+
// PAGE_SIZE has to be a power of 2
|
|
13239
|
+
const PAGE_SIZE$1 = 1 << PAGE_SIZE_SHIFT;
|
|
13240
|
+
const MIN_ALLOCATION_SHIFT = (() => {
|
|
13241
|
+
const MIN_ALLOCATION_SHIFT = 7;
|
|
13242
|
+
check `${MIN_ALLOCATION_SHIFT < PAGE_SIZE_SHIFT} incorrect minimal allocation shift`;
|
|
13243
|
+
return MIN_ALLOCATION_SHIFT;
|
|
13244
|
+
})();
|
|
13245
|
+
const MIN_ALLOCATION_LENGTH = PAGE_SIZE$1 >> MIN_ALLOCATION_SHIFT;
|
|
13246
|
+
const LAST_PAGE_NUMBER = (MEMORY_SIZE - PAGE_SIZE$1) / PAGE_SIZE$1;
|
|
13247
|
+
/** https://graypaper.fluffylabs.dev/#/68eaa1f/35a60235a602?v=0.6.4 */
|
|
13248
|
+
const RESERVED_NUMBER_OF_PAGES = 16;
|
|
13249
|
+
/** https://graypaper.fluffylabs.dev/#/68eaa1f/35a60235a602?v=0.6.4 */
|
|
13250
|
+
const MAX_NUMBER_OF_PAGES = MEMORY_SIZE / PAGE_SIZE$1;
|
|
13251
|
+
|
|
13252
|
+
/** Ensure that given memory `index` is within `[0...PAGE_SIZE)` and can be used to index a page */
|
|
13253
|
+
const tryAsPageIndex = (index) => {
|
|
13254
|
+
check `${index >= 0 && index < PAGE_SIZE$1}, Incorect page index: ${index}!`;
|
|
13255
|
+
return asOpaqueType(index);
|
|
13256
|
+
};
|
|
13257
|
+
/** Ensure that given `index` represents an index of one of the pages. */
|
|
13258
|
+
const tryAsPageNumber = (index) => {
|
|
13259
|
+
check `${index >= 0 && index <= LAST_PAGE_NUMBER}, Incorect page number: ${index}!`;
|
|
13260
|
+
return asOpaqueType(index);
|
|
13261
|
+
};
|
|
12970
13262
|
/**
|
|
12971
|
-
*
|
|
12972
|
-
*/
|
|
12973
|
-
const MAX_INSTRUCTION_DISTANCE = 25;
|
|
12974
|
-
/**
|
|
12975
|
-
* Mask class is an implementation of skip function defined in GP.
|
|
13263
|
+
* Get the next page number and wrap the result if it is bigger than LAST_PAGE_NUMBER
|
|
12976
13264
|
*
|
|
12977
|
-
*
|
|
13265
|
+
* GP references:
|
|
13266
|
+
* 1. The modulo subscription operator is used in all load/store instructions, for example:
|
|
13267
|
+
* https://graypaper.fluffylabs.dev/#/579bd12/25af0125af01
|
|
13268
|
+
*
|
|
13269
|
+
* 2. Here is the definition of the modulo subscription operator:
|
|
13270
|
+
* https://graypaper.fluffylabs.dev/#/579bd12/073a00073a00
|
|
12978
13271
|
*/
|
|
12979
|
-
|
|
12980
|
-
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
13272
|
+
function getNextPageNumber(pageNumber) {
|
|
13273
|
+
const newPageNumber = pageNumber === LAST_PAGE_NUMBER ? 0 : pageNumber + 1;
|
|
13274
|
+
return tryAsPageNumber(newPageNumber);
|
|
13275
|
+
}
|
|
13276
|
+
|
|
13277
|
+
function alignToPageSize$1(length) {
|
|
13278
|
+
return PAGE_SIZE$1 * Math.ceil(length / PAGE_SIZE$1);
|
|
13279
|
+
}
|
|
13280
|
+
function getPageNumber(address) {
|
|
13281
|
+
return tryAsPageNumber(address >>> PAGE_SIZE_SHIFT);
|
|
13282
|
+
}
|
|
13283
|
+
function getStartPageIndex(address) {
|
|
13284
|
+
return tryAsMemoryIndex((address >>> PAGE_SIZE_SHIFT) << PAGE_SIZE_SHIFT);
|
|
13285
|
+
}
|
|
13286
|
+
function getStartPageIndexFromPageNumber(pageNumber) {
|
|
13287
|
+
// >>> 0 is needed to avoid changing sign of the number
|
|
13288
|
+
return tryAsMemoryIndex((pageNumber << PAGE_SIZE_SHIFT) >>> 0);
|
|
13289
|
+
}
|
|
13290
|
+
|
|
13291
|
+
class PageFault {
|
|
13292
|
+
address;
|
|
13293
|
+
isAccessFault;
|
|
13294
|
+
constructor(address, isAccessFault = true) {
|
|
13295
|
+
this.address = address;
|
|
13296
|
+
this.isAccessFault = isAccessFault;
|
|
12994
13297
|
}
|
|
12995
|
-
|
|
12996
|
-
|
|
13298
|
+
static fromPageNumber(maybePageNumber, isAccessFault = false) {
|
|
13299
|
+
const pageNumber = tryAsPageNumber(maybePageNumber);
|
|
13300
|
+
const startPageIndex = getStartPageIndexFromPageNumber(pageNumber);
|
|
13301
|
+
return new PageFault(tryAsU32(startPageIndex), isAccessFault);
|
|
12997
13302
|
}
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
|
|
13303
|
+
static fromMemoryIndex(maybeMemoryIndex, isAccessFault = false) {
|
|
13304
|
+
const memoryIndex = tryAsMemoryIndex(maybeMemoryIndex % MEMORY_SIZE);
|
|
13305
|
+
const startPageIndex = getStartPageIndex(memoryIndex);
|
|
13306
|
+
return new PageFault(tryAsU32(startPageIndex), isAccessFault);
|
|
13001
13307
|
}
|
|
13002
|
-
|
|
13003
|
-
|
|
13004
|
-
|
|
13005
|
-
|
|
13006
|
-
if (mask.isSet(i)) {
|
|
13007
|
-
lastInstructionOffset = 0;
|
|
13008
|
-
}
|
|
13009
|
-
else {
|
|
13010
|
-
lastInstructionOffset++;
|
|
13011
|
-
}
|
|
13012
|
-
table[i] = lastInstructionOffset;
|
|
13013
|
-
}
|
|
13014
|
-
return table;
|
|
13308
|
+
}
|
|
13309
|
+
class IncorrectSbrkIndex extends Error {
|
|
13310
|
+
constructor() {
|
|
13311
|
+
super("Space between sbrk index and max heap index should be empty!");
|
|
13015
13312
|
}
|
|
13016
|
-
|
|
13017
|
-
|
|
13313
|
+
}
|
|
13314
|
+
class FinalizedBuilderModification extends Error {
|
|
13315
|
+
constructor() {
|
|
13316
|
+
super("MemoryBuilder was finalized and cannot be changed!");
|
|
13018
13317
|
}
|
|
13019
13318
|
}
|
|
13020
|
-
|
|
13021
|
-
var ArgumentType;
|
|
13022
|
-
(function (ArgumentType) {
|
|
13023
|
-
ArgumentType[ArgumentType["NO_ARGUMENTS"] = 0] = "NO_ARGUMENTS";
|
|
13024
|
-
ArgumentType[ArgumentType["ONE_IMMEDIATE"] = 1] = "ONE_IMMEDIATE";
|
|
13025
|
-
ArgumentType[ArgumentType["TWO_IMMEDIATES"] = 2] = "TWO_IMMEDIATES";
|
|
13026
|
-
ArgumentType[ArgumentType["ONE_OFFSET"] = 3] = "ONE_OFFSET";
|
|
13027
|
-
ArgumentType[ArgumentType["ONE_REGISTER_ONE_IMMEDIATE"] = 4] = "ONE_REGISTER_ONE_IMMEDIATE";
|
|
13028
|
-
ArgumentType[ArgumentType["ONE_REGISTER_TWO_IMMEDIATES"] = 5] = "ONE_REGISTER_TWO_IMMEDIATES";
|
|
13029
|
-
ArgumentType[ArgumentType["ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET"] = 6] = "ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET";
|
|
13030
|
-
ArgumentType[ArgumentType["TWO_REGISTERS"] = 7] = "TWO_REGISTERS";
|
|
13031
|
-
ArgumentType[ArgumentType["TWO_REGISTERS_ONE_IMMEDIATE"] = 8] = "TWO_REGISTERS_ONE_IMMEDIATE";
|
|
13032
|
-
ArgumentType[ArgumentType["TWO_REGISTERS_ONE_OFFSET"] = 9] = "TWO_REGISTERS_ONE_OFFSET";
|
|
13033
|
-
ArgumentType[ArgumentType["TWO_REGISTERS_TWO_IMMEDIATES"] = 10] = "TWO_REGISTERS_TWO_IMMEDIATES";
|
|
13034
|
-
ArgumentType[ArgumentType["THREE_REGISTERS"] = 11] = "THREE_REGISTERS";
|
|
13035
|
-
ArgumentType[ArgumentType["ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE"] = 12] = "ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE";
|
|
13036
|
-
})(ArgumentType || (ArgumentType = {}));
|
|
13037
|
-
|
|
13038
|
-
const BUFFER_SIZE = 8;
|
|
13039
|
-
const IMMEDIATE_SIZE$1 = 4;
|
|
13040
|
-
const U32_INDEX = 0;
|
|
13041
|
-
const U64_INDEX = 0;
|
|
13042
|
-
class ImmediateDecoder {
|
|
13043
|
-
u32;
|
|
13044
|
-
i32;
|
|
13045
|
-
u64;
|
|
13046
|
-
i64;
|
|
13047
|
-
view;
|
|
13048
|
-
bytes;
|
|
13319
|
+
class ReservedMemoryFault extends Error {
|
|
13049
13320
|
constructor() {
|
|
13050
|
-
|
|
13051
|
-
this.u32 = new Uint32Array(buffer);
|
|
13052
|
-
this.i32 = new Int32Array(buffer);
|
|
13053
|
-
this.u64 = new BigUint64Array(buffer);
|
|
13054
|
-
this.i64 = new BigInt64Array(buffer);
|
|
13055
|
-
this.view = new DataView(buffer);
|
|
13056
|
-
this.bytes = new Uint8Array(buffer);
|
|
13321
|
+
super("You are trying to access reserved memory!");
|
|
13057
13322
|
}
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
this.view.setUint8(i, prefix);
|
|
13068
|
-
}
|
|
13323
|
+
}
|
|
13324
|
+
class PageNotExist extends Error {
|
|
13325
|
+
constructor() {
|
|
13326
|
+
super("You try to fill data on memory page that does not exist!");
|
|
13327
|
+
}
|
|
13328
|
+
}
|
|
13329
|
+
class OutOfMemory extends Error {
|
|
13330
|
+
constructor() {
|
|
13331
|
+
super("Out of memory");
|
|
13069
13332
|
}
|
|
13333
|
+
}
|
|
13334
|
+
|
|
13335
|
+
/**
|
|
13336
|
+
* A representation of open-ended range of consecutive indices in memory,
|
|
13337
|
+
* possibly empty or wrapping around.
|
|
13338
|
+
*
|
|
13339
|
+
* `[start, start + length)`
|
|
13340
|
+
*/
|
|
13341
|
+
class MemoryRange {
|
|
13342
|
+
start;
|
|
13343
|
+
length;
|
|
13070
13344
|
/**
|
|
13071
|
-
*
|
|
13345
|
+
* Exclusive end index of the range.
|
|
13346
|
+
*
|
|
13347
|
+
* NOTE: The index may be wrapped around and smaller than `start`!
|
|
13072
13348
|
*/
|
|
13073
|
-
|
|
13074
|
-
return this.u32[U32_INDEX];
|
|
13075
|
-
}
|
|
13349
|
+
end;
|
|
13076
13350
|
/**
|
|
13077
|
-
*
|
|
13351
|
+
* Inclusive last index of the range (present unless the range is empty).
|
|
13352
|
+
*
|
|
13353
|
+
* NOTE: the index may be wrapped around and smaller than `start`!
|
|
13078
13354
|
*/
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13355
|
+
lastIndex = null;
|
|
13356
|
+
constructor(start, length) {
|
|
13357
|
+
this.start = start;
|
|
13358
|
+
this.length = length;
|
|
13359
|
+
this.end = tryAsMemoryIndex((this.start + this.length) % MEMORY_SIZE);
|
|
13360
|
+
if (length > 0) {
|
|
13361
|
+
this.lastIndex = tryAsMemoryIndex((this.end - 1 + MEMORY_SIZE) % MEMORY_SIZE);
|
|
13362
|
+
}
|
|
13084
13363
|
}
|
|
13085
|
-
|
|
13086
|
-
|
|
13364
|
+
/** Creates a memory range from given starting point and length */
|
|
13365
|
+
static fromStartAndLength(start, length) {
|
|
13366
|
+
if (!Number.isInteger(length) || length < 0 || length > MEMORY_SIZE) {
|
|
13367
|
+
throw new TypeError(`length must be a non-negative integer and less than ${MEMORY_SIZE}, got ${length}`);
|
|
13368
|
+
}
|
|
13369
|
+
return new MemoryRange(start, length);
|
|
13087
13370
|
}
|
|
13088
|
-
|
|
13089
|
-
|
|
13371
|
+
/** Checks if a range is empty (`length === 0`) */
|
|
13372
|
+
isEmpty() {
|
|
13373
|
+
return this.length === 0;
|
|
13090
13374
|
}
|
|
13091
|
-
|
|
13092
|
-
|
|
13375
|
+
/** Returns true if the range is wrapped (`start` >= `end`) and is not empty */
|
|
13376
|
+
isWrapped() {
|
|
13377
|
+
return this.start >= this.end && !this.isEmpty();
|
|
13093
13378
|
}
|
|
13094
|
-
|
|
13095
|
-
|
|
13379
|
+
/** Checks if given memory address is within the range */
|
|
13380
|
+
isInRange(address) {
|
|
13381
|
+
if (this.isWrapped()) {
|
|
13382
|
+
return address >= this.start || address < this.end;
|
|
13383
|
+
}
|
|
13384
|
+
return address >= this.start && address < this.end;
|
|
13096
13385
|
}
|
|
13097
|
-
|
|
13098
|
-
|
|
13386
|
+
/** Checks if this range overlaps with another range */
|
|
13387
|
+
overlapsWith(other) {
|
|
13388
|
+
if (this.lastIndex === null || other.lastIndex === null) {
|
|
13389
|
+
return false;
|
|
13390
|
+
}
|
|
13391
|
+
return (this.isInRange(other.start) ||
|
|
13392
|
+
this.isInRange(other.lastIndex) ||
|
|
13393
|
+
other.isInRange(this.start) ||
|
|
13394
|
+
other.isInRange(this.lastIndex));
|
|
13099
13395
|
}
|
|
13100
13396
|
}
|
|
13397
|
+
/**
|
|
13398
|
+
* The first 16 pages of memory are reserved.
|
|
13399
|
+
*
|
|
13400
|
+
* https://graypaper.fluffylabs.dev/#/cc517d7/24d00024d000?v=0.6.5
|
|
13401
|
+
*
|
|
13402
|
+
* it should be in `memory-consts` but it cannot be there because of circular dependency
|
|
13403
|
+
*/
|
|
13404
|
+
const RESERVED_MEMORY_RANGE = MemoryRange.fromStartAndLength(tryAsMemoryIndex(0), RESERVED_NUMBER_OF_PAGES * PAGE_SIZE$1);
|
|
13101
13405
|
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13406
|
+
/**
|
|
13407
|
+
* A half-open range of memory pages. Similarly to [`MemoryRange`], can be empty
|
|
13408
|
+
* or wrapped around the memory.
|
|
13409
|
+
*/
|
|
13410
|
+
class PageRange {
|
|
13411
|
+
start;
|
|
13412
|
+
length;
|
|
13413
|
+
/**
|
|
13414
|
+
* Exclusive end of the page range.
|
|
13415
|
+
*
|
|
13416
|
+
* NOTE: it may be smaller than `start` in case the range is wrapped.
|
|
13417
|
+
*/
|
|
13418
|
+
end;
|
|
13419
|
+
constructor(start, length) {
|
|
13420
|
+
this.start = start;
|
|
13421
|
+
this.length = length;
|
|
13422
|
+
this.end = tryAsPageNumber((this.start + this.length) % MAX_NUMBER_OF_PAGES);
|
|
13114
13423
|
}
|
|
13115
|
-
|
|
13116
|
-
|
|
13424
|
+
/**
|
|
13425
|
+
* Creates range of pages that includes all indices in a given memory range.
|
|
13426
|
+
*
|
|
13427
|
+
* Example: For memory range `[PAGE_SIZE, MEMORY_SIZE - PAGE_SIZE)`
|
|
13428
|
+
* we will get `[1, MAX_NUMBER_OF_PAGES - 1)` page range.
|
|
13429
|
+
*/
|
|
13430
|
+
static fromMemoryRange(range) {
|
|
13431
|
+
const startPage = getPageNumber(range.start);
|
|
13432
|
+
if (range.isEmpty()) {
|
|
13433
|
+
return new PageRange(startPage, 0);
|
|
13434
|
+
}
|
|
13435
|
+
// lastIndex is not null because we just ensured that the range is not empty
|
|
13436
|
+
const pageWithLastIndex = getPageNumber(range.lastIndex ?? range.end);
|
|
13437
|
+
const endPage = getNextPageNumber(pageWithLastIndex);
|
|
13438
|
+
if ((startPage === endPage || startPage === pageWithLastIndex) && range.length > PAGE_SIZE$1) {
|
|
13439
|
+
// full range
|
|
13440
|
+
return new PageRange(startPage, MAX_NUMBER_OF_PAGES);
|
|
13441
|
+
}
|
|
13442
|
+
const length = startPage < endPage ? endPage - startPage : MAX_NUMBER_OF_PAGES - startPage + endPage;
|
|
13443
|
+
return PageRange.fromStartAndLength(startPage, length);
|
|
13117
13444
|
}
|
|
13118
|
-
|
|
13119
|
-
|
|
13445
|
+
/** Creates a page range from given starting point and length */
|
|
13446
|
+
static fromStartAndLength(start, length) {
|
|
13447
|
+
if (!Number.isInteger(length) || length < 0 || length > MAX_NUMBER_OF_PAGES) {
|
|
13448
|
+
throw new TypeError(`length must be a non-negative integer and less than ${MAX_NUMBER_OF_PAGES}, got ${length}`);
|
|
13449
|
+
}
|
|
13450
|
+
return new PageRange(start, length);
|
|
13120
13451
|
}
|
|
13121
|
-
|
|
13122
|
-
|
|
13452
|
+
/** Returns true if the page range is wrapped (`start` >= `end`) and is not empty */
|
|
13453
|
+
isWrapped() {
|
|
13454
|
+
return this.start >= this.end && !this.isEmpty();
|
|
13123
13455
|
}
|
|
13124
|
-
|
|
13125
|
-
|
|
13456
|
+
/** Checks if given page number is within the range */
|
|
13457
|
+
isInRange(page) {
|
|
13458
|
+
if (this.isWrapped()) {
|
|
13459
|
+
return page >= this.start || page < this.end;
|
|
13460
|
+
}
|
|
13461
|
+
return page >= this.start && page < this.end;
|
|
13126
13462
|
}
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13130
|
-
class ArgsDecoder {
|
|
13131
|
-
nibblesDecoder = new NibblesDecoder();
|
|
13132
|
-
offsetDecoder = new ImmediateDecoder();
|
|
13133
|
-
code = new Uint8Array();
|
|
13134
|
-
mask = Mask.empty();
|
|
13135
|
-
reset(code, mask) {
|
|
13136
|
-
this.code = code;
|
|
13137
|
-
this.mask = mask;
|
|
13463
|
+
/** Checks if a range is empty (`length === 0`) */
|
|
13464
|
+
isEmpty() {
|
|
13465
|
+
return this.length === 0;
|
|
13138
13466
|
}
|
|
13139
|
-
|
|
13140
|
-
|
|
13141
|
-
|
|
13142
|
-
switch (result.type) {
|
|
13143
|
-
case ArgumentType.NO_ARGUMENTS:
|
|
13144
|
-
break;
|
|
13145
|
-
case ArgumentType.ONE_IMMEDIATE: {
|
|
13146
|
-
const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, nextInstructionDistance - 1);
|
|
13147
|
-
const argsStartIndex = pc + 1;
|
|
13148
|
-
result.immediateDecoder.setBytes(this.code.subarray(argsStartIndex, argsStartIndex + immediateLength));
|
|
13149
|
-
break;
|
|
13150
|
-
}
|
|
13151
|
-
case ArgumentType.THREE_REGISTERS: {
|
|
13152
|
-
const firstByte = this.code[pc + 1];
|
|
13153
|
-
const secondByte = this.code[pc + 2];
|
|
13154
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13155
|
-
result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13156
|
-
result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
13157
|
-
this.nibblesDecoder.setByte(secondByte);
|
|
13158
|
-
result.thirdRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13159
|
-
break;
|
|
13160
|
-
}
|
|
13161
|
-
case ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE: {
|
|
13162
|
-
const firstByte = this.code[pc + 1];
|
|
13163
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13164
|
-
result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13165
|
-
result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
13166
|
-
const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
|
|
13167
|
-
const immediateStartIndex = pc + 2;
|
|
13168
|
-
const immediateEndIndex = immediateStartIndex + immediateLength;
|
|
13169
|
-
result.immediateDecoder.setBytes(this.code.subarray(immediateStartIndex, immediateEndIndex));
|
|
13170
|
-
break;
|
|
13171
|
-
}
|
|
13172
|
-
case ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET: {
|
|
13173
|
-
const firstByte = this.code[pc + 1];
|
|
13174
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13175
|
-
result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13176
|
-
const immediateLength = this.nibblesDecoder.getHighNibbleAsLength();
|
|
13177
|
-
const immediateStartIndex = pc + 2;
|
|
13178
|
-
const immediateEndIndex = immediateStartIndex + immediateLength;
|
|
13179
|
-
result.immediateDecoder.setBytes(this.code.subarray(immediateStartIndex, immediateEndIndex));
|
|
13180
|
-
const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - immediateLength));
|
|
13181
|
-
const offsetStartIndex = pc + 2 + immediateLength;
|
|
13182
|
-
const offsetEndIndex = offsetStartIndex + offsetLength;
|
|
13183
|
-
this.offsetDecoder.setBytes(this.code.subarray(offsetStartIndex, offsetEndIndex));
|
|
13184
|
-
result.nextPc = pc + this.offsetDecoder.getSigned();
|
|
13185
|
-
break;
|
|
13186
|
-
}
|
|
13187
|
-
case ArgumentType.TWO_REGISTERS_ONE_OFFSET: {
|
|
13188
|
-
const firstByte = this.code[pc + 1];
|
|
13189
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13190
|
-
result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13191
|
-
result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
13192
|
-
const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
|
|
13193
|
-
const offsetStartIndex = pc + 2;
|
|
13194
|
-
const offsetEndIndex = offsetStartIndex + offsetLength;
|
|
13195
|
-
this.offsetDecoder.setBytes(this.code.subarray(offsetStartIndex, offsetEndIndex));
|
|
13196
|
-
result.nextPc = pc + this.offsetDecoder.getSigned();
|
|
13197
|
-
break;
|
|
13198
|
-
}
|
|
13199
|
-
case ArgumentType.TWO_REGISTERS: {
|
|
13200
|
-
const firstByte = this.code[pc + 1];
|
|
13201
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13202
|
-
result.firstRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
13203
|
-
result.secondRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13204
|
-
break;
|
|
13205
|
-
}
|
|
13206
|
-
case ArgumentType.ONE_OFFSET: {
|
|
13207
|
-
const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, nextInstructionDistance - 1);
|
|
13208
|
-
const offsetStartIndex = pc + 1;
|
|
13209
|
-
const offsetEndIndex = offsetStartIndex + offsetLength;
|
|
13210
|
-
const offsetBytes = this.code.subarray(offsetStartIndex, offsetEndIndex);
|
|
13211
|
-
this.offsetDecoder.setBytes(offsetBytes);
|
|
13212
|
-
const offsetValue = this.offsetDecoder.getSigned();
|
|
13213
|
-
result.nextPc = pc + offsetValue;
|
|
13214
|
-
break;
|
|
13215
|
-
}
|
|
13216
|
-
case ArgumentType.ONE_REGISTER_ONE_IMMEDIATE: {
|
|
13217
|
-
const firstByte = this.code[pc + 1];
|
|
13218
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13219
|
-
result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13220
|
-
const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
|
|
13221
|
-
const immediateStartIndex = pc + 2;
|
|
13222
|
-
const immediateEndIndex = immediateStartIndex + immediateLength;
|
|
13223
|
-
const immediateBytes = this.code.subarray(immediateStartIndex, immediateEndIndex);
|
|
13224
|
-
result.immediateDecoder.setBytes(immediateBytes);
|
|
13225
|
-
break;
|
|
13226
|
-
}
|
|
13227
|
-
case ArgumentType.TWO_IMMEDIATES: {
|
|
13228
|
-
const firstByte = this.code[pc + 1];
|
|
13229
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13230
|
-
const firstImmediateLength = this.nibblesDecoder.getLowNibbleAsLength();
|
|
13231
|
-
const firstImmediateStartIndex = pc + 2;
|
|
13232
|
-
const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
|
|
13233
|
-
const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
|
|
13234
|
-
result.firstImmediateDecoder.setBytes(firstImmediateBytes);
|
|
13235
|
-
const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - firstImmediateLength));
|
|
13236
|
-
const secondImmediateStartIndex = firstImmediateEndIndex;
|
|
13237
|
-
const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
|
|
13238
|
-
const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
|
|
13239
|
-
result.secondImmediateDecoder.setBytes(secondImmediateBytes);
|
|
13240
|
-
break;
|
|
13241
|
-
}
|
|
13242
|
-
case ArgumentType.ONE_REGISTER_TWO_IMMEDIATES: {
|
|
13243
|
-
const firstByte = this.code[pc + 1];
|
|
13244
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13245
|
-
result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13246
|
-
const firstImmediateLength = this.nibblesDecoder.getHighNibbleAsLength();
|
|
13247
|
-
const firstImmediateStartIndex = pc + 2;
|
|
13248
|
-
const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
|
|
13249
|
-
const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
|
|
13250
|
-
result.firstImmediateDecoder.setBytes(firstImmediateBytes);
|
|
13251
|
-
const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - firstImmediateLength));
|
|
13252
|
-
const secondImmediateStartIndex = firstImmediateEndIndex;
|
|
13253
|
-
const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
|
|
13254
|
-
const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
|
|
13255
|
-
result.secondImmediateDecoder.setBytes(secondImmediateBytes);
|
|
13256
|
-
break;
|
|
13257
|
-
}
|
|
13258
|
-
case ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES: {
|
|
13259
|
-
const firstByte = this.code[pc + 1];
|
|
13260
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13261
|
-
result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13262
|
-
result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
13263
|
-
const secondByte = this.code[pc + 2];
|
|
13264
|
-
this.nibblesDecoder.setByte(secondByte);
|
|
13265
|
-
const firstImmediateLength = this.nibblesDecoder.getLowNibbleAsLength();
|
|
13266
|
-
const firstImmediateStartIndex = pc + 3;
|
|
13267
|
-
const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
|
|
13268
|
-
const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
|
|
13269
|
-
result.firstImmediateDecoder.setBytes(firstImmediateBytes);
|
|
13270
|
-
const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 3 - firstImmediateLength));
|
|
13271
|
-
const secondImmediateStartIndex = firstImmediateEndIndex;
|
|
13272
|
-
const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
|
|
13273
|
-
const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
|
|
13274
|
-
result.secondImmediateDecoder.setBytes(secondImmediateBytes);
|
|
13275
|
-
break;
|
|
13276
|
-
}
|
|
13277
|
-
case ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE: {
|
|
13278
|
-
const firstByte = this.code[pc + 1];
|
|
13279
|
-
this.nibblesDecoder.setByte(firstByte);
|
|
13280
|
-
result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
13281
|
-
const immediateStartIndex = pc + 2;
|
|
13282
|
-
const immediateEndIndex = immediateStartIndex + 8;
|
|
13283
|
-
const immediateBytes = this.code.subarray(immediateStartIndex, immediateEndIndex);
|
|
13284
|
-
result.immediateDecoder.setBytes(immediateBytes);
|
|
13285
|
-
break;
|
|
13286
|
-
}
|
|
13467
|
+
*[Symbol.iterator]() {
|
|
13468
|
+
if (this.isEmpty()) {
|
|
13469
|
+
return;
|
|
13287
13470
|
}
|
|
13471
|
+
const end = this.end;
|
|
13472
|
+
let i = this.start;
|
|
13473
|
+
do {
|
|
13474
|
+
yield i;
|
|
13475
|
+
i = getNextPageNumber(i);
|
|
13476
|
+
} while (i !== end);
|
|
13288
13477
|
}
|
|
13289
13478
|
}
|
|
13290
13479
|
|
|
13291
|
-
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
constructor() {
|
|
13296
|
-
const buffer = new ArrayBuffer(IMMEDIATE_SIZE);
|
|
13297
|
-
this.unsignedImmediate = new BigUint64Array(buffer);
|
|
13298
|
-
this.bytes = new Uint8Array(buffer);
|
|
13480
|
+
class MemoryPage {
|
|
13481
|
+
start;
|
|
13482
|
+
constructor(pageNumber) {
|
|
13483
|
+
this.start = getStartPageIndexFromPageNumber(pageNumber);
|
|
13299
13484
|
}
|
|
13300
|
-
|
|
13301
|
-
|
|
13302
|
-
|
|
13303
|
-
|
|
13304
|
-
|
|
13305
|
-
|
|
13306
|
-
|
|
13485
|
+
}
|
|
13486
|
+
|
|
13487
|
+
class ReadablePage extends MemoryPage {
|
|
13488
|
+
data;
|
|
13489
|
+
constructor(pageNumber, data) {
|
|
13490
|
+
super(pageNumber);
|
|
13491
|
+
this.data = data;
|
|
13492
|
+
}
|
|
13493
|
+
loadInto(result, startIndex, length) {
|
|
13494
|
+
const endIndex = startIndex + length;
|
|
13495
|
+
if (endIndex > PAGE_SIZE$1) {
|
|
13496
|
+
return Result$1.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE$1), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE$1}`);
|
|
13307
13497
|
}
|
|
13498
|
+
const bytes = this.data.subarray(startIndex, endIndex);
|
|
13499
|
+
// we zero the bytes, since data might not yet be initialized at `endIndex`.
|
|
13500
|
+
result.fill(0, bytes.length, length);
|
|
13501
|
+
result.set(bytes);
|
|
13502
|
+
return Result$1.ok(OK);
|
|
13308
13503
|
}
|
|
13309
|
-
|
|
13310
|
-
return this.
|
|
13504
|
+
storeFrom(_address, _data) {
|
|
13505
|
+
return Result$1.error(PageFault.fromMemoryIndex(this.start, true), () => `Page fault: attempted to write to read-only page at ${this.start}`);
|
|
13311
13506
|
}
|
|
13312
|
-
|
|
13313
|
-
|
|
13507
|
+
setData(pageIndex, data) {
|
|
13508
|
+
this.data.set(data, pageIndex);
|
|
13509
|
+
}
|
|
13510
|
+
isWriteable() {
|
|
13511
|
+
return false;
|
|
13512
|
+
}
|
|
13513
|
+
getPageDump() {
|
|
13514
|
+
return this.data;
|
|
13314
13515
|
}
|
|
13315
13516
|
}
|
|
13316
13517
|
|
|
13317
|
-
|
|
13318
|
-
|
|
13319
|
-
|
|
13320
|
-
|
|
13321
|
-
|
|
13322
|
-
|
|
13323
|
-
|
|
13324
|
-
|
|
13325
|
-
|
|
13326
|
-
|
|
13327
|
-
|
|
13328
|
-
|
|
13329
|
-
|
|
13330
|
-
|
|
13331
|
-
|
|
13332
|
-
|
|
13333
|
-
|
|
13334
|
-
|
|
13335
|
-
|
|
13336
|
-
|
|
13337
|
-
|
|
13338
|
-
|
|
13339
|
-
|
|
13340
|
-
|
|
13341
|
-
|
|
13342
|
-
|
|
13343
|
-
|
|
13344
|
-
|
|
13345
|
-
|
|
13346
|
-
|
|
13347
|
-
|
|
13348
|
-
}
|
|
13349
|
-
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
|
|
13353
|
-
|
|
13354
|
-
|
|
13355
|
-
}
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
results[ArgumentType.ONE_REGISTER_ONE_IMMEDIATE] = {
|
|
13364
|
-
type: ArgumentType.ONE_REGISTER_ONE_IMMEDIATE,
|
|
13365
|
-
noOfBytesToSkip: 1,
|
|
13366
|
-
registerIndex: 0,
|
|
13367
|
-
immediateDecoder: new ImmediateDecoder(),
|
|
13368
|
-
};
|
|
13369
|
-
results[ArgumentType.ONE_REGISTER_TWO_IMMEDIATES] = {
|
|
13370
|
-
type: ArgumentType.ONE_REGISTER_TWO_IMMEDIATES,
|
|
13371
|
-
noOfBytesToSkip: 1,
|
|
13372
|
-
registerIndex: 0,
|
|
13373
|
-
firstImmediateDecoder: new ImmediateDecoder(),
|
|
13374
|
-
secondImmediateDecoder: new ImmediateDecoder(),
|
|
13375
|
-
};
|
|
13376
|
-
results[ArgumentType.ONE_OFFSET] = {
|
|
13377
|
-
type: ArgumentType.ONE_OFFSET,
|
|
13378
|
-
noOfBytesToSkip: 1,
|
|
13379
|
-
nextPc: 0,
|
|
13380
|
-
};
|
|
13381
|
-
results[ArgumentType.TWO_IMMEDIATES] = {
|
|
13382
|
-
type: ArgumentType.TWO_IMMEDIATES,
|
|
13383
|
-
noOfBytesToSkip: 1,
|
|
13384
|
-
firstImmediateDecoder: new ImmediateDecoder(),
|
|
13385
|
-
secondImmediateDecoder: new ImmediateDecoder(),
|
|
13386
|
-
};
|
|
13387
|
-
results[ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES] = {
|
|
13388
|
-
type: ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES,
|
|
13389
|
-
noOfBytesToSkip: 1,
|
|
13390
|
-
firstImmediateDecoder: new ImmediateDecoder(),
|
|
13391
|
-
secondImmediateDecoder: new ImmediateDecoder(),
|
|
13392
|
-
firstRegisterIndex: 0,
|
|
13393
|
-
secondRegisterIndex: 0,
|
|
13394
|
-
};
|
|
13395
|
-
results[ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE] = {
|
|
13396
|
-
type: ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE,
|
|
13397
|
-
noOfBytesToSkip: 9,
|
|
13398
|
-
registerIndex: 0,
|
|
13399
|
-
immediateDecoder: new ExtendedWitdthImmediateDecoder(),
|
|
13400
|
-
};
|
|
13401
|
-
return results;
|
|
13402
|
-
};
|
|
13518
|
+
class WriteablePage extends MemoryPage {
|
|
13519
|
+
buffer;
|
|
13520
|
+
view;
|
|
13521
|
+
constructor(pageNumber, initialData) {
|
|
13522
|
+
super(pageNumber);
|
|
13523
|
+
const dataLength = initialData?.length ?? 0;
|
|
13524
|
+
const initialPageLength = Math.min(PAGE_SIZE$1, Math.max(dataLength, MIN_ALLOCATION_LENGTH));
|
|
13525
|
+
this.buffer = new ArrayBuffer(initialPageLength, { maxByteLength: PAGE_SIZE$1 });
|
|
13526
|
+
this.view = new Uint8Array(this.buffer);
|
|
13527
|
+
if (initialData !== undefined) {
|
|
13528
|
+
this.view.set(initialData);
|
|
13529
|
+
}
|
|
13530
|
+
}
|
|
13531
|
+
loadInto(result, startIndex, length) {
|
|
13532
|
+
const endIndex = startIndex + length;
|
|
13533
|
+
if (endIndex > PAGE_SIZE$1) {
|
|
13534
|
+
return Result$1.error(PageFault.fromMemoryIndex(this.start + PAGE_SIZE$1), () => `Page fault: read beyond page boundary at ${this.start + PAGE_SIZE$1}`);
|
|
13535
|
+
}
|
|
13536
|
+
const bytes = this.view.subarray(startIndex, endIndex);
|
|
13537
|
+
// we zero the bytes, since the view might not yet be initialized at `endIndex`.
|
|
13538
|
+
result.fill(0, bytes.length, length);
|
|
13539
|
+
result.set(bytes);
|
|
13540
|
+
return Result$1.ok(OK);
|
|
13541
|
+
}
|
|
13542
|
+
storeFrom(startIndex, bytes) {
|
|
13543
|
+
if (this.buffer.byteLength < startIndex + bytes.length && this.buffer.byteLength < PAGE_SIZE$1) {
|
|
13544
|
+
const newLength = Math.min(PAGE_SIZE$1, Math.max(MIN_ALLOCATION_LENGTH, startIndex + bytes.length));
|
|
13545
|
+
this.buffer.resize(newLength);
|
|
13546
|
+
}
|
|
13547
|
+
this.view.set(bytes, startIndex);
|
|
13548
|
+
return Result$1.ok(OK);
|
|
13549
|
+
}
|
|
13550
|
+
setData(pageIndex, data) {
|
|
13551
|
+
if (this.buffer.byteLength < pageIndex + data.length && this.buffer.byteLength < PAGE_SIZE$1) {
|
|
13552
|
+
const newLength = Math.min(PAGE_SIZE$1, Math.max(MIN_ALLOCATION_LENGTH, pageIndex + data.length));
|
|
13553
|
+
this.buffer.resize(newLength);
|
|
13554
|
+
}
|
|
13555
|
+
this.view.set(data, pageIndex);
|
|
13556
|
+
}
|
|
13557
|
+
isWriteable() {
|
|
13558
|
+
return true;
|
|
13559
|
+
}
|
|
13560
|
+
getPageDump() {
|
|
13561
|
+
return this.view;
|
|
13562
|
+
}
|
|
13563
|
+
}
|
|
13403
13564
|
|
|
13404
|
-
var
|
|
13405
|
-
(function (
|
|
13406
|
-
|
|
13407
|
-
|
|
13408
|
-
|
|
13409
|
-
|
|
13410
|
-
|
|
13411
|
-
|
|
13412
|
-
|
|
13413
|
-
|
|
13414
|
-
|
|
13415
|
-
|
|
13416
|
-
|
|
13417
|
-
|
|
13418
|
-
|
|
13419
|
-
|
|
13420
|
-
|
|
13421
|
-
|
|
13422
|
-
|
|
13423
|
-
|
|
13424
|
-
|
|
13425
|
-
|
|
13426
|
-
|
|
13427
|
-
|
|
13428
|
-
|
|
13429
|
-
|
|
13430
|
-
|
|
13431
|
-
|
|
13432
|
-
|
|
13433
|
-
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13439
|
-
|
|
13440
|
-
|
|
13441
|
-
|
|
13442
|
-
|
|
13443
|
-
|
|
13444
|
-
|
|
13445
|
-
|
|
13446
|
-
|
|
13447
|
-
|
|
13448
|
-
|
|
13449
|
-
|
|
13450
|
-
|
|
13451
|
-
|
|
13452
|
-
|
|
13453
|
-
|
|
13454
|
-
|
|
13455
|
-
|
|
13456
|
-
|
|
13457
|
-
|
|
13458
|
-
|
|
13459
|
-
|
|
13460
|
-
|
|
13461
|
-
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
|
|
13465
|
-
|
|
13466
|
-
|
|
13467
|
-
|
|
13468
|
-
|
|
13469
|
-
|
|
13470
|
-
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
|
|
13475
|
-
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13479
|
-
|
|
13480
|
-
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
|
|
13500
|
-
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
13504
|
-
|
|
13505
|
-
|
|
13506
|
-
|
|
13507
|
-
|
|
13508
|
-
|
|
13509
|
-
|
|
13510
|
-
|
|
13511
|
-
|
|
13512
|
-
Instruction[Instruction["SHLO_R_32"] = 198] = "SHLO_R_32";
|
|
13513
|
-
Instruction[Instruction["SHAR_R_32"] = 199] = "SHAR_R_32";
|
|
13514
|
-
Instruction[Instruction["ADD_64"] = 200] = "ADD_64";
|
|
13515
|
-
Instruction[Instruction["SUB_64"] = 201] = "SUB_64";
|
|
13516
|
-
Instruction[Instruction["MUL_64"] = 202] = "MUL_64";
|
|
13517
|
-
Instruction[Instruction["DIV_U_64"] = 203] = "DIV_U_64";
|
|
13518
|
-
Instruction[Instruction["DIV_S_64"] = 204] = "DIV_S_64";
|
|
13519
|
-
Instruction[Instruction["REM_U_64"] = 205] = "REM_U_64";
|
|
13520
|
-
Instruction[Instruction["REM_S_64"] = 206] = "REM_S_64";
|
|
13521
|
-
Instruction[Instruction["SHLO_L_64"] = 207] = "SHLO_L_64";
|
|
13522
|
-
Instruction[Instruction["SHLO_R_64"] = 208] = "SHLO_R_64";
|
|
13523
|
-
Instruction[Instruction["SHAR_R_64"] = 209] = "SHAR_R_64";
|
|
13524
|
-
Instruction[Instruction["AND"] = 210] = "AND";
|
|
13525
|
-
Instruction[Instruction["XOR"] = 211] = "XOR";
|
|
13526
|
-
Instruction[Instruction["OR"] = 212] = "OR";
|
|
13527
|
-
Instruction[Instruction["MUL_UPPER_S_S"] = 213] = "MUL_UPPER_S_S";
|
|
13528
|
-
Instruction[Instruction["MUL_UPPER_U_U"] = 214] = "MUL_UPPER_U_U";
|
|
13529
|
-
Instruction[Instruction["MUL_UPPER_S_U"] = 215] = "MUL_UPPER_S_U";
|
|
13530
|
-
Instruction[Instruction["SET_LT_U"] = 216] = "SET_LT_U";
|
|
13531
|
-
Instruction[Instruction["SET_LT_S"] = 217] = "SET_LT_S";
|
|
13532
|
-
Instruction[Instruction["CMOV_IZ"] = 218] = "CMOV_IZ";
|
|
13533
|
-
Instruction[Instruction["CMOV_NZ"] = 219] = "CMOV_NZ";
|
|
13534
|
-
Instruction[Instruction["ROT_L_64"] = 220] = "ROT_L_64";
|
|
13535
|
-
Instruction[Instruction["ROT_L_32"] = 221] = "ROT_L_32";
|
|
13536
|
-
Instruction[Instruction["ROT_R_64"] = 222] = "ROT_R_64";
|
|
13537
|
-
Instruction[Instruction["ROT_R_32"] = 223] = "ROT_R_32";
|
|
13538
|
-
Instruction[Instruction["AND_INV"] = 224] = "AND_INV";
|
|
13539
|
-
Instruction[Instruction["OR_INV"] = 225] = "OR_INV";
|
|
13540
|
-
Instruction[Instruction["XNOR"] = 226] = "XNOR";
|
|
13541
|
-
Instruction[Instruction["MAX"] = 227] = "MAX";
|
|
13542
|
-
Instruction[Instruction["MAX_U"] = 228] = "MAX_U";
|
|
13543
|
-
Instruction[Instruction["MIN"] = 229] = "MIN";
|
|
13544
|
-
Instruction[Instruction["MIN_U"] = 230] = "MIN_U";
|
|
13545
|
-
})(Instruction || (Instruction = {}));
|
|
13546
|
-
const HIGHEST_INSTRUCTION_NUMBER = Instruction.MIN_U;
|
|
13547
|
-
|
|
13548
|
-
const instructionArgumentTypeMap = (() => {
|
|
13549
|
-
const instructionArgumentTypeMap = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
|
|
13550
|
-
instructionArgumentTypeMap[Instruction.TRAP] = ArgumentType.NO_ARGUMENTS;
|
|
13551
|
-
instructionArgumentTypeMap[Instruction.FALLTHROUGH] = ArgumentType.NO_ARGUMENTS;
|
|
13552
|
-
instructionArgumentTypeMap[Instruction.ECALLI] = ArgumentType.ONE_IMMEDIATE;
|
|
13553
|
-
instructionArgumentTypeMap[Instruction.LOAD_IMM_64] = ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE;
|
|
13554
|
-
instructionArgumentTypeMap[Instruction.STORE_IMM_U8] = ArgumentType.TWO_IMMEDIATES;
|
|
13555
|
-
instructionArgumentTypeMap[Instruction.STORE_IMM_U16] = ArgumentType.TWO_IMMEDIATES;
|
|
13556
|
-
instructionArgumentTypeMap[Instruction.STORE_IMM_U32] = ArgumentType.TWO_IMMEDIATES;
|
|
13557
|
-
instructionArgumentTypeMap[Instruction.STORE_IMM_U64] = ArgumentType.TWO_IMMEDIATES;
|
|
13558
|
-
instructionArgumentTypeMap[Instruction.JUMP] = ArgumentType.ONE_OFFSET;
|
|
13559
|
-
instructionArgumentTypeMap[Instruction.JUMP_IND] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13560
|
-
instructionArgumentTypeMap[Instruction.LOAD_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13561
|
-
instructionArgumentTypeMap[Instruction.LOAD_U8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13562
|
-
instructionArgumentTypeMap[Instruction.LOAD_I8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13563
|
-
instructionArgumentTypeMap[Instruction.LOAD_U16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13564
|
-
instructionArgumentTypeMap[Instruction.LOAD_I16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13565
|
-
instructionArgumentTypeMap[Instruction.LOAD_U32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13566
|
-
instructionArgumentTypeMap[Instruction.LOAD_I32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13567
|
-
instructionArgumentTypeMap[Instruction.LOAD_U64] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13568
|
-
instructionArgumentTypeMap[Instruction.STORE_U8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13569
|
-
instructionArgumentTypeMap[Instruction.STORE_U16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13570
|
-
instructionArgumentTypeMap[Instruction.STORE_U32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13571
|
-
instructionArgumentTypeMap[Instruction.STORE_U64] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
13572
|
-
instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U8] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
|
|
13573
|
-
instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U16] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
|
|
13574
|
-
instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U32] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
|
|
13575
|
-
instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U64] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
|
|
13576
|
-
instructionArgumentTypeMap[Instruction.LOAD_IMM_JUMP] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13577
|
-
instructionArgumentTypeMap[Instruction.BRANCH_EQ_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13578
|
-
instructionArgumentTypeMap[Instruction.BRANCH_NE_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13579
|
-
instructionArgumentTypeMap[Instruction.BRANCH_LT_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13580
|
-
instructionArgumentTypeMap[Instruction.BRANCH_LE_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13581
|
-
instructionArgumentTypeMap[Instruction.BRANCH_GE_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13582
|
-
instructionArgumentTypeMap[Instruction.BRANCH_GT_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13583
|
-
instructionArgumentTypeMap[Instruction.BRANCH_LT_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13584
|
-
instructionArgumentTypeMap[Instruction.BRANCH_LE_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13585
|
-
instructionArgumentTypeMap[Instruction.BRANCH_GE_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13586
|
-
instructionArgumentTypeMap[Instruction.BRANCH_GT_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
13587
|
-
instructionArgumentTypeMap[Instruction.MOVE_REG] = ArgumentType.TWO_REGISTERS;
|
|
13588
|
-
instructionArgumentTypeMap[Instruction.SBRK] = ArgumentType.TWO_REGISTERS;
|
|
13589
|
-
instructionArgumentTypeMap[Instruction.COUNT_SET_BITS_64] = ArgumentType.TWO_REGISTERS;
|
|
13590
|
-
instructionArgumentTypeMap[Instruction.COUNT_SET_BITS_32] = ArgumentType.TWO_REGISTERS;
|
|
13591
|
-
instructionArgumentTypeMap[Instruction.LEADING_ZERO_BITS_64] = ArgumentType.TWO_REGISTERS;
|
|
13592
|
-
instructionArgumentTypeMap[Instruction.LEADING_ZERO_BITS_32] = ArgumentType.TWO_REGISTERS;
|
|
13593
|
-
instructionArgumentTypeMap[Instruction.TRAILING_ZERO_BITS_64] = ArgumentType.TWO_REGISTERS;
|
|
13594
|
-
instructionArgumentTypeMap[Instruction.TRAILING_ZERO_BITS_32] = ArgumentType.TWO_REGISTERS;
|
|
13595
|
-
instructionArgumentTypeMap[Instruction.SIGN_EXTEND_8] = ArgumentType.TWO_REGISTERS;
|
|
13596
|
-
instructionArgumentTypeMap[Instruction.SIGN_EXTEND_16] = ArgumentType.TWO_REGISTERS;
|
|
13597
|
-
instructionArgumentTypeMap[Instruction.ZERO_EXTEND_16] = ArgumentType.TWO_REGISTERS;
|
|
13598
|
-
instructionArgumentTypeMap[Instruction.REVERSE_BYTES] = ArgumentType.TWO_REGISTERS;
|
|
13599
|
-
instructionArgumentTypeMap[Instruction.STORE_IND_U8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13600
|
-
instructionArgumentTypeMap[Instruction.STORE_IND_U16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13601
|
-
instructionArgumentTypeMap[Instruction.STORE_IND_U32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13602
|
-
instructionArgumentTypeMap[Instruction.STORE_IND_U64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13603
|
-
instructionArgumentTypeMap[Instruction.LOAD_IND_U8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13604
|
-
instructionArgumentTypeMap[Instruction.LOAD_IND_I8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13605
|
-
instructionArgumentTypeMap[Instruction.LOAD_IND_U16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13606
|
-
instructionArgumentTypeMap[Instruction.LOAD_IND_I16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13607
|
-
instructionArgumentTypeMap[Instruction.LOAD_IND_U32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13608
|
-
instructionArgumentTypeMap[Instruction.LOAD_IND_I32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13609
|
-
instructionArgumentTypeMap[Instruction.LOAD_IND_U64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13610
|
-
instructionArgumentTypeMap[Instruction.ADD_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13611
|
-
instructionArgumentTypeMap[Instruction.ADD_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13612
|
-
instructionArgumentTypeMap[Instruction.AND_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13613
|
-
instructionArgumentTypeMap[Instruction.XOR_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13614
|
-
instructionArgumentTypeMap[Instruction.OR_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13615
|
-
instructionArgumentTypeMap[Instruction.MUL_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13616
|
-
instructionArgumentTypeMap[Instruction.MUL_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13617
|
-
instructionArgumentTypeMap[Instruction.SET_LT_U_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13618
|
-
instructionArgumentTypeMap[Instruction.SET_LT_S_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13619
|
-
instructionArgumentTypeMap[Instruction.SHLO_L_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13620
|
-
instructionArgumentTypeMap[Instruction.SHLO_R_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13621
|
-
instructionArgumentTypeMap[Instruction.SHAR_R_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13622
|
-
instructionArgumentTypeMap[Instruction.NEG_ADD_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13623
|
-
instructionArgumentTypeMap[Instruction.SHLO_L_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13624
|
-
instructionArgumentTypeMap[Instruction.SHLO_R_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13625
|
-
instructionArgumentTypeMap[Instruction.SHAR_R_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13626
|
-
instructionArgumentTypeMap[Instruction.NEG_ADD_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13627
|
-
instructionArgumentTypeMap[Instruction.SET_GT_U_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13628
|
-
instructionArgumentTypeMap[Instruction.SET_GT_S_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13629
|
-
instructionArgumentTypeMap[Instruction.SHLO_L_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13630
|
-
instructionArgumentTypeMap[Instruction.SHLO_R_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13631
|
-
instructionArgumentTypeMap[Instruction.SHAR_R_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13632
|
-
instructionArgumentTypeMap[Instruction.SHLO_L_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13633
|
-
instructionArgumentTypeMap[Instruction.SHLO_R_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13634
|
-
instructionArgumentTypeMap[Instruction.SHAR_R_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13635
|
-
instructionArgumentTypeMap[Instruction.CMOV_IZ_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13636
|
-
instructionArgumentTypeMap[Instruction.CMOV_NZ_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13637
|
-
instructionArgumentTypeMap[Instruction.ROT_R_64_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13638
|
-
instructionArgumentTypeMap[Instruction.ROT_R_64_IMM_ALT] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13639
|
-
instructionArgumentTypeMap[Instruction.ROT_R_32_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13640
|
-
instructionArgumentTypeMap[Instruction.ROT_R_32_IMM_ALT] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
13641
|
-
instructionArgumentTypeMap[Instruction.BRANCH_EQ] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
13642
|
-
instructionArgumentTypeMap[Instruction.BRANCH_NE] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
13643
|
-
instructionArgumentTypeMap[Instruction.BRANCH_LT_U] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
13644
|
-
instructionArgumentTypeMap[Instruction.BRANCH_LT_S] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
13645
|
-
instructionArgumentTypeMap[Instruction.BRANCH_GE_U] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
13646
|
-
instructionArgumentTypeMap[Instruction.BRANCH_GE_S] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
13647
|
-
instructionArgumentTypeMap[Instruction.LOAD_IMM_JUMP_IND] = ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES;
|
|
13648
|
-
instructionArgumentTypeMap[Instruction.ADD_32] = ArgumentType.THREE_REGISTERS;
|
|
13649
|
-
instructionArgumentTypeMap[Instruction.ADD_64] = ArgumentType.THREE_REGISTERS;
|
|
13650
|
-
instructionArgumentTypeMap[Instruction.SUB_32] = ArgumentType.THREE_REGISTERS;
|
|
13651
|
-
instructionArgumentTypeMap[Instruction.SUB_64] = ArgumentType.THREE_REGISTERS;
|
|
13652
|
-
instructionArgumentTypeMap[Instruction.AND] = ArgumentType.THREE_REGISTERS;
|
|
13653
|
-
instructionArgumentTypeMap[Instruction.XOR] = ArgumentType.THREE_REGISTERS;
|
|
13654
|
-
instructionArgumentTypeMap[Instruction.OR] = ArgumentType.THREE_REGISTERS;
|
|
13655
|
-
instructionArgumentTypeMap[Instruction.MUL_32] = ArgumentType.THREE_REGISTERS;
|
|
13656
|
-
instructionArgumentTypeMap[Instruction.MUL_64] = ArgumentType.THREE_REGISTERS;
|
|
13657
|
-
instructionArgumentTypeMap[Instruction.MUL_UPPER_S_S] = ArgumentType.THREE_REGISTERS;
|
|
13658
|
-
instructionArgumentTypeMap[Instruction.MUL_UPPER_U_U] = ArgumentType.THREE_REGISTERS;
|
|
13659
|
-
instructionArgumentTypeMap[Instruction.MUL_UPPER_S_U] = ArgumentType.THREE_REGISTERS;
|
|
13660
|
-
instructionArgumentTypeMap[Instruction.DIV_U_32] = ArgumentType.THREE_REGISTERS;
|
|
13661
|
-
instructionArgumentTypeMap[Instruction.DIV_S_32] = ArgumentType.THREE_REGISTERS;
|
|
13662
|
-
instructionArgumentTypeMap[Instruction.REM_U_32] = ArgumentType.THREE_REGISTERS;
|
|
13663
|
-
instructionArgumentTypeMap[Instruction.REM_S_32] = ArgumentType.THREE_REGISTERS;
|
|
13664
|
-
instructionArgumentTypeMap[Instruction.DIV_U_64] = ArgumentType.THREE_REGISTERS;
|
|
13665
|
-
instructionArgumentTypeMap[Instruction.DIV_S_64] = ArgumentType.THREE_REGISTERS;
|
|
13666
|
-
instructionArgumentTypeMap[Instruction.REM_U_64] = ArgumentType.THREE_REGISTERS;
|
|
13667
|
-
instructionArgumentTypeMap[Instruction.REM_S_64] = ArgumentType.THREE_REGISTERS;
|
|
13668
|
-
instructionArgumentTypeMap[Instruction.SET_LT_U] = ArgumentType.THREE_REGISTERS;
|
|
13669
|
-
instructionArgumentTypeMap[Instruction.SET_LT_S] = ArgumentType.THREE_REGISTERS;
|
|
13670
|
-
instructionArgumentTypeMap[Instruction.SHLO_L_32] = ArgumentType.THREE_REGISTERS;
|
|
13671
|
-
instructionArgumentTypeMap[Instruction.SHLO_R_32] = ArgumentType.THREE_REGISTERS;
|
|
13672
|
-
instructionArgumentTypeMap[Instruction.SHAR_R_32] = ArgumentType.THREE_REGISTERS;
|
|
13673
|
-
instructionArgumentTypeMap[Instruction.SHLO_L_64] = ArgumentType.THREE_REGISTERS;
|
|
13674
|
-
instructionArgumentTypeMap[Instruction.SHLO_R_64] = ArgumentType.THREE_REGISTERS;
|
|
13675
|
-
instructionArgumentTypeMap[Instruction.SHAR_R_64] = ArgumentType.THREE_REGISTERS;
|
|
13676
|
-
instructionArgumentTypeMap[Instruction.CMOV_IZ] = ArgumentType.THREE_REGISTERS;
|
|
13677
|
-
instructionArgumentTypeMap[Instruction.CMOV_NZ] = ArgumentType.THREE_REGISTERS;
|
|
13678
|
-
instructionArgumentTypeMap[Instruction.ROT_L_64] = ArgumentType.THREE_REGISTERS;
|
|
13679
|
-
instructionArgumentTypeMap[Instruction.ROT_L_32] = ArgumentType.THREE_REGISTERS;
|
|
13680
|
-
instructionArgumentTypeMap[Instruction.ROT_R_64] = ArgumentType.THREE_REGISTERS;
|
|
13681
|
-
instructionArgumentTypeMap[Instruction.ROT_R_32] = ArgumentType.THREE_REGISTERS;
|
|
13682
|
-
instructionArgumentTypeMap[Instruction.AND_INV] = ArgumentType.THREE_REGISTERS;
|
|
13683
|
-
instructionArgumentTypeMap[Instruction.OR_INV] = ArgumentType.THREE_REGISTERS;
|
|
13684
|
-
instructionArgumentTypeMap[Instruction.XNOR] = ArgumentType.THREE_REGISTERS;
|
|
13685
|
-
instructionArgumentTypeMap[Instruction.MAX] = ArgumentType.THREE_REGISTERS;
|
|
13686
|
-
instructionArgumentTypeMap[Instruction.MAX_U] = ArgumentType.THREE_REGISTERS;
|
|
13687
|
-
instructionArgumentTypeMap[Instruction.MIN] = ArgumentType.THREE_REGISTERS;
|
|
13688
|
-
instructionArgumentTypeMap[Instruction.MIN_U] = ArgumentType.THREE_REGISTERS;
|
|
13689
|
-
return instructionArgumentTypeMap;
|
|
13690
|
-
})();
|
|
13691
|
-
|
|
13692
|
-
const instructionsWithoutArgs = [
|
|
13693
|
-
[Instruction.TRAP, 1],
|
|
13694
|
-
[Instruction.FALLTHROUGH, 1],
|
|
13695
|
-
];
|
|
13696
|
-
const instructionsWithOneImmediate = [[Instruction.ECALLI, 1]];
|
|
13697
|
-
const instructionsWithOneRegisterAndOneExtendedWidthImmediate = [[Instruction.LOAD_IMM_64, 1]];
|
|
13698
|
-
const instructionsWithTwoImmediates = [
|
|
13699
|
-
[Instruction.STORE_IMM_U8, 1],
|
|
13700
|
-
[Instruction.STORE_IMM_U16, 1],
|
|
13701
|
-
[Instruction.STORE_IMM_U32, 1],
|
|
13702
|
-
[Instruction.STORE_IMM_U64, 1],
|
|
13703
|
-
];
|
|
13704
|
-
const instructionsWithOneOffset = [[Instruction.JUMP, 1]];
|
|
13705
|
-
const instructionsWithOneRegisterAndOneImmediate = [
|
|
13706
|
-
[Instruction.JUMP_IND, 1],
|
|
13707
|
-
[Instruction.LOAD_IMM, 1],
|
|
13708
|
-
[Instruction.LOAD_U8, 1],
|
|
13709
|
-
[Instruction.LOAD_I8, 1],
|
|
13710
|
-
[Instruction.LOAD_U16, 1],
|
|
13711
|
-
[Instruction.LOAD_I16, 1],
|
|
13712
|
-
[Instruction.LOAD_U32, 1],
|
|
13713
|
-
[Instruction.LOAD_I32, 1],
|
|
13714
|
-
[Instruction.LOAD_U64, 1],
|
|
13715
|
-
[Instruction.STORE_U8, 1],
|
|
13716
|
-
[Instruction.STORE_U16, 1],
|
|
13717
|
-
[Instruction.STORE_U32, 1],
|
|
13718
|
-
[Instruction.STORE_U64, 1],
|
|
13719
|
-
];
|
|
13720
|
-
const instructionsWithOneRegisterAndTwoImmediate = [
|
|
13721
|
-
[Instruction.STORE_IMM_IND_U8, 1],
|
|
13722
|
-
[Instruction.STORE_IMM_IND_U16, 1],
|
|
13723
|
-
[Instruction.STORE_IMM_IND_U32, 1],
|
|
13724
|
-
[Instruction.STORE_IMM_IND_U64, 1],
|
|
13725
|
-
];
|
|
13726
|
-
const instructionsWithOneRegisterOneImmediateAndOneOffset = [
|
|
13727
|
-
[Instruction.LOAD_IMM_JUMP, 1],
|
|
13728
|
-
[Instruction.BRANCH_EQ_IMM, 1],
|
|
13729
|
-
[Instruction.BRANCH_NE_IMM, 1],
|
|
13730
|
-
[Instruction.BRANCH_LT_U_IMM, 1],
|
|
13731
|
-
[Instruction.BRANCH_LE_U_IMM, 1],
|
|
13732
|
-
[Instruction.BRANCH_GE_U_IMM, 1],
|
|
13733
|
-
[Instruction.BRANCH_GT_U_IMM, 1],
|
|
13734
|
-
[Instruction.BRANCH_LT_S_IMM, 1],
|
|
13735
|
-
[Instruction.BRANCH_LE_S_IMM, 1],
|
|
13736
|
-
[Instruction.BRANCH_GE_S_IMM, 1],
|
|
13737
|
-
[Instruction.BRANCH_GT_S_IMM, 1],
|
|
13738
|
-
];
|
|
13739
|
-
const instructionsWithTwoRegisters = [
|
|
13740
|
-
[Instruction.MOVE_REG, 1],
|
|
13741
|
-
[Instruction.SBRK, 1],
|
|
13742
|
-
[Instruction.COUNT_SET_BITS_64, 1],
|
|
13743
|
-
[Instruction.COUNT_SET_BITS_32, 1],
|
|
13744
|
-
[Instruction.LEADING_ZERO_BITS_64, 1],
|
|
13745
|
-
[Instruction.LEADING_ZERO_BITS_32, 1],
|
|
13746
|
-
[Instruction.TRAILING_ZERO_BITS_64, 1],
|
|
13747
|
-
[Instruction.TRAILING_ZERO_BITS_32, 1],
|
|
13748
|
-
[Instruction.SIGN_EXTEND_8, 1],
|
|
13749
|
-
[Instruction.SIGN_EXTEND_16, 1],
|
|
13750
|
-
[Instruction.ZERO_EXTEND_16, 1],
|
|
13751
|
-
[Instruction.REVERSE_BYTES, 1],
|
|
13752
|
-
];
|
|
13753
|
-
const instructionsWithTwoRegistersAndOneImmediate = [
|
|
13754
|
-
[Instruction.STORE_IND_U8, 1],
|
|
13755
|
-
[Instruction.STORE_IND_U16, 1],
|
|
13756
|
-
[Instruction.STORE_IND_U32, 1],
|
|
13757
|
-
[Instruction.STORE_IND_U64, 1],
|
|
13758
|
-
[Instruction.LOAD_IND_U8, 1],
|
|
13759
|
-
[Instruction.LOAD_IND_I8, 1],
|
|
13760
|
-
[Instruction.LOAD_IND_U16, 1],
|
|
13761
|
-
[Instruction.LOAD_IND_I16, 1],
|
|
13762
|
-
[Instruction.LOAD_IND_U32, 1],
|
|
13763
|
-
[Instruction.LOAD_IND_I32, 1],
|
|
13764
|
-
[Instruction.LOAD_IND_U64, 1],
|
|
13765
|
-
[Instruction.ADD_IMM_32, 1],
|
|
13766
|
-
[Instruction.AND_IMM, 1],
|
|
13767
|
-
[Instruction.XOR_IMM, 1],
|
|
13768
|
-
[Instruction.OR_IMM, 1],
|
|
13769
|
-
[Instruction.MUL_IMM_32, 1],
|
|
13770
|
-
[Instruction.SET_LT_U_IMM, 1],
|
|
13771
|
-
[Instruction.SET_LT_S_IMM, 1],
|
|
13772
|
-
[Instruction.SHLO_L_IMM_32, 1],
|
|
13773
|
-
[Instruction.SHLO_R_IMM_32, 1],
|
|
13774
|
-
[Instruction.SHAR_R_IMM_32, 1],
|
|
13775
|
-
[Instruction.NEG_ADD_IMM_32, 1],
|
|
13776
|
-
[Instruction.SET_GT_U_IMM, 1],
|
|
13777
|
-
[Instruction.SET_GT_S_IMM, 1],
|
|
13778
|
-
[Instruction.SHLO_L_IMM_ALT_32, 1],
|
|
13779
|
-
[Instruction.SHLO_R_IMM_ALT_32, 1],
|
|
13780
|
-
[Instruction.SHAR_R_IMM_ALT_32, 1],
|
|
13781
|
-
[Instruction.CMOV_IZ_IMM, 1],
|
|
13782
|
-
[Instruction.CMOV_NZ_IMM, 1],
|
|
13783
|
-
[Instruction.ADD_IMM_64, 1],
|
|
13784
|
-
[Instruction.MUL_IMM_64, 1],
|
|
13785
|
-
[Instruction.SHLO_L_IMM_64, 1],
|
|
13786
|
-
[Instruction.SHLO_R_IMM_64, 1],
|
|
13787
|
-
[Instruction.SHAR_R_IMM_64, 1],
|
|
13788
|
-
[Instruction.NEG_ADD_IMM_64, 1],
|
|
13789
|
-
[Instruction.SHLO_L_IMM_ALT_64, 1],
|
|
13790
|
-
[Instruction.SHLO_R_IMM_ALT_64, 1],
|
|
13791
|
-
[Instruction.SHAR_R_IMM_ALT_64, 1],
|
|
13792
|
-
[Instruction.ROT_R_64_IMM, 1],
|
|
13793
|
-
[Instruction.ROT_R_64_IMM_ALT, 1],
|
|
13794
|
-
[Instruction.ROT_R_32_IMM, 1],
|
|
13795
|
-
[Instruction.ROT_R_32_IMM_ALT, 1],
|
|
13796
|
-
];
|
|
13797
|
-
const instructionsWithTwoRegistersAndOneOffset = [
|
|
13798
|
-
[Instruction.BRANCH_EQ, 1],
|
|
13799
|
-
[Instruction.BRANCH_NE, 1],
|
|
13800
|
-
[Instruction.BRANCH_LT_U, 1],
|
|
13801
|
-
[Instruction.BRANCH_LT_S, 1],
|
|
13802
|
-
[Instruction.BRANCH_GE_U, 1],
|
|
13803
|
-
[Instruction.BRANCH_GE_S, 1],
|
|
13804
|
-
];
|
|
13805
|
-
const instructionWithTwoRegistersAndTwoImmediates = [[Instruction.LOAD_IMM_JUMP_IND, 1]];
|
|
13806
|
-
const instructionsWithThreeRegisters = [
|
|
13807
|
-
[Instruction.ADD_32, 1],
|
|
13808
|
-
[Instruction.SUB_32, 1],
|
|
13809
|
-
[Instruction.MUL_32, 1],
|
|
13810
|
-
[Instruction.DIV_U_32, 1],
|
|
13811
|
-
[Instruction.DIV_S_32, 1],
|
|
13812
|
-
[Instruction.REM_U_32, 1],
|
|
13813
|
-
[Instruction.REM_S_32, 1],
|
|
13814
|
-
[Instruction.SHLO_L_32, 1],
|
|
13815
|
-
[Instruction.SHLO_R_32, 1],
|
|
13816
|
-
[Instruction.SHAR_R_32, 1],
|
|
13817
|
-
[Instruction.ADD_64, 1],
|
|
13818
|
-
[Instruction.SUB_64, 1],
|
|
13819
|
-
[Instruction.MUL_64, 1],
|
|
13820
|
-
[Instruction.DIV_U_64, 1],
|
|
13821
|
-
[Instruction.DIV_S_64, 1],
|
|
13822
|
-
[Instruction.REM_U_64, 1],
|
|
13823
|
-
[Instruction.REM_S_64, 1],
|
|
13824
|
-
[Instruction.SHLO_L_64, 1],
|
|
13825
|
-
[Instruction.SHLO_R_64, 1],
|
|
13826
|
-
[Instruction.SHAR_R_64, 1],
|
|
13827
|
-
[Instruction.AND, 1],
|
|
13828
|
-
[Instruction.XOR, 1],
|
|
13829
|
-
[Instruction.OR, 1],
|
|
13830
|
-
[Instruction.MUL_UPPER_S_S, 1],
|
|
13831
|
-
[Instruction.MUL_UPPER_U_U, 1],
|
|
13832
|
-
[Instruction.MUL_UPPER_S_U, 1],
|
|
13833
|
-
[Instruction.SET_LT_U, 1],
|
|
13834
|
-
[Instruction.SET_LT_S, 1],
|
|
13835
|
-
[Instruction.CMOV_IZ, 1],
|
|
13836
|
-
[Instruction.CMOV_NZ, 1],
|
|
13837
|
-
[Instruction.ROT_L_64, 1],
|
|
13838
|
-
[Instruction.ROT_L_32, 1],
|
|
13839
|
-
[Instruction.ROT_R_64, 1],
|
|
13840
|
-
[Instruction.ROT_R_32, 1],
|
|
13841
|
-
[Instruction.AND_INV, 1],
|
|
13842
|
-
[Instruction.OR_INV, 1],
|
|
13843
|
-
[Instruction.XNOR, 1],
|
|
13844
|
-
[Instruction.MAX, 1],
|
|
13845
|
-
[Instruction.MAX_U, 1],
|
|
13846
|
-
[Instruction.MIN, 1],
|
|
13847
|
-
[Instruction.MIN_U, 1],
|
|
13848
|
-
];
|
|
13849
|
-
const instructions = [
|
|
13850
|
-
...instructionsWithoutArgs,
|
|
13851
|
-
...instructionsWithOneImmediate,
|
|
13852
|
-
...instructionsWithOneRegisterAndOneExtendedWidthImmediate,
|
|
13853
|
-
...instructionsWithTwoImmediates,
|
|
13854
|
-
...instructionsWithOneOffset,
|
|
13855
|
-
...instructionsWithOneRegisterAndOneImmediate,
|
|
13856
|
-
...instructionsWithOneRegisterAndTwoImmediate,
|
|
13857
|
-
...instructionsWithOneRegisterOneImmediateAndOneOffset,
|
|
13858
|
-
...instructionsWithTwoRegisters,
|
|
13859
|
-
...instructionsWithTwoRegistersAndOneImmediate,
|
|
13860
|
-
...instructionsWithTwoRegistersAndOneOffset,
|
|
13861
|
-
...instructionWithTwoRegistersAndTwoImmediates,
|
|
13862
|
-
...instructionsWithThreeRegisters,
|
|
13863
|
-
];
|
|
13864
|
-
const createOpCodeEntry = ([byte, gas]) => [byte, { gas: tryAsSmallGas(gas) }];
|
|
13865
|
-
const byteToOpCodeMap = instructions.reduce((acc, instruction) => {
|
|
13866
|
-
const [byte, opCode] = createOpCodeEntry(instruction);
|
|
13867
|
-
acc[byte] = opCode;
|
|
13868
|
-
return acc;
|
|
13869
|
-
}, {});
|
|
13870
|
-
function assemblify(program, mask) {
|
|
13871
|
-
return program.reduce((acc, byte, index) => {
|
|
13872
|
-
if (mask.isInstruction(index)) {
|
|
13873
|
-
acc.push([Instruction[byte]]);
|
|
13565
|
+
var AccessType;
|
|
13566
|
+
(function (AccessType) {
|
|
13567
|
+
AccessType[AccessType["READ"] = 0] = "READ";
|
|
13568
|
+
AccessType[AccessType["WRITE"] = 1] = "WRITE";
|
|
13569
|
+
})(AccessType || (AccessType = {}));
|
|
13570
|
+
const logger$2 = Logger.new(import.meta.filename, "pvm:mem");
|
|
13571
|
+
class Memory {
|
|
13572
|
+
sbrkIndex;
|
|
13573
|
+
virtualSbrkIndex;
|
|
13574
|
+
endHeapIndex;
|
|
13575
|
+
memory;
|
|
13576
|
+
static fromInitialMemory(initialMemoryState) {
|
|
13577
|
+
return new Memory(initialMemoryState?.sbrkIndex, initialMemoryState?.sbrkIndex, initialMemoryState?.endHeapIndex, initialMemoryState?.memory);
|
|
13578
|
+
}
|
|
13579
|
+
constructor(sbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end), virtualSbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end), endHeapIndex = tryAsSbrkIndex(MAX_MEMORY_INDEX), memory = new Map()) {
|
|
13580
|
+
this.sbrkIndex = sbrkIndex;
|
|
13581
|
+
this.virtualSbrkIndex = virtualSbrkIndex;
|
|
13582
|
+
this.endHeapIndex = endHeapIndex;
|
|
13583
|
+
this.memory = memory;
|
|
13584
|
+
}
|
|
13585
|
+
store(address, bytes) {
|
|
13586
|
+
return this.storeFrom(tryAsMemoryIndex(address), bytes);
|
|
13587
|
+
}
|
|
13588
|
+
read(address, output) {
|
|
13589
|
+
return this.loadInto(output, tryAsMemoryIndex(address));
|
|
13590
|
+
}
|
|
13591
|
+
reset() {
|
|
13592
|
+
this.sbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end);
|
|
13593
|
+
this.virtualSbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end);
|
|
13594
|
+
this.endHeapIndex = tryAsSbrkIndex(MAX_MEMORY_INDEX);
|
|
13595
|
+
this.memory = new Map(); // TODO [MaSi]: We should keep allocated pages somewhere and reuse it when it is possible
|
|
13596
|
+
}
|
|
13597
|
+
copyFrom(memory) {
|
|
13598
|
+
this.sbrkIndex = memory.sbrkIndex;
|
|
13599
|
+
this.virtualSbrkIndex = memory.virtualSbrkIndex;
|
|
13600
|
+
this.endHeapIndex = memory.endHeapIndex;
|
|
13601
|
+
this.memory = memory.memory;
|
|
13602
|
+
}
|
|
13603
|
+
storeFrom(address, bytes) {
|
|
13604
|
+
if (bytes.length === 0) {
|
|
13605
|
+
return Result$1.ok(OK);
|
|
13606
|
+
}
|
|
13607
|
+
logger$2.insane `MEM[${address}] <- ${BytesBlob.blobFrom(bytes)}`;
|
|
13608
|
+
const pagesResult = this.getPages(address, bytes.length, AccessType.WRITE);
|
|
13609
|
+
if (pagesResult.isError) {
|
|
13610
|
+
return Result$1.error(pagesResult.error, pagesResult.details);
|
|
13611
|
+
}
|
|
13612
|
+
const pages = pagesResult.ok;
|
|
13613
|
+
let currentPosition = address;
|
|
13614
|
+
let bytesLeft = bytes.length;
|
|
13615
|
+
for (const page of pages) {
|
|
13616
|
+
const pageStartIndex = tryAsPageIndex(currentPosition % PAGE_SIZE$1);
|
|
13617
|
+
const bytesToWrite = Math.min(PAGE_SIZE$1 - pageStartIndex, bytesLeft);
|
|
13618
|
+
const sourceStartIndex = currentPosition - address;
|
|
13619
|
+
const source = bytes.subarray(sourceStartIndex, sourceStartIndex + bytesToWrite);
|
|
13620
|
+
page.storeFrom(pageStartIndex, source);
|
|
13621
|
+
currentPosition += bytesToWrite;
|
|
13622
|
+
bytesLeft -= bytesToWrite;
|
|
13623
|
+
}
|
|
13624
|
+
return Result$1.ok(OK);
|
|
13625
|
+
}
|
|
13626
|
+
getPages(startAddress, length, accessType) {
|
|
13627
|
+
if (length === 0) {
|
|
13628
|
+
return Result$1.ok([]);
|
|
13629
|
+
}
|
|
13630
|
+
const memoryRange = MemoryRange.fromStartAndLength(startAddress, length);
|
|
13631
|
+
const pageRange = PageRange.fromMemoryRange(memoryRange);
|
|
13632
|
+
const pages = [];
|
|
13633
|
+
for (const pageNumber of pageRange) {
|
|
13634
|
+
if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
|
|
13635
|
+
return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to access reserved page ${pageNumber}`);
|
|
13636
|
+
}
|
|
13637
|
+
const page = this.memory.get(pageNumber);
|
|
13638
|
+
if (page === undefined) {
|
|
13639
|
+
return Result$1.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
|
|
13640
|
+
}
|
|
13641
|
+
if (accessType === AccessType.WRITE && !page.isWriteable()) {
|
|
13642
|
+
return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to write to read-only page ${pageNumber}`);
|
|
13643
|
+
}
|
|
13644
|
+
pages.push(page);
|
|
13645
|
+
}
|
|
13646
|
+
return Result$1.ok(pages);
|
|
13647
|
+
}
|
|
13648
|
+
/**
|
|
13649
|
+
* Read content of the memory at `[address, address + result.length)` and
|
|
13650
|
+
* write the result into the `result` buffer.
|
|
13651
|
+
*
|
|
13652
|
+
* Returns `null` if the data was read successfully or `PageFault` otherwise.
|
|
13653
|
+
*/
|
|
13654
|
+
loadInto(result, startAddress) {
|
|
13655
|
+
if (result.length === 0) {
|
|
13656
|
+
return Result$1.ok(OK);
|
|
13657
|
+
}
|
|
13658
|
+
const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
|
|
13659
|
+
if (pagesResult.isError) {
|
|
13660
|
+
return Result$1.error(pagesResult.error, pagesResult.details);
|
|
13661
|
+
}
|
|
13662
|
+
const pages = pagesResult.ok;
|
|
13663
|
+
let currentPosition = startAddress;
|
|
13664
|
+
let bytesLeft = result.length;
|
|
13665
|
+
for (const page of pages) {
|
|
13666
|
+
const pageStartIndex = tryAsPageIndex(currentPosition % PAGE_SIZE$1);
|
|
13667
|
+
const bytesToRead = Math.min(PAGE_SIZE$1 - pageStartIndex, bytesLeft);
|
|
13668
|
+
const destinationStartIndex = currentPosition - startAddress;
|
|
13669
|
+
const destination = result.subarray(destinationStartIndex);
|
|
13670
|
+
page.loadInto(destination, pageStartIndex, bytesToRead);
|
|
13671
|
+
currentPosition += bytesToRead;
|
|
13672
|
+
bytesLeft -= bytesToRead;
|
|
13874
13673
|
}
|
|
13875
|
-
|
|
13876
|
-
|
|
13674
|
+
logger$2.insane `MEM[${startAddress}] => ${BytesBlob.blobFrom(result)}`;
|
|
13675
|
+
return Result$1.ok(OK);
|
|
13676
|
+
}
|
|
13677
|
+
sbrk(length) {
|
|
13678
|
+
const currentSbrkIndex = this.sbrkIndex;
|
|
13679
|
+
const currentVirtualSbrkIndex = this.virtualSbrkIndex;
|
|
13680
|
+
// new sbrk index is bigger than 2 ** 32 or endHeapIndex
|
|
13681
|
+
if (MAX_MEMORY_INDEX < currentVirtualSbrkIndex + length || currentVirtualSbrkIndex + length > this.endHeapIndex) {
|
|
13682
|
+
throw new OutOfMemory();
|
|
13877
13683
|
}
|
|
13878
|
-
|
|
13879
|
-
|
|
13684
|
+
const newVirtualSbrkIndex = tryAsSbrkIndex(this.virtualSbrkIndex + length);
|
|
13685
|
+
// no alllocation needed
|
|
13686
|
+
if (newVirtualSbrkIndex <= currentSbrkIndex) {
|
|
13687
|
+
this.virtualSbrkIndex = newVirtualSbrkIndex;
|
|
13688
|
+
return currentVirtualSbrkIndex;
|
|
13689
|
+
}
|
|
13690
|
+
// standard allocation using "Writeable" pages
|
|
13691
|
+
const newSbrkIndex = tryAsSbrkIndex(alignToPageSize$1(newVirtualSbrkIndex));
|
|
13692
|
+
// TODO [MaSi]: `getPageNumber` works incorrectly for SbrkIndex. Sbrk index should be changed to MemoryIndex
|
|
13693
|
+
const firstPageNumber = getPageNumber(currentSbrkIndex);
|
|
13694
|
+
const pagesToAllocate = (newSbrkIndex - currentSbrkIndex) / PAGE_SIZE$1;
|
|
13695
|
+
const rangeToAllocate = PageRange.fromStartAndLength(firstPageNumber, pagesToAllocate);
|
|
13696
|
+
for (const pageNumber of rangeToAllocate) {
|
|
13697
|
+
const page = new WriteablePage(pageNumber);
|
|
13698
|
+
this.memory.set(pageNumber, page);
|
|
13699
|
+
}
|
|
13700
|
+
this.virtualSbrkIndex = newVirtualSbrkIndex;
|
|
13701
|
+
this.sbrkIndex = newSbrkIndex;
|
|
13702
|
+
return currentVirtualSbrkIndex;
|
|
13703
|
+
}
|
|
13704
|
+
getPageDump(pageNumber) {
|
|
13705
|
+
const page = this.memory.get(pageNumber);
|
|
13706
|
+
return page?.getPageDump() ?? null;
|
|
13707
|
+
}
|
|
13708
|
+
getDirtyPages() {
|
|
13709
|
+
return this.memory.keys();
|
|
13710
|
+
}
|
|
13711
|
+
}
|
|
13712
|
+
|
|
13713
|
+
class MemoryBuilder {
|
|
13714
|
+
initialMemory = new Map();
|
|
13715
|
+
isFinalized = false;
|
|
13716
|
+
ensureNotFinalized() {
|
|
13717
|
+
if (this.isFinalized) {
|
|
13718
|
+
throw new FinalizedBuilderModification();
|
|
13719
|
+
}
|
|
13720
|
+
}
|
|
13721
|
+
ensureNoReservedMemoryUsage(range) {
|
|
13722
|
+
if (range.overlapsWith(RESERVED_MEMORY_RANGE)) {
|
|
13723
|
+
throw new ReservedMemoryFault();
|
|
13724
|
+
}
|
|
13725
|
+
}
|
|
13726
|
+
/**
|
|
13727
|
+
* Create entire readable pages to handle the `[start, end)` range.
|
|
13728
|
+
*
|
|
13729
|
+
* Note that both `start` and `end` must be multiple of the `PAGE_SIZE`, i.e.
|
|
13730
|
+
* they need to be the start indices of the pages.
|
|
13731
|
+
*
|
|
13732
|
+
* The data passed will be placed at `start`, but might be shorter than the requested range,
|
|
13733
|
+
* prepend it with zeros if you don't wish to have it at the beginning of the page.
|
|
13734
|
+
*/
|
|
13735
|
+
setReadablePages(start, end, data = new Uint8Array()) {
|
|
13736
|
+
this.ensureNotFinalized();
|
|
13737
|
+
check `${start < end} end has to be bigger than start`;
|
|
13738
|
+
check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
13739
|
+
check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
13740
|
+
check `${data.length <= end - start} the initial data is longer than address range`;
|
|
13741
|
+
const length = end - start;
|
|
13742
|
+
const range = MemoryRange.fromStartAndLength(start, length);
|
|
13743
|
+
this.ensureNoReservedMemoryUsage(range);
|
|
13744
|
+
const pages = Array.from(PageRange.fromMemoryRange(range));
|
|
13745
|
+
const noOfPages = pages.length;
|
|
13746
|
+
for (let i = 0; i < noOfPages; i++) {
|
|
13747
|
+
const pageNumber = pages[i];
|
|
13748
|
+
const dataChunk = data.subarray(i * PAGE_SIZE$1, (i + 1) * PAGE_SIZE$1);
|
|
13749
|
+
const page = new ReadablePage(pageNumber, dataChunk);
|
|
13750
|
+
this.initialMemory.set(pageNumber, page);
|
|
13751
|
+
}
|
|
13752
|
+
return this;
|
|
13753
|
+
}
|
|
13754
|
+
/**
|
|
13755
|
+
* Create entire writeable pages to handle the `[start, end)` range.
|
|
13756
|
+
*
|
|
13757
|
+
* Note that both `start` and `end` must be multiple of the `PAGE_SIZE`, i.e.
|
|
13758
|
+
* they need to be the start indices of the pages.
|
|
13759
|
+
*
|
|
13760
|
+
* The data passed will be placed at `start`, but might be shorter than the requested range,
|
|
13761
|
+
* prepend it with zeros if you don't wish to have it at the beginning of the page.
|
|
13762
|
+
*/
|
|
13763
|
+
setWriteablePages(start, end, data = new Uint8Array()) {
|
|
13764
|
+
this.ensureNotFinalized();
|
|
13765
|
+
check `${start < end} end has to be bigger than start`;
|
|
13766
|
+
check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
13767
|
+
check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
13768
|
+
check `${data.length <= end - start} the initial data is longer than address range`;
|
|
13769
|
+
const length = end - start;
|
|
13770
|
+
const range = MemoryRange.fromStartAndLength(start, length);
|
|
13771
|
+
this.ensureNoReservedMemoryUsage(range);
|
|
13772
|
+
const pages = Array.from(PageRange.fromMemoryRange(range));
|
|
13773
|
+
const noOfPages = pages.length;
|
|
13774
|
+
for (let i = 0; i < noOfPages; i++) {
|
|
13775
|
+
const pageNumber = pages[i];
|
|
13776
|
+
const dataChunk = data.subarray(i * PAGE_SIZE$1, (i + 1) * PAGE_SIZE$1);
|
|
13777
|
+
const page = new WriteablePage(pageNumber, dataChunk);
|
|
13778
|
+
this.initialMemory.set(pageNumber, page);
|
|
13779
|
+
}
|
|
13780
|
+
return this;
|
|
13781
|
+
}
|
|
13782
|
+
/**
|
|
13783
|
+
* This function can be useful when page map and initial memory data are provided separatelly.
|
|
13784
|
+
* You can use setWriteablePages/setReadablePages to create empty pages and then setData to fill them
|
|
13785
|
+
*/
|
|
13786
|
+
setData(start, data) {
|
|
13787
|
+
this.ensureNotFinalized();
|
|
13788
|
+
const pageOffset = start % PAGE_SIZE$1;
|
|
13789
|
+
const remainingSpaceOnPage = PAGE_SIZE$1 - pageOffset;
|
|
13790
|
+
check `${data.length <= remainingSpaceOnPage} The data has to fit into a single page.`;
|
|
13791
|
+
const length = data.length;
|
|
13792
|
+
const range = MemoryRange.fromStartAndLength(start, length);
|
|
13793
|
+
this.ensureNoReservedMemoryUsage(range);
|
|
13794
|
+
const pageNumber = getPageNumber(start);
|
|
13795
|
+
const page = this.initialMemory.get(pageNumber);
|
|
13796
|
+
if (page === undefined) {
|
|
13797
|
+
throw new PageNotExist();
|
|
13798
|
+
}
|
|
13799
|
+
const startPageIndex = tryAsPageIndex(start - page.start);
|
|
13800
|
+
page.setData(startPageIndex, data);
|
|
13801
|
+
return this;
|
|
13802
|
+
}
|
|
13803
|
+
finalize(startHeapIndex, endHeapIndex) {
|
|
13804
|
+
check `
|
|
13805
|
+
${startHeapIndex <= endHeapIndex}
|
|
13806
|
+
startHeapIndex (${startHeapIndex}) has to be less than or equal to endHeapIndex (${endHeapIndex})
|
|
13807
|
+
`;
|
|
13808
|
+
this.ensureNotFinalized();
|
|
13809
|
+
const heapRange = MemoryRange.fromStartAndLength(startHeapIndex, endHeapIndex - startHeapIndex);
|
|
13810
|
+
const heapPagesRange = PageRange.fromMemoryRange(heapRange);
|
|
13811
|
+
const initializedPageNumbers = Array.from(this.initialMemory.keys());
|
|
13812
|
+
for (const pageNumber of initializedPageNumbers) {
|
|
13813
|
+
if (heapPagesRange.isInRange(pageNumber)) {
|
|
13814
|
+
throw new IncorrectSbrkIndex();
|
|
13815
|
+
}
|
|
13816
|
+
}
|
|
13817
|
+
const memory = Memory.fromInitialMemory({
|
|
13818
|
+
memory: this.initialMemory,
|
|
13819
|
+
sbrkIndex: tryAsSbrkIndex(startHeapIndex),
|
|
13820
|
+
endHeapIndex,
|
|
13821
|
+
});
|
|
13822
|
+
this.isFinalized = true;
|
|
13823
|
+
return memory;
|
|
13824
|
+
}
|
|
13825
|
+
}
|
|
13826
|
+
|
|
13827
|
+
// GP reference: https://graypaper.fluffylabs.dev/#/7e6ff6a/2d32002d3200?v=0.6.7
|
|
13828
|
+
const PAGE_SIZE = 2 ** 12; // Z_P from GP
|
|
13829
|
+
const SEGMENT_SIZE = 2 ** 16; // Z_Z from GP
|
|
13830
|
+
const DATA_LEGNTH = 2 ** 24; // Z_I from GP
|
|
13831
|
+
const STACK_SEGMENT = 0xfe_fe_00_00; // 2^32 - 2Z_Z - Z_I from GP
|
|
13832
|
+
const ARGS_SEGMENT = 0xfe_ff_00_00; // 2^32 - Z_Z - Z_I from GP
|
|
13833
|
+
const LAST_PAGE = 0xff_ff_00_00;
|
|
13834
|
+
|
|
13835
|
+
// GP reference: https://graypaper.fluffylabs.dev/#/579bd12/2bd2022bd202
|
|
13836
|
+
function alignToSegmentSize(size) {
|
|
13837
|
+
// Q(x) from GP
|
|
13838
|
+
return SEGMENT_SIZE * Math.ceil(size / SEGMENT_SIZE);
|
|
13839
|
+
}
|
|
13840
|
+
function alignToPageSize(size) {
|
|
13841
|
+
// P(x) from GP
|
|
13842
|
+
return PAGE_SIZE * Math.ceil(size / PAGE_SIZE);
|
|
13843
|
+
}
|
|
13844
|
+
|
|
13845
|
+
const NO_OF_REGISTERS = 13;
|
|
13846
|
+
class MemorySegment extends WithDebug {
|
|
13847
|
+
start;
|
|
13848
|
+
end;
|
|
13849
|
+
data;
|
|
13850
|
+
static from({ start, end, data }) {
|
|
13851
|
+
return new MemorySegment(start, end, data);
|
|
13852
|
+
}
|
|
13853
|
+
constructor(start, end, data) {
|
|
13854
|
+
super();
|
|
13855
|
+
this.start = start;
|
|
13856
|
+
this.end = end;
|
|
13857
|
+
this.data = data;
|
|
13858
|
+
}
|
|
13859
|
+
}
|
|
13860
|
+
class SpiMemory extends WithDebug {
|
|
13861
|
+
readable;
|
|
13862
|
+
writeable;
|
|
13863
|
+
sbrkIndex;
|
|
13864
|
+
heapEnd;
|
|
13865
|
+
constructor(readable, writeable, sbrkIndex, heapEnd) {
|
|
13866
|
+
super();
|
|
13867
|
+
this.readable = readable;
|
|
13868
|
+
this.writeable = writeable;
|
|
13869
|
+
this.sbrkIndex = sbrkIndex;
|
|
13870
|
+
this.heapEnd = heapEnd;
|
|
13871
|
+
}
|
|
13872
|
+
}
|
|
13873
|
+
class SpiProgram extends WithDebug {
|
|
13874
|
+
code;
|
|
13875
|
+
memory;
|
|
13876
|
+
registers;
|
|
13877
|
+
constructor(code, memory, registers) {
|
|
13878
|
+
super();
|
|
13879
|
+
this.code = code;
|
|
13880
|
+
this.memory = memory;
|
|
13881
|
+
this.registers = registers;
|
|
13882
|
+
}
|
|
13883
|
+
}
|
|
13884
|
+
/**
|
|
13885
|
+
* program = E_3(|o|) ++ E_3(|w|) ++ E_2(z) ++ E_3(s) ++ o ++ w ++ E_4(|c|) ++ c
|
|
13886
|
+
*
|
|
13887
|
+
* E_n - little endian encoding, n - length
|
|
13888
|
+
* o - initial read only data
|
|
13889
|
+
* w - initial heap
|
|
13890
|
+
* z - heap pages filled with zeros
|
|
13891
|
+
* s - stack size
|
|
13892
|
+
* c - program code
|
|
13893
|
+
*
|
|
13894
|
+
* https://graypaper.fluffylabs.dev/#/579bd12/2b92022b9202
|
|
13895
|
+
*/
|
|
13896
|
+
function decodeStandardProgram(program, args) {
|
|
13897
|
+
const decoder = Decoder.fromBlob(program);
|
|
13898
|
+
const oLength = decoder.u24();
|
|
13899
|
+
const wLength = decoder.u24();
|
|
13900
|
+
check `${args.length <= DATA_LEGNTH} Incorrect arguments length`;
|
|
13901
|
+
check `${oLength <= DATA_LEGNTH} Incorrect readonly segment length`;
|
|
13902
|
+
const readOnlyLength = oLength;
|
|
13903
|
+
check `${wLength <= DATA_LEGNTH} Incorrect heap segment length`;
|
|
13904
|
+
const heapLength = wLength;
|
|
13905
|
+
const noOfHeapZerosPages = decoder.u16();
|
|
13906
|
+
const stackSize = decoder.u24();
|
|
13907
|
+
const readOnlyMemory = decoder.bytes(readOnlyLength).raw;
|
|
13908
|
+
const initialHeap = decoder.bytes(heapLength).raw;
|
|
13909
|
+
const codeLength = decoder.u32();
|
|
13910
|
+
const code = decoder.bytes(codeLength).raw;
|
|
13911
|
+
decoder.finish();
|
|
13912
|
+
const readonlyDataStart = SEGMENT_SIZE;
|
|
13913
|
+
const readonlyDataEnd = SEGMENT_SIZE + alignToPageSize(readOnlyLength);
|
|
13914
|
+
const heapDataStart = 2 * SEGMENT_SIZE + alignToSegmentSize(readOnlyLength);
|
|
13915
|
+
const heapDataEnd = heapDataStart + alignToPageSize(heapLength);
|
|
13916
|
+
const heapZerosEnd = heapDataStart + alignToPageSize(heapLength) + noOfHeapZerosPages * PAGE_SIZE;
|
|
13917
|
+
const stackStart = STACK_SEGMENT - alignToPageSize(stackSize);
|
|
13918
|
+
const stackEnd = STACK_SEGMENT;
|
|
13919
|
+
const argsStart = ARGS_SEGMENT;
|
|
13920
|
+
const argsEnd = argsStart + alignToPageSize(args.length);
|
|
13921
|
+
const argsZerosEnd = argsEnd + alignToPageSize(args.length);
|
|
13922
|
+
function nonEmpty(s) {
|
|
13923
|
+
return s !== false;
|
|
13924
|
+
}
|
|
13925
|
+
const readableMemory = [
|
|
13926
|
+
readOnlyLength > 0 && getMemorySegment(readonlyDataStart, readonlyDataEnd, readOnlyMemory),
|
|
13927
|
+
args.length > 0 && getMemorySegment(argsStart, argsEnd, args),
|
|
13928
|
+
argsEnd < argsZerosEnd && getMemorySegment(argsEnd, argsZerosEnd),
|
|
13929
|
+
].filter(nonEmpty);
|
|
13930
|
+
const writeableMemory = [
|
|
13931
|
+
heapLength > 0 && getMemorySegment(heapDataStart, heapDataEnd, initialHeap),
|
|
13932
|
+
heapDataEnd < heapZerosEnd && getMemorySegment(heapDataEnd, heapZerosEnd),
|
|
13933
|
+
stackStart < stackEnd && getMemorySegment(stackStart, stackEnd),
|
|
13934
|
+
].filter(nonEmpty);
|
|
13935
|
+
return new SpiProgram(code, new SpiMemory(readableMemory, writeableMemory, heapZerosEnd, stackStart), getRegisters(args.length));
|
|
13936
|
+
}
|
|
13937
|
+
function getMemorySegment(start, end, data = null) {
|
|
13938
|
+
return new MemorySegment(start, end, data);
|
|
13939
|
+
}
|
|
13940
|
+
function getRegisters(argsLength) {
|
|
13941
|
+
const regs = new BigUint64Array(NO_OF_REGISTERS);
|
|
13942
|
+
// GP reference: https://graypaper.fluffylabs.dev/#/579bd12/2c7c012cb101
|
|
13943
|
+
regs[0] = BigInt(LAST_PAGE);
|
|
13944
|
+
regs[1] = BigInt(STACK_SEGMENT);
|
|
13945
|
+
regs[7] = BigInt(ARGS_SEGMENT);
|
|
13946
|
+
regs[8] = BigInt(argsLength);
|
|
13947
|
+
return regs;
|
|
13880
13948
|
}
|
|
13881
13949
|
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
terminationInstructions[Instruction.LOAD_IMM_JUMP] = true;
|
|
13890
|
-
terminationInstructions[Instruction.LOAD_IMM_JUMP_IND] = true;
|
|
13891
|
-
terminationInstructions[Instruction.BRANCH_EQ] = true;
|
|
13892
|
-
terminationInstructions[Instruction.BRANCH_NE] = true;
|
|
13893
|
-
terminationInstructions[Instruction.BRANCH_GE_U] = true;
|
|
13894
|
-
terminationInstructions[Instruction.BRANCH_GE_S] = true;
|
|
13895
|
-
terminationInstructions[Instruction.BRANCH_LT_U] = true;
|
|
13896
|
-
terminationInstructions[Instruction.BRANCH_LT_S] = true;
|
|
13897
|
-
terminationInstructions[Instruction.BRANCH_EQ_IMM] = true;
|
|
13898
|
-
terminationInstructions[Instruction.BRANCH_NE_IMM] = true;
|
|
13899
|
-
terminationInstructions[Instruction.BRANCH_LT_U_IMM] = true;
|
|
13900
|
-
terminationInstructions[Instruction.BRANCH_LT_S_IMM] = true;
|
|
13901
|
-
terminationInstructions[Instruction.BRANCH_LE_U_IMM] = true;
|
|
13902
|
-
terminationInstructions[Instruction.BRANCH_LE_S_IMM] = true;
|
|
13903
|
-
terminationInstructions[Instruction.BRANCH_GE_U_IMM] = true;
|
|
13904
|
-
terminationInstructions[Instruction.BRANCH_GE_S_IMM] = true;
|
|
13905
|
-
terminationInstructions[Instruction.BRANCH_GT_U_IMM] = true;
|
|
13906
|
-
terminationInstructions[Instruction.BRANCH_GT_S_IMM] = true;
|
|
13907
|
-
return terminationInstructions;
|
|
13908
|
-
})();
|
|
13950
|
+
var index$7 = /*#__PURE__*/Object.freeze({
|
|
13951
|
+
__proto__: null,
|
|
13952
|
+
MemorySegment: MemorySegment,
|
|
13953
|
+
SpiMemory: SpiMemory,
|
|
13954
|
+
SpiProgram: SpiProgram,
|
|
13955
|
+
decodeStandardProgram: decodeStandardProgram
|
|
13956
|
+
});
|
|
13909
13957
|
|
|
13910
|
-
class
|
|
13911
|
-
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
const
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
|
|
13958
|
+
class Program {
|
|
13959
|
+
code;
|
|
13960
|
+
registers;
|
|
13961
|
+
memory;
|
|
13962
|
+
metadata;
|
|
13963
|
+
static fromSpi(blob, args, hasMetadata) {
|
|
13964
|
+
const { code: spiCode, metadata } = hasMetadata ? extractCodeAndMetadata(blob) : { code: blob };
|
|
13965
|
+
const { code, memory: rawMemory, registers } = decodeStandardProgram(spiCode, args);
|
|
13966
|
+
const regs = new Registers();
|
|
13967
|
+
regs.copyFrom(registers);
|
|
13968
|
+
const memoryBuilder = new MemoryBuilder();
|
|
13969
|
+
for (const { start, end, data } of rawMemory.readable) {
|
|
13970
|
+
const startIndex = tryAsMemoryIndex(start);
|
|
13971
|
+
const endIndex = tryAsMemoryIndex(end);
|
|
13972
|
+
memoryBuilder.setReadablePages(startIndex, endIndex, data ?? new Uint8Array());
|
|
13921
13973
|
}
|
|
13974
|
+
for (const { start, end, data } of rawMemory.writeable) {
|
|
13975
|
+
const startIndex = tryAsMemoryIndex(start);
|
|
13976
|
+
const endIndex = tryAsMemoryIndex(end);
|
|
13977
|
+
memoryBuilder.setWriteablePages(startIndex, endIndex, data ?? new Uint8Array());
|
|
13978
|
+
}
|
|
13979
|
+
const heapStart = tryAsMemoryIndex(rawMemory.sbrkIndex);
|
|
13980
|
+
const heapEnd = tryAsSbrkIndex(rawMemory.heapEnd);
|
|
13981
|
+
const memory = memoryBuilder.finalize(heapStart, heapEnd);
|
|
13982
|
+
return new Program(code, regs, memory, metadata);
|
|
13922
13983
|
}
|
|
13923
|
-
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
const instructionGasMap = (() => {
|
|
13929
|
-
const instructionGasMap = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
|
|
13930
|
-
for (let i = 0; i < HIGHEST_INSTRUCTION_NUMBER + 1; i++) {
|
|
13931
|
-
const gas = byteToOpCodeMap[i]?.gas;
|
|
13932
|
-
instructionGasMap[i] = gas;
|
|
13984
|
+
static fromGeneric(blob, hasMetadata) {
|
|
13985
|
+
const { code, metadata } = hasMetadata ? extractCodeAndMetadata(blob) : { code: blob };
|
|
13986
|
+
const regs = new Registers();
|
|
13987
|
+
const memory = new Memory();
|
|
13988
|
+
return new Program(code, regs, memory, metadata);
|
|
13933
13989
|
}
|
|
13934
|
-
|
|
13935
|
-
|
|
13936
|
-
|
|
13937
|
-
|
|
13938
|
-
|
|
13939
|
-
status = null;
|
|
13940
|
-
/**
|
|
13941
|
-
* A numeric exit parameter of the PVM.
|
|
13942
|
-
*
|
|
13943
|
-
* In case of a `status === Result.FAULT` this will be the memory address
|
|
13944
|
-
* that triggered the fault.
|
|
13945
|
-
* In case of a `status === Result.HOST` this will be the host call index
|
|
13946
|
-
* that should be invoked.
|
|
13947
|
-
*
|
|
13948
|
-
* In any other circumstance the value should be `null`.
|
|
13949
|
-
*/
|
|
13950
|
-
exitParam = null;
|
|
13951
|
-
reset() {
|
|
13952
|
-
this.nextPc = 0;
|
|
13953
|
-
this.status = null;
|
|
13954
|
-
this.exitParam = null;
|
|
13990
|
+
constructor(code, registers, memory, metadata = new Uint8Array()) {
|
|
13991
|
+
this.code = code;
|
|
13992
|
+
this.registers = registers;
|
|
13993
|
+
this.memory = memory;
|
|
13994
|
+
this.metadata = metadata;
|
|
13955
13995
|
}
|
|
13956
13996
|
}
|
|
13957
|
-
|
|
13958
|
-
const MAX_MEMORY_INDEX = 0xffff_ffff;
|
|
13959
|
-
const MEMORY_SIZE = MAX_MEMORY_INDEX + 1;
|
|
13960
|
-
const PAGE_SIZE_SHIFT = 12;
|
|
13961
|
-
// PAGE_SIZE has to be a power of 2
|
|
13962
|
-
const PAGE_SIZE$1 = 1 << PAGE_SIZE_SHIFT;
|
|
13963
|
-
const MIN_ALLOCATION_SHIFT = (() => {
|
|
13964
|
-
const MIN_ALLOCATION_SHIFT = 7;
|
|
13965
|
-
check `${MIN_ALLOCATION_SHIFT < PAGE_SIZE_SHIFT} incorrect minimal allocation shift`;
|
|
13966
|
-
return MIN_ALLOCATION_SHIFT;
|
|
13967
|
-
})();
|
|
13968
|
-
const MIN_ALLOCATION_LENGTH = PAGE_SIZE$1 >> MIN_ALLOCATION_SHIFT;
|
|
13969
|
-
const LAST_PAGE_NUMBER = (MEMORY_SIZE - PAGE_SIZE$1) / PAGE_SIZE$1;
|
|
13970
|
-
/** https://graypaper.fluffylabs.dev/#/68eaa1f/35a60235a602?v=0.6.4 */
|
|
13971
|
-
const RESERVED_NUMBER_OF_PAGES = 16;
|
|
13972
|
-
/** https://graypaper.fluffylabs.dev/#/68eaa1f/35a60235a602?v=0.6.4 */
|
|
13973
|
-
const MAX_NUMBER_OF_PAGES = MEMORY_SIZE / PAGE_SIZE$1;
|
|
13974
|
-
|
|
13975
|
-
const tryAsMemoryIndex = (index) => {
|
|
13976
|
-
check `${index >= 0 && index <= MAX_MEMORY_INDEX} Incorrect memory index: ${index}!`;
|
|
13977
|
-
return asOpaqueType(index);
|
|
13978
|
-
};
|
|
13979
|
-
const tryAsSbrkIndex = (index) => {
|
|
13980
|
-
check `${index >= 0 && index <= MAX_MEMORY_INDEX + 1} Incorrect sbrk index: ${index}!`;
|
|
13981
|
-
return asOpaqueType(index);
|
|
13982
|
-
};
|
|
13983
|
-
|
|
13984
|
-
/** Ensure that given memory `index` is within `[0...PAGE_SIZE)` and can be used to index a page */
|
|
13985
|
-
const tryAsPageIndex = (index) => {
|
|
13986
|
-
check `${index >= 0 && index < PAGE_SIZE$1}, Incorect page index: ${index}!`;
|
|
13987
|
-
return asOpaqueType(index);
|
|
13988
|
-
};
|
|
13989
|
-
/** Ensure that given `index` represents an index of one of the pages. */
|
|
13990
|
-
const tryAsPageNumber = (index) => {
|
|
13991
|
-
check `${index >= 0 && index <= LAST_PAGE_NUMBER}, Incorect page number: ${index}!`;
|
|
13992
|
-
return asOpaqueType(index);
|
|
13993
|
-
};
|
|
13994
13997
|
/**
|
|
13995
|
-
*
|
|
13996
|
-
*
|
|
13997
|
-
* GP references:
|
|
13998
|
-
* 1. The modulo subscription operator is used in all load/store instructions, for example:
|
|
13999
|
-
* https://graypaper.fluffylabs.dev/#/579bd12/25af0125af01
|
|
13998
|
+
* A function that splits preimage into metadata and code.
|
|
14000
13999
|
*
|
|
14001
|
-
*
|
|
14002
|
-
* https://graypaper.fluffylabs.dev/#/579bd12/073a00073a00
|
|
14000
|
+
* https://graypaper.fluffylabs.dev/#/cc517d7/109a01109a01?v=0.6.5
|
|
14003
14001
|
*/
|
|
14004
|
-
function
|
|
14005
|
-
const
|
|
14006
|
-
|
|
14002
|
+
function extractCodeAndMetadata(blobWithMetadata) {
|
|
14003
|
+
const decoder = Decoder.fromBlob(blobWithMetadata);
|
|
14004
|
+
const metadata = decoder.bytesBlob().raw;
|
|
14005
|
+
const code = decoder.remainingBytes().raw;
|
|
14006
|
+
return { metadata, code };
|
|
14007
14007
|
}
|
|
14008
14008
|
|
|
14009
|
-
|
|
14010
|
-
|
|
14011
|
-
|
|
14012
|
-
|
|
14013
|
-
|
|
14014
|
-
}
|
|
14015
|
-
function getStartPageIndex(address) {
|
|
14016
|
-
return tryAsMemoryIndex((address >>> PAGE_SIZE_SHIFT) << PAGE_SIZE_SHIFT);
|
|
14017
|
-
}
|
|
14018
|
-
function getStartPageIndexFromPageNumber(pageNumber) {
|
|
14019
|
-
// >>> 0 is needed to avoid changing sign of the number
|
|
14020
|
-
return tryAsMemoryIndex((pageNumber << PAGE_SIZE_SHIFT) >>> 0);
|
|
14021
|
-
}
|
|
14009
|
+
var index$6 = /*#__PURE__*/Object.freeze({
|
|
14010
|
+
__proto__: null,
|
|
14011
|
+
Program: Program,
|
|
14012
|
+
extractCodeAndMetadata: extractCodeAndMetadata
|
|
14013
|
+
});
|
|
14022
14014
|
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14015
|
+
/**
|
|
14016
|
+
* Upper bound of instruction distance - it is equal to max value of GP's skip function + 1
|
|
14017
|
+
*/
|
|
14018
|
+
const MAX_INSTRUCTION_DISTANCE = 25;
|
|
14019
|
+
/**
|
|
14020
|
+
* Mask class is an implementation of skip function defined in GP.
|
|
14021
|
+
*
|
|
14022
|
+
* https://graypaper.fluffylabs.dev/#/5f542d7/237201239801
|
|
14023
|
+
*/
|
|
14024
|
+
class Mask {
|
|
14025
|
+
/**
|
|
14026
|
+
* The lookup table will have `0` at the index which corresponds to an instruction on the same index in the bytecode.
|
|
14027
|
+
* In case the value is non-zero it signifies the offset to the index with next instruction.
|
|
14028
|
+
*
|
|
14029
|
+
* Example:
|
|
14030
|
+
* ```
|
|
14031
|
+
* 0..1..2..3..4..5..6..7..8..9 # Indices
|
|
14032
|
+
* 0..2..1..0..1..0..3..2..1..0 # lookupTable forward values
|
|
14033
|
+
* ```
|
|
14034
|
+
* There are instructions at indices `0, 3, 5, 9`.
|
|
14035
|
+
*/
|
|
14036
|
+
lookupTableForward;
|
|
14037
|
+
constructor(mask) {
|
|
14038
|
+
this.lookupTableForward = this.buildLookupTableForward(mask);
|
|
14029
14039
|
}
|
|
14030
|
-
|
|
14031
|
-
|
|
14032
|
-
|
|
14033
|
-
|
|
14040
|
+
isInstruction(index) {
|
|
14041
|
+
return this.lookupTableForward[index] === 0;
|
|
14042
|
+
}
|
|
14043
|
+
getNoOfBytesToNextInstruction(index) {
|
|
14044
|
+
check `${index >= 0} index (${index}) cannot be a negative number`;
|
|
14045
|
+
return Math.min(this.lookupTableForward[index] ?? 0, MAX_INSTRUCTION_DISTANCE);
|
|
14046
|
+
}
|
|
14047
|
+
buildLookupTableForward(mask) {
|
|
14048
|
+
const table = safeAllocUint8Array(mask.bitLength);
|
|
14049
|
+
let lastInstructionOffset = 0;
|
|
14050
|
+
for (let i = mask.bitLength - 1; i >= 0; i--) {
|
|
14051
|
+
if (mask.isSet(i)) {
|
|
14052
|
+
lastInstructionOffset = 0;
|
|
14053
|
+
}
|
|
14054
|
+
else {
|
|
14055
|
+
lastInstructionOffset++;
|
|
14056
|
+
}
|
|
14057
|
+
table[i] = lastInstructionOffset;
|
|
14058
|
+
}
|
|
14059
|
+
return table;
|
|
14034
14060
|
}
|
|
14035
|
-
static
|
|
14036
|
-
|
|
14037
|
-
const startPageIndex = getStartPageIndex(memoryIndex);
|
|
14038
|
-
return new PageFault(startPageIndex, isAccessFault);
|
|
14061
|
+
static empty() {
|
|
14062
|
+
return new Mask(BitVec.empty(0));
|
|
14039
14063
|
}
|
|
14040
14064
|
}
|
|
14041
|
-
|
|
14065
|
+
|
|
14066
|
+
var ArgumentType;
|
|
14067
|
+
(function (ArgumentType) {
|
|
14068
|
+
ArgumentType[ArgumentType["NO_ARGUMENTS"] = 0] = "NO_ARGUMENTS";
|
|
14069
|
+
ArgumentType[ArgumentType["ONE_IMMEDIATE"] = 1] = "ONE_IMMEDIATE";
|
|
14070
|
+
ArgumentType[ArgumentType["TWO_IMMEDIATES"] = 2] = "TWO_IMMEDIATES";
|
|
14071
|
+
ArgumentType[ArgumentType["ONE_OFFSET"] = 3] = "ONE_OFFSET";
|
|
14072
|
+
ArgumentType[ArgumentType["ONE_REGISTER_ONE_IMMEDIATE"] = 4] = "ONE_REGISTER_ONE_IMMEDIATE";
|
|
14073
|
+
ArgumentType[ArgumentType["ONE_REGISTER_TWO_IMMEDIATES"] = 5] = "ONE_REGISTER_TWO_IMMEDIATES";
|
|
14074
|
+
ArgumentType[ArgumentType["ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET"] = 6] = "ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET";
|
|
14075
|
+
ArgumentType[ArgumentType["TWO_REGISTERS"] = 7] = "TWO_REGISTERS";
|
|
14076
|
+
ArgumentType[ArgumentType["TWO_REGISTERS_ONE_IMMEDIATE"] = 8] = "TWO_REGISTERS_ONE_IMMEDIATE";
|
|
14077
|
+
ArgumentType[ArgumentType["TWO_REGISTERS_ONE_OFFSET"] = 9] = "TWO_REGISTERS_ONE_OFFSET";
|
|
14078
|
+
ArgumentType[ArgumentType["TWO_REGISTERS_TWO_IMMEDIATES"] = 10] = "TWO_REGISTERS_TWO_IMMEDIATES";
|
|
14079
|
+
ArgumentType[ArgumentType["THREE_REGISTERS"] = 11] = "THREE_REGISTERS";
|
|
14080
|
+
ArgumentType[ArgumentType["ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE"] = 12] = "ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE";
|
|
14081
|
+
})(ArgumentType || (ArgumentType = {}));
|
|
14082
|
+
|
|
14083
|
+
const BUFFER_SIZE = 8;
|
|
14084
|
+
const IMMEDIATE_SIZE$1 = 4;
|
|
14085
|
+
const U32_INDEX = 0;
|
|
14086
|
+
const U64_INDEX = 0;
|
|
14087
|
+
class ImmediateDecoder {
|
|
14088
|
+
u32;
|
|
14089
|
+
i32;
|
|
14090
|
+
u64;
|
|
14091
|
+
i64;
|
|
14092
|
+
view;
|
|
14093
|
+
bytes;
|
|
14042
14094
|
constructor() {
|
|
14043
|
-
|
|
14095
|
+
const buffer = new ArrayBuffer(BUFFER_SIZE);
|
|
14096
|
+
this.u32 = new Uint32Array(buffer);
|
|
14097
|
+
this.i32 = new Int32Array(buffer);
|
|
14098
|
+
this.u64 = new BigUint64Array(buffer);
|
|
14099
|
+
this.i64 = new BigInt64Array(buffer);
|
|
14100
|
+
this.view = new DataView(buffer);
|
|
14101
|
+
this.bytes = new Uint8Array(buffer);
|
|
14044
14102
|
}
|
|
14045
|
-
|
|
14046
|
-
|
|
14047
|
-
|
|
14048
|
-
|
|
14103
|
+
setBytes(bytes) {
|
|
14104
|
+
const n = bytes.length;
|
|
14105
|
+
const msb = n > 0 ? bytes[n - 1] & 0x80 : 0;
|
|
14106
|
+
const noOfBytes = Math.min(n, BUFFER_SIZE);
|
|
14107
|
+
const prefix = msb !== 0 ? 0xff : 0x00;
|
|
14108
|
+
for (let i = 0; i < noOfBytes; i++) {
|
|
14109
|
+
this.view.setUint8(i, bytes[i]);
|
|
14110
|
+
}
|
|
14111
|
+
for (let i = n; i < BUFFER_SIZE; i++) {
|
|
14112
|
+
this.view.setUint8(i, prefix);
|
|
14113
|
+
}
|
|
14049
14114
|
}
|
|
14050
|
-
|
|
14051
|
-
|
|
14052
|
-
|
|
14053
|
-
|
|
14115
|
+
/**
|
|
14116
|
+
* @deprecated Use getU32 instead
|
|
14117
|
+
*/
|
|
14118
|
+
getUnsigned() {
|
|
14119
|
+
return this.u32[U32_INDEX];
|
|
14054
14120
|
}
|
|
14055
|
-
|
|
14056
|
-
|
|
14057
|
-
|
|
14058
|
-
|
|
14121
|
+
/**
|
|
14122
|
+
* @deprecated Use getI32 instead
|
|
14123
|
+
*/
|
|
14124
|
+
getSigned() {
|
|
14125
|
+
return this.i32[U32_INDEX];
|
|
14059
14126
|
}
|
|
14060
|
-
|
|
14061
|
-
|
|
14062
|
-
constructor() {
|
|
14063
|
-
super("You try to fill data on memory page that does not exist!");
|
|
14127
|
+
getU32() {
|
|
14128
|
+
return this.u32[U32_INDEX];
|
|
14064
14129
|
}
|
|
14065
|
-
|
|
14066
|
-
|
|
14067
|
-
|
|
14068
|
-
|
|
14130
|
+
getI32() {
|
|
14131
|
+
return this.i32[U32_INDEX];
|
|
14132
|
+
}
|
|
14133
|
+
getU64() {
|
|
14134
|
+
return this.u64[U64_INDEX];
|
|
14135
|
+
}
|
|
14136
|
+
getI64() {
|
|
14137
|
+
return this.i64[U64_INDEX];
|
|
14138
|
+
}
|
|
14139
|
+
getBytesAsLittleEndian() {
|
|
14140
|
+
return this.bytes.subarray(0, IMMEDIATE_SIZE$1);
|
|
14141
|
+
}
|
|
14142
|
+
getExtendedBytesAsLittleEndian() {
|
|
14143
|
+
return this.bytes;
|
|
14069
14144
|
}
|
|
14070
14145
|
}
|
|
14071
14146
|
|
|
14072
|
-
|
|
14073
|
-
|
|
14074
|
-
|
|
14075
|
-
|
|
14076
|
-
|
|
14077
|
-
|
|
14078
|
-
class MemoryRange {
|
|
14079
|
-
start;
|
|
14080
|
-
length;
|
|
14081
|
-
/**
|
|
14082
|
-
* Exclusive end index of the range.
|
|
14083
|
-
*
|
|
14084
|
-
* NOTE: The index may be wrapped around and smaller than `start`!
|
|
14085
|
-
*/
|
|
14086
|
-
end;
|
|
14087
|
-
/**
|
|
14088
|
-
* Inclusive last index of the range (present unless the range is empty).
|
|
14089
|
-
*
|
|
14090
|
-
* NOTE: the index may be wrapped around and smaller than `start`!
|
|
14091
|
-
*/
|
|
14092
|
-
lastIndex = null;
|
|
14093
|
-
constructor(start, length) {
|
|
14094
|
-
this.start = start;
|
|
14095
|
-
this.length = length;
|
|
14096
|
-
this.end = tryAsMemoryIndex((this.start + this.length) % MEMORY_SIZE);
|
|
14097
|
-
if (length > 0) {
|
|
14098
|
-
this.lastIndex = tryAsMemoryIndex((this.end - 1 + MEMORY_SIZE) % MEMORY_SIZE);
|
|
14099
|
-
}
|
|
14147
|
+
const MAX_REGISTER_INDEX = NO_OF_REGISTERS$1 - 1;
|
|
14148
|
+
const MAX_LENGTH = 4;
|
|
14149
|
+
class NibblesDecoder {
|
|
14150
|
+
byte = new Int8Array(1);
|
|
14151
|
+
setByte(byte) {
|
|
14152
|
+
this.byte[0] = byte;
|
|
14100
14153
|
}
|
|
14101
|
-
|
|
14102
|
-
|
|
14103
|
-
if (!Number.isInteger(length) || length < 0 || length > MEMORY_SIZE) {
|
|
14104
|
-
throw new TypeError(`length must be a non-negative integer and less than ${MEMORY_SIZE}, got ${length}`);
|
|
14105
|
-
}
|
|
14106
|
-
return new MemoryRange(start, length);
|
|
14154
|
+
getHighNibble() {
|
|
14155
|
+
return (this.byte[0] & 0xf0) >>> 4;
|
|
14107
14156
|
}
|
|
14108
|
-
|
|
14109
|
-
|
|
14110
|
-
return this.length === 0;
|
|
14157
|
+
getLowNibble() {
|
|
14158
|
+
return this.byte[0] & 0x0f;
|
|
14111
14159
|
}
|
|
14112
|
-
|
|
14113
|
-
|
|
14114
|
-
return this.start >= this.end && !this.isEmpty();
|
|
14160
|
+
getHighNibbleAsRegisterIndex() {
|
|
14161
|
+
return Math.min(this.getHighNibble(), MAX_REGISTER_INDEX);
|
|
14115
14162
|
}
|
|
14116
|
-
|
|
14117
|
-
|
|
14118
|
-
if (this.isWrapped()) {
|
|
14119
|
-
return address >= this.start || address < this.end;
|
|
14120
|
-
}
|
|
14121
|
-
return address >= this.start && address < this.end;
|
|
14163
|
+
getLowNibbleAsRegisterIndex() {
|
|
14164
|
+
return Math.min(this.getLowNibble(), MAX_REGISTER_INDEX);
|
|
14122
14165
|
}
|
|
14123
|
-
|
|
14124
|
-
|
|
14125
|
-
|
|
14126
|
-
|
|
14166
|
+
getHighNibbleAsLength() {
|
|
14167
|
+
return Math.min(this.getHighNibble(), MAX_LENGTH);
|
|
14168
|
+
}
|
|
14169
|
+
getLowNibbleAsLength() {
|
|
14170
|
+
return Math.min(this.getLowNibble(), MAX_LENGTH);
|
|
14171
|
+
}
|
|
14172
|
+
}
|
|
14173
|
+
|
|
14174
|
+
const IMMEDIATE_AND_OFFSET_MAX_LENGTH = 4;
|
|
14175
|
+
class ArgsDecoder {
|
|
14176
|
+
nibblesDecoder = new NibblesDecoder();
|
|
14177
|
+
offsetDecoder = new ImmediateDecoder();
|
|
14178
|
+
code = new Uint8Array();
|
|
14179
|
+
mask = Mask.empty();
|
|
14180
|
+
reset(code, mask) {
|
|
14181
|
+
this.code = code;
|
|
14182
|
+
this.mask = mask;
|
|
14183
|
+
}
|
|
14184
|
+
fillArgs(pc, result) {
|
|
14185
|
+
const nextInstructionDistance = 1 + this.mask.getNoOfBytesToNextInstruction(pc + 1);
|
|
14186
|
+
result.noOfBytesToSkip = nextInstructionDistance;
|
|
14187
|
+
switch (result.type) {
|
|
14188
|
+
case ArgumentType.NO_ARGUMENTS:
|
|
14189
|
+
break;
|
|
14190
|
+
case ArgumentType.ONE_IMMEDIATE: {
|
|
14191
|
+
const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, nextInstructionDistance - 1);
|
|
14192
|
+
const argsStartIndex = pc + 1;
|
|
14193
|
+
result.immediateDecoder.setBytes(this.code.subarray(argsStartIndex, argsStartIndex + immediateLength));
|
|
14194
|
+
break;
|
|
14195
|
+
}
|
|
14196
|
+
case ArgumentType.THREE_REGISTERS: {
|
|
14197
|
+
const firstByte = this.code[pc + 1];
|
|
14198
|
+
const secondByte = this.code[pc + 2];
|
|
14199
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14200
|
+
result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14201
|
+
result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
14202
|
+
this.nibblesDecoder.setByte(secondByte);
|
|
14203
|
+
result.thirdRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14204
|
+
break;
|
|
14205
|
+
}
|
|
14206
|
+
case ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE: {
|
|
14207
|
+
const firstByte = this.code[pc + 1];
|
|
14208
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14209
|
+
result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14210
|
+
result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
14211
|
+
const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
|
|
14212
|
+
const immediateStartIndex = pc + 2;
|
|
14213
|
+
const immediateEndIndex = immediateStartIndex + immediateLength;
|
|
14214
|
+
result.immediateDecoder.setBytes(this.code.subarray(immediateStartIndex, immediateEndIndex));
|
|
14215
|
+
break;
|
|
14216
|
+
}
|
|
14217
|
+
case ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET: {
|
|
14218
|
+
const firstByte = this.code[pc + 1];
|
|
14219
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14220
|
+
result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14221
|
+
const immediateLength = this.nibblesDecoder.getHighNibbleAsLength();
|
|
14222
|
+
const immediateStartIndex = pc + 2;
|
|
14223
|
+
const immediateEndIndex = immediateStartIndex + immediateLength;
|
|
14224
|
+
result.immediateDecoder.setBytes(this.code.subarray(immediateStartIndex, immediateEndIndex));
|
|
14225
|
+
const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - immediateLength));
|
|
14226
|
+
const offsetStartIndex = pc + 2 + immediateLength;
|
|
14227
|
+
const offsetEndIndex = offsetStartIndex + offsetLength;
|
|
14228
|
+
this.offsetDecoder.setBytes(this.code.subarray(offsetStartIndex, offsetEndIndex));
|
|
14229
|
+
result.nextPc = pc + this.offsetDecoder.getSigned();
|
|
14230
|
+
break;
|
|
14231
|
+
}
|
|
14232
|
+
case ArgumentType.TWO_REGISTERS_ONE_OFFSET: {
|
|
14233
|
+
const firstByte = this.code[pc + 1];
|
|
14234
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14235
|
+
result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14236
|
+
result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
14237
|
+
const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
|
|
14238
|
+
const offsetStartIndex = pc + 2;
|
|
14239
|
+
const offsetEndIndex = offsetStartIndex + offsetLength;
|
|
14240
|
+
this.offsetDecoder.setBytes(this.code.subarray(offsetStartIndex, offsetEndIndex));
|
|
14241
|
+
result.nextPc = pc + this.offsetDecoder.getSigned();
|
|
14242
|
+
break;
|
|
14243
|
+
}
|
|
14244
|
+
case ArgumentType.TWO_REGISTERS: {
|
|
14245
|
+
const firstByte = this.code[pc + 1];
|
|
14246
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14247
|
+
result.firstRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
14248
|
+
result.secondRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14249
|
+
break;
|
|
14250
|
+
}
|
|
14251
|
+
case ArgumentType.ONE_OFFSET: {
|
|
14252
|
+
const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, nextInstructionDistance - 1);
|
|
14253
|
+
const offsetStartIndex = pc + 1;
|
|
14254
|
+
const offsetEndIndex = offsetStartIndex + offsetLength;
|
|
14255
|
+
const offsetBytes = this.code.subarray(offsetStartIndex, offsetEndIndex);
|
|
14256
|
+
this.offsetDecoder.setBytes(offsetBytes);
|
|
14257
|
+
const offsetValue = this.offsetDecoder.getSigned();
|
|
14258
|
+
result.nextPc = pc + offsetValue;
|
|
14259
|
+
break;
|
|
14260
|
+
}
|
|
14261
|
+
case ArgumentType.ONE_REGISTER_ONE_IMMEDIATE: {
|
|
14262
|
+
const firstByte = this.code[pc + 1];
|
|
14263
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14264
|
+
result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14265
|
+
const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
|
|
14266
|
+
const immediateStartIndex = pc + 2;
|
|
14267
|
+
const immediateEndIndex = immediateStartIndex + immediateLength;
|
|
14268
|
+
const immediateBytes = this.code.subarray(immediateStartIndex, immediateEndIndex);
|
|
14269
|
+
result.immediateDecoder.setBytes(immediateBytes);
|
|
14270
|
+
break;
|
|
14271
|
+
}
|
|
14272
|
+
case ArgumentType.TWO_IMMEDIATES: {
|
|
14273
|
+
const firstByte = this.code[pc + 1];
|
|
14274
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14275
|
+
const firstImmediateLength = this.nibblesDecoder.getLowNibbleAsLength();
|
|
14276
|
+
const firstImmediateStartIndex = pc + 2;
|
|
14277
|
+
const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
|
|
14278
|
+
const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
|
|
14279
|
+
result.firstImmediateDecoder.setBytes(firstImmediateBytes);
|
|
14280
|
+
const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - firstImmediateLength));
|
|
14281
|
+
const secondImmediateStartIndex = firstImmediateEndIndex;
|
|
14282
|
+
const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
|
|
14283
|
+
const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
|
|
14284
|
+
result.secondImmediateDecoder.setBytes(secondImmediateBytes);
|
|
14285
|
+
break;
|
|
14286
|
+
}
|
|
14287
|
+
case ArgumentType.ONE_REGISTER_TWO_IMMEDIATES: {
|
|
14288
|
+
const firstByte = this.code[pc + 1];
|
|
14289
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14290
|
+
result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14291
|
+
const firstImmediateLength = this.nibblesDecoder.getHighNibbleAsLength();
|
|
14292
|
+
const firstImmediateStartIndex = pc + 2;
|
|
14293
|
+
const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
|
|
14294
|
+
const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
|
|
14295
|
+
result.firstImmediateDecoder.setBytes(firstImmediateBytes);
|
|
14296
|
+
const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - firstImmediateLength));
|
|
14297
|
+
const secondImmediateStartIndex = firstImmediateEndIndex;
|
|
14298
|
+
const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
|
|
14299
|
+
const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
|
|
14300
|
+
result.secondImmediateDecoder.setBytes(secondImmediateBytes);
|
|
14301
|
+
break;
|
|
14302
|
+
}
|
|
14303
|
+
case ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES: {
|
|
14304
|
+
const firstByte = this.code[pc + 1];
|
|
14305
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14306
|
+
result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14307
|
+
result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
|
|
14308
|
+
const secondByte = this.code[pc + 2];
|
|
14309
|
+
this.nibblesDecoder.setByte(secondByte);
|
|
14310
|
+
const firstImmediateLength = this.nibblesDecoder.getLowNibbleAsLength();
|
|
14311
|
+
const firstImmediateStartIndex = pc + 3;
|
|
14312
|
+
const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
|
|
14313
|
+
const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
|
|
14314
|
+
result.firstImmediateDecoder.setBytes(firstImmediateBytes);
|
|
14315
|
+
const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 3 - firstImmediateLength));
|
|
14316
|
+
const secondImmediateStartIndex = firstImmediateEndIndex;
|
|
14317
|
+
const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
|
|
14318
|
+
const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
|
|
14319
|
+
result.secondImmediateDecoder.setBytes(secondImmediateBytes);
|
|
14320
|
+
break;
|
|
14321
|
+
}
|
|
14322
|
+
case ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE: {
|
|
14323
|
+
const firstByte = this.code[pc + 1];
|
|
14324
|
+
this.nibblesDecoder.setByte(firstByte);
|
|
14325
|
+
result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
|
|
14326
|
+
const immediateStartIndex = pc + 2;
|
|
14327
|
+
const immediateEndIndex = immediateStartIndex + 8;
|
|
14328
|
+
const immediateBytes = this.code.subarray(immediateStartIndex, immediateEndIndex);
|
|
14329
|
+
result.immediateDecoder.setBytes(immediateBytes);
|
|
14330
|
+
break;
|
|
14331
|
+
}
|
|
14127
14332
|
}
|
|
14128
|
-
return (this.isInRange(other.start) ||
|
|
14129
|
-
this.isInRange(other.lastIndex) ||
|
|
14130
|
-
other.isInRange(this.start) ||
|
|
14131
|
-
other.isInRange(this.lastIndex));
|
|
14132
14333
|
}
|
|
14133
14334
|
}
|
|
14134
|
-
/**
|
|
14135
|
-
* The first 16 pages of memory are reserved.
|
|
14136
|
-
*
|
|
14137
|
-
* https://graypaper.fluffylabs.dev/#/cc517d7/24d00024d000?v=0.6.5
|
|
14138
|
-
*
|
|
14139
|
-
* it should be in `memory-consts` but it cannot be there because of circular dependency
|
|
14140
|
-
*/
|
|
14141
|
-
const RESERVED_MEMORY_RANGE = MemoryRange.fromStartAndLength(tryAsMemoryIndex(0), RESERVED_NUMBER_OF_PAGES * PAGE_SIZE$1);
|
|
14142
14335
|
|
|
14143
|
-
|
|
14144
|
-
|
|
14145
|
-
|
|
14146
|
-
|
|
14147
|
-
|
|
14148
|
-
|
|
14149
|
-
|
|
14150
|
-
|
|
14151
|
-
* Exclusive end of the page range.
|
|
14152
|
-
*
|
|
14153
|
-
* NOTE: it may be smaller than `start` in case the range is wrapped.
|
|
14154
|
-
*/
|
|
14155
|
-
end;
|
|
14156
|
-
constructor(start, length) {
|
|
14157
|
-
this.start = start;
|
|
14158
|
-
this.length = length;
|
|
14159
|
-
this.end = tryAsPageNumber((this.start + this.length) % MAX_NUMBER_OF_PAGES);
|
|
14160
|
-
}
|
|
14161
|
-
/**
|
|
14162
|
-
* Creates range of pages that includes all indices in a given memory range.
|
|
14163
|
-
*
|
|
14164
|
-
* Example: For memory range `[PAGE_SIZE, MEMORY_SIZE - PAGE_SIZE)`
|
|
14165
|
-
* we will get `[1, MAX_NUMBER_OF_PAGES - 1)` page range.
|
|
14166
|
-
*/
|
|
14167
|
-
static fromMemoryRange(range) {
|
|
14168
|
-
const startPage = getPageNumber(range.start);
|
|
14169
|
-
if (range.isEmpty()) {
|
|
14170
|
-
return new PageRange(startPage, 0);
|
|
14171
|
-
}
|
|
14172
|
-
// lastIndex is not null because we just ensured that the range is not empty
|
|
14173
|
-
const pageWithLastIndex = getPageNumber(range.lastIndex ?? range.end);
|
|
14174
|
-
const endPage = getNextPageNumber(pageWithLastIndex);
|
|
14175
|
-
if ((startPage === endPage || startPage === pageWithLastIndex) && range.length > PAGE_SIZE$1) {
|
|
14176
|
-
// full range
|
|
14177
|
-
return new PageRange(startPage, MAX_NUMBER_OF_PAGES);
|
|
14178
|
-
}
|
|
14179
|
-
const length = startPage < endPage ? endPage - startPage : MAX_NUMBER_OF_PAGES - startPage + endPage;
|
|
14180
|
-
return PageRange.fromStartAndLength(startPage, length);
|
|
14336
|
+
const IMMEDIATE_SIZE = 8;
|
|
14337
|
+
class ExtendedWitdthImmediateDecoder {
|
|
14338
|
+
unsignedImmediate;
|
|
14339
|
+
bytes;
|
|
14340
|
+
constructor() {
|
|
14341
|
+
const buffer = new ArrayBuffer(IMMEDIATE_SIZE);
|
|
14342
|
+
this.unsignedImmediate = new BigUint64Array(buffer);
|
|
14343
|
+
this.bytes = new Uint8Array(buffer);
|
|
14181
14344
|
}
|
|
14182
|
-
|
|
14183
|
-
|
|
14184
|
-
|
|
14185
|
-
|
|
14345
|
+
setBytes(bytes) {
|
|
14346
|
+
let i = 0;
|
|
14347
|
+
for (; i < bytes.length; i++) {
|
|
14348
|
+
this.bytes[i] = bytes[i];
|
|
14186
14349
|
}
|
|
14187
|
-
|
|
14188
|
-
|
|
14189
|
-
/** Returns true if the page range is wrapped (`start` >= `end`) and is not empty */
|
|
14190
|
-
isWrapped() {
|
|
14191
|
-
return this.start >= this.end && !this.isEmpty();
|
|
14192
|
-
}
|
|
14193
|
-
/** Checks if given page number is within the range */
|
|
14194
|
-
isInRange(page) {
|
|
14195
|
-
if (this.isWrapped()) {
|
|
14196
|
-
return page >= this.start || page < this.end;
|
|
14350
|
+
for (; i < IMMEDIATE_SIZE; i++) {
|
|
14351
|
+
this.bytes[i] = 0;
|
|
14197
14352
|
}
|
|
14198
|
-
return page >= this.start && page < this.end;
|
|
14199
14353
|
}
|
|
14200
|
-
|
|
14201
|
-
|
|
14202
|
-
return this.length === 0;
|
|
14354
|
+
getValue() {
|
|
14355
|
+
return this.unsignedImmediate[0];
|
|
14203
14356
|
}
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
return;
|
|
14207
|
-
}
|
|
14208
|
-
const end = this.end;
|
|
14209
|
-
let i = this.start;
|
|
14210
|
-
do {
|
|
14211
|
-
yield i;
|
|
14212
|
-
i = getNextPageNumber(i);
|
|
14213
|
-
} while (i !== end);
|
|
14357
|
+
getBytesAsLittleEndian() {
|
|
14358
|
+
return this.bytes.subarray(0, IMMEDIATE_SIZE);
|
|
14214
14359
|
}
|
|
14215
14360
|
}
|
|
14216
14361
|
|
|
14217
|
-
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
|
|
14362
|
+
const ARGUMENT_TYPE_LENGTH = Object.keys(ArgumentType).length / 2;
|
|
14363
|
+
const createResults = () => {
|
|
14364
|
+
const results = new Array(ARGUMENT_TYPE_LENGTH);
|
|
14365
|
+
results[ArgumentType.NO_ARGUMENTS] = {
|
|
14366
|
+
type: ArgumentType.NO_ARGUMENTS,
|
|
14367
|
+
noOfBytesToSkip: 1,
|
|
14368
|
+
};
|
|
14369
|
+
results[ArgumentType.ONE_IMMEDIATE] = {
|
|
14370
|
+
type: ArgumentType.ONE_IMMEDIATE,
|
|
14371
|
+
noOfBytesToSkip: 1,
|
|
14372
|
+
immediateDecoder: new ImmediateDecoder(),
|
|
14373
|
+
};
|
|
14374
|
+
results[ArgumentType.TWO_REGISTERS] = {
|
|
14375
|
+
type: ArgumentType.TWO_REGISTERS,
|
|
14376
|
+
noOfBytesToSkip: 1,
|
|
14377
|
+
firstRegisterIndex: 0,
|
|
14378
|
+
secondRegisterIndex: 0,
|
|
14379
|
+
};
|
|
14380
|
+
results[ArgumentType.THREE_REGISTERS] = {
|
|
14381
|
+
type: ArgumentType.THREE_REGISTERS,
|
|
14382
|
+
noOfBytesToSkip: 1,
|
|
14383
|
+
firstRegisterIndex: 0,
|
|
14384
|
+
secondRegisterIndex: 0,
|
|
14385
|
+
thirdRegisterIndex: 0,
|
|
14386
|
+
};
|
|
14387
|
+
results[ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET] = {
|
|
14388
|
+
type: ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET,
|
|
14389
|
+
noOfBytesToSkip: 1,
|
|
14390
|
+
registerIndex: 0,
|
|
14391
|
+
immediateDecoder: new ImmediateDecoder(),
|
|
14392
|
+
nextPc: 0,
|
|
14393
|
+
};
|
|
14394
|
+
results[ArgumentType.TWO_REGISTERS_ONE_OFFSET] = {
|
|
14395
|
+
type: ArgumentType.TWO_REGISTERS_ONE_OFFSET,
|
|
14396
|
+
noOfBytesToSkip: 1,
|
|
14397
|
+
firstRegisterIndex: 0,
|
|
14398
|
+
secondRegisterIndex: 0,
|
|
14399
|
+
nextPc: 0,
|
|
14400
|
+
};
|
|
14401
|
+
results[ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE] = {
|
|
14402
|
+
type: ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE,
|
|
14403
|
+
noOfBytesToSkip: 1,
|
|
14404
|
+
firstRegisterIndex: 0,
|
|
14405
|
+
secondRegisterIndex: 0,
|
|
14406
|
+
immediateDecoder: new ImmediateDecoder(),
|
|
14407
|
+
};
|
|
14408
|
+
results[ArgumentType.ONE_REGISTER_ONE_IMMEDIATE] = {
|
|
14409
|
+
type: ArgumentType.ONE_REGISTER_ONE_IMMEDIATE,
|
|
14410
|
+
noOfBytesToSkip: 1,
|
|
14411
|
+
registerIndex: 0,
|
|
14412
|
+
immediateDecoder: new ImmediateDecoder(),
|
|
14413
|
+
};
|
|
14414
|
+
results[ArgumentType.ONE_REGISTER_TWO_IMMEDIATES] = {
|
|
14415
|
+
type: ArgumentType.ONE_REGISTER_TWO_IMMEDIATES,
|
|
14416
|
+
noOfBytesToSkip: 1,
|
|
14417
|
+
registerIndex: 0,
|
|
14418
|
+
firstImmediateDecoder: new ImmediateDecoder(),
|
|
14419
|
+
secondImmediateDecoder: new ImmediateDecoder(),
|
|
14420
|
+
};
|
|
14421
|
+
results[ArgumentType.ONE_OFFSET] = {
|
|
14422
|
+
type: ArgumentType.ONE_OFFSET,
|
|
14423
|
+
noOfBytesToSkip: 1,
|
|
14424
|
+
nextPc: 0,
|
|
14425
|
+
};
|
|
14426
|
+
results[ArgumentType.TWO_IMMEDIATES] = {
|
|
14427
|
+
type: ArgumentType.TWO_IMMEDIATES,
|
|
14428
|
+
noOfBytesToSkip: 1,
|
|
14429
|
+
firstImmediateDecoder: new ImmediateDecoder(),
|
|
14430
|
+
secondImmediateDecoder: new ImmediateDecoder(),
|
|
14431
|
+
};
|
|
14432
|
+
results[ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES] = {
|
|
14433
|
+
type: ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES,
|
|
14434
|
+
noOfBytesToSkip: 1,
|
|
14435
|
+
firstImmediateDecoder: new ImmediateDecoder(),
|
|
14436
|
+
secondImmediateDecoder: new ImmediateDecoder(),
|
|
14437
|
+
firstRegisterIndex: 0,
|
|
14438
|
+
secondRegisterIndex: 0,
|
|
14439
|
+
};
|
|
14440
|
+
results[ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE] = {
|
|
14441
|
+
type: ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE,
|
|
14442
|
+
noOfBytesToSkip: 9,
|
|
14443
|
+
registerIndex: 0,
|
|
14444
|
+
immediateDecoder: new ExtendedWitdthImmediateDecoder(),
|
|
14445
|
+
};
|
|
14446
|
+
return results;
|
|
14447
|
+
};
|
|
14448
|
+
|
|
14449
|
+
var Instruction;
|
|
14450
|
+
(function (Instruction) {
|
|
14451
|
+
Instruction[Instruction["TRAP"] = 0] = "TRAP";
|
|
14452
|
+
Instruction[Instruction["FALLTHROUGH"] = 1] = "FALLTHROUGH";
|
|
14453
|
+
Instruction[Instruction["ECALLI"] = 10] = "ECALLI";
|
|
14454
|
+
Instruction[Instruction["LOAD_IMM_64"] = 20] = "LOAD_IMM_64";
|
|
14455
|
+
Instruction[Instruction["STORE_IMM_U8"] = 30] = "STORE_IMM_U8";
|
|
14456
|
+
Instruction[Instruction["STORE_IMM_U16"] = 31] = "STORE_IMM_U16";
|
|
14457
|
+
Instruction[Instruction["STORE_IMM_U32"] = 32] = "STORE_IMM_U32";
|
|
14458
|
+
Instruction[Instruction["STORE_IMM_U64"] = 33] = "STORE_IMM_U64";
|
|
14459
|
+
Instruction[Instruction["JUMP"] = 40] = "JUMP";
|
|
14460
|
+
Instruction[Instruction["JUMP_IND"] = 50] = "JUMP_IND";
|
|
14461
|
+
Instruction[Instruction["LOAD_IMM"] = 51] = "LOAD_IMM";
|
|
14462
|
+
Instruction[Instruction["LOAD_U8"] = 52] = "LOAD_U8";
|
|
14463
|
+
Instruction[Instruction["LOAD_I8"] = 53] = "LOAD_I8";
|
|
14464
|
+
Instruction[Instruction["LOAD_U16"] = 54] = "LOAD_U16";
|
|
14465
|
+
Instruction[Instruction["LOAD_I16"] = 55] = "LOAD_I16";
|
|
14466
|
+
Instruction[Instruction["LOAD_U32"] = 56] = "LOAD_U32";
|
|
14467
|
+
Instruction[Instruction["LOAD_I32"] = 57] = "LOAD_I32";
|
|
14468
|
+
Instruction[Instruction["LOAD_U64"] = 58] = "LOAD_U64";
|
|
14469
|
+
Instruction[Instruction["STORE_U8"] = 59] = "STORE_U8";
|
|
14470
|
+
Instruction[Instruction["STORE_U16"] = 60] = "STORE_U16";
|
|
14471
|
+
Instruction[Instruction["STORE_U32"] = 61] = "STORE_U32";
|
|
14472
|
+
Instruction[Instruction["STORE_U64"] = 62] = "STORE_U64";
|
|
14473
|
+
Instruction[Instruction["STORE_IMM_IND_U8"] = 70] = "STORE_IMM_IND_U8";
|
|
14474
|
+
Instruction[Instruction["STORE_IMM_IND_U16"] = 71] = "STORE_IMM_IND_U16";
|
|
14475
|
+
Instruction[Instruction["STORE_IMM_IND_U32"] = 72] = "STORE_IMM_IND_U32";
|
|
14476
|
+
Instruction[Instruction["STORE_IMM_IND_U64"] = 73] = "STORE_IMM_IND_U64";
|
|
14477
|
+
Instruction[Instruction["LOAD_IMM_JUMP"] = 80] = "LOAD_IMM_JUMP";
|
|
14478
|
+
Instruction[Instruction["BRANCH_EQ_IMM"] = 81] = "BRANCH_EQ_IMM";
|
|
14479
|
+
Instruction[Instruction["BRANCH_NE_IMM"] = 82] = "BRANCH_NE_IMM";
|
|
14480
|
+
Instruction[Instruction["BRANCH_LT_U_IMM"] = 83] = "BRANCH_LT_U_IMM";
|
|
14481
|
+
Instruction[Instruction["BRANCH_LE_U_IMM"] = 84] = "BRANCH_LE_U_IMM";
|
|
14482
|
+
Instruction[Instruction["BRANCH_GE_U_IMM"] = 85] = "BRANCH_GE_U_IMM";
|
|
14483
|
+
Instruction[Instruction["BRANCH_GT_U_IMM"] = 86] = "BRANCH_GT_U_IMM";
|
|
14484
|
+
Instruction[Instruction["BRANCH_LT_S_IMM"] = 87] = "BRANCH_LT_S_IMM";
|
|
14485
|
+
Instruction[Instruction["BRANCH_LE_S_IMM"] = 88] = "BRANCH_LE_S_IMM";
|
|
14486
|
+
Instruction[Instruction["BRANCH_GE_S_IMM"] = 89] = "BRANCH_GE_S_IMM";
|
|
14487
|
+
Instruction[Instruction["BRANCH_GT_S_IMM"] = 90] = "BRANCH_GT_S_IMM";
|
|
14488
|
+
Instruction[Instruction["MOVE_REG"] = 100] = "MOVE_REG";
|
|
14489
|
+
Instruction[Instruction["SBRK"] = 101] = "SBRK";
|
|
14490
|
+
Instruction[Instruction["COUNT_SET_BITS_64"] = 102] = "COUNT_SET_BITS_64";
|
|
14491
|
+
Instruction[Instruction["COUNT_SET_BITS_32"] = 103] = "COUNT_SET_BITS_32";
|
|
14492
|
+
Instruction[Instruction["LEADING_ZERO_BITS_64"] = 104] = "LEADING_ZERO_BITS_64";
|
|
14493
|
+
Instruction[Instruction["LEADING_ZERO_BITS_32"] = 105] = "LEADING_ZERO_BITS_32";
|
|
14494
|
+
Instruction[Instruction["TRAILING_ZERO_BITS_64"] = 106] = "TRAILING_ZERO_BITS_64";
|
|
14495
|
+
Instruction[Instruction["TRAILING_ZERO_BITS_32"] = 107] = "TRAILING_ZERO_BITS_32";
|
|
14496
|
+
Instruction[Instruction["SIGN_EXTEND_8"] = 108] = "SIGN_EXTEND_8";
|
|
14497
|
+
Instruction[Instruction["SIGN_EXTEND_16"] = 109] = "SIGN_EXTEND_16";
|
|
14498
|
+
Instruction[Instruction["ZERO_EXTEND_16"] = 110] = "ZERO_EXTEND_16";
|
|
14499
|
+
Instruction[Instruction["REVERSE_BYTES"] = 111] = "REVERSE_BYTES";
|
|
14500
|
+
Instruction[Instruction["STORE_IND_U8"] = 120] = "STORE_IND_U8";
|
|
14501
|
+
Instruction[Instruction["STORE_IND_U16"] = 121] = "STORE_IND_U16";
|
|
14502
|
+
Instruction[Instruction["STORE_IND_U32"] = 122] = "STORE_IND_U32";
|
|
14503
|
+
Instruction[Instruction["STORE_IND_U64"] = 123] = "STORE_IND_U64";
|
|
14504
|
+
Instruction[Instruction["LOAD_IND_U8"] = 124] = "LOAD_IND_U8";
|
|
14505
|
+
Instruction[Instruction["LOAD_IND_I8"] = 125] = "LOAD_IND_I8";
|
|
14506
|
+
Instruction[Instruction["LOAD_IND_U16"] = 126] = "LOAD_IND_U16";
|
|
14507
|
+
Instruction[Instruction["LOAD_IND_I16"] = 127] = "LOAD_IND_I16";
|
|
14508
|
+
Instruction[Instruction["LOAD_IND_U32"] = 128] = "LOAD_IND_U32";
|
|
14509
|
+
Instruction[Instruction["LOAD_IND_I32"] = 129] = "LOAD_IND_I32";
|
|
14510
|
+
Instruction[Instruction["LOAD_IND_U64"] = 130] = "LOAD_IND_U64";
|
|
14511
|
+
Instruction[Instruction["ADD_IMM_32"] = 131] = "ADD_IMM_32";
|
|
14512
|
+
Instruction[Instruction["AND_IMM"] = 132] = "AND_IMM";
|
|
14513
|
+
Instruction[Instruction["XOR_IMM"] = 133] = "XOR_IMM";
|
|
14514
|
+
Instruction[Instruction["OR_IMM"] = 134] = "OR_IMM";
|
|
14515
|
+
Instruction[Instruction["MUL_IMM_32"] = 135] = "MUL_IMM_32";
|
|
14516
|
+
Instruction[Instruction["SET_LT_U_IMM"] = 136] = "SET_LT_U_IMM";
|
|
14517
|
+
Instruction[Instruction["SET_LT_S_IMM"] = 137] = "SET_LT_S_IMM";
|
|
14518
|
+
Instruction[Instruction["SHLO_L_IMM_32"] = 138] = "SHLO_L_IMM_32";
|
|
14519
|
+
Instruction[Instruction["SHLO_R_IMM_32"] = 139] = "SHLO_R_IMM_32";
|
|
14520
|
+
Instruction[Instruction["SHAR_R_IMM_32"] = 140] = "SHAR_R_IMM_32";
|
|
14521
|
+
Instruction[Instruction["NEG_ADD_IMM_32"] = 141] = "NEG_ADD_IMM_32";
|
|
14522
|
+
Instruction[Instruction["SET_GT_U_IMM"] = 142] = "SET_GT_U_IMM";
|
|
14523
|
+
Instruction[Instruction["SET_GT_S_IMM"] = 143] = "SET_GT_S_IMM";
|
|
14524
|
+
Instruction[Instruction["SHLO_L_IMM_ALT_32"] = 144] = "SHLO_L_IMM_ALT_32";
|
|
14525
|
+
Instruction[Instruction["SHLO_R_IMM_ALT_32"] = 145] = "SHLO_R_IMM_ALT_32";
|
|
14526
|
+
Instruction[Instruction["SHAR_R_IMM_ALT_32"] = 146] = "SHAR_R_IMM_ALT_32";
|
|
14527
|
+
Instruction[Instruction["CMOV_IZ_IMM"] = 147] = "CMOV_IZ_IMM";
|
|
14528
|
+
Instruction[Instruction["CMOV_NZ_IMM"] = 148] = "CMOV_NZ_IMM";
|
|
14529
|
+
Instruction[Instruction["ADD_IMM_64"] = 149] = "ADD_IMM_64";
|
|
14530
|
+
Instruction[Instruction["MUL_IMM_64"] = 150] = "MUL_IMM_64";
|
|
14531
|
+
Instruction[Instruction["SHLO_L_IMM_64"] = 151] = "SHLO_L_IMM_64";
|
|
14532
|
+
Instruction[Instruction["SHLO_R_IMM_64"] = 152] = "SHLO_R_IMM_64";
|
|
14533
|
+
Instruction[Instruction["SHAR_R_IMM_64"] = 153] = "SHAR_R_IMM_64";
|
|
14534
|
+
Instruction[Instruction["NEG_ADD_IMM_64"] = 154] = "NEG_ADD_IMM_64";
|
|
14535
|
+
Instruction[Instruction["SHLO_L_IMM_ALT_64"] = 155] = "SHLO_L_IMM_ALT_64";
|
|
14536
|
+
Instruction[Instruction["SHLO_R_IMM_ALT_64"] = 156] = "SHLO_R_IMM_ALT_64";
|
|
14537
|
+
Instruction[Instruction["SHAR_R_IMM_ALT_64"] = 157] = "SHAR_R_IMM_ALT_64";
|
|
14538
|
+
Instruction[Instruction["ROT_R_64_IMM"] = 158] = "ROT_R_64_IMM";
|
|
14539
|
+
Instruction[Instruction["ROT_R_64_IMM_ALT"] = 159] = "ROT_R_64_IMM_ALT";
|
|
14540
|
+
Instruction[Instruction["ROT_R_32_IMM"] = 160] = "ROT_R_32_IMM";
|
|
14541
|
+
Instruction[Instruction["ROT_R_32_IMM_ALT"] = 161] = "ROT_R_32_IMM_ALT";
|
|
14542
|
+
Instruction[Instruction["BRANCH_EQ"] = 170] = "BRANCH_EQ";
|
|
14543
|
+
Instruction[Instruction["BRANCH_NE"] = 171] = "BRANCH_NE";
|
|
14544
|
+
Instruction[Instruction["BRANCH_LT_U"] = 172] = "BRANCH_LT_U";
|
|
14545
|
+
Instruction[Instruction["BRANCH_LT_S"] = 173] = "BRANCH_LT_S";
|
|
14546
|
+
Instruction[Instruction["BRANCH_GE_U"] = 174] = "BRANCH_GE_U";
|
|
14547
|
+
Instruction[Instruction["BRANCH_GE_S"] = 175] = "BRANCH_GE_S";
|
|
14548
|
+
Instruction[Instruction["LOAD_IMM_JUMP_IND"] = 180] = "LOAD_IMM_JUMP_IND";
|
|
14549
|
+
Instruction[Instruction["ADD_32"] = 190] = "ADD_32";
|
|
14550
|
+
Instruction[Instruction["SUB_32"] = 191] = "SUB_32";
|
|
14551
|
+
Instruction[Instruction["MUL_32"] = 192] = "MUL_32";
|
|
14552
|
+
Instruction[Instruction["DIV_U_32"] = 193] = "DIV_U_32";
|
|
14553
|
+
Instruction[Instruction["DIV_S_32"] = 194] = "DIV_S_32";
|
|
14554
|
+
Instruction[Instruction["REM_U_32"] = 195] = "REM_U_32";
|
|
14555
|
+
Instruction[Instruction["REM_S_32"] = 196] = "REM_S_32";
|
|
14556
|
+
Instruction[Instruction["SHLO_L_32"] = 197] = "SHLO_L_32";
|
|
14557
|
+
Instruction[Instruction["SHLO_R_32"] = 198] = "SHLO_R_32";
|
|
14558
|
+
Instruction[Instruction["SHAR_R_32"] = 199] = "SHAR_R_32";
|
|
14559
|
+
Instruction[Instruction["ADD_64"] = 200] = "ADD_64";
|
|
14560
|
+
Instruction[Instruction["SUB_64"] = 201] = "SUB_64";
|
|
14561
|
+
Instruction[Instruction["MUL_64"] = 202] = "MUL_64";
|
|
14562
|
+
Instruction[Instruction["DIV_U_64"] = 203] = "DIV_U_64";
|
|
14563
|
+
Instruction[Instruction["DIV_S_64"] = 204] = "DIV_S_64";
|
|
14564
|
+
Instruction[Instruction["REM_U_64"] = 205] = "REM_U_64";
|
|
14565
|
+
Instruction[Instruction["REM_S_64"] = 206] = "REM_S_64";
|
|
14566
|
+
Instruction[Instruction["SHLO_L_64"] = 207] = "SHLO_L_64";
|
|
14567
|
+
Instruction[Instruction["SHLO_R_64"] = 208] = "SHLO_R_64";
|
|
14568
|
+
Instruction[Instruction["SHAR_R_64"] = 209] = "SHAR_R_64";
|
|
14569
|
+
Instruction[Instruction["AND"] = 210] = "AND";
|
|
14570
|
+
Instruction[Instruction["XOR"] = 211] = "XOR";
|
|
14571
|
+
Instruction[Instruction["OR"] = 212] = "OR";
|
|
14572
|
+
Instruction[Instruction["MUL_UPPER_S_S"] = 213] = "MUL_UPPER_S_S";
|
|
14573
|
+
Instruction[Instruction["MUL_UPPER_U_U"] = 214] = "MUL_UPPER_U_U";
|
|
14574
|
+
Instruction[Instruction["MUL_UPPER_S_U"] = 215] = "MUL_UPPER_S_U";
|
|
14575
|
+
Instruction[Instruction["SET_LT_U"] = 216] = "SET_LT_U";
|
|
14576
|
+
Instruction[Instruction["SET_LT_S"] = 217] = "SET_LT_S";
|
|
14577
|
+
Instruction[Instruction["CMOV_IZ"] = 218] = "CMOV_IZ";
|
|
14578
|
+
Instruction[Instruction["CMOV_NZ"] = 219] = "CMOV_NZ";
|
|
14579
|
+
Instruction[Instruction["ROT_L_64"] = 220] = "ROT_L_64";
|
|
14580
|
+
Instruction[Instruction["ROT_L_32"] = 221] = "ROT_L_32";
|
|
14581
|
+
Instruction[Instruction["ROT_R_64"] = 222] = "ROT_R_64";
|
|
14582
|
+
Instruction[Instruction["ROT_R_32"] = 223] = "ROT_R_32";
|
|
14583
|
+
Instruction[Instruction["AND_INV"] = 224] = "AND_INV";
|
|
14584
|
+
Instruction[Instruction["OR_INV"] = 225] = "OR_INV";
|
|
14585
|
+
Instruction[Instruction["XNOR"] = 226] = "XNOR";
|
|
14586
|
+
Instruction[Instruction["MAX"] = 227] = "MAX";
|
|
14587
|
+
Instruction[Instruction["MAX_U"] = 228] = "MAX_U";
|
|
14588
|
+
Instruction[Instruction["MIN"] = 229] = "MIN";
|
|
14589
|
+
Instruction[Instruction["MIN_U"] = 230] = "MIN_U";
|
|
14590
|
+
})(Instruction || (Instruction = {}));
|
|
14591
|
+
const HIGHEST_INSTRUCTION_NUMBER = Instruction.MIN_U;
|
|
14223
14592
|
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
|
|
14230
|
-
|
|
14231
|
-
|
|
14232
|
-
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
|
|
14239
|
-
|
|
14240
|
-
|
|
14241
|
-
|
|
14242
|
-
|
|
14243
|
-
|
|
14244
|
-
|
|
14245
|
-
|
|
14246
|
-
|
|
14247
|
-
|
|
14248
|
-
|
|
14249
|
-
|
|
14250
|
-
|
|
14251
|
-
|
|
14252
|
-
|
|
14253
|
-
|
|
14593
|
+
const instructionArgumentTypeMap = (() => {
|
|
14594
|
+
const instructionArgumentTypeMap = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
|
|
14595
|
+
instructionArgumentTypeMap[Instruction.TRAP] = ArgumentType.NO_ARGUMENTS;
|
|
14596
|
+
instructionArgumentTypeMap[Instruction.FALLTHROUGH] = ArgumentType.NO_ARGUMENTS;
|
|
14597
|
+
instructionArgumentTypeMap[Instruction.ECALLI] = ArgumentType.ONE_IMMEDIATE;
|
|
14598
|
+
instructionArgumentTypeMap[Instruction.LOAD_IMM_64] = ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE;
|
|
14599
|
+
instructionArgumentTypeMap[Instruction.STORE_IMM_U8] = ArgumentType.TWO_IMMEDIATES;
|
|
14600
|
+
instructionArgumentTypeMap[Instruction.STORE_IMM_U16] = ArgumentType.TWO_IMMEDIATES;
|
|
14601
|
+
instructionArgumentTypeMap[Instruction.STORE_IMM_U32] = ArgumentType.TWO_IMMEDIATES;
|
|
14602
|
+
instructionArgumentTypeMap[Instruction.STORE_IMM_U64] = ArgumentType.TWO_IMMEDIATES;
|
|
14603
|
+
instructionArgumentTypeMap[Instruction.JUMP] = ArgumentType.ONE_OFFSET;
|
|
14604
|
+
instructionArgumentTypeMap[Instruction.JUMP_IND] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14605
|
+
instructionArgumentTypeMap[Instruction.LOAD_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14606
|
+
instructionArgumentTypeMap[Instruction.LOAD_U8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14607
|
+
instructionArgumentTypeMap[Instruction.LOAD_I8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14608
|
+
instructionArgumentTypeMap[Instruction.LOAD_U16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14609
|
+
instructionArgumentTypeMap[Instruction.LOAD_I16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14610
|
+
instructionArgumentTypeMap[Instruction.LOAD_U32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14611
|
+
instructionArgumentTypeMap[Instruction.LOAD_I32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14612
|
+
instructionArgumentTypeMap[Instruction.LOAD_U64] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14613
|
+
instructionArgumentTypeMap[Instruction.STORE_U8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14614
|
+
instructionArgumentTypeMap[Instruction.STORE_U16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14615
|
+
instructionArgumentTypeMap[Instruction.STORE_U32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14616
|
+
instructionArgumentTypeMap[Instruction.STORE_U64] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
|
|
14617
|
+
instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U8] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
|
|
14618
|
+
instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U16] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
|
|
14619
|
+
instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U32] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
|
|
14620
|
+
instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U64] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
|
|
14621
|
+
instructionArgumentTypeMap[Instruction.LOAD_IMM_JUMP] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14622
|
+
instructionArgumentTypeMap[Instruction.BRANCH_EQ_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14623
|
+
instructionArgumentTypeMap[Instruction.BRANCH_NE_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14624
|
+
instructionArgumentTypeMap[Instruction.BRANCH_LT_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14625
|
+
instructionArgumentTypeMap[Instruction.BRANCH_LE_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14626
|
+
instructionArgumentTypeMap[Instruction.BRANCH_GE_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14627
|
+
instructionArgumentTypeMap[Instruction.BRANCH_GT_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14628
|
+
instructionArgumentTypeMap[Instruction.BRANCH_LT_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14629
|
+
instructionArgumentTypeMap[Instruction.BRANCH_LE_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14630
|
+
instructionArgumentTypeMap[Instruction.BRANCH_GE_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14631
|
+
instructionArgumentTypeMap[Instruction.BRANCH_GT_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
|
|
14632
|
+
instructionArgumentTypeMap[Instruction.MOVE_REG] = ArgumentType.TWO_REGISTERS;
|
|
14633
|
+
instructionArgumentTypeMap[Instruction.SBRK] = ArgumentType.TWO_REGISTERS;
|
|
14634
|
+
instructionArgumentTypeMap[Instruction.COUNT_SET_BITS_64] = ArgumentType.TWO_REGISTERS;
|
|
14635
|
+
instructionArgumentTypeMap[Instruction.COUNT_SET_BITS_32] = ArgumentType.TWO_REGISTERS;
|
|
14636
|
+
instructionArgumentTypeMap[Instruction.LEADING_ZERO_BITS_64] = ArgumentType.TWO_REGISTERS;
|
|
14637
|
+
instructionArgumentTypeMap[Instruction.LEADING_ZERO_BITS_32] = ArgumentType.TWO_REGISTERS;
|
|
14638
|
+
instructionArgumentTypeMap[Instruction.TRAILING_ZERO_BITS_64] = ArgumentType.TWO_REGISTERS;
|
|
14639
|
+
instructionArgumentTypeMap[Instruction.TRAILING_ZERO_BITS_32] = ArgumentType.TWO_REGISTERS;
|
|
14640
|
+
instructionArgumentTypeMap[Instruction.SIGN_EXTEND_8] = ArgumentType.TWO_REGISTERS;
|
|
14641
|
+
instructionArgumentTypeMap[Instruction.SIGN_EXTEND_16] = ArgumentType.TWO_REGISTERS;
|
|
14642
|
+
instructionArgumentTypeMap[Instruction.ZERO_EXTEND_16] = ArgumentType.TWO_REGISTERS;
|
|
14643
|
+
instructionArgumentTypeMap[Instruction.REVERSE_BYTES] = ArgumentType.TWO_REGISTERS;
|
|
14644
|
+
instructionArgumentTypeMap[Instruction.STORE_IND_U8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14645
|
+
instructionArgumentTypeMap[Instruction.STORE_IND_U16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14646
|
+
instructionArgumentTypeMap[Instruction.STORE_IND_U32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14647
|
+
instructionArgumentTypeMap[Instruction.STORE_IND_U64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14648
|
+
instructionArgumentTypeMap[Instruction.LOAD_IND_U8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14649
|
+
instructionArgumentTypeMap[Instruction.LOAD_IND_I8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14650
|
+
instructionArgumentTypeMap[Instruction.LOAD_IND_U16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14651
|
+
instructionArgumentTypeMap[Instruction.LOAD_IND_I16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14652
|
+
instructionArgumentTypeMap[Instruction.LOAD_IND_U32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14653
|
+
instructionArgumentTypeMap[Instruction.LOAD_IND_I32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14654
|
+
instructionArgumentTypeMap[Instruction.LOAD_IND_U64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14655
|
+
instructionArgumentTypeMap[Instruction.ADD_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14656
|
+
instructionArgumentTypeMap[Instruction.ADD_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14657
|
+
instructionArgumentTypeMap[Instruction.AND_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14658
|
+
instructionArgumentTypeMap[Instruction.XOR_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14659
|
+
instructionArgumentTypeMap[Instruction.OR_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14660
|
+
instructionArgumentTypeMap[Instruction.MUL_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14661
|
+
instructionArgumentTypeMap[Instruction.MUL_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14662
|
+
instructionArgumentTypeMap[Instruction.SET_LT_U_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14663
|
+
instructionArgumentTypeMap[Instruction.SET_LT_S_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14664
|
+
instructionArgumentTypeMap[Instruction.SHLO_L_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14665
|
+
instructionArgumentTypeMap[Instruction.SHLO_R_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14666
|
+
instructionArgumentTypeMap[Instruction.SHAR_R_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14667
|
+
instructionArgumentTypeMap[Instruction.NEG_ADD_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14668
|
+
instructionArgumentTypeMap[Instruction.SHLO_L_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14669
|
+
instructionArgumentTypeMap[Instruction.SHLO_R_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14670
|
+
instructionArgumentTypeMap[Instruction.SHAR_R_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14671
|
+
instructionArgumentTypeMap[Instruction.NEG_ADD_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14672
|
+
instructionArgumentTypeMap[Instruction.SET_GT_U_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14673
|
+
instructionArgumentTypeMap[Instruction.SET_GT_S_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14674
|
+
instructionArgumentTypeMap[Instruction.SHLO_L_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14675
|
+
instructionArgumentTypeMap[Instruction.SHLO_R_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14676
|
+
instructionArgumentTypeMap[Instruction.SHAR_R_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14677
|
+
instructionArgumentTypeMap[Instruction.SHLO_L_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14678
|
+
instructionArgumentTypeMap[Instruction.SHLO_R_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14679
|
+
instructionArgumentTypeMap[Instruction.SHAR_R_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14680
|
+
instructionArgumentTypeMap[Instruction.CMOV_IZ_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14681
|
+
instructionArgumentTypeMap[Instruction.CMOV_NZ_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14682
|
+
instructionArgumentTypeMap[Instruction.ROT_R_64_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14683
|
+
instructionArgumentTypeMap[Instruction.ROT_R_64_IMM_ALT] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14684
|
+
instructionArgumentTypeMap[Instruction.ROT_R_32_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14685
|
+
instructionArgumentTypeMap[Instruction.ROT_R_32_IMM_ALT] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
|
|
14686
|
+
instructionArgumentTypeMap[Instruction.BRANCH_EQ] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
14687
|
+
instructionArgumentTypeMap[Instruction.BRANCH_NE] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
14688
|
+
instructionArgumentTypeMap[Instruction.BRANCH_LT_U] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
14689
|
+
instructionArgumentTypeMap[Instruction.BRANCH_LT_S] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
14690
|
+
instructionArgumentTypeMap[Instruction.BRANCH_GE_U] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
14691
|
+
instructionArgumentTypeMap[Instruction.BRANCH_GE_S] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
|
|
14692
|
+
instructionArgumentTypeMap[Instruction.LOAD_IMM_JUMP_IND] = ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES;
|
|
14693
|
+
instructionArgumentTypeMap[Instruction.ADD_32] = ArgumentType.THREE_REGISTERS;
|
|
14694
|
+
instructionArgumentTypeMap[Instruction.ADD_64] = ArgumentType.THREE_REGISTERS;
|
|
14695
|
+
instructionArgumentTypeMap[Instruction.SUB_32] = ArgumentType.THREE_REGISTERS;
|
|
14696
|
+
instructionArgumentTypeMap[Instruction.SUB_64] = ArgumentType.THREE_REGISTERS;
|
|
14697
|
+
instructionArgumentTypeMap[Instruction.AND] = ArgumentType.THREE_REGISTERS;
|
|
14698
|
+
instructionArgumentTypeMap[Instruction.XOR] = ArgumentType.THREE_REGISTERS;
|
|
14699
|
+
instructionArgumentTypeMap[Instruction.OR] = ArgumentType.THREE_REGISTERS;
|
|
14700
|
+
instructionArgumentTypeMap[Instruction.MUL_32] = ArgumentType.THREE_REGISTERS;
|
|
14701
|
+
instructionArgumentTypeMap[Instruction.MUL_64] = ArgumentType.THREE_REGISTERS;
|
|
14702
|
+
instructionArgumentTypeMap[Instruction.MUL_UPPER_S_S] = ArgumentType.THREE_REGISTERS;
|
|
14703
|
+
instructionArgumentTypeMap[Instruction.MUL_UPPER_U_U] = ArgumentType.THREE_REGISTERS;
|
|
14704
|
+
instructionArgumentTypeMap[Instruction.MUL_UPPER_S_U] = ArgumentType.THREE_REGISTERS;
|
|
14705
|
+
instructionArgumentTypeMap[Instruction.DIV_U_32] = ArgumentType.THREE_REGISTERS;
|
|
14706
|
+
instructionArgumentTypeMap[Instruction.DIV_S_32] = ArgumentType.THREE_REGISTERS;
|
|
14707
|
+
instructionArgumentTypeMap[Instruction.REM_U_32] = ArgumentType.THREE_REGISTERS;
|
|
14708
|
+
instructionArgumentTypeMap[Instruction.REM_S_32] = ArgumentType.THREE_REGISTERS;
|
|
14709
|
+
instructionArgumentTypeMap[Instruction.DIV_U_64] = ArgumentType.THREE_REGISTERS;
|
|
14710
|
+
instructionArgumentTypeMap[Instruction.DIV_S_64] = ArgumentType.THREE_REGISTERS;
|
|
14711
|
+
instructionArgumentTypeMap[Instruction.REM_U_64] = ArgumentType.THREE_REGISTERS;
|
|
14712
|
+
instructionArgumentTypeMap[Instruction.REM_S_64] = ArgumentType.THREE_REGISTERS;
|
|
14713
|
+
instructionArgumentTypeMap[Instruction.SET_LT_U] = ArgumentType.THREE_REGISTERS;
|
|
14714
|
+
instructionArgumentTypeMap[Instruction.SET_LT_S] = ArgumentType.THREE_REGISTERS;
|
|
14715
|
+
instructionArgumentTypeMap[Instruction.SHLO_L_32] = ArgumentType.THREE_REGISTERS;
|
|
14716
|
+
instructionArgumentTypeMap[Instruction.SHLO_R_32] = ArgumentType.THREE_REGISTERS;
|
|
14717
|
+
instructionArgumentTypeMap[Instruction.SHAR_R_32] = ArgumentType.THREE_REGISTERS;
|
|
14718
|
+
instructionArgumentTypeMap[Instruction.SHLO_L_64] = ArgumentType.THREE_REGISTERS;
|
|
14719
|
+
instructionArgumentTypeMap[Instruction.SHLO_R_64] = ArgumentType.THREE_REGISTERS;
|
|
14720
|
+
instructionArgumentTypeMap[Instruction.SHAR_R_64] = ArgumentType.THREE_REGISTERS;
|
|
14721
|
+
instructionArgumentTypeMap[Instruction.CMOV_IZ] = ArgumentType.THREE_REGISTERS;
|
|
14722
|
+
instructionArgumentTypeMap[Instruction.CMOV_NZ] = ArgumentType.THREE_REGISTERS;
|
|
14723
|
+
instructionArgumentTypeMap[Instruction.ROT_L_64] = ArgumentType.THREE_REGISTERS;
|
|
14724
|
+
instructionArgumentTypeMap[Instruction.ROT_L_32] = ArgumentType.THREE_REGISTERS;
|
|
14725
|
+
instructionArgumentTypeMap[Instruction.ROT_R_64] = ArgumentType.THREE_REGISTERS;
|
|
14726
|
+
instructionArgumentTypeMap[Instruction.ROT_R_32] = ArgumentType.THREE_REGISTERS;
|
|
14727
|
+
instructionArgumentTypeMap[Instruction.AND_INV] = ArgumentType.THREE_REGISTERS;
|
|
14728
|
+
instructionArgumentTypeMap[Instruction.OR_INV] = ArgumentType.THREE_REGISTERS;
|
|
14729
|
+
instructionArgumentTypeMap[Instruction.XNOR] = ArgumentType.THREE_REGISTERS;
|
|
14730
|
+
instructionArgumentTypeMap[Instruction.MAX] = ArgumentType.THREE_REGISTERS;
|
|
14731
|
+
instructionArgumentTypeMap[Instruction.MAX_U] = ArgumentType.THREE_REGISTERS;
|
|
14732
|
+
instructionArgumentTypeMap[Instruction.MIN] = ArgumentType.THREE_REGISTERS;
|
|
14733
|
+
instructionArgumentTypeMap[Instruction.MIN_U] = ArgumentType.THREE_REGISTERS;
|
|
14734
|
+
return instructionArgumentTypeMap;
|
|
14735
|
+
})();
|
|
14254
14736
|
|
|
14255
|
-
|
|
14256
|
-
|
|
14257
|
-
|
|
14258
|
-
|
|
14259
|
-
|
|
14260
|
-
|
|
14261
|
-
|
|
14262
|
-
|
|
14263
|
-
|
|
14264
|
-
|
|
14265
|
-
|
|
14266
|
-
|
|
14267
|
-
|
|
14268
|
-
|
|
14269
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
|
|
14274
|
-
|
|
14275
|
-
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14737
|
+
const instructionsWithoutArgs = [
|
|
14738
|
+
[Instruction.TRAP, 1],
|
|
14739
|
+
[Instruction.FALLTHROUGH, 1],
|
|
14740
|
+
];
|
|
14741
|
+
const instructionsWithOneImmediate = [[Instruction.ECALLI, 1]];
|
|
14742
|
+
const instructionsWithOneRegisterAndOneExtendedWidthImmediate = [[Instruction.LOAD_IMM_64, 1]];
|
|
14743
|
+
const instructionsWithTwoImmediates = [
|
|
14744
|
+
[Instruction.STORE_IMM_U8, 1],
|
|
14745
|
+
[Instruction.STORE_IMM_U16, 1],
|
|
14746
|
+
[Instruction.STORE_IMM_U32, 1],
|
|
14747
|
+
[Instruction.STORE_IMM_U64, 1],
|
|
14748
|
+
];
|
|
14749
|
+
const instructionsWithOneOffset = [[Instruction.JUMP, 1]];
|
|
14750
|
+
const instructionsWithOneRegisterAndOneImmediate = [
|
|
14751
|
+
[Instruction.JUMP_IND, 1],
|
|
14752
|
+
[Instruction.LOAD_IMM, 1],
|
|
14753
|
+
[Instruction.LOAD_U8, 1],
|
|
14754
|
+
[Instruction.LOAD_I8, 1],
|
|
14755
|
+
[Instruction.LOAD_U16, 1],
|
|
14756
|
+
[Instruction.LOAD_I16, 1],
|
|
14757
|
+
[Instruction.LOAD_U32, 1],
|
|
14758
|
+
[Instruction.LOAD_I32, 1],
|
|
14759
|
+
[Instruction.LOAD_U64, 1],
|
|
14760
|
+
[Instruction.STORE_U8, 1],
|
|
14761
|
+
[Instruction.STORE_U16, 1],
|
|
14762
|
+
[Instruction.STORE_U32, 1],
|
|
14763
|
+
[Instruction.STORE_U64, 1],
|
|
14764
|
+
];
|
|
14765
|
+
const instructionsWithOneRegisterAndTwoImmediate = [
|
|
14766
|
+
[Instruction.STORE_IMM_IND_U8, 1],
|
|
14767
|
+
[Instruction.STORE_IMM_IND_U16, 1],
|
|
14768
|
+
[Instruction.STORE_IMM_IND_U32, 1],
|
|
14769
|
+
[Instruction.STORE_IMM_IND_U64, 1],
|
|
14770
|
+
];
|
|
14771
|
+
const instructionsWithOneRegisterOneImmediateAndOneOffset = [
|
|
14772
|
+
[Instruction.LOAD_IMM_JUMP, 1],
|
|
14773
|
+
[Instruction.BRANCH_EQ_IMM, 1],
|
|
14774
|
+
[Instruction.BRANCH_NE_IMM, 1],
|
|
14775
|
+
[Instruction.BRANCH_LT_U_IMM, 1],
|
|
14776
|
+
[Instruction.BRANCH_LE_U_IMM, 1],
|
|
14777
|
+
[Instruction.BRANCH_GE_U_IMM, 1],
|
|
14778
|
+
[Instruction.BRANCH_GT_U_IMM, 1],
|
|
14779
|
+
[Instruction.BRANCH_LT_S_IMM, 1],
|
|
14780
|
+
[Instruction.BRANCH_LE_S_IMM, 1],
|
|
14781
|
+
[Instruction.BRANCH_GE_S_IMM, 1],
|
|
14782
|
+
[Instruction.BRANCH_GT_S_IMM, 1],
|
|
14783
|
+
];
|
|
14784
|
+
const instructionsWithTwoRegisters = [
|
|
14785
|
+
[Instruction.MOVE_REG, 1],
|
|
14786
|
+
[Instruction.SBRK, 1],
|
|
14787
|
+
[Instruction.COUNT_SET_BITS_64, 1],
|
|
14788
|
+
[Instruction.COUNT_SET_BITS_32, 1],
|
|
14789
|
+
[Instruction.LEADING_ZERO_BITS_64, 1],
|
|
14790
|
+
[Instruction.LEADING_ZERO_BITS_32, 1],
|
|
14791
|
+
[Instruction.TRAILING_ZERO_BITS_64, 1],
|
|
14792
|
+
[Instruction.TRAILING_ZERO_BITS_32, 1],
|
|
14793
|
+
[Instruction.SIGN_EXTEND_8, 1],
|
|
14794
|
+
[Instruction.SIGN_EXTEND_16, 1],
|
|
14795
|
+
[Instruction.ZERO_EXTEND_16, 1],
|
|
14796
|
+
[Instruction.REVERSE_BYTES, 1],
|
|
14797
|
+
];
|
|
14798
|
+
const instructionsWithTwoRegistersAndOneImmediate = [
|
|
14799
|
+
[Instruction.STORE_IND_U8, 1],
|
|
14800
|
+
[Instruction.STORE_IND_U16, 1],
|
|
14801
|
+
[Instruction.STORE_IND_U32, 1],
|
|
14802
|
+
[Instruction.STORE_IND_U64, 1],
|
|
14803
|
+
[Instruction.LOAD_IND_U8, 1],
|
|
14804
|
+
[Instruction.LOAD_IND_I8, 1],
|
|
14805
|
+
[Instruction.LOAD_IND_U16, 1],
|
|
14806
|
+
[Instruction.LOAD_IND_I16, 1],
|
|
14807
|
+
[Instruction.LOAD_IND_U32, 1],
|
|
14808
|
+
[Instruction.LOAD_IND_I32, 1],
|
|
14809
|
+
[Instruction.LOAD_IND_U64, 1],
|
|
14810
|
+
[Instruction.ADD_IMM_32, 1],
|
|
14811
|
+
[Instruction.AND_IMM, 1],
|
|
14812
|
+
[Instruction.XOR_IMM, 1],
|
|
14813
|
+
[Instruction.OR_IMM, 1],
|
|
14814
|
+
[Instruction.MUL_IMM_32, 1],
|
|
14815
|
+
[Instruction.SET_LT_U_IMM, 1],
|
|
14816
|
+
[Instruction.SET_LT_S_IMM, 1],
|
|
14817
|
+
[Instruction.SHLO_L_IMM_32, 1],
|
|
14818
|
+
[Instruction.SHLO_R_IMM_32, 1],
|
|
14819
|
+
[Instruction.SHAR_R_IMM_32, 1],
|
|
14820
|
+
[Instruction.NEG_ADD_IMM_32, 1],
|
|
14821
|
+
[Instruction.SET_GT_U_IMM, 1],
|
|
14822
|
+
[Instruction.SET_GT_S_IMM, 1],
|
|
14823
|
+
[Instruction.SHLO_L_IMM_ALT_32, 1],
|
|
14824
|
+
[Instruction.SHLO_R_IMM_ALT_32, 1],
|
|
14825
|
+
[Instruction.SHAR_R_IMM_ALT_32, 1],
|
|
14826
|
+
[Instruction.CMOV_IZ_IMM, 1],
|
|
14827
|
+
[Instruction.CMOV_NZ_IMM, 1],
|
|
14828
|
+
[Instruction.ADD_IMM_64, 1],
|
|
14829
|
+
[Instruction.MUL_IMM_64, 1],
|
|
14830
|
+
[Instruction.SHLO_L_IMM_64, 1],
|
|
14831
|
+
[Instruction.SHLO_R_IMM_64, 1],
|
|
14832
|
+
[Instruction.SHAR_R_IMM_64, 1],
|
|
14833
|
+
[Instruction.NEG_ADD_IMM_64, 1],
|
|
14834
|
+
[Instruction.SHLO_L_IMM_ALT_64, 1],
|
|
14835
|
+
[Instruction.SHLO_R_IMM_ALT_64, 1],
|
|
14836
|
+
[Instruction.SHAR_R_IMM_ALT_64, 1],
|
|
14837
|
+
[Instruction.ROT_R_64_IMM, 1],
|
|
14838
|
+
[Instruction.ROT_R_64_IMM_ALT, 1],
|
|
14839
|
+
[Instruction.ROT_R_32_IMM, 1],
|
|
14840
|
+
[Instruction.ROT_R_32_IMM_ALT, 1],
|
|
14841
|
+
];
|
|
14842
|
+
const instructionsWithTwoRegistersAndOneOffset = [
|
|
14843
|
+
[Instruction.BRANCH_EQ, 1],
|
|
14844
|
+
[Instruction.BRANCH_NE, 1],
|
|
14845
|
+
[Instruction.BRANCH_LT_U, 1],
|
|
14846
|
+
[Instruction.BRANCH_LT_S, 1],
|
|
14847
|
+
[Instruction.BRANCH_GE_U, 1],
|
|
14848
|
+
[Instruction.BRANCH_GE_S, 1],
|
|
14849
|
+
];
|
|
14850
|
+
const instructionWithTwoRegistersAndTwoImmediates = [[Instruction.LOAD_IMM_JUMP_IND, 1]];
|
|
14851
|
+
const instructionsWithThreeRegisters = [
|
|
14852
|
+
[Instruction.ADD_32, 1],
|
|
14853
|
+
[Instruction.SUB_32, 1],
|
|
14854
|
+
[Instruction.MUL_32, 1],
|
|
14855
|
+
[Instruction.DIV_U_32, 1],
|
|
14856
|
+
[Instruction.DIV_S_32, 1],
|
|
14857
|
+
[Instruction.REM_U_32, 1],
|
|
14858
|
+
[Instruction.REM_S_32, 1],
|
|
14859
|
+
[Instruction.SHLO_L_32, 1],
|
|
14860
|
+
[Instruction.SHLO_R_32, 1],
|
|
14861
|
+
[Instruction.SHAR_R_32, 1],
|
|
14862
|
+
[Instruction.ADD_64, 1],
|
|
14863
|
+
[Instruction.SUB_64, 1],
|
|
14864
|
+
[Instruction.MUL_64, 1],
|
|
14865
|
+
[Instruction.DIV_U_64, 1],
|
|
14866
|
+
[Instruction.DIV_S_64, 1],
|
|
14867
|
+
[Instruction.REM_U_64, 1],
|
|
14868
|
+
[Instruction.REM_S_64, 1],
|
|
14869
|
+
[Instruction.SHLO_L_64, 1],
|
|
14870
|
+
[Instruction.SHLO_R_64, 1],
|
|
14871
|
+
[Instruction.SHAR_R_64, 1],
|
|
14872
|
+
[Instruction.AND, 1],
|
|
14873
|
+
[Instruction.XOR, 1],
|
|
14874
|
+
[Instruction.OR, 1],
|
|
14875
|
+
[Instruction.MUL_UPPER_S_S, 1],
|
|
14876
|
+
[Instruction.MUL_UPPER_U_U, 1],
|
|
14877
|
+
[Instruction.MUL_UPPER_S_U, 1],
|
|
14878
|
+
[Instruction.SET_LT_U, 1],
|
|
14879
|
+
[Instruction.SET_LT_S, 1],
|
|
14880
|
+
[Instruction.CMOV_IZ, 1],
|
|
14881
|
+
[Instruction.CMOV_NZ, 1],
|
|
14882
|
+
[Instruction.ROT_L_64, 1],
|
|
14883
|
+
[Instruction.ROT_L_32, 1],
|
|
14884
|
+
[Instruction.ROT_R_64, 1],
|
|
14885
|
+
[Instruction.ROT_R_32, 1],
|
|
14886
|
+
[Instruction.AND_INV, 1],
|
|
14887
|
+
[Instruction.OR_INV, 1],
|
|
14888
|
+
[Instruction.XNOR, 1],
|
|
14889
|
+
[Instruction.MAX, 1],
|
|
14890
|
+
[Instruction.MAX_U, 1],
|
|
14891
|
+
[Instruction.MIN, 1],
|
|
14892
|
+
[Instruction.MIN_U, 1],
|
|
14893
|
+
];
|
|
14894
|
+
const instructions = [
|
|
14895
|
+
...instructionsWithoutArgs,
|
|
14896
|
+
...instructionsWithOneImmediate,
|
|
14897
|
+
...instructionsWithOneRegisterAndOneExtendedWidthImmediate,
|
|
14898
|
+
...instructionsWithTwoImmediates,
|
|
14899
|
+
...instructionsWithOneOffset,
|
|
14900
|
+
...instructionsWithOneRegisterAndOneImmediate,
|
|
14901
|
+
...instructionsWithOneRegisterAndTwoImmediate,
|
|
14902
|
+
...instructionsWithOneRegisterOneImmediateAndOneOffset,
|
|
14903
|
+
...instructionsWithTwoRegisters,
|
|
14904
|
+
...instructionsWithTwoRegistersAndOneImmediate,
|
|
14905
|
+
...instructionsWithTwoRegistersAndOneOffset,
|
|
14906
|
+
...instructionWithTwoRegistersAndTwoImmediates,
|
|
14907
|
+
...instructionsWithThreeRegisters,
|
|
14908
|
+
];
|
|
14909
|
+
const createOpCodeEntry = ([byte, gas]) => [byte, { gas: tryAsSmallGas(gas) }];
|
|
14910
|
+
const byteToOpCodeMap = instructions.reduce((acc, instruction) => {
|
|
14911
|
+
const [byte, opCode] = createOpCodeEntry(instruction);
|
|
14912
|
+
acc[byte] = opCode;
|
|
14913
|
+
return acc;
|
|
14914
|
+
}, {});
|
|
14915
|
+
function assemblify(program, mask) {
|
|
14916
|
+
return program.reduce((acc, byte, index) => {
|
|
14917
|
+
if (mask.isInstruction(index)) {
|
|
14918
|
+
acc.push([Instruction[byte]]);
|
|
14283
14919
|
}
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
}
|
|
14287
|
-
setData(pageIndex, data) {
|
|
14288
|
-
if (this.buffer.byteLength < pageIndex + data.length && this.buffer.byteLength < PAGE_SIZE$1) {
|
|
14289
|
-
const newLength = Math.min(PAGE_SIZE$1, Math.max(MIN_ALLOCATION_LENGTH, pageIndex + data.length));
|
|
14290
|
-
this.buffer.resize(newLength);
|
|
14920
|
+
else {
|
|
14921
|
+
acc[acc.length - 1].push(byte);
|
|
14291
14922
|
}
|
|
14292
|
-
|
|
14293
|
-
}
|
|
14294
|
-
isWriteable() {
|
|
14295
|
-
return true;
|
|
14296
|
-
}
|
|
14297
|
-
getPageDump() {
|
|
14298
|
-
return this.view;
|
|
14299
|
-
}
|
|
14923
|
+
return acc;
|
|
14924
|
+
}, []);
|
|
14300
14925
|
}
|
|
14301
14926
|
|
|
14302
|
-
|
|
14303
|
-
(
|
|
14304
|
-
|
|
14305
|
-
|
|
14306
|
-
|
|
14307
|
-
|
|
14308
|
-
|
|
14309
|
-
|
|
14310
|
-
|
|
14311
|
-
|
|
14312
|
-
|
|
14313
|
-
|
|
14314
|
-
|
|
14315
|
-
|
|
14316
|
-
|
|
14317
|
-
|
|
14318
|
-
|
|
14319
|
-
|
|
14320
|
-
|
|
14321
|
-
|
|
14322
|
-
|
|
14323
|
-
|
|
14324
|
-
|
|
14325
|
-
|
|
14326
|
-
|
|
14327
|
-
|
|
14328
|
-
|
|
14329
|
-
|
|
14330
|
-
|
|
14331
|
-
|
|
14332
|
-
|
|
14333
|
-
|
|
14334
|
-
|
|
14335
|
-
|
|
14336
|
-
|
|
14337
|
-
|
|
14338
|
-
|
|
14339
|
-
|
|
14340
|
-
if (pagesResult.isError) {
|
|
14341
|
-
return Result$1.error(pagesResult.error, pagesResult.details);
|
|
14342
|
-
}
|
|
14343
|
-
const pages = pagesResult.ok;
|
|
14344
|
-
let currentPosition = address;
|
|
14345
|
-
let bytesLeft = bytes.length;
|
|
14346
|
-
for (const page of pages) {
|
|
14347
|
-
const pageStartIndex = tryAsPageIndex(currentPosition % PAGE_SIZE$1);
|
|
14348
|
-
const bytesToWrite = Math.min(PAGE_SIZE$1 - pageStartIndex, bytesLeft);
|
|
14349
|
-
const sourceStartIndex = currentPosition - address;
|
|
14350
|
-
const source = bytes.subarray(sourceStartIndex, sourceStartIndex + bytesToWrite);
|
|
14351
|
-
page.storeFrom(pageStartIndex, source);
|
|
14352
|
-
currentPosition += bytesToWrite;
|
|
14353
|
-
bytesLeft -= bytesToWrite;
|
|
14354
|
-
}
|
|
14355
|
-
return Result$1.ok(OK);
|
|
14356
|
-
}
|
|
14357
|
-
getPages(startAddress, length, accessType) {
|
|
14358
|
-
if (length === 0) {
|
|
14359
|
-
return Result$1.ok([]);
|
|
14360
|
-
}
|
|
14361
|
-
const memoryRange = MemoryRange.fromStartAndLength(startAddress, length);
|
|
14362
|
-
const pageRange = PageRange.fromMemoryRange(memoryRange);
|
|
14363
|
-
const pages = [];
|
|
14364
|
-
for (const pageNumber of pageRange) {
|
|
14365
|
-
if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
|
|
14366
|
-
return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to access reserved page ${pageNumber}`);
|
|
14367
|
-
}
|
|
14368
|
-
const page = this.memory.get(pageNumber);
|
|
14369
|
-
if (page === undefined) {
|
|
14370
|
-
return Result$1.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
|
|
14371
|
-
}
|
|
14372
|
-
if (accessType === AccessType.WRITE && !page.isWriteable()) {
|
|
14373
|
-
return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to write to read-only page ${pageNumber}`);
|
|
14927
|
+
const terminationInstructions = (() => {
|
|
14928
|
+
const terminationInstructions = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
|
|
14929
|
+
terminationInstructions.fill(false);
|
|
14930
|
+
terminationInstructions[Instruction.TRAP] = true;
|
|
14931
|
+
terminationInstructions[Instruction.FALLTHROUGH] = true;
|
|
14932
|
+
terminationInstructions[Instruction.JUMP] = true;
|
|
14933
|
+
terminationInstructions[Instruction.JUMP_IND] = true;
|
|
14934
|
+
terminationInstructions[Instruction.LOAD_IMM_JUMP] = true;
|
|
14935
|
+
terminationInstructions[Instruction.LOAD_IMM_JUMP_IND] = true;
|
|
14936
|
+
terminationInstructions[Instruction.BRANCH_EQ] = true;
|
|
14937
|
+
terminationInstructions[Instruction.BRANCH_NE] = true;
|
|
14938
|
+
terminationInstructions[Instruction.BRANCH_GE_U] = true;
|
|
14939
|
+
terminationInstructions[Instruction.BRANCH_GE_S] = true;
|
|
14940
|
+
terminationInstructions[Instruction.BRANCH_LT_U] = true;
|
|
14941
|
+
terminationInstructions[Instruction.BRANCH_LT_S] = true;
|
|
14942
|
+
terminationInstructions[Instruction.BRANCH_EQ_IMM] = true;
|
|
14943
|
+
terminationInstructions[Instruction.BRANCH_NE_IMM] = true;
|
|
14944
|
+
terminationInstructions[Instruction.BRANCH_LT_U_IMM] = true;
|
|
14945
|
+
terminationInstructions[Instruction.BRANCH_LT_S_IMM] = true;
|
|
14946
|
+
terminationInstructions[Instruction.BRANCH_LE_U_IMM] = true;
|
|
14947
|
+
terminationInstructions[Instruction.BRANCH_LE_S_IMM] = true;
|
|
14948
|
+
terminationInstructions[Instruction.BRANCH_GE_U_IMM] = true;
|
|
14949
|
+
terminationInstructions[Instruction.BRANCH_GE_S_IMM] = true;
|
|
14950
|
+
terminationInstructions[Instruction.BRANCH_GT_U_IMM] = true;
|
|
14951
|
+
terminationInstructions[Instruction.BRANCH_GT_S_IMM] = true;
|
|
14952
|
+
return terminationInstructions;
|
|
14953
|
+
})();
|
|
14954
|
+
|
|
14955
|
+
class BasicBlocks {
|
|
14956
|
+
basicBlocks = new Set();
|
|
14957
|
+
reset(code, mask) {
|
|
14958
|
+
this.basicBlocks.clear();
|
|
14959
|
+
this.basicBlocks.add(0);
|
|
14960
|
+
const codeLength = code.length;
|
|
14961
|
+
const isBasicBlockTermination = (index) => mask.isInstruction(index) && terminationInstructions[code[index]];
|
|
14962
|
+
for (let i = 0; i < codeLength; i++) {
|
|
14963
|
+
if (mask.isInstruction(i) && isBasicBlockTermination(i)) {
|
|
14964
|
+
this.basicBlocks.add(i + 1 + mask.getNoOfBytesToNextInstruction(i + 1));
|
|
14374
14965
|
}
|
|
14375
|
-
pages.push(page);
|
|
14376
|
-
}
|
|
14377
|
-
return Result$1.ok(pages);
|
|
14378
|
-
}
|
|
14379
|
-
/**
|
|
14380
|
-
* Read content of the memory at `[address, address + result.length)` and
|
|
14381
|
-
* write the result into the `result` buffer.
|
|
14382
|
-
*
|
|
14383
|
-
* Returns `null` if the data was read successfully or `PageFault` otherwise.
|
|
14384
|
-
*/
|
|
14385
|
-
loadInto(result, startAddress) {
|
|
14386
|
-
if (result.length === 0) {
|
|
14387
|
-
return Result$1.ok(OK);
|
|
14388
|
-
}
|
|
14389
|
-
const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
|
|
14390
|
-
if (pagesResult.isError) {
|
|
14391
|
-
return Result$1.error(pagesResult.error, pagesResult.details);
|
|
14392
|
-
}
|
|
14393
|
-
const pages = pagesResult.ok;
|
|
14394
|
-
let currentPosition = startAddress;
|
|
14395
|
-
let bytesLeft = result.length;
|
|
14396
|
-
for (const page of pages) {
|
|
14397
|
-
const pageStartIndex = tryAsPageIndex(currentPosition % PAGE_SIZE$1);
|
|
14398
|
-
const bytesToRead = Math.min(PAGE_SIZE$1 - pageStartIndex, bytesLeft);
|
|
14399
|
-
const destinationStartIndex = currentPosition - startAddress;
|
|
14400
|
-
const destination = result.subarray(destinationStartIndex);
|
|
14401
|
-
page.loadInto(destination, pageStartIndex, bytesToRead);
|
|
14402
|
-
currentPosition += bytesToRead;
|
|
14403
|
-
bytesLeft -= bytesToRead;
|
|
14404
|
-
}
|
|
14405
|
-
logger$3.insane `MEM[${startAddress}] => ${BytesBlob.blobFrom(result)}`;
|
|
14406
|
-
return Result$1.ok(OK);
|
|
14407
|
-
}
|
|
14408
|
-
sbrk(length) {
|
|
14409
|
-
const currentSbrkIndex = this.sbrkIndex;
|
|
14410
|
-
const currentVirtualSbrkIndex = this.virtualSbrkIndex;
|
|
14411
|
-
// new sbrk index is bigger than 2 ** 32 or endHeapIndex
|
|
14412
|
-
if (MAX_MEMORY_INDEX < currentVirtualSbrkIndex + length || currentVirtualSbrkIndex + length > this.endHeapIndex) {
|
|
14413
|
-
throw new OutOfMemory();
|
|
14414
|
-
}
|
|
14415
|
-
const newVirtualSbrkIndex = tryAsSbrkIndex(this.virtualSbrkIndex + length);
|
|
14416
|
-
// no alllocation needed
|
|
14417
|
-
if (newVirtualSbrkIndex <= currentSbrkIndex) {
|
|
14418
|
-
this.virtualSbrkIndex = newVirtualSbrkIndex;
|
|
14419
|
-
return currentVirtualSbrkIndex;
|
|
14420
|
-
}
|
|
14421
|
-
// standard allocation using "Writeable" pages
|
|
14422
|
-
const newSbrkIndex = tryAsSbrkIndex(alignToPageSize$1(newVirtualSbrkIndex));
|
|
14423
|
-
// TODO [MaSi]: `getPageNumber` works incorrectly for SbrkIndex. Sbrk index should be changed to MemoryIndex
|
|
14424
|
-
const firstPageNumber = getPageNumber(currentSbrkIndex);
|
|
14425
|
-
const pagesToAllocate = (newSbrkIndex - currentSbrkIndex) / PAGE_SIZE$1;
|
|
14426
|
-
const rangeToAllocate = PageRange.fromStartAndLength(firstPageNumber, pagesToAllocate);
|
|
14427
|
-
for (const pageNumber of rangeToAllocate) {
|
|
14428
|
-
const page = new WriteablePage(pageNumber);
|
|
14429
|
-
this.memory.set(pageNumber, page);
|
|
14430
14966
|
}
|
|
14431
|
-
this.virtualSbrkIndex = newVirtualSbrkIndex;
|
|
14432
|
-
this.sbrkIndex = newSbrkIndex;
|
|
14433
|
-
return currentVirtualSbrkIndex;
|
|
14434
|
-
}
|
|
14435
|
-
getPageDump(pageNumber) {
|
|
14436
|
-
const page = this.memory.get(pageNumber);
|
|
14437
|
-
return page?.getPageDump() ?? null;
|
|
14438
14967
|
}
|
|
14439
|
-
|
|
14440
|
-
return this.
|
|
14968
|
+
isBeginningOfBasicBlock(index) {
|
|
14969
|
+
return this.basicBlocks.has(index);
|
|
14441
14970
|
}
|
|
14442
14971
|
}
|
|
14443
|
-
|
|
14444
|
-
|
|
14445
|
-
|
|
14446
|
-
|
|
14447
|
-
|
|
14448
|
-
|
|
14449
|
-
throw new FinalizedBuilderModification();
|
|
14450
|
-
}
|
|
14451
|
-
}
|
|
14452
|
-
ensureNoReservedMemoryUsage(range) {
|
|
14453
|
-
if (range.overlapsWith(RESERVED_MEMORY_RANGE)) {
|
|
14454
|
-
throw new ReservedMemoryFault();
|
|
14455
|
-
}
|
|
14456
|
-
}
|
|
14457
|
-
/**
|
|
14458
|
-
* Create entire readable pages to handle the `[start, end)` range.
|
|
14459
|
-
*
|
|
14460
|
-
* Note that both `start` and `end` must be multiple of the `PAGE_SIZE`, i.e.
|
|
14461
|
-
* they need to be the start indices of the pages.
|
|
14462
|
-
*
|
|
14463
|
-
* The data passed will be placed at `start`, but might be shorter than the requested range,
|
|
14464
|
-
* prepend it with zeros if you don't wish to have it at the beginning of the page.
|
|
14465
|
-
*/
|
|
14466
|
-
setReadablePages(start, end, data = new Uint8Array()) {
|
|
14467
|
-
this.ensureNotFinalized();
|
|
14468
|
-
check `${start < end} end has to be bigger than start`;
|
|
14469
|
-
check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
14470
|
-
check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
14471
|
-
check `${data.length <= end - start} the initial data is longer than address range`;
|
|
14472
|
-
const length = end - start;
|
|
14473
|
-
const range = MemoryRange.fromStartAndLength(start, length);
|
|
14474
|
-
this.ensureNoReservedMemoryUsage(range);
|
|
14475
|
-
const pages = Array.from(PageRange.fromMemoryRange(range));
|
|
14476
|
-
const noOfPages = pages.length;
|
|
14477
|
-
for (let i = 0; i < noOfPages; i++) {
|
|
14478
|
-
const pageNumber = pages[i];
|
|
14479
|
-
const dataChunk = data.subarray(i * PAGE_SIZE$1, (i + 1) * PAGE_SIZE$1);
|
|
14480
|
-
const page = new ReadablePage(pageNumber, dataChunk);
|
|
14481
|
-
this.initialMemory.set(pageNumber, page);
|
|
14482
|
-
}
|
|
14483
|
-
return this;
|
|
14972
|
+
|
|
14973
|
+
const instructionGasMap = (() => {
|
|
14974
|
+
const instructionGasMap = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
|
|
14975
|
+
for (let i = 0; i < HIGHEST_INSTRUCTION_NUMBER + 1; i++) {
|
|
14976
|
+
const gas = byteToOpCodeMap[i]?.gas;
|
|
14977
|
+
instructionGasMap[i] = gas;
|
|
14484
14978
|
}
|
|
14979
|
+
return instructionGasMap;
|
|
14980
|
+
})();
|
|
14981
|
+
|
|
14982
|
+
class InstructionResult {
|
|
14983
|
+
nextPc = 0;
|
|
14984
|
+
status = null;
|
|
14485
14985
|
/**
|
|
14486
|
-
*
|
|
14986
|
+
* A numeric exit parameter of the PVM.
|
|
14487
14987
|
*
|
|
14488
|
-
*
|
|
14489
|
-
*
|
|
14988
|
+
* In case of a `status === Result.FAULT` this will be the memory address
|
|
14989
|
+
* that triggered the fault.
|
|
14990
|
+
* In case of a `status === Result.HOST` this will be the host call index
|
|
14991
|
+
* that should be invoked.
|
|
14490
14992
|
*
|
|
14491
|
-
*
|
|
14492
|
-
* prepend it with zeros if you don't wish to have it at the beginning of the page.
|
|
14493
|
-
*/
|
|
14494
|
-
setWriteablePages(start, end, data = new Uint8Array()) {
|
|
14495
|
-
this.ensureNotFinalized();
|
|
14496
|
-
check `${start < end} end has to be bigger than start`;
|
|
14497
|
-
check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
14498
|
-
check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
|
|
14499
|
-
check `${data.length <= end - start} the initial data is longer than address range`;
|
|
14500
|
-
const length = end - start;
|
|
14501
|
-
const range = MemoryRange.fromStartAndLength(start, length);
|
|
14502
|
-
this.ensureNoReservedMemoryUsage(range);
|
|
14503
|
-
const pages = Array.from(PageRange.fromMemoryRange(range));
|
|
14504
|
-
const noOfPages = pages.length;
|
|
14505
|
-
for (let i = 0; i < noOfPages; i++) {
|
|
14506
|
-
const pageNumber = pages[i];
|
|
14507
|
-
const dataChunk = data.subarray(i * PAGE_SIZE$1, (i + 1) * PAGE_SIZE$1);
|
|
14508
|
-
const page = new WriteablePage(pageNumber, dataChunk);
|
|
14509
|
-
this.initialMemory.set(pageNumber, page);
|
|
14510
|
-
}
|
|
14511
|
-
return this;
|
|
14512
|
-
}
|
|
14513
|
-
/**
|
|
14514
|
-
* This function can be useful when page map and initial memory data are provided separatelly.
|
|
14515
|
-
* You can use setWriteablePages/setReadablePages to create empty pages and then setData to fill them
|
|
14993
|
+
* In any other circumstance the value should be `null`.
|
|
14516
14994
|
*/
|
|
14517
|
-
|
|
14518
|
-
|
|
14519
|
-
|
|
14520
|
-
|
|
14521
|
-
|
|
14522
|
-
const length = data.length;
|
|
14523
|
-
const range = MemoryRange.fromStartAndLength(start, length);
|
|
14524
|
-
this.ensureNoReservedMemoryUsage(range);
|
|
14525
|
-
const pageNumber = getPageNumber(start);
|
|
14526
|
-
const page = this.initialMemory.get(pageNumber);
|
|
14527
|
-
if (page === undefined) {
|
|
14528
|
-
throw new PageNotExist();
|
|
14529
|
-
}
|
|
14530
|
-
const startPageIndex = tryAsPageIndex(start - page.start);
|
|
14531
|
-
page.setData(startPageIndex, data);
|
|
14532
|
-
return this;
|
|
14533
|
-
}
|
|
14534
|
-
finalize(startHeapIndex, endHeapIndex) {
|
|
14535
|
-
check `
|
|
14536
|
-
${startHeapIndex <= endHeapIndex}
|
|
14537
|
-
startHeapIndex (${startHeapIndex}) has to be less than or equal to endHeapIndex (${endHeapIndex})
|
|
14538
|
-
`;
|
|
14539
|
-
this.ensureNotFinalized();
|
|
14540
|
-
const heapRange = MemoryRange.fromStartAndLength(startHeapIndex, endHeapIndex - startHeapIndex);
|
|
14541
|
-
const heapPagesRange = PageRange.fromMemoryRange(heapRange);
|
|
14542
|
-
const initializedPageNumbers = Array.from(this.initialMemory.keys());
|
|
14543
|
-
for (const pageNumber of initializedPageNumbers) {
|
|
14544
|
-
if (heapPagesRange.isInRange(pageNumber)) {
|
|
14545
|
-
throw new IncorrectSbrkIndex();
|
|
14546
|
-
}
|
|
14547
|
-
}
|
|
14548
|
-
const memory = Memory.fromInitialMemory({
|
|
14549
|
-
memory: this.initialMemory,
|
|
14550
|
-
sbrkIndex: tryAsSbrkIndex(startHeapIndex),
|
|
14551
|
-
endHeapIndex,
|
|
14552
|
-
});
|
|
14553
|
-
this.isFinalized = true;
|
|
14554
|
-
return memory;
|
|
14995
|
+
exitParam = null;
|
|
14996
|
+
reset() {
|
|
14997
|
+
this.nextPc = 0;
|
|
14998
|
+
this.status = null;
|
|
14999
|
+
this.exitParam = null;
|
|
14555
15000
|
}
|
|
14556
15001
|
}
|
|
14557
15002
|
|
|
@@ -15490,7 +15935,7 @@ class StoreOps {
|
|
|
15490
15935
|
}
|
|
15491
15936
|
else {
|
|
15492
15937
|
this.instructionResult.status = Result.FAULT;
|
|
15493
|
-
this.instructionResult.exitParam = getStartPageIndex(storeResult.error.address);
|
|
15938
|
+
this.instructionResult.exitParam = getStartPageIndex(tryAsMemoryIndex(storeResult.error.address));
|
|
15494
15939
|
}
|
|
15495
15940
|
}
|
|
15496
15941
|
}
|
|
@@ -16142,7 +16587,7 @@ class JumpTable {
|
|
|
16142
16587
|
}
|
|
16143
16588
|
}
|
|
16144
16589
|
|
|
16145
|
-
const logger$
|
|
16590
|
+
const logger$1 = Logger.new(import.meta.filename, "pvm-interpreter");
|
|
16146
16591
|
var ProgramDecoderError;
|
|
16147
16592
|
(function (ProgramDecoderError) {
|
|
16148
16593
|
ProgramDecoderError[ProgramDecoderError["InvalidProgramError"] = 0] = "InvalidProgramError";
|
|
@@ -16192,21 +16637,21 @@ class ProgramDecoder {
|
|
|
16192
16637
|
return Result$1.ok(new ProgramDecoder(program));
|
|
16193
16638
|
}
|
|
16194
16639
|
catch (e) {
|
|
16195
|
-
logger$
|
|
16640
|
+
logger$1.error `Invalid program: ${e}`;
|
|
16196
16641
|
return Result$1.error(ProgramDecoderError.InvalidProgramError, () => `Program decoder error: ${e}`);
|
|
16197
16642
|
}
|
|
16198
16643
|
}
|
|
16199
16644
|
}
|
|
16200
16645
|
|
|
16201
|
-
const logger
|
|
16646
|
+
const logger = Logger.new(import.meta.filename, "pvm");
|
|
16202
16647
|
class Interpreter {
|
|
16203
16648
|
useSbrkGas;
|
|
16204
16649
|
registers = new Registers();
|
|
16650
|
+
memory = new Memory();
|
|
16651
|
+
gas = gasCounter(tryAsGas(0));
|
|
16205
16652
|
code = new Uint8Array();
|
|
16206
16653
|
mask = Mask.empty();
|
|
16207
16654
|
pc = 0;
|
|
16208
|
-
gas = gasCounter(tryAsGas(0));
|
|
16209
|
-
initialGas = gasCounter(tryAsGas(0));
|
|
16210
16655
|
argsDecoder;
|
|
16211
16656
|
threeRegsDispatcher;
|
|
16212
16657
|
twoRegsOneImmDispatcher;
|
|
@@ -16216,7 +16661,6 @@ class Interpreter {
|
|
|
16216
16661
|
oneOffsetDispatcher;
|
|
16217
16662
|
oneRegOneImmDispatcher;
|
|
16218
16663
|
instructionResult = new InstructionResult();
|
|
16219
|
-
memory = new Memory();
|
|
16220
16664
|
twoImmsDispatcher;
|
|
16221
16665
|
oneRegTwoImmsDispatcher;
|
|
16222
16666
|
noArgsDispatcher;
|
|
@@ -16258,14 +16702,17 @@ class Interpreter {
|
|
|
16258
16702
|
this.oneImmDispatcher = new OneImmDispatcher(hostCallOps);
|
|
16259
16703
|
this.oneRegOneExtImmDispatcher = new OneRegOneExtImmDispatcher(loadOps);
|
|
16260
16704
|
}
|
|
16261
|
-
|
|
16705
|
+
resetJam(program, args, pc, gas) {
|
|
16706
|
+
const p = Program.fromSpi(program, args, true);
|
|
16707
|
+
this.resetGeneric(p.code, pc, gas, p.registers, p.memory);
|
|
16708
|
+
}
|
|
16709
|
+
resetGeneric(rawProgram, pc, gas, maybeRegisters, maybeMemory) {
|
|
16262
16710
|
const programDecoder = new ProgramDecoder(rawProgram);
|
|
16263
16711
|
this.code = programDecoder.getCode();
|
|
16264
16712
|
this.mask = programDecoder.getMask();
|
|
16265
16713
|
this.jumpTable.copyFrom(programDecoder.getJumpTable());
|
|
16266
16714
|
this.pc = pc;
|
|
16267
16715
|
this.gas = gasCounter(gas);
|
|
16268
|
-
this.initialGas = gasCounter(gas);
|
|
16269
16716
|
this.status = Status.OK;
|
|
16270
16717
|
this.argsDecoder.reset(this.code, this.mask);
|
|
16271
16718
|
this.basicBlocks.reset(this.code, this.mask);
|
|
@@ -16317,7 +16764,7 @@ class Interpreter {
|
|
|
16317
16764
|
const argsType = instructionArgumentTypeMap[currentInstruction] ?? ArgumentType.NO_ARGUMENTS;
|
|
16318
16765
|
const argsResult = this.argsDecodingResults[argsType];
|
|
16319
16766
|
this.argsDecoder.fillArgs(this.pc, argsResult);
|
|
16320
|
-
logger
|
|
16767
|
+
logger.insane `[PC: ${this.pc}] ${Instruction[currentInstruction]}`;
|
|
16321
16768
|
if (!isValidInstruction) {
|
|
16322
16769
|
this.instructionResult.status = Result.PANIC;
|
|
16323
16770
|
}
|
|
@@ -16389,34 +16836,18 @@ class Interpreter {
|
|
|
16389
16836
|
this.status = Status.HOST;
|
|
16390
16837
|
break;
|
|
16391
16838
|
}
|
|
16392
|
-
logger
|
|
16839
|
+
logger.insane `[PC: ${this.pc}] Status: ${Result[this.instructionResult.status]}`;
|
|
16393
16840
|
return this.status;
|
|
16394
16841
|
}
|
|
16395
16842
|
this.pc = this.instructionResult.nextPc;
|
|
16396
16843
|
return this.status;
|
|
16397
16844
|
}
|
|
16398
|
-
getRegisters() {
|
|
16399
|
-
return this.registers;
|
|
16400
|
-
}
|
|
16401
16845
|
getPC() {
|
|
16402
16846
|
return this.pc;
|
|
16403
16847
|
}
|
|
16404
16848
|
setNextPC(nextPc) {
|
|
16405
16849
|
this.pc = nextPc;
|
|
16406
16850
|
}
|
|
16407
|
-
getGas() {
|
|
16408
|
-
return this.gas.get();
|
|
16409
|
-
}
|
|
16410
|
-
getGasConsumed() {
|
|
16411
|
-
const gasConsumed = tryAsBigGas(this.initialGas.get()) - tryAsBigGas(this.gas.get());
|
|
16412
|
-
if (gasConsumed < 0) {
|
|
16413
|
-
return this.initialGas.get();
|
|
16414
|
-
}
|
|
16415
|
-
return tryAsBigGas(gasConsumed);
|
|
16416
|
-
}
|
|
16417
|
-
getGasCounter() {
|
|
16418
|
-
return this.gas;
|
|
16419
|
-
}
|
|
16420
16851
|
getStatus() {
|
|
16421
16852
|
return this.status;
|
|
16422
16853
|
}
|
|
@@ -16424,9 +16855,6 @@ class Interpreter {
|
|
|
16424
16855
|
const p = this.instructionResult.exitParam;
|
|
16425
16856
|
return p !== null ? tryAsU32(p) : p;
|
|
16426
16857
|
}
|
|
16427
|
-
getMemory() {
|
|
16428
|
-
return this.memory;
|
|
16429
|
-
}
|
|
16430
16858
|
getMemoryPage(pageNumber) {
|
|
16431
16859
|
return this.memory.getPageDump(tryAsPageNumber(pageNumber));
|
|
16432
16860
|
}
|
|
@@ -16450,212 +16878,560 @@ class Interpreter {
|
|
|
16450
16878
|
}
|
|
16451
16879
|
}
|
|
16452
16880
|
|
|
16453
|
-
var index$
|
|
16881
|
+
var index$5 = /*#__PURE__*/Object.freeze({
|
|
16454
16882
|
__proto__: null,
|
|
16455
16883
|
Interpreter: Interpreter,
|
|
16456
16884
|
Memory: Memory,
|
|
16457
16885
|
MemoryBuilder: MemoryBuilder,
|
|
16458
16886
|
Registers: Registers,
|
|
16459
16887
|
gasCounter: gasCounter,
|
|
16460
|
-
tryAsBigGas: tryAsBigGas,
|
|
16461
|
-
tryAsGas: tryAsGas,
|
|
16462
16888
|
tryAsMemoryIndex: tryAsMemoryIndex,
|
|
16463
|
-
tryAsSbrkIndex: tryAsSbrkIndex
|
|
16464
|
-
tryAsSmallGas: tryAsSmallGas
|
|
16889
|
+
tryAsSbrkIndex: tryAsSbrkIndex
|
|
16465
16890
|
});
|
|
16466
16891
|
|
|
16467
|
-
|
|
16468
|
-
|
|
16469
|
-
|
|
16470
|
-
|
|
16471
|
-
|
|
16472
|
-
|
|
16473
|
-
|
|
16474
|
-
|
|
16475
|
-
|
|
16476
|
-
|
|
16477
|
-
|
|
16478
|
-
|
|
16479
|
-
|
|
16480
|
-
|
|
16481
|
-
|
|
16482
|
-
|
|
16483
|
-
|
|
16484
|
-
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
|
|
16892
|
+
async function instantiate(module, imports = {}) {
|
|
16893
|
+
const adaptedImports = {
|
|
16894
|
+
env: Object.setPrototypeOf({
|
|
16895
|
+
abort(message, fileName, lineNumber, columnNumber) {
|
|
16896
|
+
// ~lib/builtins/abort(~lib/string/String | null?, ~lib/string/String | null?, u32?, u32?) => void
|
|
16897
|
+
message = __liftString(message >>> 0);
|
|
16898
|
+
fileName = __liftString(fileName >>> 0);
|
|
16899
|
+
lineNumber = lineNumber >>> 0;
|
|
16900
|
+
columnNumber = columnNumber >>> 0;
|
|
16901
|
+
(() => {
|
|
16902
|
+
// @external.js
|
|
16903
|
+
throw Error(`${message} in ${fileName}:${lineNumber}:${columnNumber}`);
|
|
16904
|
+
})();
|
|
16905
|
+
},
|
|
16906
|
+
"console.log"(text) {
|
|
16907
|
+
// ~lib/bindings/dom/console.log(~lib/string/String) => void
|
|
16908
|
+
text = __liftString(text >>> 0);
|
|
16909
|
+
console.log(text);
|
|
16910
|
+
},
|
|
16911
|
+
}, Object.assign(Object.create(globalThis), imports.env || {})),
|
|
16912
|
+
};
|
|
16913
|
+
const { exports } = await WebAssembly.instantiate(module, adaptedImports);
|
|
16914
|
+
const memory = exports.memory || imports.env.memory;
|
|
16915
|
+
const adaptedExports = Object.setPrototypeOf({
|
|
16916
|
+
getAssembly(p) {
|
|
16917
|
+
// assembly/api-internal/getAssembly(assembly/program/Program) => ~lib/string/String
|
|
16918
|
+
p = __lowerInternref(p) || __notnull();
|
|
16919
|
+
return __liftString(exports.getAssembly(p) >>> 0);
|
|
16920
|
+
},
|
|
16921
|
+
wrapAsProgram(bytecode) {
|
|
16922
|
+
// assembly/program-build/wrapAsProgram(~lib/typedarray/Uint8Array) => ~lib/typedarray/Uint8Array
|
|
16923
|
+
bytecode = __lowerTypedArray(Uint8Array, 10, 0, bytecode) || __notnull();
|
|
16924
|
+
return __liftTypedArray(Uint8Array, exports.wrapAsProgram(bytecode) >>> 0);
|
|
16925
|
+
},
|
|
16926
|
+
resetJAM(program, pc, initialGas, args, hasMetadata) {
|
|
16927
|
+
// assembly/api-debugger/resetJAM(~lib/array/Array<u8>, f64, i64, ~lib/array/Array<u8>, bool?) => void
|
|
16928
|
+
program = __retain(__lowerArray(__setU8, 6, 0, program) || __notnull());
|
|
16929
|
+
initialGas = initialGas || 0n;
|
|
16930
|
+
args = __lowerArray(__setU8, 6, 0, args) || __notnull();
|
|
16931
|
+
hasMetadata = hasMetadata ? 1 : 0;
|
|
16932
|
+
try {
|
|
16933
|
+
exports.__setArgumentsLength(arguments.length);
|
|
16934
|
+
exports.resetJAM(program, pc, initialGas, args, hasMetadata);
|
|
16935
|
+
} finally {
|
|
16936
|
+
__release(program);
|
|
16937
|
+
}
|
|
16938
|
+
},
|
|
16939
|
+
resetGeneric(program, flatRegisters, initialGas, hasMetadata) {
|
|
16940
|
+
// assembly/api-debugger/resetGeneric(~lib/array/Array<u8>, ~lib/array/Array<u8>, i64, bool?) => void
|
|
16941
|
+
program = __retain(__lowerArray(__setU8, 6, 0, program) || __notnull());
|
|
16942
|
+
flatRegisters = __lowerArray(__setU8, 6, 0, flatRegisters) || __notnull();
|
|
16943
|
+
initialGas = initialGas || 0n;
|
|
16944
|
+
hasMetadata = hasMetadata ? 1 : 0;
|
|
16945
|
+
try {
|
|
16946
|
+
exports.__setArgumentsLength(arguments.length);
|
|
16947
|
+
exports.resetGeneric(program, flatRegisters, initialGas, hasMetadata);
|
|
16948
|
+
} finally {
|
|
16949
|
+
__release(program);
|
|
16950
|
+
}
|
|
16951
|
+
},
|
|
16952
|
+
resetGenericWithMemory(program, flatRegisters, pageMap, chunks, initialGas, hasMetadata) {
|
|
16953
|
+
// assembly/api-debugger/resetGenericWithMemory(~lib/array/Array<u8>, ~lib/array/Array<u8>, ~lib/typedarray/Uint8Array, ~lib/typedarray/Uint8Array, i64, bool?) => void
|
|
16954
|
+
program = __retain(__lowerArray(__setU8, 6, 0, program) || __notnull());
|
|
16955
|
+
flatRegisters = __retain(__lowerArray(__setU8, 6, 0, flatRegisters) || __notnull());
|
|
16956
|
+
pageMap = __retain(__lowerTypedArray(Uint8Array, 10, 0, pageMap) || __notnull());
|
|
16957
|
+
chunks = __lowerTypedArray(Uint8Array, 10, 0, chunks) || __notnull();
|
|
16958
|
+
initialGas = initialGas || 0n;
|
|
16959
|
+
hasMetadata = hasMetadata ? 1 : 0;
|
|
16960
|
+
try {
|
|
16961
|
+
exports.__setArgumentsLength(arguments.length);
|
|
16962
|
+
exports.resetGenericWithMemory(program, flatRegisters, pageMap, chunks, initialGas, hasMetadata);
|
|
16963
|
+
} finally {
|
|
16964
|
+
__release(program);
|
|
16965
|
+
__release(flatRegisters);
|
|
16966
|
+
__release(pageMap);
|
|
16967
|
+
}
|
|
16968
|
+
},
|
|
16969
|
+
nextStep() {
|
|
16970
|
+
// assembly/api-debugger/nextStep() => bool
|
|
16971
|
+
return exports.nextStep() != 0;
|
|
16972
|
+
},
|
|
16973
|
+
nSteps(steps) {
|
|
16974
|
+
// assembly/api-debugger/nSteps(u32) => bool
|
|
16975
|
+
return exports.nSteps(steps) != 0;
|
|
16976
|
+
},
|
|
16977
|
+
getProgramCounter() {
|
|
16978
|
+
// assembly/api-debugger/getProgramCounter() => u32
|
|
16979
|
+
return exports.getProgramCounter() >>> 0;
|
|
16980
|
+
},
|
|
16981
|
+
getExitArg() {
|
|
16982
|
+
// assembly/api-debugger/getExitArg() => u32
|
|
16983
|
+
return exports.getExitArg() >>> 0;
|
|
16984
|
+
},
|
|
16985
|
+
setGasLeft(gas) {
|
|
16986
|
+
// assembly/api-debugger/setGasLeft(i64) => void
|
|
16987
|
+
gas = gas || 0n;
|
|
16988
|
+
exports.setGasLeft(gas);
|
|
16989
|
+
},
|
|
16990
|
+
getRegisters() {
|
|
16991
|
+
// assembly/api-debugger/getRegisters() => ~lib/typedarray/Uint8Array
|
|
16992
|
+
return __liftTypedArray(Uint8Array, exports.getRegisters() >>> 0);
|
|
16993
|
+
},
|
|
16994
|
+
setRegisters(flatRegisters) {
|
|
16995
|
+
// assembly/api-debugger/setRegisters(~lib/array/Array<u8>) => void
|
|
16996
|
+
flatRegisters = __lowerArray(__setU8, 6, 0, flatRegisters) || __notnull();
|
|
16997
|
+
exports.setRegisters(flatRegisters);
|
|
16998
|
+
},
|
|
16999
|
+
getPageDump(index) {
|
|
17000
|
+
// assembly/api-debugger/getPageDump(u32) => ~lib/typedarray/Uint8Array
|
|
17001
|
+
return __liftTypedArray(Uint8Array, exports.getPageDump(index) >>> 0);
|
|
17002
|
+
},
|
|
17003
|
+
getMemory(address, length) {
|
|
17004
|
+
// assembly/api-debugger/getMemory(u32, u32) => ~lib/typedarray/Uint8Array | null
|
|
17005
|
+
return __liftTypedArray(Uint8Array, exports.getMemory(address, length) >>> 0);
|
|
17006
|
+
},
|
|
17007
|
+
setMemory(address, data) {
|
|
17008
|
+
// assembly/api-debugger/setMemory(u32, ~lib/typedarray/Uint8Array) => bool
|
|
17009
|
+
data = __lowerTypedArray(Uint8Array, 10, 0, data) || __notnull();
|
|
17010
|
+
return exports.setMemory(address, data) != 0;
|
|
17011
|
+
},
|
|
17012
|
+
InputKind: (values => (
|
|
17013
|
+
// assembly/api-utils/InputKind
|
|
17014
|
+
values[values.Generic = exports["InputKind.Generic"].valueOf()] = "Generic",
|
|
17015
|
+
values[values.SPI = exports["InputKind.SPI"].valueOf()] = "SPI",
|
|
17016
|
+
values
|
|
17017
|
+
))({}),
|
|
17018
|
+
HasMetadata: (values => (
|
|
17019
|
+
// assembly/api-utils/HasMetadata
|
|
17020
|
+
values[values.Yes = exports["HasMetadata.Yes"].valueOf()] = "Yes",
|
|
17021
|
+
values[values.No = exports["HasMetadata.No"].valueOf()] = "No",
|
|
17022
|
+
values
|
|
17023
|
+
))({}),
|
|
17024
|
+
getGasCosts(input, kind, withMetadata) {
|
|
17025
|
+
// assembly/api-utils/getGasCosts(~lib/array/Array<u8>, i32, i32) => ~lib/array/Array<assembly/gas-costs/BlockGasCost>
|
|
17026
|
+
input = __lowerArray(__setU8, 6, 0, input) || __notnull();
|
|
17027
|
+
return __liftArray(pointer => __liftRecord50(__getU32(pointer)), 2, exports.getGasCosts(input, kind, withMetadata) >>> 0);
|
|
17028
|
+
},
|
|
17029
|
+
disassemble(input, kind, withMetadata) {
|
|
17030
|
+
// assembly/api-utils/disassemble(~lib/array/Array<u8>, i32, i32) => ~lib/string/String
|
|
17031
|
+
input = __lowerArray(__setU8, 6, 0, input) || __notnull();
|
|
17032
|
+
return __liftString(exports.disassemble(input, kind, withMetadata) >>> 0);
|
|
17033
|
+
},
|
|
17034
|
+
prepareProgram(kind, hasMetadata, program, initialRegisters, initialPageMap, initialMemory, args) {
|
|
17035
|
+
// assembly/api-utils/prepareProgram(i32, i32, ~lib/array/Array<u8>, ~lib/array/Array<u64>, ~lib/array/Array<assembly/api-internal/InitialPage>, ~lib/array/Array<assembly/api-internal/InitialChunk>, ~lib/array/Array<u8>) => assembly/spi/StandardProgram
|
|
17036
|
+
program = __retain(__lowerArray(__setU8, 6, 0, program) || __notnull());
|
|
17037
|
+
initialRegisters = __retain(__lowerArray(__setU64, 52, 3, initialRegisters) || __notnull());
|
|
17038
|
+
initialPageMap = __retain(__lowerArray((pointer, value) => { __setU32(pointer, __lowerRecord46(value) || __notnull()); }, 47, 2, initialPageMap) || __notnull());
|
|
17039
|
+
initialMemory = __retain(__lowerArray((pointer, value) => { __setU32(pointer, __lowerRecord48(value) || __notnull()); }, 49, 2, initialMemory) || __notnull());
|
|
17040
|
+
args = __lowerArray(__setU8, 6, 0, args) || __notnull();
|
|
17041
|
+
try {
|
|
17042
|
+
return __liftInternref(exports.prepareProgram(kind, hasMetadata, program, initialRegisters, initialPageMap, initialMemory, args) >>> 0);
|
|
17043
|
+
} finally {
|
|
17044
|
+
__release(program);
|
|
17045
|
+
__release(initialRegisters);
|
|
17046
|
+
__release(initialPageMap);
|
|
17047
|
+
__release(initialMemory);
|
|
17048
|
+
}
|
|
17049
|
+
},
|
|
17050
|
+
runProgram(program, initialGas, programCounter, logs, useSbrkGas) {
|
|
17051
|
+
// assembly/api-utils/runProgram(assembly/spi/StandardProgram, i64?, u32?, bool?, bool?) => assembly/api-internal/VmOutput
|
|
17052
|
+
program = __lowerInternref(program) || __notnull();
|
|
17053
|
+
initialGas = initialGas || 0n;
|
|
17054
|
+
logs = logs ? 1 : 0;
|
|
17055
|
+
useSbrkGas = useSbrkGas ? 1 : 0;
|
|
17056
|
+
exports.__setArgumentsLength(arguments.length);
|
|
17057
|
+
return __liftRecord55(exports.runProgram(program, initialGas, programCounter, logs, useSbrkGas) >>> 0);
|
|
17058
|
+
},
|
|
17059
|
+
}, exports);
|
|
17060
|
+
function __liftRecord50(pointer) {
|
|
17061
|
+
// assembly/gas-costs/BlockGasCost
|
|
17062
|
+
// Hint: Opt-out from lifting as a record by providing an empty constructor
|
|
17063
|
+
if (!pointer) return null;
|
|
17064
|
+
return {
|
|
17065
|
+
pc: __getU32(pointer + 0),
|
|
17066
|
+
gas: __getU64(pointer + 8),
|
|
17067
|
+
};
|
|
17068
|
+
}
|
|
17069
|
+
function __lowerRecord46(value) {
|
|
17070
|
+
// assembly/api-internal/InitialPage
|
|
17071
|
+
// Hint: Opt-out from lowering as a record by providing an empty constructor
|
|
17072
|
+
if (value == null) return 0;
|
|
17073
|
+
const pointer = exports.__pin(exports.__new(12, 46));
|
|
17074
|
+
__setU32(pointer + 0, value.address);
|
|
17075
|
+
__setU32(pointer + 4, value.length);
|
|
17076
|
+
__setU32(pointer + 8, value.access);
|
|
17077
|
+
exports.__unpin(pointer);
|
|
17078
|
+
return pointer;
|
|
17079
|
+
}
|
|
17080
|
+
function __lowerRecord48(value) {
|
|
17081
|
+
// assembly/api-internal/InitialChunk
|
|
17082
|
+
// Hint: Opt-out from lowering as a record by providing an empty constructor
|
|
17083
|
+
if (value == null) return 0;
|
|
17084
|
+
const pointer = exports.__pin(exports.__new(8, 48));
|
|
17085
|
+
__setU32(pointer + 0, value.address);
|
|
17086
|
+
__setU32(pointer + 4, __lowerArray(__setU8, 6, 0, value.data) || __notnull());
|
|
17087
|
+
exports.__unpin(pointer);
|
|
17088
|
+
return pointer;
|
|
17089
|
+
}
|
|
17090
|
+
function __liftRecord48(pointer) {
|
|
17091
|
+
// assembly/api-internal/InitialChunk
|
|
17092
|
+
// Hint: Opt-out from lifting as a record by providing an empty constructor
|
|
17093
|
+
if (!pointer) return null;
|
|
17094
|
+
return {
|
|
17095
|
+
address: __getU32(pointer + 0),
|
|
17096
|
+
data: __liftArray(__getU8, 0, __getU32(pointer + 4)),
|
|
17097
|
+
};
|
|
17098
|
+
}
|
|
17099
|
+
function __liftRecord55(pointer) {
|
|
17100
|
+
// assembly/api-internal/VmOutput
|
|
17101
|
+
// Hint: Opt-out from lifting as a record by providing an empty constructor
|
|
17102
|
+
if (!pointer) return null;
|
|
17103
|
+
return {
|
|
17104
|
+
status: __getI32(pointer + 0),
|
|
17105
|
+
registers: __liftArray(pointer => BigInt.asUintN(64, __getU64(pointer)), 3, __getU32(pointer + 4)),
|
|
17106
|
+
pc: __getU32(pointer + 8),
|
|
17107
|
+
memory: __liftArray(pointer => __liftRecord48(__getU32(pointer)), 2, __getU32(pointer + 12)),
|
|
17108
|
+
gas: __getI64(pointer + 16),
|
|
17109
|
+
exitCode: __getU32(pointer + 24),
|
|
17110
|
+
};
|
|
17111
|
+
}
|
|
17112
|
+
function __liftString(pointer) {
|
|
17113
|
+
if (!pointer) return null;
|
|
17114
|
+
const
|
|
17115
|
+
end = pointer + new Uint32Array(memory.buffer)[pointer - 4 >>> 2] >>> 1,
|
|
17116
|
+
memoryU16 = new Uint16Array(memory.buffer);
|
|
17117
|
+
let
|
|
17118
|
+
start = pointer >>> 1,
|
|
17119
|
+
string = "";
|
|
17120
|
+
while (end - start > 1024) string += String.fromCharCode(...memoryU16.subarray(start, start += 1024));
|
|
17121
|
+
return string + String.fromCharCode(...memoryU16.subarray(start, end));
|
|
17122
|
+
}
|
|
17123
|
+
function __liftArray(liftElement, align, pointer) {
|
|
17124
|
+
if (!pointer) return null;
|
|
17125
|
+
const
|
|
17126
|
+
dataStart = __getU32(pointer + 4),
|
|
17127
|
+
length = __dataview.getUint32(pointer + 12, true),
|
|
17128
|
+
values = new Array(length);
|
|
17129
|
+
for (let i = 0; i < length; ++i) values[i] = liftElement(dataStart + (i << align >>> 0));
|
|
17130
|
+
return values;
|
|
17131
|
+
}
|
|
17132
|
+
function __lowerArray(lowerElement, id, align, values) {
|
|
17133
|
+
if (values == null) return 0;
|
|
17134
|
+
const
|
|
17135
|
+
length = values.length,
|
|
17136
|
+
buffer = exports.__pin(exports.__new(length << align, 1)) >>> 0,
|
|
17137
|
+
header = exports.__pin(exports.__new(16, id)) >>> 0;
|
|
17138
|
+
__setU32(header + 0, buffer);
|
|
17139
|
+
__dataview.setUint32(header + 4, buffer, true);
|
|
17140
|
+
__dataview.setUint32(header + 8, length << align, true);
|
|
17141
|
+
__dataview.setUint32(header + 12, length, true);
|
|
17142
|
+
for (let i = 0; i < length; ++i) lowerElement(buffer + (i << align >>> 0), values[i]);
|
|
17143
|
+
exports.__unpin(buffer);
|
|
17144
|
+
exports.__unpin(header);
|
|
17145
|
+
return header;
|
|
17146
|
+
}
|
|
17147
|
+
function __liftTypedArray(constructor, pointer) {
|
|
17148
|
+
if (!pointer) return null;
|
|
17149
|
+
return new constructor(
|
|
17150
|
+
memory.buffer,
|
|
17151
|
+
__getU32(pointer + 4),
|
|
17152
|
+
__dataview.getUint32(pointer + 8, true) / constructor.BYTES_PER_ELEMENT
|
|
17153
|
+
).slice();
|
|
17154
|
+
}
|
|
17155
|
+
function __lowerTypedArray(constructor, id, align, values) {
|
|
17156
|
+
if (values == null) return 0;
|
|
17157
|
+
const
|
|
17158
|
+
length = values.length,
|
|
17159
|
+
buffer = exports.__pin(exports.__new(length << align, 1)) >>> 0,
|
|
17160
|
+
header = exports.__new(12, id) >>> 0;
|
|
17161
|
+
__setU32(header + 0, buffer);
|
|
17162
|
+
__dataview.setUint32(header + 4, buffer, true);
|
|
17163
|
+
__dataview.setUint32(header + 8, length << align, true);
|
|
17164
|
+
new constructor(memory.buffer, buffer, length).set(values);
|
|
17165
|
+
exports.__unpin(buffer);
|
|
17166
|
+
return header;
|
|
17167
|
+
}
|
|
17168
|
+
class Internref extends Number {}
|
|
17169
|
+
const registry = new FinalizationRegistry(__release);
|
|
17170
|
+
function __liftInternref(pointer) {
|
|
17171
|
+
if (!pointer) return null;
|
|
17172
|
+
const sentinel = new Internref(__retain(pointer));
|
|
17173
|
+
registry.register(sentinel, pointer);
|
|
17174
|
+
return sentinel;
|
|
17175
|
+
}
|
|
17176
|
+
function __lowerInternref(value) {
|
|
17177
|
+
if (value == null) return 0;
|
|
17178
|
+
if (value instanceof Internref) return value.valueOf();
|
|
17179
|
+
throw TypeError("internref expected");
|
|
17180
|
+
}
|
|
17181
|
+
const refcounts = new Map();
|
|
17182
|
+
function __retain(pointer) {
|
|
17183
|
+
if (pointer) {
|
|
17184
|
+
const refcount = refcounts.get(pointer);
|
|
17185
|
+
if (refcount) refcounts.set(pointer, refcount + 1);
|
|
17186
|
+
else refcounts.set(exports.__pin(pointer), 1);
|
|
17187
|
+
}
|
|
17188
|
+
return pointer;
|
|
17189
|
+
}
|
|
17190
|
+
function __release(pointer) {
|
|
17191
|
+
if (pointer) {
|
|
17192
|
+
const refcount = refcounts.get(pointer);
|
|
17193
|
+
if (refcount === 1) exports.__unpin(pointer), refcounts.delete(pointer);
|
|
17194
|
+
else if (refcount) refcounts.set(pointer, refcount - 1);
|
|
17195
|
+
else throw Error(`invalid refcount '${refcount}' for reference '${pointer}'`);
|
|
17196
|
+
}
|
|
17197
|
+
}
|
|
17198
|
+
function __notnull() {
|
|
17199
|
+
throw TypeError("value must not be null");
|
|
17200
|
+
}
|
|
17201
|
+
let __dataview = new DataView(memory.buffer);
|
|
17202
|
+
function __setU8(pointer, value) {
|
|
17203
|
+
try {
|
|
17204
|
+
__dataview.setUint8(pointer, value, true);
|
|
17205
|
+
} catch {
|
|
17206
|
+
__dataview = new DataView(memory.buffer);
|
|
17207
|
+
__dataview.setUint8(pointer, value, true);
|
|
16489
17208
|
}
|
|
16490
|
-
}
|
|
16491
|
-
|
|
16492
|
-
|
|
16493
|
-
|
|
16494
|
-
|
|
16495
|
-
|
|
17209
|
+
}
|
|
17210
|
+
function __setU32(pointer, value) {
|
|
17211
|
+
try {
|
|
17212
|
+
__dataview.setUint32(pointer, value, true);
|
|
17213
|
+
} catch {
|
|
17214
|
+
__dataview = new DataView(memory.buffer);
|
|
17215
|
+
__dataview.setUint32(pointer, value, true);
|
|
16496
17216
|
}
|
|
16497
|
-
|
|
16498
|
-
|
|
17217
|
+
}
|
|
17218
|
+
function __setU64(pointer, value) {
|
|
17219
|
+
try {
|
|
17220
|
+
__dataview.setBigUint64(pointer, value, true);
|
|
17221
|
+
} catch {
|
|
17222
|
+
__dataview = new DataView(memory.buffer);
|
|
17223
|
+
__dataview.setBigUint64(pointer, value, true);
|
|
16499
17224
|
}
|
|
16500
|
-
|
|
16501
|
-
|
|
17225
|
+
}
|
|
17226
|
+
function __getU8(pointer) {
|
|
17227
|
+
try {
|
|
17228
|
+
return __dataview.getUint8(pointer, true);
|
|
17229
|
+
} catch {
|
|
17230
|
+
__dataview = new DataView(memory.buffer);
|
|
17231
|
+
return __dataview.getUint8(pointer, true);
|
|
16502
17232
|
}
|
|
16503
|
-
}
|
|
16504
|
-
|
|
16505
|
-
|
|
16506
|
-
|
|
16507
|
-
|
|
16508
|
-
|
|
16509
|
-
|
|
16510
|
-
this.consumedGas = consumedGas;
|
|
16511
|
-
this.status = status;
|
|
16512
|
-
this.memorySlice = memorySlice;
|
|
16513
|
-
check `
|
|
16514
|
-
${(status === null && memorySlice !== null) || (status !== null && memorySlice === null)}
|
|
16515
|
-
'status' and 'memorySlice' must not both be null or both be non-null — exactly one must be provided
|
|
16516
|
-
`;
|
|
17233
|
+
}
|
|
17234
|
+
function __getI32(pointer) {
|
|
17235
|
+
try {
|
|
17236
|
+
return __dataview.getInt32(pointer, true);
|
|
17237
|
+
} catch {
|
|
17238
|
+
__dataview = new DataView(memory.buffer);
|
|
17239
|
+
return __dataview.getInt32(pointer, true);
|
|
16517
17240
|
}
|
|
16518
|
-
|
|
16519
|
-
|
|
17241
|
+
}
|
|
17242
|
+
function __getU32(pointer) {
|
|
17243
|
+
try {
|
|
17244
|
+
return __dataview.getUint32(pointer, true);
|
|
17245
|
+
} catch {
|
|
17246
|
+
__dataview = new DataView(memory.buffer);
|
|
17247
|
+
return __dataview.getUint32(pointer, true);
|
|
16520
17248
|
}
|
|
16521
|
-
|
|
16522
|
-
|
|
17249
|
+
}
|
|
17250
|
+
function __getI64(pointer) {
|
|
17251
|
+
try {
|
|
17252
|
+
return __dataview.getBigInt64(pointer, true);
|
|
17253
|
+
} catch {
|
|
17254
|
+
__dataview = new DataView(memory.buffer);
|
|
17255
|
+
return __dataview.getBigInt64(pointer, true);
|
|
16523
17256
|
}
|
|
16524
|
-
|
|
16525
|
-
|
|
17257
|
+
}
|
|
17258
|
+
function __getU64(pointer) {
|
|
17259
|
+
try {
|
|
17260
|
+
return __dataview.getBigUint64(pointer, true);
|
|
17261
|
+
} catch {
|
|
17262
|
+
__dataview = new DataView(memory.buffer);
|
|
17263
|
+
return __dataview.getBigUint64(pointer, true);
|
|
17264
|
+
}
|
|
17265
|
+
}
|
|
17266
|
+
return adaptedExports;
|
|
17267
|
+
}
|
|
17268
|
+
|
|
17269
|
+
// TODO [ToDr] Temporary solution. We need to inline WASM files for the final build.
|
|
17270
|
+
const wasmPath = fileURLToPath(new URL(import.meta.resolve("@fluffylabs/anan-as/release-mini.wasm"), import.meta.url));
|
|
17271
|
+
const wasmBuffer = readFileSync(wasmPath);
|
|
17272
|
+
// Max u32 value
|
|
17273
|
+
const INF_STEPS = 2 ** 32 - 1;
|
|
17274
|
+
class AnanasRegisters {
|
|
17275
|
+
instance;
|
|
17276
|
+
constructor(instance) {
|
|
17277
|
+
this.instance = instance;
|
|
17278
|
+
}
|
|
17279
|
+
getAllEncoded() {
|
|
17280
|
+
return this.instance.getRegisters();
|
|
17281
|
+
}
|
|
17282
|
+
setAllEncoded(bytes) {
|
|
17283
|
+
check `${bytes.length === NO_OF_REGISTERS$1 * REGISTER_BYTE_SIZE}
|
|
17284
|
+
Incorrect size of input registers. Got: ${bytes.length},
|
|
17285
|
+
need: ${NO_OF_REGISTERS$1 * REGISTER_BYTE_SIZE}`;
|
|
17286
|
+
this.instance.setRegisters(lowerBytes(bytes));
|
|
16526
17287
|
}
|
|
16527
|
-
|
|
16528
|
-
|
|
17288
|
+
getAllU64() {
|
|
17289
|
+
const bytes = this.getAllEncoded();
|
|
17290
|
+
return new BigUint64Array(bytes.buffer, bytes.byteOffset);
|
|
16529
17291
|
}
|
|
16530
17292
|
}
|
|
16531
|
-
class
|
|
16532
|
-
|
|
16533
|
-
|
|
16534
|
-
|
|
16535
|
-
this.pvmInstanceManager = pvmInstanceManager;
|
|
16536
|
-
this.hostCalls = hostCalls;
|
|
17293
|
+
class AnanasMemory {
|
|
17294
|
+
instance;
|
|
17295
|
+
constructor(instance) {
|
|
17296
|
+
this.instance = instance;
|
|
16537
17297
|
}
|
|
16538
|
-
|
|
16539
|
-
|
|
16540
|
-
|
|
16541
|
-
return ReturnValue.fromStatus(gasConsumed, status);
|
|
16542
|
-
}
|
|
16543
|
-
if (status === Status.HALT) {
|
|
16544
|
-
const memory = pvmInstance.getMemory();
|
|
16545
|
-
const regs = pvmInstance.getRegisters();
|
|
16546
|
-
const maybeAddress = regs.getLowerU32(7);
|
|
16547
|
-
const maybeLength = regs.getLowerU32(8);
|
|
16548
|
-
const result = safeAllocUint8Array(maybeLength);
|
|
16549
|
-
const startAddress = tryAsMemoryIndex(maybeAddress);
|
|
16550
|
-
const loadResult = memory.loadInto(result, startAddress);
|
|
16551
|
-
if (loadResult.isError) {
|
|
16552
|
-
return ReturnValue.fromMemorySlice(gasConsumed, new Uint8Array());
|
|
16553
|
-
}
|
|
16554
|
-
return ReturnValue.fromMemorySlice(gasConsumed, result);
|
|
17298
|
+
store(address, bytes) {
|
|
17299
|
+
if (this.instance.setMemory(address, bytes)) {
|
|
17300
|
+
return Result$1.ok(OK);
|
|
16555
17301
|
}
|
|
16556
|
-
return
|
|
17302
|
+
return Result$1.error({ address: getPageStartAddress(address) }, () => "Memory is unwritable!");
|
|
16557
17303
|
}
|
|
16558
|
-
|
|
16559
|
-
|
|
16560
|
-
|
|
16561
|
-
let status = pvmInstance.getStatus();
|
|
16562
|
-
if (status !== Status.HOST) {
|
|
16563
|
-
return this.getReturnValue(status, pvmInstance);
|
|
16564
|
-
}
|
|
16565
|
-
check `
|
|
16566
|
-
${pvmInstance.getExitParam() !== null}
|
|
16567
|
-
"We know that the exit param is not null, because the status is 'Status.HOST'
|
|
16568
|
-
`;
|
|
16569
|
-
const hostCallIndex = pvmInstance.getExitParam() ?? -1;
|
|
16570
|
-
const gas = pvmInstance.getGasCounter();
|
|
16571
|
-
const regs = new HostCallRegisters(pvmInstance.getRegisters());
|
|
16572
|
-
const memory = new HostCallMemory(pvmInstance.getMemory());
|
|
16573
|
-
const index = tryAsHostCallIndex(hostCallIndex);
|
|
16574
|
-
const hostCall = this.hostCalls.get(index);
|
|
16575
|
-
const gasBefore = gas.get();
|
|
16576
|
-
// NOTE: `basicGasCost(regs)` function is for compatibility reasons: pre GP 0.7.2
|
|
16577
|
-
const basicGasCost = typeof hostCall.basicGasCost === "number" ? hostCall.basicGasCost : hostCall.basicGasCost(regs);
|
|
16578
|
-
const underflow = gas.sub(basicGasCost);
|
|
16579
|
-
const pcLog = `[PC: ${pvmInstance.getPC()}]`;
|
|
16580
|
-
if (underflow) {
|
|
16581
|
-
this.hostCalls.traceHostCall(`${pcLog} OOG`, index, hostCall, regs, gas.get());
|
|
16582
|
-
return ReturnValue.fromStatus(pvmInstance.getGasConsumed(), Status.OOG);
|
|
16583
|
-
}
|
|
16584
|
-
this.hostCalls.traceHostCall(`${pcLog} Invoking`, index, hostCall, regs, gasBefore);
|
|
16585
|
-
const result = await hostCall.execute(gas, regs, memory);
|
|
16586
|
-
this.hostCalls.traceHostCall(result === undefined ? `${pcLog} Result` : `${pcLog} Status(${PvmExecution[result]})`, index, hostCall, regs, gas.get());
|
|
16587
|
-
if (result === PvmExecution.Halt) {
|
|
16588
|
-
status = Status.HALT;
|
|
16589
|
-
return this.getReturnValue(status, pvmInstance);
|
|
16590
|
-
}
|
|
16591
|
-
if (result === PvmExecution.Panic) {
|
|
16592
|
-
status = Status.PANIC;
|
|
16593
|
-
return this.getReturnValue(status, pvmInstance);
|
|
16594
|
-
}
|
|
16595
|
-
if (result === PvmExecution.OOG) {
|
|
16596
|
-
status = Status.OOG;
|
|
16597
|
-
return this.getReturnValue(status, pvmInstance);
|
|
16598
|
-
}
|
|
16599
|
-
if (result === undefined) {
|
|
16600
|
-
pvmInstance.runProgram();
|
|
16601
|
-
status = pvmInstance.getStatus();
|
|
16602
|
-
continue;
|
|
16603
|
-
}
|
|
16604
|
-
assertNever(result);
|
|
17304
|
+
read(address, result) {
|
|
17305
|
+
if (result.length === 0) {
|
|
17306
|
+
return Result$1.ok(OK);
|
|
16605
17307
|
}
|
|
17308
|
+
const newResult = this.instance.getMemory(address, result.length);
|
|
17309
|
+
if (newResult === null) {
|
|
17310
|
+
return Result$1.error({ address: getPageStartAddress(address) }, () => "Memory is inaccessible!");
|
|
17311
|
+
}
|
|
17312
|
+
result.set(newResult, 0);
|
|
17313
|
+
return Result$1.ok(OK);
|
|
16606
17314
|
}
|
|
16607
|
-
|
|
16608
|
-
|
|
16609
|
-
|
|
16610
|
-
|
|
16611
|
-
|
|
17315
|
+
}
|
|
17316
|
+
class AnanasGasCounter {
|
|
17317
|
+
instance;
|
|
17318
|
+
initialGas = tryAsGas(0n);
|
|
17319
|
+
constructor(instance) {
|
|
17320
|
+
this.instance = instance;
|
|
17321
|
+
}
|
|
17322
|
+
get() {
|
|
17323
|
+
return tryAsGas(this.instance.getGasLeft());
|
|
17324
|
+
}
|
|
17325
|
+
set(g) {
|
|
17326
|
+
this.instance.setGasLeft(BigInt(g));
|
|
17327
|
+
}
|
|
17328
|
+
sub(g) {
|
|
17329
|
+
const result = this.instance.getGasLeft() - BigInt(g);
|
|
17330
|
+
if (result >= 0n) {
|
|
17331
|
+
this.instance.setGasLeft(result);
|
|
17332
|
+
return false;
|
|
16612
17333
|
}
|
|
16613
|
-
|
|
16614
|
-
|
|
17334
|
+
this.instance.setGasLeft(0n);
|
|
17335
|
+
return true;
|
|
17336
|
+
}
|
|
17337
|
+
used() {
|
|
17338
|
+
const gasConsumed = BigInt(this.initialGas) - BigInt(this.get());
|
|
17339
|
+
if (gasConsumed < 0) {
|
|
17340
|
+
return this.initialGas;
|
|
16615
17341
|
}
|
|
17342
|
+
return tryAsBigGas(gasConsumed);
|
|
16616
17343
|
}
|
|
16617
17344
|
}
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
|
|
16624
|
-
|
|
16625
|
-
this.
|
|
16626
|
-
|
|
16627
|
-
|
|
16628
|
-
|
|
17345
|
+
class AnanasInterpreter {
|
|
17346
|
+
instance;
|
|
17347
|
+
registers;
|
|
17348
|
+
memory;
|
|
17349
|
+
gas;
|
|
17350
|
+
constructor(instance) {
|
|
17351
|
+
this.instance = instance;
|
|
17352
|
+
this.registers = new AnanasRegisters(instance);
|
|
17353
|
+
this.memory = new AnanasMemory(instance);
|
|
17354
|
+
this.gas = new AnanasGasCounter(instance);
|
|
17355
|
+
}
|
|
17356
|
+
static async new() {
|
|
17357
|
+
const wasmModule = await WebAssembly.compile(wasmBuffer);
|
|
17358
|
+
const instance = await instantiate(wasmModule, {
|
|
17359
|
+
env: {
|
|
17360
|
+
abort: () => {
|
|
17361
|
+
throw new Error("Abort called from WASM");
|
|
17362
|
+
},
|
|
17363
|
+
},
|
|
17364
|
+
});
|
|
17365
|
+
return new AnanasInterpreter(instance);
|
|
17366
|
+
}
|
|
17367
|
+
resetJam(program, args, pc, gas) {
|
|
17368
|
+
const programArr = lowerBytes(program);
|
|
17369
|
+
const argsArr = lowerBytes(args);
|
|
17370
|
+
this.gas.initialGas = gas;
|
|
17371
|
+
this.instance.resetJAM(programArr, pc, BigInt(gas), argsArr, true);
|
|
17372
|
+
}
|
|
17373
|
+
resetGeneric(program, _pc, gas) {
|
|
17374
|
+
const programArr = lowerBytes(program);
|
|
17375
|
+
const emptyRegisters = Array(13 * 8).fill(0);
|
|
17376
|
+
const pageMap = new Uint8Array();
|
|
17377
|
+
const chunks = new Uint8Array();
|
|
17378
|
+
this.gas.initialGas = gas;
|
|
17379
|
+
this.instance.resetGenericWithMemory(programArr, emptyRegisters, pageMap, chunks, BigInt(gas), false);
|
|
17380
|
+
}
|
|
17381
|
+
nextStep() {
|
|
17382
|
+
return this.instance.nextStep();
|
|
17383
|
+
}
|
|
17384
|
+
runProgram() {
|
|
17385
|
+
// NOTE Setting max value u32 in nNextSteps making ananas running until finished
|
|
17386
|
+
// without comming back and forth between JS <-> WASM
|
|
17387
|
+
while (this.instance.nSteps(INF_STEPS)) { }
|
|
17388
|
+
}
|
|
17389
|
+
getStatus() {
|
|
17390
|
+
const status = this.instance.getStatus();
|
|
17391
|
+
if (status < 0) {
|
|
17392
|
+
return Status.OK;
|
|
16629
17393
|
}
|
|
17394
|
+
check `${Status[status] !== undefined} Invalid status returned: ${status}`;
|
|
17395
|
+
return status;
|
|
16630
17396
|
}
|
|
16631
|
-
|
|
16632
|
-
|
|
16633
|
-
return this.hostCalls.get(hostCallIndex) ?? this.missing;
|
|
17397
|
+
getPC() {
|
|
17398
|
+
return this.instance.getProgramCounter();
|
|
16634
17399
|
}
|
|
16635
|
-
|
|
16636
|
-
|
|
16637
|
-
|
|
16638
|
-
|
|
16639
|
-
|
|
16640
|
-
|
|
16641
|
-
|
|
16642
|
-
|
|
16643
|
-
|
|
16644
|
-
})
|
|
16645
|
-
.join(", ");
|
|
16646
|
-
logger.insane `[${currentServiceId}] ${context} ${name}${requested}. Gas: ${gas}. Regs: ${registerValues}.`;
|
|
17400
|
+
getExitParam() {
|
|
17401
|
+
return tryAsU32(this.instance.getExitArg());
|
|
17402
|
+
}
|
|
17403
|
+
}
|
|
17404
|
+
/** Convert `Uint8Array` to `number[]` */
|
|
17405
|
+
function lowerBytes(data) {
|
|
17406
|
+
const r = new Array(data.length);
|
|
17407
|
+
for (let i = 0; i < data.length; i++) {
|
|
17408
|
+
r[i] = data[i];
|
|
16647
17409
|
}
|
|
17410
|
+
return r;
|
|
16648
17411
|
}
|
|
16649
17412
|
|
|
17413
|
+
// TODO [MaSo] Delete this & also make host calls independent from intepreters.
|
|
16650
17414
|
class InterpreterInstanceManager {
|
|
16651
|
-
instances
|
|
17415
|
+
instances;
|
|
16652
17416
|
waitingQueue = [];
|
|
16653
|
-
constructor(
|
|
16654
|
-
|
|
16655
|
-
|
|
16656
|
-
|
|
16657
|
-
|
|
17417
|
+
constructor(instances) {
|
|
17418
|
+
this.instances = instances;
|
|
17419
|
+
}
|
|
17420
|
+
static async new(interpreter) {
|
|
17421
|
+
const instances = [];
|
|
17422
|
+
switch (interpreter) {
|
|
17423
|
+
case PvmBackend.BuiltIn:
|
|
17424
|
+
instances.push(new Interpreter({
|
|
17425
|
+
useSbrkGas: false,
|
|
17426
|
+
}));
|
|
17427
|
+
break;
|
|
17428
|
+
case PvmBackend.Ananas:
|
|
17429
|
+
instances.push(await AnanasInterpreter.new());
|
|
17430
|
+
break;
|
|
17431
|
+
default:
|
|
17432
|
+
assertNever(interpreter);
|
|
16658
17433
|
}
|
|
17434
|
+
return new InterpreterInstanceManager(instances);
|
|
16659
17435
|
}
|
|
16660
17436
|
async getInstance() {
|
|
16661
17437
|
const instance = this.instances.pop();
|
|
@@ -16675,7 +17451,7 @@ class InterpreterInstanceManager {
|
|
|
16675
17451
|
}
|
|
16676
17452
|
}
|
|
16677
17453
|
|
|
16678
|
-
var index$
|
|
17454
|
+
var index$4 = /*#__PURE__*/Object.freeze({
|
|
16679
17455
|
__proto__: null,
|
|
16680
17456
|
HostCallMemory: HostCallMemory,
|
|
16681
17457
|
HostCallRegisters: HostCallRegisters,
|
|
@@ -16687,194 +17463,6 @@ var index$6 = /*#__PURE__*/Object.freeze({
|
|
|
16687
17463
|
tryAsHostCallIndex: tryAsHostCallIndex
|
|
16688
17464
|
});
|
|
16689
17465
|
|
|
16690
|
-
// GP reference: https://graypaper.fluffylabs.dev/#/7e6ff6a/2d32002d3200?v=0.6.7
|
|
16691
|
-
const PAGE_SIZE = 2 ** 12; // Z_P from GP
|
|
16692
|
-
const SEGMENT_SIZE = 2 ** 16; // Z_Z from GP
|
|
16693
|
-
const DATA_LEGNTH = 2 ** 24; // Z_I from GP
|
|
16694
|
-
const STACK_SEGMENT = 0xfe_fe_00_00; // 2^32 - 2Z_Z - Z_I from GP
|
|
16695
|
-
const ARGS_SEGMENT = 0xfe_ff_00_00; // 2^32 - Z_Z - Z_I from GP
|
|
16696
|
-
const LAST_PAGE = 0xff_ff_00_00;
|
|
16697
|
-
|
|
16698
|
-
// GP reference: https://graypaper.fluffylabs.dev/#/579bd12/2bd2022bd202
|
|
16699
|
-
function alignToSegmentSize(size) {
|
|
16700
|
-
// Q(x) from GP
|
|
16701
|
-
return SEGMENT_SIZE * Math.ceil(size / SEGMENT_SIZE);
|
|
16702
|
-
}
|
|
16703
|
-
function alignToPageSize(size) {
|
|
16704
|
-
// P(x) from GP
|
|
16705
|
-
return PAGE_SIZE * Math.ceil(size / PAGE_SIZE);
|
|
16706
|
-
}
|
|
16707
|
-
|
|
16708
|
-
const NO_OF_REGISTERS = 13;
|
|
16709
|
-
class MemorySegment extends WithDebug {
|
|
16710
|
-
start;
|
|
16711
|
-
end;
|
|
16712
|
-
data;
|
|
16713
|
-
static from({ start, end, data }) {
|
|
16714
|
-
return new MemorySegment(start, end, data);
|
|
16715
|
-
}
|
|
16716
|
-
constructor(start, end, data) {
|
|
16717
|
-
super();
|
|
16718
|
-
this.start = start;
|
|
16719
|
-
this.end = end;
|
|
16720
|
-
this.data = data;
|
|
16721
|
-
}
|
|
16722
|
-
}
|
|
16723
|
-
class SpiMemory extends WithDebug {
|
|
16724
|
-
readable;
|
|
16725
|
-
writeable;
|
|
16726
|
-
sbrkIndex;
|
|
16727
|
-
heapEnd;
|
|
16728
|
-
constructor(readable, writeable, sbrkIndex, heapEnd) {
|
|
16729
|
-
super();
|
|
16730
|
-
this.readable = readable;
|
|
16731
|
-
this.writeable = writeable;
|
|
16732
|
-
this.sbrkIndex = sbrkIndex;
|
|
16733
|
-
this.heapEnd = heapEnd;
|
|
16734
|
-
}
|
|
16735
|
-
}
|
|
16736
|
-
class SpiProgram extends WithDebug {
|
|
16737
|
-
code;
|
|
16738
|
-
memory;
|
|
16739
|
-
registers;
|
|
16740
|
-
constructor(code, memory, registers) {
|
|
16741
|
-
super();
|
|
16742
|
-
this.code = code;
|
|
16743
|
-
this.memory = memory;
|
|
16744
|
-
this.registers = registers;
|
|
16745
|
-
}
|
|
16746
|
-
}
|
|
16747
|
-
/**
|
|
16748
|
-
* program = E_3(|o|) ++ E_3(|w|) ++ E_2(z) ++ E_3(s) ++ o ++ w ++ E_4(|c|) ++ c
|
|
16749
|
-
*
|
|
16750
|
-
* E_n - little endian encoding, n - length
|
|
16751
|
-
* o - initial read only data
|
|
16752
|
-
* w - initial heap
|
|
16753
|
-
* z - heap pages filled with zeros
|
|
16754
|
-
* s - stack size
|
|
16755
|
-
* c - program code
|
|
16756
|
-
*
|
|
16757
|
-
* https://graypaper.fluffylabs.dev/#/579bd12/2b92022b9202
|
|
16758
|
-
*/
|
|
16759
|
-
function decodeStandardProgram(program, args) {
|
|
16760
|
-
const decoder = Decoder.fromBlob(program);
|
|
16761
|
-
const oLength = decoder.u24();
|
|
16762
|
-
const wLength = decoder.u24();
|
|
16763
|
-
check `${args.length <= DATA_LEGNTH} Incorrect arguments length`;
|
|
16764
|
-
check `${oLength <= DATA_LEGNTH} Incorrect readonly segment length`;
|
|
16765
|
-
const readOnlyLength = oLength;
|
|
16766
|
-
check `${wLength <= DATA_LEGNTH} Incorrect heap segment length`;
|
|
16767
|
-
const heapLength = wLength;
|
|
16768
|
-
const noOfHeapZerosPages = decoder.u16();
|
|
16769
|
-
const stackSize = decoder.u24();
|
|
16770
|
-
const readOnlyMemory = decoder.bytes(readOnlyLength).raw;
|
|
16771
|
-
const initialHeap = decoder.bytes(heapLength).raw;
|
|
16772
|
-
const codeLength = decoder.u32();
|
|
16773
|
-
const code = decoder.bytes(codeLength).raw;
|
|
16774
|
-
decoder.finish();
|
|
16775
|
-
const readonlyDataStart = SEGMENT_SIZE;
|
|
16776
|
-
const readonlyDataEnd = SEGMENT_SIZE + alignToPageSize(readOnlyLength);
|
|
16777
|
-
const heapDataStart = 2 * SEGMENT_SIZE + alignToSegmentSize(readOnlyLength);
|
|
16778
|
-
const heapDataEnd = heapDataStart + alignToPageSize(heapLength);
|
|
16779
|
-
const heapZerosEnd = heapDataStart + alignToPageSize(heapLength) + noOfHeapZerosPages * PAGE_SIZE;
|
|
16780
|
-
const stackStart = STACK_SEGMENT - alignToPageSize(stackSize);
|
|
16781
|
-
const stackEnd = STACK_SEGMENT;
|
|
16782
|
-
const argsStart = ARGS_SEGMENT;
|
|
16783
|
-
const argsEnd = argsStart + alignToPageSize(args.length);
|
|
16784
|
-
const argsZerosEnd = argsEnd + alignToPageSize(args.length);
|
|
16785
|
-
function nonEmpty(s) {
|
|
16786
|
-
return s !== false;
|
|
16787
|
-
}
|
|
16788
|
-
const readableMemory = [
|
|
16789
|
-
readOnlyLength > 0 && getMemorySegment(readonlyDataStart, readonlyDataEnd, readOnlyMemory),
|
|
16790
|
-
args.length > 0 && getMemorySegment(argsStart, argsEnd, args),
|
|
16791
|
-
argsEnd < argsZerosEnd && getMemorySegment(argsEnd, argsZerosEnd),
|
|
16792
|
-
].filter(nonEmpty);
|
|
16793
|
-
const writeableMemory = [
|
|
16794
|
-
heapLength > 0 && getMemorySegment(heapDataStart, heapDataEnd, initialHeap),
|
|
16795
|
-
heapDataEnd < heapZerosEnd && getMemorySegment(heapDataEnd, heapZerosEnd),
|
|
16796
|
-
stackStart < stackEnd && getMemorySegment(stackStart, stackEnd),
|
|
16797
|
-
].filter(nonEmpty);
|
|
16798
|
-
return new SpiProgram(code, new SpiMemory(readableMemory, writeableMemory, heapZerosEnd, stackStart), getRegisters(args.length));
|
|
16799
|
-
}
|
|
16800
|
-
function getMemorySegment(start, end, data = null) {
|
|
16801
|
-
return new MemorySegment(start, end, data);
|
|
16802
|
-
}
|
|
16803
|
-
function getRegisters(argsLength) {
|
|
16804
|
-
const regs = new BigUint64Array(NO_OF_REGISTERS);
|
|
16805
|
-
// GP reference: https://graypaper.fluffylabs.dev/#/579bd12/2c7c012cb101
|
|
16806
|
-
regs[0] = BigInt(LAST_PAGE);
|
|
16807
|
-
regs[1] = BigInt(STACK_SEGMENT);
|
|
16808
|
-
regs[7] = BigInt(ARGS_SEGMENT);
|
|
16809
|
-
regs[8] = BigInt(argsLength);
|
|
16810
|
-
return regs;
|
|
16811
|
-
}
|
|
16812
|
-
|
|
16813
|
-
var index$5 = /*#__PURE__*/Object.freeze({
|
|
16814
|
-
__proto__: null,
|
|
16815
|
-
MemorySegment: MemorySegment,
|
|
16816
|
-
SpiMemory: SpiMemory,
|
|
16817
|
-
SpiProgram: SpiProgram,
|
|
16818
|
-
decodeStandardProgram: decodeStandardProgram
|
|
16819
|
-
});
|
|
16820
|
-
|
|
16821
|
-
class Program {
|
|
16822
|
-
code;
|
|
16823
|
-
registers;
|
|
16824
|
-
memory;
|
|
16825
|
-
metadata;
|
|
16826
|
-
static fromSpi(blob, args, hasMetadata) {
|
|
16827
|
-
const { code: spiCode, metadata } = hasMetadata ? extractCodeAndMetadata(blob) : { code: blob };
|
|
16828
|
-
const { code, memory: rawMemory, registers } = decodeStandardProgram(spiCode, args);
|
|
16829
|
-
const regs = new Registers();
|
|
16830
|
-
regs.copyFrom(registers);
|
|
16831
|
-
const memoryBuilder = new MemoryBuilder();
|
|
16832
|
-
for (const { start, end, data } of rawMemory.readable) {
|
|
16833
|
-
const startIndex = tryAsMemoryIndex(start);
|
|
16834
|
-
const endIndex = tryAsMemoryIndex(end);
|
|
16835
|
-
memoryBuilder.setReadablePages(startIndex, endIndex, data ?? new Uint8Array());
|
|
16836
|
-
}
|
|
16837
|
-
for (const { start, end, data } of rawMemory.writeable) {
|
|
16838
|
-
const startIndex = tryAsMemoryIndex(start);
|
|
16839
|
-
const endIndex = tryAsMemoryIndex(end);
|
|
16840
|
-
memoryBuilder.setWriteablePages(startIndex, endIndex, data ?? new Uint8Array());
|
|
16841
|
-
}
|
|
16842
|
-
const heapStart = tryAsMemoryIndex(rawMemory.sbrkIndex);
|
|
16843
|
-
const heapEnd = tryAsSbrkIndex(rawMemory.heapEnd);
|
|
16844
|
-
const memory = memoryBuilder.finalize(heapStart, heapEnd);
|
|
16845
|
-
return new Program(code, regs, memory, metadata);
|
|
16846
|
-
}
|
|
16847
|
-
static fromGeneric(blob, hasMetadata) {
|
|
16848
|
-
const { code, metadata } = hasMetadata ? extractCodeAndMetadata(blob) : { code: blob };
|
|
16849
|
-
const regs = new Registers();
|
|
16850
|
-
const memory = new Memory();
|
|
16851
|
-
return new Program(code, regs, memory, metadata);
|
|
16852
|
-
}
|
|
16853
|
-
constructor(code, registers, memory, metadata = new Uint8Array()) {
|
|
16854
|
-
this.code = code;
|
|
16855
|
-
this.registers = registers;
|
|
16856
|
-
this.memory = memory;
|
|
16857
|
-
this.metadata = metadata;
|
|
16858
|
-
}
|
|
16859
|
-
}
|
|
16860
|
-
/**
|
|
16861
|
-
* A function that splits preimage into metadata and code.
|
|
16862
|
-
*
|
|
16863
|
-
* https://graypaper.fluffylabs.dev/#/cc517d7/109a01109a01?v=0.6.5
|
|
16864
|
-
*/
|
|
16865
|
-
function extractCodeAndMetadata(blobWithMetadata) {
|
|
16866
|
-
const decoder = Decoder.fromBlob(blobWithMetadata);
|
|
16867
|
-
const metadata = decoder.bytesBlob().raw;
|
|
16868
|
-
const code = decoder.remainingBytes().raw;
|
|
16869
|
-
return { metadata, code };
|
|
16870
|
-
}
|
|
16871
|
-
|
|
16872
|
-
var index$4 = /*#__PURE__*/Object.freeze({
|
|
16873
|
-
__proto__: null,
|
|
16874
|
-
Program: Program,
|
|
16875
|
-
extractCodeAndMetadata: extractCodeAndMetadata
|
|
16876
|
-
});
|
|
16877
|
-
|
|
16878
17466
|
class DebuggerAdapter {
|
|
16879
17467
|
pvm;
|
|
16880
17468
|
constructor(useSbrkGas = false) {
|
|
@@ -16885,10 +17473,10 @@ class DebuggerAdapter {
|
|
|
16885
17473
|
return this.pvm;
|
|
16886
17474
|
}
|
|
16887
17475
|
resetGeneric(rawProgram, flatRegisters, initialGas) {
|
|
16888
|
-
this.pvm.
|
|
17476
|
+
this.pvm.resetGeneric(rawProgram, 0, tryAsGas(initialGas), new Registers(flatRegisters));
|
|
16889
17477
|
}
|
|
16890
17478
|
reset(rawProgram, pc, gas, maybeRegisters, maybeMemory) {
|
|
16891
|
-
this.pvm.
|
|
17479
|
+
this.pvm.resetGeneric(rawProgram, pc, tryAsGas(gas), maybeRegisters, maybeMemory);
|
|
16892
17480
|
}
|
|
16893
17481
|
getPageDump(pageNumber) {
|
|
16894
17482
|
const page = this.pvm.getMemoryPage(pageNumber);
|
|
@@ -16906,7 +17494,7 @@ class DebuggerAdapter {
|
|
|
16906
17494
|
return fullPage;
|
|
16907
17495
|
}
|
|
16908
17496
|
setMemory(address, value) {
|
|
16909
|
-
this.pvm.
|
|
17497
|
+
this.pvm.memory.storeFrom(tryAsMemoryIndex(address), value);
|
|
16910
17498
|
}
|
|
16911
17499
|
getExitArg() {
|
|
16912
17500
|
return this.pvm.getExitParam() ?? 0;
|
|
@@ -16928,10 +17516,10 @@ class DebuggerAdapter {
|
|
|
16928
17516
|
return true;
|
|
16929
17517
|
}
|
|
16930
17518
|
getRegisters() {
|
|
16931
|
-
return this.pvm.
|
|
17519
|
+
return this.pvm.registers.getAllU64();
|
|
16932
17520
|
}
|
|
16933
17521
|
setRegisters(registers) {
|
|
16934
|
-
this.pvm.
|
|
17522
|
+
this.pvm.registers.copyFrom(new Registers(registers));
|
|
16935
17523
|
}
|
|
16936
17524
|
getProgramCounter() {
|
|
16937
17525
|
return this.pvm.getPC();
|
|
@@ -16940,10 +17528,10 @@ class DebuggerAdapter {
|
|
|
16940
17528
|
this.pvm.setNextPC(nextPc);
|
|
16941
17529
|
}
|
|
16942
17530
|
getGasLeft() {
|
|
16943
|
-
return BigInt(this.pvm.
|
|
17531
|
+
return BigInt(this.pvm.gas.get());
|
|
16944
17532
|
}
|
|
16945
17533
|
setGasLeft(gas) {
|
|
16946
|
-
this.pvm.
|
|
17534
|
+
this.pvm.gas.set(tryAsGas(gas));
|
|
16947
17535
|
}
|
|
16948
17536
|
}
|
|
16949
17537
|
|
|
@@ -17002,13 +17590,14 @@ var index$3 = /*#__PURE__*/Object.freeze({
|
|
|
17002
17590
|
clampU64ToU32: clampU64ToU32,
|
|
17003
17591
|
createResults: createResults,
|
|
17004
17592
|
decodeStandardProgram: decodeStandardProgram,
|
|
17593
|
+
emptyRegistersBuffer: emptyRegistersBuffer,
|
|
17005
17594
|
extractCodeAndMetadata: extractCodeAndMetadata,
|
|
17006
17595
|
getServiceId: getServiceId,
|
|
17007
17596
|
getServiceIdOrCurrent: getServiceIdOrCurrent,
|
|
17008
17597
|
hash: index$o,
|
|
17009
17598
|
inspect: inspect,
|
|
17010
17599
|
instructionArgumentTypeMap: instructionArgumentTypeMap,
|
|
17011
|
-
interpreter: index$
|
|
17600
|
+
interpreter: index$5,
|
|
17012
17601
|
isBrowser: isBrowser,
|
|
17013
17602
|
measure: measure,
|
|
17014
17603
|
numbers: index$r,
|
|
@@ -17615,4 +18204,4 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
17615
18204
|
TransitionHasher: TransitionHasher
|
|
17616
18205
|
});
|
|
17617
18206
|
|
|
17618
|
-
export { index$l as block, index$j as block_json, index$s as bytes, index$q as codec, index$n as collections, index$m as config, index$h as config_node, index$p as crypto, index$d as database, index$c as erasure_coding, index$a as fuzz_proto, index$o as hash, index$9 as jam_host_calls, index$k as json_parser, index$i as logger, index$8 as mmr, index$r as numbers, index$t as ordering, index$3 as pvm, index$
|
|
18207
|
+
export { index$l as block, index$j as block_json, index$s as bytes, index$q as codec, index$n as collections, index$m as config, index$h as config_node, index$p as crypto, index$d as database, index$c as erasure_coding, index$a as fuzz_proto, index$o as hash, index$9 as jam_host_calls, index$k as json_parser, index$i as logger, index$8 as mmr, index$r as numbers, index$t as ordering, index$3 as pvm, index$4 as pvm_host_calls, index$5 as pvm_interpreter, index$6 as pvm_program, index$7 as pvm_spi_decoder, index$2 as shuffling, index$g as state, index$1 as state_json, index$e as state_merkleization, index as transition, index$f as trie, index$u as utils };
|