Introduction
The last letter of a mnemonic is the addressing mode: Z a register (the other operand is R0), I an immediate byte, R a relative memory address,
A an absolute one. r is the register in the low two bits of the opcode (0 to 3); cc the condition in the low two bits of a branch or return (0 EQ, 1 GT, 2 LT, 3 UN).
An opcode range lists every register or condition. The Cycles column is machine cycles, taken as the clock-cycle counts of the FBNeo core read divided by three (the core counts 6, 9 or 12); an indirect operand adds 2
(a conditional branch adds them only when it is taken), and a taken RETC takes 5. The Flags column names the PSW bits the instruction may change (CC the condition code; see the status word).
The cycle counts are those of one core, not of a data sheet.
Load and store
| Instruction | Opcode | Bytes | Cycles | What it does | Flags |
|---|---|---|---|---|---|
LODZ,r | 00-03 | 1 | 2 | R0 = register r. LODZ,R0 only sets the condition code. | CC |
LODI,r imm | 04-07 | 2 | 2 | Register r = the immediate byte. | CC |
LODR,r rel | 08-0B | 2 | 3 | Register r = the memory byte at the relative address. | CC |
LODA,r abs | 0C-0F | 3 | 4 | Register r = the memory byte at the absolute address; with indexing R0 = the byte at the address plus the index register. | CC |
STRZ,r | C1-C3 | 1 | 2 | Register r = R0. STRZ,R0 would be C0, which is NOP. | CC |
STRR,r rel | C8-CB | 2 | 3 | Store register r at the relative address. | none |
STRA,r abs | CC-CF | 3 | 4 | Store register r (R0 when indexed) at the absolute address. | none |
NOP | C0 | 1 | 2 | No operation. | none |
There is no store-immediate: STRI would be opcodes C4 to C7, which are undefined.
Arithmetic
The carry goes into an addition only when WC is set. A subtraction sets C when there is no borrow; with WC set the carry flag also takes part. The cycle counts of the Z, I, R and A forms are 2, 2, 3 and 4.
| Instruction | Opcode | Bytes | Cycles | What it does | Flags |
|---|---|---|---|---|---|
ADDZ,r | 80-83 | 1 | 2 | R0 = R0 + register r (+ C if WC). | CC C OVF IDC |
ADDI,r imm | 84-87 | 2 | 2 | Register r = register r + the immediate byte. | CC C OVF IDC |
ADDR,r rel | 88-8B | 2 | 3 | Register r = register r + the memory byte (relative address). | CC C OVF IDC |
ADDA,r abs | 8C-8F | 3 | 4 | Register r = register r + the memory byte (absolute; R0 when indexed). | CC C OVF IDC |
SUBZ,r | A0-A3 | 1 | 2 | R0 = R0 - register r. | CC C OVF IDC |
SUBI,r imm | A4-A7 | 2 | 2 | Register r = register r - the immediate byte. | CC C OVF IDC |
SUBR,r rel | A8-AB | 2 | 3 | Register r = register r - the memory byte (relative address). | CC C OVF IDC |
SUBA,r abs | AC-AF | 3 | 4 | Register r = register r - the memory byte (absolute; R0 when indexed). | CC C OVF IDC |
DAR,r | 94-97 | 1 | 3 | Decimal adjust register r after a BCD addition or subtraction: add $A0 to the high digit if C is clear and $0A to the low digit if IDC is clear. | none |
Logic
| Instruction | Opcode | Bytes | Cycles | What it does | Flags |
|---|---|---|---|---|---|
ANDZ,r | 41-43 | 1 | 2 | R0 = R0 AND register r. Opcode 40 would be ANDZ,R0: it is HALT. | CC |
ANDI,r imm | 44-47 | 2 | 2 | Register r = register r AND the immediate byte. | CC |
ANDR,r rel | 48-4B | 2 | 3 | Register r = register r AND the memory byte (relative). | CC |
ANDA,r abs | 4C-4F | 3 | 4 | Register r = register r AND the memory byte (absolute). | CC |
IORZ,r | 60-63 | 1 | 2 | R0 = R0 OR register r. | CC |
IORI,r imm | 64-67 | 2 | 2 | Register r = register r OR the immediate byte. | CC |
IORR,r rel | 68-6B | 2 | 3 | Register r = register r OR the memory byte (relative). | CC |
IORA,r abs | 6C-6F | 3 | 4 | Register r = register r OR the memory byte (absolute). | CC |
EORZ,r | 20-23 | 1 | 2 | R0 = R0 XOR register r. EORZ,R0 clears R0. | CC |
EORI,r imm | 24-27 | 2 | 2 | Register r = register r XOR the immediate byte. | CC |
EORR,r rel | 28-2B | 2 | 3 | Register r = register r XOR the memory byte (relative). | CC |
EORA,r abs | 2C-2F | 3 | 4 | Register r = register r XOR the memory byte (absolute). | CC |
Compare, test and rotate
Compares do not change a register: the condition code says whether the register is equal (0), greater (1) or less (2), signed or, when COM is set, unsigned.
| Instruction | Opcode | Bytes | Cycles | What it does | Flags |
|---|---|---|---|---|---|
COMZ,r | E0-E3 | 1 | 2 | Compare R0 with register r. | CC |
COMI,r imm | E4-E7 | 2 | 2 | Compare register r with the immediate byte. | CC |
COMR,r rel | E8-EB | 2 | 3 | Compare register r with the memory byte (relative). | CC |
COMA,r abs | EC-EF | 3 | 4 | Compare register r with the memory byte (absolute). | CC |
TMI,r imm | F4-F7 | 2 | 3 | Test register r under the mask: condition code 0 if every bit that is 1 in the mask is 1 in the register, else 2. | CC |
RRL,r | D0-D3 | 1 | 2 | Rotate register r left; with WC set, through the carry (nine bits), with WC clear eight bits and C unchanged. | CC C IDC OVF |
RRR,r | 50-53 | 1 | 2 | Rotate register r right (as RRL). | CC C IDC OVF |
Branches
The relative forms (R) have two bytes and reach the page of the instruction; the absolute forms (A) have three bytes and a 15-bit address. cc is the condition; UN always branches. BCT branches if the condition code equals the condition,
BCF if it does not. The BRN forms test a register for non-zero; BIR and BDR add or subtract one first (the register changes whether or not the branch is taken). A taken indirect branch adds two cycles. Branches change no status bit.
| Instruction | Opcode | Bytes | Cycles | What it does | Flags |
|---|---|---|---|---|---|
BCTR,cc rel | 18-1B | 2 | 3 | Branch relative if the condition holds. | none |
BCTA,cc addr | 1C-1F | 3 | 3 | Branch absolute if the condition holds. BCTA,UN (1F) is the unconditional jump. | none |
BCFR,cc rel | 98-9A | 2 | 3 | Branch relative if the condition does not hold (cc 0 to 2). | none |
BCFA,cc addr | 9C-9E | 3 | 3 | Branch absolute if the condition does not hold (cc 0 to 2). | none |
ZBRR rel | 9B | 2 | 3 | Branch relative to page 0 (the displacement is added to address 0). | none |
BXA addr,R3 | 9F | 3 | 3 | Branch to the 15-bit address plus R3. | none |
BRNR,r rel | 58-5B | 2 | 3 | Branch relative if register r is not zero. | none |
BRNA,r addr | 5C-5F | 3 | 3 | Branch absolute if register r is not zero. | none |
BIRR,r rel | D8-DB | 2 | 3 | Increase register r; branch relative if it is not zero. | none |
BIRA,r addr | DC-DF | 3 | 3 | Increase register r; branch absolute if it is not zero. | none |
BDRR,r rel | F8-FB | 2 | 3 | Decrease register r; branch relative if it is not zero (the loop instruction). | none |
BDRA,r addr | FC-FF | 3 | 3 | Decrease register r; branch absolute if it is not zero. | none |
Calls and returns
A call pushes the address of the next instruction on the return stack (the stack pointer in PSU is increased first). RETC and RETE pop it when the condition holds; RETE also clears II (interrupts allowed again).
| Instruction | Opcode | Bytes | Cycles | What it does | Flags |
|---|---|---|---|---|---|
BSTR,cc rel | 38-3B | 2 | 3 | Call relative if the condition holds (BSTR,UN always). | SP |
BSTA,cc addr | 3C-3F | 3 | 3 | Call absolute if the condition holds (BSTA,UN always). | SP |
BSFR,cc rel | B8-BA | 2 | 3 | Call relative if the condition does not hold (cc 0 to 2). | SP |
BSFA,cc addr | BC-BE | 3 | 3 | Call absolute if the condition does not hold (cc 0 to 2). | SP |
ZBSR rel | BB | 2 | 3 | Call relative to page 0. | SP |
BSXA addr,R3 | BF | 3 | 3 | Call the 15-bit address plus R3. | SP |
BSNR,r rel | 78-7B | 2 | 3 | Call relative if register r is not zero. | SP |
BSNA,r addr | 7C-7F | 3 | 3 | Call absolute if register r is not zero. | SP |
RETC,cc | 14-17 | 1 | 3 (5 taken) | Return if the condition holds (RETC,UN always). | SP |
RETE,cc | 34-37 | 1 | 3 | Return and clear II if the condition holds. | SP II |
Program status word
The operand byte is a mask. In the viewer, the note of each instruction names the bits of the mask.
| Instruction | Opcode | Bytes | Cycles | What it does | Flags |
|---|---|---|---|---|---|
SPSU | 12 | 1 | 2 | R0 = PSU (bit 7 is the sense input). | CC |
SPSL | 13 | 1 | 2 | R0 = PSL. | CC |
LPSU | 92 | 1 | 2 | PSU = R0 (the sense input and the two unused bits are not written). | PSU |
LPSL | 93 | 1 | 2 | PSL = R0. If RS changes, R1 to R3 are the other bank’s. | PSL |
CPSU mask | 74 | 2 | 3 | Clear the PSU bits that are 1 in the mask. | the mask bits |
CPSL mask | 75 | 2 | 3 | Clear the PSL bits that are 1 in the mask. CPSL $01 clears the carry. | the mask bits |
PPSU mask | 76 | 2 | 3 | Set the PSU bits that are 1 in the mask (not the sense input). | the mask bits |
PPSL mask | 77 | 2 | 3 | Set the PSL bits that are 1 in the mask. PPSL $08 sets WC. | the mask bits |
TPSU mask | B4 | 2 | 3 | Test PSU under the mask: condition code 0 if all the mask bits are 1, else 2. | CC |
TPSL mask | B5 | 2 | 3 | Test PSL under the mask. | CC |
HALT | 40 | 1 | 2 | Halt until reset or an interrupt. | none |
Input and output
The 2650 has three I/O paths: the control port, the data port and 256 extended ports. The Arcadia 2001 reaches its video chip through memory ($1800 to $19FF), not through these ports; the Wikibook says the I/O hardware is not used on the 2650 consoles. What each machine connects to the ports is for the machine pages.
| Instruction | Opcode | Bytes | Cycles | What it does | Flags |
|---|---|---|---|---|---|
REDC,r | 30-33 | 1 | 2 | Read the control port into register r. | CC |
REDD,r | 70-73 | 1 | 2 | Read the data port into register r. | CC |
REDE,r port | 54-57 | 2 | 3 | Read extended port 0 to 255 into register r. | CC |
WRTC,r | B0-B3 | 1 | 2 | Write register r to the control port. | none |
WRTD,r | F0-F3 | 1 | 2 | Write register r to the data port. | none |
WRTE,r port | D4-D7 | 2 | 3 | Write register r to extended port 0 to 255. | none |
Not described
Known, not yet covered
- Reference: a per-instruction timing table from a data sheet, and a worked example for each group.
Unknown
- Reference: the exact flag values (IDC after a subtraction; C and IDC after a rotate through the carry) as a manufacturer defines them: the two emulator cores read differ in these (see the checks), and neither is a data sheet.
- Reference: whether
LODZ,R0,IORZ,R0,ADDZ,R0,SUBZ,R0andCOMZ,R0are meant to be used: they decode and run in the cores read.
Links
Reference
- Signetics 2650 & 2636 programming – Wikibooks
- AS2650 instruction set architecture – Avalon Semiconductors
- 2650dasm.cpp – MAME