Skip to content

Commit

Permalink
Fix immediate limit.
Browse files Browse the repository at this point in the history
  • Loading branch information
tomusdrw committed Jan 2, 2025
1 parent 6b48c83 commit 2bc923d
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 39 deletions.
6 changes: 4 additions & 2 deletions assembly/api-generic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ export function getAssembly(p: Program): string {
v += `(${instruction})`;

const skipBytes = p.mask.bytesToNextInstruction(i);
const args = decodeArguments(iData.kind, p.code.subarray(i + 1));
const args = decodeArguments(iData.kind, p.code.subarray(i + 1), skipBytes);
const argsArray = [args.a, args.b, args.c, args.d];
const relevantArgs = RELEVANT_ARGS[iData.kind];
for (let i = 0; i < relevantArgs; i++) {
v += ` ${argsArray[i]}, `;
}
i += skipBytes;
console.log(`${v}, nextPC: ${i}`);
}
return v;
}
Expand Down Expand Up @@ -94,9 +95,10 @@ export function runVm(input: VmInput, logs: boolean = false): VmOutput {
if (logs) {
const instruction = int.pc < u32(int.program.code.length) ? int.program.code[int.pc] : 0;
const iData = instruction >= <u8>INSTRUCTIONS.length ? MISSING_INSTRUCTION : INSTRUCTIONS[instruction];
const skipBytes = p.mask.bytesToNextInstruction(int.pc);
const name = changetype<string>(iData.namePtr);
console.log(`INSTRUCTION = ${name} (${instruction})`);
const args = resolveArguments(iData.kind, int.program.code.subarray(int.pc + 1), int.registers);
const args = resolveArguments(iData.kind, int.program.code.subarray(int.pc + 1), skipBytes, int.registers);
if (args !== null) {
console.log(`ARGUMENTS:
${args.a} (${args.decoded.a}) = 0x${u64(args.a).toString(16)},
Expand Down
57 changes: 29 additions & 28 deletions assembly/arguments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,81 +36,81 @@ function asArgs(a: u32, b: u32, c: u32, d: u32): Args {
return x;
}

type ArgsDecoder = (data: Uint8Array) => Args;
type ArgsDecoder = (data: Uint8Array, immLimit: u32) => Args;

function twoImm(data: Uint8Array): Args {
function twoImm(data: Uint8Array, lim: u32): Args {
const n = nibbles(data[0]);
const split = <i32>Math.min(4, n.low) + 1;
const first = decodeI32(data.subarray(1, split));
const second = decodeI32(data.subarray(split));
const first = decodeI32(data, 1, split);
const second = decodeI32(data, split, lim);
return asArgs(first, second, 0, 0);
}

export const DECODERS: ArgsDecoder[] = [
// DECODERS[Arguments.Zero] =
(_) => {
(_d, _l) => {
return asArgs(0, 0, 0, 0);
},
// DECODERS[Arguments.OneImm] =
(data: Uint8Array) => {
return asArgs(decodeI32(data), 0, 0, 0);
(data, lim) => {
return asArgs(decodeI32(data, 0, lim), 0, 0, 0);
},
// DECODERS[Arguments.TwoImm] =
(data: Uint8Array) => twoImm(data),
(data, lim) => twoImm(data, lim),
// DECODERS[Arguments.OneOff] =
(data: Uint8Array) => {
return asArgs(decodeI32(data), 0, 0, 0);
(data, lim) => {
return asArgs(decodeI32(data, 0, lim), 0, 0, 0);
},
// DECODERS[Arguments.OneRegOneImm] =
(data: Uint8Array) => {
return asArgs(nibbles(data[0]).low, decodeI32(data.subarray(1)), 0, 0);
(data, lim) => {
return asArgs(nibbles(data[0]).low, decodeI32(data, 1, lim), 0, 0);
},
// DECODERS[Arguments.OneRegOneExtImm] =
(data: Uint8Array) => {
(data, _lim) => {
const a = nibbles(data[0]).low;
const b = decodeU32(data.subarray(1));
const c = decodeU32(data.subarray(5));
return asArgs(a, b, c, 0);
},
//DECODERS[Arguments.OneRegTwoImm] =
(data: Uint8Array) => {
(data, lim) => {
const n = nibbles(data[0]);
const split = <i32>Math.min(4, n.hig) + 1;
const immA = decodeI32(data.subarray(1, split));
const immB = decodeI32(data.subarray(split));
const immA = decodeI32(data, 1, split);
const immB = decodeI32(data, split, lim);
return asArgs(n.low, immA, immB, 0);
},
// DECODERS[Arguments.OneRegOneImmOneOff] =
(data: Uint8Array) => {
(data, lim) => {
const n = nibbles(data[0]);
const split = <i32>Math.min(4, n.hig) + 1;
const immA = decodeI32(data.subarray(1, split));
const offs = decodeI32(data.subarray(split));
const immA = decodeI32(data, 1, split);
const offs = decodeI32(data, split, lim);
return asArgs(n.low, immA, offs, 0);
},
// DECODERS[Arguments.TwoReg] =
(data: Uint8Array) => {
(data, _lim) => {
const n = nibbles(data[0]);
return asArgs(n.hig, n.low, 0, 0);
},
// DECODERS[Arguments.TwoRegOneImm] =
(data: Uint8Array) => {
(data, lim) => {
const n = nibbles(data[0]);
return asArgs(n.hig, n.low, decodeI32(data.subarray(1)), 0);
return asArgs(n.hig, n.low, decodeI32(data, 1, lim), 0);
},
// DECODERS[Arguments.TwoRegOneOff] =
(data: Uint8Array) => {
(data, lim) => {
const n = nibbles(data[0]);
return asArgs(n.hig, n.low, decodeI32(data.subarray(1)), 0);
return asArgs(n.hig, n.low, decodeI32(data, 1, lim), 0);
},
// DECODERS[Arguments.TwoRegTwoImm] =
(data: Uint8Array) => {
(data, lim) => {
const n = nibbles(data[0]);
const result = twoImm(data.subarray(1));
const result = twoImm(data.subarray(1), lim > 1 ? lim - 1 : 0);
return asArgs(n.hig, n.low, result.a, result.b);
},
// DECODERS[Arguments.ThreeReg] =
(data: Uint8Array) => {
(data, _lim) => {
const a = nibbles(data[0]);
const b = nibbles(data[1]);
return asArgs(a.hig, a.low, b.low, 0);
Expand All @@ -134,7 +134,8 @@ export function nibbles(byte: u8): Nibbles {
}

//@inline
function decodeI32(data: Uint8Array): u32 {
function decodeI32(input: Uint8Array, start: u32, end: u32): u32 {
const data = input.subarray(start, end > start ? end : start);
const len = <u32>Math.min(4, data.length);
let num = 0;
for (let i: u32 = 0; i < len; i++) {
Expand Down
4 changes: 2 additions & 2 deletions assembly/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export class Interpreter {

// get args and invoke instruction
const skipBytes = this.program.mask.bytesToNextInstruction(pc);
const args = decodeArguments(iData.kind, this.program.code.subarray(pc + 1));
const args = decodeArguments(iData.kind, this.program.code.subarray(pc + 1), skipBytes);

// additional gas cost of sbrk
if (iData === SBRK) {
Expand Down Expand Up @@ -147,7 +147,7 @@ export class Interpreter {
}
case Outcome.Ok: {
// by default move to next instruction.
this.pc += skipBytes;
this.pc += 1 + skipBytes;
return true;
}
}
Expand Down
19 changes: 12 additions & 7 deletions assembly/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ export class Mask {

bytesToNextInstruction(i: u32): u32 {
if (i + 1 < <u32>this.bytesToSkip.length) {
return this.bytesToSkip[i + 1] + 1;
return this.bytesToSkip[i + 1];
}

return 1;
return 0;
}

toString(): string {
Expand Down Expand Up @@ -199,16 +199,16 @@ export class Program {
}
}

export function decodeArguments(kind: Arguments, data: Uint8Array): Args {
export function decodeArguments(kind: Arguments, data: Uint8Array, lim: u32): Args {
if (data.length < REQUIRED_BYTES[kind]) {
// in case we have less data than needed we extend the data with zeros.
const extended = new Uint8Array(REQUIRED_BYTES[kind]);
for (let i = 0; i < data.length; i++) {
extended[i] = data[i];
}
return DECODERS[kind](extended);
return DECODERS[kind](extended, lim);
}
return DECODERS[kind](data);
return DECODERS[kind](data, lim);
}

class ResolvedArguments {
Expand All @@ -219,8 +219,13 @@ class ResolvedArguments {
decoded: Args = new Args();
}

export function resolveArguments(kind: Arguments, data: Uint8Array, registers: Registers): ResolvedArguments | null {
const args = decodeArguments(kind, data);
export function resolveArguments(
kind: Arguments,
data: Uint8Array,
lim: u32,
registers: Registers,
): ResolvedArguments | null {
const args = decodeArguments(kind, data, lim);
if (args === null) {
return null;
}
Expand Down

0 comments on commit 2bc923d

Please sign in to comment.