bird-vm/main.go

125 lines
3.6 KiB
Go

package main
import (
"flag"
"fmt"
"os"
)
/*
TODO
- Add SST (set string: move a string from the stack to memory)
- Add a flag that lets the heap pointer move after the write?
- If this isn't present then GST and RST have to add a length
to TOS so that a length can be known
- Add GST (get string: move a string from an address to the stack)
*/
// This has room for up to 255 ops, but just uses these right now.
// Once a screen device is enable there will likely be more. Screen
// and sound, really.
var ops = []func(bool, *Stack){
// Regular ops
opNop, opSet, opGet, opSei, opGei, opAll, opNop,
opPsh, opPop, opOvr, opSwp, opRot, opDup, opSsw, // <-13
opAdd, opSub, opMul, opDiv, opInc, opDec, opNop,
opAnd, opBor, opXor, opShr, opShl, opNop, opNop, // <-27
opJmp, opCal, opJcd, opRet, opNop, opNop, opNop,
opRch, opRst, opPut, opPst, opHlt, opSst, opGst,
opGrt, opLst, opGte, opLte, opEql, opNeq, opNop, //<-48
opNop, opNop, opNop, opNop, opNop, opNop, opNop,
opNop, opNop, opNop, opNop, opNop, opNop, opNop,
opNop,
// r ops
opNop, opSet, opGet, opSei, opGei, opAll, opNop,
opPsh, opPop, opOvr, opSwp, opRot, opDup, opSsw,
opAdd, opSub, opMul, opDiv, opInc, opDec, opNop,
opAnd, opBor, opXor, opShr, opShl, opNop, opNop,
opJmp, opCal, opJcd, opRet, opNop, opNop, opNop,
opRch, opRst, opPut, opPst, opHlt, opSst, opGst,
opGrt, opLst, opGte, opLte, opEql, opNeq, opNop, //<-112
opNop, opNop, opNop, opNop, opNop, opNop, opNop,
opNop, opNop, opNop, opNop, opNop, opNop, opNop,
opNop,
// 2 ops
opNop, opSet, opGet, opSei, opGei, opAll, opNop,
opPsh, opPop, opOvr, opSwp, opRot, opDup, opNop,
opAdd, opSub, opMul, opDiv, opInc, opDec, opNop,
opAnd, opBor, opXor, opShr, opShl, opNop, opNop,
opJmp, opCal, opJcd, opRet, opNop, opNop, opNop,
opRch, opRst, opPut, opPst, opHlt, opSst, opGst,
opGrt, opLst, opGte, opLte, opEql, opNeq, opNop, //<-176
opNop, opNop, opNop, opNop, opNop, opNop, opNop,
opNop, opNop, opNop, opNop, opNop, opNop, opNop,
opNop,
// 2r ops
opNop, opSet, opGet, opSei, opGei, opAll, opNop,
opPsh, opPop, opOvr, opSwp, opRot, opDup, opNop,
opAdd, opSub, opMul, opDiv, opInc, opDec, opNop,
opAnd, opBor, opXor, opShr, opShl, opNop, opNop,
opJmp, opCal, opJcd, opRet, opNop, opNop, opNop,
opRch, opRst, opPut, opPst, opHlt, opSst, opGst,
opGrt, opLst, opGte, opLte, opEql, opNeq, opNop, //<-176
opNop, opNop, opNop, opNop, opNop, opNop, opNop,
opNop, opNop, opNop, opNop, opNop, opNop, opNop,
opNop,
}
var jump bool
var vm Vm = Vm{0, [MaxUint16]byte{0}, [MaxUint16]byte{0}, Stack{0, [MaxByte]byte{0}}, Stack{0, [MaxByte]byte{0}}, 0}
var dumpVmData bool
var debug bool
var halt = -1
func main() {
flag.BoolVar(&dumpVmData, "dump", false, "Dump stacks on exit")
flag.BoolVar(&debug, "d", false, "Turn on debug mode")
flag.Parse()
args := flag.Args()
if len(args) == 0 {
fmt.Fprint(os.Stderr, "No input file")
os.Exit(1)
} else if len(args) > 1 {
fmt.Fprint(os.Stderr, "Too many input files")
os.Exit(1)
}
in, err := loadFile(args[0])
if err != nil {
fmt.Fprint(os.Stderr, "Could not read file")
os.Exit(1)
}
l := LoadProg(in)
vm.PC = 2
// Loop
for ;vm.PC < MaxUint16 && halt < 0;vm.PC++{
Jump:
o := vm.Prog.Read(vm.PC)
if debug {
fmt.Fprintf(os.Stderr, "\033[32m0x%02x\033[0m ", o)
}
if IsRetStackOp(o) {
ops[o](IsLongOp(o), &(vm.Return))
} else {
ops[o](IsLongOp(o), &(vm.Data))
}
if jump {
jump = false
goto Jump
}
}
if halt < 0 {
halt = 9
}
if dumpVmData {
DumpVm(l)
}
os.Exit(halt)
}