Skip to content

Commit 5b3cd5a

Browse files
authored
Simplified the translation of most binary instructions. (#93)
1 parent 5670f71 commit 5b3cd5a

File tree

2 files changed

+79
-134
lines changed

2 files changed

+79
-134
lines changed

integration/src/instruction_builder.rs

Lines changed: 7 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ use openvm_instructions::{instruction::Instruction, riscv, LocalOpcode, SystemOp
22
use openvm_stark_backend::p3_field::PrimeField32;
33
use openvm_womir_transpiler::{
44
AllocateFrameOpcode, BaseAlu64Opcode, BaseAluOpcode, ConstOpcodes, CopyIntoFrameOpcode,
5-
DivRem64Opcode, DivRemOpcode, Eq64Opcode, EqOpcode, HintStoreOpcode, JaafOpcode, JumpOpcode,
6-
LessThan64Opcode, LessThanOpcode, LoadStoreOpcode, Mul64Opcode, MulOpcode, Phantom,
7-
Shift64Opcode, ShiftOpcode,
5+
Eq64Opcode, EqOpcode, HintStoreOpcode, JaafOpcode, JumpOpcode, LessThan64Opcode,
6+
LessThanOpcode, LoadStoreOpcode, MulOpcode, Phantom, Shift64Opcode, ShiftOpcode,
87
};
98

109
use crate::womir_translation::{ERROR_ABORT_CODE, ERROR_CODE_OFFSET};
@@ -54,6 +53,7 @@ pub fn sub<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F>
5453
instr_r(BaseAluOpcode::SUB.global_opcode().as_usize(), rd, rs1, rs2)
5554
}
5655

56+
#[cfg(test)]
5757
pub fn mul<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
5858
instr_r(MulOpcode::MUL.global_opcode().as_usize(), rd, rs1, rs2)
5959
}
@@ -62,52 +62,13 @@ pub fn muli<F: PrimeField32>(rd: usize, rs1: usize, imm: F) -> Instruction<F> {
6262
instr_i(MulOpcode::MUL.global_opcode().as_usize(), rd, rs1, imm)
6363
}
6464

65-
pub fn mul_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
66-
instr_r(Mul64Opcode::MUL.global_opcode().as_usize(), rd, rs1, rs2)
67-
}
68-
65+
#[cfg(test)]
6966
pub fn div<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
67+
use openvm_womir_transpiler::DivRemOpcode;
7068
instr_r(DivRemOpcode::DIV.global_opcode().as_usize(), rd, rs1, rs2)
7169
}
7270

73-
pub fn divu<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
74-
instr_r(DivRemOpcode::DIVU.global_opcode().as_usize(), rd, rs1, rs2)
75-
}
76-
77-
pub fn rem<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
78-
instr_r(DivRemOpcode::REM.global_opcode().as_usize(), rd, rs1, rs2)
79-
}
80-
81-
pub fn remu<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
82-
instr_r(DivRemOpcode::REMU.global_opcode().as_usize(), rd, rs1, rs2)
83-
}
84-
85-
pub fn div_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
86-
instr_r(DivRem64Opcode::DIV.global_opcode().as_usize(), rd, rs1, rs2)
87-
}
88-
89-
pub fn divu_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
90-
instr_r(
91-
DivRem64Opcode::DIVU.global_opcode().as_usize(),
92-
rd,
93-
rs1,
94-
rs2,
95-
)
96-
}
97-
98-
pub fn rem_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
99-
instr_r(DivRem64Opcode::REM.global_opcode().as_usize(), rd, rs1, rs2)
100-
}
101-
102-
pub fn remu_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
103-
instr_r(
104-
DivRem64Opcode::REMU.global_opcode().as_usize(),
105-
rd,
106-
rs1,
107-
rs2,
108-
)
109-
}
110-
71+
#[cfg(test)]
11172
pub fn xor<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
11273
instr_r(BaseAluOpcode::XOR.global_opcode().as_usize(), rd, rs1, rs2)
11374
}
@@ -116,6 +77,7 @@ pub fn or<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F>
11677
instr_r(BaseAluOpcode::OR.global_opcode().as_usize(), rd, rs1, rs2)
11778
}
11879

80+
#[cfg(test)]
11981
pub fn and<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
12082
instr_r(BaseAluOpcode::AND.global_opcode().as_usize(), rd, rs1, rs2)
12183
}
@@ -140,10 +102,6 @@ pub fn shr_u_imm<F: PrimeField32>(rd: usize, rs1: usize, imm: F) -> Instruction<
140102
instr_i(ShiftOpcode::SRL.global_opcode().as_usize(), rd, rs1, imm)
141103
}
142104

143-
pub fn shr_s<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
144-
instr_r(ShiftOpcode::SRA.global_opcode().as_usize(), rd, rs1, rs2)
145-
}
146-
147105
pub fn shr_s_imm<F: PrimeField32>(rd: usize, rs1: usize, imm: F) -> Instruction<F> {
148106
instr_i(ShiftOpcode::SRA.global_opcode().as_usize(), rd, rs1, imm)
149107
}
@@ -161,10 +119,6 @@ pub fn shr_u_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instructi
161119
instr_r(Shift64Opcode::SRL.global_opcode().as_usize(), rd, rs1, rs2)
162120
}
163121

164-
pub fn shr_s_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
165-
instr_r(Shift64Opcode::SRA.global_opcode().as_usize(), rd, rs1, rs2)
166-
}
167-
168122
pub fn shr_s_imm_64<F: PrimeField32>(rd: usize, rs1: usize, imm: F) -> Instruction<F> {
169123
instr_i(Shift64Opcode::SRA.global_opcode().as_usize(), rd, rs1, imm)
170124
}
@@ -251,22 +205,10 @@ pub fn eqi<F: PrimeField32>(rd: usize, rs1: usize, imm: F) -> Instruction<F> {
251205
instr_i(EqOpcode::EQ.global_opcode().as_usize(), rd, rs1, imm)
252206
}
253207

254-
pub fn neq<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
255-
instr_r(EqOpcode::NEQ.global_opcode().as_usize(), rd, rs1, rs2)
256-
}
257-
258-
pub fn eq_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
259-
instr_r(Eq64Opcode::EQ.global_opcode().as_usize(), rd, rs1, rs2)
260-
}
261-
262208
pub fn eqi_64<F: PrimeField32>(rd: usize, rs1: usize, imm: F) -> Instruction<F> {
263209
instr_i(Eq64Opcode::EQ.global_opcode().as_usize(), rd, rs1, imm)
264210
}
265211

266-
pub fn neq_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
267-
instr_r(Eq64Opcode::NEQ.global_opcode().as_usize(), rd, rs1, rs2)
268-
}
269-
270212
pub fn const_32_imm<F: PrimeField32>(
271213
target_reg: usize,
272214
imm_lo: u16,
@@ -286,15 +228,6 @@ pub fn const_32_imm<F: PrimeField32>(
286228
)
287229
}
288230

289-
pub fn add_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
290-
instr_r(
291-
BaseAlu64Opcode::ADD.global_opcode().as_usize(),
292-
rd,
293-
rs1,
294-
rs2,
295-
)
296-
}
297-
298231
#[allow(dead_code)]
299232
pub fn addi_64<F: PrimeField32>(rd: usize, rs1: usize, imm: F) -> Instruction<F> {
300233
instr_i(
@@ -314,28 +247,10 @@ pub fn sub_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction
314247
)
315248
}
316249

317-
pub fn xor_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
318-
instr_r(
319-
BaseAlu64Opcode::XOR.global_opcode().as_usize(),
320-
rd,
321-
rs1,
322-
rs2,
323-
)
324-
}
325-
326250
pub fn or_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
327251
instr_r(BaseAlu64Opcode::OR.global_opcode().as_usize(), rd, rs1, rs2)
328252
}
329253

330-
pub fn and_64<F: PrimeField32>(rd: usize, rs1: usize, rs2: usize) -> Instruction<F> {
331-
instr_r(
332-
BaseAlu64Opcode::AND.global_opcode().as_usize(),
333-
rd,
334-
rs1,
335-
rs2,
336-
)
337-
}
338-
339254
pub fn andi_64<F: PrimeField32>(rd: usize, rs1: usize, imm: F) -> Instruction<F> {
340255
instr_i(
341256
BaseAlu64Opcode::AND.global_opcode().as_usize(),

integration/src/womir_translation.rs

Lines changed: 72 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ use openvm_instructions::{
1212
riscv,
1313
};
1414
use openvm_stark_backend::p3_field::PrimeField32;
15+
use openvm_womir_transpiler::{
16+
BaseAlu64Opcode, BaseAluOpcode, DivRem64Opcode, DivRemOpcode, Eq64Opcode, EqOpcode,
17+
LessThan64Opcode, LessThanOpcode, Mul64Opcode, MulOpcode, Shift64Opcode, ShiftOpcode,
18+
};
1519
use wasmparser::{MemArg, Operator as Op, ValType};
1620
use womir::{
1721
linker::LabelValue,
@@ -675,50 +679,47 @@ impl<'a, F: PrimeField32> Settings<'a> for OpenVMSettings<F> {
675679
inputs: Vec<Range<u32>>,
676680
output: Option<Range<u32>>,
677681
) -> Vec<Self::Directive> {
682+
use openvm_instructions::LocalOpcode;
683+
678684
// First handle single-instruction binary operations.
679-
type BinaryOpFn<F> = fn(usize, usize, usize) -> Instruction<F>;
680-
let binary_op: Result<BinaryOpFn<F>, Op> = match op {
685+
let binary_op = match op {
681686
// 32-bit integer instructions
682-
Op::I32Eq => Ok(ib::eq),
683-
Op::I32Ne => Ok(ib::neq),
684-
Op::I32LtS => Ok(ib::lt_s),
685-
Op::I32LtU => Ok(ib::lt_u),
686-
Op::I32GtS => Ok(ib::gt_s),
687-
Op::I32GtU => Ok(ib::gt_u),
688-
Op::I32Add => Ok(ib::add),
689-
Op::I32Sub => Ok(ib::sub),
690-
Op::I32Mul => Ok(ib::mul),
691-
Op::I32DivS => Ok(ib::div),
692-
Op::I32DivU => Ok(ib::divu),
693-
Op::I32RemS => Ok(ib::rem),
694-
Op::I32RemU => Ok(ib::remu),
695-
Op::I32And => Ok(ib::and),
696-
Op::I32Or => Ok(ib::or),
697-
Op::I32Xor => Ok(ib::xor),
698-
Op::I32Shl => Ok(ib::shl),
699-
Op::I32ShrS => Ok(ib::shr_s),
700-
Op::I32ShrU => Ok(ib::shr_u),
687+
Op::I32Eq => Ok(EqOpcode::EQ.global_opcode()),
688+
Op::I32Ne => Ok(EqOpcode::NEQ.global_opcode()),
689+
Op::I32LtS => Ok(LessThanOpcode::SLT.global_opcode()),
690+
Op::I32LtU => Ok(LessThanOpcode::SLTU.global_opcode()),
691+
Op::I32Add => Ok(BaseAluOpcode::ADD.global_opcode()),
692+
Op::I32Sub => Ok(BaseAluOpcode::SUB.global_opcode()),
693+
Op::I32And => Ok(BaseAluOpcode::AND.global_opcode()),
694+
Op::I32Or => Ok(BaseAluOpcode::OR.global_opcode()),
695+
Op::I32Xor => Ok(BaseAluOpcode::XOR.global_opcode()),
696+
Op::I32Mul => Ok(MulOpcode::MUL.global_opcode()),
697+
Op::I32DivS => Ok(DivRemOpcode::DIV.global_opcode()),
698+
Op::I32DivU => Ok(DivRemOpcode::DIVU.global_opcode()),
699+
Op::I32RemS => Ok(DivRemOpcode::REM.global_opcode()),
700+
Op::I32RemU => Ok(DivRemOpcode::REMU.global_opcode()),
701+
Op::I32Shl => Ok(ShiftOpcode::SLL.global_opcode()),
702+
Op::I32ShrS => Ok(ShiftOpcode::SRA.global_opcode()),
703+
Op::I32ShrU => Ok(ShiftOpcode::SRL.global_opcode()),
701704

702705
// 64-bit integer instructions
703-
Op::I64Eq => Ok(ib::eq_64),
704-
Op::I64Ne => Ok(ib::neq_64),
705-
Op::I64LtS => Ok(ib::lt_s_64),
706-
Op::I64LtU => Ok(ib::lt_u_64),
707-
Op::I64GtS => Ok(ib::gt_s_64),
708-
Op::I64GtU => Ok(ib::gt_u_64),
709-
Op::I64Add => Ok(ib::add_64),
710-
Op::I64Sub => Ok(ib::sub_64),
711-
Op::I64Mul => Ok(ib::mul_64),
712-
Op::I64DivS => Ok(ib::div_64),
713-
Op::I64DivU => Ok(ib::divu_64),
714-
Op::I64RemS => Ok(ib::rem_64),
715-
Op::I64RemU => Ok(ib::remu_64),
716-
Op::I64And => Ok(ib::and_64),
717-
Op::I64Or => Ok(ib::or_64),
718-
Op::I64Xor => Ok(ib::xor_64),
719-
Op::I64Shl => Ok(ib::shl_64),
720-
Op::I64ShrS => Ok(ib::shr_s_64),
721-
Op::I64ShrU => Ok(ib::shr_u_64),
706+
Op::I64Eq => Ok(Eq64Opcode::EQ.global_opcode()),
707+
Op::I64Ne => Ok(Eq64Opcode::NEQ.global_opcode()),
708+
Op::I64LtS => Ok(LessThan64Opcode::SLT.global_opcode()),
709+
Op::I64LtU => Ok(LessThan64Opcode::SLTU.global_opcode()),
710+
Op::I64Add => Ok(BaseAlu64Opcode::ADD.global_opcode()),
711+
Op::I64Sub => Ok(BaseAlu64Opcode::SUB.global_opcode()),
712+
Op::I64And => Ok(BaseAlu64Opcode::AND.global_opcode()),
713+
Op::I64Or => Ok(BaseAlu64Opcode::OR.global_opcode()),
714+
Op::I64Xor => Ok(BaseAlu64Opcode::XOR.global_opcode()),
715+
Op::I64Mul => Ok(Mul64Opcode::MUL.global_opcode()),
716+
Op::I64DivS => Ok(DivRem64Opcode::DIV.global_opcode()),
717+
Op::I64DivU => Ok(DivRem64Opcode::DIVU.global_opcode()),
718+
Op::I64RemS => Ok(DivRem64Opcode::REM.global_opcode()),
719+
Op::I64RemU => Ok(DivRem64Opcode::REMU.global_opcode()),
720+
Op::I64Shl => Ok(Shift64Opcode::SLL.global_opcode()),
721+
Op::I64ShrS => Ok(Shift64Opcode::SRA.global_opcode()),
722+
Op::I64ShrU => Ok(Shift64Opcode::SRL.global_opcode()),
722723

723724
// Float instructions
724725
Op::F32Eq => todo!(),
@@ -753,11 +754,40 @@ impl<'a, F: PrimeField32> Settings<'a> for OpenVMSettings<F> {
753754
};
754755

755756
let op: Op<'_> = match binary_op {
756-
Ok(op_fn) => {
757+
Ok(op) => {
757758
let input1 = inputs[0].start as usize;
758759
let input2 = inputs[1].start as usize;
759760
let output = output.unwrap().start as usize;
760-
return vec![Directive::Instruction(op_fn(output, input1, input2))];
761+
return vec![Directive::Instruction(ib::instr_r(
762+
op.as_usize(),
763+
output,
764+
input1,
765+
input2,
766+
))];
767+
}
768+
Err(op) => op,
769+
};
770+
771+
// Handle the GT instructions, which are just reversed LT
772+
let op = match op {
773+
Op::I32GtS => Ok(LessThanOpcode::SLT.global_opcode()),
774+
Op::I32GtU => Ok(LessThanOpcode::SLTU.global_opcode()),
775+
Op::I64GtS => Ok(LessThan64Opcode::SLT.global_opcode()),
776+
Op::I64GtU => Ok(LessThan64Opcode::SLTU.global_opcode()),
777+
op => Err(op),
778+
};
779+
780+
let op = match op {
781+
Ok(op) => {
782+
let greater_side = inputs[0].start as usize;
783+
let lower_side = inputs[1].start as usize;
784+
let output = output.unwrap().start as usize;
785+
return vec![Directive::Instruction(ib::instr_r(
786+
op.as_usize(),
787+
output,
788+
lower_side,
789+
greater_side,
790+
))];
761791
}
762792
Err(op) => op,
763793
};

0 commit comments

Comments
 (0)