-
Notifications
You must be signed in to change notification settings - Fork 327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(avm): simulator relative addr #8837
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,26 +3,28 @@ import { strict as assert } from 'assert'; | |
import { type TaggedMemoryInterface } from '../avm_memory_types.js'; | ||
|
||
export enum AddressingMode { | ||
DIRECT, | ||
INDIRECT, | ||
INDIRECT_PLUS_CONSTANT, // Not implemented yet. | ||
DIRECT = 0, | ||
INDIRECT = 1, | ||
RELATIVE = 2, | ||
INDIRECT_RELATIVE = 3, | ||
} | ||
|
||
/** A class to represent the addressing mode of an instruction. */ | ||
export class Addressing { | ||
public constructor( | ||
/** The addressing mode for each operand. The length of this array is the number of operands of the instruction. */ | ||
private readonly modePerOperand: AddressingMode[], | ||
) { | ||
assert(modePerOperand.length <= 8, 'At most 8 operands are supported'); | ||
} | ||
) {} | ||
|
||
public static fromWire(wireModes: number): Addressing { | ||
// TODO(facundo): 8 for backwards compatibility. | ||
public static fromWire(wireModes: number, numOperands: number = 8): Addressing { | ||
// The modes are stored in the wire format as a byte, with each bit representing the mode for an operand. | ||
// The least significant bit represents the zeroth operand, and the most significant bit represents the last operand. | ||
const modes = new Array<AddressingMode>(8); | ||
for (let i = 0; i < 8; i++) { | ||
modes[i] = (wireModes & (1 << i)) === 0 ? AddressingMode.DIRECT : AddressingMode.INDIRECT; | ||
const modes = new Array<AddressingMode>(numOperands); | ||
for (let i = 0; i < numOperands; i++) { | ||
modes[i] = | ||
(((wireModes >> i) & 1) * AddressingMode.INDIRECT) | | ||
(((wireModes >> (i + numOperands)) & 1) * AddressingMode.RELATIVE); | ||
} | ||
Comment on lines
-23
to
28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes that what it means!
It does not need special casing here, we just need to make the wire format indirect be a u16 for those operations to be usable in relative mode. Also mentioned here: https://docs.google.com/document/d/1uiSp8Q2Pu8L2UCba1PPPNQfxxK3d78_-vrzud7PECnw/edit#bookmark=id.wmo1rdovzz9f |
||
return new Addressing(modes); | ||
} | ||
|
@@ -31,17 +33,20 @@ export class Addressing { | |
// The modes are stored in the wire format as a byte, with each bit representing the mode for an operand. | ||
// The least significant bit represents the zeroth operand, and the least significant bit represents the last operand. | ||
let wire: number = 0; | ||
for (let i = 0; i < 8; i++) { | ||
if (this.modePerOperand[i] === AddressingMode.INDIRECT) { | ||
for (let i = 0; i < this.modePerOperand.length; i++) { | ||
if (this.modePerOperand[i] & AddressingMode.INDIRECT) { | ||
wire |= 1 << i; | ||
} | ||
if (this.modePerOperand[i] & AddressingMode.RELATIVE) { | ||
wire |= 1 << (this.modePerOperand.length + i); | ||
} | ||
} | ||
return wire; | ||
} | ||
|
||
/** Returns how many operands use the given addressing mode. */ | ||
public count(mode: AddressingMode): number { | ||
return this.modePerOperand.filter(m => m === mode).length; | ||
return this.modePerOperand.filter(m => (m & mode) !== 0).length; | ||
} | ||
|
||
/** | ||
|
@@ -54,17 +59,15 @@ export class Addressing { | |
assert(offsets.length <= this.modePerOperand.length); | ||
const resolved = new Array(offsets.length); | ||
for (const [i, offset] of offsets.entries()) { | ||
switch (this.modePerOperand[i]) { | ||
case AddressingMode.INDIRECT: | ||
// NOTE(reviewer): less than equal is a deviation from the spec - i dont see why this shouldnt be possible! | ||
mem.checkIsValidMemoryOffsetTag(offset); | ||
resolved[i] = Number(mem.get(offset).toBigInt()); | ||
break; | ||
case AddressingMode.DIRECT: | ||
resolved[i] = offset; | ||
break; | ||
default: | ||
throw new Error(`Unimplemented addressing mode: ${AddressingMode[this.modePerOperand[i]]}`); | ||
const mode = this.modePerOperand[i]; | ||
resolved[i] = offset; | ||
if (mode & AddressingMode.RELATIVE) { | ||
mem.checkIsValidMemoryOffsetTag(0); | ||
resolved[i] += Number(mem.get(0).toBigInt()); | ||
} | ||
if (mode & AddressingMode.INDIRECT) { | ||
mem.checkIsValidMemoryOffsetTag(resolved[i]); | ||
resolved[i] = Number(mem.get(resolved[i]).toBigInt()); | ||
} | ||
Comment on lines
61
to
71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this is the crux of the PR. Looks good to me! |
||
} | ||
return resolved; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard to parse what's going on in to/from wire here. Not going to block merge, but some additional comments would be helpful. If this might change again soon, then I'm fine with procrastinating on more comments for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes you are right that it's not explicit in the code, I will add some comments in some other PR. The encoding is explained here: https://docs.google.com/document/d/1uiSp8Q2Pu8L2UCba1PPPNQfxxK3d78_-vrzud7PECnw/edit#bookmark=id.wmo1rdovzz9f