mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-10-01 04:56:14 +00:00
1748 lines
86 KiB
TypeScript
1748 lines
86 KiB
TypeScript
|
// Generated by CoffeeScript 1.9.3
|
||
|
|
||
|
import { CPU, Bus, InstructionBased, IOBusConnected, SavesState, Interruptable } from "../devices";
|
||
|
|
||
|
/*
|
||
|
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)
|
||
|
*/
|
||
|
|
||
|
var 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 = "this._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 +
|
||
|
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);
|
||
|
};
|
||
|
|
||
|
export interface Z80State {
|
||
|
AF,BC,DE,HL,AF_,BC_,DE_,HL_,IX,IY,SP,PC,IR : number;
|
||
|
iff1,iff2,im,halted : number;
|
||
|
T,intp,intd : number;
|
||
|
}
|
||
|
|
||
|
export class Z80 implements CPU, InstructionBased, IOBusConnected, SavesState<Z80State>, Interruptable<number> {
|
||
|
|
||
|
cpu;
|
||
|
interruptType;
|
||
|
memBus : Bus;
|
||
|
ioBus : Bus;
|
||
|
|
||
|
private buildCPU(z80opts?) {
|
||
|
if (this.memBus && this.ioBus) {
|
||
|
this.cpu = buildZ80(z80opts||{})({
|
||
|
display: {},
|
||
|
memory: this.memBus,
|
||
|
ioBus: this.ioBus,
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
connectMemoryBus(bus:Bus) {
|
||
|
this.memBus = bus;
|
||
|
this.buildCPU();
|
||
|
}
|
||
|
connectIOBus(bus:Bus) {
|
||
|
this.ioBus = bus;
|
||
|
this.buildCPU();
|
||
|
}
|
||
|
advanceInsn() {
|
||
|
let t0 = this.cpu.getTstates();
|
||
|
this.cpu.runFrame(t0+1); //TODO
|
||
|
return this.cpu.getTstates() - t0;
|
||
|
}
|
||
|
reset() {
|
||
|
this.cpu.reset();
|
||
|
}
|
||
|
interrupt(itype:number) {
|
||
|
this.cpu.requestInterrupt(itype);
|
||
|
}
|
||
|
getSP() {
|
||
|
return this.cpu.getSP();
|
||
|
}
|
||
|
getPC() {
|
||
|
return this.cpu.getPC();
|
||
|
}
|
||
|
saveState() {
|
||
|
return this.cpu.saveState();
|
||
|
}
|
||
|
loadState(s) {
|
||
|
this.cpu.loadState(s);
|
||
|
}
|
||
|
// TODO: metadata
|
||
|
// TODO: disassembler
|
||
|
}
|