Intel 8080 CPU Reference
Overview
The Intel 8080 is an 8-bit microprocessor introduced in 1974. It is the foundation for the Z80 and Game Boy CPUs, and was used in early personal computers and arcade games. This implementation provides a reusable 8080 CPU core that can be used by any system (Space Invaders, CP/M systems, etc.) by implementing the Memory8080 trait.
Implementation: crates/core/src/cpu_8080.rs
Architecture
Registers
The 8080 has seven 8-bit registers that can be used as pairs:
- A (Accumulator): Primary register for arithmetic and logic operations
- B, C: 8-bit registers (can be paired as BC)
- D, E: 8-bit registers (can be paired as DE)
- H, L: 8-bit registers (can be paired as HL for memory addressing)
- SP (Stack Pointer): 16-bit pointer to stack
- PC (Program Counter): 16-bit pointer to current instruction
- Flags: 8-bit status flags register
Register Pairs
Registers can be accessed as 16-bit pairs:
- BC: B (high byte) and C (low byte)
- DE: D (high byte) and E (low byte)
- HL: H (high byte) and L (low byte)
- PSW: A (high byte) and Flags (low byte)
Flags Register
SZ-A-P-C
││ │ │ └─ Carry flag
││ │ └─── Parity flag
││ └───── Auxiliary Carry flag (for BCD)
│└─────── Zero flag
└──────── Sign flag
Bits 1, 3, and 5 are always 0, 0, and 0 respectively.
Usage
Systems using the 8080 must implement the Memory8080 trait:
pub trait Memory8080 {
fn read(&self, addr: u16) -> u8;
fn write(&mut self, addr: u16, val: u8);
fn port_in(&mut self, port: u8) -> u8;
fn port_out(&mut self, port: u8, val: u8);
}
Example
use emu_core::cpu_8080::{Cpu8080, Memory8080};
struct MySystem {
ram: [u8; 65536],
}
impl Memory8080 for MySystem {
fn read(&self, addr: u16) -> u8 {
self.ram[addr as usize]
}
fn write(&mut self, addr: u16, val: u8) {
self.ram[addr as usize] = val;
}
fn port_in(&mut self, port: u8) -> u8 {
0 // System-specific I/O handling
}
fn port_out(&mut self, port: u8, val: u8) {
// System-specific I/O handling
}
}
let system = MySystem { ram: [0; 65536] };
let mut cpu = Cpu8080::new(system);
cpu.reset();
Instruction Set
The 8080 has 244 opcodes organized into the following categories:
Data Transfer
- MOV: Move register to register
- MVI: Move immediate to register
- LDA: Load accumulator direct
- STA: Store accumulator direct
- LHLD: Load HL direct
- SHLD: Store HL direct
- LXI: Load register pair immediate
- LDAX: Load accumulator indirect (BC or DE)
- STAX: Store accumulator indirect (BC or DE)
- XCHG: Exchange DE and HL
Arithmetic
- ADD: Add register to accumulator
- ADI: Add immediate to accumulator
- ADC: Add register to accumulator with carry
- ACI: Add immediate to accumulator with carry
- SUB: Subtract register from accumulator
- SUI: Subtract immediate from accumulator
- SBB: Subtract register from accumulator with borrow
- SBI: Subtract immediate from accumulator with borrow
- INR: Increment register
- DCR: Decrement register
- INX: Increment register pair
- DCX: Decrement register pair
- DAD: Add register pair to HL
Logical
- ANA: AND register with accumulator
- ANI: AND immediate with accumulator
- ORA: OR register with accumulator
- ORI: OR immediate with accumulator
- XRA: XOR register with accumulator
- XRI: XOR immediate with accumulator
- CMP: Compare register with accumulator
- CPI: Compare immediate with accumulator
Rotate
- RLC: Rotate accumulator left
- RRC: Rotate accumulator right
- RAL: Rotate accumulator left through carry
- RAR: Rotate accumulator right through carry
Branch
- JMP: Jump unconditional
- Jcc: Conditional jumps (JC, JNC, JZ, JNZ, JP, JM, JPE, JPO)
- CALL: Call subroutine unconditional
- Ccc: Conditional calls (CC, CNC, CZ, CNZ, CP, CM, CPE, CPO)
- RET: Return from subroutine unconditional
- Rcc: Conditional returns (RC, RNC, RZ, RNZ, RP, RM, RPE, RPO)
- PCHL: Jump to address in HL
Stack
- PUSH: Push register pair onto stack
- POP: Pop register pair from stack
- XTHL: Exchange top of stack with HL
- SPHL: Load SP from HL
I/O
- IN: Input from port
- OUT: Output to port
Special
- NOP: No operation
- HLT: Halt
- DI: Disable interrupts
- EI: Enable interrupts
- RST: Restart (8 vectors: RST 0-7)
- DAA: Decimal adjust accumulator
- CMA: Complement accumulator
- STC: Set carry flag
- CMC: Complement carry flag
Addressing Modes
The 8080 supports several addressing modes:
- Register: Operates on registers (e.g.,
MOV A,B) - Immediate: Operand is next byte (e.g.,
MVI A,42H) - Direct: 16-bit address (e.g.,
LDA 1234H) - Register Indirect: Address in HL (e.g.,
MOV A,M) - Register Pair: 16-bit register pair (e.g.,
LXI H,1234H)
Interrupts
The 8080 supports interrupts with the following mechanism:
- INTE (Interrupt Enable) flag controls interrupt handling
- When an interrupt occurs, the CPU:
- Pushes PC onto stack
- Disables further interrupts (INTE = 0)
- Jumps to interrupt vector (provided by interrupting device)
- Use EI to enable interrupts, DI to disable
- Use RET to return from interrupt handler
RST Instructions
The 8080 has 8 restart instructions (RST 0-7) that act as 1-byte CALL instructions:
- RST 0: CALL $0000
- RST 1: CALL $0008
- RST 2: CALL $0010
- RST 3: CALL $0018
- RST 4: CALL $0020
- RST 5: CALL $0028
- RST 6: CALL $0030
- RST 7: CALL $0038
I/O Operations
The 8080 has a separate I/O address space (256 ports):
- IN port: Read from I/O port
- OUT port: Write to I/O port
Systems must implement port_in() and port_out() to handle I/O.
Timing
The 8080 uses a two-phase clock. Instructions take between 4 and 18 clock cycles (1-4.5 machine cycles). Typical timings:
- Simple register operations: 4-5 cycles
- Memory access: 7-10 cycles
- I/O operations: 10 cycles
- Jumps/calls: 10-17 cycles
Differences from Z80
The 8080 is a subset of the Z80. Key differences:
- Z80 adds IX, IY index registers
- Z80 adds shadow register set
- Z80 adds more instructions
- Z80 has different flag behavior for some instructions
- 8080 has external status signals that Z80 internalizes
Implementation Notes
Parity Flag
The parity flag is set if the number of 1 bits in the result is even. This requires counting bits in the result.
Auxiliary Carry
The auxiliary carry flag is used for BCD (Binary Coded Decimal) operations. It is set if there is a carry from bit 3 to bit 4.
Undocumented Flags
Some flag bits are affected by operations in undocumented ways. This implementation follows the documented behavior.
Systems That Could Use 8080
While not currently used directly in Hemulator, this CPU core could be used for:
- Space Invaders arcade game
- CP/M systems
- Early microcomputers (Altair 8800, IMSAI 8080)
The Z80 and LR35902 (Game Boy) CPUs are derivatives that extend the 8080 architecture.
References
- Intel 8080 Datasheet - Official documentation
- 8080 Instruction Set - Complete opcode reference
- 8080 Assembly Programming Manual - Programming guide