Переглянути джерело

MOS6502 CPU buildout.

master
Bryan Miller 5 роки тому
джерело
коміт
58e181fac5
1 змінених файлів з 287 додано та 10 видалено
  1. +287
    -10
      src/chip/MOS6502/cpu.js

+ 287
- 10
src/chip/MOS6502/cpu.js Переглянути файл

@@ -1,23 +1,196 @@
/*
* Emulate a basic 6502 (MOS) chip.
*/
const BIT = require('../../utils/bitman.js');
var Memory = require('../../common/memory.js');


function ADC(cpu){

}

function AND(cpu){

}

function ASL(cpu){

}

function BIT(cpu){

}

function BRANCH(cpu){

}

function BRK(cpu){

}

function CMP(cpu){

}

function CPX(cpu){

}

function CPY(cpu){

}

function DEC(cpu){

}

function EOR(cpu){

}

function FLAG(cpu){

}

function INC(cpu){

}

function JMP(cpu){

}

function JRS(cpu){

}

function LDA(cpu){

}

function LDX(cpu){

}

function LDY(cpu){

}

function LSR(cpu){

}

function ORA(cpu){

}

function REGISTER(cpu){

}

function ROL(cpu){

}

function ROR(cpu){

}

function RTI(cpu){

}

function RTS(cpu){

}

function SBC(cpu){

}

function STA(cpu){

}

function STACK(cpu){

}

function STX(cpu){

}

function STY(cpu){

}


// --------------------------------------------------------------------------------------------

// Test to see if both a and b's high byte is the same... same page.
function SamePage(a, b){
return ((a >> 8) == (b >> 8));
}

function PCHI(cpu, b){
cpu.__PC = (cpu.__PC & 0x00FF) | (b << 8);
}

function PCLOW(cpu, b){
cpu.__PC = (cpu.__PC & 0xFF00) | b;
}

function PCUp(cpu, amount){
if (cpu.__pcc === 1){
PCHI(cpu, ((cpu.__PC & 0xFF00) >> 8) + 1);
cpu.__pcc = 0;
} else if ((cpu.__PC & 0x00FF) + amount > 255){
cpu.__pcc = 1;
PCLOW(cpu, ((cpu.__PC & 0x00FF) + amount) - 256);
} else {
PCLOW(cpu, (cpu.__PC & 0x00FF) + amount);
}
}

function PCDown(cpu, amount){
if (cpu.__pcc === -1){
PCHI(cpu, ((cpu.__PC & 0xFF00) >> 8) - 1);
cpu.__pcc = 0;
} else if ((cpu.__PC & 0x00FF) - amount < 0){
cpu.__pcc = -1;
PCLOW(cpu, ((cpu.__PC & 0x00FF) - amount) + 256);
} else {
PCLOW(cpu, (cpu.__PC & 0x00FF) - amount);
}
}

// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------


class CPU{
constructor(){
// Registers
this.__PC = 0; // Program Counter (16 bit)
this.__IRQ = 0; // IRQ interrupt address code (16 bit)
this.__SR = 0; // Status Register (8 bit)
this.__PR = 0; // Status Register (8 bit)
this.__XR = 0; // X Register (8 bit)
this.__YR = 0; // Y Register (8 bit)
this.__AR = 0; // Accumulator Register (8 bit)

// Variables to watch for Interrupts.
// Variables to watch for Hardware Interrupts.
this.__nmi = false;
this.__irq = false;

// Variable for tracking tick operations.
this.__op = -1;
this.__opmem = 0;
this.__opv = 0;
this.__step = 0;
this.__pcc = 0; // Program Counter Carry.

// Memory module or controller.
this.__mem = null; // Must be explicitly attached.

@@ -25,6 +198,16 @@ class CPU{
this.__clkfn = null;
}

// ----------------------------------------
// CPU Registers. Here for debug purposes.
get PC(){return this.__PC;}
get P(){return this.__SR;}
get X(){return this.__XR;}
get Y(){return this.__YR;}
get A(){return this.__AR;}

// ----------------------------------------
// Hardware interrupt triggers. Settable only.
set NMI(n){
this.__nmi = (n === true);
}
@@ -40,20 +223,114 @@ class CPU{
// TODO: Reset status registers that get changed on a reset.
}

// -----------------------------------------
// Set and Get Memory property.
get memory(){return this.__mem;}
set memory(m){
if (!(mem instanceof Memory))
throw new ValueError("Expected Memory instance object.");
this.__mem = m;
}


// -----------------------------------------

clk(){
if (this.__clkfn === null){
this.__clkfn = (function(){
// TODO: All the work!!
if (this.__pcc !== 0){
if (this.__pcc > 0) {
PCUp(this, 1);
} else {
PCDown(this, 1);
}
} else if (this.__op < 0){
if (this.__nmi) {
// TODO: Handle NMI Interrupt.
} else if (this.__irq) {
this.__irq = false;
if (!BIT.isOn(this.__PR, 5)){
// TODO: Handle IRQ Interrupt.
}
} else {
this.__step = 0;
this.__op = this.__mem.byte;
PCUp(this, 1);
}
} else {
switch(this.__op){
case 0x69: case 0x65: case 0x75: case 0x6D: case 0x7D: case 0x79: case 0x61: case 0x71:
ADC(this); break;
case 0x29: case 0x25: case 0x35: case 0x2D: case 0x3D: case 0x39: case 0x21: case 0x31:
AND(this); break;
case 0x0A: case 0x06: case 0x16: case 0x0E: case 0x1E:
ASL(this); break;
case 0x24: case 0x2C:
BIT(this); break;
case 0x10: case 0x30: case 0x50: case 0x70: case 0x90: case 0xB0: case 0xD0: case 0xF0:
BRANCH(this); break;
case 0x00:
BRK(this); break;
case 0xC9: case 0xC5: case 0xD5: case 0xCD: case 0xDD: case 0xD9: case 0xC1: case 0xD1:
CMP(this); break;
case 0xE0: case 0xE4: case 0xEC:
CPX(this); break;
case 0xC0: case 0xC4: case 0xCC:
CPY(this); break;
case 0xC6: case 0xD6: case 0xCE: case 0xDE:
DEC(this); break;
case 0x49: case 0x45: case 0x55: case 0x4D: case 0x5D: case 0x59: case 0x41: case 0x51:
EOR(this); break;
case 0x18: case 0x38: case 0x58: case 0x78: case 0xB8: case 0xD8: case 0xF8:
FLAG(this); break;
case 0xE6: case 0xF6: case 0xEE: case 0xFE:
INC(this); break;
case 0x4C: case 0x6C:
JMP(this); break;
case 0x20:
JSR(this); break;
case 0xA9: case 0xA5: case 0xB5: case 0xAD: case 0xBD: case 0xB9: case 0xA1: case 0xB1:
LDA(this); break;
case 0xA2: case 0xA6: case 0xB6: case 0xAE: case 0xBE:
LDX(this); break;
case 0xA0: case 0xA4: case 0xB4: case 0xAC: case 0xBC:
LDY(this); break;
case 0x4A: case 0x46: case 0x56: case 0x4E: case 0x5E:
LSR(this); break;
case 0xEA:
// NOP
if (this.__step == 1){
this.__op = -1;
} else {this.__step += 1;}
break;
case 0x09: case 0x05: case 0x15: case 0x0D: case 0x1D: case 0x19: case 0x01: case 0x11:
ORA(this); break;
case 0xAA: case 0x8A: case 0xCA: case 0xE8: case 0xA8: case 0x98: case 0x88: case 0xC8:
REGISTER(this); break;
case 0x2A: case 0x26: case 0x36: case 0x2E: case 0x3E:
ROL(this); break;
case 0x6A: case 0x66: case 0x76: case 0x6E: case 0x7E:
ROR(this); break;
case 0x40:
RTI(this); break;
case 0x60:
RTS(this); break;
case 0xE9: case 0xE5: case 0xF5: case 0xED: case 0xFD: case 0xF9: case 0xE1: case 0xF1:
SBC(this); break;
case 0x85: case 0x95: case 0x8D: case 0x9D: case 0x99: case 0x81: case 0x91:
STA(this); break;
case 0x9A: case 0xBA: case 0x48: case 0x68: case 0x08: case 0x28:
STACK(this); break;
case 0x86: case 0x96: case 0x8E:
STX(this); break;
case 0x84: case 0x94: case 0x8C:
STY(this); break;
}
}
}).bind(this);
}
return this.__clkfn;
}

memory(mem){
if (!(mem instanceof Memory))
throw new ValueError("Expected Memory instance object.");
this.__mem = mem;
}
}

module.exports = CPU;

Завантаження…
Відмінити
Зберегти