// Generated by CoffeeScript 1.9.3 /* Z80 core. To avoid mass repetition of code across the numerous instruction variants the code for this component is built up programmatically and evaluated in the global scope. CoffeeScript is used here for its support of multi-line strings, and expression interpolation in strings. */ /* Registers are stored in a typed array as a way of automatically casting calculations to 8/16 bit, and to allow accessing them interchangeably as register pairs or individual registers by having two arrays backed by the same buffer. For the latter to work, we need to find out the endianness of the host processor, as typed arrays are native-endian (http://lists.w3.org/Archives/Public/public-script-coord/2010AprJun/0048.html, http://cat-in-136.blogspot.com/2011/03/javascript-typed-array-use-native.html) */ (function() { window.buildZ80 = function(opts) { var ADC_A, ADC_HL_RR, ADD_A, ADD_RR_RR, AND_A, BIT_N_R, BIT_N_iHLi, BIT_N_iRRpNNi, CALL_C_NN, CALL_NN, CCF, CPD, CPDR, CPI, CPIR, CPIR_CPDR, CPI_CPD, CPL, CP_A, DAA, DEC, DEC_RR, DI, DJNZ_N, EI, EXX, EX_RR_RR, EX_iSPi_RR, FLAG_3, FLAG_5, FLAG_C, FLAG_H, FLAG_N, FLAG_P, FLAG_S, FLAG_V, FLAG_Z, HALT, IM, INC, INC_RR, IND, INDR, INI, INIR, INIR_INDR, INI_IND, IN_A_N, IN_F_iCi, IN_R_iCi, JP_C_NN, JP_NN, JP_RR, JR_C_N, JR_N, LDBITOP, LDD, LDDR, LDI, LDIR, LDIR_LDDR, LDI_LDD, LDSHIFTOP, LD_A_iNNi, LD_RR_NN, LD_RR_RR, LD_RR_iNNi, LD_R_N, LD_R_R, LD_R_iRRi, LD_R_iRRpNNi, LD_iNNi_A, LD_iNNi_RR, LD_iRRi_N, LD_iRRi_R, LD_iRRpNNi_N, LD_iRRpNNi_R, NEG, NOP, OPCODE_RUN_STRINGS, OPCODE_RUN_STRINGS_CB, OPCODE_RUN_STRINGS_DD, OPCODE_RUN_STRINGS_DDCB, OPCODE_RUN_STRINGS_ED, OPCODE_RUN_STRINGS_FD, OPCODE_RUN_STRINGS_FDCB, OR_A, OTDR, OTIR, OTIR_OTDR, OUTD, OUTI, OUTI_OUTD, OUT_iCi_0, OUT_iCi_R, OUT_iNi_A, POP_RR, PUSH_RR, RES, RET, RETN, RET_C, RL, RLA, RLC, RLCA, RLD, RR, RRA, RRC, RRCA, RRD, RST, SBC_A, SBC_HL_RR, SCF, SET, SHIFT, SLA, SLL, SRA, SRL, SUB_A, XOR_A, defineZ80JS, endianTestBuffer, endianTestUint16, endianTestUint8, generateddfdOpcodeSet, generateddfdcbOpcodeSet, getParamBoilerplate, indirectEval, isBigEndian, opcodeSwitch, rA, rA_, rB, rB_, rC, rC_, rD, rD_, rE, rE_, rF, rF_, rH, rH_, rI, rIXH, rIXL, rIYH, rIYL, rL, rL_, rR, registerIndexes, registerPairIndexes, rpAF, rpAF_, rpBC, rpBC_, rpDE, rpDE_, rpHL, rpHL_, rpIR, rpIX, rpIY, rpPC, rpSP, setUpStateJS; if (opts == null) { opts = {}; } endianTestBuffer = new ArrayBuffer(2); endianTestUint16 = new Uint16Array(endianTestBuffer); endianTestUint8 = new Uint8Array(endianTestBuffer); endianTestUint16[0] = 0x0100; isBigEndian = endianTestUint8[0] === 0x01; rpAF = 0; rpBC = 1; rpDE = 2; rpHL = 3; rpAF_ = 4; rpBC_ = 5; rpDE_ = 6; rpHL_ = 7; rpIX = 8; rpIY = 9; rpIR = 10; rpSP = 11; rpPC = 12; registerPairIndexes = { 'IX': 8, 'IY': 9 }; if (isBigEndian) { rA = 0; rF = 1; rB = 2; rC = 3; rD = 4; rE = 5; rH = 6; rL = 7; rA_ = 8; rF_ = 9; rB_ = 10; rC_ = 11; rD_ = 12; rE_ = 13; rH_ = 14; rL_ = 15; rIXH = 16; rIXL = 17; rIYH = 18; rIYL = 19; rI = 20; rR = 21; registerIndexes = { A: 0, F: 1, B: 2, C: 3, D: 4, E: 5, H: 6, L: 7, IXH: 16, IXL: 17, IYH: 18, IYL: 19 }; } else { rF = 0; rA = 1; rC = 2; rB = 3; rE = 4; rD = 5; rL = 6; rH = 7; rF_ = 8; rA_ = 9; rC_ = 10; rB_ = 11; rE_ = 12; rD_ = 13; rL_ = 14; rH_ = 15; rIXL = 16; rIXH = 17; rIYL = 18; rIYH = 19; rR = 20; rI = 21; registerIndexes = { F: 0, A: 1, C: 2, B: 3, E: 4, D: 5, L: 6, H: 7, IXL: 16, IXH: 17, IYL: 18, IYH: 19 }; } FLAG_C = 0x01; FLAG_N = 0x02; FLAG_P = 0x04; FLAG_V = 0x04; FLAG_3 = 0x08; FLAG_H = 0x10; FLAG_5 = 0x20; FLAG_Z = 0x40; FLAG_S = 0x80; setUpStateJS = "var memory = opts.memory;\nvar ioBus = opts.ioBus;\nvar display = opts.display;\n\nvar registerBuffer = new ArrayBuffer(26);\n/* Expose registerBuffer as both register pairs and individual registers */\nvar regPairs = new Uint16Array(registerBuffer);\nvar regs = new Uint8Array(registerBuffer);\n\nvar tstates = 0; /* number of tstates since start of this frame */\nvar iff1 = 0;\nvar iff2 = 0;\nvar im = 0;\nvar halted = false;\n\n/* tables for setting Z80 flags */\n\n/*\n Whether a half carry occurred or not can be determined by looking at\n the 3rd bit of the two arguments and the result; these are hashed\n into this table in the form r12, where r is the 3rd bit of the\n result, 1 is the 3rd bit of the 1st argument and 2 is the\n third bit of the 2nd argument; the tables differ for add and subtract\n operations\n*/\nvar halfcarryAddTable = new Uint8Array([0, " + FLAG_H + ", " + FLAG_H + ", " + FLAG_H + ", 0, 0, 0, " + FLAG_H + "]);\nvar halfcarrySubTable = new Uint8Array([0, 0, " + FLAG_H + ", 0, " + FLAG_H + ", 0, " + FLAG_H + ", " + FLAG_H + "]);\n\n/*\n Similarly, overflow can be determined by looking at the 7th bits; again\n the hash into this table is r12\n*/\nvar overflowAddTable = new Uint8Array([0, 0, 0, " + FLAG_V + ", " + FLAG_V + ", 0, 0, 0]);\nvar overflowSubTable = new Uint8Array([0, " + FLAG_V + ", 0, 0, 0, 0, " + FLAG_V + ", 0]);\n\nvar sz53Table = new Uint8Array(0x100); /* The S, Z, 5 and 3 bits of the index */\nvar parityTable = new Uint8Array(0x100); /* The parity of the lookup value */\nvar sz53pTable = new Uint8Array(0x100); /* OR the above two tables together */\n\nfor (var i = 0; i < 0x100; i++) {\n sz53Table[i] = i & ( " + (FLAG_3 | FLAG_5 | FLAG_S) + " );\n var j = i;\n var parity = 0;\n for (var k = 0; k < 8; k++) {\n parity ^= j & 1;\n j >>=1;\n }\n\n parityTable[i] = (parity ? 0 : " + FLAG_P + ");\n sz53pTable[i] = sz53Table[i] | parityTable[i];\n\n sz53Table[0] |= " + FLAG_Z + ";\n sz53pTable[0] |= " + FLAG_Z + ";\n}\n\nvar interruptible = true;\nvar interruptPending = false;\nvar interruptDataBus = 0;\nvar opcodePrefix = '';"; /* Boilerplate generator: a helper to deal with classes of opcodes which perform the same task on different types of operands: e.g. XOR B, XOR (HL), XOR nn, XOR (IX+nn). This function accepts the parameter in question, and returns a set of canned strings for use in the opcode runner body: 'getter': a block of code that performs any necessary memory access etc in order to make 'v' a valid expression; 'v': an expression with no side effects, evaluating to the operand's value. (Must also be a valid lvalue for assignment) 'trunc': an expression such as '& 0xff' to truncate v back to its proper range, if appropriate 'setter': a block of code that writes an updated value back to its proper location, if any Passing hasIXOffsetAlready = true indicates that we have already read the offset value of (IX+nn)/(IY+nn) into a variable 'offset' (necessary because DDCB/FFCB instructions put this before the final opcode byte). */ getParamBoilerplate = function(param, hasIXOffsetAlready) { var getter, match, regNum, rp; if (hasIXOffsetAlready == null) { hasIXOffsetAlready = false; } if (param.match(/^[AFBCDEHL]|I[XY][HL]$/)) { regNum = registerIndexes[param]; return { 'getter': '', 'v': "regs[" + regNum + "]", 'trunc': '', 'setter': '' }; } else if (param === '(HL)') { return { 'getter': "var val = READMEM(regPairs[" + rpHL + "]);", 'v': 'val', 'trunc': '& 0xff', 'setter': "CONTEND_READ_NO_MREQ(regPairs[" + rpHL + "], 1);\nWRITEMEM(regPairs[" + rpHL + "], val);" }; } else if (param === 'nn') { return { 'getter': "var val = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;", 'v': 'val', 'trunc': '& 0xff', 'setter': '' }; } else if ((match = param.match(/^\((I[XY])\+nn\)$/))) { rp = registerPairIndexes[match[1]]; if (hasIXOffsetAlready) { getter = ''; } else { getter = "var offset = READMEM(regPairs[" + rpPC + "]);\nif (offset & 0x80) offset -= 0x100;\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nregPairs[" + rpPC + "]++;"; } getter += "var addr = (regPairs[" + rp + "] + offset) & 0xffff;\nvar val = READMEM(addr);"; return { 'getter': getter, 'v': 'val', 'trunc': '& 0xff', 'setter': "CONTEND_READ_NO_MREQ(addr, 1);\nWRITEMEM(addr, val);" }; } else if (param === 'add') { return { 'getter': '', 'v': 'add', 'trunc': '', 'setter': '' }; } else { throw "Unknown param format: " + param; } }; /* Opcode generator functions: each returns a string of Javascript that performs the opcode when executed within this module's scope. Note that instructions with DDCBnn opcodes also require an 'offset' variable to be defined as nn (as a signed byte). */ ADC_A = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\n\nvar adctemp = regs[" + rA + "] + " + operand.v + " + (regs[" + rF + "] & " + FLAG_C + ");\nvar lookup = ( (regs[" + rA + "] & 0x88) >> 3 ) | ( (" + operand.v + " & 0x88) >> 2 ) | ( (adctemp & 0x88) >> 1 );\nregs[" + rA + "] = adctemp;\nregs[" + rF + "] = ( adctemp & 0x100 ? " + FLAG_C + " : 0 ) | halfcarryAddTable[lookup & 0x07] | overflowAddTable[lookup >> 4] | sz53Table[regs[" + rA + "]];"; }; ADC_HL_RR = function(rp2) { return "var add16temp = regPairs[" + rpHL + "] + regPairs[" + rp2 + "] + (regs[" + rF + "] & " + FLAG_C + ");\nvar lookup = (\n ( (regPairs[" + rpHL + "] & 0x8800) >> 11 ) |\n ( (regPairs[" + rp2 + "] & 0x8800) >> 10 ) |\n ( (add16temp & 0x8800) >> 9 )\n);\nregPairs[" + rpHL + "] = add16temp;\nregs[" + rF + "] = (\n (add16temp & 0x10000 ? " + FLAG_C + " : 0) |\n overflowAddTable[lookup >> 4] |\n (regs[" + rH + "] & " + (FLAG_3 | FLAG_5 | FLAG_S) + ") |\n halfcarryAddTable[lookup & 0x07] |\n (regPairs[" + rpHL + "] ? 0 : " + FLAG_Z + ")\n);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);"; }; ADD_A = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\n\nvar addtemp = regs[" + rA + "] + " + operand.v + ";\nvar lookup = ( (regs[" + rA + "] & 0x88) >> 3 ) | ( (" + operand.v + " & 0x88) >> 2 ) | ( (addtemp & 0x88) >> 1 );\nregs[" + rA + "] = addtemp;\nregs[" + rF + "] = ( addtemp & 0x100 ? " + FLAG_C + " : 0 ) | halfcarryAddTable[lookup & 0x07] | overflowAddTable[lookup >> 4] | sz53Table[regs[" + rA + "]];"; }; ADD_RR_RR = function(rp1, rp2) { return "var add16temp = regPairs[" + rp1 + "] + regPairs[" + rp2 + "];\nvar lookup = ( (regPairs[" + rp1 + "] & 0x0800) >> 11 ) | ( (regPairs[" + rp2 + "] & 0x0800) >> 10 ) | ( (add16temp & 0x0800) >> 9 );\nregPairs[" + rp1 + "] = add16temp;\nregs[" + rF + "] = ( regs[" + rF + "] & ( " + (FLAG_V | FLAG_Z | FLAG_S) + " ) ) | ( add16temp & 0x10000 ? " + FLAG_C + " : 0 ) | ( ( add16temp >> 8 ) & ( " + (FLAG_3 | FLAG_5) + " ) ) | halfcarryAddTable[lookup];\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);"; }; AND_A = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\n\nregs[" + rA + "] &= " + operand.v + ";\nregs[" + rF + "] = " + FLAG_H + " | sz53pTable[regs[" + rA + "]];"; }; BIT_N_iRRpNNi = function(bit, rp) { var updateSignFlag; if (bit === 7) { updateSignFlag = "if (value & 0x80) regs[" + rF + "] |= " + FLAG_S + ";"; } else { updateSignFlag = ""; } return "var addr = (regPairs[" + rp + "] + offset) & 0xffff;\nvar value = READMEM(addr);\nregs[" + rF + "] = ( regs[" + rF + "] & " + FLAG_C + " ) | " + FLAG_H + " | ( ( addr >> 8 ) & " + (FLAG_3 | FLAG_5) + " );\nif ( !(value & " + (0x01 << bit) + ") ) regs[" + rF + "] |= " + (FLAG_P | FLAG_Z) + ";\n" + updateSignFlag + "\nCONTEND_READ_NO_MREQ(addr, 1);"; }; BIT_N_iHLi = function(bit) { var updateSignFlag; if (bit === 7) { updateSignFlag = "if (value & 0x80) regs[" + rF + "] |= " + FLAG_S + ";"; } else { updateSignFlag = ""; } return "var addr = regPairs[" + rpHL + "];\nvar value = READMEM(addr);\nCONTEND_READ_NO_MREQ(addr, 1);\nregs[" + rF + "] = ( regs[" + rF + "] & " + FLAG_C + " ) | " + FLAG_H + " | ( value & " + (FLAG_3 | FLAG_5) + " );\nif( !(value & " + (0x01 << bit) + ") ) regs[" + rF + "] |= " + (FLAG_P | FLAG_Z) + ";\n" + updateSignFlag; }; BIT_N_R = function(bit, r) { var updateSignFlag; if (bit === 7) { updateSignFlag = "if (regs[" + r + "] & 0x80) regs[" + rF + "] |= " + FLAG_S + ";"; } else { updateSignFlag = ""; } return "regs[" + rF + "] = ( regs[" + rF + "] & " + FLAG_C + " ) | " + FLAG_H + " | ( regs[" + r + "] & " + (FLAG_3 | FLAG_5) + " );\nif( !(regs[" + r + "] & " + (0x01 << bit) + ") ) regs[" + rF + "] |= " + (FLAG_P | FLAG_Z) + ";\n" + updateSignFlag; }; CALL_C_NN = function(flag, sense) { var condition; condition = "regs[" + rF + "] & " + flag; if (!sense) { condition = "!(" + condition + ")"; } return "if (" + condition + ") {\n var l = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n var h = READMEM(regPairs[" + rpPC + "]);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n regPairs[" + rpPC + "]++;\n regPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rpPC + "] >> 8);\n regPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rpPC + "] & 0xff);\n regPairs[" + rpPC + "] = (h<<8) | l;\n} else {\n CONTEND_READ(regPairs[" + rpPC + "], 3);\n regPairs[" + rpPC + "]++;\n CONTEND_READ(regPairs[" + rpPC + "], 3);\n regPairs[" + rpPC + "]++;\n}"; }; CALL_NN = function() { return "var l = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar h = READMEM(regPairs[" + rpPC + "]);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nregPairs[" + rpPC + "]++;\nregPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rpPC + "] >> 8);\nregPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rpPC + "] & 0xff);\nregPairs[" + rpPC + "] = (h<<8) | l;"; }; CCF = function() { return "regs[" + rF + "] = ( regs[" + rF + "] & " + (FLAG_P | FLAG_Z | FLAG_S) + " ) | ( (regs[" + rF + "] & " + FLAG_C + ") ? " + FLAG_H + " : " + FLAG_C + " ) | ( regs[" + rA + "] & " + (FLAG_3 | FLAG_5) + " );"; }; CP_A = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\n\nvar cptemp = regs[" + rA + "] - " + operand.v + ";\nvar lookup = ( (regs[" + rA + "] & 0x88) >> 3 ) | ( (" + operand.v + " & 0x88) >> 2 ) | ( (cptemp & 0x88) >> 1 );\nregs[" + rF + "] = ( cptemp & 0x100 ? " + FLAG_C + " : ( cptemp ? 0 : " + FLAG_Z + " ) ) | " + FLAG_N + " | halfcarrySubTable[lookup & 0x07] | overflowSubTable[lookup >> 4] | ( " + operand.v + " & " + (FLAG_3 | FLAG_5) + " ) | ( cptemp & " + FLAG_S + " );"; }; CPI_CPD = function(modifier) { return "var value = READMEM(regPairs[" + rpHL + "]);\nvar bytetemp = (regs[" + rA + "] - value) & 0xff;\nvar lookup = ((regs[" + rA + "] & 0x08) >> 3) | ((value & 0x08) >> 2) | ((bytetemp & 0x08) >> 1);\nvar originalHL = regPairs[" + rpHL + "];\nCONTEND_READ_NO_MREQ(originalHL, 1);\nCONTEND_READ_NO_MREQ(originalHL, 1);\nCONTEND_READ_NO_MREQ(originalHL, 1);\nCONTEND_READ_NO_MREQ(originalHL, 1);\nCONTEND_READ_NO_MREQ(originalHL, 1);\nregPairs[" + rpHL + "]" + modifier + "; regPairs[" + rpBC + "]--;\nregs[" + rF + "] = (regs[" + rF + "] & " + FLAG_C + ") | (regPairs[" + rpBC + "] ? " + (FLAG_V | FLAG_N) + " : " + FLAG_N + ") | halfcarrySubTable[lookup] | (bytetemp ? 0 : " + FLAG_Z + ") | (bytetemp & " + FLAG_S + ");\nif (regs[" + rF + "] & " + FLAG_H + ") bytetemp--;\nregs[" + rF + "] |= (bytetemp & " + FLAG_3 + ") | ( (bytetemp & 0x02) ? " + FLAG_5 + " : 0 );"; }; CPIR_CPDR = function(modifier) { return (CPI_CPD(modifier)) + "\nif ((regs[" + rF + "] & " + (FLAG_V | FLAG_Z) + ") == " + FLAG_V + ") {\n regPairs[" + rpPC + "] -= 2;\n CONTEND_READ_NO_MREQ(originalHL, 1);\n CONTEND_READ_NO_MREQ(originalHL, 1);\n CONTEND_READ_NO_MREQ(originalHL, 1);\n CONTEND_READ_NO_MREQ(originalHL, 1);\n CONTEND_READ_NO_MREQ(originalHL, 1);\n}"; }; CPD = function() { return CPI_CPD('--'); }; CPI = function() { return CPI_CPD('++'); }; CPDR = function() { return CPIR_CPDR('--'); }; CPIR = function() { return CPIR_CPDR('++'); }; DAA = function() { var addClause, subClause; subClause = SUB_A('add'); addClause = ADD_A('add'); return "var add = 0;\nvar carry = regs[" + rF + "] & " + FLAG_C + ";\nif( ( regs[" + rF + "] & " + FLAG_H + " ) || ( ( regs[" + rA + "] & 0x0f ) > 9 ) ) add = 6;\nif( carry || ( regs[" + rA + "] > 0x99 ) ) add |= 0x60;\nif( regs[" + rA + "] > 0x99 ) carry = " + FLAG_C + ";\nif( regs[" + rF + "] & " + FLAG_N + " ) {\n " + subClause + "\n} else {\n " + addClause + "\n}\nregs[" + rF + "] = ( regs[" + rF + "] & " + (~(FLAG_C | FLAG_P)) + " ) | carry | parityTable[regs[" + rA + "]];"; }; CPL = function() { return "regs[" + rA + "] ^= 0xff;\nregs[" + rF + "] = (regs[" + rF + "] & " + (FLAG_C | FLAG_P | FLAG_Z | FLAG_S) + ") | (regs[" + rA + "] & " + (FLAG_3 | FLAG_5) + ") | " + (FLAG_N | FLAG_H) + ";"; }; DEC = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\n\nregs[" + rF + "] = (regs[" + rF + "] & " + FLAG_C + " ) | ( " + operand.v + " & 0x0f ? 0 : " + FLAG_H + " ) | " + FLAG_N + ";\n" + operand.v + " = (" + operand.v + " - 1) " + operand.trunc + ";\n\n" + operand.setter + "\nregs[" + rF + "] |= (" + operand.v + " == 0x7f ? " + FLAG_V + " : 0) | sz53Table[" + operand.v + "];"; }; DEC_RR = function(rp) { return "regPairs[" + rp + "]--;\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);"; }; DI = function() { return "iff1 = iff2 = 0;"; }; DJNZ_N = function() { return "CONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nregs[" + rB + "]--;\nif (regs[" + rB + "]) {\n /* take branch */\n var offset = READMEM(regPairs[" + rpPC + "]);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n regPairs[" + rpPC + "]++;\n regPairs[" + rpPC + "] += (offset & 0x80 ? offset - 0x100 : offset);\n} else {\n /* do not take branch */\n CONTEND_READ(regPairs[" + rpPC + "], 3);\n regPairs[" + rpPC + "]++;\n}"; }; EI = function() { return "iff1 = iff2 = 1;\ninterruptible = false;"; }; EX_iSPi_RR = function(rp) { return "var l = READMEM(regPairs[" + rpSP + "]);\nvar spPlus1 = (regPairs[" + rpSP + "] + 1) & 0xffff;\nvar h = READMEM(spPlus1);\nCONTEND_READ_NO_MREQ(spPlus1, 1);\nWRITEMEM(spPlus1, regPairs[" + rp + "] >> 8);\nWRITEMEM(regPairs[" + rpSP + "], regPairs[" + rp + "] & 0xff);\nregPairs[" + rp + "] = (h<<8) | l;\nCONTEND_WRITE_NO_MREQ(regPairs[" + rpSP + "], 1);\nCONTEND_WRITE_NO_MREQ(regPairs[" + rpSP + "], 1);"; }; EX_RR_RR = function(rp1, rp2) { return "var temp = regPairs[" + rp1 + "];\nregPairs[" + rp1 + "] = regPairs[" + rp2 + "];\nregPairs[" + rp2 + "] = temp;"; }; EXX = function() { return "var wordtemp;\nwordtemp = regPairs[" + rpBC + "]; regPairs[" + rpBC + "] = regPairs[" + rpBC_ + "]; regPairs[" + rpBC_ + "] = wordtemp;\nwordtemp = regPairs[" + rpDE + "]; regPairs[" + rpDE + "] = regPairs[" + rpDE_ + "]; regPairs[" + rpDE_ + "] = wordtemp;\nwordtemp = regPairs[" + rpHL + "]; regPairs[" + rpHL + "] = regPairs[" + rpHL_ + "]; regPairs[" + rpHL_ + "] = wordtemp;"; }; HALT = function() { return "halted = true;\nregPairs[" + rpPC + "]--;"; }; IM = function(val) { return "im = " + val + ";"; }; IN_A_N = function() { return "var val = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar port = (regs[" + rA + "] << 8) | val;\nCONTEND_PORT_EARLY(port);\nregs[" + rA + "] = ioBus.read(port);\nCONTEND_PORT_LATE(port);"; }; IN_F_iCi = function() { return "var port = regPairs[" + rpBC + "];\nCONTEND_PORT_EARLY(port);\nvar result = ioBus.read(port);\nCONTEND_PORT_LATE(port);\nregs[" + rF + "] = (regs[" + rF + "] & " + FLAG_C + ") | sz53pTable[result];"; }; IN_R_iCi = function(r) { return "var port = regPairs[" + rpBC + "];\nCONTEND_PORT_EARLY(port);\nregs[" + r + "] = ioBus.read(port);\nCONTEND_PORT_LATE(port);\nregs[" + rF + "] = (regs[" + rF + "] & " + FLAG_C + ") | sz53pTable[regs[" + r + "]];"; }; INC = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\n\nregs[" + rF + "] = (regs[" + rF + "] & " + FLAG_C + ") | (" + operand.v + " & 0x0f ? 0 : " + FLAG_H + ") | " + FLAG_N + ";\n" + operand.v + " = (" + operand.v + " + 1) " + operand.trunc + ";\n\n" + operand.setter + "\nregs[" + rF + "] = (regs[" + rF + "] & " + FLAG_C + ") | ( " + operand.v + " == 0x80 ? " + FLAG_V + " : 0 ) | ( " + operand.v + " & 0x0f ? 0 : " + FLAG_H + " ) | sz53Table[" + operand.v + "];"; }; INC_RR = function(rp) { return "regPairs[" + rp + "]++;\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);"; }; INI_IND = function(modifier) { return "CONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_PORT_EARLY(regPairs[" + rpBC + "]);\nvar initemp = ioBus.read(regPairs[" + rpBC + "]);\nCONTEND_PORT_LATE(regPairs[" + rpBC + "]);\nWRITEMEM(regPairs[" + rpHL + "], initemp);\nregs[" + rB + "]--;\nvar originalHL = regPairs[" + rpHL + "];\nregPairs[" + rpHL + "]" + modifier + modifier + ";\nvar initemp2 = (initemp + regs[" + rC + "] " + modifier + " 1) & 0xff;\n\nregs[" + rF + "] = (initemp & 0x80 ? " + FLAG_N + " : 0) | ((initemp2 < initemp) ? " + (FLAG_H | FLAG_C) + " : 0 ) | ( parityTable[ (initemp2 & 0x07) ^ regs[" + rB + "] ] ? " + FLAG_P + " : 0 ) | sz53Table[regs[" + rB + "]];"; }; INIR_INDR = function(modifier) { return (INI_IND(modifier)) + "\nif (regs[" + rB + "]) {\n CONTEND_WRITE_NO_MREQ(originalHL, 1);\n CONTEND_WRITE_NO_MREQ(originalHL, 1);\n CONTEND_WRITE_NO_MREQ(originalHL, 1);\n CONTEND_WRITE_NO_MREQ(originalHL, 1);\n CONTEND_WRITE_NO_MREQ(originalHL, 1);\n regPairs[" + rpPC + "] -= 2;\n}"; }; INI = function() { return INI_IND('+'); }; IND = function() { return INI_IND('-'); }; INIR = function() { return INIR_INDR('+'); }; INDR = function() { return INIR_INDR('-'); }; JP_C_NN = function(flag, sense) { var condition; condition = "regs[" + rF + "] & " + flag; if (!sense) { condition = "!(" + condition + ")"; } return "if (" + condition + ") {\n var l = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n var h = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n regPairs[" + rpPC + "] = (h<<8) | l;\n} else {\n CONTEND_READ(regPairs[" + rpPC + "], 3);\n regPairs[" + rpPC + "]++;\n CONTEND_READ(regPairs[" + rpPC + "], 3);\n regPairs[" + rpPC + "]++;\n}"; }; JP_RR = function(rp) { return "regPairs[" + rpPC + "] = regPairs[" + rp + "];"; }; JP_NN = function() { return "var l = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar h = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nregPairs[" + rpPC + "] = (h<<8) | l;"; }; JR_C_N = function(flag, sense) { var condition; condition = "regs[" + rF + "] & " + flag; if (!sense) { condition = "!(" + condition + ")"; } return "if (" + condition + ") {\n var offset = READMEM(regPairs[" + rpPC + "]);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n regPairs[" + rpPC + "]++;\n regPairs[" + rpPC + "] += (offset & 0x80 ? offset - 0x100 : offset);\n} else {\n CONTEND_READ(regPairs[" + rpPC + "], 3);\n regPairs[" + rpPC + "]++; /* skip past offset byte */\n}"; }; JR_N = function() { return "var offset = READMEM(regPairs[" + rpPC + "]);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nregPairs[" + rpPC + "]++;\nregPairs[" + rpPC + "] += (offset & 0x80 ? offset - 0x100 : offset);"; }; LD_A_iNNi = function() { return "var l = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar h = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar addr = (h<<8) | l;\nregs[" + rA + "] = READMEM(addr);"; }; LD_iNNi_A = function() { return "var l = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar h = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar addr = (h<<8) | l;\nWRITEMEM(addr, regs[" + rA + "]);"; }; LD_iNNi_RR = function(rp) { return "var l = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar h = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar addr = (h<<8) | l;\nWRITEMEM(addr, regPairs[" + rp + "] & 0xff);\naddr = (addr + 1) & 0xffff;\nWRITEMEM(addr, regPairs[" + rp + "] >> 8);"; }; LD_iRRi_N = function(rp) { return "var n = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nWRITEMEM(regPairs[" + rp + "], n);"; }; LD_iRRi_R = function(rp, r) { return "WRITEMEM(regPairs[" + rp + "], regs[" + r + "]);"; }; LD_iRRpNNi_N = function(rp) { return "var offset = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nif (offset & 0x80) offset -= 0x100;\nvar addr = (regPairs[" + rp + "] + offset) & 0xffff;\n\nvar val = READMEM(regPairs[" + rpPC + "]);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nregPairs[" + rpPC + "]++;\nWRITEMEM(addr, val);"; }; LD_iRRpNNi_R = function(rp, r) { return "var offset = READMEM(regPairs[" + rpPC + "]);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nregPairs[" + rpPC + "]++;\nif (offset & 0x80) offset -= 0x100;\nvar addr = (regPairs[" + rp + "] + offset) & 0xffff;\n\nWRITEMEM(addr, regs[" + r + "]);"; }; LD_R_iRRi = function(r, rp) { return "regs[" + r + "] = READMEM(regPairs[" + rp + "]);"; }; LD_R_iRRpNNi = function(r, rp) { return "var offset = READMEM(regPairs[" + rpPC + "]);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\nregPairs[" + rpPC + "]++;\nif (offset & 0x80) offset -= 0x100;\nvar addr = (regPairs[" + rp + "] + offset) & 0xffff;\n\nregs[" + r + "] = READMEM(addr);"; }; LD_R_N = function(r) { return "regs[" + r + "] = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;"; }; LD_R_R = function(r1, r2) { var output; if (r1 === rI || r2 === rI || r1 === rR || r2 === rR) { output = "CONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nregs[" + r1 + "] = regs[" + r2 + "];"; if (r1 === rA) { output += "regs[" + rF + "] = (regs[" + rF + "] & " + FLAG_C + ") | sz53Table[regs[" + rA + "]] | ( iff2 ? " + FLAG_V + " : 0 );"; } return output; } else { return "regs[" + r1 + "] = regs[" + r2 + "];"; } }; LD_RR_iNNi = function(rp, shifted) { return "var l = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar h = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar addr = (h<<8) | l;\nl = READMEM(addr);\naddr = (addr + 1) & 0xffff;\nh = READMEM(addr);\nregPairs[" + rp + "] = (h<<8) | l;"; }; LD_RR_NN = function(rp) { return "var l = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nvar h = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nregPairs[" + rp + "] = (h<<8) | l;"; }; LD_RR_RR = function(rp1, rp2) { return "regPairs[" + rp1 + "] = regPairs[" + rp2 + "];\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);"; }; LDBITOP = function(regName, opcode, bit, rp) { var regNum; regNum = registerIndexes[regName]; return "var addr = (regPairs[" + rp + "] + offset) & 0xffff;\nregs[" + regNum + "] = READMEM(addr);\n" + (opcode(bit, regName)) + "\nCONTEND_READ_NO_MREQ(addr, 1);\nWRITEMEM(addr, regs[" + regNum + "]);"; }; LDI_LDD = function(modifier) { return "var bytetemp = READMEM(regPairs[" + rpHL + "]);\nregPairs[" + rpBC + "]--;\nWRITEMEM(regPairs[" + rpDE + "],bytetemp);\nvar originalDE = regPairs[" + rpDE + "];\nregPairs[" + rpDE + "]" + modifier + "; regPairs[" + rpHL + "]" + modifier + ";\nbytetemp = (bytetemp + regs[" + rA + "]) & 0xff;\nregs[" + rF + "] = (regs[" + rF + "] & " + (FLAG_C | FLAG_Z | FLAG_S) + ") | (regPairs[" + rpBC + "] ? " + FLAG_V + " : 0) | (bytetemp & " + FLAG_3 + ") | ((bytetemp & 0x02) ? " + FLAG_5 + " : 0);\nCONTEND_READ_NO_MREQ(originalDE, 1);\nCONTEND_READ_NO_MREQ(originalDE, 1);"; }; LDIR_LDDR = function(modifier) { return (LDI_LDD(modifier)) + "\nif (regPairs[" + rpBC + "]) {\n regPairs[" + rpPC + "]-=2;\n CONTEND_READ_NO_MREQ(originalDE, 1);\n CONTEND_READ_NO_MREQ(originalDE, 1);\n CONTEND_READ_NO_MREQ(originalDE, 1);\n CONTEND_READ_NO_MREQ(originalDE, 1);\n CONTEND_READ_NO_MREQ(originalDE, 1);\n}"; }; LDI = function() { return LDI_LDD('++'); }; LDD = function() { return LDI_LDD('--'); }; LDIR = function() { return LDIR_LDDR('++'); }; LDDR = function() { return LDIR_LDDR('--'); }; LDSHIFTOP = function(regName, opcode, rp) { var regNum; regNum = registerIndexes[regName]; return "var addr = (regPairs[" + rp + "] + offset) & 0xffff;\nregs[" + regNum + "] = READMEM(addr);\n" + (opcode(regName)) + "\nCONTEND_READ_NO_MREQ(addr, 1);\nWRITEMEM(addr, regs[" + regNum + "]);"; }; NEG = function() { return "var val = regs[" + rA + "];\nvar subtemp = -val;\nvar lookup = ( (val & 0x88) >> 2 ) | ( (subtemp & 0x88) >> 1 );\nregs[" + rA + "] = subtemp;\nregs[" + rF + "] = ( subtemp & 0x100 ? " + FLAG_C + " : 0 ) | " + FLAG_N + " | halfcarrySubTable[lookup & 0x07] | overflowSubTable[lookup >> 4] | sz53Table[regs[" + rA + "]];"; }; NOP = function() { return " "; }; OR_A = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\n\nregs[" + rA + "] |= " + operand.v + ";\nregs[" + rF + "] = sz53pTable[regs[" + rA + "]];"; }; OUT_iCi_0 = function(r) { return "CONTEND_PORT_EARLY(regPairs[" + rpBC + "]);\nioBus.write(regPairs[" + rpBC + "], 0, tstates);\nCONTEND_PORT_LATE(regPairs[" + rpBC + "]);"; }; OUT_iCi_R = function(r) { return "CONTEND_PORT_EARLY(regPairs[" + rpBC + "]);\nioBus.write(regPairs[" + rpBC + "], regs[" + r + "], tstates);\nCONTEND_PORT_LATE(regPairs[" + rpBC + "]);"; }; OUT_iNi_A = function() { return "var port = (regs[" + rA + "] << 8) | READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\nCONTEND_PORT_EARLY(port);\nioBus.write(port, regs[" + rA + "], tstates);\nCONTEND_PORT_LATE(port);"; }; OUTI_OUTD = function(modifier) { return "CONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nvar outitemp = READMEM(regPairs[" + rpHL + "]);\nregs[" + rB + "]--; /* This does happen first, despite what the specs say */\nCONTEND_PORT_EARLY(regPairs[" + rpBC + "]);\nioBus.write(regPairs[" + rpBC + "], outitemp, tstates);\nCONTEND_PORT_LATE(regPairs[" + rpBC + "]);\n\nregPairs[" + rpHL + "]" + modifier + ";\noutitemp2 = (outitemp + regs[" + rL + "]) & 0xff;\nregs[" + rF + "] = (outitemp & 0x80 ? " + FLAG_N + " : 0) | ( (outitemp2 < outitemp) ? " + (FLAG_H | FLAG_C) + " : 0) | (parityTable[ (outitemp2 & 0x07) ^ regs[" + rB + "] ] ? " + FLAG_P + " : 0 ) | sz53Table[ regs[" + rB + "] ];"; }; OTIR_OTDR = function(modifier) { return (OUTI_OUTD(modifier)) + "\nif (regs[" + rB + "]) {\n regPairs[" + rpPC + "]-=2;\n CONTEND_READ_NO_MREQ(regPairs[" + rpBC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpBC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpBC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpBC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpBC + "], 1);\n}"; }; OUTD = function() { return OUTI_OUTD('--'); }; OUTI = function() { return OUTI_OUTD('++'); }; OTDR = function() { return OTIR_OTDR('--'); }; OTIR = function() { return OTIR_OTDR('++'); }; POP_RR = function(rp) { return "var l = READMEM(regPairs[" + rpSP + "]); regPairs[" + rpSP + "]++;\nvar h = READMEM(regPairs[" + rpSP + "]); regPairs[" + rpSP + "]++;\nregPairs[" + rp + "] = (h<<8) | l;"; }; PUSH_RR = function(rp) { return "CONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nregPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rp + "] >> 8);\nregPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rp + "] & 0xff);"; }; RES = function(bit, param) { var hexMask, operand; operand = getParamBoilerplate(param, true); hexMask = 0xff ^ (1 << bit); return operand.getter + "\n" + operand.v + " &= " + hexMask + ";\n" + operand.setter; }; RET = function() { return "var l = READMEM(regPairs[" + rpSP + "]); regPairs[" + rpSP + "]++;\nvar h = READMEM(regPairs[" + rpSP + "]); regPairs[" + rpSP + "]++;\nregPairs[" + rpPC + "] = (h<<8) | l;"; }; RET_C = function(flag, sense) { var condition; condition = "regs[" + rF + "] & " + flag; if (!sense) { condition = "!(" + condition + ")"; } return "CONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nif (" + condition + ") {\n var l = READMEM(regPairs[" + rpSP + "]); regPairs[" + rpSP + "]++;\n var h = READMEM(regPairs[" + rpSP + "]); regPairs[" + rpSP + "]++;\n regPairs[" + rpPC + "] = (h<<8) | l;\n}"; }; RETN = function() { return "iff1 = iff2;\n" + (RET()); }; RL = function(param) { var operand; operand = getParamBoilerplate(param, true); return operand.getter + "\nvar rltemp = " + operand.v + ";\n" + operand.v + " = ( (" + operand.v + " << 1) | (regs[" + rF + "] & " + FLAG_C + ") ) " + operand.trunc + ";\nregs[" + rF + "] = ( rltemp >> 7 ) | sz53pTable[" + operand.v + "];\n" + operand.setter; }; RLA = function() { return "var bytetemp = regs[" + rA + "];\nregs[" + rA + "] = (regs[" + rA + "] << 1) | (regs[" + rF + "] & " + FLAG_C + ");\nregs[" + rF + "] = (regs[" + rF + "] & " + (FLAG_P | FLAG_Z | FLAG_S) + ") | (regs[" + rA + "] & " + (FLAG_3 | FLAG_5) + ") | (bytetemp >> 7);"; }; RLC = function(param) { var operand; operand = getParamBoilerplate(param, true); return operand.getter + "\n" + operand.v + " = ( (" + operand.v + " << 1) | (" + operand.v + " >> 7) ) " + operand.trunc + ";\nregs[" + rF + "] = (" + operand.v + " & " + FLAG_C + ") | sz53pTable[" + operand.v + "];\n" + operand.setter; }; RLD = function() { return "var bytetemp = READMEM(regPairs[" + rpHL + "]);\nCONTEND_READ_NO_MREQ(regPairs[" + rpHL + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpHL + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpHL + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpHL + "], 1);\nvar val = (bytetemp << 4) | (regs[" + rA + "] & 0x0f);\nWRITEMEM(regPairs[" + rpHL + "], val);\nregs[" + rA + "] = (regs[" + rA + "] & 0xf0) | (bytetemp >> 4);\nregs[" + rF + "] = (regs[" + rF + "] & " + FLAG_C + ") | sz53pTable[regs[" + rA + "]];"; }; RLCA = function() { return "regs[" + rA + "] = (regs[" + rA + "] << 1) | (regs[" + rA + "] >> 7);\nregs[" + rF + "] = (regs[" + rF + "] & " + (FLAG_P | FLAG_Z | FLAG_S) + ") | (regs[" + rA + "] & " + (FLAG_C | FLAG_3 | FLAG_5) + ");"; }; RR = function(param) { var operand; operand = getParamBoilerplate(param, true); return operand.getter + "\nvar rrtemp = " + operand.v + ";\n" + operand.v + " = ( (" + operand.v + " >> 1) | ( regs[" + rF + "] << 7 ) ) " + operand.trunc + ";\nregs[" + rF + "] = (rrtemp & " + FLAG_C + ") | sz53pTable[" + operand.v + "];\n" + operand.setter; }; RRA = function() { return "var bytetemp = regs[" + rA + "];\nregs[" + rA + "] = (bytetemp >> 1) | (regs[" + rF + "] << 7);\nregs[" + rF + "] = (regs[" + rF + "] & " + (FLAG_P | FLAG_Z | FLAG_S) + ") | (regs[" + rA + "] & " + (FLAG_3 | FLAG_5) + ") | (bytetemp & " + FLAG_C + ");"; }; RRC = function(param) { var operand; operand = getParamBoilerplate(param, true); return operand.getter + "\nregs[" + rF + "] = " + operand.v + " & " + FLAG_C + ";\n" + operand.v + " = ( (" + operand.v + " >> 1) | (" + operand.v + " << 7) ) " + operand.trunc + ";\nregs[" + rF + "] |= sz53pTable[" + operand.v + "];\n" + operand.setter; }; RRCA = function() { return "regs[" + rF + "] = (regs[" + rF + "] & " + (FLAG_P | FLAG_Z | FLAG_S) + ") | (regs[" + rA + "] & " + FLAG_C + ");\nregs[" + rA + "] = (regs[" + rA + "] >> 1) | (regs[" + rA + "] << 7);\nregs[" + rF + "] |= (regs[" + rA + "] & " + (FLAG_3 | FLAG_5) + ");"; }; RRD = function() { return "var bytetemp = READMEM(regPairs[" + rpHL + "]);\nCONTEND_READ_NO_MREQ(regPairs[" + rpHL + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpHL + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpHL + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpHL + "], 1);\nvar val = (regs[" + rA + "] << 4) | (bytetemp >> 4);\nWRITEMEM(regPairs[" + rpHL + "], val);\nregs[" + rA + "] = (regs[" + rA + "] & 0xf0) | (bytetemp & 0x0f);\nregs[" + rF + "] = (regs[" + rF + "] & " + FLAG_C + ") | sz53pTable[regs[" + rA + "]];"; }; RST = function(addr) { return "CONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nregPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rpPC + "] >> 8);\nregPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rpPC + "] & 0xff);\nregPairs[" + rpPC + "] = " + addr + ";"; }; SBC_A = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\nvar sbctemp = regs[" + rA + "] - " + operand.v + " - (regs[" + rF + "] & " + FLAG_C + ");\nvar lookup = ( (regs[" + rA + "] & 0x88) >> 3 ) | ( (" + operand.v + " & 0x88) >> 2 ) | ( (sbctemp & 0x88) >> 1 );\nregs[" + rA + "] = sbctemp;\nregs[" + rF + "] = ( sbctemp & 0x100 ? " + FLAG_C + " : 0 ) | " + FLAG_N + " | halfcarrySubTable[lookup & 0x07] | overflowSubTable[lookup >> 4] | sz53Table[regs[" + rA + "]];"; }; SBC_HL_RR = function(rp) { return "var sub16temp = regPairs[" + rpHL + "] - regPairs[" + rp + "] - (regs[" + rF + "] & " + FLAG_C + ");\nvar lookup = ( (regPairs[" + rpHL + "] & 0x8800) >> 11 ) | ( (regPairs[" + rp + "] & 0x8800) >> 10 ) | ( (sub16temp & 0x8800) >> 9 );\nregPairs[" + rpHL + "] = sub16temp;\nregs[" + rF + "] = ( sub16temp & 0x10000 ? " + FLAG_C + " : 0 ) | " + FLAG_N + " | overflowSubTable[lookup >> 4] | (regs[" + rH + "] & " + (FLAG_3 | FLAG_5 | FLAG_S) + ") | halfcarrySubTable[lookup&0x07] | (regPairs[" + rpHL + "] ? 0 : " + FLAG_Z + ");\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);\nCONTEND_READ_NO_MREQ(regPairs[" + rpIR + "], 1);"; }; SCF = function() { return "regs[" + rF + "] = (regs[" + rF + "] & " + (FLAG_P | FLAG_Z | FLAG_S) + ") | (regs[" + rA + "] & " + (FLAG_3 | FLAG_5) + ") | " + FLAG_C + ";"; }; SET = function(bit, param) { var hexMask, operand; hexMask = 1 << bit; operand = getParamBoilerplate(param, true); return operand.getter + "\n" + operand.v + " |= " + hexMask + ";\n" + operand.setter; }; SHIFT = function(prefix) { return "opcodePrefix = '" + prefix + "';\ninterruptible = false;"; }; SLA = function(param) { var operand; operand = getParamBoilerplate(param, true); return operand.getter + "\nregs[" + rF + "] = " + operand.v + " >> 7;\n" + operand.v + " = (" + operand.v + " << 1) " + operand.trunc + ";\nregs[" + rF + "] |= sz53pTable[" + operand.v + "];\n" + operand.setter; }; SLL = function(param) { var operand; operand = getParamBoilerplate(param, true); return operand.getter + "\nregs[" + rF + "] = " + operand.v + " >> 7;\n" + operand.v + " = (((" + operand.v + ") << 1) " + operand.trunc + ") | 0x01;\nregs[" + rF + "] |= sz53pTable[" + operand.v + "];\n" + operand.setter; }; SRA = function(param) { var operand; operand = getParamBoilerplate(param, true); return operand.getter + "\nregs[" + rF + "] = " + operand.v + " & " + FLAG_C + ";\n" + operand.v + " = ( (" + operand.v + " & 0x80) | (" + operand.v + " >> 1) ) " + operand.trunc + ";\nregs[" + rF + "] |= sz53pTable[" + operand.v + "];\n" + operand.setter; }; SRL = function(param) { var operand; operand = getParamBoilerplate(param, true); return operand.getter + "\nregs[" + rF + "] = " + operand.v + " & " + FLAG_C + ";\n" + operand.v + " >>= 1;\nregs[" + rF + "] |= sz53pTable[" + operand.v + "];\n" + operand.setter; }; SUB_A = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\nvar subtemp = regs[" + rA + "] - " + operand.v + ";\nvar lookup = ( (regs[" + rA + "] & 0x88) >> 3 ) | ( (" + operand.v + " & 0x88) >> 2 ) | ( (subtemp & 0x88) >> 1 );\nregs[" + rA + "] = subtemp;\nregs[" + rF + "] = ( subtemp & 0x100 ? " + FLAG_C + " : 0 ) | " + FLAG_N + " | halfcarrySubTable[lookup & 0x07] | overflowSubTable[lookup >> 4] | sz53Table[regs[" + rA + "]];"; }; XOR_A = function(param) { var operand; operand = getParamBoilerplate(param); return operand.getter + "\nregs[" + rA + "] ^= " + operand.v + ";\nregs[" + rF + "] = sz53pTable[regs[" + rA + "]];"; }; /* Given a table mapping opcodes to Javascript snippets (and optionally a fallback table for opcodes that aren't defined in the first one), build an enormous switch statement for them */ opcodeSwitch = function(runStringTable, fallbackTable, traps) { var action, address, clauses, i, j, opcode, relevantTraps, runString, trapCode; if (fallbackTable == null) { fallbackTable = {}; } if (traps == null) { traps = []; } clauses = []; for (i = j = 0; j < 256; i = ++j) { runString = runStringTable[i]; if (runString == null) { runString = fallbackTable[i]; } if (runString != null) { relevantTraps = (function() { var k, len, ref, results; results = []; for (k = 0, len = traps.length; k < len; k++) { ref = traps[k], address = ref[0], opcode = ref[1], action = ref[2]; if (opcode === i) { results.push([address, action]); } } return results; })(); trapCode = (function() { var k, len, ref, results; results = []; for (k = 0, len = relevantTraps.length; k < len; k++) { ref = relevantTraps[k], address = ref[0], action = ref[1]; results.push("if (regPairs[" + rpPC + "] == " + ((address + 1) & 0xffff) + " && !(" + action + ")) break;"); } return results; })(); clauses.push("case " + i + ": { var fn" + i + " = function() {\n " + (trapCode.join("\n")) + "\n " + runString + "\n}; fn" + i + "(); }\n break;"); } } return "switch (opcode) {\n " + (clauses.join('')) + "\n default:\n var addr = regPairs[" + rpPC + "] - 1;\n throw(\"Unimplemented opcode \" + opcode + \" in page " + runStringTable[0x100] + " - PC = \" + addr);\n}"; }; OPCODE_RUN_STRINGS_CB = { 0x00: RLC("B"), 0x01: RLC("C"), 0x02: RLC("D"), 0x03: RLC("E"), 0x04: RLC("H"), 0x05: RLC("L"), 0x06: RLC("(HL)"), 0x07: RLC("A"), 0x08: RRC("B"), 0x09: RRC("C"), 0x0a: RRC("D"), 0x0b: RRC("E"), 0x0c: RRC("H"), 0x0d: RRC("L"), 0x0e: RRC("(HL)"), 0x0f: RRC("A"), 0x10: RL('B'), 0x11: RL('C'), 0x12: RL('D'), 0x13: RL('E'), 0x14: RL('H'), 0x15: RL('L'), 0x16: RL('(HL)'), 0x17: RL('A'), 0x18: RR('B'), 0x19: RR('C'), 0x1a: RR('D'), 0x1b: RR('E'), 0x1c: RR('H'), 0x1d: RR('L'), 0x1e: RR('(HL)'), 0x1f: RR('A'), 0x20: SLA('B'), 0x21: SLA('C'), 0x22: SLA('D'), 0x23: SLA('E'), 0x24: SLA('H'), 0x25: SLA('L'), 0x26: SLA('(HL)'), 0x27: SLA('A'), 0x28: SRA('B'), 0x29: SRA('C'), 0x2a: SRA('D'), 0x2b: SRA('E'), 0x2c: SRA('H'), 0x2d: SRA('L'), 0x2e: SRA('(HL)'), 0x2f: SRA('A'), 0x30: SLL('B'), 0x31: SLL('C'), 0x32: SLL('D'), 0x33: SLL('E'), 0x34: SLL('H'), 0x35: SLL('L'), 0x36: SLL('(HL)'), 0x37: SLL('A'), 0x38: SRL('B'), 0x39: SRL('C'), 0x3a: SRL('D'), 0x3b: SRL('E'), 0x3c: SRL('H'), 0x3d: SRL('L'), 0x3e: SRL('(HL)'), 0x3f: SRL('A'), 0x40: BIT_N_R(0, rB), 0x41: BIT_N_R(0, rC), 0x42: BIT_N_R(0, rD), 0x43: BIT_N_R(0, rE), 0x44: BIT_N_R(0, rH), 0x45: BIT_N_R(0, rL), 0x46: BIT_N_iHLi(0), 0x47: BIT_N_R(0, rA), 0x48: BIT_N_R(1, rB), 0x49: BIT_N_R(1, rC), 0x4A: BIT_N_R(1, rD), 0x4B: BIT_N_R(1, rE), 0x4C: BIT_N_R(1, rH), 0x4D: BIT_N_R(1, rL), 0x4E: BIT_N_iHLi(1), 0x4F: BIT_N_R(1, rA), 0x50: BIT_N_R(2, rB), 0x51: BIT_N_R(2, rC), 0x52: BIT_N_R(2, rD), 0x53: BIT_N_R(2, rE), 0x54: BIT_N_R(2, rH), 0x55: BIT_N_R(2, rL), 0x56: BIT_N_iHLi(2), 0x57: BIT_N_R(2, rA), 0x58: BIT_N_R(3, rB), 0x59: BIT_N_R(3, rC), 0x5A: BIT_N_R(3, rD), 0x5B: BIT_N_R(3, rE), 0x5C: BIT_N_R(3, rH), 0x5D: BIT_N_R(3, rL), 0x5E: BIT_N_iHLi(3), 0x5F: BIT_N_R(3, rA), 0x60: BIT_N_R(4, rB), 0x61: BIT_N_R(4, rC), 0x62: BIT_N_R(4, rD), 0x63: BIT_N_R(4, rE), 0x64: BIT_N_R(4, rH), 0x65: BIT_N_R(4, rL), 0x66: BIT_N_iHLi(4), 0x67: BIT_N_R(4, rA), 0x68: BIT_N_R(5, rB), 0x69: BIT_N_R(5, rC), 0x6A: BIT_N_R(5, rD), 0x6B: BIT_N_R(5, rE), 0x6C: BIT_N_R(5, rH), 0x6D: BIT_N_R(5, rL), 0x6E: BIT_N_iHLi(5), 0x6F: BIT_N_R(5, rA), 0x70: BIT_N_R(6, rB), 0x71: BIT_N_R(6, rC), 0x72: BIT_N_R(6, rD), 0x73: BIT_N_R(6, rE), 0x74: BIT_N_R(6, rH), 0x75: BIT_N_R(6, rL), 0x76: BIT_N_iHLi(6), 0x77: BIT_N_R(6, rA), 0x78: BIT_N_R(7, rB), 0x79: BIT_N_R(7, rC), 0x7A: BIT_N_R(7, rD), 0x7B: BIT_N_R(7, rE), 0x7C: BIT_N_R(7, rH), 0x7D: BIT_N_R(7, rL), 0x7E: BIT_N_iHLi(7), 0x7F: BIT_N_R(7, rA), 0x80: RES(0, 'B'), 0x81: RES(0, 'C'), 0x82: RES(0, 'D'), 0x83: RES(0, 'E'), 0x84: RES(0, 'H'), 0x85: RES(0, 'L'), 0x86: RES(0, '(HL)'), 0x87: RES(0, 'A'), 0x88: RES(1, 'B'), 0x89: RES(1, 'C'), 0x8A: RES(1, 'D'), 0x8B: RES(1, 'E'), 0x8C: RES(1, 'H'), 0x8D: RES(1, 'L'), 0x8E: RES(1, '(HL)'), 0x8F: RES(1, 'A'), 0x90: RES(2, 'B'), 0x91: RES(2, 'C'), 0x92: RES(2, 'D'), 0x93: RES(2, 'E'), 0x94: RES(2, 'H'), 0x95: RES(2, 'L'), 0x96: RES(2, '(HL)'), 0x97: RES(2, 'A'), 0x98: RES(3, 'B'), 0x99: RES(3, 'C'), 0x9A: RES(3, 'D'), 0x9B: RES(3, 'E'), 0x9C: RES(3, 'H'), 0x9D: RES(3, 'L'), 0x9E: RES(3, '(HL)'), 0x9F: RES(3, 'A'), 0xA0: RES(4, 'B'), 0xA1: RES(4, 'C'), 0xA2: RES(4, 'D'), 0xA3: RES(4, 'E'), 0xA4: RES(4, 'H'), 0xA5: RES(4, 'L'), 0xA6: RES(4, '(HL)'), 0xA7: RES(4, 'A'), 0xA8: RES(5, 'B'), 0xA9: RES(5, 'C'), 0xAA: RES(5, 'D'), 0xAB: RES(5, 'E'), 0xAC: RES(5, 'H'), 0xAD: RES(5, 'L'), 0xAE: RES(5, '(HL)'), 0xAF: RES(5, 'A'), 0xB0: RES(6, 'B'), 0xB1: RES(6, 'C'), 0xB2: RES(6, 'D'), 0xB3: RES(6, 'E'), 0xB4: RES(6, 'H'), 0xB5: RES(6, 'L'), 0xB6: RES(6, '(HL)'), 0xB7: RES(6, 'A'), 0xB8: RES(7, 'B'), 0xB9: RES(7, 'C'), 0xBA: RES(7, 'D'), 0xBB: RES(7, 'E'), 0xBC: RES(7, 'H'), 0xBD: RES(7, 'L'), 0xBE: RES(7, '(HL)'), 0xBF: RES(7, 'A'), 0xC0: SET(0, 'B'), 0xC1: SET(0, 'C'), 0xC2: SET(0, 'D'), 0xC3: SET(0, 'E'), 0xC4: SET(0, 'H'), 0xC5: SET(0, 'L'), 0xC6: SET(0, '(HL)'), 0xC7: SET(0, 'A'), 0xC8: SET(1, 'B'), 0xC9: SET(1, 'C'), 0xCA: SET(1, 'D'), 0xCB: SET(1, 'E'), 0xCC: SET(1, 'H'), 0xCD: SET(1, 'L'), 0xCE: SET(1, '(HL)'), 0xCF: SET(1, 'A'), 0xD0: SET(2, 'B'), 0xD1: SET(2, 'C'), 0xD2: SET(2, 'D'), 0xD3: SET(2, 'E'), 0xD4: SET(2, 'H'), 0xD5: SET(2, 'L'), 0xD6: SET(2, '(HL)'), 0xD7: SET(2, 'A'), 0xD8: SET(3, 'B'), 0xD9: SET(3, 'C'), 0xDA: SET(3, 'D'), 0xDB: SET(3, 'E'), 0xDC: SET(3, 'H'), 0xDD: SET(3, 'L'), 0xDE: SET(3, '(HL)'), 0xDF: SET(3, 'A'), 0xE0: SET(4, 'B'), 0xE1: SET(4, 'C'), 0xE2: SET(4, 'D'), 0xE3: SET(4, 'E'), 0xE4: SET(4, 'H'), 0xE5: SET(4, 'L'), 0xE6: SET(4, '(HL)'), 0xE7: SET(4, 'A'), 0xE8: SET(5, 'B'), 0xE9: SET(5, 'C'), 0xEA: SET(5, 'D'), 0xEB: SET(5, 'E'), 0xEC: SET(5, 'H'), 0xED: SET(5, 'L'), 0xEE: SET(5, '(HL)'), 0xEF: SET(5, 'A'), 0xF0: SET(6, 'B'), 0xF1: SET(6, 'C'), 0xF2: SET(6, 'D'), 0xF3: SET(6, 'E'), 0xF4: SET(6, 'H'), 0xF5: SET(6, 'L'), 0xF6: SET(6, '(HL)'), 0xF7: SET(6, 'A'), 0xF8: SET(7, 'B'), 0xF9: SET(7, 'C'), 0xFA: SET(7, 'D'), 0xFB: SET(7, 'E'), 0xFC: SET(7, 'H'), 0xFD: SET(7, 'L'), 0xFE: SET(7, '(HL)'), 0xFF: SET(7, 'A'), 0x100: 'cb' }; generateddfdcbOpcodeSet = function(prefix) { var rh, rhn, rl, rln, rp, rpn; if (prefix === 'DDCB') { rp = rpIX; rh = rIXH; rl = rIXL; rpn = 'IX'; rhn = 'IXH'; rln = 'IXL'; } else { rp = rpIY; rh = rIYH; rl = rIYL; rpn = 'IY'; rhn = 'IYH'; rln = 'IYL'; } return { 0x00: LDSHIFTOP('B', RLC, rp), 0x01: LDSHIFTOP('C', RLC, rp), 0x02: LDSHIFTOP('D', RLC, rp), 0x03: LDSHIFTOP('E', RLC, rp), 0x04: LDSHIFTOP('H', RLC, rp), 0x05: LDSHIFTOP('L', RLC, rp), 0x06: RLC("(" + rpn + "+nn)"), 0x07: LDSHIFTOP('A', RLC, rp), 0x08: LDSHIFTOP('B', RRC, rp), 0x09: LDSHIFTOP('C', RRC, rp), 0x0A: LDSHIFTOP('D', RRC, rp), 0x0B: LDSHIFTOP('E', RRC, rp), 0x0C: LDSHIFTOP('H', RRC, rp), 0x0D: LDSHIFTOP('L', RRC, rp), 0x0E: RRC("(" + rpn + "+nn)"), 0x0F: LDSHIFTOP('A', RRC, rp), 0x10: LDSHIFTOP('B', RL, rp), 0x11: LDSHIFTOP('C', RL, rp), 0x12: LDSHIFTOP('D', RL, rp), 0x13: LDSHIFTOP('E', RL, rp), 0x14: LDSHIFTOP('H', RL, rp), 0x15: LDSHIFTOP('L', RL, rp), 0x16: RL("(" + rpn + "+nn)"), 0x17: LDSHIFTOP('A', RL, rp), 0x18: LDSHIFTOP('B', RR, rp), 0x19: LDSHIFTOP('C', RR, rp), 0x1A: LDSHIFTOP('D', RR, rp), 0x1B: LDSHIFTOP('E', RR, rp), 0x1C: LDSHIFTOP('H', RR, rp), 0x1D: LDSHIFTOP('L', RR, rp), 0x1E: RR("(" + rpn + "+nn)"), 0x1F: LDSHIFTOP('A', RR, rp), 0x20: LDSHIFTOP('B', SLA, rp), 0x21: LDSHIFTOP('C', SLA, rp), 0x22: LDSHIFTOP('D', SLA, rp), 0x23: LDSHIFTOP('E', SLA, rp), 0x24: LDSHIFTOP('H', SLA, rp), 0x25: LDSHIFTOP('L', SLA, rp), 0x26: SLA("(" + rpn + "+nn)"), 0x27: LDSHIFTOP('A', SLA, rp), 0x28: LDSHIFTOP('B', SRA, rp), 0x29: LDSHIFTOP('C', SRA, rp), 0x2A: LDSHIFTOP('D', SRA, rp), 0x2B: LDSHIFTOP('E', SRA, rp), 0x2C: LDSHIFTOP('H', SRA, rp), 0x2D: LDSHIFTOP('L', SRA, rp), 0x2E: SRA("(" + rpn + "+nn)"), 0x2F: LDSHIFTOP('A', SRA, rp), 0x30: LDSHIFTOP('B', SLL, rp), 0x31: LDSHIFTOP('C', SLL, rp), 0x32: LDSHIFTOP('D', SLL, rp), 0x33: LDSHIFTOP('E', SLL, rp), 0x34: LDSHIFTOP('H', SLL, rp), 0x35: LDSHIFTOP('L', SLL, rp), 0x36: SLL("(" + rpn + "+nn)"), 0x37: LDSHIFTOP('A', SLL, rp), 0x38: LDSHIFTOP('B', SRL, rp), 0x39: LDSHIFTOP('C', SRL, rp), 0x3A: LDSHIFTOP('D', SRL, rp), 0x3B: LDSHIFTOP('E', SRL, rp), 0x3C: LDSHIFTOP('H', SRL, rp), 0x3D: LDSHIFTOP('L', SRL, rp), 0x3E: SRL("(" + rpn + "+nn)"), 0x3F: LDSHIFTOP('A', SRL, rp), 0x40: BIT_N_iRRpNNi(0, rp), 0x41: BIT_N_iRRpNNi(0, rp), 0x42: BIT_N_iRRpNNi(0, rp), 0x43: BIT_N_iRRpNNi(0, rp), 0x44: BIT_N_iRRpNNi(0, rp), 0x45: BIT_N_iRRpNNi(0, rp), 0x46: BIT_N_iRRpNNi(0, rp), 0x47: BIT_N_iRRpNNi(0, rp), 0x48: BIT_N_iRRpNNi(1, rp), 0x49: BIT_N_iRRpNNi(1, rp), 0x4A: BIT_N_iRRpNNi(1, rp), 0x4B: BIT_N_iRRpNNi(1, rp), 0x4C: BIT_N_iRRpNNi(1, rp), 0x4D: BIT_N_iRRpNNi(1, rp), 0x4E: BIT_N_iRRpNNi(1, rp), 0x4F: BIT_N_iRRpNNi(1, rp), 0x50: BIT_N_iRRpNNi(2, rp), 0x51: BIT_N_iRRpNNi(2, rp), 0x52: BIT_N_iRRpNNi(2, rp), 0x53: BIT_N_iRRpNNi(2, rp), 0x54: BIT_N_iRRpNNi(2, rp), 0x55: BIT_N_iRRpNNi(2, rp), 0x56: BIT_N_iRRpNNi(2, rp), 0x57: BIT_N_iRRpNNi(2, rp), 0x58: BIT_N_iRRpNNi(3, rp), 0x59: BIT_N_iRRpNNi(3, rp), 0x5A: BIT_N_iRRpNNi(3, rp), 0x5B: BIT_N_iRRpNNi(3, rp), 0x5C: BIT_N_iRRpNNi(3, rp), 0x5D: BIT_N_iRRpNNi(3, rp), 0x5E: BIT_N_iRRpNNi(3, rp), 0x5F: BIT_N_iRRpNNi(3, rp), 0x60: BIT_N_iRRpNNi(4, rp), 0x61: BIT_N_iRRpNNi(4, rp), 0x62: BIT_N_iRRpNNi(4, rp), 0x63: BIT_N_iRRpNNi(4, rp), 0x64: BIT_N_iRRpNNi(4, rp), 0x65: BIT_N_iRRpNNi(4, rp), 0x66: BIT_N_iRRpNNi(4, rp), 0x67: BIT_N_iRRpNNi(4, rp), 0x68: BIT_N_iRRpNNi(5, rp), 0x69: BIT_N_iRRpNNi(5, rp), 0x6A: BIT_N_iRRpNNi(5, rp), 0x6B: BIT_N_iRRpNNi(5, rp), 0x6C: BIT_N_iRRpNNi(5, rp), 0x6D: BIT_N_iRRpNNi(5, rp), 0x6E: BIT_N_iRRpNNi(5, rp), 0x6F: BIT_N_iRRpNNi(5, rp), 0x70: BIT_N_iRRpNNi(6, rp), 0x71: BIT_N_iRRpNNi(6, rp), 0x72: BIT_N_iRRpNNi(6, rp), 0x73: BIT_N_iRRpNNi(6, rp), 0x74: BIT_N_iRRpNNi(6, rp), 0x75: BIT_N_iRRpNNi(6, rp), 0x76: BIT_N_iRRpNNi(6, rp), 0x77: BIT_N_iRRpNNi(6, rp), 0x78: BIT_N_iRRpNNi(7, rp), 0x79: BIT_N_iRRpNNi(7, rp), 0x7A: BIT_N_iRRpNNi(7, rp), 0x7B: BIT_N_iRRpNNi(7, rp), 0x7C: BIT_N_iRRpNNi(7, rp), 0x7D: BIT_N_iRRpNNi(7, rp), 0x7E: BIT_N_iRRpNNi(7, rp), 0x7F: BIT_N_iRRpNNi(7, rp), 0x80: LDBITOP('B', RES, 0, rp), 0x81: LDBITOP('C', RES, 0, rp), 0x82: LDBITOP('D', RES, 0, rp), 0x83: LDBITOP('E', RES, 0, rp), 0x84: LDBITOP('H', RES, 0, rp), 0x85: LDBITOP('L', RES, 0, rp), 0x86: RES(0, "(" + rpn + "+nn)"), 0x87: LDBITOP('A', RES, 0, rp), 0x88: LDBITOP('B', RES, 1, rp), 0x89: LDBITOP('C', RES, 1, rp), 0x8A: LDBITOP('D', RES, 1, rp), 0x8B: LDBITOP('E', RES, 1, rp), 0x8C: LDBITOP('H', RES, 1, rp), 0x8D: LDBITOP('L', RES, 1, rp), 0x8E: RES(1, "(" + rpn + "+nn)"), 0x8F: LDBITOP('A', RES, 1, rp), 0x90: LDBITOP('B', RES, 2, rp), 0x91: LDBITOP('C', RES, 2, rp), 0x92: LDBITOP('D', RES, 2, rp), 0x93: LDBITOP('E', RES, 2, rp), 0x94: LDBITOP('H', RES, 2, rp), 0x95: LDBITOP('L', RES, 2, rp), 0x96: RES(2, "(" + rpn + "+nn)"), 0x97: LDBITOP('A', RES, 2, rp), 0x98: LDBITOP('B', RES, 3, rp), 0x99: LDBITOP('C', RES, 3, rp), 0x9A: LDBITOP('D', RES, 3, rp), 0x9B: LDBITOP('E', RES, 3, rp), 0x9C: LDBITOP('H', RES, 3, rp), 0x9D: LDBITOP('L', RES, 3, rp), 0x9E: RES(3, "(" + rpn + "+nn)"), 0x9F: LDBITOP('A', RES, 3, rp), 0xA0: LDBITOP('B', RES, 4, rp), 0xA1: LDBITOP('C', RES, 4, rp), 0xA2: LDBITOP('D', RES, 4, rp), 0xA3: LDBITOP('E', RES, 4, rp), 0xA4: LDBITOP('H', RES, 4, rp), 0xA5: LDBITOP('L', RES, 4, rp), 0xA6: RES(4, "(" + rpn + "+nn)"), 0xA7: LDBITOP('A', RES, 4, rp), 0xA8: LDBITOP('B', RES, 5, rp), 0xA9: LDBITOP('C', RES, 5, rp), 0xAA: LDBITOP('D', RES, 5, rp), 0xAB: LDBITOP('E', RES, 5, rp), 0xAC: LDBITOP('H', RES, 5, rp), 0xAD: LDBITOP('L', RES, 5, rp), 0xAE: RES(5, "(" + rpn + "+nn)"), 0xAF: LDBITOP('A', RES, 5, rp), 0xB0: LDBITOP('B', RES, 6, rp), 0xB1: LDBITOP('C', RES, 6, rp), 0xB2: LDBITOP('D', RES, 6, rp), 0xB3: LDBITOP('E', RES, 6, rp), 0xB4: LDBITOP('H', RES, 6, rp), 0xB5: LDBITOP('L', RES, 6, rp), 0xB6: RES(6, "(" + rpn + "+nn)"), 0xB7: LDBITOP('A', RES, 6, rp), 0xB8: LDBITOP('B', RES, 7, rp), 0xB9: LDBITOP('C', RES, 7, rp), 0xBA: LDBITOP('D', RES, 7, rp), 0xBB: LDBITOP('E', RES, 7, rp), 0xBC: LDBITOP('H', RES, 7, rp), 0xBD: LDBITOP('L', RES, 7, rp), 0xBE: RES(7, "(" + rpn + "+nn)"), 0xBF: LDBITOP('A', RES, 7, rp), 0xC0: LDBITOP('B', SET, 0, rp), 0xC1: LDBITOP('C', SET, 0, rp), 0xC2: LDBITOP('D', SET, 0, rp), 0xC3: LDBITOP('E', SET, 0, rp), 0xC4: LDBITOP('H', SET, 0, rp), 0xC5: LDBITOP('L', SET, 0, rp), 0xC6: SET(0, "(" + rpn + "+nn)"), 0xC7: LDBITOP('A', SET, 0, rp), 0xC8: LDBITOP('B', SET, 1, rp), 0xC9: LDBITOP('C', SET, 1, rp), 0xCA: LDBITOP('D', SET, 1, rp), 0xCB: LDBITOP('E', SET, 1, rp), 0xCC: LDBITOP('H', SET, 1, rp), 0xCD: LDBITOP('L', SET, 1, rp), 0xCE: SET(1, "(" + rpn + "+nn)"), 0xCF: LDBITOP('A', SET, 1, rp), 0xD0: LDBITOP('B', SET, 2, rp), 0xD1: LDBITOP('C', SET, 2, rp), 0xD2: LDBITOP('D', SET, 2, rp), 0xD3: LDBITOP('E', SET, 2, rp), 0xD4: LDBITOP('H', SET, 2, rp), 0xD5: LDBITOP('L', SET, 2, rp), 0xD6: SET(2, "(" + rpn + "+nn)"), 0xD7: LDBITOP('A', SET, 2, rp), 0xD8: LDBITOP('B', SET, 3, rp), 0xD9: LDBITOP('C', SET, 3, rp), 0xDA: LDBITOP('D', SET, 3, rp), 0xDB: LDBITOP('E', SET, 3, rp), 0xDC: LDBITOP('H', SET, 3, rp), 0xDD: LDBITOP('L', SET, 3, rp), 0xDE: SET(3, "(" + rpn + "+nn)"), 0xDF: LDBITOP('A', SET, 3, rp), 0xE0: LDBITOP('B', SET, 4, rp), 0xE1: LDBITOP('C', SET, 4, rp), 0xE2: LDBITOP('D', SET, 4, rp), 0xE3: LDBITOP('E', SET, 4, rp), 0xE4: LDBITOP('H', SET, 4, rp), 0xE5: LDBITOP('L', SET, 4, rp), 0xE6: SET(4, "(" + rpn + "+nn)"), 0xE7: LDBITOP('A', SET, 4, rp), 0xE8: LDBITOP('B', SET, 5, rp), 0xE9: LDBITOP('C', SET, 5, rp), 0xEA: LDBITOP('D', SET, 5, rp), 0xEB: LDBITOP('E', SET, 5, rp), 0xEC: LDBITOP('H', SET, 5, rp), 0xED: LDBITOP('L', SET, 5, rp), 0xEE: SET(5, "(" + rpn + "+nn)"), 0xEF: LDBITOP('A', SET, 5, rp), 0xF0: LDBITOP('B', SET, 6, rp), 0xF1: LDBITOP('C', SET, 6, rp), 0xF2: LDBITOP('D', SET, 6, rp), 0xF3: LDBITOP('E', SET, 6, rp), 0xF4: LDBITOP('H', SET, 6, rp), 0xF5: LDBITOP('L', SET, 6, rp), 0xF6: SET(6, "(" + rpn + "+nn)"), 0xF7: LDBITOP('A', SET, 6, rp), 0xF8: LDBITOP('B', SET, 7, rp), 0xF9: LDBITOP('C', SET, 7, rp), 0xFA: LDBITOP('D', SET, 7, rp), 0xFB: LDBITOP('E', SET, 7, rp), 0xFC: LDBITOP('H', SET, 7, rp), 0xFD: LDBITOP('L', SET, 7, rp), 0xFE: SET(7, "(" + rpn + "+nn)"), 0xFF: LDBITOP('A', SET, 7, rp), 0x100: 'ddcb' }; }; OPCODE_RUN_STRINGS_DDCB = generateddfdcbOpcodeSet('DDCB'); OPCODE_RUN_STRINGS_FDCB = generateddfdcbOpcodeSet('FDCB'); generateddfdOpcodeSet = function(prefix) { var rh, rhn, rl, rln, rp, rpn; if (prefix === 'DD') { rp = rpIX; rh = rIXH; rl = rIXL; rpn = 'IX'; rhn = 'IXH'; rln = 'IXL'; } else { rp = rpIY; rh = rIYH; rl = rIYL; rpn = 'IY'; rhn = 'IYH'; rln = 'IYL'; } return { 0x09: ADD_RR_RR(rp, rpBC), 0x19: ADD_RR_RR(rp, rpDE), 0x21: LD_RR_NN(rp), 0x22: LD_iNNi_RR(rp), 0x23: INC_RR(rp), 0x24: INC(rhn), 0x25: DEC(rhn), 0x26: LD_R_N(rh), 0x29: ADD_RR_RR(rp, rp), 0x2A: LD_RR_iNNi(rp), 0x2B: DEC_RR(rp), 0x2C: INC(rln), 0x2D: DEC(rln), 0x2E: LD_R_N(rl), 0x34: INC("(" + rpn + "+nn)"), 0x35: DEC("(" + rpn + "+nn)"), 0x36: LD_iRRpNNi_N(rp), 0x39: ADD_RR_RR(rp, rpSP), 0x44: LD_R_R(rB, rh), 0x45: LD_R_R(rB, rl), 0x46: LD_R_iRRpNNi(rB, rp), 0x4C: LD_R_R(rC, rh), 0x4D: LD_R_R(rC, rl), 0x4E: LD_R_iRRpNNi(rC, rp), 0x54: LD_R_R(rD, rh), 0x55: LD_R_R(rD, rl), 0x56: LD_R_iRRpNNi(rD, rp), 0x5C: LD_R_R(rE, rh), 0x5D: LD_R_R(rE, rl), 0x5E: LD_R_iRRpNNi(rE, rp), 0x60: LD_R_R(rh, rB), 0x61: LD_R_R(rh, rC), 0x62: LD_R_R(rh, rD), 0x63: LD_R_R(rh, rE), 0x64: LD_R_R(rh, rh), 0x65: LD_R_R(rh, rl), 0x66: LD_R_iRRpNNi(rH, rp), 0x67: LD_R_R(rh, rA), 0x68: LD_R_R(rl, rB), 0x69: LD_R_R(rl, rC), 0x6A: LD_R_R(rl, rD), 0x6B: LD_R_R(rl, rE), 0x6C: LD_R_R(rl, rh), 0x6D: LD_R_R(rl, rl), 0x6E: LD_R_iRRpNNi(rL, rp), 0x6F: LD_R_R(rl, rA), 0x70: LD_iRRpNNi_R(rp, rB), 0x71: LD_iRRpNNi_R(rp, rC), 0x72: LD_iRRpNNi_R(rp, rD), 0x73: LD_iRRpNNi_R(rp, rE), 0x74: LD_iRRpNNi_R(rp, rH), 0x75: LD_iRRpNNi_R(rp, rL), 0x77: LD_iRRpNNi_R(rp, rA), 0x7C: LD_R_R(rA, rh), 0x7D: LD_R_R(rA, rl), 0x7E: LD_R_iRRpNNi(rA, rp), 0x84: ADD_A(rhn), 0x85: ADD_A(rln), 0x86: ADD_A("(" + rpn + "+nn)"), 0x8C: ADC_A(rhn), 0x8D: ADC_A(rln), 0x8E: ADC_A("(" + rpn + "+nn)"), 0x94: SUB_A(rhn), 0x95: SUB_A(rln), 0x96: SUB_A("(" + rpn + "+nn)"), 0x9C: SBC_A(rhn), 0x9D: SBC_A(rln), 0x9E: SBC_A("(" + rpn + "+nn)"), 0xA4: AND_A(rhn), 0xA5: AND_A(rln), 0xA6: AND_A("(" + rpn + "+nn)"), 0xAC: XOR_A(rhn), 0xAD: XOR_A(rln), 0xAE: XOR_A("(" + rpn + "+nn)"), 0xB4: OR_A(rhn), 0xB5: OR_A(rln), 0xB6: OR_A("(" + rpn + "+nn)"), 0xBC: CP_A(rhn), 0xBD: CP_A(rln), 0xBE: CP_A("(" + rpn + "+nn)"), 0xCB: SHIFT(prefix + 'CB'), 0xDD: SHIFT('DD'), 0xE1: POP_RR(rp), 0xE3: EX_iSPi_RR(rp), 0xE5: PUSH_RR(rp), 0xE9: JP_RR(rp), 0xF9: LD_RR_RR(rpSP, rp), 0xFD: SHIFT('FD'), 0x100: 'dd' }; }; OPCODE_RUN_STRINGS_DD = generateddfdOpcodeSet('DD'); OPCODE_RUN_STRINGS_ED = { 0x40: IN_R_iCi(rB), 0x41: OUT_iCi_R(rB), 0x42: SBC_HL_RR(rpBC), 0x43: LD_iNNi_RR(rpBC), 0x44: NEG(), 0x45: RETN(), 0x46: IM(0), 0x47: LD_R_R(rI, rA), 0x48: IN_R_iCi(rC), 0x49: OUT_iCi_R(rC), 0x4A: ADC_HL_RR(rpBC), 0x4B: LD_RR_iNNi(rpBC), 0x4C: NEG(), 0x4D: RETN(), 0x4E: IM(0), 0x4F: LD_R_R(rR, rA), 0x50: IN_R_iCi(rD), 0x51: OUT_iCi_R(rD), 0x52: SBC_HL_RR(rpDE), 0x53: LD_iNNi_RR(rpDE), 0x54: NEG(), 0x55: RETN(), 0x56: IM(1), 0x57: LD_R_R(rA, rI), 0x58: IN_R_iCi(rE), 0x59: OUT_iCi_R(rE), 0x5A: ADC_HL_RR(rpDE), 0x5B: LD_RR_iNNi(rpDE), 0x5C: NEG(), 0x5D: RETN(), 0x5E: IM(2), 0x5F: LD_R_R(rA, rR), 0x60: IN_R_iCi(rH), 0x61: OUT_iCi_R(rH), 0x62: SBC_HL_RR(rpHL), 0x63: LD_iNNi_RR(rpHL), 0x64: NEG(), 0x65: RETN(), 0x66: IM(0), 0x67: RRD(), 0x68: IN_R_iCi(rL), 0x69: OUT_iCi_R(rL), 0x6A: ADC_HL_RR(rpHL), 0x6B: LD_RR_iNNi(rpHL, true), 0x6C: NEG(), 0x6D: RETN(), 0x6E: IM(0), 0x6F: RLD(), 0x70: IN_F_iCi(), 0x71: OUT_iCi_0(), 0x72: SBC_HL_RR(rpSP), 0x73: LD_iNNi_RR(rpSP), 0x74: NEG(), 0x75: RETN(), 0x76: IM(1), 0x78: IN_R_iCi(rA), 0x79: OUT_iCi_R(rA), 0x7A: ADC_HL_RR(rpSP), 0x7B: LD_RR_iNNi(rpSP), 0x7C: NEG(), 0x7D: RETN(), 0x7E: IM(2), 0xA0: LDI(), 0xA1: CPI(), 0xA2: INI(), 0xA3: OUTI(), 0xA8: LDD(), 0xA9: CPD(), 0xAA: IND(), 0xAB: OUTD(), 0xB0: LDIR(), 0xb1: CPIR(), 0xB2: INIR(), 0xB3: OTIR(), 0xB8: LDDR(), 0xb9: CPDR(), 0xBA: INDR(), 0xBB: OTDR(), 0x100: 'ed' }; OPCODE_RUN_STRINGS_FD = generateddfdOpcodeSet('FD'); OPCODE_RUN_STRINGS = { 0x00: NOP(), 0x01: LD_RR_NN(rpBC), 0x02: LD_iRRi_R(rpBC, rA), 0x03: INC_RR(rpBC), 0x04: INC("B"), 0x05: DEC("B"), 0x06: LD_R_N(rB), 0x07: RLCA(), 0x08: EX_RR_RR(rpAF, rpAF_), 0x09: ADD_RR_RR(rpHL, rpBC), 0x0A: LD_R_iRRi(rA, rpBC), 0x0B: DEC_RR(rpBC), 0x0C: INC("C"), 0x0D: DEC("C"), 0x0E: LD_R_N(rC), 0x0F: RRCA(), 0x10: DJNZ_N(), 0x11: LD_RR_NN(rpDE), 0x12: LD_iRRi_R(rpDE, rA), 0x13: INC_RR(rpDE), 0x14: INC("D"), 0x15: DEC("D"), 0x16: LD_R_N(rD), 0x17: RLA(), 0x18: JR_N(), 0x19: ADD_RR_RR(rpHL, rpDE), 0x1A: LD_R_iRRi(rA, rpDE), 0x1B: DEC_RR(rpDE), 0x1C: INC("E"), 0x1D: DEC("E"), 0x1E: LD_R_N(rE), 0x1F: RRA(), 0x20: JR_C_N(FLAG_Z, false), 0x21: LD_RR_NN(rpHL), 0x22: LD_iNNi_RR(rpHL), 0x23: INC_RR(rpHL), 0x24: INC("H"), 0x25: DEC("H"), 0x26: LD_R_N(rH), 0x27: DAA(), 0x28: JR_C_N(FLAG_Z, true), 0x29: ADD_RR_RR(rpHL, rpHL), 0x2A: LD_RR_iNNi(rpHL), 0x2B: DEC_RR(rpHL), 0x2C: INC("L"), 0x2D: DEC("L"), 0x2E: LD_R_N(rL), 0x2F: CPL(), 0x30: JR_C_N(FLAG_C, false), 0x31: LD_RR_NN(rpSP), 0x32: LD_iNNi_A(), 0x33: INC_RR(rpSP), 0x34: INC("(HL)"), 0x35: DEC("(HL)"), 0x36: LD_iRRi_N(rpHL), 0x37: SCF(), 0x38: JR_C_N(FLAG_C, true), 0x39: ADD_RR_RR(rpHL, rpSP), 0x3A: LD_A_iNNi(), 0x3B: DEC_RR(rpSP), 0x3C: INC("A"), 0x3D: DEC("A"), 0x3E: LD_R_N(rA), 0x3F: CCF(), 0x40: LD_R_R(rB, rB), 0x41: LD_R_R(rB, rC), 0x42: LD_R_R(rB, rD), 0x43: LD_R_R(rB, rE), 0x44: LD_R_R(rB, rH), 0x45: LD_R_R(rB, rL), 0x46: LD_R_iRRi(rB, rpHL), 0x47: LD_R_R(rB, rA), 0x48: LD_R_R(rC, rB), 0x49: LD_R_R(rC, rC), 0x4a: LD_R_R(rC, rD), 0x4b: LD_R_R(rC, rE), 0x4c: LD_R_R(rC, rH), 0x4d: LD_R_R(rC, rL), 0x4e: LD_R_iRRi(rC, rpHL), 0x4f: LD_R_R(rC, rA), 0x50: LD_R_R(rD, rB), 0x51: LD_R_R(rD, rC), 0x52: LD_R_R(rD, rD), 0x53: LD_R_R(rD, rE), 0x54: LD_R_R(rD, rH), 0x55: LD_R_R(rD, rL), 0x56: LD_R_iRRi(rD, rpHL), 0x57: LD_R_R(rD, rA), 0x58: LD_R_R(rE, rB), 0x59: LD_R_R(rE, rC), 0x5a: LD_R_R(rE, rD), 0x5b: LD_R_R(rE, rE), 0x5c: LD_R_R(rE, rH), 0x5d: LD_R_R(rE, rL), 0x5e: LD_R_iRRi(rE, rpHL), 0x5f: LD_R_R(rE, rA), 0x60: LD_R_R(rH, rB), 0x61: LD_R_R(rH, rC), 0x62: LD_R_R(rH, rD), 0x63: LD_R_R(rH, rE), 0x64: LD_R_R(rH, rH), 0x65: LD_R_R(rH, rL), 0x66: LD_R_iRRi(rH, rpHL), 0x67: LD_R_R(rH, rA), 0x68: LD_R_R(rL, rB), 0x69: LD_R_R(rL, rC), 0x6a: LD_R_R(rL, rD), 0x6b: LD_R_R(rL, rE), 0x6c: LD_R_R(rL, rH), 0x6d: LD_R_R(rL, rL), 0x6e: LD_R_iRRi(rL, rpHL), 0x6f: LD_R_R(rL, rA), 0x70: LD_iRRi_R(rpHL, rB), 0x71: LD_iRRi_R(rpHL, rC), 0x72: LD_iRRi_R(rpHL, rD), 0x73: LD_iRRi_R(rpHL, rE), 0x74: LD_iRRi_R(rpHL, rH), 0x75: LD_iRRi_R(rpHL, rL), 0x76: HALT(), 0x77: LD_iRRi_R(rpHL, rA), 0x78: LD_R_R(rA, rB), 0x79: LD_R_R(rA, rC), 0x7a: LD_R_R(rA, rD), 0x7b: LD_R_R(rA, rE), 0x7c: LD_R_R(rA, rH), 0x7d: LD_R_R(rA, rL), 0x7e: LD_R_iRRi(rA, rpHL), 0x7f: LD_R_R(rA, rA), 0x80: ADD_A("B"), 0x81: ADD_A("C"), 0x82: ADD_A("D"), 0x83: ADD_A("E"), 0x84: ADD_A("H"), 0x85: ADD_A("L"), 0x86: ADD_A("(HL)"), 0x87: ADD_A("A"), 0x88: ADC_A("B"), 0x89: ADC_A("C"), 0x8a: ADC_A("D"), 0x8b: ADC_A("E"), 0x8c: ADC_A("H"), 0x8d: ADC_A("L"), 0x8e: ADC_A("(HL)"), 0x8f: ADC_A("A"), 0x90: SUB_A("B"), 0x91: SUB_A("C"), 0x92: SUB_A("D"), 0x93: SUB_A("E"), 0x94: SUB_A("H"), 0x95: SUB_A("L"), 0x96: SUB_A("(HL)"), 0x97: SUB_A("A"), 0x98: SBC_A("B"), 0x99: SBC_A("C"), 0x9a: SBC_A("D"), 0x9b: SBC_A("E"), 0x9c: SBC_A("H"), 0x9d: SBC_A("L"), 0x9e: SBC_A("(HL)"), 0x9f: SBC_A("A"), 0xa0: AND_A("B"), 0xa1: AND_A("C"), 0xa2: AND_A("D"), 0xa3: AND_A("E"), 0xa4: AND_A("H"), 0xa5: AND_A("L"), 0xa6: AND_A("(HL)"), 0xa7: AND_A("A"), 0xA8: XOR_A("B"), 0xA9: XOR_A("C"), 0xAA: XOR_A("D"), 0xAB: XOR_A("E"), 0xAC: XOR_A("H"), 0xAD: XOR_A("L"), 0xAE: XOR_A("(HL)"), 0xAF: XOR_A("A"), 0xb0: OR_A("B"), 0xb1: OR_A("C"), 0xb2: OR_A("D"), 0xb3: OR_A("E"), 0xb4: OR_A("H"), 0xb5: OR_A("L"), 0xb6: OR_A("(HL)"), 0xb7: OR_A("A"), 0xb8: CP_A("B"), 0xb9: CP_A("C"), 0xba: CP_A("D"), 0xbb: CP_A("E"), 0xbc: CP_A("H"), 0xbd: CP_A("L"), 0xbe: CP_A("(HL)"), 0xbf: CP_A("A"), 0xC0: RET_C(FLAG_Z, false), 0xC1: POP_RR(rpBC), 0xC2: JP_C_NN(FLAG_Z, false), 0xC3: JP_NN(), 0xC4: CALL_C_NN(FLAG_Z, false), 0xC5: PUSH_RR(rpBC), 0xC6: ADD_A("nn"), 0xC7: RST(0x0000), 0xC8: RET_C(FLAG_Z, true), 0xC9: RET(), 0xCA: JP_C_NN(FLAG_Z, true), 0xCB: SHIFT('CB'), 0xCC: CALL_C_NN(FLAG_Z, true), 0xCD: CALL_NN(), 0xCE: ADC_A("nn"), 0xCF: RST(0x0008), 0xD0: RET_C(FLAG_C, false), 0xD1: POP_RR(rpDE), 0xD2: JP_C_NN(FLAG_C, false), 0xD3: OUT_iNi_A(), 0xD4: CALL_C_NN(FLAG_C, false), 0xD5: PUSH_RR(rpDE), 0xD6: SUB_A("nn"), 0xD7: RST(0x0010), 0xD8: RET_C(FLAG_C, true), 0xD9: EXX(), 0xDA: JP_C_NN(FLAG_C, true), 0xDB: IN_A_N(), 0xDC: CALL_C_NN(FLAG_C, true), 0xDD: SHIFT('DD'), 0xDE: SBC_A("nn"), 0xDF: RST(0x0018), 0xE0: RET_C(FLAG_P, false), 0xE1: POP_RR(rpHL), 0xE2: JP_C_NN(FLAG_P, false), 0xE3: EX_iSPi_RR(rpHL), 0xE4: CALL_C_NN(FLAG_P, false), 0xE5: PUSH_RR(rpHL), 0xE6: AND_A("nn"), 0xE7: RST(0x0020), 0xE8: RET_C(FLAG_P, true), 0xE9: JP_RR(rpHL), 0xEA: JP_C_NN(FLAG_P, true), 0xEB: EX_RR_RR(rpDE, rpHL), 0xEC: CALL_C_NN(FLAG_P, true), 0xED: SHIFT('ED'), 0xEE: XOR_A("nn"), 0xEF: RST(0x0028), 0xF0: RET_C(FLAG_S, false), 0xF1: POP_RR(rpAF), 0xF2: JP_C_NN(FLAG_S, false), 0xF3: DI(), 0xF4: CALL_C_NN(FLAG_S, false), 0xF5: PUSH_RR(rpAF), 0xF6: OR_A("nn"), 0xF7: RST(0x0030), 0xF8: RET_C(FLAG_S, true), 0xF9: LD_RR_RR(rpSP, rpHL), 0xFA: JP_C_NN(FLAG_S, true), 0xFB: EI(), 0xFC: CALL_C_NN(FLAG_S, true), 0xFD: SHIFT('FD'), 0xFE: CP_A("nn"), 0xFF: RST(0x0038), 0x100: 0 }; /* Assemble and evaluate the final JS code for the Z80 component. The indirection on 'eval' causes most browsers to evaluate it in the global scope, giving a significant speed boost */ defineZ80JS = "window.Z80 = function(opts) {\n var self = {};\n\n " + setUpStateJS + "\n\n self.requestInterrupt = function(dataBus) {\n interruptPending = true;\n interruptDataBus = dataBus & 0xffff;\n /* TODO: use event scheduling to keep the interrupt line active for a fixed\n ~48T window, to support retriggered interrupts and interrupt blocking via\n chains of EI or DD/FD prefixes */\n }\n self.nonMaskableInterrupt = function() {\n iff1 = 1;\n self.requestInterrupt(0x66);\n }\n var z80Interrupt = function() {\n if (iff1) {\n if (halted) {\n /* move PC on from the HALT opcode */\n regPairs[" + rpPC + "]++;\n halted = false;\n }\n\n iff1 = iff2 = 0;\n\n /* push current PC in readiness for call to interrupt handler */\n regPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rpPC + "] >> 8);\n regPairs[" + rpSP + "]--; WRITEMEM(regPairs[" + rpSP + "], regPairs[" + rpPC + "] & 0xff);\n\n /* TODO: R register */\n\n switch (im) {\n case 0:\n regPairs[" + rpPC + "] = interruptDataBus; // assume always RST\n tstates += 6;\n break;\n case 1:\n regPairs[" + rpPC + "] = 0x0038;\n tstates += 7;\n break;\n case 2:\n inttemp = (regs[" + rI + "] << 8) | (interruptDataBus & 0xff);\n l = READMEM(inttemp);\n inttemp = (inttemp+1) & 0xffff;\n h = READMEM(inttemp);\n /*console.log(hex(interruptDataBus), hex(inttemp), hex(l), hex(h));*/\n regPairs[" + rpPC + "] = (h<<8) | l;\n tstates += 7;\n break;\n }\n }\n };\n\n self.runFrame = function(frameLength) {\n var lastOpcodePrefix, offset, opcode;\n\n while (tstates < frameLength || opcodePrefix) {\n if (interruptible && interruptPending && (iff1 || !self.retryInterrupts)) {\n z80Interrupt();\n interruptPending = false;\n }\n interruptible = true; /* unless overridden by opcode */\n lastOpcodePrefix = opcodePrefix;\n opcodePrefix = '';\n switch (lastOpcodePrefix) {\n case '':\n CONTEND_READ(regPairs[" + rpPC + "], 4);\n opcode = memory.read(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n regs[" + rR + "] = ((regs[" + rR + "] + 1) & 0x7f) | (regs[" + rR + "] & 0x80);\n " + (opcodeSwitch(OPCODE_RUN_STRINGS, null, opts.traps)) + "\n break;\n case 'CB':\n CONTEND_READ(regPairs[" + rpPC + "], 4);\n opcode = memory.read(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n regs[" + rR + "] = ((regs[" + rR + "] + 1) & 0x7f) | (regs[" + rR + "] & 0x80);\n " + (opcodeSwitch(OPCODE_RUN_STRINGS_CB)) + "\n break;\n case 'DD':\n CONTEND_READ(regPairs[" + rpPC + "], 4);\n opcode = memory.read(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n regs[" + rR + "] = ((regs[" + rR + "] + 1) & 0x7f) | (regs[" + rR + "] & 0x80);\n " + (opcodeSwitch(OPCODE_RUN_STRINGS_DD, OPCODE_RUN_STRINGS)) + "\n break;\n case 'DDCB':\n offset = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n if (offset & 0x80) offset -= 0x100;\n CONTEND_READ(regPairs[" + rpPC + "], 3);\n opcode = memory.read(regPairs[" + rpPC + "]);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n regPairs[" + rpPC + "]++;\n " + (opcodeSwitch(OPCODE_RUN_STRINGS_DDCB)) + "\n break;\n case 'ED':\n CONTEND_READ(regPairs[" + rpPC + "], 4);\n opcode = memory.read(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n regs[" + rR + "] = ((regs[" + rR + "] + 1) & 0x7f) | (regs[" + rR + "] & 0x80);\n " + (opcodeSwitch(OPCODE_RUN_STRINGS_ED)) + "\n break;\n case 'FD':\n CONTEND_READ(regPairs[" + rpPC + "], 4);\n opcode = memory.read(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n regs[" + rR + "] = ((regs[" + rR + "] + 1) & 0x7f) | (regs[" + rR + "] & 0x80);\n " + (opcodeSwitch(OPCODE_RUN_STRINGS_FD, OPCODE_RUN_STRINGS)) + "\n break;\n case 'FDCB':\n offset = READMEM(regPairs[" + rpPC + "]); regPairs[" + rpPC + "]++;\n if (offset & 0x80) offset -= 0x100;\n CONTEND_READ(regPairs[" + rpPC + "], 3);\n opcode = memory.read(regPairs[" + rpPC + "]);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n CONTEND_READ_NO_MREQ(regPairs[" + rpPC + "], 1);\n regPairs[" + rpPC + "]++;\n " + (opcodeSwitch(OPCODE_RUN_STRINGS_FDCB)) + "\n break;\n default:\n throw(\"Unknown opcode prefix: \" + lastOpcodePrefix);\n }\n }\n while (display.nextEventTime != null && display.nextEventTime <= tstates) display.doEvent();\n };\n\n self.reset = function() {\n regPairs[" + rpPC + "] = regPairs[" + rpIR + "] = 0;\n iff1 = 0; iff2 = 0; im = 0; halted = false;\n };\n\n self.loadState = function(snapRegs) {\n regPairs[" + rpAF + "] = snapRegs['AF'];\n regPairs[" + rpBC + "] = snapRegs['BC'];\n regPairs[" + rpDE + "] = snapRegs['DE'];\n regPairs[" + rpHL + "] = snapRegs['HL'];\n regPairs[" + rpAF_ + "] = snapRegs['AF_'];\n regPairs[" + rpBC_ + "] = snapRegs['BC_'];\n regPairs[" + rpDE_ + "] = snapRegs['DE_'];\n regPairs[" + rpHL_ + "] = snapRegs['HL_'];\n regPairs[" + rpIX + "] = snapRegs['IX'];\n regPairs[" + rpIY + "] = snapRegs['IY'];\n regPairs[" + rpSP + "] = snapRegs['SP'];\n regPairs[" + rpPC + "] = snapRegs['PC'];\n regPairs[" + rpIR + "] = snapRegs['IR'];\n iff1 = snapRegs['iff1'] & 1;\n iff2 = snapRegs['iff2'] & 1;\n im = snapRegs['im'] & 3;\n halted = !!snapRegs['halted'];\n tstates = snapRegs['T'] * 1;\n interruptPending = !!snapRegs['intp'];\n interruptDataBus = snapRegs['intd'] & 0xffff;\n };\n\n self.saveState = function() {\n return {\n AF: regPairs[" + rpAF + "],\n BC: regPairs[" + rpBC + "],\n DE: regPairs[" + rpDE + "],\n HL: regPairs[" + rpHL + "],\n AF_: regPairs[" + rpAF_ + "],\n BC_: regPairs[" + rpBC_ + "],\n DE_: regPairs[" + rpDE_ + "],\n HL_: regPairs[" + rpHL_ + "],\n IX: regPairs[" + rpIX + "],\n IY: regPairs[" + rpIY + "],\n SP: regPairs[" + rpSP + "],\n PC: regPairs[" + rpPC + "],\n IR: regPairs[" + rpIR + "],\n iff1: iff1,\n iff2: iff2,\n im: im,\n halted: halted,\n T: tstates,\n intp: interruptPending,\n intd: interruptDataBus,\n };\n };\n\n /* Register / flag accessors (used for tape trapping and test harness) */\n self.getAF = function() {\n return regPairs[" + rpAF + "];\n }\n self.getBC = function() {\n return regPairs[" + rpBC + "];\n }\n self.getDE = function() {\n return regPairs[" + rpDE + "];\n }\n self.getHL = function() {\n return regPairs[" + rpHL + "];\n }\n self.getAF_ = function() {\n return regPairs[" + rpAF_ + "];\n }\n self.getBC_ = function() {\n return regPairs[" + rpBC_ + "];\n }\n self.getDE_ = function() {\n return regPairs[" + rpDE_ + "];\n }\n self.getHL_ = function() {\n return regPairs[" + rpHL_ + "];\n }\n self.getIX = function() {\n return regPairs[" + rpIX + "];\n }\n self.getIY = function() {\n return regPairs[" + rpIY + "];\n }\n self.getI = function() {\n return regs[" + rI + "];\n }\n self.getR = function() {\n return regs[" + rR + "];\n }\n self.getSP = function() {\n return regPairs[" + rpSP + "];\n }\n self.getPC = function() {\n return regPairs[" + rpPC + "];\n }\n self.getIFF1 = function() {\n return iff1;\n }\n self.getIFF2 = function() {\n return iff2;\n }\n self.getIM = function() {\n return im;\n }\n self.getHalted = function() {\n return halted;\n }\n\n self.setAF = function(val) {\n regPairs[" + rpAF + "] = val;\n }\n self.setBC = function(val) {\n regPairs[" + rpBC + "] = val;\n }\n self.setDE = function(val) {\n regPairs[" + rpDE + "] = val;\n }\n self.setHL = function(val) {\n regPairs[" + rpHL + "] = val;\n }\n self.setAF_ = function(val) {\n regPairs[" + rpAF_ + "] = val;\n }\n self.setBC_ = function(val) {\n regPairs[" + rpBC_ + "] = val;\n }\n self.setDE_ = function(val) {\n regPairs[" + rpDE_ + "] = val;\n }\n self.setHL_ = function(val) {\n regPairs[" + rpHL_ + "] = val;\n }\n self.setIX = function(val) {\n regPairs[" + rpIX + "] = val;\n }\n self.setIY = function(val) {\n regPairs[" + rpIY + "] = val;\n }\n self.setI = function(val) {\n regs[" + rI + "] = val;\n }\n self.setR = function(val) {\n regs[" + rR + "] = val;\n }\n self.setSP = function(val) {\n regPairs[" + rpSP + "] = val;\n }\n self.setPC = function(val) {\n regPairs[" + rpPC + "] = val;\n }\n self.setIFF1 = function(val) {\n iff1 = val & 1;\n }\n self.setIFF2 = function(val) {\n iff2 = val & 1;\n }\n self.setIM = function(val) {\n im = val & 1;\n }\n self.setHalted = function(val) {\n halted = !!val;\n }\n\n self.getTstates = function() {\n return tstates;\n }\n self.setTstates = function(val) {\n tstates = val * 1;\n }\n\n self.getCarry_ = function() {\n return regs[" + rF_ + "] & " + FLAG_C + ";\n };\n self.setCarry = function(val) {\n if (val) {\n regs[" + rF + "] |= " + FLAG_C + ";\n } else {\n regs[" + rF + "] &= " + (~FLAG_C) + ";\n }\n };\n self.getA_ = function() {\n return regs[" + rA_ + "];\n };\n self.retryInterrupts = false;\n return self;\n};"; defineZ80JS = defineZ80JS.replace(/READMEM\((.*?)\)/g, '(CONTEND_READ($1, 3), memory.read($1))'); defineZ80JS = defineZ80JS.replace(/WRITEMEM\((.*?),(.*?)\)/g, "CONTEND_WRITE($1, 3);\nwhile (display.nextEventTime != null && display.nextEventTime < tstates) display.doEvent();\nmemory.write($1,$2);"); if (opts.applyContention) { defineZ80JS = defineZ80JS.replace(/CONTEND_READ\((.*?),(.*?)\)/g, '(tstates += memory.contend($1, tstates) + ($2))'); defineZ80JS = defineZ80JS.replace(/CONTEND_WRITE\((.*?),(.*?)\)/g, '(tstates += memory.contend($1, tstates) + ($2))'); defineZ80JS = defineZ80JS.replace(/CONTEND_READ_NO_MREQ\((.*?),(.*?)\)/g, '(tstates += memory.contend($1, tstates) + ($2))'); defineZ80JS = defineZ80JS.replace(/CONTEND_WRITE_NO_MREQ\((.*?),(.*?)\)/g, '(tstates += memory.contend($1, tstates) + ($2))'); defineZ80JS = defineZ80JS.replace(/CONTEND_PORT_EARLY\((.*?)\)/g, "var isContendedMemory = memory.isContended($1);\nvar isULAPort = ioBus.isULAPort($1);\nif (isContendedMemory) tstates += ioBus.contend($1, tstates);\ntstates += 1;\nwhile (display.nextEventTime != null && display.nextEventTime < tstates) display.doEvent();"); defineZ80JS = defineZ80JS.replace(/CONTEND_PORT_LATE\((.*?)\)/g, "if (isContendedMemory || isULAPort) {\n ioBus.contend($1);\n tstates += 1;\n if (!isULAPort) {\n ioBus.contend($1); tstates += 1;\n ioBus.contend($1); tstates += 1;\n } else {\n tstates += 2;\n }\n} else {\n tstates += 3;\n}"); } else { defineZ80JS = defineZ80JS.replace(/CONTEND_READ\((.*?),(.*?)\)/g, 'tstates += ($2)'); defineZ80JS = defineZ80JS.replace(/CONTEND_WRITE\((.*?),(.*?)\)/g, 'tstates += ($2)'); defineZ80JS = defineZ80JS.replace(/CONTEND_READ_NO_MREQ\((.*?),(.*?)\)/g, 'tstates += ($2)'); defineZ80JS = defineZ80JS.replace(/CONTEND_WRITE_NO_MREQ\((.*?),(.*?)\)/g, 'tstates += ($2)'); defineZ80JS = defineZ80JS.replace(/CONTEND_PORT_EARLY\((.*?)\)/g, 'tstates += 1'); defineZ80JS = defineZ80JS.replace(/CONTEND_PORT_LATE\((.*?)\)/g, 'tstates += 3'); } indirectEval = eval; return indirectEval(defineZ80JS); }; }).call(this);