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