velxio/test/test_intel/src/isa/8080-opcodes.js

115 lines
4.0 KiB
JavaScript

/**
* Intel 8080 opcodes — selected, byte-accurate constants for tests.
*
* Source: Intel 8080 Programmer's Manual (1975, public Intel publication).
* Names follow the standard mnemonics. Multi-byte instructions list only
* the leading byte; tests append the operand bytes inline.
*
* This is intentionally NOT a complete table — it's a tested sub-set
* sufficient for the unit tests in test_8080/. Add more as tests grow.
*/
export const I8080 = {
// Data movement, register-direct
MOV_A_A: 0x7F, MOV_A_B: 0x78, MOV_A_C: 0x79, MOV_A_D: 0x7A, MOV_A_E: 0x7B,
MOV_A_H: 0x7C, MOV_A_L: 0x7D, MOV_A_M: 0x7E,
MOV_B_A: 0x47, MOV_C_A: 0x4F, MOV_D_A: 0x57, MOV_E_A: 0x5F,
MOV_H_A: 0x67, MOV_L_A: 0x6F, MOV_M_A: 0x77,
// Move immediate (one operand byte follows)
MVI_A: 0x3E, MVI_B: 0x06, MVI_C: 0x0E, MVI_D: 0x16,
MVI_E: 0x1E, MVI_H: 0x26, MVI_L: 0x2E, MVI_M: 0x36,
// Load 16-bit immediate (LSB then MSB follow)
LXI_B: 0x01, LXI_D: 0x11, LXI_H: 0x21, LXI_SP: 0x31,
// Direct memory addressing (16-bit addr operand, LSB first)
STA: 0x32, LDA: 0x3A, SHLD: 0x22, LHLD: 0x2A,
// Indirect via register pair
STAX_B: 0x02, STAX_D: 0x12, LDAX_B: 0x0A, LDAX_D: 0x1A,
// Arithmetic (8-bit)
ADD_B: 0x80, ADD_C: 0x81, ADD_D: 0x82, ADD_E: 0x83,
ADD_H: 0x84, ADD_L: 0x85, ADD_M: 0x86, ADD_A: 0x87,
ADC_B: 0x88,
SUB_B: 0x90, SUB_C: 0x91,
SBB_B: 0x98,
ANA_B: 0xA0, XRA_B: 0xA8, ORA_B: 0xB0, CMP_B: 0xB8,
// Immediate arithmetic (one operand byte)
ADI: 0xC6, ACI: 0xCE, SUI: 0xD6, SBI: 0xDE,
ANI: 0xE6, XRI: 0xEE, ORI: 0xF6, CPI: 0xFE,
// Increment / decrement
INR_A: 0x3C, INR_B: 0x04, INR_C: 0x0C, INR_D: 0x14,
INR_E: 0x1C, INR_H: 0x24, INR_L: 0x2C, INR_M: 0x34,
DCR_A: 0x3D, DCR_B: 0x05,
INX_B: 0x03, INX_D: 0x13, INX_H: 0x23, INX_SP: 0x33,
DCX_B: 0x0B, DCX_D: 0x1B, DCX_H: 0x2B, DCX_SP: 0x3B,
// Rotates
RLC: 0x07, RRC: 0x0F, RAL: 0x17, RAR: 0x1F,
// 16-bit add into HL
DAD_B: 0x09, DAD_D: 0x19, DAD_H: 0x29, DAD_SP: 0x39,
// Decimal adjust + complement / flag ops
DAA: 0x27, CMA: 0x2F, STC: 0x37, CMC: 0x3F,
// Control flow — unconditional (16-bit addr operand)
JMP: 0xC3, CALL: 0xCD, RET: 0xC9,
// Conditional jumps / calls / returns
JNZ: 0xC2, JZ: 0xCA, JNC: 0xD2, JC: 0xDA,
JPO: 0xE2, JPE: 0xEA, JP: 0xF2, JM: 0xFA,
CNZ: 0xC4, CZ: 0xCC, CNC: 0xD4, CC: 0xDC,
CPO: 0xE4, CPE: 0xEC, CP: 0xF4, CM: 0xFC,
RNZ: 0xC0, RZ: 0xC8, RNC: 0xD0, RC: 0xD8,
RPO: 0xE0, RPE: 0xE8, RP: 0xF0, RM: 0xF8,
// Stack
PUSH_B: 0xC5, PUSH_D: 0xD5, PUSH_H: 0xE5, PUSH_PSW: 0xF5,
POP_B: 0xC1, POP_D: 0xD1, POP_H: 0xE1, POP_PSW: 0xF1,
XTHL: 0xE3, SPHL: 0xF9, PCHL: 0xE9, XCHG: 0xEB,
// I/O (one operand byte = port number)
IN: 0xDB, OUT: 0xD3,
// Interrupt control
EI: 0xFB, DI: 0xF3,
// Restart vectors
RST_0: 0xC7, RST_1: 0xCF, RST_2: 0xD7, RST_3: 0xDF,
RST_4: 0xE7, RST_5: 0xEF, RST_6: 0xF7, RST_7: 0xFF,
// Halt and no-op
NOP: 0x00, HLT: 0x76,
};
/** Status-byte values the 8080 emits on D0..D7 during T1 (real chip). */
export const I8080_STATUS = {
INTA: 0b00100011, // interrupt-acknowledge
WO: 0b00010000, // write output (active LOW for writes — 0 = write)
STACK: 0b00000100,
HLTA: 0b00001000,
OUT: 0b00010000,
M1: 0b00100000,
INP: 0b01000000,
MEMR: 0b10000000,
};
/** Helper: assemble a small program from mnemonic-tagged tuples. */
export function asm(...parts) {
const out = [];
for (const p of parts) {
if (Array.isArray(p)) out.push(...p);
else out.push(p);
}
return Uint8Array.from(out);
}
/** Split a 16-bit value into [LSB, MSB] for use with LXI / JMP / CALL / etc. */
export function imm16(v) {
return [v & 0xff, (v >> 8) & 0xff];
}