@asm80/core
Version:
Core ASM80 compiler / assembler
433 lines (395 loc) • 11.7 kB
JavaScript
/*
http://pastraiser.com/cpu/i8008/i8008_opcodes.html
http://petsd.net/8008.php
*/
export const I8008 = {
endian: false,
cpu: "i8008",
ext: "a08",
set: {
//old syntax
ADA: { o: 0x80, t: "0" },
ADB: { o: 0x81, t: "0" },
ADC: { o: 0x82, t: "0" },
ADD: { o: 0x83, t: "0" },
ADE: { o: 0x84, t: "0" },
ADH: { o: 0x85, t: "0" },
ADL: { o: 0x86, t: "0" },
ADM: { o: 0x87, t: "0" },
ACA: { o: 0x88, t: "0" },
ACB: { o: 0x89, t: "0" },
ACC: { o: 0x8a, t: "0" },
ACD: { o: 0x8b, t: "0" },
ACE: { o: 0x8c, t: "0" },
ACH: { o: 0x8d, t: "0" },
ACL: { o: 0x8e, t: "0" },
ACM: { o: 0x8f, t: "0" },
SUA: { o: 0x90, t: "0" },
SUB: { o: 0x91, t: "0" },
SUC: { o: 0x92, t: "0" },
SUD: { o: 0x93, t: "0" },
SUE: { o: 0x94, t: "0" },
SUH: { o: 0x95, t: "0" },
SUL: { o: 0x96, t: "0" },
SUM: { o: 0x97, t: "0" },
SBA: { o: 0x98, t: "0" },
SBB: { o: 0x99, t: "0" },
SBC: { o: 0x9a, t: "0" },
SBD: { o: 0x9b, t: "0" },
SBE: { o: 0x9c, t: "0" },
SBH: { o: 0x9d, t: "0" },
SBL: { o: 0x9e, t: "0" },
SBM: { o: 0x9f, t: "0" },
NDA: { o: 0xa0, t: "0" },
NDB: { o: 0xa1, t: "0" },
NDC: { o: 0xa2, t: "0" },
NDD: { o: 0xa3, t: "0" },
NDE: { o: 0xa4, t: "0" },
NDH: { o: 0xa5, t: "0" },
NDL: { o: 0xa6, t: "0" },
NDM: { o: 0xa7, t: "0" },
XRA: { o: 0xa8, t: "0" },
XRB: { o: 0xa9, t: "0" },
XRC: { o: 0xaa, t: "0" },
XRD: { o: 0xab, t: "0" },
XRE: { o: 0xac, t: "0" },
XRH: { o: 0xad, t: "0" },
XRL: { o: 0xae, t: "0" },
XRM: { o: 0xaf, t: "0" },
ORA: { o: 0xb0, t: "0" },
ORB: { o: 0xb1, t: "0" },
ORC: { o: 0xb2, t: "0" },
ORD: { o: 0xb3, t: "0" },
ORE: { o: 0xb4, t: "0" },
ORH: { o: 0xb5, t: "0" },
ORL: { o: 0xb6, t: "0" },
ORM: { o: 0xb7, t: "0" },
CPA: { o: 0xb8, t: "0" },
CPB: { o: 0xb9, t: "0" },
CPC: { o: 0xba, t: "0" },
CPD: { o: 0xbb, t: "0" },
CPE: { o: 0xbc, t: "0" },
CPH: { o: 0xbd, t: "0" },
CPL: { o: 0xbe, t: "0" },
CPM: { o: 0xbf, t: "0" },
LAA: { o: 0xc0, t: "0" },
LAB: { o: 0xc1, t: "0" },
LAC: { o: 0xc2, t: "0" },
LAD: { o: 0xc3, t: "0" },
LAE: { o: 0xc4, t: "0" },
LAH: { o: 0xc5, t: "0" },
LAL: { o: 0xc6, t: "0" },
LAM: { o: 0xc7, t: "0" },
LBA: { o: 0xc8, t: "0" },
LBB: { o: 0xc9, t: "0" },
LBC: { o: 0xca, t: "0" },
LBD: { o: 0xcb, t: "0" },
LBE: { o: 0xcc, t: "0" },
LBH: { o: 0xcd, t: "0" },
LBL: { o: 0xce, t: "0" },
LBM: { o: 0xcf, t: "0" },
LCA: { o: 0xd0, t: "0" },
LCB: { o: 0xd1, t: "0" },
LCC: { o: 0xd2, t: "0" },
LCD: { o: 0xd3, t: "0" },
LCE: { o: 0xd4, t: "0" },
LCH: { o: 0xd5, t: "0" },
LCL: { o: 0xd6, t: "0" },
LCM: { o: 0xd7, t: "0" },
LDA: { o: 0xd8, t: "0" },
LDB: { o: 0xd9, t: "0" },
LDC: { o: 0xda, t: "0" },
LDD: { o: 0xdb, t: "0" },
LDE: { o: 0xdc, t: "0" },
LDH: { o: 0xdd, t: "0" },
LDL: { o: 0xde, t: "0" },
LDM: { o: 0xdf, t: "0" },
LEA: { o: 0xe0, t: "0" },
LEB: { o: 0xe1, t: "0" },
LEC: { o: 0xe2, t: "0" },
LED: { o: 0xe3, t: "0" },
LEE: { o: 0xe4, t: "0" },
LEH: { o: 0xe5, t: "0" },
LEL: { o: 0xe6, t: "0" },
LEM: { o: 0xe7, t: "0" },
LHA: { o: 0xe8, t: "0" },
LHB: { o: 0xe9, t: "0" },
LHC: { o: 0xea, t: "0" },
LHD: { o: 0xeb, t: "0" },
LHE: { o: 0xec, t: "0" },
LHH: { o: 0xed, t: "0" },
LHL: { o: 0xee, t: "0" },
LHM: { o: 0xef, t: "0" },
LLA: { o: 0xf0, t: "0" },
LLB: { o: 0xf1, t: "0" },
LLC: { o: 0xf2, t: "0" },
LLD: { o: 0xf3, t: "0" },
LLE: { o: 0xf4, t: "0" },
LLH: { o: 0xf5, t: "0" },
LLL: { o: 0xf6, t: "0" },
LLM: { o: 0xf7, t: "0" },
LMA: { o: 0xf8, t: "0" },
LMB: { o: 0xf9, t: "0" },
LMC: { o: 0xfa, t: "0" },
LMD: { o: 0xfb, t: "0" },
LME: { o: 0xfc, t: "0" },
LMH: { o: 0xfd, t: "0" },
LML: { o: 0xfe, t: "0" },
LMM: { o: 0xff, t: "0" },
JMP: { o: 0x44, t: "IW" },
CAL: { o: 0x46, t: "IW" },
CALL: { o: 0x46, t: "IW" },
RET: { o: 0x07, t: "0" },
JFC: { o: 0x40, t: "IW" },
JFZ: { o: 0x48, t: "IW" },
JFS: { o: 0x50, t: "IW" },
JFP: { o: 0x58, t: "IW" },
JTC: { o: 0x60, t: "IW" },
JTZ: { o: 0x68, t: "IW" },
JTS: { o: 0x70, t: "IW" },
JTP: { o: 0x78, t: "IW" },
CFC: { o: 0x42, t: "IW" },
CFZ: { o: 0x4a, t: "IW" },
CFS: { o: 0x52, t: "IW" },
CFP: { o: 0x5a, t: "IW" },
CTC: { o: 0x62, t: "IW" },
CTZ: { o: 0x6a, t: "IW" },
CTS: { o: 0x72, t: "IW" },
CTP: { o: 0x7a, t: "IW" },
RFC: { o: 0x03, t: "0" },
RFZ: { o: 0x0b, t: "0" },
RFS: { o: 0x13, t: "0" },
RFP: { o: 0x1b, t: "0" },
RTC: { o: 0x23, t: "0" },
RTZ: { o: 0x2b, t: "0" },
RTS: { o: 0x33, t: "0" },
RTP: { o: 0x3b, t: "0" },
//new syntax
JNC: { o: 0x40, t: "IW" },
JNZ: { o: 0x48, t: "IW" },
JP: { o: 0x50, t: "IW" },
JPO: { o: 0x58, t: "IW" },
JC: { o: 0x60, t: "IW" },
JZ: { o: 0x68, t: "IW" },
JM: { o: 0x70, t: "IW" },
JPE: { o: 0x78, t: "IW" },
CNC: { o: 0x42, t: "IW" },
CNZ: { o: 0x4a, t: "IW" },
CP: { o: 0x52, t: "IW" },
CPO: { o: 0x5a, t: "IW" },
CC: { o: 0x62, t: "IW" },
CZ: { o: 0x6a, t: "IW" },
CM: { o: 0x72, t: "IW" },
//'CPE': {o:0x7a, t:"IW"}, //duplicate, fixed below
"CPE-": { o: 0x7a, t: "IW" }, //fixed CPE
RNC: { o: 0x03, t: "0" },
RNZ: { o: 0x0b, t: "0" },
RP: { o: 0x13, t: "0" },
RPO: { o: 0x1b, t: "0" },
RC: { o: 0x23, t: "0" },
RZ: { o: 0x2b, t: "0" },
RM: { o: 0x33, t: "0" },
RPE: { o: 0x3b, t: "0" },
RST: { o: 0x05, t: "RST" },
INP: { o: 0x41, t: "INP" },
IN: { o: 0x41, t: "INP" }, //new syntax
OUT: { o: 0x51, t: "OUT" },
LAI: { o: 0x06, t: "B" },
LBI: { o: 0x0e, t: "B" },
LCI: { o: 0x16, t: "B" },
LDI: { o: 0x1e, t: "B" },
LEI: { o: 0x26, t: "B" },
LHI: { o: 0x2e, t: "B" },
LLI: { o: 0x36, t: "B" },
LMI: { o: 0x3e, t: "B" },
RLC: { o: 0x02, t: "0" },
RRC: { o: 0x0a, t: "0" },
RAL: { o: 0x12, t: "0" },
RAR: { o: 0x1a, t: "0" },
ADI: { o: 0x04, t: "B" },
ACI: { o: 0x0c, t: "B" },
SUI: { o: 0x14, t: "B" },
SBI: { o: 0x1c, t: "B" },
NDI: { o: 0x24, t: "B" },
ANI: { o: 0x24, t: "B" }, //new syntax
XRI: { o: 0x2c, t: "B" },
ORI: { o: 0x34, t: "B" },
CPI: { o: 0x3c, t: "B" },
INB: { o: 0x08, t: "0" },
INC: { o: 0x10, t: "0" },
IND: { o: 0x18, t: "0" },
INE: { o: 0x20, t: "0" },
INH: { o: 0x28, t: "0" },
INL: { o: 0x30, t: "0" },
DCB: { o: 0x09, t: "0" },
DCC: { o: 0x11, t: "0" },
DCD: { o: 0x19, t: "0" },
DCE: { o: 0x21, t: "0" },
DCH: { o: 0x29, t: "0" },
DCL: { o: 0x31, t: "0" },
//new syntax
MVI: { o: 0x06, t: "RB" },
MOV: { o: 0xc0, t: "RRR" },
//duplicates
"ADD-": { o: 0x80, t: "RR0" },
"ADC-": { o: 0x88, t: "RR0" },
"SUB-": { o: 0x90, t: "RR0" },
"SBB-": { o: 0x98, t: "RR0" },
ANA: { o: 0xa0, t: "RR0" },
"XRA-": { o: 0xa8, t: "RR0" },
"ORA-": { o: 0xb0, t: "RR0" },
CMP: { o: 0xb8, t: "RR0" },
INR: { o: 0x00, t: "RR-" },
DCR: { o: 0x01, t: "RR" },
HLT: { o: 0xff, t: "0" },
NOP: { o: 0xc0, t: "0" },
},
lens: {
R: function (reg) {
return "ABCDEHLM".indexOf(reg.toUpperCase());
},
RDD: function (reg) {
return "BDHSP".indexOf(reg.toUpperCase());
},
RBD: function (reg) {
return "BD".indexOf(reg.toUpperCase());
},
RQQ: function (reg) {
return "BDHPSW".indexOf(reg.toUpperCase());
},
RB: function (op, params, Parser) {
var reg = this.R(params[0]);
if (reg < 0) throw "Unknown register " + params[0];
reg <<= 3;
return [
reg | op,
function (vars) {
return Parser.evaluate(params[1], vars);
},
];
},
B: function (op, params, Parser) {
return [
op,
function (vars) {
return Parser.evaluate(params[0], vars);
},
];
},
RR: function (op, params, Parser) {
var reg = this.R(params[0]);
if (reg < 0) throw "Unknown register " + params[0];
reg <<= 3;
return [reg | op];
},
"RR-": function (op, params, Parser) {
var reg = this.R(params[0]);
if (reg < 0) throw "Unknown register " + params[0];
if (reg === 0) throw "Cannot use A register here";
reg <<= 3;
return [reg | op];
},
RR0: function (op, params, Parser) {
var reg = this.R(params[0]);
if (reg < 0) throw "Unknown register " + params[0];
return [reg | op];
},
RRR: function (op, params, Parser) {
var reg1 = this.R(params[0]);
if (reg1 < 0) throw "Unknown register " + params[0];
if (!params[1]) throw "Missing second register";
var reg2 = this.R(params[1]);
if (reg2 < 0) throw "Unknown register " + params[1];
reg1 <<= 3;
return [reg1 | reg2 | op];
},
RPW: function (op, params, Parser) {
var reg = this.RDD(params[0]);
if (reg < 0 || reg > 3) throw "Unknown register " + params[0];
reg <<= 4;
return [
reg | op,
function (vars) {
return Parser.evaluate(params[1], vars);
},
null,
];
},
RPWD: function (op, params, Parser) {
var reg = this.RDD(params[0]);
if (reg < 0 || reg > 3) throw "Unknown register " + params[0];
reg <<= 4;
return [reg | op];
},
BD: function (op, params, Parser) {
var reg = this.RBD(params[0]);
if (reg < 0 || reg > 1) throw "Unknown register " + params[0];
reg <<= 4;
return [reg | op];
},
RQW: function (op, params, Parser) {
var reg = this.RQQ(params[0]);
if (reg < 0 || reg > 3) throw "Unknown register " + params[0];
reg <<= 4;
return [reg | op];
},
IW: function (op, params, Parser) {
return [
op,
function (vars) {
return Parser.evaluate(params[0], vars);
},
null,
];
},
INP: function (op, params, Parser) {
var v = Parser.evaluate(params[0], {});
if (v < 0 || v > 7) throw "INP address out of limit (0-7): " + params[0];
return [op + (v << 1)];
},
OUT: function (op, params, Parser) {
var v = Parser.evaluate(params[0], {});
if (v < 8 || v > 31)
throw "OUT address out of limit (8-31): " + params[0];
v -= 8;
return [op + (v << 1)];
},
RST: function (op, params, Parser) {
var v = parseInt(params[0], 10);
return [op | (v << 3)];
},
"0": function (op, params, Parser) {
return [op];
},
},
parseOpcode: function (s, vars, Parser) {
var ax = I8008.set[s.opcode];
if (ax) {
if (
s.params &&
["CPE", "ADD", "ADC", "SBB", "SUB", "XRA", "ORA"].indexOf(s.opcode) >=
0 &&
s.params.length
) {
ax = I8008.set[s.opcode + "-"];
}
var typ = ax.t;
var lens = I8008.lens[typ](ax.o, s.params, Parser);
s.bytes = lens.length;
s.lens = lens;
s.wia = 1; //Where is address (for relocation)
s.resolve = lens.reduce(function (inter, v) {
return typeof v == "function" ? inter + 1 : inter;
}, 0);
return s;
}
return null;
},
};
//types
/*
IW - 3 bytes (opcode, LO, HI), format: INSTR num16
RPW - 3 bytes, (opcode, LO, HI), format: INSTR regpair, num16
0 - 1 byte, just instruction
RB - 2 bytes, (opcode, NN), format INSTR reg, NN
*/