Skip to content

Commit

Permalink
Mul and div opcodes (#26)
Browse files Browse the repository at this point in the history
* impl mul

* add div

* refactor makefile and programs dir

* add missing flag for test

* add flag setting for mul

* fix mul not following spec

* impl div set flags

* div set flags test

* more tests

* clippy

* add mul conditional test

* add div conditional tests

* wrap address_operands

* justify unwrap

* remove makefile changes
  • Loading branch information
juan518munoz authored Jun 19, 2024
1 parent 322f605 commit de1192b
Show file tree
Hide file tree
Showing 22 changed files with 565 additions and 59 deletions.
2 changes: 1 addition & 1 deletion programs/add_sets_overflow.zasm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.text
.file "add_sets_overflow.zasm"
.file "mul_sets_overflow.zasm"
.globl __entry
__entry:

Expand Down
14 changes: 14 additions & 0 deletions programs/div.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.text
.file "div.zasm"
.globl __entry
__entry:
.func_begin0:
add 25, r0, r1
add 6, r0, r2
div r1, r2, r3, r4
sstore r0, r3
ret
.func_end0:

.note.GNU-stack
.rodata
20 changes: 20 additions & 0 deletions programs/div_codepage.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.text
.file "div_codepage.zasm"
.globl __entry

.rodata
datavar:
.cell 42
.cell 3
.text

__entry:
.func_begin0:
add 3, r0, r1
div @datavar[0], r1, r3, r4
sstore r0, r0
ret
.func_end0:

.note.GNU-stack
.rodata
14 changes: 14 additions & 0 deletions programs/div_conditional.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.text
.file "div.zasm"
.globl __entry
__entry:
.func_begin0:
add 25, r0, r1
add 6, r0, r2
div r1, r2, r3, r4
sstore r0, r3
ret
.func_end0:

.note.GNU-stack
.rodata
16 changes: 16 additions & 0 deletions programs/div_conditional_gt.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.text
.file "div_conditional_gt.zasm"
.globl __entry
__entry:
.func_begin0:
add 1, r0, r3
add 1, r0, r4
add 42, r0, r1
add 3, r0, r2
div.gt r1, r2, r3, r4
sstore r0, r3
ret
.func_end0:

.note.GNU-stack
.rodata
15 changes: 15 additions & 0 deletions programs/div_set_eq_flag.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.text
.file "div_set_eq_flag.zasm"
.globl __entry
__entry:
.func_begin0:
; EQ is set if the quotient is not zero
add 25, r0, r1
add 6, r0, r2
div! r1, r2, r3, r4
sstore r0, r3
ret
.func_end0:

.note.GNU-stack
.rodata
15 changes: 15 additions & 0 deletions programs/div_set_gt_flag.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.text
.file "div_set_gt_flag.zasm"
.globl __entry
__entry:
.func_begin0:
; GT is set if the reminder is not zero.
add 25, r0, r1
add 6, r0, r2
div! r1, r2, r3, r4
sstore r0, r3
ret
.func_end0:

.note.GNU-stack
.rodata
19 changes: 19 additions & 0 deletions programs/div_stack.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.text
.file "div_stack.zasm"
.globl __entry
__entry:

.func_begin0:
add 3, r0, r2
; grow stack
add 1, r0, stack+=[1]
; set stack values
add 42, r0, stack=[0]
; divide stack of absolute index 0
div stack=[0],r2, r3, r4
sstore r0, r0
ret

.func_end0:
.note.GNU-stack
.rodata
13 changes: 13 additions & 0 deletions programs/div_zero.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.text
.file "div_zero.zasm"
.globl __entry
__entry:
.func_begin0:
add 1, r0, r1
div r1, r0, r3, r4
sstore r0, r0
ret
.func_end0:

.note.GNU-stack
.rodata
15 changes: 15 additions & 0 deletions programs/mul.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.text
.file "mul.zasm"
.globl __entry
__entry:
.func_begin0:
add 3, r0, r1
add 2, r0, r2
mul r1, r2, r1, r0
mul 1, r1, r3, r4
sstore r0, r3
ret
.func_end0:

.note.GNU-stack
.rodata
13 changes: 13 additions & 0 deletions programs/mul_big.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.text
.file "mul_big.zasm"
.globl __entry
__entry:
.func_begin0:
; test sets r1 = 2**(256) - 1, r2 = 2**(256)
mul r1, r2, r3, r4
sstore r0, r1
ret
.func_end0:

.note.GNU-stack
.rodata
21 changes: 21 additions & 0 deletions programs/mul_codepage.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.text
.file "mul_codepage.zasm"
.globl __entry

.rodata
datavar:
.cell 42
.cell 3
.text

__entry:
.func_begin0:
add 1, r0, r1
mul @datavar[0], r1, r1, r0
mul @datavar[1], r1, r1, r0
sstore r0, r1
ret
.func_end0:

.note.GNU-stack
.rodata
14 changes: 14 additions & 0 deletions programs/mul_conditional_gt.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.text
.file "mul_conditional_gt.zasm"
.globl __entry
__entry:
.func_begin0:
add 3, r0, r1
add 14, r0, r2
mul.gt r1, r2, r3, r4
sstore r0, r3
ret
.func_end0:

.note.GNU-stack
.rodata
14 changes: 14 additions & 0 deletions programs/mul_sets_overflow.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.text
.file "add_sets_overflow.zasm"
.globl __entry
__entry:

.func_begin0:
; test sets r1 = 2**(256) - 1, r2 = 2**(256) - 1
mul! r1, r2, r3, r4
sstore r0, r1
ret

.func_end0:
.note.GNU-stack
.rodata
22 changes: 22 additions & 0 deletions programs/mul_stack.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.text
.file "mul_stack.zasm"
.globl __entry
__entry:

.func_begin0:
add 1, r0, r2
; grow stack
add 1, r0, stack+=[2]
; set stack values
add 2, r0, stack=[0]
add 3, r0, stack=[1]
; multiply by stack of absolute index 0
mul stack=[0],r2, r1, r0
; pop stack and multiply by the topmost value
mul stack-=[2],r1, r1, r0
sstore r0, r1
ret

.func_end0:
.note.GNU-stack
.rodata
13 changes: 13 additions & 0 deletions programs/mul_zero.zasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.text
.file "mul_zero.zasm"
.globl __entry
__entry:
.func_begin0:
add 1, r0, r1
mul r1, r0, r1, r0
sstore r0, r1
ret
.func_end0:

.note.GNU-stack
.rodata
74 changes: 59 additions & 15 deletions src/address_operands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,65 @@ pub fn address_operands_read(vm: &mut VMState, opcode: &Opcode) -> (U256, U256)
}
}
}
fn only_reg_write(vm: &mut VMState, opcode: &Opcode, res: U256) {
vm.set_register(opcode.dst0_index, res);

/// The first operand is used most of the times
/// the second operand is used only for div and mul
enum OutputOperandPosition {
First,
Second,
}

fn reg_and_imm_write(vm: &mut VMState, opcode: &Opcode) -> U256 {
let dst0 = vm.get_register(opcode.dst0_index);
let offset = opcode.imm1;
fn only_reg_write(
vm: &mut VMState,
opcode: &Opcode,
output_op_pos: OutputOperandPosition,
res: U256,
) {
match output_op_pos {
OutputOperandPosition::First => vm.set_register(opcode.dst0_index, res),
OutputOperandPosition::Second => vm.set_register(opcode.dst1_index, res),
}
}

dst0 + U256::from(offset)
fn reg_and_imm_write(
vm: &mut VMState,
output_op_pos: OutputOperandPosition,
opcode: &Opcode,
) -> U256 {
match output_op_pos {
OutputOperandPosition::First => {
let dst0 = vm.get_register(opcode.dst0_index);
let offset = opcode.imm1;
let res = dst0 + U256::from(offset);
vm.set_register(opcode.dst0_index, res);
res
}
OutputOperandPosition::Second => {
let dst1 = vm.get_register(opcode.dst1_index);
let offset = opcode.imm1;
let res = dst1 + U256::from(offset);
vm.set_register(opcode.dst1_index, res);
res
}
}
}

pub fn address_operands_store(vm: &mut VMState, opcode: &Opcode, res: U256) {
address_operands(vm, opcode, (res, None))
}

pub fn address_operands_div_mul(vm: &mut VMState, opcode: &Opcode, res: (U256, U256)) {
address_operands(vm, opcode, (res.0, Some(res.1)))
}

fn address_operands(vm: &mut VMState, opcode: &Opcode, res: (U256, Option<U256>)) {
match opcode.dst0_operand_type {
Operand::RegOnly => {
only_reg_write(vm, opcode, res);
only_reg_write(vm, opcode, OutputOperandPosition::First, res.0);
}
Operand::RegOrImm(variant) => match variant {
RegOrImmFlags::UseRegOnly => {
only_reg_write(vm, opcode, res);
only_reg_write(vm, opcode, OutputOperandPosition::First, res.0);
}
RegOrImmFlags::UseImm16Only => {
panic!("dest cannot be imm16 only");
Expand All @@ -99,38 +139,38 @@ pub fn address_operands_store(vm: &mut VMState, opcode: &Opcode, res: U256) {
Operand::Full(variant) => {
match variant {
ImmMemHandlerFlags::UseRegOnly => {
only_reg_write(vm, opcode, res);
only_reg_write(vm, opcode, OutputOperandPosition::First, res.0);
}
ImmMemHandlerFlags::UseStackWithPushPop => {
// stack+=[src0 + offset] + src1
let src0 = reg_and_imm_write(vm, opcode);
let src0 = reg_and_imm_write(vm, OutputOperandPosition::First, opcode);
vm.current_frame.stack.fill_with_zeros(src0 + 1);
vm.current_frame.stack.store_with_offset(
1,
TaggedValue {
value: res,
value: res.0,
is_pointer: false,
},
);
}
ImmMemHandlerFlags::UseStackWithOffset => {
// stack[src0 + offset] + src1
let src0 = reg_and_imm_write(vm, opcode);
let src0 = reg_and_imm_write(vm, OutputOperandPosition::First, opcode);
vm.current_frame.stack.store_with_offset(
src0.as_usize(),
TaggedValue {
value: res,
value: res.0,
is_pointer: false,
},
);
}
ImmMemHandlerFlags::UseAbsoluteOnStack => {
// stack=[src0 + offset] + src1
let src0 = reg_and_imm_write(vm, opcode);
let src0 = reg_and_imm_write(vm, OutputOperandPosition::First, opcode);
vm.current_frame.stack.store_absolute(
src0.as_usize(),
TaggedValue {
value: res,
value: res.0,
is_pointer: false,
},
);
Expand All @@ -144,4 +184,8 @@ pub fn address_operands_store(vm: &mut VMState, opcode: &Opcode, res: U256) {
}
}
}
if let Some(res) = res.1 {
// Second operand can only be a register
only_reg_write(vm, opcode, OutputOperandPosition::Second, res);
}
}
Loading

0 comments on commit de1192b

Please sign in to comment.