summaryrefslogtreecommitdiff
path: root/libgo/go/exp/spacewar/pdp1.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/exp/spacewar/pdp1.go')
-rw-r--r--libgo/go/exp/spacewar/pdp1.go389
1 files changed, 0 insertions, 389 deletions
diff --git a/libgo/go/exp/spacewar/pdp1.go b/libgo/go/exp/spacewar/pdp1.go
deleted file mode 100644
index e3abd6807fd..00000000000
--- a/libgo/go/exp/spacewar/pdp1.go
+++ /dev/null
@@ -1,389 +0,0 @@
-// Copyright (c) 1996 Barry Silverman, Brian Silverman, Vadim Gerasimov.
-// Portions Copyright (c) 2009 The Go Authors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// This package and spacewar.go implement a simple PDP-1 emulator
-// complete enough to run the original PDP-1 video game Spacewar!
-// See ../../nacl/README for details on running them.
-//
-// They are a translation of the Java emulator pdp1.java in
-// http://spacewar.oversigma.com/sources/sources.zip.
-//
-// See also the PDP-1 handbook at http://www.dbit.com/~greeng3/pdp1/pdp1.html
-//
-// http://spacewar.oversigma.com/readme.html reads:
-//
-// Spacewar! was conceived in 1961 by Martin Graetz, Stephen Russell,
-// and Wayne Wiitanen. It was first realized on the PDP-1 in 1962 by
-// Stephen Russell, Peter Samson, Dan Edwards, and Martin Graetz,
-// together with Alan Kotok, Steve Piner, and Robert A Saunders.
-// Spacewar! is in the public domain, but this credit paragraph must
-// accompany all distributed versions of the program.
-//
-// This is the original version! Martin Graetz provided us with a
-// printed version of the source. We typed in in again - it was about
-// 40 pages long - and re-assembled it with a PDP-1 assembler written
-// in PERL. The resulting binary runs on a PDP-1 emulator written as
-// a Java applet. The code is extremely faithful to the original. There
-// are only two changes. 1)The spaceships have been made bigger and
-// 2) The overall timing has been special cased to deal with varying
-// machine speeds.
-//
-// The "a", "s", "d", "f" keys control one of the spaceships. The "k",
-// "l", ";", "'" keys control the other. The controls are spin one
-// way, spin the other, thrust, and fire.
-//
-// Barry Silverman
-// Brian Silverman
-// Vadim Gerasimov
-//
-package pdp1
-
-import (
- "bufio"
- "fmt"
- "os"
- "io"
-)
-
-type Word uint32
-
-const mask = 0777777
-const sign = 0400000
-
-const (
- _ = iota // 00
- opAND
- opIOR
- opXOR
- opXCT
- _
- _
- opCALJDA
-
- opLAC // 10
- opLIO
- opDAC
- opDAP
- _
- opDIO
- opDZM
- _
-
- opADD // 20
- opSUB
- opIDX
- opISP
- opSAD
- opSAS
- opMUS
- opDIS
-
- opJMP // 30
- opJSP
- opSKP
- opSFT
- opLAW
- opIOT
- _
- opOPR
-)
-
-// A Trapper represents an object with a Trap method.
-// The machine calls the Trap method to implement the
-// PDP-1 IOT instruction.
-type Trapper interface {
- Trap(y Word)
-}
-
-// An M represents the machine state of a PDP-1.
-// Clients can set Display to install an output device.
-type M struct {
- AC, IO, PC, OV Word
- Mem [010000]Word
- Flag [7]bool
- Sense [7]bool
- Halt bool
-}
-
-
-// Step runs a single machine instruction.
-func (m *M) Step(t Trapper) os.Error {
- inst := m.Mem[m.PC]
- m.PC++
- return m.run(inst, t)
-}
-
-// Normalize actual 32-bit integer i to 18-bit ones-complement integer.
-// Interpret mod 0777777, because 0777777 == -0 == +0 == 0000000.
-func norm(i Word) Word {
- i += i >> 18
- i &= mask
- if i == mask {
- i = 0
- }
- return i
-}
-
-type UnknownInstrError struct {
- Inst Word
- PC Word
-}
-
-func (e UnknownInstrError) String() string {
- return fmt.Sprintf("unknown instruction %06o at %06o", e.Inst, e.PC)
-}
-
-type HaltError Word
-
-func (e HaltError) String() string {
- return fmt.Sprintf("executed HLT instruction at %06o", e)
-}
-
-type LoopError Word
-
-func (e LoopError) String() string { return fmt.Sprintf("indirect load looping at %06o", e) }
-
-func (m *M) run(inst Word, t Trapper) os.Error {
- ib, y := (inst>>12)&1, inst&07777
- op := inst >> 13
- if op < opSKP && op != opCALJDA {
- for n := 0; ib != 0; n++ {
- if n > 07777 {
- return LoopError(m.PC - 1)
- }
- ib = (m.Mem[y] >> 12) & 1
- y = m.Mem[y] & 07777
- }
- }
-
- switch op {
- case opAND:
- m.AC &= m.Mem[y]
- case opIOR:
- m.AC |= m.Mem[y]
- case opXOR:
- m.AC ^= m.Mem[y]
- case opXCT:
- m.run(m.Mem[y], t)
- case opCALJDA:
- a := y
- if ib == 0 {
- a = 64
- }
- m.Mem[a] = m.AC
- m.AC = (m.OV << 17) + m.PC
- m.PC = a + 1
- case opLAC:
- m.AC = m.Mem[y]
- case opLIO:
- m.IO = m.Mem[y]
- case opDAC:
- m.Mem[y] = m.AC
- case opDAP:
- m.Mem[y] = m.Mem[y]&0770000 | m.AC&07777
- case opDIO:
- m.Mem[y] = m.IO
- case opDZM:
- m.Mem[y] = 0
- case opADD:
- m.AC += m.Mem[y]
- m.OV = m.AC >> 18
- m.AC = norm(m.AC)
- case opSUB:
- diffSigns := (m.AC^m.Mem[y])>>17 == 1
- m.AC += m.Mem[y] ^ mask
- m.AC = norm(m.AC)
- if diffSigns && m.Mem[y]>>17 == m.AC>>17 {
- m.OV = 1
- }
- case opIDX:
- m.AC = norm(m.Mem[y] + 1)
- m.Mem[y] = m.AC
- case opISP:
- m.AC = norm(m.Mem[y] + 1)
- m.Mem[y] = m.AC
- if m.AC&sign == 0 {
- m.PC++
- }
- case opSAD:
- if m.AC != m.Mem[y] {
- m.PC++
- }
- case opSAS:
- if m.AC == m.Mem[y] {
- m.PC++
- }
- case opMUS:
- if m.IO&1 == 1 {
- m.AC += m.Mem[y]
- m.AC = norm(m.AC)
- }
- m.IO = (m.IO>>1 | m.AC<<17) & mask
- m.AC >>= 1
- case opDIS:
- m.AC, m.IO = (m.AC<<1|m.IO>>17)&mask,
- ((m.IO<<1|m.AC>>17)&mask)^1
- if m.IO&1 == 1 {
- m.AC = m.AC + (m.Mem[y] ^ mask)
- } else {
- m.AC = m.AC + 1 + m.Mem[y]
- }
- m.AC = norm(m.AC)
- case opJMP:
- m.PC = y
- case opJSP:
- m.AC = (m.OV << 17) + m.PC
- m.PC = y
- case opSKP:
- cond := y&0100 == 0100 && m.AC == 0 ||
- y&0200 == 0200 && m.AC>>17 == 0 ||
- y&0400 == 0400 && m.AC>>17 == 1 ||
- y&01000 == 01000 && m.OV == 0 ||
- y&02000 == 02000 && m.IO>>17 == 0 ||
- y&7 != 0 && !m.Flag[y&7] ||
- y&070 != 0 && !m.Sense[(y&070)>>3] ||
- y&070 == 010
- if (ib == 0) == cond {
- m.PC++
- }
- if y&01000 == 01000 {
- m.OV = 0
- }
- case opSFT:
- for count := inst & 0777; count != 0; count >>= 1 {
- if count&1 == 0 {
- continue
- }
- switch (inst >> 9) & 017 {
- case 001: // rotate AC left
- m.AC = (m.AC<<1 | m.AC>>17) & mask
- case 002: // rotate IO left
- m.IO = (m.IO<<1 | m.IO>>17) & mask
- case 003: // rotate AC and IO left.
- w := uint64(m.AC)<<18 | uint64(m.IO)
- w = w<<1 | w>>35
- m.AC = Word(w>>18) & mask
- m.IO = Word(w) & mask
- case 005: // shift AC left (excluding sign bit)
- m.AC = (m.AC<<1|m.AC>>17)&mask&^sign | m.AC&sign
- case 006: // shift IO left (excluding sign bit)
- m.IO = (m.IO<<1|m.IO>>17)&mask&^sign | m.IO&sign
- case 007: // shift AC and IO left (excluding AC's sign bit)
- w := uint64(m.AC)<<18 | uint64(m.IO)
- w = w<<1 | w>>35
- m.AC = Word(w>>18)&mask&^sign | m.AC&sign
- m.IO = Word(w)&mask&^sign | m.AC&sign
- case 011: // rotate AC right
- m.AC = (m.AC>>1 | m.AC<<17) & mask
- case 012: // rotate IO right
- m.IO = (m.IO>>1 | m.IO<<17) & mask
- case 013: // rotate AC and IO right
- w := uint64(m.AC)<<18 | uint64(m.IO)
- w = w>>1 | w<<35
- m.AC = Word(w>>18) & mask
- m.IO = Word(w) & mask
- case 015: // shift AC right (excluding sign bit)
- m.AC = m.AC>>1 | m.AC&sign
- case 016: // shift IO right (excluding sign bit)
- m.IO = m.IO>>1 | m.IO&sign
- case 017: // shift AC and IO right (excluding AC's sign bit)
- w := uint64(m.AC)<<18 | uint64(m.IO)
- w = w >> 1
- m.AC = Word(w>>18) | m.AC&sign
- m.IO = Word(w) & mask
- default:
- goto Unknown
- }
- }
- case opLAW:
- if ib == 0 {
- m.AC = y
- } else {
- m.AC = y ^ mask
- }
- case opIOT:
- t.Trap(y)
- case opOPR:
- if y&0200 == 0200 {
- m.AC = 0
- }
- if y&04000 == 04000 {
- m.IO = 0
- }
- if y&01000 == 01000 {
- m.AC ^= mask
- }
- if y&0400 == 0400 {
- m.PC--
- return HaltError(m.PC)
- }
- switch i, f := y&7, y&010 == 010; {
- case i == 7:
- for i := 2; i < 7; i++ {
- m.Flag[i] = f
- }
- case i >= 2:
- m.Flag[i] = f
- }
- default:
- Unknown:
- return UnknownInstrError{inst, m.PC - 1}
- }
- return nil
-}
-
-// Load loads the machine's memory from a text input file
-// listing octal address-value pairs, one per line, matching the
-// regular expression ^[ +]([0-7]+)\t([0-7]+).
-func (m *M) Load(r io.Reader) os.Error {
- b := bufio.NewReader(r)
- for {
- line, err := b.ReadString('\n')
- if err != nil {
- if err != os.EOF {
- return err
- }
- break
- }
- // look for ^[ +]([0-9]+)\t([0-9]+)
- if line[0] != ' ' && line[0] != '+' {
- continue
- }
- i := 1
- a := Word(0)
- for ; i < len(line) && '0' <= line[i] && line[i] <= '7'; i++ {
- a = a*8 + Word(line[i]-'0')
- }
- if i >= len(line) || line[i] != '\t' || i == 1 {
- continue
- }
- v := Word(0)
- j := i
- for i++; i < len(line) && '0' <= line[i] && line[i] <= '7'; i++ {
- v = v*8 + Word(line[i]-'0')
- }
- if i == j {
- continue
- }
- m.Mem[a] = v
- }
- return nil
-}