diff --git a/pkg/vm/memory/relocatable.go b/pkg/vm/memory/relocatable.go index 4c18e61a..917520b2 100644 --- a/pkg/vm/memory/relocatable.go +++ b/pkg/vm/memory/relocatable.go @@ -15,8 +15,23 @@ type Relocatable struct { // Creates a new Relocatable struct with the specified segment index // and offset. -func NewRelocatable(segment_idx int, offset uint) *Relocatable { - return &Relocatable{segment_idx, offset} +func NewRelocatable(segment_idx int, offset uint) Relocatable { + return Relocatable{segment_idx, offset} +} + +func (relocatable *Relocatable) SubRelocatable(other uint) (Relocatable, error) { + if relocatable.offset < other { + return NewRelocatable(0, 0), &SubReloctableError{Msg: "RelocatableSubUsizeNegOffset"} + } else { + new_offset := relocatable.offset - other + return NewRelocatable(relocatable.segmentIndex, new_offset), nil + } +} + +func (relocatable *Relocatable) AddRelocatable(other uint) (Relocatable, error) { + new_offset := relocatable.offset + other + return NewRelocatable(relocatable.segmentIndex, new_offset), nil + } // Get the the indexes of the Relocatable struct. @@ -33,8 +48,6 @@ func (r *Relocatable) into_indexes() (uint, uint) { // Int in the Cairo VM represents a value in memory that // is not an address. type Int struct { - // FIXME: Here we should use Lambdaworks felt, just mocking - // this for now. felt lambdaworks.Felt } diff --git a/pkg/vm/memory/relocatable_err.go b/pkg/vm/memory/relocatable_err.go new file mode 100644 index 00000000..5acae4ff --- /dev/null +++ b/pkg/vm/memory/relocatable_err.go @@ -0,0 +1,9 @@ +package memory + +type SubReloctableError struct { + Msg string +} + +func (e *SubReloctableError) Error() string { + return e.Msg +} diff --git a/pkg/vm/memory/segments.go b/pkg/vm/memory/segments.go index 3fc1c025..d08dfa13 100644 --- a/pkg/vm/memory/segments.go +++ b/pkg/vm/memory/segments.go @@ -4,6 +4,6 @@ package memory // Also holds metadata useful for the relocation process of // the memory at the end of the VM run. type MemorySegmentManager struct { - segmentSizes map[uint]uint - memory Memory + SegmentSizes map[uint]uint + Memory Memory } diff --git a/pkg/vm/run_context.go b/pkg/vm/run_context.go index 769e25e1..85b4b320 100644 --- a/pkg/vm/run_context.go +++ b/pkg/vm/run_context.go @@ -1,6 +1,11 @@ package vm -import "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" +import ( + "math" + + "github.com/lambdaclass/cairo-vm.go/pkg/lambdaworks" + "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" +) // RunContext containts the register states of the // Cairo VM. @@ -9,3 +14,72 @@ type RunContext struct { ap uint fp uint } + +func (run_context RunContext) GetAp() memory.Relocatable { + return memory.NewRelocatable(1, run_context.ap) +} + +func (run_context RunContext) GetFP() memory.Relocatable { + return memory.NewRelocatable(1, run_context.fp) +} + +func (run_context RunContext) get_pc() memory.Relocatable { + return run_context.pc +} + +func (run_context RunContext) ComputeDstAddr(instruction Instruction) (memory.Relocatable, error) { + var base_addr memory.Relocatable + switch instruction.DstReg { + case AP: + base_addr = run_context.GetAp() + case FP: + base_addr = run_context.GetFP() + } + + if instruction.OffOp0 < 0 { + return base_addr.SubRelocatable(uint(math.Abs(float64(instruction.OffDst)))) + } else { + return base_addr.AddRelocatable(uint(instruction.OffDst)) + } + +} + +func (run_context RunContext) ComputeOp0Addr(instruction Instruction) (memory.Relocatable, error) { + var base_addr memory.Relocatable + switch instruction.Op0Reg { + case AP: + base_addr = run_context.GetAp() + case FP: + base_addr = run_context.GetFP() + } + + if instruction.OffOp1 < 0 { + return base_addr.SubRelocatable(uint(math.Abs(float64(instruction.OffOp0)))) + } else { + return base_addr.AddRelocatable(uint(instruction.OffOp0)) + } +} + +func (run_context RunContext) ComputeOp1Addr(instruction Instruction, op0 memory.MaybeRelocatable) (memory.Relocatable, error) { + var base_addr memory.Relocatable + + switch instruction.Op1Addr { + case Op1SrcFP: + base_addr = run_context.GetFP() + case Op1SrcAP: + base_addr = run_context.GetAp() + case Op1SrcImm: + if instruction.OffOp1 == 1 { + base_addr = run_context.get_pc() + } else { + base_addr = memory.NewRelocatable(-1, 0) + return base_addr, VirtualMachineError{Msg: "UnknownOp0"} + } + // Todo:check case op0 + } + if instruction.OffOp1 < 0 { + return base_addr.SubRelocatable(uint(math.Abs(float64(instruction.OffOp1)))) + } else { + return base_addr.AddRelocatable(uint(instruction.OffOp1)) + } +} diff --git a/pkg/vm/vm_core.go b/pkg/vm/vm_core.go index 009c789f..a9216da1 100644 --- a/pkg/vm/vm_core.go +++ b/pkg/vm/vm_core.go @@ -5,6 +5,14 @@ import ( "github.com/lambdaclass/cairo-vm.go/pkg/vm/memory" ) +type VirtualMachineError struct { + Msg string +} + +func (e VirtualMachineError) Error() string { + return fmt.Sprintf(e.Msg) +} + // VirtualMachine represents the Cairo VM. // Runs Cairo assembly and produces an execution trace. type VirtualMachine struct { @@ -26,7 +34,34 @@ type OperandsAddresses struct { op1_addr memory.Relocatable } -func (vm VirtualMachine) compute_operands(instruction Instruction) {} +type DeducedOperands struct { + operands uint8 +} + +func (vm VirtualMachine) compute_operands(instruction Instruction) (Operands, OperandsAddresses, DeducedOperands, VirtualMachineError) { + + dst_addr, err := vm.runContext.ComputeDstAddr(instruction) + if err != nil { + return Operands{}, OperandsAddresses{}, DeducedOperands{}, VirtualMachineError{Msg: "FailtToComputeDstAddr"} + } + + dst_op, err_dst = vm.segments.Memory.Get(&dst_addr) + + op0_addr, err := vm.runContext.ComputeOp0Addr(instruction) + if err != nil { + return Operands{}, OperandsAddresses{}, DeducedOperands{}, VirtualMachineError{Msg: "FailtToComputeOp0Addr"} + } + + op0_op, err_op0 := vm.segments.Memory.Get(&op0_addr) + + op1_addr, err := vm.runContext.ComputeOp1Addr(instruction) + if err != nil { + return Operands{}, OperandsAddresses{}, DeducedOperands{}, VirtualMachineError{Msg: "FailtToComputeOp1Addr"} + } + op1_op, err_op1 := vm.segments.Memory.Get(&op1_addr) + + deduced_operands := DeducedOperands{operands: 0} +} func (vm VirtualMachine) run_instrucion(instruction Instruction) { fmt.Println("hello from instruction")