76 lines
1.3 KiB
Go
76 lines
1.3 KiB
Go
package gmachine
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
)
|
|
|
|
// DefaultMemSize is the number of 64-bit words of memory which will be
|
|
// allocated to a new G-machine by default.
|
|
const DefaultMemSize = 1024
|
|
|
|
const (
|
|
OpHALT uint64 = iota
|
|
OpNOOP
|
|
OpINCA
|
|
OpDECA
|
|
OpSETA
|
|
)
|
|
|
|
type gMachine struct {
|
|
// Memory 64-bit words of memory
|
|
Memory []uint64
|
|
// P (Program counter)
|
|
P uint64
|
|
// A (Register A)
|
|
A uint64
|
|
// Debugging flag, if turned on will print OpCodes
|
|
DebugOn bool
|
|
}
|
|
|
|
func New() *gMachine {
|
|
return &gMachine{
|
|
P: 0,
|
|
Memory: make([]uint64, DefaultMemSize),
|
|
DebugOn: false,
|
|
}
|
|
}
|
|
|
|
func (m *gMachine) NewProgram(program []uint64) {
|
|
copy(m.Memory, program)
|
|
m.Run()
|
|
}
|
|
|
|
func (m *gMachine) Run() {
|
|
for {
|
|
pointer := m.P
|
|
m.P++
|
|
switch m.Memory[pointer] {
|
|
case OpHALT:
|
|
m.printIfDebug("OpHALT")
|
|
return
|
|
case OpNOOP:
|
|
m.printIfDebug("OpNOOP")
|
|
case OpINCA:
|
|
m.printIfDebug("OpINCA")
|
|
m.A++
|
|
case OpDECA:
|
|
m.printIfDebug("OpDECA")
|
|
m.A--
|
|
case OpSETA:
|
|
m.A = m.Memory[m.P]
|
|
m.P++
|
|
m.printIfDebug(fmt.Sprintf("OpSETA %d", m.A))
|
|
default:
|
|
m.printIfDebug(fmt.Sprintf("COULD NOT DETERMINE OP CODE, code:%d, pointer:%d", m.Memory[pointer], pointer))
|
|
panic(pointer)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (m *gMachine) printIfDebug(message string) {
|
|
if m.DebugOn {
|
|
log.Println(message)
|
|
}
|
|
}
|