Wang 3300 Origin (link)
Before Wang made the incredibly successful 2200 series of computers, they had attempted the job at least twice before, with the Wang 4000 Computer System and the 3300 BASIC computer. Where one draws the line between their programmable calculators and their calculating computers is debatable.
Rick Bensene has done a tremendous job of documenting the Wang timeline, starting at their calculators, turning up a lot of great information on the "4000" system as well as the "3300 BASIC" system, which is also described here. If you want to see a bigger picture, as well as alternate information on the 3300, please read what Rick has written.
In June 1968, Wang bought out Philip Hankins Incorporated (PHI), a mainframe data processing services supplier. Wang was interested in them for their software expertise as well as the fact that they owned an IBM 360/65. This powerful mainframe played an important role in the development of the 3300.
After acquiring PHI, Wang moved quickly. They kicked off two computer designs with in a few months. Although both were intended as general purpose CPUs, one of them ended up getting diverted into being a super calculator instead of an inexpensive computer. This became known as the 700 series of programmable calculators, a tremendously successful and important product for Wang. The other machine, which ended up being named the 3300 BASIC computer, was aimed directly at the PDP-8 customer.
While the hardware design of the 3300 progressed, the software group was busy simulating their software creations on their IBM 360 system, via a software simulation of the 3300 hardware. According to Wang's press releases of the time, the early experiences of writing code for the simulated machine directly lead to changes in the 3300's hardware design. Besides having a BASIC interpreter, the system had an assembler, a loader, and diagnostic software. Wang also envisioned a library of applications to run on the machine that could be a source of continuing revenue. The software applications manager was Bob Kolk, who would later become the project lead for the first generation 2200 family.
Although the 3300 design got off to a quick start, the product was late getting to market. The product was announced and orders were taken in the spring of 1970, although it was almost a year before any units actually shipped. It didn't matter much because the system didn't sell well.
3300 System Configuration (link)
The 3300 was a modular system. Although the minimum configuration was for one user, the machine was most cost effective when used in timesharing mode, since most of the cost could be amortized over all the users. Up to 16 users could be accommodated with one CPU, and a system could have up to 64 KB of RAM. I/O was performed using modified IBM Selectric typewriters. Optionally, teletype consoles could be used instead.
According to the press of the time, the line item costs were as follows:
Item | Unit Cost |
---|---|
CPU + 4KB RAM | $4,950 |
4KB RAM expansion | $2,500 |
Selectric terminal | $4,200 |
Terminal control unit | $500 |
Cassette storage | $1,400 |
BASIC software and system setup | $1,500 |
Besides the cassette storage, 64KB disk and 0.5 MB disk storage was promised for future delivery. It took a while for that to appear, so early users were stuck loading system software via paper tape. This became a major sore point. Loading BASIC was a multi-step process, requiring toggling in a tape boot loader by hand, loading a bootstrap loader from paper tape, then loading the BASIC interpreter from paper tape. It took on the order of 40 minutes to get the interpreter running. Then came the process of loading the BASIC program itself, if required.
Tom Lake, a user of the 3300, says that the cassette tape option showed up in 1972, but it wasn't reliable enough for common use.
The base 3300 configuration was to have the CPU, 12 KB of core memory (three 4 KB boards), two Selectric terminals, a terminal control unit (suitable for controlling up to four Selectrics), cassette storage, and BASIC software, all for a total cost of $17,550. There was an option to do without cassette storage for $15,200.
3300 Front Panel (link)
Like all good minicomputers (and even early microcomputers), the 3300 had a front panel with a lot of indicator lights and switches. Besides looking whizzy, they were useful for debugging and for doing an initial program load (i.e., a tiny program that tells the computer how to load a much larger program off of the paper tape.)
Although programmed primarily via the BASIC language, the 3300 was a general-purpose machine. The user visible state of the machine appeared almost entirely on the front panel. Those fields were:
- A, an 8b register; the primary accumulator
- Z, an 8b register; utility register; some instructions pair {Z,A} to form a 16b register
- S, an 8b register; holds the usual collection of status flags
- BC, a 16b register; the program counter
- M, an 8b register; the most recent 8b of data to or from memory
The group of eight toggle buttons "80", "40", "20", "10", "8", "4", "2", "1" was used to specify an 8b value. By themselves they did nothing, but this 8b value was used by other front panel operations, described next.
A group of three buttons labeled "Run", "Display", and "Enter" set the major operating mode.
- In "Enter" mode, pressing one of the momentary buttons labeled "B", "C", "Z", "A", "S", "M" would set the selected register to the 8b immediate value. Pressing "Core" caused a write of the 8b immediate value to the location addressed by the {B,C} pair, and also incremented the {B,C} pair, making it easier to enter programs, most frequently the boot loader program.
- "Display" mode was useful for inspecting memory. First, a 16b address value was entered into the {B,C} pair using the Enter mode. Pressing the "Core" button caused the memory at that location to be fetched into the M register, which is displayed on the Memory lamps. Each press of Core would also cause {B,C} to increment, making it easy to inspect the contents of a range of memory.
-
"Run" mode, as the name implies, was used to allow a program to run,
or to be stopped or single stepped. After setting up the {B,C} pair
to the starting program counter location using Enter mode, the Run
button was depressed to establish Run mode. Pressing Run would not
do anything by itself, other than esablishing run mode. One of the
four buttons in the rightmost group would select what type of run
behavior to perform.
- The Go button caused the CPU to start running at the location addressed by the {B,C} pair.
- The Step button caused a running program to halt. If the program was halted, one instruction would be fetched and executed, then the program would halt again.
- Pressing the Exq button would execute an instruction entered directly from the front panel.
- Load wasn't described in the manual. According to Rick Bensene, this was used in some models to trigger a small bootloader program.
3300 Architecture Overview (link)
This section gives a brief overview of the CPU architecture, but please consult the 3300 Computer Reference Manual for more detailed information.
According to Sam Gagliano, who worked on the 3300 line for a couple of years, the 3300 was positioned to compete against DEC's PDP-8 and PDP-11 series as well as Data General's Nova series. He said of the 3300,
It was doomed from the start because Wang sales people knew nothing about selling general purpose minicomputers. Wang products were always turn 'em on and they boot by themselves. No knowledge required of set up, booting and languages required.
The memory system used core memory, populated by adding 4 KB boards. To run BASIC and have a small amount of memory left over for one user required at least 12 KB of RAM, but the intended multiuser configuration practically needed at least 20 KB. Memory cycle time was 1.6 µs in each 1.6 µs one byte could be read, or written, or read, modified, and written back to the same address.
Instruction execution time was largely determined simply by the number of addresses of memory it had to touch. For instance, the AI instruction (add an 8 bit immediate value to the A register) required fetching the two instruction bytes, so it took 3.2 µs. The DAM instruction (the {Z,A} register pair are added to the value already stored in a pair of adjacent locations in memory) took 6.2 µs as it had to fetch two instruction bytes, then perform two read/modify/write operations to affect the add to memory. If the DAM instruction used indirect address, which required reading two memory locations to find the address of the place in memory to add to, the time went up to six memory cycles, taking 9.4 µs, the slowest instruction available.
All instructions were two bytes long, aligned on even address boundaries. The first byte contained the opcode and addressing mode information, while the second byte contained either an immediate 8 bit value, or the lower 8 bits of an address, which was interpreted according to the address mode encoded in the first byte. The instruction set operated on individual bytes and byte pairs, although one instruction allowed writing to a single nibble of a memory location. Most operations used binary math, but half a dozen could operate using either binary or BCD math based on the setting of the decimal mode flag in the S (status/control) register.
The instruction set largely viewed memory as 256 pages of 256 bytes each. For instance, for an instruction was at 0x1236, any byte or pair of bytes on that same page, that is page 0x12, could be accessed simply using the current page direct addressing mode: the second byte of the instruction specified the offset of the byte or byte pair on the page.
Absolute direct addressing mode allowed fetching a byte or byte pair from page 0 or page 1 from any page in memory, making page 0 and 1 the best place to store global variables. The choice of page 0 or page 1 wasn't encoded in the instruction; instead it came from the P bit in the S status register.
Most instruction allowed not only current and absolute page direct addressing modes but current page indirect and absolute page indirect modes as well. These are like the direct mode, except the address calculated by the instruction wasn't the location of the operand: it instead contained a pair of bytes forming a 16 bit address which pointed to the location of the operand.
Many instructions went a step further and also supported autoincrement and autodecrement modes. These are just like the indirect modes, but adjust the operand pointer after the operand is accessed (autoincrement) or before the operand access (autodecrement), making it easy to build stacks and do linear traversals of memory in either direction. When operating on byte quantities, the adjustment was by ±1, while operating on byte pairs resulted in an adjustment of ±2.
The CPU had a general purpose I/O bus, which was capable of addressing 128 devices. Devices were either polled or could use the hierarchically prioritized interrupt service. Wang documents say the 3300 had a DMA channel controller, capable of up to 300,000 cps transfer rates, but architectural manual does not provide any detail and the BASIC interpreter didn't use it.
Architecturally, there were a number of registers visible to the programmer:
- The 8 bit "A" register was the accumulator for the instruction set. It could be loaded from memory, or saved to memory, loaded with or combined with an immediate value, or be transferred to/from another register.
- The 8b "Z" register was a much more restricted, but one important feature was that some instructions paired {Z,A} together to form a 16 bit value. This 16 bit value could be loaded from memory, stored to memory, added to memory, shifted, or provide a jump address.
- Conceptually there was the 16 bit {B,C} register pair, but they weren't individually addressable, other than from the front panel! These make up what most architectures call the program counter or instruction pointer.
-
The 8 bit status register, called "S", contained a collection of bits,
including:
- Z(ero) result flag
- C(arry) out flag
- absolute P(page) indicator
- D(ecimal) mode indicator
- V(alid decimal) result status
- S.1 and S.0, two general purpose status bits for software use
The instruction set didn't directly support a call return address stack. Instead, subroutine linkage used a technique fairly common for the 60s. The caller would save the return address to the first two bytes of the the subroutine entry point, and then begin executing the instruction after that. The "JST" instruction performed that linkage. When the subroutine wanted to return, it would perform an indirect jump through the location at the start of the subroutine where the caller had saved the return address. Using the various addressing modes of the instruction set, this return address location was operated upon to perform various calling conventions, including fetching parameters from the call site, or returning to the first instruction after the call on error conditions or returning to the second instruction after the call if there was no error. However, the lack of a stack precluded reentrant calls unless the subroutine manually manipulated a software-constructed stack to avoid problems.
3300 BASIC (link)
Although the 3300 was a general purpose CPU, Wang expected most customers to take advantage of BASIC as the primary means of programming. At that point Dartmouth BASIC was already six years old and had a reputation for ease of use.
The first version of BASIC released for the 3300 lacked alphanumeric variables and supported only the simplest BASIC dialect. Even the first version, though, was designed to support timesharing. A configuration program was run at boot time to establish how many terminals were to be supported and how much memory to allocate to each. After that the BASIC interpreter was loaded, and it gave out time slices to each terminal.
The BASIC interpreter was written within PHI. An Wang's autobiography credits Dave Moros as the author. Wang further said that this code was recycled to become the 2200's BASIC. This isn't literally true: the 3300 instruction set was very different than that used by the 2200. What is true is that the architecture of the 2200 Wang BASIC interpreter was very closely modeled on the 3300's, to the point that they shared some of the same bugs.
In 1971, Wang released an updated version of BASIC, called Extended BASIC. This added some support for alphanumeric variables, although the maximum length string was 18 characters. Extended 3300 BASIC also added a host of matrix operations (MAT statements). Being a more capable interpreter, Extended BASIC ate up more memory, leaving less for each user.
In 3300 BASIC, each variable was a single precision floating point number, represented in memory by five bytes. One byte held the sign of the mantissa, the sign of the exponent, and a six bit exponent magnitude; the other four bytes held eight normalized BCD digits. The maximum representable number was +/- 9.9999999E+63. The smallest non-zero number was +/-1.0000000E-63. Some intermediate calculations were done with an extra byte of precision (two decimal digits), namely, the Taylor series evaluation of the transcendentals, to help maintain accuracy in the final result.
Apparently FORTRAN was also developed for the 3300, but as yet no docs or (heaven forbid) boot tape has surfaced. It isn't just apocryphal, though, because the PARTGEN (partition generator) program, which was used to configure the system for timesharing, had options for setting things up for different versions of BASIC and FORTRAN.
3300 BASIC Decoded (link)
To get the emulator to run 3300 BASIC, I had to do a lot of reverse engineering, as I have detailed no documentation on how to boot BASIC. It was a multi-step process, and the state of each step affects the next. I didn't even know what was the correct program counter entry point to run BASIC. It involved disassembling the boot loaders and the BASIC interpreter to get a handle on how it was all put together and what locations in memory had to be set by the PARTGEN program before BASIC could run. Because of the extensive amount of indirection, the self modifying code, and that some address operations depend on the dynamic state of a bit in the S(tatus) register, it wasn't straightforward.
The task is to separate out data from instructions, and to figure out for each instruction if the P(age) bit would be 0 or 1 during runtime. My approach was to write a Perl script which could decode instructions from a known valid instruction, then advance to the next logical instruction. Along the way all memory references would be noted, which would be printed out and would be used to help decipher what was code, and what was data. When a memory location was found to never be modified, indirections through that location could be resolved to a specific absolute location. It was complicated by the fact that PARTGEN sets up some of those locations.
The Perl script reads in a configuration script which uses a simple notation for adding comments to specific locations, noting which locations are known to be instructions or data, and marking subroutines that have special calling conventions. The Perl program reads in the .HEX image and the configuration script to produce a listing. I ended up deciphering and commenting a bunch of routines that weren't strictly necessary to determine the initial conditions to produce a successful boot of BASIC, but I enjoyed the puzzle. Maybe when I retire in 20 years I will try to figure out the rest. As it is, a bunch of sections are quite speculative.
In case you care, this zip file contains the perl script, the configuration files, the .HEX files, and the resulting output.
Sources (link)
The information presented here was collected from a few sources:
- Riding the Runaway Horse, by Charles C. Kenney
This book doesn't contain very many technical details.
- Lessons, by Dr. An Wang
While rich in technical details, some have called into question the accuracy of Dr. Wang's recollections.
- Wang 3300 brochure
- Some press clippings
- Rick Bensene's web site
- Discussions with Steve Witham, a former 3300 user
- Discussions with Tom Lake, a former 3300 user
- Discussions with Mark Crispin, a former 3300 user
If you have any information on the Wang 3300 family (manuals, instruction set, schematics, sales literature, etc.), or you worked at Wang at the time, please get in contact with me. I'd like to learn more about the machine.