(function (name, definition) { if (typeof module != "undefined") module.exports = definition(); else if (typeof define == "function" && typeof define.amd == "object") define(definition); else this[name] = definition(); })("CPU6809", function () { var rA, rB, rX, rY, rU, rS, PC, CC, DP, F_CARRY = 1, F_OVERFLOW = 2, F_ZERO = 4, F_NEGATIVE = 8, F_IRQMASK = 16, F_HALFCARRY = 32, F_FIRQMASK = 64, F_ENTIRE = 128, vecRESET = 0xfffe, vecNMI = 0xfffc, vecSWI = 0xfffa, vecIRQ = 0xfff8, vecFIRQ = 0xfff6, vecSWI2 = 0xfff4, vecSWI3 = 0xfff2, ticks = null, T = 0; var IRQs; var byteTo, byteAt; var cycles = [ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 6, 3, 6 /* 00-0F */, 0, 0, 2, 4, 0, 0, 5, 9, 0, 2, 3, 0, 3, 2, 8, 6 /* 10-1F */, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 /* 20-2F */, 4, 4, 4, 4, 5, 5, 5, 5, 0, 5, 3, 6, 9, 11, 0, 19 /* 30-3F */, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2 /* 40-4F */, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2 /* 50-5F */, 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 6, 3, 6 /* 60-6F */, 7, 0, 0, 7, 7, 0, 7, 7, 7, 7, 7, 0, 7, 7, 4, 7 /* 70-7F */, 2, 2, 2, 4, 2, 2, 2, 0, 2, 2, 2, 2, 4, 7, 3, 0 /* 80-8F */, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5 /* 90-9F */, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 6, 7, 5, 5 /* A0-AF */, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 7, 8, 6, 6 /* B0-BF */, 2, 2, 2, 4, 2, 2, 2, 0, 2, 2, 2, 2, 3, 0, 3, 0 /* C0-CF */, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5 /* D0-DF */, 4, 4, 4, 6, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5 /* E0-EF */, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, ]; /* F0-FF */ /* Instruction timing for the two-byte opcodes */ var cycles2 = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 00-0F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 10-1F */, 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 /* 20-2F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20 /* 30-3F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 40-4F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 50-5F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 60-6F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70-7F */, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 4, 0 /* 80-8F */, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 6, 6 /* 90-9F */, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 6, 6 /* A0-AF */, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 7, 7 /* B0-BF */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0 /* C0-CF */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6 /* D0-DF */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6 /* E0-EF */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, ]; /* F0-FF */ /* Negative and zero flags for quicker flag settings */ var flagsNZ = [ 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 00-0F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 10-1F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 20-2F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 30-3F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 40-4F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 50-5F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 60-6F */, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70-7F */, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 /* 80-8F */, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 /* 90-9F */, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 /* A0-AF */, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 /* B0-BF */, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 /* C0-CF */, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 /* D0-DF */, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 /* E0-EF */, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, ]; /* F0-FF */ var setV8 = function (a, b, r) { CC |= ((a ^ b ^ r ^ (r >> 1)) & 0x80) >> 6; }; var setV8cmp = function (a, b, r) { if ((a ^ b) & (a ^ r)) CC |= F_OVERFLOW; }; var setV16 = function (a, b, r) { CC |= ((a ^ b ^ r ^ (r >> 1)) & 0x8000) >> 14; }; var getD = function () { return rA * 256 + rB; }; var setD = function (v) { rA = (v >> 8) & 0xff; rB = v & 0xff; }; var PUSHB = function (b) { byteTo(--rS, b & 0xff); }; var PUSHW = function (b) { byteTo(--rS, b & 0xff); byteTo(--rS, (b >> 8) & 0xff); }; var PUSHBU = function (b) { byteTo(--rU, b & 0xff); }; var PUSHWU = function (b) { byteTo(--rU, b & 0xff); byteTo(--rU, (b >> 8) & 0xff); }; var PULLB = function (b) { return byteAt(rS++); }; var PULLW = function (b) { return byteAt(rS++) * 256 + byteAt(rS++); }; var PULLBU = function (b) { return byteAt(rU++); }; var PULLWU = function (b) { return byteAt(rU++) * 256 + byteAt(rU++); }; var PSHS = function (ucTemp) { var i = 0; if (ucTemp & 0x80) { PUSHW(PC); i += 2; } if (ucTemp & 0x40) { PUSHW(rU); i += 2; } if (ucTemp & 0x20) { PUSHW(rY); i += 2; } if (ucTemp & 0x10) { PUSHW(rX); i += 2; } if (ucTemp & 0x8) { PUSHB(DP); i++; } if (ucTemp & 0x4) { PUSHB(rB); i++; } if (ucTemp & 0x2) { PUSHB(rA); i++; } if (ucTemp & 0x1) { PUSHB(CC); i++; } T += i; //timing }; var PSHU = function (ucTemp) { var i = 0; if (ucTemp & 0x80) { PUSHWU(PC); i += 2; } if (ucTemp & 0x40) { PUSHWU(rS); i += 2; } if (ucTemp & 0x20) { PUSHWU(rY); i += 2; } if (ucTemp & 0x10) { PUSHWU(rX); i += 2; } if (ucTemp & 0x8) { PUSHBU(DP); i++; } if (ucTemp & 0x4) { PUSHBU(rB); i++; } if (ucTemp & 0x2) { PUSHBU(rA); i++; } if (ucTemp & 0x1) { PUSHBU(CC); i++; } T += i; //timing }; var PULS = function (ucTemp) { var i = 0; if (ucTemp & 0x1) { CC = PULLB(); i++; } if (ucTemp & 0x2) { rA = PULLB(); i++; } if (ucTemp & 0x4) { rB = PULLB(); i++; } if (ucTemp & 0x8) { DP = PULLB(); i++; } if (ucTemp & 0x10) { rX = PULLW(); i += 2; } if (ucTemp & 0x20) { rY = PULLW(); i += 2; } if (ucTemp & 0x40) { rU = PULLW(); i += 2; } if (ucTemp & 0x80) { PC = PULLW(); i += 2; } T += i; //timing }; var PULU = function (ucTemp) { var i = 0; if (ucTemp & 0x1) { CC = PULLBU(); i++; } if (ucTemp & 0x2) { rA = PULLBU(); i++; } if (ucTemp & 0x4) { rB = PULLBU(); i++; } if (ucTemp & 0x8) { DP = PULLBU(); i++; } if (ucTemp & 0x10) { rX = PULLWU(); i += 2; } if (ucTemp & 0x20) { rY = PULLWU(); i += 2; } if (ucTemp & 0x40) { rS = PULLWU(); i += 2; } if (ucTemp & 0x80) { PC = PULLWU(); i += 2; } T += i; //timing }; var getPBR = function (ucPostByte) { switch (ucPostByte & 0xf) { case 0x00 /* D */: return getD(); case 0x1 /* X */: return rX; case 0x2 /* Y */: return rY; case 0x3 /* U */: return rU; case 0x4 /* S */: return rS; case 0x5 /* PC */: return PC; case 0x8 /* A */: return rA; case 0x9 /* B */: return rB; case 0xa /* CC */: return CC; case 0xb /* DP */: return DP; default: /* illegal */ return null; } }; var setPBR = function (ucPostByte, v) { switch (ucPostByte & 0xf /* Get destination register */) { case 0x00 /* D */: setD(v); return; case 0x1 /* X */: rX = v; return; case 0x2 /* Y */: rY = v; return; case 0x3 /* U */: rU = v; return; case 0x4 /* S */: rS = v; return; case 0x5 /* PC */: PC = v; return; case 0x8 /* A */: rA = v; return; case 0x9 /* B */: rB = v; return; case 0xa /* CC */: CC = v; return; case 0xb /* DP */: DP = v; return; default: /* illegal */ return; } }; var TFREXG = function (ucPostByte, bExchange) { var ucTemp = ucPostByte & 0x88; if (ucTemp == 0x80 || ucTemp == 0x08) ucTemp = 0; /* PROBLEM! */ if (bExchange) { ucTemp = getPBR(ucPostByte >> 4); setPBR(ucPostByte >> 4, getPBR(ucPostByte)); setPBR(ucPostByte, ucTemp); } /* Transfer */ else { setPBR(ucPostByte, getPBR(ucPostByte >> 4)); } }; var signed = function (x) { return x > 127 ? x - 256 : x; }; var signed16 = function (x) { return x > 32767 ? x - 65536 : x; }; var fetch = function () { var v = byteAt(PC++); PC &= 0xffff; return v; }; var fetch16 = function () { var v1 = byteAt(PC++); PC &= 0xffff; var v2 = byteAt(PC++); PC &= 0xffff; return v1 * 256 + v2; }; var ReadWord = function (addr) { var v1 = byteAt(addr++); addr &= 0xffff; var v2 = byteAt(addr++); addr &= 0xffff; return v1 * 256 + v2; }; var WriteWord = function (addr, v) { byteTo(addr++, (v >> 8) & 0xff); addr &= 0xffff; byteTo(addr, v & 0xff); }; var PostByte = function () { var pb = fetch(); var preg; switch (pb & 0x60) { case 0: preg = rX; break; case 0x20: preg = rY; break; case 0x40: preg = rU; break; case 0x60: preg = rS; break; } var xchg = null; var addr = null; var sTemp; if (pb & 0x80) { /* Complex stuff */ switch (pb & 0x0f) { case 0 /* EA = ,reg+ */: addr = preg; xchg = preg + 1; T += 2; break; case 1 /* EA = ,reg++ */: addr = preg; xchg = preg + 2; T += 3; break; case 2 /* EA = ,-reg */: xchg = preg - 1; addr = xchg; T += 2; break; case 3 /* EA = ,--reg */: xchg = preg - 2; addr = xchg; T += 3; break; case 4 /* EA = ,reg */: addr = preg; break; case 5 /* EA = ,reg + B */: //usAddr = *pReg + (signed short)(signed char)regs->ucRegB; addr = preg + signed(rB); T += 1; break; case 6 /* EA = ,reg + A */: addr = preg + signed(rA); T += 1; break; case 7 /* illegal */: addr = 0; break; case 8 /* EA = ,reg + 8-bit offset */: addr = preg + signed(fetch()); T += 1; break; case 9 /* EA = ,reg + 16-bit offset */: addr = preg + signed16(fetch16()); T += 4; break; case 0xa /* illegal */: addr = 0; break; case 0xb /* EA = ,reg + D */: T += 4; addr = preg + getD(); break; case 0xc /* EA = PC + 8-bit offset */: sTemp = signed(fetch()); addr = PC + sTemp; T += 1; break; case 0xd /* EA = PC + 16-bit offset */: sTemp = signed16(fetch16()); addr = PC + sTemp; T += 5; break; case 0xe /* Illegal */: addr = 0; break; case 0xf /* EA = [,address] */: T += 5; addr = fetch16(); break; } /* switch */ addr &= 0xffff; if (pb & 0x10) { /* Indirect addressing */ addr = byteAt(addr) * 256 + byteAt((addr + 1) & 0xffff); T += 3; } } /* Just a 5 bit signed offset + register */ else { var sByte = pb & 0x1f; if (sByte > 15) /* Two's complement 5-bit value */ sByte -= 32; addr = preg + sByte; T += 1; } if (xchg !== null) { switch (pb & 0x60) { case 0: rX = xchg; break; case 0x20: rY = xchg; break; case 0x40: rU = xchg; break; case 0x60: rS = xchg; break; } } return addr & 0xffff; /* Return the effective address */ }; var flagsNZ16 = function (word) { CC &= ~(F_ZERO | F_NEGATIVE); if (word === 0) CC |= F_ZERO; if (word & 0x8000) CC |= F_NEGATIVE; }; // ============= Operations var oINC = function (b) { b++; b &= 0xff; CC &= ~(F_ZERO | F_OVERFLOW | F_NEGATIVE); CC |= flagsNZ[b]; if (b === 0 || b == 0x80) CC |= F_OVERFLOW; return b; }; var oDEC = function (b) { b--; b &= 0xff; CC &= ~(F_ZERO | F_OVERFLOW | F_NEGATIVE); CC |= flagsNZ[b]; if (b === 0x7f || b == 0xff) CC |= F_OVERFLOW; return b; }; var oSUB = function (b, v) { var temp = b - v; //temp &= 0xff; CC &= ~(F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); CC |= flagsNZ[temp & 0xff]; if (temp & 0x100) CC |= F_CARRY; setV8(b, v, temp); return temp & 0xff; }; var oSUB16 = function (b, v) { var temp = b - v; //temp &= 0xff; CC &= ~(F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); if ((temp & 0xffff) === 0) CC |= F_ZERO; if (temp & 0x8000) CC |= F_NEGATIVE; if (temp & 0x10000) CC |= F_CARRY; setV16(b, v, temp); return temp & 0xffff; }; var oADD = function (b, v) { var temp = b + v; //temp &= 0xff; CC &= ~(F_HALFCARRY | F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); CC |= flagsNZ[temp & 0xff]; if (temp & 0x100) CC |= F_CARRY; setV8(b, v, temp); if ((temp ^ b ^ v) & 0x10) CC |= F_HALFCARRY; return temp & 0xff; }; var oADD16 = function (b, v) { var temp = b + v; //temp &= 0xff; CC &= ~(F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); if ((temp & 0xffff) === 0) CC |= F_ZERO; if (temp & 0x8000) CC |= F_NEGATIVE; if (temp & 0x10000) CC |= F_CARRY; setV16(b, v, temp); return temp & 0xffff; }; var oADC = function (b, v) { var temp = b + v + (CC & F_CARRY); //temp &= 0xff; CC &= ~(F_HALFCARRY | F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); CC |= flagsNZ[temp & 0xff]; if (temp & 0x100) CC |= F_CARRY; setV8(b, v, temp); if ((temp ^ b ^ v) & 0x10) CC |= F_HALFCARRY; return temp & 0xff; }; var oSBC = function (b, v) { var temp = b - v - (CC & F_CARRY); //temp &= 0xff; CC &= ~(F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); CC |= flagsNZ[temp & 0xff]; if (temp & 0x100) CC |= F_CARRY; setV8(b, v, temp); return temp & 0xff; }; /* var oSUB = function(b,v) { var temp = b-v; //temp &= 0xff; CC &= ~(F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); CC |= flagsNZ[temp & 0xff]; if (temp&0x100) CC|=F_CARRY; setV8(b,v,temp); return temp&0xff; }; */ var oCMP = function (b, v) { var temp = b - v; //temp &= 0xff; CC &= ~(F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); CC |= flagsNZ[temp & 0xff]; if (temp & 0x100) CC |= F_CARRY; //setV8cmp(b,v,temp); setV8(b, v, temp); return; }; var oCMP16 = function (b, v) { var temp = b - v; //temp &= 0xff; CC &= ~(F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); if ((temp & 0xffff) === 0) CC |= F_ZERO; if (temp & 0x8000) CC |= F_NEGATIVE; if (temp & 0x10000) CC |= F_CARRY; setV16(b, v, temp); return; }; var oNEG = function (b) { CC &= ~(F_CARRY | F_ZERO | F_OVERFLOW | F_NEGATIVE); if (b == 0x80) CC |= F_OVERFLOW; b = (~b & 0xff) + 1; if (b === 0) CC |= F_ZERO; else { CC |= F_CARRY; } if (b & 0x80) { CC |= F_NEGATIVE; } if (b & 0x80) CC |= F_NEGATIVE; return b; }; var oLSR = function (b) { CC &= ~(F_ZERO | F_CARRY | F_NEGATIVE); if (b & 0x01) CC |= F_CARRY; b >>= 1; if (b === 0) CC |= F_ZERO; return b & 0xff; }; var oASR = function (b) { CC &= ~(F_ZERO | F_CARRY | F_NEGATIVE); if (b & 0x01) CC |= F_CARRY; b = (b & 0x80) | (b >> 1); CC |= flagsNZ[b]; return b; }; var oASL = function (b) { var temp = b; CC &= ~(F_ZERO | F_CARRY | F_NEGATIVE | F_OVERFLOW); if (b & 0x80) CC |= F_CARRY; b <<= 1; CC |= flagsNZ[b]; if ((b ^ temp) & 0x80) CC |= F_OVERFLOW; return b; }; var oROL = function (b) { var temp = b; var oldc = CC & F_CARRY; CC &= ~(F_ZERO | F_CARRY | F_NEGATIVE | F_OVERFLOW); if (b & 0x80) CC |= F_CARRY; b = (b << 1) | oldc; CC |= flagsNZ[b]; if ((b ^ temp) & 0x80) CC |= F_OVERFLOW; return b; }; var oROR = function (b) { var oldc = CC & F_CARRY; CC &= ~(F_ZERO | F_CARRY | F_NEGATIVE); if (b & 0x01) CC |= F_CARRY; b = (b >> 1) | (oldc << 7); CC |= flagsNZ[b]; // if ((b ^ temp) & 0x80) CC|=F_OVERFLOW; return b; }; var oEOR = function (b, v) { CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); b ^= v; CC |= flagsNZ[b]; return b; }; var oOR = function (b, v) { CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); b |= v; CC |= flagsNZ[b]; return b; }; var oAND = function (b, v) { CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); b &= v; CC |= flagsNZ[b]; return b; }; var oCOM = function (b) { CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); b ^= 0xff; CC |= flagsNZ[b]; CC |= F_CARRY; return b; }; //----common var dpadd = function () { //direct page + 8bit index return DP * 256 + fetch(); }; var step = function () { var oldT = T; if (IRQs) { //;;; } var addr = null; var pb = null; var oldPC = PC; var opcode = fetch(); T += cycles[opcode]; switch (opcode) { case 0x00: //NEG DP addr = dpadd(); byteTo(addr, oNEG(byteAt(addr))); break; case 0x03: //COM DP addr = dpadd(); byteTo(addr, oCOM(byteAt(addr))); break; case 0x04: //LSR DP addr = dpadd(); byteTo(addr, oLSR(byteAt(addr))); break; case 0x06: //ROR DP addr = dpadd(); byteTo(addr, oROR(byteAt(addr))); break; case 0x07: //ASR DP addr = dpadd(); byteTo(addr, oASR(byteAt(addr))); break; case 0x08: //ASL DP addr = dpadd(); byteTo(addr, oASL(byteAt(addr))); break; case 0x09: //ROL DP addr = dpadd(); byteTo(addr, oROL(byteAt(addr))); break; case 0x0a: //DEC DP addr = dpadd(); byteTo(addr, oDEC(byteAt(addr))); break; case 0x0c: //INC DP addr = dpadd(); byteTo(addr, oINC(byteAt(addr))); break; case 0x0d: //TST DP addr = dpadd(); pb = byteAt(addr); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[pb]; break; case 0x0e: //JMP DP addr = dpadd(); PC = addr; break; case 0x0f: //CLR DP addr = dpadd(); byteTo(addr, 0); CC &= ~(F_CARRY | F_NEGATIVE | F_OVERFLOW); CC |= F_ZERO; break; case 0x12: //NOP break; case 0x13: //SYNC break; case 0x16: //LBRA relative addr = signed16(fetch16()); PC += addr; break; case 0x17: //LBSR relative addr = signed16(fetch16()); PUSHW(PC); PC += addr; break; case 0x19: //DAA var tdaa; //var precarry = CC & F_CARRY; var cf = 0; var nhi = rA & 0xf0, nlo = rA & 0x0f; if (nlo > 0x09 || CC & 0x20) cf |= 0x06; if (nhi > 0x80 && nlo > 0x09) cf |= 0x60; if (nhi > 0x90 || CC & 0x01) cf |= 0x60; tdaa = cf + rA; CC &= ~(F_NEGATIVE | F_ZERO | F_OVERFLOW); if (tdaa & 0x100) CC |= F_CARRY; rA = tdaa & 0xff; CC |= flagsNZ[rA]; //console.log(precarry, CC & F_CARRY); break; case 0x1a: //ORCC CC |= fetch(); break; case 0x1c: //ANDCC CC &= fetch(); break; case 0x1d: //SEX rA = rB & 0x80 ? 0xff : 0; flagsNZ16(getD()); CC &= ~F_OVERFLOW; break; case 0x1e: //EXG pb = fetch(); TFREXG(pb, true); break; case 0x1f: //EXG pb = fetch(); TFREXG(pb, false); break; case 0x20: //BRA addr = signed(fetch()); PC += addr; break; case 0x21: //BRN addr = signed(fetch()); break; case 0x22: //BHI addr = signed(fetch()); if (!(CC & (F_CARRY | F_ZERO))) PC += addr; break; case 0x23: //BLS addr = signed(fetch()); if (CC & (F_CARRY | F_ZERO)) PC += addr; break; case 0x24: //BCC addr = signed(fetch()); if (!(CC & F_CARRY)) PC += addr; break; case 0x25: //BCS addr = signed(fetch()); if (CC & F_CARRY) PC += addr; break; case 0x26: //BNE addr = signed(fetch()); if (!(CC & F_ZERO)) PC += addr; break; case 0x27: //BEQ addr = signed(fetch()); if (CC & F_ZERO) PC += addr; break; case 0x28: //BVC addr = signed(fetch()); if (!(CC & F_OVERFLOW)) PC += addr; break; case 0x29: //BVS addr = signed(fetch()); if (CC & F_OVERFLOW) PC += addr; break; case 0x2a: //BPL addr = signed(fetch()); if (!(CC & F_NEGATIVE)) PC += addr; break; case 0x2b: //BMI addr = signed(fetch()); if (CC & F_NEGATIVE) PC += addr; break; case 0x2c: //BGE addr = signed(fetch()); if (!((CC & F_NEGATIVE) ^ ((CC & F_OVERFLOW) << 2))) PC += addr; break; case 0x2d: //BLT addr = signed(fetch()); if ((CC & F_NEGATIVE) ^ ((CC & F_OVERFLOW) << 2)) PC += addr; break; case 0x2e: //BGT addr = signed(fetch()); //if (!((CC&F_NEGATIVE) ^ ((CC&F_OVERFLOW)<<2) || (CC&F_ZERO))) PC += addr; if (!((CC & F_NEGATIVE) ^ ((CC & F_OVERFLOW) << 2) || CC & F_ZERO)) PC += addr; break; case 0x2f: //BLE addr = signed(fetch()); if ((CC & F_NEGATIVE) ^ ((CC & F_OVERFLOW) << 2) || CC & F_ZERO) PC += addr; break; case 0x30: //LEAX rX = PostByte(); if (rX === 0) CC |= F_ZERO; else CC &= ~F_ZERO; break; case 0x31: //LEAY rY = PostByte(); if (rY === 0) CC |= F_ZERO; else CC &= ~F_ZERO; break; case 0x32: //LEAS rS = PostByte(); break; case 0x33: //LEAU rU = PostByte(); break; case 0x34: //PSHS PSHS(fetch()); break; case 0x35: //PULS PULS(fetch()); break; case 0x36: //PSHU PSHU(fetch()); break; case 0x37: //PULU PULU(fetch()); break; case 0x39: //RTS PC = PULLW(); break; case 0x3a: //ABX rX += rB; break; case 0x3b: //RTI CC = PULLB(); if (CC & F_ENTIRE) { T += 9; rA = PULLB(); rB = PULLB(); DP = PULLB(); rX = PULLW(); rY = PULLW(); rU = PULLW(); } PC = PULLW(); break; case 0x3c: //CWAI **todo CC &= fetch(); break; case 0x3d: //MUL addr = rA * rB; if (addr === 0) CC |= F_ZERO; else CC &= ~F_ZERO; if (addr & 0x80) CC |= F_CARRY; else CC &= ~F_CARRY; setD(addr); break; case 0x3f: //SWI CC |= F_ENTIRE; PUSHW(PC); PUSHW(rU); PUSHW(rY); PUSHW(rX); PUSHB(DP); PUSHB(rB); PUSHB(rA); PUSHB(CC); CC |= F_IRQMASK | F_FIRQMASK; PC = ReadWord(vecSWI); break; case 0x40: rA = oNEG(rA); break; case 0x43: rA = oCOM(rA); break; case 0x44: rA = oLSR(rA); break; case 0x46: rA = oROR(rA); break; case 0x47: rA = oASR(rA); break; case 0x48: rA = oASL(rA); break; case 0x49: rA = oROL(rA); break; case 0x4a: rA = oDEC(rA); break; case 0x4c: rA = oINC(rA); break; case 0x4d: CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rA]; break; case 0x4f: rA = 0; CC &= ~(F_NEGATIVE | F_OVERFLOW | F_CARRY); CC |= F_ZERO; break; case 0x50: rB = oNEG(rB); break; case 0x53: rB = oCOM(rB); break; case 0x54: rB = oLSR(rB); break; case 0x56: rB = oROR(rB); break; case 0x57: rB = oASR(rB); break; case 0x58: rB = oASL(rB); break; case 0x59: rB = oROL(rB); break; case 0x5a: rB = oDEC(rB); break; case 0x5c: rB = oINC(rB); break; case 0x5d: CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rB]; break; case 0x5f: rB = 0; CC &= ~(F_NEGATIVE | F_OVERFLOW | F_CARRY); CC |= F_ZERO; break; case 0x60: //NEG indexed addr = PostByte(); byteTo(addr, oNEG(byteAt(addr))); break; case 0x63: //COM indexed addr = PostByte(); byteTo(addr, oCOM(byteAt(addr))); break; case 0x64: //LSR indexed addr = PostByte(); byteTo(addr, oLSR(byteAt(addr))); break; case 0x66: //ROR indexed addr = PostByte(); byteTo(addr, oROR(byteAt(addr))); break; case 0x67: //ASR indexed addr = PostByte(); byteTo(addr, oASR(byteAt(addr))); break; case 0x68: //ASL indexed addr = PostByte(); byteTo(addr, oASL(byteAt(addr))); break; case 0x69: //ROL indexed addr = PostByte(); byteTo(addr, oROL(byteAt(addr))); break; case 0x6a: //DEC indexed addr = PostByte(); byteTo(addr, oDEC(byteAt(addr))); break; case 0x6c: //INC indexed addr = PostByte(); byteTo(addr, oINC(byteAt(addr))); break; case 0x6d: //TST indexed addr = PostByte(); pb = byteAt(addr); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[pb]; break; case 0x6e: //JMP indexed addr = PostByte(); PC = addr; break; case 0x6f: //CLR indexed addr = PostByte(); byteTo(addr, 0); CC &= ~(F_CARRY | F_NEGATIVE | F_OVERFLOW); CC |= F_ZERO; break; case 0x70: //NEG extended addr = fetch16(); byteTo(addr, oNEG(byteAt(addr))); break; case 0x73: //COM extended addr = fetch16(); byteTo(addr, oCOM(byteAt(addr))); break; case 0x74: //LSR extended addr = fetch16(); byteTo(addr, oLSR(byteAt(addr))); break; case 0x76: //ROR extended addr = fetch16(); byteTo(addr, oROR(byteAt(addr))); break; case 0x77: //ASR extended addr = fetch16(); byteTo(addr, oASR(byteAt(addr))); break; case 0x78: //ASL extended addr = fetch16(); byteTo(addr, oASL(byteAt(addr))); break; case 0x79: //ROL extended addr = fetch16(); byteTo(addr, oROL(byteAt(addr))); break; case 0x7a: //DEC extended addr = fetch16(); byteTo(addr, oDEC(byteAt(addr))); break; case 0x7c: //INC extended addr = fetch16(); byteTo(addr, oINC(byteAt(addr))); break; case 0x7d: //TST extended addr = fetch16(); pb = byteAt(addr); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[pb]; break; case 0x7e: //JMP extended addr = fetch16(); PC = addr; break; case 0x7f: //CLR extended addr = fetch16(); byteTo(addr, 0); CC &= ~(F_CARRY | F_NEGATIVE | F_OVERFLOW); CC |= F_ZERO; break; // regs A,X case 0x80: //SUBA imm rA = oSUB(rA, fetch()); break; case 0x81: //CMPA imm oCMP(rA, fetch()); break; case 0x82: //SBCA imm rA = oSBC(rA, fetch()); break; case 0x83: //SUBD imm setD(oSUB16(getD(), fetch16())); break; case 0x84: //ANDA imm rA = oAND(rA, fetch()); break; case 0x85: //BITA imm oAND(rA, fetch()); break; case 0x86: //LDA imm rA = fetch(); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rA]; break; case 0x88: //EORA imm rA = oEOR(rA, fetch()); break; case 0x89: //ADCA imm rA = oADC(rA, fetch()); break; case 0x8a: //ORA imm rA = oOR(rA, fetch()); break; case 0x8b: //ADDA imm rA = oADD(rA, fetch()); break; case 0x8c: //CMPX imm oCMP16(rX, fetch16()); break; case 0x8d: //JSR imm addr = signed(fetch()); PUSHW(PC); PC += addr; break; case 0x8e: //LDX imm rX = fetch16(); flagsNZ16(rX); CC &= ~F_OVERFLOW; break; case 0x90: //SUBA direct addr = dpadd(); rA = oSUB(rA, byteAt(addr)); break; case 0x91: //CMPA direct addr = dpadd(); oCMP(rA, byteAt(addr)); break; case 0x92: //SBCA direct addr = dpadd(); rA = oSBC(rA, byteAt(addr)); break; case 0x93: //SUBD direct addr = dpadd(); setD(oSUB16(getD(), ReadWord(addr))); break; case 0x94: //ANDA direct addr = dpadd(); rA = oAND(rA, byteAt(addr)); break; case 0x95: //BITA direct addr = dpadd(); oAND(rA, byteAt(addr)); break; case 0x96: //LDA direct addr = dpadd(); rA = byteAt(addr); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rA]; break; case 0x97: //STA direct addr = dpadd(); byteTo(addr, rA); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rA]; break; case 0x98: //EORA direct addr = dpadd(); rA = oEOR(rA, byteAt(addr)); break; case 0x99: //ADCA direct addr = dpadd(); rA = oADC(rA, byteAt(addr)); break; case 0x9a: //ORA direct addr = dpadd(); rA = oOR(rA, byteAt(addr)); break; case 0x9b: //ADDA direct addr = dpadd(); rA = oADD(rA, byteAt(addr)); break; case 0x9c: //CMPX direct addr = dpadd(); oCMP16(rX, ReadWord(addr)); break; case 0x9d: //JSR direct addr = dpadd(); PUSHW(PC); PC = addr; break; case 0x9e: //LDX direct addr = dpadd(); rX = ReadWord(addr); flagsNZ16(rX); CC &= ~F_OVERFLOW; break; case 0x9f: //STX direct addr = dpadd(); WriteWord(addr, rX); flagsNZ16(rX); CC &= ~F_OVERFLOW; break; case 0xa0: //SUBA indexed addr = PostByte(); rA = oSUB(rA, byteAt(addr)); break; case 0xa1: //CMPA indexed addr = PostByte(); oCMP(rA, byteAt(addr)); break; case 0xa2: //SBCA indexed addr = PostByte(); rA = oSBC(rA, byteAt(addr)); break; case 0xa3: //SUBD indexed addr = PostByte(); setD(oSUB16(getD(), ReadWord(addr))); break; case 0xa4: //ANDA indexed addr = PostByte(); rA = oAND(rA, byteAt(addr)); break; case 0xa5: //BITA indexed addr = PostByte(); oAND(rA, byteAt(addr)); break; case 0xa6: //LDA indexed addr = PostByte(); rA = byteAt(addr); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rA]; break; case 0xa7: //STA indexed addr = PostByte(); byteTo(addr, rA); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rA]; break; case 0xa8: //EORA indexed addr = PostByte(); rA = oEOR(rA, byteAt(addr)); break; case 0xa9: //ADCA indexed addr = PostByte(); rA = oADC(rA, byteAt(addr)); break; case 0xaa: //ORA indexed addr = PostByte(); rA = oOR(rA, byteAt(addr)); break; case 0xab: //ADDA indexed addr = PostByte(); rA = oADD(rA, byteAt(addr)); break; case 0xac: //CMPX indexed addr = PostByte(); oCMP16(rX, ReadWord(addr)); break; case 0xad: //JSR indexed addr = PostByte(); PUSHW(PC); PC = addr; break; case 0xae: //LDX indexed addr = PostByte(); rX = ReadWord(addr); flagsNZ16(rX); CC &= ~F_OVERFLOW; break; case 0xaf: //STX indexed addr = PostByte(); WriteWord(addr, rX); flagsNZ16(rX); CC &= ~F_OVERFLOW; break; case 0xb0: //SUBA extended addr = fetch16(); rA = oSUB(rA, byteAt(addr)); break; case 0xb1: //CMPA extended addr = fetch16(); oCMP(rA, byteAt(addr)); break; case 0xb2: //SBCA extended addr = fetch16(); rA = oSBC(rA, byteAt(addr)); break; case 0xb3: //SUBD extended addr = fetch16(); setD(oSUB16(getD(), ReadWord(addr))); break; case 0xb4: //ANDA extended addr = fetch16(); rA = oAND(rA, byteAt(addr)); break; case 0xb5: //BITA extended addr = fetch16(); oAND(rA, byteAt(addr)); break; case 0xb6: //LDA extended addr = fetch16(); rA = byteAt(addr); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rA]; break; case 0xb7: //STA extended addr = fetch16(); byteTo(addr, rA); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rA]; break; case 0xb8: //EORA extended addr = fetch16(); rA = oEOR(rA, byteAt(addr)); break; case 0xb9: //ADCA extended addr = fetch16(); rA = oADC(rA, byteAt(addr)); break; case 0xba: //ORA extended addr = fetch16(); rA = oOR(rA, byteAt(addr)); break; case 0xbb: //ADDA extended addr = fetch16(); rA = oADD(rA, byteAt(addr)); break; case 0xbc: //CMPX extended addr = fetch16(); oCMP16(rX, ReadWord(addr)); break; case 0xbd: //JSR extended addr = fetch16(); PUSHW(PC); PC = addr; break; case 0xbe: //LDX extended addr = fetch16(); rX = ReadWord(addr); flagsNZ16(rX); CC &= ~F_OVERFLOW; break; case 0xbf: //STX extended addr = fetch16(); WriteWord(addr, rX); flagsNZ16(rX); CC &= ~F_OVERFLOW; break; //Regs B, Y case 0xc0: //SUBB imm rB = oSUB(rB, fetch()); break; case 0xc1: //CMPB imm oCMP(rB, fetch()); break; case 0xc2: //SBCB imm rB = oSBC(rB, fetch()); break; case 0xc3: //ADDD imm setD(oADD16(getD(), fetch16())); break; case 0xc4: //ANDB imm rB = oAND(rB, fetch()); break; case 0xc5: //BITB imm oAND(rB, fetch()); break; case 0xc6: //LDB imm rB = fetch(); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rB]; break; case 0xc8: //EORB imm rB = oEOR(rB, fetch()); break; case 0xc9: //ADCB imm rB = oADC(rB, fetch()); break; case 0xca: //ORB imm rB = oOR(rB, fetch()); break; case 0xcb: //ADDB imm rB = oADD(rB, fetch()); break; case 0xcc: //LDD imm addr = fetch16(); setD(addr); flagsNZ16(addr); CC &= ~F_OVERFLOW; break; case 0xce: //LDU imm rU = fetch16(); flagsNZ16(rU); CC &= ~F_OVERFLOW; break; case 0xd0: //SUBB direct addr = dpadd(); rB = oSUB(rB, byteAt(addr)); break; case 0xd1: //CMPB direct addr = dpadd(); oCMP(rB, byteAt(addr)); break; case 0xd2: //SBCB direct addr = dpadd(); rB = oSBC(rB, byteAt(addr)); break; case 0xd3: //ADDD direct addr = dpadd(); setD(oADD16(getD(), ReadWord(addr))); break; case 0xd4: //ANDB direct addr = dpadd(); rB = oAND(rB, byteAt(addr)); break; case 0xd5: //BITB direct addr = dpadd(); oAND(rB, byteAt(addr)); break; case 0xd6: //LDB direct addr = dpadd(); rB = byteAt(addr); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rB]; break; case 0xd7: //STB direct addr = dpadd(); byteTo(addr, rB); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rB]; break; case 0xd8: //EORB direct addr = dpadd(); rB = oEOR(rB, byteAt(addr)); break; case 0xd9: //ADCB direct addr = dpadd(); rB = oADC(rB, byteAt(addr)); break; case 0xda: //ORB direct addr = dpadd(); rB = oOR(rB, byteAt(addr)); break; case 0xdb: //ADDB direct addr = dpadd(); rB = oADD(rB, byteAt(addr)); break; case 0xdc: //LDD direct addr = dpadd(); pb = ReadWord(addr); setD(pb); flagsNZ16(pb); CC &= ~F_OVERFLOW; break; case 0xdd: //STD direct addr = dpadd(); WriteWord(addr, getD()); CC &= ~F_OVERFLOW; break; case 0xde: //LDU direct addr = dpadd(); rU = ReadWord(addr); flagsNZ16(rX); CC &= ~F_OVERFLOW; break; case 0xdf: //STU direct addr = dpadd(); WriteWord(addr, rU); flagsNZ16(rU); CC &= ~F_OVERFLOW; break; case 0xe0: //SUBB indexed addr = PostByte(); rB = oSUB(rB, byteAt(addr)); break; case 0xe1: //CMPB indexed addr = PostByte(); oCMP(rB, byteAt(addr)); break; case 0xe2: //SBCB indexed addr = PostByte(); rB = oSBC(rB, byteAt(addr)); break; case 0xe3: //ADDD indexed addr = PostByte(); setD(oADD16(getD(), ReadWord(addr))); break; case 0xe4: //ANDB indexed addr = PostByte(); rB = oAND(rB, byteAt(addr)); break; case 0xe5: //BITB indexed addr = PostByte(); oAND(rB, byteAt(addr)); break; case 0xe6: //LDB indexed addr = PostByte(); rB = byteAt(addr); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rB]; break; case 0xe7: //STB indexed addr = PostByte(); byteTo(addr, rB); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rB]; break; case 0xe8: //EORB indexed addr = PostByte(); rB = oEOR(rB, byteAt(addr)); break; case 0xe9: //ADCB indexed addr = PostByte(); rB = oADC(rB, byteAt(addr)); break; case 0xea: //ORB indexed addr = PostByte(); rB = oOR(rB, byteAt(addr)); break; case 0xeb: //ADDB indexed addr = PostByte(); rB = oADD(rB, byteAt(addr)); break; case 0xec: //LDD indexed addr = PostByte(); pb = ReadWord(addr); setD(pb); flagsNZ16(pb); CC &= ~F_OVERFLOW; break; case 0xed: //STD indexed addr = PostByte(); WriteWord(addr, getD()); CC &= ~F_OVERFLOW; break; case 0xee: //LDU indexed addr = PostByte(); rU = ReadWord(addr); flagsNZ16(rU); CC &= ~F_OVERFLOW; break; case 0xef: //STU indexed addr = PostByte(); WriteWord(addr, rU); flagsNZ16(rU); CC &= ~F_OVERFLOW; break; case 0xf0: //SUBB extended addr = fetch16(); rB = oSUB(rB, byteAt(addr)); break; case 0xf1: //CMPB extended addr = fetch16(); oCMP(rB, byteAt(addr)); break; case 0xf2: //SBCB extended addr = fetch16(); rB = oSBC(rB, byteAt(addr)); break; case 0xf3: //ADDD extended addr = fetch16(); setD(oADD16(getD(), ReadWord(addr))); break; case 0xf4: //ANDB extended addr = fetch16(); rB = oAND(rB, byteAt(addr)); break; case 0xf5: //BITB extended addr = fetch16(); oAND(rB, byteAt(addr)); break; case 0xf6: //LDB extended addr = fetch16(); rB = byteAt(addr); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rB]; break; case 0xf7: //STB extended addr = fetch16(); byteTo(addr, rB); CC &= ~(F_ZERO | F_NEGATIVE | F_OVERFLOW); CC |= flagsNZ[rB]; break; case 0xf8: //EORB extended addr = fetch16(); rB = oEOR(rB, byteAt(addr)); break; case 0xf9: //ADCB extended addr = fetch16(); rB = oADC(rB, byteAt(addr)); break; case 0xfa: //ORB extended addr = fetch16(); rB = oOR(rB, byteAt(addr)); break; case 0xfb: //ADDB extended addr = fetch16(); rB = oADD(rB, byteAt(addr)); break; case 0xfc: //LDD extended addr = fetch16(); pb = ReadWord(addr); setD(pb); flagsNZ16(pb); CC &= ~F_OVERFLOW; break; case 0xfd: //STD extended addr = fetch16(); WriteWord(addr, getD()); CC &= ~F_OVERFLOW; break; case 0xfe: //LDU extended addr = fetch16(); rU = ReadWord(addr); flagsNZ16(rU); CC &= ~F_OVERFLOW; break; case 0xff: //STU extended addr = fetch16(); WriteWord(addr, rU); flagsNZ16(rU); CC &= ~F_OVERFLOW; break; // page 1 case 0x10: //page 1 { opcode = fetch(); T += cycles2[opcode]; switch (opcode) { case 0x21: //BRN addr = signed16(fetch16()); break; case 0x22: //BHI addr = signed16(fetch16()); if (!(CC & (F_CARRY | F_ZERO))) PC += addr; break; case 0x23: //BLS addr = signed16(fetch16()); if (CC & (F_CARRY | F_ZERO)) PC += addr; break; case 0x24: //BCC addr = signed16(fetch16()); if (!(CC & F_CARRY)) PC += addr; break; case 0x25: //BCS addr = signed16(fetch16()); if (CC & F_CARRY) PC += addr; break; case 0x26: //BNE addr = signed16(fetch16()); if (!(CC & F_ZERO)) PC += addr; break; case 0x27: //BEQ addr = signed16(fetch16()); if (CC & F_ZERO) PC += addr; break; case 0x28: //BVC addr = signed16(fetch16()); if (!(CC & F_OVERFLOW)) PC += addr; break; case 0x29: //BVS addr = signed16(fetch16()); if (CC & F_OVERFLOW) PC += addr; break; case 0x2a: //BPL addr = signed16(fetch16()); if (!(CC & F_NEGATIVE)) PC += addr; break; case 0x2b: //BMI addr = signed16(fetch16()); if (CC & F_NEGATIVE) PC += addr; break; case 0x2c: //BGE addr = signed16(fetch16()); if (!((CC & F_NEGATIVE) ^ ((CC & F_OVERFLOW) << 2))) PC += addr; break; case 0x2d: //BLT addr = signed16(fetch16()); if ((CC & F_NEGATIVE) ^ ((CC & F_OVERFLOW) << 2)) PC += addr; break; case 0x2e: //BGT addr = signed16(fetch16()); //if (!((CC&F_NEGATIVE) ^ ((CC&F_OVERFLOW)<<2) || (CC&F_ZERO))) PC += addr; if ( !((CC & F_NEGATIVE) ^ ((CC & F_OVERFLOW) << 2) && CC & F_ZERO) ) PC += addr; break; case 0x2f: //BLE addr = signed16(fetch16()); if ((CC & F_NEGATIVE) ^ ((CC & F_OVERFLOW) << 2) || CC & F_ZERO) PC += addr; break; case 0x3f: //SWI2 CC |= F_ENTIRE; PUSHW(PC); PUSHW(rU); PUSHW(rY); PUSHW(rX); PUSHB(DP); PUSHB(rB); PUSHB(rA); PUSHB(CC); CC |= F_IRQMASK | F_FIRQMASK; PC = ReadWord(vecSWI2); break; case 0x83: //CMPD imm oCMP16(getD(), fetch16()); break; case 0x8c: //CMPY imm oCMP16(rY, fetch16()); break; case 0x8e: //LDY imm rY = fetch16(); flagsNZ16(rY); CC &= ~F_OVERFLOW; break; case 0x93: //CMPD direct addr = dpadd(); oCMP16(getD(), ReadWord(addr)); break; case 0x9c: //CMPY direct addr = dpadd(); oCMP16(rY, ReadWord(addr)); break; case 0x9e: //LDY direct addr = dpadd(); rY = ReadWord(addr); flagsNZ16(rY); CC &= ~F_OVERFLOW; break; case 0x9f: //STY direct addr = dpadd(); WriteWord(addr, rY); flagsNZ16(rY); CC &= ~F_OVERFLOW; break; case 0xa3: //CMPD indexed addr = PostByte(); oCMP16(getD(), ReadWord(addr)); break; case 0xac: //CMPY indexed addr = PostByte(); oCMP16(rY, ReadWord(addr)); break; case 0xae: //LDY indexed addr = PostByte(); rY = ReadWord(addr); flagsNZ16(rY); CC &= ~F_OVERFLOW; break; case 0xaf: //STY indexed addr = PostByte(); WriteWord(addr, rY); flagsNZ16(rY); CC &= ~F_OVERFLOW; break; case 0xb3: //CMPD extended addr = fetch16(); oCMP16(getD(), ReadWord(addr)); break; case 0xbc: //CMPY extended addr = fetch16(); oCMP16(rY, ReadWord(addr)); break; case 0xbe: //LDY extended addr = fetch16(); rY = ReadWord(addr); flagsNZ16(rY); CC &= ~F_OVERFLOW; break; case 0xbf: //STY extended addr = fetch16(); WriteWord(addr, rY); flagsNZ16(rY); CC &= ~F_OVERFLOW; break; case 0xce: //LDS imm rS = fetch16(); flagsNZ16(rS); CC &= ~F_OVERFLOW; break; case 0xde: //LDS direct addr = dpadd(); rS = ReadWord(addr); flagsNZ16(rS); CC &= ~F_OVERFLOW; break; case 0xdf: //STS direct addr = dpadd(); WriteWord(addr, rS); flagsNZ16(rS); CC &= ~F_OVERFLOW; break; case 0xee: //LDS indexed addr = PostByte(); rS = ReadWord(addr); flagsNZ16(rS); CC &= ~F_OVERFLOW; break; case 0xef: //STS indexed addr = PostByte(); WriteWord(addr, rS); flagsNZ16(rS); CC &= ~F_OVERFLOW; break; case 0xfe: //LDS extended addr = fetch16(); rS = ReadWord(addr); flagsNZ16(rS); CC &= ~F_OVERFLOW; break; case 0xff: //STS extended addr = fetch16(); WriteWord(addr, rS); flagsNZ16(rS); CC &= ~F_OVERFLOW; break; } } break; // page 2 case 0x11: //page 2 { opcode = fetch(); T += cycles2[opcode]; switch (opcode) { case 0x3f: //SWI3 CC |= F_ENTIRE; PUSHW(PC); PUSHW(rU); PUSHW(rY); PUSHW(rX); PUSHB(DP); PUSHB(rB); PUSHB(rA); PUSHB(CC); CC |= F_IRQMASK | F_FIRQMASK; PC = ReadWord(vecSWI3); break; case 0x83: //CMPU imm oCMP16(rU, fetch16()); break; case 0x8c: //CMPS imm oCMP16(rS, fetch16()); break; case 0x93: //CMPU imm addr = dpadd(); oCMP16(rU, ReadWord(addr)); break; case 0x9c: //CMPS imm addr = dpadd(); oCMP16(rS, ReadWord(addr)); break; case 0xa3: //CMPU imm addr = PostByte(); oCMP16(rU, ReadWord(addr)); break; case 0xac: //CMPS imm addr = PostByte(); oCMP16(rS, ReadWord(addr)); break; case 0xb3: //CMPU imm addr = fetch16(); oCMP16(rU, ReadWord(addr)); break; case 0xbc: //CMPS imm addr = fetch16(); oCMP16(rS, ReadWord(addr)); break; } } break; } rA &= 0xff; rB &= 0xff; CC &= 0xff; DP &= 0xff; rX &= 0xffff; rY &= 0xffff; rU &= 0xffff; rS &= 0xffff; PC &= 0xffff; return T - oldT; }; var reset = function () { rA = rA | 0x00; rB = rB | 0x00; rX = rX | 0x00; rY = rY | 0x00; rU = rU | 0x00; rS = rS | 0x00; PC = ReadWord(vecRESET); DP = 0; CC |= F_FIRQMASK | F_IRQMASK; T = 0; }; //---------- Disassembler /* ILLEGAL 0 DIRECT 1 INHERENT 2 BRANCH_REL_16 3 IMMEDIAT_8 4 BRANCH_REL_8 5 INDEXED 6 EXTENDED 7 IMMEDIAT_16 8 PSHS 10 PSHU 11 EXG, TFR 20 */ var ds = [ [2, 1, "NEG"], [1, 0, "???"], [1, 0, "???"], [2, 1, "COM"], [2, 1, "LSR"], [1, 0, "???"], [2, 1, "ROR"], [2, 1, "ASR"], [2, 1, "LSL"], [2, 1, "ROL"], [2, 1, "DEC"], [1, 0, "???"], [2, 1, "INC"], [2, 1, "TST"], [2, 1, "JMP"], [2, 1, "CLR"], [1, 0, "Prefix"], [1, 0, "Prefix"], [1, 2, "NOP"], [1, 2, "SYNC"], [1, 0, "???"], [1, 0, "???"], [3, 3, "LBRA"], [3, 3, "LBSR"], [1, 0, "???"], [1, 2, "DAA"], [2, 4, "ORCC"], [1, 0, "???"], [2, 4, "ANDCC"], [1, 2, "SEX"], [2, 20, "EXG"], [2, 20, "TFR"], [2, 5, "BRA"], [2, 5, "BRN"], [2, 5, "BHI"], [2, 5, "BLS"], [2, 5, "BCC"], [2, 5, "BCS"], [2, 5, "BNE"], [2, 5, "BEQ"], [2, 5, "BVC"], [2, 5, "BVS"], [2, 5, "BPL"], [2, 5, "BMI"], [2, 5, "BGE"], [2, 5, "BLT"], [2, 5, "BGT"], [2, 5, "BLE"], [2, 6, "LEAX"], [2, 6, "LEAY"], [2, 6, "LEAS"], [2, 6, "LEAU"], [2, 10, "PSHS"], [2, 10, "PULS"], [2, 11, "PSHU"], [2, 11, "PULU"], [1, 0, "???"], [1, 2, "RTS"], [1, 2, "ABX"], [1, 2, "RTI"], [2, 2, "CWAI"], [1, 2, "MUL"], [1, 2, "RESET"], [1, 2, "SWI1"], [1, 2, "NEGA"], [1, 0, "???"], [1, 0, "???"], [1, 2, "COMA"], [1, 2, "LSRA"], [1, 0, "???"], [1, 2, "RORA"], [1, 2, "ASRA"], [1, 2, "ASLA"], [1, 2, "ROLA"], [1, 2, "DECA"], [1, 0, "???"], [1, 2, "INCA"], [1, 2, "TSTA"], [1, 0, "???"], [1, 2, "CLRA"], [1, 2, "NEGB"], [1, 0, "???"], [1, 0, "???"], [1, 2, "COMB"], [1, 2, "LSRB"], [1, 0, "???"], [1, 2, "RORB"], [1, 2, "ASRB"], [1, 2, "ASLB"], [1, 2, "ROLB"], [1, 2, "DECB"], [1, 0, "???"], [1, 2, "INCB"], [1, 2, "TSTB"], [1, 0, "???"], [1, 2, "CLRB"], [2, 6, "NEG"], [1, 0, "???"], [1, 0, "???"], [2, 6, "COM"], [2, 6, "LSR"], [1, 0, "???"], [2, 6, "ROR"], [2, 6, "ASR"], [2, 6, "LSL"], [2, 6, "ROL"], [2, 6, "DEC"], [1, 0, "???"], [2, 6, "INC"], [2, 6, "TST"], [2, 6, "JMP"], [2, 6, "CLR"], [3, 7, "NEG"], [1, 0, "???"], [1, 0, "???"], [3, 7, "COM"], [3, 7, "LSR"], [1, 0, "???"], [3, 7, "ROR"], [3, 7, "ASR"], [3, 7, "LSL"], [3, 7, "ROL"], [3, 7, "DEC"], [1, 0, "???"], [3, 7, "INC"], [3, 7, "TST"], [3, 7, "JMP"], [3, 7, "CLR"], [2, 4, "SUBA"], [2, 4, "CMPA"], [2, 4, "SBCA"], [3, 8, "SUBD"], [2, 4, "ANDA"], [2, 4, "BITA"], [2, 4, "LDA"], [1, 0, "???"], [2, 4, "EORA"], [2, 4, "ADCA"], [2, 4, "ORA"], [2, 4, "ADDA"], [3, 8, "CMPX"], [2, 5, "BSR"], [3, 8, "LDX"], [1, 0, "???"], [2, 1, "SUBA"], [2, 1, "CMPA"], [2, 1, "SBCA"], [2, 1, "SUBd"], [2, 1, "ANDA"], [2, 1, "BITA"], [2, 1, "LDA"], [2, 1, "STA"], [2, 1, "EORA"], [2, 1, "ADCA"], [2, 1, "ORA"], [2, 1, "ADDA"], [2, 1, "CMPX"], [2, 1, "JSR"], [2, 1, "LDX"], [2, 1, "STX"], [2, 6, "SUBA"], [2, 6, "CMPA"], [2, 6, "SBCA"], [2, 6, "SUBD"], [2, 6, "ANDA"], [2, 6, "BITA"], [2, 6, "LDA"], [2, 6, "STA"], [2, 6, "EORA"], [2, 6, "ADCA"], [2, 6, "ORA"], [2, 6, "ADDA"], [2, 6, "CMPX"], [2, 6, "JSR"], [2, 6, "LDX"], [2, 6, "STX"], [3, 7, "SUBA"], [3, 7, "CMPA"], [3, 7, "SBCA"], [3, 7, "SUBD"], [3, 7, "ANDA"], [3, 7, "BITA"], [3, 7, "LDA"], [3, 7, "STA"], [3, 7, "EORA"], [3, 7, "ADCA"], [3, 7, "ORA"], [3, 7, "ADDA"], [3, 7, "CMPX"], [3, 7, "JSR"], [3, 7, "LDX"], [3, 7, "STX"], [2, 4, "SUBB"], [2, 4, "CMPB"], [2, 4, "SBCB"], [3, 8, "ADDD"], [2, 4, "ANDB"], [2, 4, "BITB"], [2, 4, "LDB"], [1, 0, "???"], [2, 4, "EORB"], [2, 4, "ADCB"], [2, 4, "ORB"], [2, 4, "ADDB"], [3, 8, "LDD"], [1, 0, "???"], [3, 8, "LDU"], [1, 0, "???"], [2, 1, "SUBB"], [2, 1, "CMPB"], [2, 1, "SBCB"], [2, 1, "ADDD"], [2, 1, "ANDB"], [2, 1, "BITB"], [2, 1, "LDB"], [2, 1, "STB"], [2, 1, "EORB"], [2, 1, "ADCB"], [2, 1, "ORB "], [2, 1, "ADDB"], [2, 1, "LDD "], [2, 1, "STD "], [2, 1, "LDU "], [2, 1, "STU "], [2, 6, "SUBB"], [2, 6, "CMPB"], [2, 6, "SBCB"], [2, 6, "ADDD"], [2, 6, "ANDB"], [2, 6, "BITB"], [2, 6, "LDB"], [2, 6, "STB"], [2, 6, "EORB"], [2, 6, "ADCB"], [2, 6, "ORB"], [2, 6, "ADDB"], [2, 6, "LDD"], [2, 6, "STD"], [2, 6, "LDU"], [2, 6, "STU"], [3, 7, "SUBB"], [3, 7, "CMPB"], [3, 7, "SBCB"], [3, 7, "ADDD"], [3, 7, "ANDB"], [3, 7, "BITB"], [3, 7, "LDB"], [3, 7, "STB"], [3, 7, "EORB"], [3, 7, "ADCB"], [3, 7, "ORB"], [3, 7, "ADDB"], [3, 7, "LDD"], [3, 7, "STD"], [3, 7, "LDU"], [3, 7, "STU"], ]; var ds11 = { 0x3f: [2, 2, "SWI3"], 0x83: [4, 8, "CMPU"], 0x8c: [4, 8, "CMPS"], 0x93: [3, 1, "CMPU"], 0x9c: [3, 1, "CMPS"], 0xa3: [3, 6, "CMPU"], 0xac: [3, 6, "CMPS"], 0xb3: [4, 7, "CMPU"], 0xbc: [4, 7, "CMPS"], }; var ds10 = { 0x21: [5, 3, "LBRN"], 0x22: [5, 3, "LBHI"], 0x23: [5, 3, "LBLS"], 0x24: [5, 3, "LBCC"], 0x25: [5, 3, "LBCS"], 0x26: [5, 3, "LBNE"], 0x27: [5, 3, "LBEQ"], 0x28: [5, 3, "LBVC"], 0x29: [5, 3, "LBVS"], 0x2a: [5, 3, "LBPL"], 0x2b: [5, 3, "LBMI"], 0x2c: [5, 3, "LBGE"], 0x2d: [5, 3, "LBLT"], 0x2e: [5, 3, "LBGT"], 0x2f: [5, 3, "LBLE"], 0x3f: [2, 2, "SWI2"], 0x83: [4, 8, "CMPD"], 0x8c: [4, 8, "CMPY"], 0x8e: [4, 8, "LDY"], 0x93: [3, 1, "CMPD"], 0x9c: [3, 1, "CMPY"], 0x9e: [3, 1, "LDY"], 0x9f: [3, 1, "STY"], 0xa3: [3, 6, "CMPD"], 0xac: [3, 6, "CMPY"], 0xae: [3, 6, "LDY"], 0xaf: [3, 6, "STY"], 0xb3: [4, 7, "CMPD"], 0xbc: [4, 7, "CMPY"], 0xbe: [4, 7, "LDY"], 0xbf: [4, 7, "STY"], 0xce: [4, 8, "LDS"], 0xde: [3, 1, "LDS"], 0xdf: [3, 1, "STS"], 0xee: [3, 6, "LDS"], 0xef: [3, 6, "STS"], 0xfe: [4, 7, "LDS"], 0xff: [4, 7, "STS"], }; /* ILLEGAL 0 DIRECT 1 INHERENT 2 BRANCH_REL_16 3 IMMEDIAT_8 4 BRANCH_REL_8 5 INDEXED 6 EXTENDED 7 IMMEDIAT_16 8 */ var disasm = function (i, a, b, c, d, pc) { var toHexN = function (n, d) { var s = n.toString(16); while (s.length < d) { s = "0" + s; } return s.toUpperCase(); }; var toHex2 = function (n) { return toHexN(n & 0xff, 2); }; var toHex4 = function (n) { return toHexN(n, 4); }; var rx, ro, j; var sx = ds[i]; if (i === 0x10) { sx = ds10[a]; if (sx === undefined) { return ["???", 2]; } i = a; a = b; b = c; c = d; } if (i === 0x11) { sx = ds11[a]; if (sx === undefined) { return ["???", 2]; } i = a; a = b; b = c; c = d; } var bytes = sx[0]; var mode = sx[1]; var mnemo = sx[2]; switch (mode) { case 0: //invalid break; case 1: //direct page mnemo += " $" + toHex2(a); break; case 2: // inherent break; case 3: //brel16 mnemo += " #$" + toHex4( a * 256 + b < 32768 ? a * 256 + b + pc : a * 256 + b + pc - 65536 ); break; case 4: //imm8 mnemo += " #$" + toHex2(a); break; case 5: //brel8 mnemo += " #$" + toHex4(a < 128 ? a + pc + 2 : a + pc - 254); break; case 6: //indexed, postbyte etc. mnemo += " "; var pb = a; var ixr = ["X", "Y", "U", "S"][(pb & 0x60) >> 5]; if (!(pb & 0x80)) { //direct5 var disp = pb & 0x1f; if (disp > 15) disp = disp - 32; mnemo += disp + "," + ixr; break; } var ind = pb & 0x10; var mod = pb & 0x0f; var ofs8 = b > 127 ? b - 256 : b; var ofs16 = b * 256 + c > 32767 ? b * 256 + c - 65536 : b * 256 + c; if (!ind) { switch (mod) { case 0: mnemo += "," + ixr + "+"; break; case 1: mnemo += "," + ixr + "++"; break; case 2: mnemo += ",-" + ixr; break; case 3: mnemo += ",--" + ixr; break; case 4: mnemo += "," + ixr; break; case 5: mnemo += "B," + ixr; break; case 6: mnemo += "A," + ixr; break; case 7: mnemo += "???"; break; case 8: mnemo += ofs8 + "," + ixr; bytes++; break; case 9: mnemo += ofs16 + "," + ixr; bytes += 2; break; case 10: mnemo += "???"; break; case 11: mnemo += "D," + ixr; break; case 12: mnemo += ofs8 + ",PC"; bytes++; break; case 13: mnemo += ofs16 + ",PC"; bytes += 2; break; case 14: mnemo += "???"; break; case 15: mnemo += "$" + toHex4(b * 256 + c); bytes += 2; break; } } else { switch (mod) { case 0: mnemo += "???"; break; case 1: mnemo += "[," + ixr + "++]"; break; case 2: mnemo += "???"; break; case 3: mnemo += "[,--" + ixr + "]"; break; case 4: mnemo += "[," + ixr + "]"; break; case 5: mnemo += "[B," + ixr + "]"; break; case 6: mnemo += "[A," + ixr + "]"; break; case 7: mnemo += "???"; break; case 8: mnemo += "[" + ofs8 + "," + ixr + "]"; bytes++; break; case 9: mnemo += "[" + ofs16 + "," + ixr + "]"; bytes += 2; break; case 10: mnemo += "???"; break; case 11: mnemo += "[D," + ixr + "]"; break; case 12: mnemo += "[" + ofs8 + ",PC]"; bytes++; break; case 13: mnemo += "[" + ofs16 + ",PC]"; bytes += 2; break; case 14: mnemo += "???"; break; case 15: mnemo += "[$" + toHex4(b * 256 + c) + "]"; bytes += 2; break; } } break; case 7: //extended mnemo += " $" + toHex4(a * 256 + b); break; case 8: //imm16 mnemo += " #$" + toHex4(a * 256 + b); break; case 10: //pshs, puls rx = ["PC", "U", "Y", "X", "DP", "B", "A", "CC"]; ro = []; for (j = 0; j < 8; j++) { if ((a & 1) !== 0) { ro.push(rx[7 - j]); } a >>= 1; } mnemo += " " + ro.join(","); break; case 11: //pshs, puls rx = ["PC", "S", "Y", "X", "DP", "B", "A", "CC"]; ro = []; for (j = 0; j < 8; j++) { if ((a & 1) !== 0) { ro.push(rx[7 - j]); } a >>= 1; } mnemo += " " + ro.join(","); break; case 20: //TFR etc rx = [ "D", "X", "Y", "U", "S", "PC", "?", "?", "A", "B", "CC", "DP", "?", "?", "?", "?", ]; mnemo += " " + rx[a >> 4] + "," + rx[a & 0x0f]; break; } return [mnemo, bytes]; }; //---------- Exports return { steps: function (Ts) { //T=0; while (Ts > 0) { Ts -= step(); } }, T: function () { return T; }, memr: function (addr) { return byteAt(addr); }, reset: reset, init: function (bt, ba, tck) { byteTo = bt; byteAt = ba; ticks = tck; reset(); }, status: function () { return { pc: PC, sp: rS, u: rU, a: rA, b: rB, x: rX, y: rY, dp: DP, flags: CC, }; }, interrupt: function () { /* if (flags & fINT) { return; } //flags |= fBKC; stPushWord(pc); stPush(flags); flags |= fINT; pc=wordAt(IrqTo); T+=7; //console.log(pc); */ }, nmi: function () { /* return; stPushWord(pc); stPush(flags); flags |= fINT; pc=wordAt(NMITo); T+=7; //console.log(pc); */ }, set: function (reg, value) { switch (reg.toUpperCase()) { case "PC": PC = value; return; case "A": rA = value; return; case "B": rB = value; return; case "X": rX = value; return; case "Y": rY = value; return; case "SP": rS = value; return; case "U": rU = value; return; case "FLAGS": CC = value; return; } }, flagsToString: function () { var f = "", fx = "EFHINZVC"; for (var i = 0; i < 8; i++) { var n = CC & (0x80 >> i); if (n === 0) { f += fx[i].toLowerCase(); } else { f += fx[i]; } } return f; }, disasm: disasm, }; });