diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-03 04:34:57 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-03 04:34:57 +0000 |
commit | 7a9389330e91acc3ed05deac2d198af25d13cf3c (patch) | |
tree | 38fe54a4f38ede5d949c915d66191f24a6fe5153 /libgo/go/exp/spacewar/pdp1.go | |
parent | 1aa6700378e5188a853c018256113ce6e1fb5c05 (diff) | |
download | gcc-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.go | 389 |
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 +} |