UNPKG

zx-generation

Version:

A high-fidelity ZX Spectrum emulator in JavaScript — fully generated by a large language model (LLM) to explore the boundaries of AI in systems programming.

192 lines (168 loc) 4.11 kB
/** * Miscellaneous Instructions * Handles NOP, HALT, DI, EI, EX operations and stack operations */ class MiscInstructions { constructor(registers, memory) { this.registers = registers; this.memory = memory; } /** * NOP */ nop() { return 4; // cycles } /** * HALT */ halt(cpu) { if (cpu) { cpu.halted = true; } return 4; // cycles } /** * DI (Disable Interrupts) */ di(cpu) { if (cpu) { cpu.iff1 = false; cpu.iff2 = false; } return 4; // cycles } /** * EI (Enable Interrupts) */ ei(cpu) { if (cpu) { cpu.iff1 = true; cpu.iff2 = true; } return 4; // cycles } /** * EX AF, AF' */ exAF() { this.registers.exchangeAF(); return 4; // cycles } /** * EXX */ exx() { this.registers.exchangeAll(); return 4; // cycles } /** * EX DE, HL */ exDEHL() { this.registers.exchangeDE_HL(); return 4; // cycles } /** * EX (SP), HL */ exSPHL() { const spValue = this.memory.readWord(this.registers.get16('SP')); this.memory.writeWord(this.registers.get16('SP'), this.registers.getHL()); this.registers.setHL(spValue); return 19; // cycles } /** * EX (SP), IX */ exSPIX() { const spValue = this.memory.readWord(this.registers.get16('SP')); this.memory.writeWord(this.registers.get16('SP'), this.registers.get16('IX')); this.registers.set16('IX', spValue); return 23; // cycles } /** * EX (SP), IY */ exSPIY() { const spValue = this.memory.readWord(this.registers.get16('SP')); this.memory.writeWord(this.registers.get16('SP'), this.registers.get16('IY')); this.registers.set16('IY', spValue); return 23; // cycles } /** * PUSH reg16 */ push(regName) { const value = this.registers.get16(regName); this.memory.pushWord(this.registers, value); if (regName === 'IX' || regName === 'IY') { return 15; // cycles } return 11; // cycles } /** * POP reg16 */ pop(regName) { const value = this.memory.popWord(this.registers); this.registers.set16(regName, value); if (regName === 'IX' || regName === 'IY') { return 14; // cycles } return 10; // cycles } /** * IN A, (n) */ inAImmediate(port, io) { const a = this.registers.get('A'); const fullPort = port | (a << 8); this.registers.set('A', io.readPort(fullPort)); return 11; // cycles } /** * OUT (n), A */ outAImmediate(port, io) { const a = this.registers.get('A'); const fullPort = port | (a << 8); io.writePort(fullPort, a); return 11; // cycles } /** * IN reg, (C) */ inRegC(regName, io, flags) { const port = this.registers.getBC(); const value = io.readPort(port); if (regName !== null) { this.registers.set(regName, value); } // Note: When regName is null, this is the IN F,(C) instruction // where the value is read but discarded (only flags are affected) // Update flags const newF = flags.updateInFlags(this.registers.get('F'), value); this.registers.set('F', newF); return 12; // cycles } /** * OUT (C), reg */ outRegC(regName, io) { const port = this.registers.getBC(); const value = regName ? this.registers.get(regName) : 0; io.writePort(port, value); return 12; // cycles } /** * IM 0/1/2 (Set Interrupt Mode) */ setInterruptMode(mode, cpu) { if (cpu) { cpu.interruptMode = mode; } return 8; // cycles } } export { MiscInstructions };