Skip to content
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
2 changes: 1 addition & 1 deletion avm-transpiler/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl Debug for AvmInstruction {
impl Default for AvmInstruction {
fn default() -> Self {
AvmInstruction {
opcode: AvmOpcode::ADD,
opcode: AvmOpcode::ADD_8,
// TODO(4266): default to Some(0), since all instructions have indirect flag except jumps
indirect: None,
tag: None,
Expand Down
78 changes: 52 additions & 26 deletions avm-transpiler/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,33 @@
#[derive(PartialEq, Copy, Clone, Debug, Eq, Hash)]
pub enum AvmOpcode {
// Compute
ADD,
SUB,
MUL,
DIV,
FDIV,
EQ,
LT,
LTE,
AND,
OR,
XOR,
ADD_8,
ADD_16,
SUB_8,
SUB_16,
MUL_8,
MUL_16,
DIV_8,
DIV_16,
FDIV_8,
FDIV_16,
EQ_8,
EQ_16,
LT_8,
LT_16,
LTE_8,
LTE_16,
AND_8,
AND_16,
OR_8,
OR_16,
XOR_8,
XOR_16,
NOT,
SHL,
SHR,
SHL_8,
SHL_16,
SHR_8,
SHR_16,
CAST,
// Execution environment
ADDRESS,
Expand Down Expand Up @@ -89,22 +102,35 @@ impl AvmOpcode {
match self {
// Compute
// Compute - Arithmetic
AvmOpcode::ADD => "ADD",
AvmOpcode::SUB => "SUB",
AvmOpcode::MUL => "MUL",
AvmOpcode::DIV => "DIV",
AvmOpcode::FDIV => "FDIV",
AvmOpcode::ADD_8 => "ADD_8",
AvmOpcode::ADD_16 => "ADD_16",
AvmOpcode::SUB_8 => "SUB_8",
AvmOpcode::SUB_16 => "SUB_16",
AvmOpcode::MUL_8 => "MUL_8",
AvmOpcode::MUL_16 => "MUL_16",
AvmOpcode::DIV_8 => "DIV_8",
AvmOpcode::DIV_16 => "DIV_16",
AvmOpcode::FDIV_8 => "FDIV_8",
AvmOpcode::FDIV_16 => "FDIV_16",
// Compute - Comparators
AvmOpcode::EQ => "EQ",
AvmOpcode::LT => "LT",
AvmOpcode::LTE => "LTE",
AvmOpcode::EQ_8 => "EQ_8",
AvmOpcode::EQ_16 => "EQ_16",
AvmOpcode::LT_8 => "LT_8",
AvmOpcode::LT_16 => "LT_16",
AvmOpcode::LTE_8 => "LTE_8",
AvmOpcode::LTE_16 => "LTE_16",
// Compute - Bitwise
AvmOpcode::AND => "AND",
AvmOpcode::OR => "OR",
AvmOpcode::XOR => "XOR",
AvmOpcode::AND_8 => "AND_8",
AvmOpcode::AND_16 => "AND_16",
AvmOpcode::OR_8 => "OR_8",
AvmOpcode::OR_16 => "OR_16",
AvmOpcode::XOR_8 => "XOR_8",
AvmOpcode::XOR_16 => "XOR_16",
AvmOpcode::NOT => "NOT",
AvmOpcode::SHL => "SHL",
AvmOpcode::SHR => "SHR",
AvmOpcode::SHL_8 => "SHL_8",
AvmOpcode::SHL_16 => "SHL_16",
AvmOpcode::SHR_8 => "SHR_8",
AvmOpcode::SHR_16 => "SHR_16",
// Compute - Type Conversions
AvmOpcode::CAST => "CAST",

Expand Down
155 changes: 126 additions & 29 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,65 @@ pub fn brillig_to_avm(
for brillig_instr in brillig_bytecode {
match brillig_instr {
BrilligOpcode::BinaryFieldOp { destination, op, lhs, rhs } => {
let bits_needed =
[lhs.0, rhs.0, destination.0].iter().map(bits_needed_for).max().unwrap();

assert!(
bits_needed == 8 || bits_needed == 16,
"BinaryFieldOp only support 8 or 16 bit encodings, got: {}",
bits_needed
);

let avm_opcode = match op {
BinaryFieldOp::Add => AvmOpcode::ADD,
BinaryFieldOp::Sub => AvmOpcode::SUB,
BinaryFieldOp::Mul => AvmOpcode::MUL,
BinaryFieldOp::Div => AvmOpcode::FDIV,
BinaryFieldOp::IntegerDiv => AvmOpcode::DIV,
BinaryFieldOp::Equals => AvmOpcode::EQ,
BinaryFieldOp::LessThan => AvmOpcode::LT,
BinaryFieldOp::LessThanEquals => AvmOpcode::LTE,
BinaryFieldOp::Add => match bits_needed {
8 => AvmOpcode::ADD_8,
16 => AvmOpcode::ADD_16,
_ => unreachable!(),
},
BinaryFieldOp::Sub => match bits_needed {
8 => AvmOpcode::SUB_8,
16 => AvmOpcode::SUB_16,
_ => unreachable!(),
},
BinaryFieldOp::Mul => match bits_needed {
8 => AvmOpcode::MUL_8,
16 => AvmOpcode::MUL_16,
_ => unreachable!(),
},
BinaryFieldOp::Div => match bits_needed {
8 => AvmOpcode::FDIV_8,
16 => AvmOpcode::FDIV_16,
_ => unreachable!(),
},
BinaryFieldOp::IntegerDiv => match bits_needed {
8 => AvmOpcode::DIV_8,
16 => AvmOpcode::DIV_16,
_ => unreachable!(),
},
BinaryFieldOp::Equals => match bits_needed {
8 => AvmOpcode::EQ_8,
16 => AvmOpcode::EQ_16,
_ => unreachable!(),
},
BinaryFieldOp::LessThan => match bits_needed {
8 => AvmOpcode::LT_8,
16 => AvmOpcode::LT_16,
_ => unreachable!(),
},
BinaryFieldOp::LessThanEquals => match bits_needed {
8 => AvmOpcode::LTE_8,
16 => AvmOpcode::LTE_16,
_ => unreachable!(),
},
};
avm_instrs.push(AvmInstruction {
opcode: avm_opcode,
indirect: Some(ALL_DIRECT),
tag: if avm_opcode == AvmOpcode::FDIV { None } else { Some(AvmTypeTag::FIELD) },
tag: Some(AvmTypeTag::FIELD),
operands: vec![
AvmOperand::U32 { value: lhs.to_usize() as u32 },
AvmOperand::U32 { value: rhs.to_usize() as u32 },
AvmOperand::U32 { value: destination.to_usize() as u32 },
make_operand(bits_needed, &lhs.0),
make_operand(bits_needed, &rhs.0),
make_operand(bits_needed, &destination.0),
],
});
}
Expand All @@ -57,28 +98,84 @@ pub fn brillig_to_avm(
"BinaryIntOp bit size should be integral: {:?}",
brillig_instr
);
let bits_needed =
[lhs.0, rhs.0, destination.0].iter().map(bits_needed_for).max().unwrap();
assert!(
bits_needed == 8 || bits_needed == 16,
"BinaryIntOp only support 8 or 16 bit encodings, got: {}",
bits_needed
);

let avm_opcode = match op {
BinaryIntOp::Add => AvmOpcode::ADD,
BinaryIntOp::Sub => AvmOpcode::SUB,
BinaryIntOp::Mul => AvmOpcode::MUL,
BinaryIntOp::Div => AvmOpcode::DIV,
BinaryIntOp::Equals => AvmOpcode::EQ,
BinaryIntOp::LessThan => AvmOpcode::LT,
BinaryIntOp::LessThanEquals => AvmOpcode::LTE,
BinaryIntOp::And => AvmOpcode::AND,
BinaryIntOp::Or => AvmOpcode::OR,
BinaryIntOp::Xor => AvmOpcode::XOR,
BinaryIntOp::Shl => AvmOpcode::SHL,
BinaryIntOp::Shr => AvmOpcode::SHR,
BinaryIntOp::Add => match bits_needed {
8 => AvmOpcode::ADD_8,
16 => AvmOpcode::ADD_16,
_ => unreachable!(),
},
BinaryIntOp::Sub => match bits_needed {
8 => AvmOpcode::SUB_8,
16 => AvmOpcode::SUB_16,
_ => unreachable!(),
},
BinaryIntOp::Mul => match bits_needed {
8 => AvmOpcode::MUL_8,
16 => AvmOpcode::MUL_16,
_ => unreachable!(),
},
BinaryIntOp::Div => match bits_needed {
8 => AvmOpcode::DIV_8,
16 => AvmOpcode::DIV_16,
_ => unreachable!(),
},
BinaryIntOp::And => match bits_needed {
8 => AvmOpcode::AND_8,
16 => AvmOpcode::AND_16,
_ => unreachable!(),
},
BinaryIntOp::Or => match bits_needed {
8 => AvmOpcode::OR_8,
16 => AvmOpcode::OR_16,
_ => unreachable!(),
},
BinaryIntOp::Xor => match bits_needed {
8 => AvmOpcode::XOR_8,
16 => AvmOpcode::XOR_16,
_ => unreachable!(),
},
BinaryIntOp::Shl => match bits_needed {
8 => AvmOpcode::SHL_8,
16 => AvmOpcode::SHL_16,
_ => unreachable!(),
},
BinaryIntOp::Shr => match bits_needed {
8 => AvmOpcode::SHR_8,
16 => AvmOpcode::SHR_16,
_ => unreachable!(),
},
BinaryIntOp::Equals => match bits_needed {
8 => AvmOpcode::EQ_8,
16 => AvmOpcode::EQ_16,
_ => unreachable!(),
},
BinaryIntOp::LessThan => match bits_needed {
8 => AvmOpcode::LT_8,
16 => AvmOpcode::LT_16,
_ => unreachable!(),
},
BinaryIntOp::LessThanEquals => match bits_needed {
8 => AvmOpcode::LTE_8,
16 => AvmOpcode::LTE_16,
_ => unreachable!(),
},
};
avm_instrs.push(AvmInstruction {
opcode: avm_opcode,
indirect: Some(ALL_DIRECT),
tag: Some(tag_from_bit_size(BitSize::Integer(*bit_size))),
operands: vec![
AvmOperand::U32 { value: lhs.to_usize() as u32 },
AvmOperand::U32 { value: rhs.to_usize() as u32 },
AvmOperand::U32 { value: destination.to_usize() as u32 },
make_operand(bits_needed, &lhs.0),
make_operand(bits_needed, &rhs.0),
make_operand(bits_needed, &destination.0),
],
});
}
Expand Down Expand Up @@ -214,9 +311,9 @@ pub fn brillig_to_avm(
// We are adding a MOV instruction that moves a value to itself.
// This should therefore not affect the program's execution.
avm_instrs.push(AvmInstruction {
opcode: AvmOpcode::MOV_8,
opcode: AvmOpcode::MOV_16,
indirect: Some(ALL_DIRECT),
operands: vec![AvmOperand::U32 { value: 0x18ca }, AvmOperand::U32 { value: 0x18ca }],
operands: vec![AvmOperand::U16 { value: 0x18ca }, AvmOperand::U16 { value: 0x18ca }],
..Default::default()
});

Expand Down
Loading