summaryrefslogtreecommitdiff
path: root/libgo/go/exp/spacewar/pdp1.go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2010-12-03 04:34:57 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2010-12-03 04:34:57 +0000
commit7a9389330e91acc3ed05deac2d198af25d13cf3c (patch)
tree38fe54a4f38ede5d949c915d66191f24a6fe5153 /libgo/go/exp/spacewar/pdp1.go
parent1aa6700378e5188a853c018256113ce6e1fb5c05 (diff)
downloadgcc-7a9389330e91acc3ed05deac2d198af25d13cf3c.tar.gz
Add Go frontend, libgo library, and Go testsuite.
gcc/: * gcc.c (default_compilers): Add entry for ".go". * common.opt: Add -static-libgo as a driver option. * doc/install.texi (Configuration): Mention libgo as an option for --enable-shared. Mention go as an option for --enable-languages. * doc/invoke.texi (Overall Options): Mention .go as a file name suffix. Mention go as a -x option. * doc/frontends.texi (G++ and GCC): Mention Go as a supported language. * doc/sourcebuild.texi (Top Level): Mention libgo. * doc/standards.texi (Standards): Add section on Go language. Move references for other languages into their own section. * doc/contrib.texi (Contributors): Mention that I contributed the Go frontend. gcc/testsuite/: * lib/go.exp: New file. * lib/go-dg.exp: New file. * lib/go-torture.exp: New file. * lib/target-supports.exp (check_compile): Match // Go. From-SVN: r167407
Diffstat (limited to 'libgo/go/exp/spacewar/pdp1.go')
-rw-r--r--libgo/go/exp/spacewar/pdp1.go389
1 files changed, 389 insertions, 0 deletions
diff --git a/libgo/go/exp/spacewar/pdp1.go b/libgo/go/exp/spacewar/pdp1.go
new file mode 100644
index 00000000000..e3abd6807fd
--- /dev/null
+++ b/libgo/go/exp/spacewar/pdp1.go
@@ -0,0 +1,389 @@
+// 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
+}