125 lines
3.6 KiB
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)
|
|
}
|