WD16


The WD16 is a 16-bit microprocessor introduced by Western Digital in October 1976. It is based on the MCP-1600 chipset, a general-purpose design that was also used to implement the DEC LSI-11 low-end minicomputer and the Pascal MicroEngine processor. The three systems differed primarily in their microcode, giving each system a unique instruction set architecture.
The WD16 implements an extension of the PDP-11 instruction set architecture but is not machine code compatible with the PDP-11. The instruction set and microcoding were created by Dick Wilcox and Rich Notari. The WD16 is an example of orthogonal CISC architecture. Most two-operand instructions can operate memory-to-memory with any addressing mode and some instructions can result in up to ten memory accesses.
The WD16 is implemented in five 40-pin DIP packages. Maximum clock speed is 3.3 MHz. Its interface to memory is via a 16-bit multiplexed data/address bus.
The WD16 is best known for its use in Alpha Microsystems' AM-100 and AM-100/T processor boards. A prototype was demonstrated in 1977. As of 1981 there were at least 5,000 Alpha Micro computers based on the WD16. As late as 1982, WD16-based Alpha Micros were still being characterized as "supermicros." The WD16 was superseded by the Motorola 68000 in June 1982.

CPU registers

The CPU contains eight general-purpose 16-bit registers, R0 to R7. The registers can be used for any purpose with these exceptions: Register R7 is the program counter. Although any register can be used as a stack pointer, R6 is the stack pointer used for hardware interrupts and traps. R0 is the count for the block transfer instructions.

Memory

Data formats

The smallest unit of addressable and writable memory is the 8-bit byte. Bytes can also be held in the lower half of registers R0 through R5.
16-bit words are stored little-endian with least significant bytes at the lower address. Words are always aligned to even memory addresses. Words can be held in registers R0 through R7.
32-bit double words can only be stored in register pairs with the lower word being stored in the lower-numbered register. 32 bit values are used by MUL, DIV and some rotate and arithmetic shift instructions.
Floating point values are 48 bits long and can only be stored in memory. This format is half-way between single and double precision floating point formats. They are stored an unusual middle-endian format sometimes referred to as "PDP-endian." Floating point values are always aligned to even addresses. The first word contains the sign, exponent, and high byte of the mantissa. The next higher address contains the middle two bytes of the mantissa, and the next higher address contains the lowest two bytes of the mantissa. The complete format is as follows:
1. A 1 bit sign for the entire number which is zero for positive.
2. An 8-bit base-two exponent in excess-128 notation with a range of +127, -128. The only legal number with an exponent of -128 is true zero.
3. A 40 bit mantissa with the MSB implied.

Memory management

The WD16's 16-bit addresses can directly access 64 KB of memory. The WD16 does not offer any inherent memory management or protection. In the AM-100 application, the last 256 memory locations are mapped to port space. As most AM-100 computers were used as multi-user computers, the memory would usually be expanded past 64K with bank switching. Although the AM-100 could be configured for up to 22 users and 512 Kilobytes of RAM, a typical memory configuration for a 9-user AM-100 might be in the range of 352 Kilobytes. In 1981 an optional AM-700 memory management unit was offered for the AM-100/T which allowed memory segmentation in 256 byte increments.

Addressing modes

Most instructions allocate six bits to specify each operand. Three bits select one of eight addressing modes and three bits select a general register. The encoding of the six bit operand addressing mode is as follows:
In the following sections, each item includes an example of how the operand would be written in assembly language. Rn means one of the eight registers, written R0 through R7.

General register addressing modes

The following eight modes can be applied to any general register. Their effects when applied to R6 and R7 are set out separately in the following sections.
CodeNameExampleDescription
0nRegisterRnThe operand is in Rn
1nRegister deferredRn contains the address of the operand
2nAutoincrement+Rn contains the address of the operand, then increment Rn
3nAutoincrement deferred@+Rn contains the address of the address of the operand, then increment Rn by 2
4nAutodecrementDecrement Rn, then use the result as the address of the operand
5nAutodecrement deferred@−Decrement Rn by 2, then use the result as the address of the address of the operand
6nIndexXRn+X is the address of the operand
7nIndex deferred@XRn+X is the address of the address of the operand

In index and index deferred modes, X is a 16-bit value taken from a second word of the instruction. In double-operand instructions, both operands can use these modes. Such instructions are three words long.
Autoincrement and autodecrement operations on a register are by 1 in byte instructions, by 2 in word instructions, and by 2 whenever a deferred mode is used, since the quantity the register addresses is a pointer.

Program counter addressing modes

When R7 is specified, four of the addressing modes naturally yield useful effects:
CodeNameExampleDescription
27Immediate#nThe operand is the next word of the instruction
37Absolute@#aThe address of the operand is the next word of the instruction
67RelativeaThe address of the operand is the next word of the instruction added to the PC
77Relative deferred@aThe address of the address of the operand is the next word of the instruction added to PC

There are two common uses of absolute mode, whose syntax combines immediate and deferred mode. The first is accessing the reserved processor locations at 0000-003F. The other is to specify input/output registers in port space, as the registers for each device have specific memory addresses. Relative mode has a simpler syntax and is more typical for referring to program variables and jump destinations. A program that uses relative mode exclusively for internal references is position-independent; it contains no assumptions about its own location, so it can be loaded into an arbitrary memory location, or even moved, with no need for its addresses to be adjusted to reflect its location. In computing such addresses relative to the current location, the processor performs relocation on the fly.
Immediate and absolute modes are merely autoincrement and autoincrement deferred modes, respectively, applied to PC. When the auxiliary word is in the instruction, the PC for the next instruction is automatically incremented past the auxiliary word. As PC always points to words, the autoincrement operation is always by a stride of 2.

Stack addressing modes

R6, also written SP, is used as a hardware stack for traps and interrupts. A convention enforced by the set of addressing modes the WD16 provides is that a stack grows downward—toward lower addresses—as items are pushed onto it. When a mode is applied to SP, or to any register the programmer elects to use as a software stack, the addressing modes have the following effects:
CodeNameExampleDescription
16DeferredThe operand is on the top of the stack
26Autoincrement+The operand is on the top of the stack, then pop it off
36Autoincrement deferred@+A pointer to the operand is on top of stack; pop the pointer off
46AutodecrementPush a value onto the stack
66IndexedXThe operand is located X distance from the top of stack
76Indexed deferred@XThe pointer to the operand is located X distance from the top of stack

Although software stacks can contain bytes, SP always points to a stack of words. Autoincrement and autodecrement operations on SP are always by a stride of 2.

Instruction set

Most of the WD16 instructions operate on bytes and words. Bytes are specified by a register number—identifying the register's low-order byte—or by a memory location. Words are specified by a register number or by the memory location of the low-order byte, which must be an even number. All opcodes and addresses are expressed in hexadecimal.

Double-operand instructions

The high-order four bits specify the operation to be performed. Two groups of six bits specify the source operand addressing mode and the destination operand addressing mode, as defined above. This group of instructions takes up 75% of available opcodes.
OpcodeMnemonicOperation
1000ADDAdd: Dest ← Dest + Src
2000SUBSubtract: Dest ← Dest - Src
3000ANDAnd: Dest ← Dest ∧ Src
4000BICBit clear: Dest ← Dest ∧
5000BISBit Set: Dest ← Dest ∨ Src
6000XORExclusive or: Dest ← Dest ⊻ Src
9000CMPCompare: Src − Dest
A000BITBit test: Dest ∧ Src
B000MOVMove: Dest ← Src
C000CMPBCompare byte: Src − Dest
D000MOVBMove byte: Dest ← Src
E000BISBBit set byte: Dest ← Dest ∨ Src

Some two-operand instructions utilize an addressing mode for one operand and a register for the second operand:
The high-order seven bits specify the operation to be performed, six bits specify the operand addressing mode and three bits specify a register or register pair. Where a register pair is used Reg contains the low-order portion of the operand. The next higher numbered register contains the high-order portion of the operand.
OpcodeMnemonicOperation
7200LEALoad effective address: Reg ← ea
73C0JMPJump: PC ← ea
7400ASHArithmetic shift: if Src < 0 then Reg ← Shift-right else Reg ← Shift-left
7800XCHExchange: Reg ↔ Src
7A00ASHCArithmetic shift combined : if Src < 0 then ← Shift-right else ← Shift-left
7C00MULUnsigned multiply: ← Reg × Src
7E00DIVUnsigned divide: Compute ÷ Src; Reg ← quotient; Reg+1 ← remainder