Skip to content

Move instruction structure to vm #4

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

Merged
merged 3 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions src/vm/decoder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use num_bigint::BigUint;

// 0| opcode|ap_update|pc_update|res_logic|op1_src|op0_reg|dst_reg
// 15|14 13 12| 11 10| 9 8 7| 6 5|4 3 2| 1| 0

const DST_REG_MASK = 0x0001;
const DST_REG_OFF = 0;
const OP0_REG_MASK = 0x0002;
const OP0_REG_OFF = 1;
const OP1_SRC_MASK = 0x001C;
const OP1_SRC_OFF = 2;
const RES_LOGIC_MASK = 0x0060;
const RES_LOGIC_OFF = 5;
const PC_UPDATE_MASK = 0x0380;
const PC_UPDATE_OFF = 7;
const AP_UPDATE_MASK = 0x0C00;
const AP_UPDATE_OFF = 10;
const OPCODE_MASK = 0x7000;
const OPCODE_OFF = 12;

// Flags start on the 48th bit.
const FLAGS_OFFSET = 48;
const OFF0_OFF = 0;
const OFF1_OFF = 16;
const OFF2_OFF = 32;
const OFFX_MASK = 0xFFFF;

/// Decodes an instruction. The encoding is little endian, so flags go from bit 63 to 48.
pub fn decode_instruction(encoded_instr:i64, imm:Option<BigUint>) -> instruction::Instruction {
let off0 = encoded_instr >> OFF0_OFF & OFFX_MASK;
let off1 = encoded_instr >> OFF1_OFF & OFFX_MASK;
let off2 = encoded_instr >> OFF2_OFF & OFFX_MASK;
let flags = encoded_instr >> FLAGS_OFFSET;
let dst_reg_num = (flags & DST_REG_MASK) >> DST_REG_OFF;
let op0_reg_num = (flags & OP0_REG_MASK) >> OP0_REG_OFF;
let op1_reg_num = (flags & OP1_REG_MASK) >> OP1_REG_OFF;
let res_logic_num = (flags & RES_LOGIC_MASK) >> RES_LOGIC_OFF;
let pc_update_num = (flags & PC_UPDATE_MASK) >> PC_UPDATE_OFF;
let ap_update_num = (flags & AP_UPDATE_MASK) >> AP_UPDATE_OFF;
let opcode_num = (flags & OPCODE_MASK) >> OPCODE_OFF;

let dst_reg = match dst_reg_num {
0 => instruction::Register::AP,
1 => instruction::Register::FP,
_ => {},
};

let op0_reg = match op0_reg_num {
0 => instruction::Register::AP,
1 => instruction::Register::FP,
_ => {},
};

let op1_addr = match op1_reg_num {
0 => instruction::Op1Addr::OP0,
1 => instruction::Op1Addr::IMM,
2 => instruction::Op1Addr::AP,
4 => instruction::Op1Addr::FP,
_ => {},
};

let pc_update = match pc_update_num {
0 => instruction::PcUpdate::REGULAR,
1 => instruction::PcUpdate::JUMP,
2 => instruction::PcUpdate::JUMP_REL,
4 => instruction::PcUpdate::JNZ,
_ => {},
};

let res = match res_logic_num {
0 if pc_update == instruction::PcUpdate::JNZ => instruction::Res::UNCONSTRAINED,
0 => instruction::Res::OP1
1 => instruction::Res::ADD,
2 => instruction::Res::MUL,
_ => {},
};

let opcode = match opcode_num {
0 => instruction::Opcode::NOP,
1 => instruction::Opcode::ASSERT_EQ,
2 => instruction::Opcode::RET,
4 => instruction::Opcode::CALL,
_ => {},
};

let ap_update = match ap_update_num {
0 if opcode == instruction::Opcode::CALL => instruction::ApUpdate::ADD2,
0 => instruction::ApUpdate::REGULAR,
1 => instruction::ApUpdate::ADD,
2 => instruction::ApUpdate::ADD1,
_ => {},
};

let fp_update = match opcode {
instruction::Opcode::CALL => instruction::FpUpdate::AP_PLUS2,
instruction::Opcode::RET => instruction::FpUpdate::DST,
_ => instruction::FpUpdate::REGULAR,
};

let instruction = instruction::Instruction {
off0,
off1,
off2,
imm,
dst_reg,
op0_reg,
op1_addr,
res,
pc_update,
ap_update,
fp_update,
opcode
}
}

16 changes: 8 additions & 8 deletions src/compiler/instruction.rs → src/vm/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
use num_bigint::BigUint;

num Register {
AP,
FP
}

pub struct Instruction {
off0: BigUint,
off1: BigUint,
off2: BigUint,
off0: i16,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out of curiosity why are you changing the type @Juan-M-V ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the specification divides the 64-bit words into off0, off1, off2 and flags, each taking 16-bits

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, thanks

off1: i16,
off2: i16,
imm: Option<BigUint>,
dst_register: Register,
op0_register: Register,
Expand All @@ -21,6 +16,11 @@ pub struct Instruction {

}

pub enum Register {
AP,
FP
}

pub enum Op1Addr {
IMM,
AP,
Expand Down