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