Compare commits
1 Commits
main
...
sketch-low
| Author | SHA1 | Date |
|---|---|---|
|
|
871fecb9af |
|
|
@ -0,0 +1,198 @@
|
|||
/* CPU sketch */
|
||||
|
||||
class CPU {
|
||||
constructor () {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
IP = 0;
|
||||
A = 0;
|
||||
flags = 0b00000000;
|
||||
instruction = 0x00;
|
||||
operand = 0x00;
|
||||
|
||||
//What do I want for interrupts…?
|
||||
// interruptRequest = 0;
|
||||
|
||||
// TODO: can it be a simple setup with fixed instruction cycle length pls?
|
||||
_instructionCycleStep = 0;
|
||||
_decodedOp = {};
|
||||
_calculatedIP = 0;
|
||||
|
||||
tickClock () {
|
||||
console.log('cpu tick');
|
||||
if (connections.cpuWait) return false;
|
||||
|
||||
switch (this._instructionCycleStep) {
|
||||
// Fetch - instruction
|
||||
case 0:
|
||||
// initiate read
|
||||
connections.addressBus = this.IP;
|
||||
connections.memoryReadSignal = 1;
|
||||
this._calculatedIP += 2;
|
||||
break;
|
||||
case 1:
|
||||
// complete read
|
||||
connections.memoryReadSignal = 0;
|
||||
this.instruction = connections.dataBus;
|
||||
break;
|
||||
|
||||
// Fetch - operand
|
||||
case 2:
|
||||
// initiate read
|
||||
connections.addressBus = this.IP;
|
||||
connections.memoryReadSignal = 1;
|
||||
break;
|
||||
case 3:
|
||||
// complete read
|
||||
connections.memoryReadSignal = 0;
|
||||
this.operand = connections.dataBus;
|
||||
break;
|
||||
|
||||
// Decode
|
||||
case 4:
|
||||
// decode
|
||||
this._decode();
|
||||
break;
|
||||
|
||||
// Execute
|
||||
case 5:
|
||||
this._ops[this._decodedOp]();
|
||||
break;
|
||||
case 4:
|
||||
// execute more
|
||||
break;
|
||||
}
|
||||
this._instructionCycleStep = (this._instructionCycleStep + 1) % 4;
|
||||
}
|
||||
|
||||
reset () {
|
||||
this.IP = 0xFE;
|
||||
this.A = 0;
|
||||
this.flags = 0b00000000;
|
||||
connections.dataBus = 0b00000000;
|
||||
this._instructionCycleStep = 0;
|
||||
this.debug.running = true;
|
||||
}
|
||||
|
||||
_decode (instruction) {
|
||||
/*
|
||||
// gg aa iiii
|
||||
let group = 0b11000000 & instruction;
|
||||
let mode = 0b00110000 & instruction;
|
||||
let instr = 0b00001111 & instruction;
|
||||
console.log(group, mode, instr);
|
||||
*/
|
||||
|
||||
let mode = (0b00110000 & instruction) === 16 ? 'indirect' : 'direct';
|
||||
|
||||
const instrs = {
|
||||
0x00 : 'END',
|
||||
0x01 : 'NOP',
|
||||
0x50 : 'STO_indirect',
|
||||
0x51 : 'LDA_indirect',
|
||||
0x52 : 'ADD_indirect',
|
||||
0x53 : 'SUB_indirect',
|
||||
0x54 : 'HOP_indirect',
|
||||
0x55 : 'JMP_indirect',
|
||||
0x56 : 'FTG_indirect',
|
||||
0x57 : 'FHP_indirect',
|
||||
0x60 : 'STO_direct',
|
||||
0x61 : 'LDA_direct',
|
||||
0x62 : 'ADD_direct',
|
||||
0x63 : 'SUB_direct',
|
||||
0x64 : 'HOP_direct',
|
||||
0x65 : 'JMP_direct',
|
||||
0x66 : 'FTG_direct',
|
||||
0x67 : 'FHP_direct',
|
||||
};
|
||||
// return { instruction: instrs[instruction], mode: mode };
|
||||
this._decodedOp = instruction;
|
||||
}
|
||||
|
||||
_ops = {
|
||||
JMP_direct: (lit) => {
|
||||
this.debug.currentMnemonic = 'JMP lit';
|
||||
this._calculatedIP = lit;
|
||||
},
|
||||
|
||||
JMP_indirect: (addr) => {
|
||||
this.debug.currentMnemonic = 'JMP addr';
|
||||
this._calculatedIP = addr;
|
||||
},
|
||||
}
|
||||
|
||||
debug = {
|
||||
// TODO include the rest of the stuff that I have here in the current version
|
||||
running: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Memory {
|
||||
// ROM format: { addr: nn, data: nn }
|
||||
constructor (sizeInBytes, ROM) {
|
||||
// memory format: [ { data: nn, type: ‘str’ } ]
|
||||
this.memory = new Array(sizeInBytes);
|
||||
ROM.forEach((byte) => {
|
||||
this.memory[byte.address] = { data: byte.data, type: 'ROM' };
|
||||
})
|
||||
}
|
||||
|
||||
tickClock () {
|
||||
if (connections.memoryReadSignal) this._read();
|
||||
if (connections.memoryWriteSignal) this._write();
|
||||
}
|
||||
|
||||
_read () {
|
||||
connections.dataBus = this.memory[connections.addressBus].data;
|
||||
}
|
||||
|
||||
_write () {
|
||||
if (this.memory[connections.addressBus].type === 'ROM') throw new Error('Attempted write to ROM');
|
||||
this.memory[connections.addressBus].data = connections.dataBus;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** DMA controller for screen, keypad... **/
|
||||
class IO {
|
||||
// TODO…
|
||||
constructor (connections) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Connections {
|
||||
dataBus = 0;
|
||||
addressBus = 0;
|
||||
memoryReadSignal = 0;
|
||||
memoryWriteSignal = 0;
|
||||
cpuWait = 0;
|
||||
}
|
||||
|
||||
|
||||
// let rom = // TODO read in…
|
||||
|
||||
const rom = [
|
||||
{ address: 0xFE, data: 0x55, },
|
||||
{ address: 0xFF, data: 0x00, },
|
||||
{ address: 0x00, data: 0x51, },
|
||||
{ address: 0x01, data: 0x0F, },
|
||||
{ address: 0x02, data: 0x62, },
|
||||
{ address: 0x03, data: 0x01, },
|
||||
{ address: 0x04, data: 0x00, },
|
||||
];
|
||||
|
||||
let connections = new Connections();
|
||||
let memory = new Memory(256, rom);
|
||||
let cpu = new CPU();
|
||||
|
||||
let intervalTimer = setInterval( () => {
|
||||
cpu.tickClock();
|
||||
memory.tickClock();
|
||||
}, 500);
|
||||
|
||||
console.log(intervalTimer);
|
||||
Loading…
Reference in New Issue