@asm80/core
Version:
Core ASM80 compiler / assembler
617 lines (583 loc) • 20.5 kB
JavaScript
(function (name, definition) {
if (typeof module != "undefined") {
module.exports = definition();
M6809 = module.exports;
} else if (typeof define == "function" && typeof define.amd == "object")
define(definition);
else this[name] = definition();
})("M6809", function () {
var M6809 = {
set: {
// 0 1 2 3 4 5 6 7
// noparm direct idxd xtded rel8 imm8 imm16 rel16
NEG: [-1, 0x00, 0x60, 0x70, -1, -1, -1, -1],
COM: [-1, 0x03, 0x63, 0x73, -1, -1, -1, -1],
LSR: [-1, 0x04, 0x64, 0x74, -1, -1, -1, -1],
ROR: [-1, 0x06, 0x66, 0x76, -1, -1, -1, -1],
ASR: [-1, 0x07, 0x67, 0x77, -1, -1, -1, -1],
LSL: [-1, 0x08, 0x68, 0x78, -1, -1, -1, -1],
ASL: [-1, 0x08, 0x68, 0x78, -1, -1, -1, -1],
ROL: [-1, 0x09, 0x69, 0x79, -1, -1, -1, -1],
DEC: [-1, 0x0a, 0x6a, 0x7a, -1, -1, -1, -1],
INC: [-1, 0x0c, 0x6c, 0x7c, -1, -1, -1, -1],
TST: [-1, 0x0d, 0x6d, 0x7d, -1, -1, -1, -1],
JMP: [-1, 0x0e, 0x6e, 0x7e, -1, -1, -1, -1],
CLR: [-1, 0x0f, 0x6f, 0x7f, -1, -1, -1, -1],
LEAX: [-1, -1, 0x30, -1, -1, -1, -1, -1],
LEAY: [-1, -1, 0x31, -1, -1, -1, -1, -1],
LEAS: [-1, -1, 0x32, -1, -1, -1, -1, -1],
LEAU: [-1, -1, 0x33, -1, -1, -1, -1, -1],
NOP: [0x12, -1, -1, -1, -1, -1, -1, -1],
SYNC: [0x13, -1, -1, -1, -1, -1, -1, -1],
DAA: [0x19, -1, -1, -1, -1, -1, -1, -1],
SEX: [0x1d, -1, -1, -1, -1, -1, -1, -1],
RTS: [0x39, -1, -1, -1, -1, -1, -1, -1],
ABX: [0x3a, -1, -1, -1, -1, -1, -1, -1],
RTI: [0x3b, -1, -1, -1, -1, -1, -1, -1],
CWAI: [-1, -1, -1, -1, -1, 0x3c, -1, -1],
MUL: [0x3d, -1, -1, -1, -1, -1, -1, -1],
SWI: [0x3f, -1, -1, -1, -1, -1, -1, -1],
SWI2: [0x103f, -1, -1, -1, -1, -1, -1, -1],
SWI3: [0x113f, -1, -1, -1, -1, -1, -1, -1],
NEGA: [0x40, -1, -1, -1, -1, -1, -1, -1],
COMA: [0x43, -1, -1, -1, -1, -1, -1, -1],
LSRA: [0x44, -1, -1, -1, -1, -1, -1, -1],
RORA: [0x46, -1, -1, -1, -1, -1, -1, -1],
ASRA: [0x47, -1, -1, -1, -1, -1, -1, -1],
LSLA: [0x48, -1, -1, -1, -1, -1, -1, -1],
ASLA: [0x48, -1, -1, -1, -1, -1, -1, -1],
ROLA: [0x49, -1, -1, -1, -1, -1, -1, -1],
DECA: [0x4a, -1, -1, -1, -1, -1, -1, -1],
INCA: [0x4c, -1, -1, -1, -1, -1, -1, -1],
TSTA: [0x4d, -1, -1, -1, -1, -1, -1, -1],
CLRA: [0x4f, -1, -1, -1, -1, -1, -1, -1],
NEGB: [0x50, -1, -1, -1, -1, -1, -1, -1],
COMB: [0x53, -1, -1, -1, -1, -1, -1, -1],
LSRB: [0x54, -1, -1, -1, -1, -1, -1, -1],
RORB: [0x56, -1, -1, -1, -1, -1, -1, -1],
ASRB: [0x57, -1, -1, -1, -1, -1, -1, -1],
LSLB: [0x58, -1, -1, -1, -1, -1, -1, -1],
ASLB: [0x58, -1, -1, -1, -1, -1, -1, -1],
ROLB: [0x59, -1, -1, -1, -1, -1, -1, -1],
DECB: [0x5a, -1, -1, -1, -1, -1, -1, -1],
INCB: [0x5c, -1, -1, -1, -1, -1, -1, -1],
TSTB: [0x5d, -1, -1, -1, -1, -1, -1, -1],
CLRB: [0x5f, -1, -1, -1, -1, -1, -1, -1],
SUBA: [-1, 0x90, 0xa0, 0xb0, -1, 0x80, -1, -1],
CMPA: [-1, 0x91, 0xa1, 0xb1, -1, 0x81, -1, -1],
SBCA: [-1, 0x92, 0xa2, 0xb2, -1, 0x82, -1, -1],
ANDA: [-1, 0x94, 0xa4, 0xb4, -1, 0x84, -1, -1],
BITA: [-1, 0x95, 0xa5, 0xb5, -1, 0x85, -1, -1],
LDA: [-1, 0x96, 0xa6, 0xb6, -1, 0x86, -1, -1],
STA: [-1, 0x97, 0xa7, 0xb7, -1, -1, -1, -1],
EORA: [-1, 0x98, 0xa8, 0xb8, -1, 0x88, -1, -1],
ADCA: [-1, 0x99, 0xa9, 0xb9, -1, 0x89, -1, -1],
ORA: [-1, 0x9a, 0xaa, 0xba, -1, 0x8a, -1, -1],
ADDA: [-1, 0x9b, 0xab, 0xbb, -1, 0x8b, -1, -1],
JSR: [-1, 0x9d, 0xad, 0xbd, -1, -1, -1, -1],
SUBD: [-1, 0x93, 0xa3, 0xb3, -1, -1, 0x83, -1],
CMPX: [-1, 0x9c, 0xac, 0xbc, -1, -1, 0x8c, -1],
LDX: [-1, 0x9e, 0xae, 0xbe, -1, -1, 0x8e, -1],
STX: [-1, 0x9f, 0xaf, 0xbf, -1, -1, -1, -1],
CMPD: [-1, 0x1093, 0x10a3, 0x10b3, -1, -1, 0x1083, -1],
CMPY: [-1, 0x109c, 0x10ac, 0x10bc, -1, -1, 0x108c, -1],
LDY: [-1, 0x109e, 0x10ae, 0x10be, -1, -1, 0x108e, -1],
STY: [-1, 0x109f, 0x10af, 0x10bf, -1, -1, -1, -1],
LDS: [-1, 0x10de, 0x10ee, 0x10fe, -1, -1, 0x10ce, -1],
STS: [-1, 0x10df, 0x10ef, 0x10ff, -1, -1, -1, -1],
SUBB: [-1, 0xd0, 0xe0, 0xf0, -1, 0xc0, -1, -1],
CMPB: [-1, 0xd1, 0xe1, 0xf1, -1, 0xc1, -1, -1],
SBCB: [-1, 0xd2, 0xe2, 0xf2, -1, 0xc2, -1, -1],
ANDB: [-1, 0xd4, 0xe4, 0xf4, -1, 0xc4, -1, -1],
BITB: [-1, 0xd5, 0xe5, 0xf5, -1, 0xc5, -1, -1],
LDB: [-1, 0xd6, 0xe6, 0xf6, -1, 0xc6, -1, -1],
STB: [-1, 0xd7, 0xe7, 0xf7, -1, -1, -1, -1],
EORB: [-1, 0xd8, 0xe8, 0xf8, -1, 0xc8, -1, -1],
ADCB: [-1, 0xd9, 0xe9, 0xf9, -1, 0xc9, -1, -1],
ORB: [-1, 0xda, 0xea, 0xfa, -1, 0xca, -1, -1],
ADDB: [-1, 0xdb, 0xeb, 0xfb, -1, 0xcb, -1, -1],
ADDD: [-1, 0xd3, 0xe3, 0xf3, -1, -1, 0xc3, -1],
LDD: [-1, 0xdc, 0xec, 0xfc, -1, -1, 0xcc, -1],
STD: [-1, 0xdd, 0xed, 0xfd, -1, -1, -1, -1],
LDU: [-1, 0xde, 0xee, 0xfe, -1, -1, 0xce, -1],
STU: [-1, 0xdf, 0xef, 0xff, -1, -1, -1, -1],
CMPS: [-1, 0x119c, 0x11ac, 0x11bc, -1, -1, 0x118c, -1],
CMPU: [-1, 0x1193, 0x11a3, 0x11b3, -1, -1, 0x1183, -1],
LBRA: [-1, -1, -1, -1, -1, -1, -1, 0x16],
LBSR: [-1, -1, -1, -1, -1, -1, -1, 0x17],
BSR: [-1, -1, -1, -1, 0x8d, -1, -1, -1],
BRA: [-1, -1, -1, -1, 0x20, -1, -1, -1],
BRN: [-1, -1, -1, -1, 0x21, -1, -1, -1],
BHI: [-1, -1, -1, -1, 0x22, -1, -1, -1],
BLS: [-1, -1, -1, -1, 0x23, -1, -1, -1],
BHS: [-1, -1, -1, -1, 0x24, -1, -1, -1],
BCC: [-1, -1, -1, -1, 0x24, -1, -1, -1],
BLO: [-1, -1, -1, -1, 0x25, -1, -1, -1],
BCS: [-1, -1, -1, -1, 0x25, -1, -1, -1],
BNE: [-1, -1, -1, -1, 0x26, -1, -1, -1],
BEQ: [-1, -1, -1, -1, 0x27, -1, -1, -1],
BVC: [-1, -1, -1, -1, 0x28, -1, -1, -1],
BVS: [-1, -1, -1, -1, 0x29, -1, -1, -1],
BPL: [-1, -1, -1, -1, 0x2a, -1, -1, -1],
BMI: [-1, -1, -1, -1, 0x2b, -1, -1, -1],
BGE: [-1, -1, -1, -1, 0x2c, -1, -1, -1],
BLT: [-1, -1, -1, -1, 0x2d, -1, -1, -1],
BGT: [-1, -1, -1, -1, 0x2e, -1, -1, -1],
BLE: [-1, -1, -1, -1, 0x2f, -1, -1, -1],
LBRN: [-1, -1, -1, -1, -1, -1, -1, 0x1021],
LBHI: [-1, -1, -1, -1, -1, -1, -1, 0x1022],
LBLS: [-1, -1, -1, -1, -1, -1, -1, 0x1023],
LBHS: [-1, -1, -1, -1, -1, -1, -1, 0x1024],
LBCC: [-1, -1, -1, -1, -1, -1, -1, 0x1024],
LBLO: [-1, -1, -1, -1, -1, -1, -1, 0x1025],
LBCS: [-1, -1, -1, -1, -1, -1, -1, 0x1025],
LBNE: [-1, -1, -1, -1, -1, -1, -1, 0x1026],
LBEQ: [-1, -1, -1, -1, -1, -1, -1, 0x1027],
LBVC: [-1, -1, -1, -1, -1, -1, -1, 0x1028],
LBVS: [-1, -1, -1, -1, -1, -1, -1, 0x1029],
LBPL: [-1, -1, -1, -1, -1, -1, -1, 0x102a],
LBMI: [-1, -1, -1, -1, -1, -1, -1, 0x102b],
LBGE: [-1, -1, -1, -1, -1, -1, -1, 0x102c],
LBLT: [-1, -1, -1, -1, -1, -1, -1, 0x102d],
LBGT: [-1, -1, -1, -1, -1, -1, -1, 0x102e],
LBLE: [-1, -1, -1, -1, -1, -1, -1, 0x102f],
ORCC: [-1, -1, -1, -1, -1, 0x1a, -1, -1],
ANDCC: [-1, -1, -1, -1, -1, 0x1c, -1, -1],
},
parseOpcode: function (s, vars) {
if (!s._dp) s._dp = 0;
var dptest = function (par, vars, s) {
if (s._dp < 0 || s._dp > 255) return false;
try {
zptest = Parser.evaluate(par, vars);
if (zptest !== null && zptest !== undefined) {
var zpp = zptest >> 8;
//console.log("ZPTEST",zptest,s,zpp)
if (zpp === s._dp) return true;
}
} catch (e) {
return false;
}
return false;
};
var parnibble = function (par) {
var r = [
"D",
"X",
"Y",
"U",
"S",
"PC",
"",
"",
"A",
"B",
"CC",
"DP",
].indexOf(par.toUpperCase());
if (r < 0) throw "Not recognized register name";
return r;
};
var pshsbyte = function (par) {
if (par.toUpperCase() == "D") {
return 6;
}
var r = ["CC", "A", "B", "DP", "X", "Y", "U", "PC"].indexOf(
par.toUpperCase()
);
if (r < 0) throw "Not recognized register name";
return 1 << r;
};
var pshubyte = function (par) {
if (par.toUpperCase() == "D") {
return 6;
}
var r = ["CC", "A", "B", "DP", "X", "Y", "S", "PC"].indexOf(
par.toUpperCase()
);
if (r < 0) throw "Not recognized register name";
return 1 << r;
};
var ax = M6809.set[s.opcode];
var zptest,
p1,
p2,
p1x,
p2x,
amode = 0,
code = -1,
i;
var prefixed = 0,
parserfunc = null;
s.lens = [];
//special cases
if (s.opcode == "EXG") {
s.lens[0] = 0x1e;
}
if (s.opcode == "TFR") {
s.lens[0] = 0x1f;
}
if (s.opcode == "EXG" || s.opcode == "TFR") {
s.bytes = 2;
//2 params to nibbles
if (s.params.length != 2)
throw s.opcode + " needs exactly 2 registers at line " + s.numline;
s.lens[1] = (parnibble(s.params[0]) << 4) + parnibble(s.params[1]);
return s;
}
if (s.opcode == "PSHS") {
s.lens[0] = 0x34;
s.bytes = 2;
s.lens[1] = 0;
for (i = 0; i < s.params.length; i++) {
s.lens[1] |= pshsbyte(s.params[i]);
}
return s;
}
if (s.opcode == "PULS") {
s.lens[0] = 0x35;
s.bytes = 2;
s.lens[1] = 0;
for (i = 0; i < s.params.length; i++) {
s.lens[1] |= pshsbyte(s.params[i]);
}
return s;
}
if (s.opcode == "PSHU") {
s.lens[0] = 0x36;
s.bytes = 2;
s.lens[1] = 0;
for (i = 0; i < s.params.length; i++) {
s.lens[1] |= pshubyte(s.params[i]);
}
return s;
}
if (s.opcode == "PULU") {
s.lens[0] = 0x37;
s.bytes = 2;
s.lens[1] = 0;
for (i = 0; i < s.params.length; i++) {
s.lens[1] |= pshubyte(s.params[i]);
}
return s;
}
if (ax) {
if (ax[0] >= 0) {
if (ax[0] > 0xff) {
s.lens = [ax[0] >> 8, ax[0] & 0xff];
s.bytes = 2;
return s;
}
s.lens = [ax[0]];
s.bytes = 1;
return s;
}
//1 parametr
if (s.params.length == 1 && s.params[0][0] !== "[") {
s.bytes = 0;
p1 = s.params[0];
if (p1[0] == "#") {
// imm
//p1 = p1.substr(1);
prefixed = 1;
amode = 5;
if (ax[5] < 0 && ax[6] >= 0) amode = 6;
} else if (p1[0] == "<") {
// forced direct
//p1 = p1.substr(1);
prefixed = 1;
amode = 1;
} else if (p1[0] == ">") {
// forced extended
//p1 = p1.substr(1);
prefixed = 1;
amode = 3;
} else {
//no decoration. Perform ZP test
if (ax[1] >= 0) amode = 1;
if (ax[3] >= 0) amode = 3;
if (ax[4] >= 0) amode = 4; //rel8
if (ax[7] >= 0) amode = 7; //rel16
if (dptest(p1, vars, s) && ax[1] >= 0) amode = 1;
/*
try {
zptest = Parser.evaluate(p1,vars);
console.log("ZPTEST",zptest,s)
if (zptest !== null && zptest !== undefined && zptest<0x100 && ax[1]>=0) amode = 1;
} catch (e) {}
*/
}
//if (amode === 0) throw "Not detected addressing mode at line "+s.numline;
if (ax[amode] == -1) throw "Bad addressing mode at line " + s.numline;
code = ax[amode];
if (amode != 4 && amode != 7) {
parserfunc = prefixed
? function (vars) {
return Parser.evaluate(p1.substr(1), vars);
}
: function (vars) {
return Parser.evaluate(p1, vars);
};
}
if (amode === 1 && s._dp != 0) {
//direct page fix
//console.log("LDP",s._dp)
var ldp = s._dp * 256;
parserfunc = prefixed
? function (vars) {
return Parser.evaluate(p1.substr(1), vars) - ldp;
}
: function (vars) {
return Parser.evaluate(p1, vars) - ldp;
};
}
if (code > 0xff) {
s.bytes += 2;
} else {
s.bytes += 1;
}
if (amode == 4) {
parserfunc = /*prefixed ? (function(vars){
var n = Parser.evaluate(p1.substr(1),vars)-vars._PC-2;
//console.log(n)
if (n>127) throw "Target out of range"
if (n<-128) throw "Target out of range"
if (n<0) {n=256+n;}
return n;
}):*/ function (
vars
) {
var n = Parser.evaluate(p1, vars) - vars._PC - 2;
//console.log(n)
if (n > 127) throw "Target out of range";
if (n < -128) throw "Target out of range";
if (n < 0) {
n = 256 + n;
}
return n;
};
}
if (amode == 7) {
parserfunc = /* prefixed ? (function(vars){
var n = Parser.evaluate(p1.substr(1),vars)-vars._PC-s.bytes;
if (n<0) {n=65536+n;}
return n;
}):*/ function (
vars
) {
var n = Parser.evaluate(p1, vars) - vars._PC - s.bytes;
if (n < 0) {
n = 65536 + n;
}
return n;
};
}
if (code > 0xff) {
s.lens = [code >> 8, code & 0xff, parserfunc];
} else {
s.lens = [code, parserfunc];
}
if (amode == 1) s.bytes++;
if (amode == 5) s.bytes++;
if (amode == 4) s.bytes++;
if (amode == 3) {
s.bytes += 2;
s.lens[s.bytes - 1] = null;
}
if (amode == 6) {
s.bytes += 2;
s.lens[s.bytes - 1] = null;
}
if (amode == 7) {
s.bytes += 2;
s.lens[s.bytes - 1] = null;
}
return s;
}
var postbyte = 1;
s.bytes = 2;
if (s.params.length == 1 && s.params[0][0] === "[") {
if (ax[2] > 256) {
s.lens[0] = ax[2] >> 8;
s.lens[1] = ax[2] & 0xff;
postbyte = 2;
s.bytes++;
} else {
s.lens[0] = ax[2];
}
p1 = s.params[0];
s.lens[postbyte] = 0x9f;
s.lens[postbyte + 1] = function (vars) {
return Parser.evaluate(p1.substr(1, p1.length - 2), vars);
};
s.lens[postbyte + 2] = null;
s.bytes += 2;
return s;
}
// Indexed mode
if (ax[2] <= 0 || s.params.length !== 2)
throw "Bad addressing mode at line " + s.numline;
if (ax[2] > 256) {
s.lens[0] = ax[2] >> 8;
s.lens[1] = ax[2] & 0xff;
postbyte = 2;
s.bytes++;
} else {
s.lens[0] = ax[2];
}
var indir = 0;
p1 = s.params[0];
p2 = s.params[1];
p1x = p1;
p2x = p2;
if (p1[0] == "[" && p2[p2.length - 1] == "]") {
indir = 0x10;
p1 = p1.substr(1);
p2 = p2.substr(0, p2.length - 1);
}
var ixreg = function (par) {
var r = ["X", "Y", "U", "S"].indexOf(par.toUpperCase());
if (r < 0) throw "Register name not recognized: " + par;
return r << 5;
};
var ixregPC = function (par) {
var r = ["X", "Y", "U", "S", "PC"].indexOf(par.toUpperCase());
if (r == 4) return 0x04;
if (r < 0) throw "Register name not recognized: " + par;
return r << 5;
};
if (p1 === "") {
//INS ,R
if (p2[0] == "-") {
//-R
if (p2[1] == "-") {
//--R
s.lens[postbyte] = ixreg(p2.substr(2)) | 0x83 | indir;
} else {
if (indir > 0) throw "Cannot use predecrement with 1";
s.lens[postbyte] = ixreg(p2.substr(1)) | 0x82;
}
} else if (p2[1] == "+") {
//R+
if (p2[2] == "+") {
//R++
s.lens[postbyte] = ixreg(p2.substr(0, 1)) | 0x81 | indir;
} else {
if (indir > 0) throw "Cannot use postincrement with 1";
s.lens[postbyte] = ixreg(p2.substr(0, 1)) | 0x80;
}
} else {
s.lens[postbyte] = ixreg(p2) | 0x84 | indir;
}
return s;
}
if (p1.toUpperCase() === "A") {
//INS A,R
s.lens[postbyte] = ixreg(p2) | 0x86 | indir;
return s;
}
if (p1.toUpperCase() === "B") {
//INS B,R
s.lens[postbyte] = ixreg(p2) | 0x85 | indir;
return s;
}
if (p1.toUpperCase() === "D") {
//INS A,R
s.lens[postbyte] = ixreg(p2) | 0x8b | indir;
return s;
}
try {
zptest = Parser.evaluate(p1, vars);
if (p2.toUpperCase() == "PC") {
zptest -= vars._PC;
}
//console.log(s,zptest,vars._PC-zptest-3);
} catch (e) {
zptest = null;
}
/*
console.log(
"AZP",
p1,
p2,
ixreg(p2),
indir,
zptest,
(32 - (65536 - zptest)) & 0x1f
);
*/
if (zptest > 65536 - 17 && ixregPC(p2) != 4) {
//direct
s.lens[postbyte] =
ixreg(p2) | indir | ((32 - (65536 - zptest)) & 0x1f);
return s;
}
//console.log(s.params,zptest);
if (zptest < 16 && zptest > -17 && ixregPC(p2) != 4) {
//direct
s.lens[postbyte] = ixreg(p2) | indir | (zptest & 0x1f);
return s;
}
if (zptest < 128 && zptest > -129 && zptest !== null) {
//direct
if (zptest < 0) zptest = 256 + zptest;
s.lens[postbyte] = ixregPC(p2) | indir | 0x88;
s.bytes++;
if (p2.toUpperCase() == "PC") {
s.lens[postbyte + 1] = indir
? function (vars) {
var n =
Parser.evaluate(p1x.substr(1), vars) - vars._PC - s.bytes;
if (n < 0) n = 256 + n;
return n;
}
: function (vars) {
var n = Parser.evaluate(p1x, vars) - vars._PC - s.bytes;
if (n < 0) n = 256 + n;
return n;
};
} else {
s.lens[postbyte + 1] = indir
? function (vars) {
return Parser.evaluate(p1x.substr(1), vars);
}
: function (vars) {
return Parser.evaluate(p1x, vars);
};
}
return s;
}
s.bytes += 2;
s.lens[postbyte] = ixregPC(p2) | indir | 0x89;
if (p2.toUpperCase() == "PC") {
s.lens[postbyte + 1] = indir
? function (vars) {
var n =
Parser.evaluate(p1x.substr(1), vars) - vars._PC - s.bytes;
if (n < 0) n += 65536;
return n;
}
: function (vars) {
var n = Parser.evaluate(p1x, vars) - vars._PC - s.bytes;
if (n < 0) n += 65536;
return n;
};
} else {
s.lens[postbyte + 1] = indir
? function (vars) {
return Parser.evaluate(p1x.substr(1), vars);
}
: function (vars) {
return Parser.evaluate(p1x, vars);
};
}
// s.lens[postbyte+1] = function(vars){return Parser.evaluate(p1x,vars);};
s.lens[postbyte + 2] = null;
return s;
}
return null;
},
endian: true,
};
return M6809;
});