Skip to content

Commit 8ebf062

Browse files
committed
Added stop on branch to self
1 parent 6218bb2 commit 8ebf062

15 files changed

+50
-17
lines changed

cpu.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,28 +134,31 @@ func (c *Processor) Run() (err error) {
134134
if c.M == nil {
135135
return errNoProgram
136136
}
137-
c.runState = RunStateRunning
138-
for err == nil && c.runState == RunStateRunning {
137+
for {
139138
err = c.Step()
139+
if err != nil || c.runState == RunStateStopped {
140+
break
141+
}
140142
}
141-
c.runState = RunStateStopped
142143
return
143144
}
144145

145146
// Step executes the single instruction located at the address specified by the
146147
// program counter register.
147148
func (c *Processor) Step() (err error) {
148-
// TODO: consider prefetching a whole page of instructions and measure
149+
c.runState = RunStateRunning
149150

150151
// read from program pointer into op
152+
// TODO: consider prefetching a whole page of instructions and measure
151153
if _, err = c.M.Read(int(c.PC), c.buf[0:2]); err != nil {
152154
return
153155
}
154156
c.op = uint16(c.buf[0])<<8 + uint16(c.buf[1])
155-
156157
if c.op == 0 {
157-
// TODO: 0 is a valid instruction. Find a way to terminate programs
158-
// without buffer overrun.
158+
// 0x0000 is a valid instruction (ori.b #$0,D0), but is commonly found when
159+
// a program fails to terminate gracefully and we start reading zeroed
160+
// memory. Since this instruction has no practical use, for now, we treat it
161+
// as an indicator that a program has finished and stop the processor.
159162
c.runState = RunStateStopped
160163
return
161164
}

m68kmem/mapper.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ func (mm *Mapper) Write(addr int, p []byte) (n int, err error) {
8989
for m := mm.mappings; m != nil; m = m.next {
9090
if m.start <= addr && m.end >= addr {
9191
addr -= m.start
92-
return m.m.Write(addr, p)
92+
n, err = m.m.Write(addr, p)
93+
return
9394
}
9495
}
9596
return 0, accessViolationError(addr)

m68kmem/rom.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ func (m *rom) Read(addr int, p []byte) (n int, err error) {
2020
return
2121
}
2222

23+
// Write always returns an AccessViolationError.
2324
func (m *rom) Write(addr int, p []byte) (n int, err error) {
24-
return 0, accessViolationError(addr)
25+
err = accessViolationError(addr)
26+
return
2527
}
2628

29+
// Reset does nothing, but is required to implement the Memory interface.
2730
func (m *rom) Reset() (err error) {
28-
for i := 0; i < len(m.b); i++ {
29-
m.b[i] = 0
30-
}
31+
// no-op
3132
return
3233
}

op0_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func TestMove(t *testing.T) {
5757
0x22, 0x40, // movea.l D0,A1
5858
0x20, 0x7C, 0x00, 0x00, 0x20, 0x00, // movea.l #$2000,A0
5959
0x20, 0x80, // move.l D0,(A0)
60+
0x4E, 0x72, 0x27, 0x00, // stop #$2700
6061
})
6162
AssertRun(t, p)
6263
AssertDataRegister(t, p, 0, 0xFFFFFFFF)
@@ -84,6 +85,7 @@ func TestAndi(t *testing.T) {
8485
0x02, 0x01, 0x00, 0x0F, // andi.b #$0F,D1
8586
0x02, 0x41, 0x0F, 0xFF, // andi.w #$0FFF,D1
8687
0x02, 0x81, 0x0F, 0x0F, 0xFF, 0xFF, // andi.l #$0F0FFFFF,D1
88+
0x4E, 0x72, 0x27, 0x00, // stop #$2700
8789
}
8890
// p := LoadFile(t, "testdata/test-op-andi.h68")
8991
p := LoadBytes(t, b)
@@ -100,6 +102,7 @@ func TestSubi(t *testing.T) {
100102
0x04, 0x80, 0x00, 0x00, 0x00, 0x01, // subi.l #$1,D0
101103
0x04, 0x41, 0x00, 0x01, // subi.w #$1,D1
102104
0x04, 0x02, 0x00, 0x01, // subi.b #$1,D2
105+
0x4E, 0x72, 0x27, 0x00, // stop #$2700
103106
})
104107
p.D[0], p.D[1], p.D[2] = 0x01234567, 0x01234567, 0x01234567
105108
AssertRun(t, p)
@@ -115,6 +118,7 @@ func TestSubi(t *testing.T) {
115118
0x04, 0x80, 0x00, 0x00, 0x00, 0x01, // subi.l #$1,D0
116119
0x04, 0x41, 0x00, 0x01, // subi.w #$1,D1
117120
0x04, 0x02, 0x00, 0x01, // subi.b #$1,D2
121+
0x4E, 0x72, 0x27, 0x00, // stop #$2700
118122
})
119123
p.D[0], p.D[1], p.D[2] = 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF // -1
120124
AssertRun(t, p)
@@ -129,6 +133,7 @@ func TestSubi(t *testing.T) {
129133
0x04, 0x80, 0x02, 0x02, 0x02, 0x02, // subi.l #$2020202,D0
130134
0x04, 0x41, 0x02, 0x02, // subi.w #$202,D1
131135
0x04, 0x02, 0x00, 0x02, // subi.b #$2,D2
136+
0x4E, 0x72, 0x27, 0x00, // stop #$2700
132137
})
133138
p.D[0], p.D[1], p.D[2] = 0x01010101, 0x01010101, 0x01010101
134139
AssertRun(t, p)
@@ -143,6 +148,7 @@ func TestSubi(t *testing.T) {
143148
0x04, 0x80, 0xFF, 0xFF, 0xFF, 0xFE, // subi.l #$-2,D0
144149
0x04, 0x41, 0xFF, 0xFE, // subi.w #$-2,D1
145150
0x04, 0x02, 0x00, 0xFE, // subi.b #$-2,D2
151+
0x4E, 0x72, 0x27, 0x00, // stop #$2700
146152
})
147153
p.D[0], p.D[1], p.D[2] = 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
148154
AssertRun(t, p)

op4.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func opMovem(c *Processor) (t *stepTrace) {
118118
addr: c.PC,
119119
n: 1,
120120
op: "movem",
121-
sz: []uint16{SizeWord, SizeLong}[c.op&0x0040>>6],
121+
sz: []uint16{SizeWord, SizeLong}[c.op&0x40>>6],
122122
}
123123
c.PC += 2
124124
regl, _, _ := c.readImmWord() // register list
@@ -272,10 +272,12 @@ func opRts(c *Processor) (t *stepTrace) {
272272
sz: noSize,
273273
n: 1,
274274
}
275+
// move program counter to the address at the top of the stack
275276
c.PC, t.err = c.M.Long(int(c.A[7]))
276277
if t.err != nil {
277278
return
278279
}
280+
// increment stack pointer
279281
c.A[7] += 4
280282
return
281283
}

op6.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,11 @@ func opBcc(c *Processor) (t *stepTrace) {
6565
return
6666
}
6767
c.PC = uint32((int32(t.addr+2) + disp))
68+
if cc == 0 && c.PC == t.addr {
69+
// this is a branch to self - a common pattern to terminate a program by
70+
// placing the processor in an infinite loop. As a convenience to users,
71+
// let's stop the processor.
72+
t.err = c.Stop()
73+
}
6874
return
6975
}

testdata/test-op-addi.h68

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
S004000020DB
22
S1251000060000FF060000FF0641FFFF0641FFFF0682FFFFFFFF0682FFFFFFFF060300FF0643DD
3-
S10B1022FF000683FFFF00003C
3+
S10F1022FF000683FFFF00004E72270051
44
S9030000FC

testdata/test-op-addi.lis

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
0000101C 0603 00FF 17 addi.b #$FF,D3 ; add 0xFF to D3
1818
00001020 0643 FF00 18 addi.w #$FF00,D3 ; add 0xFF00 to D3
1919
00001024 0683 FFFF0000 19 addi.l #$FFFF0000,D3 ; add 0xFFFF0000
20+
0000102A 20
21+
0000102A 4E72 2700 21 stop #$2700
2022

2123
No errors detected
2224
No warnings generated

testdata/test-op-addi.x68

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@
1717
addi.b #$FF,D3 ; add 0xFF to D3
1818
addi.w #$FF00,D3 ; add 0xFF00 to D3
1919
addi.l #$FFFF0000,D3 ; add 0xFFFF0000
20+
21+
stop #$2700

testdata/test-op-move-l.h68

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ S12510224432443220FCFFFFFFFF2100203C4433443321400004203C4434443421C0201023C094
44
S125104400012000207C41304130244824082C7C000030002C88207C413141312C7C0000300467
55
S12510662CC8207C413241322CFCFFFFFFFF2D08207C4133413321C8300C23C800013000267C2E
66
S125108849304930263C49304930207C0000F00020BC49304930207C0000F00420FC4931493102
7-
S12310AA20FCFFFFFFFF213C4932493223FC493349330000F00C23FC493349330001F0009C
7+
S12510AA20FCFFFFFFFF213C4932493223FC493349330000F00C23FC493349330001F0004E72DA
8+
S10510CC2700F7
89
S9030000FC

testdata/test-op-move-l.lis

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
000010B6 65
6666
000010B6 23FC 49334933 0000F00C 66 move.l #$49334933,$F00C * immediate to absolute short
6767
000010C0 23FC 49334933 0001F000 67 move.l #$49334933,$1F000 * immediate to absolute long
68-
68+
000010CA 68
69+
000010CA 4E72 2700 69 stop #$2700
6970
No errors detected
7071
No warnings generated

testdata/test-op-move-l.x68

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,5 @@
6565

6666
move.l #$49334933,$F00C * immediate to absolute short
6767
move.l #$49334933,$1F000 * immediate to absolute long
68+
69+
stop #$2700

testdata/test-op-ori.h68

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ S12510220080004101000041020000410400004108000041100000412000004140000041800021
44
S1231044008100010000008100020000008100040000008100080000008100100000008163
55
S125106400200000008100400000008100800000008101000000008102000000008104000000FA
66
S1231086008108000000008110000000008120000000008140000000008180000000008148
7-
S11510A6000000000002001100431111008411111111F4
7+
S11710A600000000000200110043111100841111111160FE94
88
S9030000FC

testdata/test-op-ori.lis

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
000010B2 49
5050
000010B2 50 * assuming D4 = $22222222
5151
000010B2 0084 11111111 51 ori.l #$11111111,D4
52+
000010B8 52
53+
000010B8 53 forever:
54+
000010B8 60FE 54 bra forever
5255

5356
No errors detected
5457
No warnings generated

testdata/test-op-ori.x68

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,6 @@
4949

5050
* assuming D4 = $22222222
5151
ori.l #$11111111,D4
52+
53+
forever:
54+
bra forever

0 commit comments

Comments
 (0)