aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2018-01-15 00:32:37 +0100
committerDimitri Sokolyuk <demon@dim13.org>2018-01-15 00:32:37 +0100
commit3705ec154f2700d1b3c60ce56626cc520fb3e068 (patch)
tree413f995245533e627a6f78d983c77b1fe2b7a268
parentd4c791fe8e48463a9b47d3afc65b613ca61883da (diff)
rename
-rw-r--r--core.go (renamed from eval.go)111
-rw-r--r--core_test.go (renamed from eval_test.go)84
2 files changed, 96 insertions, 99 deletions
diff --git a/eval.go b/core.go
index c879d7a..5ffe7cb 100644
--- a/eval.go
+++ b/core.go
@@ -16,131 +16,128 @@ type Console interface {
Len() uint16
}
-// J1 Forth processor VM
-type J1 struct {
- memory [memSize]uint16 // 0..0x3fff main memory, 0x4000 .. 0x7fff mem-mapped i/o
- pc uint16 // 13 bit
- st0 uint16 // top of data stack
- d stack
- r stack
- console Console
- stop context.CancelFunc
+// Core of J1 Forth CPU
+type Core struct {
+ memory [memSize]uint16 // 0..0x3fff main memory, 0x4000 .. 0x7fff mem-mapped i/o
+ pc uint16 // 13 bit
+ st0 uint16 // top of data stack
+ d, r stack // data and return stacks
+ tty Console // console i/o
+ stop context.CancelFunc
}
-func New() *J1 {
- return new(J1)
+func New() *Core {
+ return new(Core)
}
// Reset VM
-func (j1 *J1) Reset() {
- j1.pc, j1.st0, j1.d.sp, j1.r.sp = 0, 0, 0, 0
+func (c *Core) Reset() {
+ c.pc, c.st0, c.d.sp, c.r.sp = 0, 0, 0, 0
}
// LoadBytes into memory
-func (j1 *J1) LoadBytes(data []byte) error {
+func (c *Core) LoadBytes(data []byte) error {
size := len(data) >> 1
if size >= memSize {
return fmt.Errorf("too big")
}
- return binary.Read(bytes.NewReader(data), binary.LittleEndian, j1.memory[:size])
+ return binary.Read(bytes.NewReader(data), binary.LittleEndian, c.memory[:size])
}
// LoadFile into memory
-func (j1 *J1) LoadFile(fname string) error {
+func (c *Core) LoadFile(fname string) error {
data, err := ioutil.ReadFile(fname)
if err != nil {
return err
}
- return j1.LoadBytes(data)
+ return c.LoadBytes(data)
}
// Run evaluates content of memory
-func (j1 *J1) Run() {
+func (c *Core) Run() {
ctx, cancel := context.WithCancel(context.Background())
- j1.console = NewConsole(ctx)
- j1.stop = cancel
+ c.tty = NewConsole(ctx)
+ c.stop = cancel
for {
select {
case <-ctx.Done():
return
default:
- ins := Decode(j1.memory[j1.pc])
- //fmt.Printf("%v\n%v", ins, j1)
- j1.Eval(ins)
+ c.Eval(Decode(c.memory[c.pc]))
}
}
}
-func (j1 *J1) String() string {
- s := fmt.Sprintf("\tPC=%0.4X ST=%0.4X\n", j1.pc, j1.st0)
- s += fmt.Sprintf("\tD=%0.4X\n", j1.d.dump())
- s += fmt.Sprintf("\tR=%0.4X\n", j1.r.dump())
+func (c *Core) String() string {
+ s := fmt.Sprintf("\tPC=%0.4X ST=%0.4X\n", c.pc, c.st0)
+ s += fmt.Sprintf("\tD=%0.4X\n", c.d.dump())
+ s += fmt.Sprintf("\tR=%0.4X\n", c.r.dump())
return s
}
-func (j1 *J1) writeAt(addr, value uint16) {
+func (c *Core) writeAt(addr, value uint16) {
if off := int(addr >> 1); off < memSize {
- j1.memory[addr>>1] = value
+ c.memory[addr>>1] = value
}
switch addr {
case 0xf000: // key
- j1.console.Write(value)
+ c.tty.Write(value)
case 0xf002: // bye
- j1.stop()
+ c.stop()
}
}
-func (j1 *J1) readAt(addr uint16) uint16 {
+func (c *Core) readAt(addr uint16) uint16 {
if off := int(addr >> 1); off < memSize {
- return j1.memory[off]
+ return c.memory[off]
}
switch addr {
case 0xf000: // tx!
- return j1.console.Read()
+ return c.tty.Read()
case 0xf001: // ?rx
- return j1.console.Len()
+ return c.tty.Len()
}
return 0
}
-func (j1 *J1) Eval(ins Instruction) {
- j1.pc++
+func (c *Core) Eval(ins Instruction) {
+ c.pc++
switch v := ins.(type) {
case Lit:
- j1.d.push(j1.st0)
- j1.st0 = v.Value()
+ c.d.push(c.st0)
+ c.st0 = v.Value()
case Jump:
- j1.pc = v.Value()
+ c.pc = v.Value()
case Call:
- j1.r.push(j1.pc << 1)
- j1.pc = v.Value()
+ c.r.push(c.pc << 1)
+ c.pc = v.Value()
case Cond:
- if j1.st0 == 0 {
- j1.pc = v.Value()
+ if c.st0 == 0 {
+ c.pc = v.Value()
}
- j1.st0 = j1.d.pop()
+ c.st0 = c.d.pop()
case ALU:
if v.RtoPC {
- j1.pc = j1.r.get() >> 1
+ c.pc = c.r.get() >> 1
}
if v.NtoAtT {
- j1.writeAt(j1.st0, j1.d.get())
+ c.writeAt(c.st0, c.d.get())
}
- st0 := j1.newST0(v.Opcode)
- j1.d.move(v.Ddir)
- j1.r.move(v.Rdir)
+ st0 := c.newST0(v.Opcode)
+ c.d.move(v.Ddir)
+ c.r.move(v.Rdir)
if v.TtoN {
- j1.d.set(j1.st0)
+ c.d.set(c.st0)
}
if v.TtoR {
- j1.r.set(j1.st0)
+ c.r.set(c.st0)
}
- j1.st0 = st0
+ c.st0 = st0
}
}
-func (j1 *J1) newST0(opcode uint16) uint16 {
- T, N, R := j1.st0, j1.d.get(), j1.r.get()
+func (c *Core) newST0(opcode uint16) uint16 {
+ T, N, R := c.st0, c.d.get(), c.r.get()
switch opcode {
case opT: // T
return T
@@ -167,11 +164,11 @@ func (j1 *J1) newST0(opcode uint16) uint16 {
case opR: // R (rT)
return R
case opAtT: // [T]
- return j1.readAt(T)
+ return c.readAt(T)
case opNlshiftT: // N<<T
return N << (T & 0xf)
case opDepth: // depth (dsp)
- return (j1.r.depth() << 8) | j1.d.depth()
+ return (c.r.depth() << 8) | c.d.depth()
case opNuleT: // Nu<T
return bool2int(N < T)
default:
diff --git a/eval_test.go b/core_test.go
index 96d111e..12ae6f9 100644
--- a/eval_test.go
+++ b/core_test.go
@@ -5,7 +5,7 @@ import (
"testing"
)
-func cmp(t *testing.T, got, want J1) {
+func cmp(t *testing.T, got, want Core) {
t.Helper()
if got.pc != want.pc {
t.Errorf("pc: got %0.4X, want %0.4X", got.pc, want.pc)
@@ -30,83 +30,83 @@ func cmp(t *testing.T, got, want J1) {
func TestEval(t *testing.T) {
testCases := []struct {
ins []Instruction
- end J1
+ end Core
}{
{
ins: []Instruction{Jump(0xff)},
- end: J1{pc: 0xff},
+ end: Core{pc: 0xff},
},
{
ins: []Instruction{Lit(1), Cond(0xff)},
- end: J1{pc: 2},
+ end: Core{pc: 2},
},
{
ins: []Instruction{Lit(0), Cond(0xff)},
- end: J1{pc: 0xff},
+ end: Core{pc: 0xff},
},
{
ins: []Instruction{Call(0xff)},
- end: J1{pc: 0xff, r: stack{data: [0x20]uint16{0x00, 0x02}, sp: 1}},
+ end: Core{pc: 0xff, r: stack{data: [0x20]uint16{0x00, 0x02}, sp: 1}},
},
{
ins: []Instruction{Lit(0xff)},
- end: J1{pc: 1, st0: 0xff, d: stack{sp: 1}},
+ end: Core{pc: 1, st0: 0xff, d: stack{sp: 1}},
},
{
ins: []Instruction{Lit(0xff), Lit(0xfe)},
- end: J1{pc: 2, st0: 0xfe, d: stack{data: [0x20]uint16{0x00, 0x00, 0xff}, sp: 2}},
+ end: Core{pc: 2, st0: 0xfe, d: stack{data: [0x20]uint16{0x00, 0x00, 0xff}, sp: 2}},
},
{ // dup
ins: []Instruction{Lit(0xff), ALU{Opcode: opT, TtoN: true, Ddir: 1}},
- end: J1{pc: 2, st0: 0xff, d: stack{data: [0x20]uint16{0x00, 0x00, 0xff}, sp: 2}},
+ end: Core{pc: 2, st0: 0xff, d: stack{data: [0x20]uint16{0x00, 0x00, 0xff}, sp: 2}},
},
{ // over
ins: []Instruction{Lit(0xaa), Lit(0xbb), ALU{Opcode: opN, TtoN: true, Ddir: 1}},
- end: J1{pc: 3, st0: 0xaa, d: stack{data: [0x20]uint16{0x00, 0x00, 0xaa, 0xbb}, sp: 3}},
+ end: Core{pc: 3, st0: 0xaa, d: stack{data: [0x20]uint16{0x00, 0x00, 0xaa, 0xbb}, sp: 3}},
},
{ // invert
ins: []Instruction{Lit(0x00ff), ALU{Opcode: opNotT}},
- end: J1{pc: 2, st0: 0xff00, d: stack{sp: 1}},
+ end: Core{pc: 2, st0: 0xff00, d: stack{sp: 1}},
},
{ // +
ins: []Instruction{Lit(1), Lit(2), ALU{Opcode: opTplusN, Ddir: -1}},
- end: J1{pc: 3, st0: 3, d: stack{data: [0x20]uint16{0, 0, 1}, sp: 1}},
+ end: Core{pc: 3, st0: 3, d: stack{data: [0x20]uint16{0, 0, 1}, sp: 1}},
},
{ // swap
ins: []Instruction{Lit(2), Lit(3), ALU{Opcode: opN, TtoN: true}},
- end: J1{pc: 3, st0: 2, d: stack{data: [0x20]uint16{0, 0, 3}, sp: 2}},
+ end: Core{pc: 3, st0: 2, d: stack{data: [0x20]uint16{0, 0, 3}, sp: 2}},
},
{ // nip
ins: []Instruction{Lit(2), Lit(3), ALU{Opcode: opT, Ddir: -1}},
- end: J1{pc: 3, st0: 3, d: stack{data: [0x20]uint16{0, 0, 2}, sp: 1}},
+ end: Core{pc: 3, st0: 3, d: stack{data: [0x20]uint16{0, 0, 2}, sp: 1}},
},
{ // drop
ins: []Instruction{Lit(2), Lit(3), ALU{Opcode: opN, Ddir: -1}},
- end: J1{pc: 3, st0: 2, d: stack{data: [0x20]uint16{0, 0, 2}, sp: 1}},
+ end: Core{pc: 3, st0: 2, d: stack{data: [0x20]uint16{0, 0, 2}, sp: 1}},
},
{ // ;
ins: []Instruction{Call(10), Call(20), ALU{Opcode: opT, RtoPC: true, Rdir: -1}},
- end: J1{pc: 11, r: stack{data: [0x20]uint16{0, 2, 22}, sp: 1}},
+ end: Core{pc: 11, r: stack{data: [0x20]uint16{0, 2, 22}, sp: 1}},
},
{ // >r
ins: []Instruction{Lit(10), ALU{Opcode: opN, TtoR: true, Ddir: -1, Rdir: 1}},
- end: J1{pc: 2, r: stack{data: [0x20]uint16{0, 10}, sp: 1}},
+ end: Core{pc: 2, r: stack{data: [0x20]uint16{0, 10}, sp: 1}},
},
{ // r>
ins: []Instruction{Lit(10), Call(20), ALU{Opcode: opR, TtoN: true, TtoR: true, Ddir: 1, Rdir: -1}},
- end: J1{pc: 21, st0: 4, d: stack{data: [0x20]uint16{0, 0, 10}, sp: 2}, r: stack{data: [0x20]uint16{10, 4}}},
+ end: Core{pc: 21, st0: 4, d: stack{data: [0x20]uint16{0, 0, 10}, sp: 2}, r: stack{data: [0x20]uint16{10, 4}}},
},
{ // r@
ins: []Instruction{Lit(10), ALU{Opcode: opR, TtoN: true, TtoR: true, Ddir: 1}},
- end: J1{pc: 2, d: stack{data: [0x20]uint16{0, 0, 10}, sp: 2}, r: stack{data: [0x20]uint16{10}}},
+ end: Core{pc: 2, d: stack{data: [0x20]uint16{0, 0, 10}, sp: 2}, r: stack{data: [0x20]uint16{10}}},
},
{ // @
ins: []Instruction{ALU{Opcode: opAtT}},
- end: J1{pc: 1},
+ end: Core{pc: 1},
},
{ // !
ins: []Instruction{Lit(1), Lit(0), ALU{Opcode: opN, NtoAtT: true, Ddir: -1}},
- end: J1{pc: 3, st0: 1, d: stack{data: [0x20]uint16{0, 0, 1}, sp: 1}, memory: [0x4000]uint16{1}},
+ end: Core{pc: 3, st0: 1, d: stack{data: [0x20]uint16{0, 0, 1}, sp: 1}, memory: [0x4000]uint16{1}},
},
}
@@ -125,27 +125,27 @@ func TestNextST0(t *testing.T) {
testCases := []struct {
ins ALU
st0 uint16
- state J1
+ state Core
}{
- {ins: ALU{Opcode: opT}, st0: 0xff, state: J1{st0: 0xff}},
- {ins: ALU{Opcode: opN}, st0: 0xbb, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
- {ins: ALU{Opcode: opTplusN}, st0: 0x01ba, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
- {ins: ALU{Opcode: opTandN}, st0: 0xbb, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
- {ins: ALU{Opcode: opTorN}, st0: 0xff, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
- {ins: ALU{Opcode: opTxorN}, st0: 0x44, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
- {ins: ALU{Opcode: opNotT}, st0: 0xff55, state: J1{st0: 0xaa}},
- {ins: ALU{Opcode: opNeqT}, st0: 0x00, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
- {ins: ALU{Opcode: opNeqT}, st0: 0xffff, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
- {ins: ALU{Opcode: opNleT}, st0: 0xffff, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
- {ins: ALU{Opcode: opNleT}, st0: 0x00, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
- {ins: ALU{Opcode: opNrshiftT}, st0: 0x3f, state: J1{st0: 0x02, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
- {ins: ALU{Opcode: opTminus1}, st0: 0x54, state: J1{st0: 0x55}},
- {ins: ALU{Opcode: opR}, st0: 0x5, state: J1{r: stack{data: [0x20]uint16{0, 0x05}, sp: 1}}},
- {ins: ALU{Opcode: opAtT}, st0: 0x5, state: J1{st0: 0x02, memory: [0x4000]uint16{0, 5, 10}}},
- {ins: ALU{Opcode: opNlshiftT}, st0: 0x3fc, state: J1{st0: 0x02, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
- {ins: ALU{Opcode: opDepth}, st0: 0x305, state: J1{r: stack{sp: 3}, d: stack{sp: 5}}},
- {ins: ALU{Opcode: opNuleT}, st0: 0xffff, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
- {ins: ALU{Opcode: opNuleT}, st0: 0x00, state: J1{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
+ {ins: ALU{Opcode: opT}, st0: 0xff, state: Core{st0: 0xff}},
+ {ins: ALU{Opcode: opN}, st0: 0xbb, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
+ {ins: ALU{Opcode: opTplusN}, st0: 0x01ba, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
+ {ins: ALU{Opcode: opTandN}, st0: 0xbb, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
+ {ins: ALU{Opcode: opTorN}, st0: 0xff, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
+ {ins: ALU{Opcode: opTxorN}, st0: 0x44, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
+ {ins: ALU{Opcode: opNotT}, st0: 0xff55, state: Core{st0: 0xaa}},
+ {ins: ALU{Opcode: opNeqT}, st0: 0x00, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
+ {ins: ALU{Opcode: opNeqT}, st0: 0xffff, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
+ {ins: ALU{Opcode: opNleT}, st0: 0xffff, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
+ {ins: ALU{Opcode: opNleT}, st0: 0x00, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
+ {ins: ALU{Opcode: opNrshiftT}, st0: 0x3f, state: Core{st0: 0x02, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
+ {ins: ALU{Opcode: opTminus1}, st0: 0x54, state: Core{st0: 0x55}},
+ {ins: ALU{Opcode: opR}, st0: 0x5, state: Core{r: stack{data: [0x20]uint16{0, 0x05}, sp: 1}}},
+ {ins: ALU{Opcode: opAtT}, st0: 0x5, state: Core{st0: 0x02, memory: [0x4000]uint16{0, 5, 10}}},
+ {ins: ALU{Opcode: opNlshiftT}, st0: 0x3fc, state: Core{st0: 0x02, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
+ {ins: ALU{Opcode: opDepth}, st0: 0x305, state: Core{r: stack{sp: 3}, d: stack{sp: 5}}},
+ {ins: ALU{Opcode: opNuleT}, st0: 0xffff, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xbb}, sp: 2}}},
+ {ins: ALU{Opcode: opNuleT}, st0: 0x00, state: Core{st0: 0xff, d: stack{data: [0x20]uint16{0, 0xaa, 0xff}, sp: 2}}},
}
for _, tc := range testCases {
t.Run(fmt.Sprint(tc.ins), func(t *testing.T) {
@@ -171,7 +171,7 @@ func TestLoadBytes(t *testing.T) {
}
func TestReset(t *testing.T) {
- j1 := &J1{pc: 100, d: stack{sp: 2}, r: stack{sp: 3}, st0: 5}
+ j1 := &Core{pc: 100, d: stack{sp: 2}, r: stack{sp: 3}, st0: 5}
j1.Reset()
if j1.pc != 0 || j1.d.sp != 0 || j1.r.sp != 0 || j1.st0 != 0 {
t.Errorf("got %v", j1)