8bitworkshop/src/common/cpu/z80.js

1692 lines
85 KiB
JavaScript

// 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);