Pep/8: Reference Documentation

Pep/8 Reference

The Pep/8 computer is a 16-bit complex instruction set computer (CISC). It is designed to teach computer architecture and assembly language programming principles. Its 39 instructions are based on an expanding opcode and are either unary (one byte) or nonunary (three bytes). The eight addressing modes are designed for straighforward translation between C/C++ and assembly language.

Topics: Instruction set, Setting the C bit on subtraction, Setting the N bit on `CPr`, Dot commands, Addressing modes, Register field, Trace tags, Assembly language syntax summary.

### Instruction set

Instruction Specifier | Mnemonic | Instruction | Addressing Modes | Status Bits
--- | --- | --- | --- | ---
`0000 0000` | `STOP` | Stop execution | U |
`0000 0001` | `RETTR` | Return from trap | U |
`0000 0010` | `MOVSPA` | Move SP to A | U |
`0000 0011` | `MOVFLGA` | Move NZVC flags to A | U |
`0000 010a` | `BR` | Branch unconditional | i, x |
`0000 011a` | `BRLE` | Branch if less than or equal to | i, x |
`0000 100a` | `BRLT` | Branch if less than | i, x |
`0000 101a` | `BREQ` | Branch if equal to | i, x |
`0000 110a` | `BRNE` | Branch if not equal to | i, x |
`0000 111a` | `BRGE` | Branch if greater than or equal to | i, x |
`0001 000a` | `BRGT` | Branch if greater than | i, x |
`0001 001a` | `BRV` | Branch if V | i, x |
`0001 010a` | `BRC` | Branch if C | i, x |
`0001 011a` | `CALL` | Call subroutine | i, x |
`0001 100r` | `NOTr` | Bitwise invert r | U | N Z
`0001 101r` | `NEGr` | Negate r | U | N Z V
`0001 110r` | `ASLr` | Arithmetic shift left r | U | N Z V C
`0001 111r` | `ASRr` | Arithmetic shift right r | U | N Z C
`0010 000r` | `ROLr` | Rotate left r | U | C
`0010 001r` | `RORr` | Rotate right r | U | C
`0010 01nn` | `NOPn` | Unary no operation trap | U |
`0010 1aaa` | `NOP` | Nonunary no operation trap | i |
`0011 0aaa` | `DECI` | Decimal input trap | d, n, s, sf, x, sx, sxf | N Z V
`0011 1aaa` | `DECO` | Decimal output trap | i, d, n, s, sf, x, sx, sxf |
`0100 0aaa` | `STRO` | String output trap | d, n, sf |
`0100 1aaa` | `CHARI` | Character input | d, n, s, sf, x, sx, sxf |
`0101 0aaa` | `CHARO` | Character output | i, d, n, s, sf, x, sx, sxf |
`0101 1nnn` | `RETn` | Return from call with n local bytes | U |
`0110 0aaa` | `ADDSP` | Add to stack pointer (SP) | i, d, n, s, sf, x, sx, sxf | N Z V C
`0110 1aaa` | `SUBSP` | Subtract from stack pointer (SP) | i, d, n, s, sf, x, sx, sxf | N Z V C
`0111 raaa` | `ADDr` | Add to r | i, d, n, s, sf, x, sx, sxf | N Z V C
`1000 raaa` | `SUBr` | Subtract from r | i, d, n, s, sf, x, sx, sxf | N Z V C
`1001 raaa` | `ANDr` | Bitwise AND to r | i, d, n, s, sf, x, sx, sxf | N Z
`1010 raaa` | `ORr` | Bitwise OR to r | i, d, n, s, sf, x, sx, sxf | N Z
`1011 raaa` | `CPr` | Compare r | i, d, n, s, sf, x, sx, sxf | N Z V C
`1100 raaa` | `LDr` | Load r from memory | i, d, n, s, sf, x, sx, sxf | N Z
`1101 raaa` | `LDBYTEr` | Load byte r from memory | i, d, n, s, sf, x, sx, sxf | N Z
`1110 raaa` | `STr` | Store r to memory | d, n, s, sf, x, sx, sxf |
`1111 raaa` | `STBYTEr` | Store byte r to memory | d, n, s, sf, x, sx, sxf |

Scroll to topics.

### Setting the C bit on subtraction

There are two different philosophies for setting the carry bit after subtraction.

Z80, x86, and SPARC treat the carry flag as a "borrow flag" when doing a subtraction. When subtracting x - y, if x is less than y (treating both operands as unsigned), the carry flag is set because there is a borrow. A BRC after a `SUBr` or `CPr` instruction is equivalent to "branch if unsigned overflow" in this case.

On other processor families, such as ARM and PowerPC, the carry flag after a subtraction is set to the adder carry output after computing (x + ~y + 1). When subtracting x - y, if x is greater than or equal to y (treating both operands as unsigned), the carry flag is set. A BRC after a `SUBr` or `CPr` instruction is equivalent to "branch if not unsigned overflow" in this case.

Previous versions of Pep/8 set the C bit on subtraction according to the first philosophy. However, starting with version 8.1.0, the C bit on subtraction is set according to the second philosophy. This is consistent with the section "The Carry Bit" in Chapter 3, and the adder/subtracter circuit in Figure 10.53 in the text.

Scroll to topics.

### Setting the N bit on `CPr`

Normally, the N bit duplicates the sign bit, so that N is 1 when the result of the operation is negative. The compare instruction `CPr` subtracts the operand from the register and sets the status bits without storing the result of the subtraction.

As long as there is no overflow when the operands are interpreted as signed integers, the N bit is set appropriately for a subsequent conditional branch instruction. If the result of the subtraction yields an overflow and the N bit were set as usual, the subsequent conditional branch instruction might execute an erroneous branch. Consequently, if the `CPr` subtraction operation overflows and sets the V bit, then the N bit is inverted from its normal value and does not duplicate the sign bit.

With this adjustment, the compare operation extends the range of valid comparisons. Even though there is an overflow, the N bit is set as if there were no overflow so that a subsequent conditional branch will operate as expected.

Scroll to topics.

### Dot commands

Dot Command | Description
--- | ---
`.ADDRSS` symbol | The address of a symbol (two bytes)
`.ASCII` "string" | A string of ASCII bytes
`.BLOCK` n | A block of n bytes
`.BURN 0xFFFF` | Initiate ROM burn ending at 0xFFFF
`.BYTE` constant | A byte value (one byte)
`.END` | The sentinel for the assembler
`.EQUATE` constant | Equate a symbol to a constant value
`.WORD` constant | A word value (two bytes)

Scroll to topics.

### Addressing modes

Addressing Mode | aaa-field | Letters | Operand
--- | --- | --- | ---
Immediate | `000` | i | OprndSpec
Direct | `001` | d | Mem [OprndSpec ]
Indirect | `010` | n | Mem [Mem [OprndSpec ] ]
Stack-relative | `011` | s | Mem [SP + OprndSpec ]
Stack-relative deferred | `100` | sf | Mem [Mem [SP + OprndSpec ] ]
Indexed | `101` | x | Mem [OprndSpec + X ]
Stack-indexed | `110` | sx | Mem [SP + OprndSpec + X ]
Stack-indexed deferred | `111` | sxf | Mem [Mem [SP + OprndSpec ] + X ]

Scroll to topics.

Addressing Mode | a-field | Letters | Operand
--- | --- | --- | ---
Immediate | `0` | i | OprndSpec
Indexed | `1` | x | Mem [OprndSpec + X ]

Scroll to topics.

### Register field

r-field | Register
--- | ---
`0` | Accumulator, A
`1` | Index register, X

Scroll to topics.

### Trace tags

Trace tag | Format
--- | ---
`#1c` | One-byte character
`#1d` | One-byte decimal
`#2d` | Two-byte decimal
`#1h` | One-byte hexadecimal
`#2h` | Two-byte hexadecimal
`#2d4a` | Two-byte decimal, four-cell array (example)

Scroll to topics.

### Assembly language syntax summary

A decimal integer starts with an optional `+` or `-`, followed by a decimal digit followed by zero or more digits.

A decimal integer used with `.BYTE` ranges from -128 to 255, otherwise from -32768 to 65535.

A hex integer starts with `0x` or `0X` followed by one or more hex digits (upper- or lower-case).

A hex integer used with `.BYTE` ranges from 0 to FF, otherwise from 0 to FFFF.

A single character is enclosed in single quotes, as in `'t'`.

An ASCII string is enclosed in double quotes, as in `"My string."`.

An arbitrary byte can be included in a string or a character by prefixing exactly two hex digits with `\x` or `\X`, as in `"Null terminated\x00"`.

A double quote is included in a string by prefixing it with `\`, as in `"She said, \"Hello\"."`.

A single quote is included in a character by prefixing it with `\`, as in `'\''`.

A backslash character is included in a string or character by prefixing it with `\`, as in `"My bash is \\."` and `'\\'`.

The following letters, when preceded by `\`, generate non printable characters—`b` backspace, `f` form feed, `n` line feed (new line), `r` carriage return, `t` horizontal tab, `v` vertical tab—in string and character constants, as in `"\n Starts on a new line."` and `'\n'`.

A backslash character followed by any character other than `b`, `f`, `n`, `r`, `t`, `v`, `x`, `X`, `"`, `'`, or `\` (except for the second of a pair of `\`’s) is an error.

A double quote preceded by a backslash in a character is not necessary but is valid and represents one double quote.

A single quote preceded by a backslash in a string is not necessary but is valid and represents one single quote.

A constant used as an operand specifier that occupies less than two bytes is right justified in the two-byte field.

A constant used as an operand specifier that occupies more than two bytes is an error.

Scroll to topics.