|
|
@ -1,6 +1,7 @@ |
|
|
|
package hal |
|
|
|
package hal |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
|
|
|
|
"fmt" |
|
|
|
"strings" |
|
|
|
"strings" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
@ -9,20 +10,20 @@ type ProgrammedInstruction struct { |
|
|
|
Operand float64 |
|
|
|
Operand float64 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (pi *ProgrammedInstruction) Execute(module *Module) { |
|
|
|
func (pi *ProgrammedInstruction) Execute(module *Module) error { |
|
|
|
if pi.Instruction.ExecuteWithOperand != nil { |
|
|
|
if pi.Instruction.ExecuteWithOperand != nil { |
|
|
|
pi.Instruction.ExecuteWithOperand(module, pi.Operand) |
|
|
|
return pi.Instruction.ExecuteWithOperand(module, pi.Operand) |
|
|
|
} else if pi.Instruction.Execute != nil { |
|
|
|
} else if pi.Instruction.Execute != nil { |
|
|
|
pi.Instruction.Execute(module) |
|
|
|
return pi.Instruction.Execute(module) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
panic("instruction is not implemented") |
|
|
|
return fmt.Errorf("instruction is not implemented") |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type Instruction struct { |
|
|
|
type Instruction struct { |
|
|
|
Name string |
|
|
|
Name string |
|
|
|
ExecuteWithOperand func(module *Module, operand float64) |
|
|
|
ExecuteWithOperand func(module *Module, operand float64) error |
|
|
|
Execute func(module *Module) |
|
|
|
Execute func(module *Module) error |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func FindInstructionByName(name string) *Instruction { |
|
|
|
func FindInstructionByName(name string) *Instruction { |
|
|
@ -43,29 +44,87 @@ var instructions = []*Instruction{ |
|
|
|
|
|
|
|
|
|
|
|
var InstructionStart = &Instruction{ |
|
|
|
var InstructionStart = &Instruction{ |
|
|
|
Name: "START", |
|
|
|
Name: "START", |
|
|
|
Execute: func(module *Module) { |
|
|
|
Execute: func(module *Module) error { |
|
|
|
// actually not required
|
|
|
|
// actually not required
|
|
|
|
module.isStopped = false |
|
|
|
module.isStopped = false |
|
|
|
|
|
|
|
return nil |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var InstructionStop = &Instruction{ |
|
|
|
var InstructionStop = &Instruction{ |
|
|
|
Name: "STOP", |
|
|
|
Name: "STOP", |
|
|
|
Execute: func(module *Module) { |
|
|
|
Execute: func(module *Module) error { |
|
|
|
module.isStopped = true |
|
|
|
module.isStopped = true |
|
|
|
|
|
|
|
return nil |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var InstructionOut = &Instruction{ |
|
|
|
var InstructionOut = &Instruction{ |
|
|
|
Name: "OUT", |
|
|
|
Name: "OUT", |
|
|
|
ExecuteWithOperand: func(module *Module, operand float64) { |
|
|
|
ExecuteWithOperand: func(module *Module, operand float64) error { |
|
|
|
|
|
|
|
index := int(operand) |
|
|
|
|
|
|
|
if len(module.IO) >= index { |
|
|
|
|
|
|
|
return fmt.Errorf("index %d exceeds IO size of %d", index, len(module.IO)) |
|
|
|
|
|
|
|
} |
|
|
|
module.IO[int64(operand)] = module.accumulator |
|
|
|
module.IO[int64(operand)] = module.accumulator |
|
|
|
|
|
|
|
return nil |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var InstructionIn = &Instruction{ |
|
|
|
var InstructionIn = &Instruction{ |
|
|
|
Name: "IN", |
|
|
|
Name: "IN", |
|
|
|
Execute: func(module *Module) { |
|
|
|
ExecuteWithOperand: func(module *Module, operand float64) error { |
|
|
|
// TODO implement
|
|
|
|
index := int(operand) |
|
|
|
|
|
|
|
if len(module.IO) >= index { |
|
|
|
|
|
|
|
return fmt.Errorf("index %d exceeds IO size of %d", index, len(module.IO)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
module.accumulator = module.IO[index] |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var InstructionLoad = &Instruction{ |
|
|
|
|
|
|
|
Name: "LOAD", |
|
|
|
|
|
|
|
ExecuteWithOperand: func(module *Module, operand float64) error { |
|
|
|
|
|
|
|
index := int(operand) |
|
|
|
|
|
|
|
if len(module.register) >= index { |
|
|
|
|
|
|
|
return fmt.Errorf("index %d exceeds register size of %d", index, len(module.IO)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
module.accumulator = module.register[index] |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var InstructionLoadNum = &Instruction{ |
|
|
|
|
|
|
|
Name: "LOADNUM", |
|
|
|
|
|
|
|
ExecuteWithOperand: func(module *Module, operand float64) error { |
|
|
|
|
|
|
|
module.accumulator = operand |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var InstructionStore = &Instruction{ |
|
|
|
|
|
|
|
Name: "STORE", |
|
|
|
|
|
|
|
ExecuteWithOperand: func(module *Module, operand float64) error { |
|
|
|
|
|
|
|
index := int(operand) |
|
|
|
|
|
|
|
if len(module.register) >= index { |
|
|
|
|
|
|
|
return fmt.Errorf("index %d exceeds register size of %d", index, len(module.IO)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
module.register[index] = module.accumulator |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var InstructionJumpNeg = &Instruction{ |
|
|
|
|
|
|
|
Name: "JUMPNEG", |
|
|
|
|
|
|
|
ExecuteWithOperand: func(module *Module, operand float64) error { |
|
|
|
|
|
|
|
index := int64(operand) |
|
|
|
|
|
|
|
if _, ok := module.programStorage[index]; !ok { |
|
|
|
|
|
|
|
return fmt.Errorf("index %d does not exist in program storage", index) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if module.accumulator < 0 { |
|
|
|
|
|
|
|
return module.setProgramCounter(index) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return nil |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
} |
|
|
|