diff options
Diffstat (limited to 'libgo/go/exp/spacewar/pdp1.go')
-rw-r--r-- | libgo/go/exp/spacewar/pdp1.go | 389 |
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 -} |