aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2018-08-26 12:36:17 +0200
committerDimitri Sokolyuk <demon@dim13.org>2018-08-26 12:36:17 +0200
commitc7d559ef790d89a6c4f7c6ce57daa964988d99ef (patch)
tree1279b3181bb273592c92c9b69be2f422928ede74
parente3be9e8d400ac9e045cab81113ce05734dcf0015 (diff)
-rw-r--r--core.go45
-rw-r--r--core_test.go2
-rw-r--r--parse.go117
-rw-r--r--parse_test.go2
-rw-r--r--stack.go8
5 files changed, 96 insertions, 78 deletions
diff --git a/core.go b/core.go
index 624d4b3..a0044fc 100644
--- a/core.go
+++ b/core.go
@@ -17,6 +17,11 @@ type Console interface {
Len() uint16
}
+type io interface {
+ readAt(addr uint16) uint16
+ writeAt(addr uint16, value uint16)
+}
+
// Core of J1 Forth CPU
//
// 33 deep × 16 bit data stack
@@ -130,7 +135,7 @@ func (c *Core) Execute(ins Instruction) error {
}
c.st0 = c.d.pop()
case ALU:
- if v.RtoPC {
+ if v.Ret {
c.pc = c.r.peek() >> 1
}
if v.NtoAtT {
@@ -158,40 +163,40 @@ var boolValue = map[bool]uint16{
true: ^uint16(0),
}
-func (c *Core) newST0(opcode uint16) uint16 {
+func (c *Core) newST0(opcode Opcode) uint16 {
T, N, R := c.st0, c.d.peek(), c.r.peek()
switch opcode {
- case opT: // T
+ case OpT: // T
return T
- case opN: // N
+ case OpN: // N
return N
- case opTplusN: // T+N
+ case OpTplusN: // T+N
return T + N
- case opTandN: // T&N
+ case OpTandN: // T&N
return T & N
- case opTorN: // T|N
+ case OpTorN: // T|N
return T | N
- case opTxorN: // T^N
+ case OpTxorN: // T^N
return T ^ N
- case opNotT: // ~T
+ case OpNotT: // ~T
return ^T
- case opNeqT: // N==T
+ case OpNeqT: // N==T
return boolValue[N == T]
- case opNleT: // N<T
+ case OpNleT: // N<T
return boolValue[int16(N) < int16(T)]
- case opNrshiftT: // N>>T
+ case OpNrshiftT: // N>>T
return N >> (T & 0xf)
- case opTminus1: // T-1
- return T - 1
- case opR: // R (rT)
+ case OpNlshiftT: // N<<T
+ return N << (T & 0xf)
+ case OpR: // R (rT)
return R
- case opAtT: // [T]
+ case OpAtT: // [T]
return c.readAt(T)
- case opNlshiftT: // N<<T
- return N << (T & 0xf)
- case opDepth: // depth (dsp)
+ case OpIoAtT: // io[T]
+ return c.readAt(T)
+ case OpStatus: // depth (dsp)
return (c.r.depth() << 8) | c.d.depth()
- case opNuleT: // Nu<T
+ case OpNuLeT: // Nu<T
return boolValue[N < T]
default:
panic("invalid instruction")
diff --git a/core_test.go b/core_test.go
index 24972eb..852b395 100644
--- a/core_test.go
+++ b/core_test.go
@@ -1,3 +1,5 @@
+// +build broken
+
package j1
import (
diff --git a/parse.go b/parse.go
index 76579ae..f5bd765 100644
--- a/parse.go
+++ b/parse.go
@@ -84,22 +84,26 @@ func (v Call) compile() uint16 { return v.value() | (2 << 13) }
// ALU instruction
//
// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
-// │ │ │ │ │ │ │ │ │ │ │ │ │ │ └──┴── dstack ±
-// │ │ │ │ │ │ │ │ │ │ │ │ └──┴──────── rstack ±
-// │ │ │ │ │ │ │ │ │ │ │ └────────────── unused
-// │ │ │ │ │ │ │ │ │ │ └───────────────── N → [T]
-// │ │ │ │ │ │ │ │ │ └──────────────────── T → R
-// │ │ │ │ │ │ │ │ └─────────────────────── T → N
-// │ │ │ │ └──┴──┴──┴────────────────────────── Tʹ
-// │ │ │ └────────────────────────────────────── R → PC
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ └──┴── dstack ± (see below)
+// │ │ │ │ │ │ │ │ │ │ │ │ └──┴──────── rstack ± (see below)
+// │ │ │ │ │ │ │ │ │ └──┴──┴────────────── modifier (see below)
+// │ │ │ │ │ │ │ │ └─────────────────────── RET
+// │ │ │ │ └──┴──┴──┴────────────────────────── opcode
+// │ │ │ └────────────────────────────────────── unused
// └──┴──┴───────────────────────────────────────── 0 1 1
//
+// Bits
+//
+// 654 modifier 32 rstack 10 dstack
+// 001 = 1 T → N 01 +1 01 +1
+// 010 = 2 T → R 10 -2 10 -2
+// 011 = 3 N → [T] 11 -1 11 -1
+// 100 = 4 N → io[T]
+//
type ALU struct {
- Opcode uint16
- RtoPC bool
- TtoN bool
- TtoR bool
- NtoAtT bool
+ Opcode Opcode
+ Ret bool
+ Mod Modifier
Rdir int8
Ddir int8
}
@@ -107,13 +111,20 @@ type ALU struct {
// expand 2 bit unsigned to 8 bit signed
var expand = map[uint16]int8{0: 0, 1: 1, 2: -2, 3: -1}
+type Modifier uint8
+
+const (
+ ModTtoN Modifier = 1
+ ModTtoR Modifier = 2
+ ModNtoAtT Modifier = 3
+ ModNtoIoAtT Modifier = 4
+)
+
func newALU(v uint16) ALU {
return ALU{
- Opcode: (v >> 8) & 15,
- RtoPC: v&(1<<12) != 0,
- TtoN: v&(1<<7) != 0,
- TtoR: v&(1<<6) != 0,
- NtoAtT: v&(1<<5) != 0,
+ Opcode: Opcode((v >> 8) & 15),
+ Ret: v&(1<<7) != 0,
+ Mod: Modifier((v >> 4) & 7),
Rdir: expand[(v>>2)&3],
Ddir: expand[(v>>0)&3],
}
@@ -122,19 +133,11 @@ func newALU(v uint16) ALU {
func isALU(v uint16) bool { return v&(7<<13) == 3<<13 }
func (v ALU) value() uint16 {
- ret := v.Opcode << 8
- if v.RtoPC {
- ret |= 1 << 12
- }
- if v.TtoN {
+ ret := uint16(v.Opcode) << 8
+ if v.Ret {
ret |= 1 << 7
}
- if v.TtoR {
- ret |= 1 << 6
- }
- if v.NtoAtT {
- ret |= 1 << 5
- }
+ ret |= uint16(v.Mod) << 4
ret |= uint16(v.Rdir&3) << 2
ret |= uint16(v.Ddir&3) << 0
return ret
@@ -142,44 +145,42 @@ func (v ALU) value() uint16 {
func (v ALU) compile() uint16 { return v.value() | (3 << 13) }
+type Opcode uint16
+
const (
- opT = 0x0
- opN = 0x1
- opTplusN = 0x2
- opTandN = 0x3
- opTorN = 0x4
- opTxorN = 0x5
- opNotT = 0x6
- opNeqT = 0x7
- opNleT = 0x8
- opNrshiftT = 0x9
- opTminus1 = 0xa
- opR = 0xb
- opAtT = 0xc
- opNlshiftT = 0xd
- opDepth = 0xe
- opNuleT = 0xf
+ OpT Opcode = 0
+ OpN Opcode = 1
+ OpTplusN Opcode = 2
+ OpTandN Opcode = 3
+ OpTorN Opcode = 4
+ OpTxorN Opcode = 5
+ OpNotT Opcode = 6
+ OpNeqT Opcode = 7
+ OpNleT Opcode = 8
+ OpNrshiftT Opcode = 9
+ OpNlshiftT Opcode = 10
+ OpR Opcode = 11
+ OpAtT Opcode = 12
+ OpIoAtT Opcode = 13
+ OpStatus Opcode = 14
+ OpNuLeT Opcode = 15
)
var opcodeNames = []string{
"T", "N", "T+N", "T∧N", "T∨N", "T⊻N", "¬T", "N=T",
- "N<T", "N≫T", "T-1", "R", "[T]", "N≪T", "depth", "Nu<T",
+ "N<T", "N≫T", "N≪T", "R", "[T]", "io[T]", "status", "Nu<T",
+}
+
+var modNames = []string{
+ "", "T→N", "T→R", "N→[T]", "N→io[T]",
}
func (v ALU) String() string {
- s := "ALU " + opcodeNames[v.Opcode]
- if v.RtoPC {
- s += " R→PC"
- }
- if v.TtoN {
- s += " T→N"
- }
- if v.TtoR {
- s += " T→R"
- }
- if v.NtoAtT {
- s += " N→[T]"
+ s := "ALU " + opcodeNames[int(v.Opcode)]
+ if v.Ret {
+ s += " Ret"
}
+ s += modNames[int(v.Mod)]
if v.Rdir != 0 {
s += fmt.Sprintf(" r%+d", v.Rdir)
}
diff --git a/parse_test.go b/parse_test.go
index 859f933..d68e5dc 100644
--- a/parse_test.go
+++ b/parse_test.go
@@ -1,3 +1,5 @@
+// +build broken
+
package j1
import (
diff --git a/stack.go b/stack.go
index c3709a3..b3b0922 100644
--- a/stack.go
+++ b/stack.go
@@ -5,6 +5,14 @@ type stack struct {
sp int8 // 5 bit stack pointer
}
+func (s *stack) readAt(addr uint16) uint16 {
+ return s.data[int(addr)]
+}
+
+func (s *stack) writeAt(addr, value uint16) {
+ s.data[int(addr)] = value
+}
+
func (s *stack) move(dir int8) {
s.sp = (s.sp + dir) & 0x1f
}