2017-01-14 02:31:04 +00:00
|
|
|
###
|
|
|
|
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)
|
|
|
|
###
|
|
|
|
|
|
|
|
window.buildZ80 = (opts) ->
|
|
|
|
opts ?= {}
|
|
|
|
endianTestBuffer = new ArrayBuffer(2)
|
|
|
|
endianTestUint16 = new Uint16Array(endianTestBuffer)
|
|
|
|
endianTestUint8 = new Uint8Array(endianTestBuffer)
|
|
|
|
endianTestUint16[0] = 0x0100
|
|
|
|
isBigEndian = (endianTestUint8[0] == 0x01)
|
|
|
|
|
|
|
|
# Offsets into register set when read as register pairs
|
|
|
|
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
|
|
|
|
# little-endian
|
|
|
|
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
|
|
|
|
|
|
|
|
# JS block setting up internal Z80 state and lookup tables
|
|
|
|
|
|
|
|
setUpStateJS = """
|
|
|
|
var memory = opts.memory;
|
|
|
|
var ioBus = opts.ioBus;
|
|
|
|
var display = opts.display;
|
|
|
|
|
|
|
|
var registerBuffer = new ArrayBuffer(26);
|
|
|
|
/* Expose registerBuffer as both register pairs and individual registers */
|
|
|
|
var regPairs = new Uint16Array(registerBuffer);
|
|
|
|
var regs = new Uint8Array(registerBuffer);
|
|
|
|
|
|
|
|
var tstates = 0; /* number of tstates since start of this frame */
|
|
|
|
var iff1 = 0;
|
|
|
|
var iff2 = 0;
|
|
|
|
var im = 0;
|
|
|
|
var halted = false;
|
|
|
|
|
|
|
|
/* tables for setting Z80 flags */
|
|
|
|
|
|
|
|
/*
|
|
|
|
Whether a half carry occurred or not can be determined by looking at
|
|
|
|
the 3rd bit of the two arguments and the result; these are hashed
|
|
|
|
into this table in the form r12, where r is the 3rd bit of the
|
|
|
|
result, 1 is the 3rd bit of the 1st argument and 2 is the
|
|
|
|
third bit of the 2nd argument; the tables differ for add and subtract
|
|
|
|
operations
|
|
|
|
*/
|
|
|
|
var halfcarryAddTable = new Uint8Array([0, #{FLAG_H}, #{FLAG_H}, #{FLAG_H}, 0, 0, 0, #{FLAG_H}]);
|
|
|
|
var halfcarrySubTable = new Uint8Array([0, 0, #{FLAG_H}, 0, #{FLAG_H}, 0, #{FLAG_H}, #{FLAG_H}]);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Similarly, overflow can be determined by looking at the 7th bits; again
|
|
|
|
the hash into this table is r12
|
|
|
|
*/
|
|
|
|
var overflowAddTable = new Uint8Array([0, 0, 0, #{FLAG_V}, #{FLAG_V}, 0, 0, 0]);
|
|
|
|
var overflowSubTable = new Uint8Array([0, #{FLAG_V}, 0, 0, 0, 0, #{FLAG_V}, 0]);
|
|
|
|
|
|
|
|
var sz53Table = new Uint8Array(0x100); /* The S, Z, 5 and 3 bits of the index */
|
|
|
|
var parityTable = new Uint8Array(0x100); /* The parity of the lookup value */
|
|
|
|
var sz53pTable = new Uint8Array(0x100); /* OR the above two tables together */
|
|
|
|
|
|
|
|
for (var i = 0; i < 0x100; i++) {
|
|
|
|
sz53Table[i] = i & ( #{FLAG_3 | FLAG_5 | FLAG_S} );
|
|
|
|
var j = i;
|
|
|
|
var parity = 0;
|
|
|
|
for (var k = 0; k < 8; k++) {
|
|
|
|
parity ^= j & 1;
|
|
|
|
j >>=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
parityTable[i] = (parity ? 0 : #{FLAG_P});
|
|
|
|
sz53pTable[i] = sz53Table[i] | parityTable[i];
|
|
|
|
|
|
|
|
sz53Table[0] |= #{FLAG_Z};
|
|
|
|
sz53pTable[0] |= #{FLAG_Z};
|
|
|
|
}
|
|
|
|
|
|
|
|
var interruptible = true;
|
|
|
|
var interruptPending = false;
|
|
|
|
var interruptDataBus = 0;
|
|
|
|
var 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 = (param, hasIXOffsetAlready = false) ->
|
|
|
|
if param.match(/^[AFBCDEHL]|I[XY][HL]$/)
|
|
|
|
regNum = registerIndexes[param]
|
|
|
|
{
|
|
|
|
'getter': ''
|
|
|
|
'v': "regs[#{regNum}]"
|
|
|
|
'trunc': ''
|
|
|
|
'setter': ''
|
|
|
|
}
|
|
|
|
else if param == '(HL)'
|
|
|
|
{
|
|
|
|
'getter': "var val = READMEM(regPairs[#{rpHL}]);"
|
|
|
|
'v': 'val'
|
|
|
|
'trunc': '& 0xff'
|
|
|
|
'setter': """
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpHL}], 1);
|
|
|
|
WRITEMEM(regPairs[#{rpHL}], val);
|
|
|
|
"""
|
|
|
|
}
|
|
|
|
else if param == 'nn'
|
|
|
|
{
|
|
|
|
'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}]);
|
|
|
|
if (offset & 0x80) offset -= 0x100;
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
"""
|
|
|
|
getter += """
|
|
|
|
var addr = (regPairs[#{rp}] + offset) & 0xffff;
|
|
|
|
var val = READMEM(addr);
|
|
|
|
"""
|
|
|
|
{
|
|
|
|
'getter': getter
|
|
|
|
'v': 'val'
|
|
|
|
'trunc': '& 0xff'
|
|
|
|
'setter': """
|
|
|
|
CONTEND_READ_NO_MREQ(addr, 1);
|
|
|
|
WRITEMEM(addr, val);
|
|
|
|
"""
|
|
|
|
}
|
|
|
|
else if param == 'add'
|
|
|
|
# special case for incorporating ADD/SUB into DAA calculation using a custom variable 'add'
|
|
|
|
{
|
|
|
|
'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 = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
|
|
|
|
var adctemp = regs[#{rA}] + #{operand.v} + (regs[#{rF}] & #{FLAG_C});
|
|
|
|
var lookup = ( (regs[#{rA}] & 0x88) >> 3 ) | ( (#{operand.v} & 0x88) >> 2 ) | ( (adctemp & 0x88) >> 1 );
|
|
|
|
regs[#{rA}] = adctemp;
|
|
|
|
regs[#{rF}] = ( adctemp & 0x100 ? #{FLAG_C} : 0 ) | halfcarryAddTable[lookup & 0x07] | overflowAddTable[lookup >> 4] | sz53Table[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
ADC_HL_RR = (rp2) ->
|
|
|
|
"""
|
|
|
|
var add16temp = regPairs[#{rpHL}] + regPairs[#{rp2}] + (regs[#{rF}] & #{FLAG_C});
|
|
|
|
var lookup = (
|
|
|
|
( (regPairs[#{rpHL}] & 0x8800) >> 11 ) |
|
|
|
|
( (regPairs[#{rp2}] & 0x8800) >> 10 ) |
|
|
|
|
( (add16temp & 0x8800) >> 9 )
|
|
|
|
);
|
|
|
|
regPairs[#{rpHL}] = add16temp;
|
|
|
|
regs[#{rF}] = (
|
|
|
|
(add16temp & 0x10000 ? #{FLAG_C} : 0) |
|
|
|
|
overflowAddTable[lookup >> 4] |
|
|
|
|
(regs[#{rH}] & #{FLAG_3 | FLAG_5 | FLAG_S}) |
|
|
|
|
halfcarryAddTable[lookup & 0x07] |
|
|
|
|
(regPairs[#{rpHL}] ? 0 : #{FLAG_Z})
|
|
|
|
);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
"""
|
|
|
|
|
|
|
|
ADD_A = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
|
|
|
|
var addtemp = regs[#{rA}] + #{operand.v};
|
|
|
|
var lookup = ( (regs[#{rA}] & 0x88) >> 3 ) | ( (#{operand.v} & 0x88) >> 2 ) | ( (addtemp & 0x88) >> 1 );
|
|
|
|
regs[#{rA}] = addtemp;
|
|
|
|
regs[#{rF}] = ( addtemp & 0x100 ? #{FLAG_C} : 0 ) | halfcarryAddTable[lookup & 0x07] | overflowAddTable[lookup >> 4] | sz53Table[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
ADD_RR_RR = (rp1, rp2) ->
|
|
|
|
"""
|
|
|
|
var add16temp = regPairs[#{rp1}] + regPairs[#{rp2}];
|
|
|
|
var lookup = ( (regPairs[#{rp1}] & 0x0800) >> 11 ) | ( (regPairs[#{rp2}] & 0x0800) >> 10 ) | ( (add16temp & 0x0800) >> 9 );
|
|
|
|
regPairs[#{rp1}] = add16temp;
|
|
|
|
regs[#{rF}] = ( regs[#{rF}] & ( #{FLAG_V | FLAG_Z | FLAG_S} ) ) | ( add16temp & 0x10000 ? #{FLAG_C} : 0 ) | ( ( add16temp >> 8 ) & ( #{FLAG_3 | FLAG_5} ) ) | halfcarryAddTable[lookup];
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
"""
|
|
|
|
|
|
|
|
AND_A = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
|
|
|
|
regs[#{rA}] &= #{operand.v};
|
|
|
|
regs[#{rF}] = #{FLAG_H} | sz53pTable[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
BIT_N_iRRpNNi = (bit, rp) -> # requires 'offset'
|
|
|
|
if bit == 7
|
|
|
|
updateSignFlag = "if (value & 0x80) regs[#{rF}] |= #{FLAG_S};"
|
|
|
|
else
|
|
|
|
updateSignFlag = ""
|
|
|
|
|
|
|
|
"""
|
|
|
|
var addr = (regPairs[#{rp}] + offset) & 0xffff;
|
|
|
|
var value = READMEM(addr);
|
|
|
|
regs[#{rF}] = ( regs[#{rF}] & #{FLAG_C} ) | #{FLAG_H} | ( ( addr >> 8 ) & #{FLAG_3 | FLAG_5} );
|
|
|
|
if ( !(value & #{0x01 << bit}) ) regs[#{rF}] |= #{FLAG_P | FLAG_Z};
|
|
|
|
#{updateSignFlag}
|
|
|
|
CONTEND_READ_NO_MREQ(addr, 1);
|
|
|
|
"""
|
|
|
|
|
|
|
|
BIT_N_iHLi = (bit) ->
|
|
|
|
if bit == 7
|
|
|
|
updateSignFlag = "if (value & 0x80) regs[#{rF}] |= #{FLAG_S};"
|
|
|
|
else
|
|
|
|
updateSignFlag = ""
|
|
|
|
|
|
|
|
"""
|
|
|
|
var addr = regPairs[#{rpHL}];
|
|
|
|
var value = READMEM(addr);
|
|
|
|
CONTEND_READ_NO_MREQ(addr, 1);
|
|
|
|
regs[#{rF}] = ( regs[#{rF}] & #{FLAG_C} ) | #{FLAG_H} | ( value & #{FLAG_3 | FLAG_5} );
|
|
|
|
if( !(value & #{0x01 << bit}) ) regs[#{rF}] |= #{FLAG_P | FLAG_Z};
|
|
|
|
#{updateSignFlag}
|
|
|
|
"""
|
|
|
|
|
|
|
|
BIT_N_R = (bit, r) ->
|
|
|
|
if bit == 7
|
|
|
|
updateSignFlag = "if (regs[#{r}] & 0x80) regs[#{rF}] |= #{FLAG_S};"
|
|
|
|
else
|
|
|
|
updateSignFlag = ""
|
|
|
|
"""
|
|
|
|
regs[#{rF}] = ( regs[#{rF}] & #{FLAG_C} ) | #{FLAG_H} | ( regs[#{r}] & #{FLAG_3 | FLAG_5} );
|
|
|
|
if( !(regs[#{r}] & #{0x01 << bit}) ) regs[#{rF}] |= #{FLAG_P | FLAG_Z};
|
|
|
|
#{updateSignFlag}
|
|
|
|
"""
|
|
|
|
|
|
|
|
CALL_C_NN = (flag, sense) ->
|
|
|
|
condition = "regs[#{rF}] & #{flag}"
|
|
|
|
condition = "!(#{condition})" if not sense
|
|
|
|
"""
|
|
|
|
if (#{condition}) {
|
|
|
|
var l = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rpPC}] >> 8);
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rpPC}] & 0xff);
|
|
|
|
regPairs[#{rpPC}] = (h<<8) | l;
|
|
|
|
} else {
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 3);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 3);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
CALL_NN = () ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rpPC}] >> 8);
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rpPC}] & 0xff);
|
|
|
|
regPairs[#{rpPC}] = (h<<8) | l;
|
|
|
|
"""
|
|
|
|
|
|
|
|
CCF = () ->
|
|
|
|
"""
|
|
|
|
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 = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
|
|
|
|
var cptemp = regs[#{rA}] - #{operand.v};
|
|
|
|
var lookup = ( (regs[#{rA}] & 0x88) >> 3 ) | ( (#{operand.v} & 0x88) >> 2 ) | ( (cptemp & 0x88) >> 1 );
|
|
|
|
regs[#{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 = (modifier) ->
|
|
|
|
"""
|
|
|
|
var value = READMEM(regPairs[#{rpHL}]);
|
|
|
|
var bytetemp = (regs[#{rA}] - value) & 0xff;
|
|
|
|
var lookup = ((regs[#{rA}] & 0x08) >> 3) | ((value & 0x08) >> 2) | ((bytetemp & 0x08) >> 1);
|
|
|
|
var originalHL = regPairs[#{rpHL}];
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
regPairs[#{rpHL}]#{modifier}; regPairs[#{rpBC}]--;
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C}) | (regPairs[#{rpBC}] ? #{FLAG_V | FLAG_N} : #{FLAG_N}) | halfcarrySubTable[lookup] | (bytetemp ? 0 : #{FLAG_Z}) | (bytetemp & #{FLAG_S});
|
|
|
|
if (regs[#{rF}] & #{FLAG_H}) bytetemp--;
|
|
|
|
regs[#{rF}] |= (bytetemp & #{FLAG_3}) | ( (bytetemp & 0x02) ? #{FLAG_5} : 0 );
|
|
|
|
"""
|
|
|
|
|
|
|
|
CPIR_CPDR = (modifier) ->
|
|
|
|
"""
|
|
|
|
#{CPI_CPD(modifier)}
|
|
|
|
if ((regs[#{rF}] & #{FLAG_V | FLAG_Z}) == #{FLAG_V}) {
|
|
|
|
regPairs[#{rpPC}] -= 2;
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalHL, 1);
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
CPD = () ->
|
|
|
|
CPI_CPD('--')
|
|
|
|
|
|
|
|
CPI = () ->
|
|
|
|
CPI_CPD('++')
|
|
|
|
|
|
|
|
CPDR = () ->
|
|
|
|
CPIR_CPDR('--')
|
|
|
|
|
|
|
|
CPIR = () ->
|
|
|
|
CPIR_CPDR('++')
|
|
|
|
|
|
|
|
|
|
|
|
DAA = () ->
|
|
|
|
subClause = SUB_A('add')
|
|
|
|
addClause = ADD_A('add')
|
|
|
|
"""
|
|
|
|
var add = 0;
|
|
|
|
var carry = regs[#{rF}] & #{FLAG_C};
|
|
|
|
if( ( regs[#{rF}] & #{FLAG_H} ) || ( ( regs[#{rA}] & 0x0f ) > 9 ) ) add = 6;
|
|
|
|
if( carry || ( regs[#{rA}] > 0x99 ) ) add |= 0x60;
|
|
|
|
if( regs[#{rA}] > 0x99 ) carry = #{FLAG_C};
|
|
|
|
if( regs[#{rF}] & #{FLAG_N} ) {
|
|
|
|
#{subClause}
|
|
|
|
} else {
|
|
|
|
#{addClause}
|
|
|
|
}
|
|
|
|
regs[#{rF}] = ( regs[#{rF}] & #{~( FLAG_C | FLAG_P )} ) | carry | parityTable[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
CPL = () ->
|
|
|
|
"""
|
|
|
|
regs[#{rA}] ^= 0xff;
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C | FLAG_P | FLAG_Z | FLAG_S}) | (regs[#{rA}] & #{FLAG_3 | FLAG_5}) | #{FLAG_N | FLAG_H};
|
|
|
|
"""
|
|
|
|
|
|
|
|
DEC = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C} ) | ( #{operand.v} & 0x0f ? 0 : #{FLAG_H} ) | #{FLAG_N};
|
|
|
|
#{operand.v} = (#{operand.v} - 1) #{operand.trunc};
|
|
|
|
|
|
|
|
#{operand.setter}
|
|
|
|
regs[#{rF}] |= (#{operand.v} == 0x7f ? #{FLAG_V} : 0) | sz53Table[#{operand.v}];
|
|
|
|
"""
|
|
|
|
|
|
|
|
DEC_RR = (rp) ->
|
|
|
|
"""
|
|
|
|
regPairs[#{rp}]--;
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
"""
|
|
|
|
|
|
|
|
DI = () ->
|
|
|
|
"""
|
|
|
|
iff1 = iff2 = 0;
|
|
|
|
"""
|
|
|
|
|
|
|
|
DJNZ_N = () ->
|
|
|
|
"""
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
regs[#{rB}]--;
|
|
|
|
if (regs[#{rB}]) {
|
|
|
|
/* take branch */
|
|
|
|
var offset = READMEM(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
regPairs[#{rpPC}] += (offset & 0x80 ? offset - 0x100 : offset);
|
|
|
|
} else {
|
|
|
|
/* do not take branch */
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 3);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
EI = () ->
|
|
|
|
"""
|
|
|
|
iff1 = iff2 = 1;
|
|
|
|
interruptible = false;
|
|
|
|
"""
|
|
|
|
|
|
|
|
EX_iSPi_RR = (rp) ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpSP}]);
|
|
|
|
var spPlus1 = (regPairs[#{rpSP}] + 1) & 0xffff;
|
|
|
|
var h = READMEM(spPlus1);
|
|
|
|
CONTEND_READ_NO_MREQ(spPlus1, 1);
|
|
|
|
WRITEMEM(spPlus1, regPairs[#{rp}] >> 8);
|
|
|
|
WRITEMEM(regPairs[#{rpSP}], regPairs[#{rp}] & 0xff);
|
|
|
|
regPairs[#{rp}] = (h<<8) | l;
|
|
|
|
CONTEND_WRITE_NO_MREQ(regPairs[#{rpSP}], 1);
|
|
|
|
CONTEND_WRITE_NO_MREQ(regPairs[#{rpSP}], 1);
|
|
|
|
"""
|
|
|
|
|
|
|
|
EX_RR_RR = (rp1, rp2) ->
|
|
|
|
"""
|
|
|
|
var temp = regPairs[#{rp1}];
|
|
|
|
regPairs[#{rp1}] = regPairs[#{rp2}];
|
|
|
|
regPairs[#{rp2}] = temp;
|
|
|
|
"""
|
|
|
|
|
|
|
|
EXX = () ->
|
|
|
|
"""
|
|
|
|
var wordtemp;
|
|
|
|
wordtemp = regPairs[#{rpBC}]; regPairs[#{rpBC}] = regPairs[#{rpBC_}]; regPairs[#{rpBC_}] = wordtemp;
|
|
|
|
wordtemp = regPairs[#{rpDE}]; regPairs[#{rpDE}] = regPairs[#{rpDE_}]; regPairs[#{rpDE_}] = wordtemp;
|
|
|
|
wordtemp = regPairs[#{rpHL}]; regPairs[#{rpHL}] = regPairs[#{rpHL_}]; regPairs[#{rpHL_}] = wordtemp;
|
|
|
|
"""
|
|
|
|
|
|
|
|
HALT = () ->
|
|
|
|
"""
|
|
|
|
halted = true;
|
|
|
|
regPairs[#{rpPC}]--;
|
|
|
|
"""
|
|
|
|
|
|
|
|
IM = (val) ->
|
|
|
|
"""
|
|
|
|
im = #{val};
|
|
|
|
"""
|
|
|
|
|
|
|
|
IN_A_N = () ->
|
|
|
|
"""
|
|
|
|
var val = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var port = (regs[#{rA}] << 8) | val;
|
|
|
|
CONTEND_PORT_EARLY(port);
|
|
|
|
regs[#{rA}] = ioBus.read(port);
|
|
|
|
CONTEND_PORT_LATE(port);
|
|
|
|
"""
|
|
|
|
|
|
|
|
IN_F_iCi = () ->
|
|
|
|
# as IN_R_iCi, but result is written to a local variable rather than a register
|
|
|
|
"""
|
|
|
|
var port = regPairs[#{rpBC}];
|
|
|
|
CONTEND_PORT_EARLY(port);
|
|
|
|
var result = ioBus.read(port);
|
|
|
|
CONTEND_PORT_LATE(port);
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C}) | sz53pTable[result];
|
|
|
|
"""
|
|
|
|
|
|
|
|
IN_R_iCi = (r) ->
|
|
|
|
"""
|
|
|
|
var port = regPairs[#{rpBC}];
|
|
|
|
CONTEND_PORT_EARLY(port);
|
|
|
|
regs[#{r}] = ioBus.read(port);
|
|
|
|
CONTEND_PORT_LATE(port);
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C}) | sz53pTable[regs[#{r}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
INC = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C}) | (#{operand.v} & 0x0f ? 0 : #{FLAG_H}) | #{FLAG_N};
|
|
|
|
#{operand.v} = (#{operand.v} + 1) #{operand.trunc};
|
|
|
|
|
|
|
|
#{operand.setter}
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C}) | ( #{operand.v} == 0x80 ? #{FLAG_V} : 0 ) | ( #{operand.v} & 0x0f ? 0 : #{FLAG_H} ) | sz53Table[#{operand.v}];
|
|
|
|
"""
|
|
|
|
|
|
|
|
INC_RR = (rp) ->
|
|
|
|
"""
|
|
|
|
regPairs[#{rp}]++;
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
"""
|
|
|
|
|
|
|
|
INI_IND = (modifier) ->
|
|
|
|
"""
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_PORT_EARLY(regPairs[#{rpBC}]);
|
|
|
|
var initemp = ioBus.read(regPairs[#{rpBC}]);
|
|
|
|
CONTEND_PORT_LATE(regPairs[#{rpBC}]);
|
|
|
|
WRITEMEM(regPairs[#{rpHL}], initemp);
|
|
|
|
regs[#{rB}]--;
|
|
|
|
var originalHL = regPairs[#{rpHL}];
|
|
|
|
regPairs[#{rpHL}]#{modifier}#{modifier};
|
|
|
|
var initemp2 = (initemp + regs[#{rC}] #{modifier} 1) & 0xff;
|
|
|
|
|
|
|
|
regs[#{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 = (modifier) ->
|
|
|
|
"""
|
|
|
|
#{INI_IND(modifier)}
|
|
|
|
if (regs[#{rB}]) {
|
|
|
|
CONTEND_WRITE_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_WRITE_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_WRITE_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_WRITE_NO_MREQ(originalHL, 1);
|
|
|
|
CONTEND_WRITE_NO_MREQ(originalHL, 1);
|
|
|
|
regPairs[#{rpPC}] -= 2;
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
INI = () ->
|
|
|
|
INI_IND('+')
|
|
|
|
|
|
|
|
IND = () ->
|
|
|
|
INI_IND('-')
|
|
|
|
|
|
|
|
INIR = () ->
|
|
|
|
INIR_INDR('+')
|
|
|
|
|
|
|
|
INDR = () ->
|
|
|
|
INIR_INDR('-')
|
|
|
|
|
|
|
|
JP_C_NN = (flag, sense) ->
|
|
|
|
condition = "regs[#{rF}] & #{flag}"
|
|
|
|
condition = "!(#{condition})" if not sense
|
|
|
|
"""
|
|
|
|
if (#{condition}) {
|
|
|
|
var l = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
regPairs[#{rpPC}] = (h<<8) | l;
|
|
|
|
} else {
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 3);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 3);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
JP_RR = (rp) ->
|
|
|
|
"""
|
|
|
|
regPairs[#{rpPC}] = regPairs[#{rp}];
|
|
|
|
"""
|
|
|
|
|
|
|
|
JP_NN = () ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
regPairs[#{rpPC}] = (h<<8) | l;
|
|
|
|
"""
|
|
|
|
|
|
|
|
JR_C_N = (flag, sense) ->
|
|
|
|
condition = "regs[#{rF}] & #{flag}"
|
|
|
|
condition = "!(#{condition})" if not sense
|
|
|
|
"""
|
|
|
|
if (#{condition}) {
|
|
|
|
var offset = READMEM(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
regPairs[#{rpPC}] += (offset & 0x80 ? offset - 0x100 : offset);
|
|
|
|
} else {
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 3);
|
|
|
|
regPairs[#{rpPC}]++; /* skip past offset byte */
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
JR_N = () ->
|
|
|
|
"""
|
|
|
|
var offset = READMEM(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
regPairs[#{rpPC}] += (offset & 0x80 ? offset - 0x100 : offset);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_A_iNNi = () ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var addr = (h<<8) | l;
|
|
|
|
regs[#{rA}] = READMEM(addr);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_iNNi_A = () ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var addr = (h<<8) | l;
|
|
|
|
WRITEMEM(addr, regs[#{rA}]);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_iNNi_RR = (rp) ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var addr = (h<<8) | l;
|
|
|
|
WRITEMEM(addr, regPairs[#{rp}] & 0xff);
|
|
|
|
addr = (addr + 1) & 0xffff;
|
|
|
|
WRITEMEM(addr, regPairs[#{rp}] >> 8);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_iRRi_N = (rp) ->
|
|
|
|
"""
|
|
|
|
var n = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
WRITEMEM(regPairs[#{rp}], n);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_iRRi_R = (rp, r) ->
|
|
|
|
"""
|
|
|
|
WRITEMEM(regPairs[#{rp}], regs[#{r}]);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_iRRpNNi_N = (rp) ->
|
|
|
|
"""
|
|
|
|
var offset = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
if (offset & 0x80) offset -= 0x100;
|
|
|
|
var addr = (regPairs[#{rp}] + offset) & 0xffff;
|
|
|
|
|
|
|
|
var val = READMEM(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
WRITEMEM(addr, val);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_iRRpNNi_R = (rp, r) ->
|
|
|
|
"""
|
|
|
|
var offset = READMEM(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
if (offset & 0x80) offset -= 0x100;
|
|
|
|
var addr = (regPairs[#{rp}] + offset) & 0xffff;
|
|
|
|
|
|
|
|
WRITEMEM(addr, regs[#{r}]);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_R_iRRi = (r, rp) ->
|
|
|
|
"""
|
|
|
|
regs[#{r}] = READMEM(regPairs[#{rp}]);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_R_iRRpNNi = (r, rp) ->
|
|
|
|
"""
|
|
|
|
var offset = READMEM(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
if (offset & 0x80) offset -= 0x100;
|
|
|
|
var addr = (regPairs[#{rp}] + offset) & 0xffff;
|
|
|
|
|
|
|
|
regs[#{r}] = READMEM(addr);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_R_N = (r) ->
|
|
|
|
"""
|
|
|
|
regs[#{r}] = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_R_R = (r1, r2) ->
|
|
|
|
if r1 == rI || r2 == rI || r1 == rR || r2 == rR
|
|
|
|
output = """
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
regs[#{r1}] = regs[#{r2}];
|
|
|
|
"""
|
|
|
|
if (r1 == rA)
|
|
|
|
output += """
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C}) | sz53Table[regs[#{rA}]] | ( iff2 ? #{FLAG_V} : 0 );
|
|
|
|
"""
|
|
|
|
output
|
|
|
|
else
|
|
|
|
"""
|
|
|
|
regs[#{r1}] = regs[#{r2}];
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_RR_iNNi = (rp, shifted) ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var addr = (h<<8) | l;
|
|
|
|
l = READMEM(addr);
|
|
|
|
addr = (addr + 1) & 0xffff;
|
|
|
|
h = READMEM(addr);
|
|
|
|
regPairs[#{rp}] = (h<<8) | l;
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_RR_NN = (rp) ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
regPairs[#{rp}] = (h<<8) | l;
|
|
|
|
"""
|
|
|
|
|
|
|
|
LD_RR_RR = (rp1, rp2) ->
|
|
|
|
# only used for LD SP,HL/IX/IY
|
|
|
|
"""
|
|
|
|
regPairs[#{rp1}] = regPairs[#{rp2}];
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LDBITOP = (regName, opcode, bit, rp) ->
|
|
|
|
# load (rp+nn) into register regName, perform opcode, write back to (rp+nn)
|
|
|
|
regNum = registerIndexes[regName]
|
|
|
|
"""
|
|
|
|
var addr = (regPairs[#{rp}] + offset) & 0xffff;
|
|
|
|
regs[#{regNum}] = READMEM(addr);
|
|
|
|
#{opcode(bit, regName)}
|
|
|
|
CONTEND_READ_NO_MREQ(addr, 1);
|
|
|
|
WRITEMEM(addr, regs[#{regNum}]);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LDI_LDD = (modifier) ->
|
|
|
|
"""
|
|
|
|
var bytetemp = READMEM(regPairs[#{rpHL}]);
|
|
|
|
regPairs[#{rpBC}]--;
|
|
|
|
WRITEMEM(regPairs[#{rpDE}],bytetemp);
|
|
|
|
var originalDE = regPairs[#{rpDE}];
|
|
|
|
regPairs[#{rpDE}]#{modifier}; regPairs[#{rpHL}]#{modifier};
|
|
|
|
bytetemp = (bytetemp + regs[#{rA}]) & 0xff;
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C | FLAG_Z | FLAG_S}) | (regPairs[#{rpBC}] ? #{FLAG_V} : 0) | (bytetemp & #{FLAG_3}) | ((bytetemp & 0x02) ? #{FLAG_5} : 0);
|
|
|
|
CONTEND_READ_NO_MREQ(originalDE, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalDE, 1);
|
|
|
|
"""
|
|
|
|
|
|
|
|
LDIR_LDDR = (modifier) ->
|
|
|
|
"""
|
|
|
|
#{LDI_LDD(modifier)}
|
|
|
|
if (regPairs[#{rpBC}]) {
|
|
|
|
regPairs[#{rpPC}]-=2;
|
|
|
|
CONTEND_READ_NO_MREQ(originalDE, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalDE, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalDE, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalDE, 1);
|
|
|
|
CONTEND_READ_NO_MREQ(originalDE, 1);
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
LDI = () ->
|
|
|
|
LDI_LDD('++')
|
|
|
|
|
|
|
|
LDD = () ->
|
|
|
|
LDI_LDD('--')
|
|
|
|
|
|
|
|
LDIR = () ->
|
|
|
|
LDIR_LDDR('++')
|
|
|
|
|
|
|
|
LDDR = () ->
|
|
|
|
LDIR_LDDR('--')
|
|
|
|
|
|
|
|
LDSHIFTOP = (regName, opcode, rp) ->
|
|
|
|
# load (rp+nn) into register regName, perform opcode, write back to (rp+nn)
|
|
|
|
regNum = registerIndexes[regName]
|
|
|
|
"""
|
|
|
|
var addr = (regPairs[#{rp}] + offset) & 0xffff;
|
|
|
|
regs[#{regNum}] = READMEM(addr);
|
|
|
|
#{opcode(regName)}
|
|
|
|
CONTEND_READ_NO_MREQ(addr, 1);
|
|
|
|
WRITEMEM(addr, regs[#{regNum}]);
|
|
|
|
"""
|
|
|
|
|
|
|
|
NEG = () ->
|
|
|
|
"""
|
|
|
|
var val = regs[#{rA}];
|
|
|
|
var subtemp = -val;
|
|
|
|
var lookup = ( (val & 0x88) >> 2 ) | ( (subtemp & 0x88) >> 1 );
|
|
|
|
regs[#{rA}] = subtemp;
|
|
|
|
regs[#{rF}] = ( subtemp & 0x100 ? #{FLAG_C} : 0 ) | #{FLAG_N} | halfcarrySubTable[lookup & 0x07] | overflowSubTable[lookup >> 4] | sz53Table[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
NOP = () ->
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
|
|
|
|
OR_A = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
|
|
|
|
regs[#{rA}] |= #{operand.v};
|
|
|
|
regs[#{rF}] = sz53pTable[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
OUT_iCi_0 = (r) ->
|
|
|
|
"""
|
|
|
|
CONTEND_PORT_EARLY(regPairs[#{rpBC}]);
|
|
|
|
ioBus.write(regPairs[#{rpBC}], 0, tstates);
|
|
|
|
CONTEND_PORT_LATE(regPairs[#{rpBC}]);
|
|
|
|
"""
|
|
|
|
|
|
|
|
OUT_iCi_R = (r) ->
|
|
|
|
"""
|
|
|
|
CONTEND_PORT_EARLY(regPairs[#{rpBC}]);
|
|
|
|
ioBus.write(regPairs[#{rpBC}], regs[#{r}], tstates);
|
|
|
|
CONTEND_PORT_LATE(regPairs[#{rpBC}]);
|
|
|
|
"""
|
|
|
|
|
|
|
|
OUT_iNi_A = () ->
|
|
|
|
"""
|
|
|
|
var port = (regs[#{rA}] << 8) | READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
CONTEND_PORT_EARLY(port);
|
|
|
|
ioBus.write(port, regs[#{rA}], tstates);
|
|
|
|
CONTEND_PORT_LATE(port);
|
|
|
|
"""
|
|
|
|
|
|
|
|
OUTI_OUTD = (modifier) ->
|
|
|
|
"""
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
var outitemp = READMEM(regPairs[#{rpHL}]);
|
|
|
|
regs[#{rB}]--; /* This does happen first, despite what the specs say */
|
|
|
|
CONTEND_PORT_EARLY(regPairs[#{rpBC}]);
|
|
|
|
ioBus.write(regPairs[#{rpBC}], outitemp, tstates);
|
|
|
|
CONTEND_PORT_LATE(regPairs[#{rpBC}]);
|
|
|
|
|
|
|
|
regPairs[#{rpHL}]#{modifier};
|
|
|
|
outitemp2 = (outitemp + regs[#{rL}]) & 0xff;
|
|
|
|
regs[#{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 = (modifier) ->
|
|
|
|
"""
|
|
|
|
#{OUTI_OUTD(modifier)}
|
|
|
|
if (regs[#{rB}]) {
|
|
|
|
regPairs[#{rpPC}]-=2;
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpBC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpBC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpBC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpBC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpBC}], 1);
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
OUTD = () ->
|
|
|
|
OUTI_OUTD('--');
|
|
|
|
|
|
|
|
OUTI = () ->
|
|
|
|
OUTI_OUTD('++');
|
|
|
|
|
|
|
|
OTDR = () ->
|
|
|
|
OTIR_OTDR('--');
|
|
|
|
|
|
|
|
OTIR = () ->
|
|
|
|
OTIR_OTDR('++');
|
|
|
|
|
|
|
|
POP_RR = (rp) ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpSP}]); regPairs[#{rpSP}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpSP}]); regPairs[#{rpSP}]++;
|
|
|
|
regPairs[#{rp}] = (h<<8) | l;
|
|
|
|
"""
|
|
|
|
|
|
|
|
PUSH_RR = (rp) ->
|
|
|
|
"""
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rp}] >> 8);
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rp}] & 0xff);
|
|
|
|
"""
|
|
|
|
|
|
|
|
RES = (bit, param) ->
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
hexMask = 0xff ^ (1 << bit)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
#{operand.v} &= #{hexMask};
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
RET = () ->
|
|
|
|
"""
|
|
|
|
var l = READMEM(regPairs[#{rpSP}]); regPairs[#{rpSP}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpSP}]); regPairs[#{rpSP}]++;
|
|
|
|
regPairs[#{rpPC}] = (h<<8) | l;
|
|
|
|
"""
|
|
|
|
|
|
|
|
RET_C = (flag, sense) ->
|
|
|
|
condition = "regs[#{rF}] & #{flag}"
|
|
|
|
condition = "!(#{condition})" if not sense
|
|
|
|
"""
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
if (#{condition}) {
|
|
|
|
var l = READMEM(regPairs[#{rpSP}]); regPairs[#{rpSP}]++;
|
|
|
|
var h = READMEM(regPairs[#{rpSP}]); regPairs[#{rpSP}]++;
|
|
|
|
regPairs[#{rpPC}] = (h<<8) | l;
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
RETN = () ->
|
|
|
|
"""
|
|
|
|
iff1 = iff2;
|
|
|
|
#{RET()}
|
|
|
|
"""
|
|
|
|
|
|
|
|
RL = (param) ->
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
var rltemp = #{operand.v};
|
|
|
|
#{operand.v} = ( (#{operand.v} << 1) | (regs[#{rF}] & #{FLAG_C}) ) #{operand.trunc};
|
|
|
|
regs[#{rF}] = ( rltemp >> 7 ) | sz53pTable[#{operand.v}];
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
RLA = () ->
|
|
|
|
"""
|
|
|
|
var bytetemp = regs[#{rA}];
|
|
|
|
regs[#{rA}] = (regs[#{rA}] << 1) | (regs[#{rF}] & #{FLAG_C});
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_P | FLAG_Z | FLAG_S}) | (regs[#{rA}] & #{FLAG_3 | FLAG_5}) | (bytetemp >> 7);
|
|
|
|
"""
|
|
|
|
|
|
|
|
RLC = (param) ->
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
#{operand.v} = ( (#{operand.v} << 1) | (#{operand.v} >> 7) ) #{operand.trunc};
|
|
|
|
regs[#{rF}] = (#{operand.v} & #{FLAG_C}) | sz53pTable[#{operand.v}];
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
RLD = () ->
|
|
|
|
"""
|
|
|
|
var bytetemp = READMEM(regPairs[#{rpHL}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpHL}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpHL}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpHL}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpHL}], 1);
|
|
|
|
var val = (bytetemp << 4) | (regs[#{rA}] & 0x0f);
|
|
|
|
WRITEMEM(regPairs[#{rpHL}], val);
|
|
|
|
regs[#{rA}] = (regs[#{rA}] & 0xf0) | (bytetemp >> 4);
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C}) | sz53pTable[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
RLCA = () ->
|
|
|
|
"""
|
|
|
|
regs[#{rA}] = (regs[#{rA}] << 1) | (regs[#{rA}] >> 7);
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_P | FLAG_Z | FLAG_S}) | (regs[#{rA}] & #{FLAG_C | FLAG_3 | FLAG_5});
|
|
|
|
"""
|
|
|
|
|
|
|
|
RR = (param) ->
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
var rrtemp = #{operand.v};
|
|
|
|
#{operand.v} = ( (#{operand.v} >> 1) | ( regs[#{rF}] << 7 ) ) #{operand.trunc};
|
|
|
|
regs[#{rF}] = (rrtemp & #{FLAG_C}) | sz53pTable[#{operand.v}];
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
RRA = () ->
|
|
|
|
"""
|
|
|
|
var bytetemp = regs[#{rA}];
|
|
|
|
regs[#{rA}] = (bytetemp >> 1) | (regs[#{rF}] << 7);
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_P | FLAG_Z | FLAG_S}) | (regs[#{rA}] & #{FLAG_3 | FLAG_5}) | (bytetemp & #{FLAG_C});
|
|
|
|
"""
|
|
|
|
|
|
|
|
RRC = (param) ->
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
regs[#{rF}] = #{operand.v} & #{FLAG_C};
|
|
|
|
#{operand.v} = ( (#{operand.v} >> 1) | (#{operand.v} << 7) ) #{operand.trunc};
|
|
|
|
regs[#{rF}] |= sz53pTable[#{operand.v}];
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
RRCA = () ->
|
|
|
|
"""
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_P | FLAG_Z | FLAG_S}) | (regs[#{rA}] & #{FLAG_C});
|
|
|
|
regs[#{rA}] = (regs[#{rA}] >> 1) | (regs[#{rA}] << 7);
|
|
|
|
regs[#{rF}] |= (regs[#{rA}] & #{FLAG_3 | FLAG_5});
|
|
|
|
"""
|
|
|
|
|
|
|
|
RRD = () ->
|
|
|
|
"""
|
|
|
|
var bytetemp = READMEM(regPairs[#{rpHL}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpHL}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpHL}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpHL}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpHL}], 1);
|
|
|
|
var val = (regs[#{rA}] << 4) | (bytetemp >> 4);
|
|
|
|
WRITEMEM(regPairs[#{rpHL}], val);
|
|
|
|
regs[#{rA}] = (regs[#{rA}] & 0xf0) | (bytetemp & 0x0f);
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_C}) | sz53pTable[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
RST = (addr) ->
|
|
|
|
"""
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rpPC}] >> 8);
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rpPC}] & 0xff);
|
|
|
|
regPairs[#{rpPC}] = #{addr};
|
|
|
|
"""
|
|
|
|
|
|
|
|
SBC_A = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
var sbctemp = regs[#{rA}] - #{operand.v} - (regs[#{rF}] & #{FLAG_C});
|
|
|
|
var lookup = ( (regs[#{rA}] & 0x88) >> 3 ) | ( (#{operand.v} & 0x88) >> 2 ) | ( (sbctemp & 0x88) >> 1 );
|
|
|
|
regs[#{rA}] = sbctemp;
|
|
|
|
regs[#{rF}] = ( sbctemp & 0x100 ? #{FLAG_C} : 0 ) | #{FLAG_N} | halfcarrySubTable[lookup & 0x07] | overflowSubTable[lookup >> 4] | sz53Table[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
SBC_HL_RR = (rp) ->
|
|
|
|
"""
|
|
|
|
var sub16temp = regPairs[#{rpHL}] - regPairs[#{rp}] - (regs[#{rF}] & #{FLAG_C});
|
|
|
|
var lookup = ( (regPairs[#{rpHL}] & 0x8800) >> 11 ) | ( (regPairs[#{rp}] & 0x8800) >> 10 ) | ( (sub16temp & 0x8800) >> 9 );
|
|
|
|
regPairs[#{rpHL}] = sub16temp;
|
|
|
|
regs[#{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});
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpIR}], 1);
|
|
|
|
"""
|
|
|
|
|
|
|
|
SCF = () ->
|
|
|
|
"""
|
|
|
|
regs[#{rF}] = (regs[#{rF}] & #{FLAG_P | FLAG_Z | FLAG_S}) | (regs[#{rA}] & #{FLAG_3 | FLAG_5}) | #{FLAG_C};
|
|
|
|
"""
|
|
|
|
|
|
|
|
SET = (bit, param) ->
|
|
|
|
hexMask = 1 << bit
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
#{operand.v} |= #{hexMask};
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
SHIFT = (prefix) ->
|
|
|
|
# Fake instruction for shifted opcodes - passes control to a secondary opcode table
|
|
|
|
"""
|
|
|
|
opcodePrefix = '#{prefix}';
|
|
|
|
interruptible = false;
|
|
|
|
"""
|
|
|
|
|
|
|
|
SLA = (param) ->
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
regs[#{rF}] = #{operand.v} >> 7;
|
|
|
|
#{operand.v} = (#{operand.v} << 1) #{operand.trunc};
|
|
|
|
regs[#{rF}] |= sz53pTable[#{operand.v}];
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
SLL = (param) ->
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
regs[#{rF}] = #{operand.v} >> 7;
|
|
|
|
#{operand.v} = (((#{operand.v}) << 1) #{operand.trunc}) | 0x01;
|
|
|
|
regs[#{rF}] |= sz53pTable[#{operand.v}];
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
SRA = (param) ->
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
regs[#{rF}] = #{operand.v} & #{FLAG_C};
|
|
|
|
#{operand.v} = ( (#{operand.v} & 0x80) | (#{operand.v} >> 1) ) #{operand.trunc};
|
|
|
|
regs[#{rF}] |= sz53pTable[#{operand.v}];
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
SRL = (param) ->
|
|
|
|
operand = getParamBoilerplate(param, true)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
regs[#{rF}] = #{operand.v} & #{FLAG_C};
|
|
|
|
#{operand.v} >>= 1;
|
|
|
|
regs[#{rF}] |= sz53pTable[#{operand.v}];
|
|
|
|
#{operand.setter}
|
|
|
|
"""
|
|
|
|
|
|
|
|
SUB_A = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
var subtemp = regs[#{rA}] - #{operand.v};
|
|
|
|
var lookup = ( (regs[#{rA}] & 0x88) >> 3 ) | ( (#{operand.v} & 0x88) >> 2 ) | ( (subtemp & 0x88) >> 1 );
|
|
|
|
regs[#{rA}] = subtemp;
|
|
|
|
regs[#{rF}] = ( subtemp & 0x100 ? #{FLAG_C} : 0 ) | #{FLAG_N} | halfcarrySubTable[lookup & 0x07] | overflowSubTable[lookup >> 4] | sz53Table[regs[#{rA}]];
|
|
|
|
"""
|
|
|
|
|
|
|
|
XOR_A = (param) ->
|
|
|
|
operand = getParamBoilerplate(param)
|
|
|
|
"""
|
|
|
|
#{operand.getter}
|
|
|
|
regs[#{rA}] ^= #{operand.v};
|
|
|
|
regs[#{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 = (runStringTable, fallbackTable = {}, traps = []) ->
|
|
|
|
clauses = []
|
|
|
|
for i in [0...0x100]
|
|
|
|
runString = runStringTable[i]
|
|
|
|
if not runString?
|
|
|
|
runString = fallbackTable[i]
|
|
|
|
if runString?
|
|
|
|
relevantTraps = ([address, action] for [address, opcode, action] in traps when opcode == i)
|
|
|
|
trapCode = (
|
|
|
|
"if (regPairs[#{rpPC}] == #{(address + 1) & 0xffff} && !(#{action})) break;" for [address, action] in relevantTraps
|
|
|
|
)
|
|
|
|
clauses.push """
|
|
|
|
case #{i}:
|
|
|
|
#{trapCode.join("\n")}
|
|
|
|
#{runString}
|
|
|
|
break;
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
switch (opcode) {
|
|
|
|
#{clauses.join('')}
|
|
|
|
default:
|
|
|
|
var addr = regPairs[#{rpPC}] - 1;
|
|
|
|
throw("Unimplemented opcode " + opcode + " in page #{runStringTable[0x100]} - PC = " + addr);
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Tables mapping opcodes to Javascript snippets
|
|
|
|
OPCODE_RUN_STRINGS_CB = {
|
|
|
|
0x00: RLC "B" # RLC B
|
|
|
|
0x01: RLC "C" # RLC C
|
|
|
|
0x02: RLC "D" # RLC D
|
|
|
|
0x03: RLC "E" # RLC E
|
|
|
|
0x04: RLC "H" # RLC H
|
|
|
|
0x05: RLC "L" # RLC L
|
|
|
|
0x06: RLC "(HL)" # RLC (HL)
|
|
|
|
0x07: RLC "A" # RLC A
|
|
|
|
0x08: RRC "B" # RRC B
|
|
|
|
0x09: RRC "C" # RRC C
|
|
|
|
0x0a: RRC "D" # RRC D
|
|
|
|
0x0b: RRC "E" # RRC E
|
|
|
|
0x0c: RRC "H" # RRC H
|
|
|
|
0x0d: RRC "L" # RRC L
|
|
|
|
0x0e: RRC "(HL)" # RRC (HL)
|
|
|
|
0x0f: RRC "A" # RRC A
|
|
|
|
0x10: RL 'B' # RL B
|
|
|
|
0x11: RL 'C' # RL C
|
|
|
|
0x12: RL 'D' # RL D
|
|
|
|
0x13: RL 'E' # RL E
|
|
|
|
0x14: RL 'H' # RL H
|
|
|
|
0x15: RL 'L' # RL L
|
|
|
|
0x16: RL '(HL)' # RL (HL)
|
|
|
|
0x17: RL 'A' # RL A
|
|
|
|
0x18: RR 'B' # RR B
|
|
|
|
0x19: RR 'C' # RR C
|
|
|
|
0x1a: RR 'D' # RR D
|
|
|
|
0x1b: RR 'E' # RR E
|
|
|
|
0x1c: RR 'H' # RR H
|
|
|
|
0x1d: RR 'L' # RR L
|
|
|
|
0x1e: RR '(HL)' # RR (HL)
|
|
|
|
0x1f: RR 'A' # RR A
|
|
|
|
0x20: SLA 'B' # SLA B
|
|
|
|
0x21: SLA 'C' # SLA C
|
|
|
|
0x22: SLA 'D' # SLA D
|
|
|
|
0x23: SLA 'E' # SLA E
|
|
|
|
0x24: SLA 'H' # SLA H
|
|
|
|
0x25: SLA 'L' # SLA L
|
|
|
|
0x26: SLA '(HL)' # SLA (HL)
|
|
|
|
0x27: SLA 'A' # SLA A
|
|
|
|
0x28: SRA 'B' # SRA B
|
|
|
|
0x29: SRA 'C' # SRA C
|
|
|
|
0x2a: SRA 'D' # SRA D
|
|
|
|
0x2b: SRA 'E' # SRA E
|
|
|
|
0x2c: SRA 'H' # SRA H
|
|
|
|
0x2d: SRA 'L' # SRA L
|
|
|
|
0x2e: SRA '(HL)' # SRA (HL)
|
|
|
|
0x2f: SRA 'A' # SRA A
|
|
|
|
0x30: SLL 'B' # SLL B
|
|
|
|
0x31: SLL 'C' # SLL C
|
|
|
|
0x32: SLL 'D' # SLL D
|
|
|
|
0x33: SLL 'E' # SLL E
|
|
|
|
0x34: SLL 'H' # SLL H
|
|
|
|
0x35: SLL 'L' # SLL L
|
|
|
|
0x36: SLL '(HL)' # SLL (HL)
|
|
|
|
0x37: SLL 'A' # SLL A
|
|
|
|
0x38: SRL 'B' # SRL B
|
|
|
|
0x39: SRL 'C' # SRL C
|
|
|
|
0x3a: SRL 'D' # SRL D
|
|
|
|
0x3b: SRL 'E' # SRL E
|
|
|
|
0x3c: SRL 'H' # SRL H
|
|
|
|
0x3d: SRL 'L' # SRL L
|
|
|
|
0x3e: SRL '(HL)' # SRL (HL)
|
|
|
|
0x3f: SRL 'A' # SRL A
|
|
|
|
0x40: BIT_N_R(0, rB) # BIT 0,B
|
|
|
|
0x41: BIT_N_R(0, rC) # BIT 0,C
|
|
|
|
0x42: BIT_N_R(0, rD) # BIT 0,D
|
|
|
|
0x43: BIT_N_R(0, rE) # BIT 0,E
|
|
|
|
0x44: BIT_N_R(0, rH) # BIT 0,H
|
|
|
|
0x45: BIT_N_R(0, rL) # BIT 0,L
|
|
|
|
0x46: BIT_N_iHLi(0) # BIT 0,(HL)
|
|
|
|
0x47: BIT_N_R(0, rA) # BIT 0,A
|
|
|
|
0x48: BIT_N_R(1, rB) # BIT 1,B
|
|
|
|
0x49: BIT_N_R(1, rC) # BIT 1,C
|
|
|
|
0x4A: BIT_N_R(1, rD) # BIT 1,D
|
|
|
|
0x4B: BIT_N_R(1, rE) # BIT 1,E
|
|
|
|
0x4C: BIT_N_R(1, rH) # BIT 1,H
|
|
|
|
0x4D: BIT_N_R(1, rL) # BIT 1,L
|
|
|
|
0x4E: BIT_N_iHLi(1) # BIT 1,(HL)
|
|
|
|
0x4F: BIT_N_R(1, rA) # BIT 1,A
|
|
|
|
0x50: BIT_N_R(2, rB) # BIT 2,B
|
|
|
|
0x51: BIT_N_R(2, rC) # BIT 2,C
|
|
|
|
0x52: BIT_N_R(2, rD) # BIT 2,D
|
|
|
|
0x53: BIT_N_R(2, rE) # BIT 2,E
|
|
|
|
0x54: BIT_N_R(2, rH) # BIT 2,H
|
|
|
|
0x55: BIT_N_R(2, rL) # BIT 2,L
|
|
|
|
0x56: BIT_N_iHLi(2) # BIT 2,(HL)
|
|
|
|
0x57: BIT_N_R(2, rA) # BIT 2,A
|
|
|
|
0x58: BIT_N_R(3, rB) # BIT 3,B
|
|
|
|
0x59: BIT_N_R(3, rC) # BIT 3,C
|
|
|
|
0x5A: BIT_N_R(3, rD) # BIT 3,D
|
|
|
|
0x5B: BIT_N_R(3, rE) # BIT 3,E
|
|
|
|
0x5C: BIT_N_R(3, rH) # BIT 3,H
|
|
|
|
0x5D: BIT_N_R(3, rL) # BIT 3,L
|
|
|
|
0x5E: BIT_N_iHLi(3) # BIT 3,(HL)
|
|
|
|
0x5F: BIT_N_R(3, rA) # BIT 3,A
|
|
|
|
0x60: BIT_N_R(4, rB) # BIT 4,B
|
|
|
|
0x61: BIT_N_R(4, rC) # BIT 4,C
|
|
|
|
0x62: BIT_N_R(4, rD) # BIT 4,D
|
|
|
|
0x63: BIT_N_R(4, rE) # BIT 4,E
|
|
|
|
0x64: BIT_N_R(4, rH) # BIT 4,H
|
|
|
|
0x65: BIT_N_R(4, rL) # BIT 4,L
|
|
|
|
0x66: BIT_N_iHLi(4) # BIT 4,(HL)
|
|
|
|
0x67: BIT_N_R(4, rA) # BIT 4,A
|
|
|
|
0x68: BIT_N_R(5, rB) # BIT 5,B
|
|
|
|
0x69: BIT_N_R(5, rC) # BIT 5,C
|
|
|
|
0x6A: BIT_N_R(5, rD) # BIT 5,D
|
|
|
|
0x6B: BIT_N_R(5, rE) # BIT 5,E
|
|
|
|
0x6C: BIT_N_R(5, rH) # BIT 5,H
|
|
|
|
0x6D: BIT_N_R(5, rL) # BIT 5,L
|
|
|
|
0x6E: BIT_N_iHLi(5) # BIT 5,(HL)
|
|
|
|
0x6F: BIT_N_R(5, rA) # BIT 5,A
|
|
|
|
0x70: BIT_N_R(6, rB) # BIT 6,B
|
|
|
|
0x71: BIT_N_R(6, rC) # BIT 6,C
|
|
|
|
0x72: BIT_N_R(6, rD) # BIT 6,D
|
|
|
|
0x73: BIT_N_R(6, rE) # BIT 6,E
|
|
|
|
0x74: BIT_N_R(6, rH) # BIT 6,H
|
|
|
|
0x75: BIT_N_R(6, rL) # BIT 6,L
|
|
|
|
0x76: BIT_N_iHLi(6) # BIT 6,(HL)
|
|
|
|
0x77: BIT_N_R(6, rA) # BIT 6,A
|
|
|
|
0x78: BIT_N_R(7, rB) # BIT 7,B
|
|
|
|
0x79: BIT_N_R(7, rC) # BIT 7,C
|
|
|
|
0x7A: BIT_N_R(7, rD) # BIT 7,D
|
|
|
|
0x7B: BIT_N_R(7, rE) # BIT 7,E
|
|
|
|
0x7C: BIT_N_R(7, rH) # BIT 7,H
|
|
|
|
0x7D: BIT_N_R(7, rL) # BIT 7,L
|
|
|
|
0x7E: BIT_N_iHLi(7) # BIT 7,(HL)
|
|
|
|
0x7F: BIT_N_R(7, rA) # BIT 7,A
|
|
|
|
0x80: RES 0, 'B' # RES 0,B
|
|
|
|
0x81: RES 0, 'C' # RES 0,C
|
|
|
|
0x82: RES 0, 'D' # RES 0,D
|
|
|
|
0x83: RES 0, 'E' # RES 0,E
|
|
|
|
0x84: RES 0, 'H' # RES 0,H
|
|
|
|
0x85: RES 0, 'L' # RES 0,L
|
|
|
|
0x86: RES 0, '(HL)' # RES 0,(HL)
|
|
|
|
0x87: RES 0, 'A' # RES 0,A
|
|
|
|
0x88: RES 1, 'B' # RES 1,B
|
|
|
|
0x89: RES 1, 'C' # RES 1,C
|
|
|
|
0x8A: RES 1, 'D' # RES 1,D
|
|
|
|
0x8B: RES 1, 'E' # RES 1,E
|
|
|
|
0x8C: RES 1, 'H' # RES 1,H
|
|
|
|
0x8D: RES 1, 'L' # RES 1,L
|
|
|
|
0x8E: RES 1, '(HL)' # RES 1,(HL)
|
|
|
|
0x8F: RES 1, 'A' # RES 1,A
|
|
|
|
0x90: RES 2, 'B' # RES 2,B
|
|
|
|
0x91: RES 2, 'C' # RES 2,C
|
|
|
|
0x92: RES 2, 'D' # RES 2,D
|
|
|
|
0x93: RES 2, 'E' # RES 2,E
|
|
|
|
0x94: RES 2, 'H' # RES 2,H
|
|
|
|
0x95: RES 2, 'L' # RES 2,L
|
|
|
|
0x96: RES 2, '(HL)' # RES 2,(HL)
|
|
|
|
0x97: RES 2, 'A' # RES 2,A
|
|
|
|
0x98: RES 3, 'B' # RES 3,B
|
|
|
|
0x99: RES 3, 'C' # RES 3,C
|
|
|
|
0x9A: RES 3, 'D' # RES 3,D
|
|
|
|
0x9B: RES 3, 'E' # RES 3,E
|
|
|
|
0x9C: RES 3, 'H' # RES 3,H
|
|
|
|
0x9D: RES 3, 'L' # RES 3,L
|
|
|
|
0x9E: RES 3, '(HL)' # RES 3,(HL)
|
|
|
|
0x9F: RES 3, 'A' # RES 3,A
|
|
|
|
0xA0: RES 4, 'B' # RES 4,B
|
|
|
|
0xA1: RES 4, 'C' # RES 4,C
|
|
|
|
0xA2: RES 4, 'D' # RES 4,D
|
|
|
|
0xA3: RES 4, 'E' # RES 4,E
|
|
|
|
0xA4: RES 4, 'H' # RES 4,H
|
|
|
|
0xA5: RES 4, 'L' # RES 4,L
|
|
|
|
0xA6: RES 4, '(HL)' # RES 4,(HL)
|
|
|
|
0xA7: RES 4, 'A' # RES 4,A
|
|
|
|
0xA8: RES 5, 'B' # RES 5,B
|
|
|
|
0xA9: RES 5, 'C' # RES 5,C
|
|
|
|
0xAA: RES 5, 'D' # RES 5,D
|
|
|
|
0xAB: RES 5, 'E' # RES 5,E
|
|
|
|
0xAC: RES 5, 'H' # RES 5,H
|
|
|
|
0xAD: RES 5, 'L' # RES 5,L
|
|
|
|
0xAE: RES 5, '(HL)' # RES 5,(HL)
|
|
|
|
0xAF: RES 5, 'A' # RES 5,A
|
|
|
|
0xB0: RES 6, 'B' # RES 6,B
|
|
|
|
0xB1: RES 6, 'C' # RES 6,C
|
|
|
|
0xB2: RES 6, 'D' # RES 6,D
|
|
|
|
0xB3: RES 6, 'E' # RES 6,E
|
|
|
|
0xB4: RES 6, 'H' # RES 6,H
|
|
|
|
0xB5: RES 6, 'L' # RES 6,L
|
|
|
|
0xB6: RES 6, '(HL)' # RES 6,(HL)
|
|
|
|
0xB7: RES 6, 'A' # RES 6,A
|
|
|
|
0xB8: RES 7, 'B' # RES 7,B
|
|
|
|
0xB9: RES 7, 'C' # RES 7,C
|
|
|
|
0xBA: RES 7, 'D' # RES 7,D
|
|
|
|
0xBB: RES 7, 'E' # RES 7,E
|
|
|
|
0xBC: RES 7, 'H' # RES 7,H
|
|
|
|
0xBD: RES 7, 'L' # RES 7,L
|
|
|
|
0xBE: RES 7, '(HL)' # RES 7,(HL)
|
|
|
|
0xBF: RES 7, 'A' # RES 7,A
|
|
|
|
0xC0: SET 0, 'B' # SET 0,B
|
|
|
|
0xC1: SET 0, 'C' # SET 0,C
|
|
|
|
0xC2: SET 0, 'D' # SET 0,D
|
|
|
|
0xC3: SET 0, 'E' # SET 0,E
|
|
|
|
0xC4: SET 0, 'H' # SET 0,H
|
|
|
|
0xC5: SET 0, 'L' # SET 0,L
|
|
|
|
0xC6: SET 0, '(HL)' # SET 0,(HL)
|
|
|
|
0xC7: SET 0, 'A' # SET 0,A
|
|
|
|
0xC8: SET 1, 'B' # SET 1,B
|
|
|
|
0xC9: SET 1, 'C' # SET 1,C
|
|
|
|
0xCA: SET 1, 'D' # SET 1,D
|
|
|
|
0xCB: SET 1, 'E' # SET 1,E
|
|
|
|
0xCC: SET 1, 'H' # SET 1,H
|
|
|
|
0xCD: SET 1, 'L' # SET 1,L
|
|
|
|
0xCE: SET 1, '(HL)' # SET 1,(HL)
|
|
|
|
0xCF: SET 1, 'A' # SET 1,A
|
|
|
|
0xD0: SET 2, 'B' # SET 2,B
|
|
|
|
0xD1: SET 2, 'C' # SET 2,C
|
|
|
|
0xD2: SET 2, 'D' # SET 2,D
|
|
|
|
0xD3: SET 2, 'E' # SET 2,E
|
|
|
|
0xD4: SET 2, 'H' # SET 2,H
|
|
|
|
0xD5: SET 2, 'L' # SET 2,L
|
|
|
|
0xD6: SET 2, '(HL)' # SET 2,(HL)
|
|
|
|
0xD7: SET 2, 'A' # SET 2,A
|
|
|
|
0xD8: SET 3, 'B' # SET 3,B
|
|
|
|
0xD9: SET 3, 'C' # SET 3,C
|
|
|
|
0xDA: SET 3, 'D' # SET 3,D
|
|
|
|
0xDB: SET 3, 'E' # SET 3,E
|
|
|
|
0xDC: SET 3, 'H' # SET 3,H
|
|
|
|
0xDD: SET 3, 'L' # SET 3,L
|
|
|
|
0xDE: SET 3, '(HL)' # SET 3,(HL)
|
|
|
|
0xDF: SET 3, 'A' # SET 3,A
|
|
|
|
0xE0: SET 4, 'B' # SET 4,B
|
|
|
|
0xE1: SET 4, 'C' # SET 4,C
|
|
|
|
0xE2: SET 4, 'D' # SET 4,D
|
|
|
|
0xE3: SET 4, 'E' # SET 4,E
|
|
|
|
0xE4: SET 4, 'H' # SET 4,H
|
|
|
|
0xE5: SET 4, 'L' # SET 4,L
|
|
|
|
0xE6: SET 4, '(HL)' # SET 4,(HL)
|
|
|
|
0xE7: SET 4, 'A' # SET 4,A
|
|
|
|
0xE8: SET 5, 'B' # SET 5,B
|
|
|
|
0xE9: SET 5, 'C' # SET 5,C
|
|
|
|
0xEA: SET 5, 'D' # SET 5,D
|
|
|
|
0xEB: SET 5, 'E' # SET 5,E
|
|
|
|
0xEC: SET 5, 'H' # SET 5,H
|
|
|
|
0xED: SET 5, 'L' # SET 5,L
|
|
|
|
0xEE: SET 5, '(HL)' # SET 5,(HL)
|
|
|
|
0xEF: SET 5, 'A' # SET 5,A
|
|
|
|
0xF0: SET 6, 'B' # SET 6,B
|
|
|
|
0xF1: SET 6, 'C' # SET 6,C
|
|
|
|
0xF2: SET 6, 'D' # SET 6,D
|
|
|
|
0xF3: SET 6, 'E' # SET 6,E
|
|
|
|
0xF4: SET 6, 'H' # SET 6,H
|
|
|
|
0xF5: SET 6, 'L' # SET 6,L
|
|
|
|
0xF6: SET 6, '(HL)' # SET 6,(HL)
|
|
|
|
0xF7: SET 6, 'A' # SET 6,A
|
|
|
|
0xF8: SET 7, 'B' # SET 7,B
|
|
|
|
0xF9: SET 7, 'C' # SET 7,C
|
|
|
|
0xFA: SET 7, 'D' # SET 7,D
|
|
|
|
0xFB: SET 7, 'E' # SET 7,E
|
|
|
|
0xFC: SET 7, 'H' # SET 7,H
|
|
|
|
0xFD: SET 7, 'L' # SET 7,L
|
|
|
|
0xFE: SET 7, '(HL)' # SET 7,(HL)
|
|
|
|
0xFF: SET 7, 'A' # SET 7,A
|
|
|
|
0x100: 'cb'
|
|
|
|
}
|
|
|
|
|
|
|
|
# Generate the opcode runner lookup table for either the DDCB or FDCB set
|
|
|
|
generateddfdcbOpcodeSet = (prefix) ->
|
|
|
|
if prefix == 'DDCB'
|
|
|
|
rp = rpIX
|
|
|
|
rh = rIXH
|
|
|
|
rl = rIXL
|
|
|
|
|
|
|
|
rpn = 'IX'
|
|
|
|
rhn = 'IXH'
|
|
|
|
rln = 'IXL'
|
|
|
|
else # prefix == 'FDCB'
|
|
|
|
rp = rpIY
|
|
|
|
rh = rIYH
|
|
|
|
rl = rIYL
|
|
|
|
|
|
|
|
rpn = 'IY'
|
|
|
|
rhn = 'IYH'
|
|
|
|
rln = 'IYL'
|
|
|
|
return {
|
|
|
|
0x00: LDSHIFTOP('B', RLC, rp) # LD B,RLC (REGISTER+dd)
|
|
|
|
0x01: LDSHIFTOP('C', RLC, rp) # LD C,RLC (REGISTER+dd)
|
|
|
|
0x02: LDSHIFTOP('D', RLC, rp) # LD D,RLC (REGISTER+dd)
|
|
|
|
0x03: LDSHIFTOP('E', RLC, rp) # LD E,RLC (REGISTER+dd)
|
|
|
|
0x04: LDSHIFTOP('H', RLC, rp) # LD H,RLC (REGISTER+dd)
|
|
|
|
0x05: LDSHIFTOP('L', RLC, rp) # LD L,RLC (REGISTER+dd)
|
|
|
|
0x06: RLC "(#{rpn}+nn)" # RLC (IX+nn)
|
|
|
|
0x07: LDSHIFTOP('A', RLC, rp) # LD A,RLC (REGISTER+dd)
|
|
|
|
0x08: LDSHIFTOP('B', RRC, rp) # LD B,RRC (REGISTER+dd)
|
|
|
|
0x09: LDSHIFTOP('C', RRC, rp) # LD C,RRC (REGISTER+dd)
|
|
|
|
0x0A: LDSHIFTOP('D', RRC, rp) # LD D,RRC (REGISTER+dd)
|
|
|
|
0x0B: LDSHIFTOP('E', RRC, rp) # LD E,RRC (REGISTER+dd)
|
|
|
|
0x0C: LDSHIFTOP('H', RRC, rp) # LD H,RRC (REGISTER+dd)
|
|
|
|
0x0D: LDSHIFTOP('L', RRC, rp) # LD L,RRC (REGISTER+dd)
|
|
|
|
0x0E: RRC "(#{rpn}+nn)" # RRC (IX+nn)
|
|
|
|
0x0F: LDSHIFTOP('A', RRC, rp) # LD A,RRC (REGISTER+dd)
|
|
|
|
0x10: LDSHIFTOP('B', RL, rp) # LD B,RL (REGISTER+dd)
|
|
|
|
0x11: LDSHIFTOP('C', RL, rp) # LD C,RL (REGISTER+dd)
|
|
|
|
0x12: LDSHIFTOP('D', RL, rp) # LD D,RL (REGISTER+dd)
|
|
|
|
0x13: LDSHIFTOP('E', RL, rp) # LD E,RL (REGISTER+dd)
|
|
|
|
0x14: LDSHIFTOP('H', RL, rp) # LD H,RL (REGISTER+dd)
|
|
|
|
0x15: LDSHIFTOP('L', RL, rp) # LD L,RL (REGISTER+dd)
|
|
|
|
0x16: RL "(#{rpn}+nn)" # RL (IX+nn)
|
|
|
|
0x17: LDSHIFTOP('A', RL, rp) # LD A,RL (REGISTER+dd)
|
|
|
|
0x18: LDSHIFTOP('B', RR, rp) # LD B,RR (REGISTER+dd)
|
|
|
|
0x19: LDSHIFTOP('C', RR, rp) # LD C,RR (REGISTER+dd)
|
|
|
|
0x1A: LDSHIFTOP('D', RR, rp) # LD D,RR (REGISTER+dd)
|
|
|
|
0x1B: LDSHIFTOP('E', RR, rp) # LD E,RR (REGISTER+dd)
|
|
|
|
0x1C: LDSHIFTOP('H', RR, rp) # LD H,RR (REGISTER+dd)
|
|
|
|
0x1D: LDSHIFTOP('L', RR, rp) # LD L,RR (REGISTER+dd)
|
|
|
|
0x1E: RR "(#{rpn}+nn)" # RR (IX+nn)
|
|
|
|
0x1F: LDSHIFTOP('A', RR, rp) # LD A,RR (REGISTER+dd)
|
|
|
|
0x20: LDSHIFTOP('B', SLA, rp) # LD B,SLA (REGISTER+dd)
|
|
|
|
0x21: LDSHIFTOP('C', SLA, rp) # LD C,SLA (REGISTER+dd)
|
|
|
|
0x22: LDSHIFTOP('D', SLA, rp) # LD D,SLA (REGISTER+dd)
|
|
|
|
0x23: LDSHIFTOP('E', SLA, rp) # LD E,SLA (REGISTER+dd)
|
|
|
|
0x24: LDSHIFTOP('H', SLA, rp) # LD H,SLA (REGISTER+dd)
|
|
|
|
0x25: LDSHIFTOP('L', SLA, rp) # LD L,SLA (REGISTER+dd)
|
|
|
|
0x26: SLA "(#{rpn}+nn)" # SLA (IX+nn)
|
|
|
|
0x27: LDSHIFTOP('A', SLA, rp) # LD A,SLA (REGISTER+dd)
|
|
|
|
0x28: LDSHIFTOP('B', SRA, rp) # LD B,SRA (REGISTER+dd)
|
|
|
|
0x29: LDSHIFTOP('C', SRA, rp) # LD C,SRA (REGISTER+dd)
|
|
|
|
0x2A: LDSHIFTOP('D', SRA, rp) # LD D,SRA (REGISTER+dd)
|
|
|
|
0x2B: LDSHIFTOP('E', SRA, rp) # LD E,SRA (REGISTER+dd)
|
|
|
|
0x2C: LDSHIFTOP('H', SRA, rp) # LD H,SRA (REGISTER+dd)
|
|
|
|
0x2D: LDSHIFTOP('L', SRA, rp) # LD L,SRA (REGISTER+dd)
|
|
|
|
0x2E: SRA "(#{rpn}+nn)" # SRA (IX+nn)
|
|
|
|
0x2F: LDSHIFTOP('A', SRA, rp) # LD A,SRA (REGISTER+dd)
|
|
|
|
0x30: LDSHIFTOP('B', SLL, rp) # LD B,SLL (REGISTER+dd)
|
|
|
|
0x31: LDSHIFTOP('C', SLL, rp) # LD C,SLL (REGISTER+dd)
|
|
|
|
0x32: LDSHIFTOP('D', SLL, rp) # LD D,SLL (REGISTER+dd)
|
|
|
|
0x33: LDSHIFTOP('E', SLL, rp) # LD E,SLL (REGISTER+dd)
|
|
|
|
0x34: LDSHIFTOP('H', SLL, rp) # LD H,SLL (REGISTER+dd)
|
|
|
|
0x35: LDSHIFTOP('L', SLL, rp) # LD L,SLL (REGISTER+dd)
|
|
|
|
0x36: SLL "(#{rpn}+nn)" # SLL (IX+nn)
|
|
|
|
0x37: LDSHIFTOP('A', SLL, rp) # LD A,SLL (REGISTER+dd)
|
|
|
|
0x38: LDSHIFTOP('B', SRL, rp) # LD B,SRL (REGISTER+dd)
|
|
|
|
0x39: LDSHIFTOP('C', SRL, rp) # LD C,SRL (REGISTER+dd)
|
|
|
|
0x3A: LDSHIFTOP('D', SRL, rp) # LD D,SRL (REGISTER+dd)
|
|
|
|
0x3B: LDSHIFTOP('E', SRL, rp) # LD E,SRL (REGISTER+dd)
|
|
|
|
0x3C: LDSHIFTOP('H', SRL, rp) # LD H,SRL (REGISTER+dd)
|
|
|
|
0x3D: LDSHIFTOP('L', SRL, rp) # LD L,SRL (REGISTER+dd)
|
|
|
|
0x3E: SRL "(#{rpn}+nn)" # SRL (IX+nn)
|
|
|
|
0x3F: LDSHIFTOP('A', SRL, rp) # LD A,SRL (REGISTER+dd)
|
|
|
|
0x40: BIT_N_iRRpNNi(0, rp) # BIT 0,(IX+nn)
|
|
|
|
0x41: BIT_N_iRRpNNi(0, rp) # BIT 0,(IX+nn)
|
|
|
|
0x42: BIT_N_iRRpNNi(0, rp) # BIT 0,(IX+nn)
|
|
|
|
0x43: BIT_N_iRRpNNi(0, rp) # BIT 0,(IX+nn)
|
|
|
|
0x44: BIT_N_iRRpNNi(0, rp) # BIT 0,(IX+nn)
|
|
|
|
0x45: BIT_N_iRRpNNi(0, rp) # BIT 0,(IX+nn)
|
|
|
|
0x46: BIT_N_iRRpNNi(0, rp) # BIT 0,(IX+nn)
|
|
|
|
0x47: BIT_N_iRRpNNi(0, rp) # BIT 0,(IX+nn)
|
|
|
|
0x48: BIT_N_iRRpNNi(1, rp) # BIT 1,(IX+nn)
|
|
|
|
0x49: BIT_N_iRRpNNi(1, rp) # BIT 1,(IX+nn)
|
|
|
|
0x4A: BIT_N_iRRpNNi(1, rp) # BIT 1,(IX+nn)
|
|
|
|
0x4B: BIT_N_iRRpNNi(1, rp) # BIT 1,(IX+nn)
|
|
|
|
0x4C: BIT_N_iRRpNNi(1, rp) # BIT 1,(IX+nn)
|
|
|
|
0x4D: BIT_N_iRRpNNi(1, rp) # BIT 1,(IX+nn)
|
|
|
|
0x4E: BIT_N_iRRpNNi(1, rp) # BIT 1,(IX+nn)
|
|
|
|
0x4F: BIT_N_iRRpNNi(1, rp) # BIT 1,(IX+nn)
|
|
|
|
0x50: BIT_N_iRRpNNi(2, rp) # BIT 2,(IX+nn)
|
|
|
|
0x51: BIT_N_iRRpNNi(2, rp) # BIT 2,(IX+nn)
|
|
|
|
0x52: BIT_N_iRRpNNi(2, rp) # BIT 2,(IX+nn)
|
|
|
|
0x53: BIT_N_iRRpNNi(2, rp) # BIT 2,(IX+nn)
|
|
|
|
0x54: BIT_N_iRRpNNi(2, rp) # BIT 2,(IX+nn)
|
|
|
|
0x55: BIT_N_iRRpNNi(2, rp) # BIT 2,(IX+nn)
|
|
|
|
0x56: BIT_N_iRRpNNi(2, rp) # BIT 2,(IX+nn)
|
|
|
|
0x57: BIT_N_iRRpNNi(2, rp) # BIT 2,(IX+nn)
|
|
|
|
0x58: BIT_N_iRRpNNi(3, rp) # BIT 3,(IX+nn)
|
|
|
|
0x59: BIT_N_iRRpNNi(3, rp) # BIT 3,(IX+nn)
|
|
|
|
0x5A: BIT_N_iRRpNNi(3, rp) # BIT 3,(IX+nn)
|
|
|
|
0x5B: BIT_N_iRRpNNi(3, rp) # BIT 3,(IX+nn)
|
|
|
|
0x5C: BIT_N_iRRpNNi(3, rp) # BIT 3,(IX+nn)
|
|
|
|
0x5D: BIT_N_iRRpNNi(3, rp) # BIT 3,(IX+nn)
|
|
|
|
0x5E: BIT_N_iRRpNNi(3, rp) # BIT 3,(IX+nn)
|
|
|
|
0x5F: BIT_N_iRRpNNi(3, rp) # BIT 3,(IX+nn)
|
|
|
|
0x60: BIT_N_iRRpNNi(4, rp) # BIT 4,(IX+nn)
|
|
|
|
0x61: BIT_N_iRRpNNi(4, rp) # BIT 4,(IX+nn)
|
|
|
|
0x62: BIT_N_iRRpNNi(4, rp) # BIT 4,(IX+nn)
|
|
|
|
0x63: BIT_N_iRRpNNi(4, rp) # BIT 4,(IX+nn)
|
|
|
|
0x64: BIT_N_iRRpNNi(4, rp) # BIT 4,(IX+nn)
|
|
|
|
0x65: BIT_N_iRRpNNi(4, rp) # BIT 4,(IX+nn)
|
|
|
|
0x66: BIT_N_iRRpNNi(4, rp) # BIT 4,(IX+nn)
|
|
|
|
0x67: BIT_N_iRRpNNi(4, rp) # BIT 4,(IX+nn)
|
|
|
|
0x68: BIT_N_iRRpNNi(5, rp) # BIT 5,(IX+nn)
|
|
|
|
0x69: BIT_N_iRRpNNi(5, rp) # BIT 5,(IX+nn)
|
|
|
|
0x6A: BIT_N_iRRpNNi(5, rp) # BIT 5,(IX+nn)
|
|
|
|
0x6B: BIT_N_iRRpNNi(5, rp) # BIT 5,(IX+nn)
|
|
|
|
0x6C: BIT_N_iRRpNNi(5, rp) # BIT 5,(IX+nn)
|
|
|
|
0x6D: BIT_N_iRRpNNi(5, rp) # BIT 5,(IX+nn)
|
|
|
|
0x6E: BIT_N_iRRpNNi(5, rp) # BIT 5,(IX+nn)
|
|
|
|
0x6F: BIT_N_iRRpNNi(5, rp) # BIT 5,(IX+nn)
|
|
|
|
0x70: BIT_N_iRRpNNi(6, rp) # BIT 6,(IX+nn)
|
|
|
|
0x71: BIT_N_iRRpNNi(6, rp) # BIT 6,(IX+nn)
|
|
|
|
0x72: BIT_N_iRRpNNi(6, rp) # BIT 6,(IX+nn)
|
|
|
|
0x73: BIT_N_iRRpNNi(6, rp) # BIT 6,(IX+nn)
|
|
|
|
0x74: BIT_N_iRRpNNi(6, rp) # BIT 6,(IX+nn)
|
|
|
|
0x75: BIT_N_iRRpNNi(6, rp) # BIT 6,(IX+nn)
|
|
|
|
0x76: BIT_N_iRRpNNi(6, rp) # BIT 6,(IX+nn)
|
|
|
|
0x77: BIT_N_iRRpNNi(6, rp) # BIT 6,(IX+nn)
|
|
|
|
0x78: BIT_N_iRRpNNi(7, rp) # BIT 7,(IX+nn)
|
|
|
|
0x79: BIT_N_iRRpNNi(7, rp) # BIT 7,(IX+nn)
|
|
|
|
0x7A: BIT_N_iRRpNNi(7, rp) # BIT 7,(IX+nn)
|
|
|
|
0x7B: BIT_N_iRRpNNi(7, rp) # BIT 7,(IX+nn)
|
|
|
|
0x7C: BIT_N_iRRpNNi(7, rp) # BIT 7,(IX+nn)
|
|
|
|
0x7D: BIT_N_iRRpNNi(7, rp) # BIT 7,(IX+nn)
|
|
|
|
0x7E: BIT_N_iRRpNNi(7, rp) # BIT 7,(IX+nn)
|
|
|
|
0x7F: BIT_N_iRRpNNi(7, rp) # BIT 7,(IX+nn)
|
|
|
|
0x80: LDBITOP('B', RES, 0, rp) # LD B,RES 0,(IX+dd)
|
|
|
|
0x81: LDBITOP('C', RES, 0, rp) # LD C,RES 0,(IX+dd)
|
|
|
|
0x82: LDBITOP('D', RES, 0, rp) # LD D,RES 0,(IX+dd)
|
|
|
|
0x83: LDBITOP('E', RES, 0, rp) # LD E,RES 0,(IX+dd)
|
|
|
|
0x84: LDBITOP('H', RES, 0, rp) # LD H,RES 0,(IX+dd)
|
|
|
|
0x85: LDBITOP('L', RES, 0, rp) # LD L,RES 0,(IX+dd)
|
|
|
|
0x86: RES 0, "(#{rpn}+nn)" # RES 0,(IX+nn)
|
|
|
|
0x87: LDBITOP('A', RES, 0, rp) # LD A,RES 0,(IX+dd)
|
|
|
|
0x88: LDBITOP('B', RES, 1, rp) # LD B,RES 1,(IX+dd)
|
|
|
|
0x89: LDBITOP('C', RES, 1, rp) # LD C,RES 1,(IX+dd)
|
|
|
|
0x8A: LDBITOP('D', RES, 1, rp) # LD D,RES 1,(IX+dd)
|
|
|
|
0x8B: LDBITOP('E', RES, 1, rp) # LD E,RES 1,(IX+dd)
|
|
|
|
0x8C: LDBITOP('H', RES, 1, rp) # LD H,RES 1,(IX+dd)
|
|
|
|
0x8D: LDBITOP('L', RES, 1, rp) # LD L,RES 1,(IX+dd)
|
|
|
|
0x8E: RES 1, "(#{rpn}+nn)" # RES 1,(IX+nn)
|
|
|
|
0x8F: LDBITOP('A', RES, 1, rp) # LD A,RES 1,(IX+dd)
|
|
|
|
0x90: LDBITOP('B', RES, 2, rp) # LD B,RES 2,(IX+dd)
|
|
|
|
0x91: LDBITOP('C', RES, 2, rp) # LD C,RES 2,(IX+dd)
|
|
|
|
0x92: LDBITOP('D', RES, 2, rp) # LD D,RES 2,(IX+dd)
|
|
|
|
0x93: LDBITOP('E', RES, 2, rp) # LD E,RES 2,(IX+dd)
|
|
|
|
0x94: LDBITOP('H', RES, 2, rp) # LD H,RES 2,(IX+dd)
|
|
|
|
0x95: LDBITOP('L', RES, 2, rp) # LD L,RES 2,(IX+dd)
|
|
|
|
0x96: RES 2, "(#{rpn}+nn)" # RES 2,(IX+nn)
|
|
|
|
0x97: LDBITOP('A', RES, 2, rp) # LD A,RES 2,(IX+dd)
|
|
|
|
0x98: LDBITOP('B', RES, 3, rp) # LD B,RES 3,(IX+dd)
|
|
|
|
0x99: LDBITOP('C', RES, 3, rp) # LD C,RES 3,(IX+dd)
|
|
|
|
0x9A: LDBITOP('D', RES, 3, rp) # LD D,RES 3,(IX+dd)
|
|
|
|
0x9B: LDBITOP('E', RES, 3, rp) # LD E,RES 3,(IX+dd)
|
|
|
|
0x9C: LDBITOP('H', RES, 3, rp) # LD H,RES 3,(IX+dd)
|
|
|
|
0x9D: LDBITOP('L', RES, 3, rp) # LD L,RES 3,(IX+dd)
|
|
|
|
0x9E: RES 3, "(#{rpn}+nn)" # RES 3,(IX+nn)
|
|
|
|
0x9F: LDBITOP('A', RES, 3, rp) # LD A,RES 3,(IX+dd)
|
|
|
|
0xA0: LDBITOP('B', RES, 4, rp) # LD B,RES 4,(IX+dd)
|
|
|
|
0xA1: LDBITOP('C', RES, 4, rp) # LD C,RES 4,(IX+dd)
|
|
|
|
0xA2: LDBITOP('D', RES, 4, rp) # LD D,RES 4,(IX+dd)
|
|
|
|
0xA3: LDBITOP('E', RES, 4, rp) # LD E,RES 4,(IX+dd)
|
|
|
|
0xA4: LDBITOP('H', RES, 4, rp) # LD H,RES 4,(IX+dd)
|
|
|
|
0xA5: LDBITOP('L', RES, 4, rp) # LD L,RES 4,(IX+dd)
|
|
|
|
0xA6: RES 4, "(#{rpn}+nn)" # RES 4,(IX+nn)
|
|
|
|
0xA7: LDBITOP('A', RES, 4, rp) # LD A,RES 4,(IX+dd)
|
|
|
|
0xA8: LDBITOP('B', RES, 5, rp) # LD B,RES 5,(IX+dd)
|
|
|
|
0xA9: LDBITOP('C', RES, 5, rp) # LD C,RES 5,(IX+dd)
|
|
|
|
0xAA: LDBITOP('D', RES, 5, rp) # LD D,RES 5,(IX+dd)
|
|
|
|
0xAB: LDBITOP('E', RES, 5, rp) # LD E,RES 5,(IX+dd)
|
|
|
|
0xAC: LDBITOP('H', RES, 5, rp) # LD H,RES 5,(IX+dd)
|
|
|
|
0xAD: LDBITOP('L', RES, 5, rp) # LD L,RES 5,(IX+dd)
|
|
|
|
0xAE: RES 5, "(#{rpn}+nn)" # RES 5,(IX+nn)
|
|
|
|
0xAF: LDBITOP('A', RES, 5, rp) # LD A,RES 5,(IX+dd)
|
|
|
|
0xB0: LDBITOP('B', RES, 6, rp) # LD B,RES 6,(IX+dd)
|
|
|
|
0xB1: LDBITOP('C', RES, 6, rp) # LD C,RES 6,(IX+dd)
|
|
|
|
0xB2: LDBITOP('D', RES, 6, rp) # LD D,RES 6,(IX+dd)
|
|
|
|
0xB3: LDBITOP('E', RES, 6, rp) # LD E,RES 6,(IX+dd)
|
|
|
|
0xB4: LDBITOP('H', RES, 6, rp) # LD H,RES 6,(IX+dd)
|
|
|
|
0xB5: LDBITOP('L', RES, 6, rp) # LD L,RES 6,(IX+dd)
|
|
|
|
0xB6: RES 6, "(#{rpn}+nn)" # RES 6,(IX+nn)
|
|
|
|
0xB7: LDBITOP('A', RES, 6, rp) # LD A,RES 6,(IX+dd)
|
|
|
|
0xB8: LDBITOP('B', RES, 7, rp) # LD B,RES 7,(IX+dd)
|
|
|
|
0xB9: LDBITOP('C', RES, 7, rp) # LD C,RES 7,(IX+dd)
|
|
|
|
0xBA: LDBITOP('D', RES, 7, rp) # LD D,RES 7,(IX+dd)
|
|
|
|
0xBB: LDBITOP('E', RES, 7, rp) # LD E,RES 7,(IX+dd)
|
|
|
|
0xBC: LDBITOP('H', RES, 7, rp) # LD H,RES 7,(IX+dd)
|
|
|
|
0xBD: LDBITOP('L', RES, 7, rp) # LD L,RES 7,(IX+dd)
|
|
|
|
0xBE: RES 7, "(#{rpn}+nn)" # RES 7,(IX+nn)
|
|
|
|
0xBF: LDBITOP('A', RES, 7, rp) # LD A,RES 7,(IX+dd)
|
|
|
|
0xC0: LDBITOP('B', SET, 0, rp) # LD B,SET 0,(IX+dd)
|
|
|
|
0xC1: LDBITOP('C', SET, 0, rp) # LD C,SET 0,(IX+dd)
|
|
|
|
0xC2: LDBITOP('D', SET, 0, rp) # LD D,SET 0,(IX+dd)
|
|
|
|
0xC3: LDBITOP('E', SET, 0, rp) # LD E,SET 0,(IX+dd)
|
|
|
|
0xC4: LDBITOP('H', SET, 0, rp) # LD H,SET 0,(IX+dd)
|
|
|
|
0xC5: LDBITOP('L', SET, 0, rp) # LD L,SET 0,(IX+dd)
|
|
|
|
0xC6: SET 0, "(#{rpn}+nn)" # SET 0,(IX+nn)
|
|
|
|
0xC7: LDBITOP('A', SET, 0, rp) # LD A,SET 0,(IX+dd)
|
|
|
|
0xC8: LDBITOP('B', SET, 1, rp) # LD B,SET 1,(IX+dd)
|
|
|
|
0xC9: LDBITOP('C', SET, 1, rp) # LD C,SET 1,(IX+dd)
|
|
|
|
0xCA: LDBITOP('D', SET, 1, rp) # LD D,SET 1,(IX+dd)
|
|
|
|
0xCB: LDBITOP('E', SET, 1, rp) # LD E,SET 1,(IX+dd)
|
|
|
|
0xCC: LDBITOP('H', SET, 1, rp) # LD H,SET 1,(IX+dd)
|
|
|
|
0xCD: LDBITOP('L', SET, 1, rp) # LD L,SET 1,(IX+dd)
|
|
|
|
0xCE: SET 1, "(#{rpn}+nn)" # SET 1,(IX+nn)
|
|
|
|
0xCF: LDBITOP('A', SET, 1, rp) # LD A,SET 1,(IX+dd)
|
|
|
|
0xD0: LDBITOP('B', SET, 2, rp) # LD B,SET 2,(IX+dd)
|
|
|
|
0xD1: LDBITOP('C', SET, 2, rp) # LD C,SET 2,(IX+dd)
|
|
|
|
0xD2: LDBITOP('D', SET, 2, rp) # LD D,SET 2,(IX+dd)
|
|
|
|
0xD3: LDBITOP('E', SET, 2, rp) # LD E,SET 2,(IX+dd)
|
|
|
|
0xD4: LDBITOP('H', SET, 2, rp) # LD H,SET 2,(IX+dd)
|
|
|
|
0xD5: LDBITOP('L', SET, 2, rp) # LD L,SET 2,(IX+dd)
|
|
|
|
0xD6: SET 2, "(#{rpn}+nn)" # SET 2,(IX+nn)
|
|
|
|
0xD7: LDBITOP('A', SET, 2, rp) # LD A,SET 2,(IX+dd)
|
|
|
|
0xD8: LDBITOP('B', SET, 3, rp) # LD B,SET 3,(IX+dd)
|
|
|
|
0xD9: LDBITOP('C', SET, 3, rp) # LD C,SET 3,(IX+dd)
|
|
|
|
0xDA: LDBITOP('D', SET, 3, rp) # LD D,SET 3,(IX+dd)
|
|
|
|
0xDB: LDBITOP('E', SET, 3, rp) # LD E,SET 3,(IX+dd)
|
|
|
|
0xDC: LDBITOP('H', SET, 3, rp) # LD H,SET 3,(IX+dd)
|
|
|
|
0xDD: LDBITOP('L', SET, 3, rp) # LD L,SET 3,(IX+dd)
|
|
|
|
0xDE: SET 3, "(#{rpn}+nn)" # SET 3,(IX+nn)
|
|
|
|
0xDF: LDBITOP('A', SET, 3, rp) # LD A,SET 3,(IX+dd)
|
|
|
|
0xE0: LDBITOP('B', SET, 4, rp) # LD B,SET 4,(IX+dd)
|
|
|
|
0xE1: LDBITOP('C', SET, 4, rp) # LD C,SET 4,(IX+dd)
|
|
|
|
0xE2: LDBITOP('D', SET, 4, rp) # LD D,SET 4,(IX+dd)
|
|
|
|
0xE3: LDBITOP('E', SET, 4, rp) # LD E,SET 4,(IX+dd)
|
|
|
|
0xE4: LDBITOP('H', SET, 4, rp) # LD H,SET 4,(IX+dd)
|
|
|
|
0xE5: LDBITOP('L', SET, 4, rp) # LD L,SET 4,(IX+dd)
|
|
|
|
0xE6: SET 4, "(#{rpn}+nn)" # SET 4,(IX+nn)
|
|
|
|
0xE7: LDBITOP('A', SET, 4, rp) # LD A,SET 4,(IX+dd)
|
|
|
|
0xE8: LDBITOP('B', SET, 5, rp) # LD B,SET 5,(IX+dd)
|
|
|
|
0xE9: LDBITOP('C', SET, 5, rp) # LD C,SET 5,(IX+dd)
|
|
|
|
0xEA: LDBITOP('D', SET, 5, rp) # LD D,SET 5,(IX+dd)
|
|
|
|
0xEB: LDBITOP('E', SET, 5, rp) # LD E,SET 5,(IX+dd)
|
|
|
|
0xEC: LDBITOP('H', SET, 5, rp) # LD H,SET 5,(IX+dd)
|
|
|
|
0xED: LDBITOP('L', SET, 5, rp) # LD L,SET 5,(IX+dd)
|
|
|
|
0xEE: SET 5, "(#{rpn}+nn)" # SET 5,(IX+nn)
|
|
|
|
0xEF: LDBITOP('A', SET, 5, rp) # LD A,SET 5,(IX+dd)
|
|
|
|
0xF0: LDBITOP('B', SET, 6, rp) # LD B,SET 6,(IX+dd)
|
|
|
|
0xF1: LDBITOP('C', SET, 6, rp) # LD C,SET 6,(IX+dd)
|
|
|
|
0xF2: LDBITOP('D', SET, 6, rp) # LD D,SET 6,(IX+dd)
|
|
|
|
0xF3: LDBITOP('E', SET, 6, rp) # LD E,SET 6,(IX+dd)
|
|
|
|
0xF4: LDBITOP('H', SET, 6, rp) # LD H,SET 6,(IX+dd)
|
|
|
|
0xF5: LDBITOP('L', SET, 6, rp) # LD L,SET 6,(IX+dd)
|
|
|
|
0xF6: SET 6, "(#{rpn}+nn)" # SET 6,(IX+nn)
|
|
|
|
0xF7: LDBITOP('A', SET, 6, rp) # LD A,SET 6,(IX+dd)
|
|
|
|
0xF8: LDBITOP('B', SET, 7, rp) # LD B,SET 7,(IX+dd)
|
|
|
|
0xF9: LDBITOP('C', SET, 7, rp) # LD C,SET 7,(IX+dd)
|
|
|
|
0xFA: LDBITOP('D', SET, 7, rp) # LD D,SET 7,(IX+dd)
|
|
|
|
0xFB: LDBITOP('E', SET, 7, rp) # LD E,SET 7,(IX+dd)
|
|
|
|
0xFC: LDBITOP('H', SET, 7, rp) # LD H,SET 7,(IX+dd)
|
|
|
|
0xFD: LDBITOP('L', SET, 7, rp) # LD L,SET 7,(IX+dd)
|
|
|
|
0xFE: SET 7, "(#{rpn}+nn)" # SET 7,(IX+nn)
|
|
|
|
0xFF: LDBITOP('A', SET, 7, rp) # LD A,SET 7,(IX+dd)
|
|
|
|
0x100: 'ddcb'
|
|
|
|
}
|
|
|
|
|
|
|
|
OPCODE_RUN_STRINGS_DDCB = generateddfdcbOpcodeSet('DDCB')
|
|
|
|
OPCODE_RUN_STRINGS_FDCB = generateddfdcbOpcodeSet('FDCB')
|
|
|
|
|
|
|
|
# Generate the opcode runner lookup table for either the DD or FD set, acting on the
|
|
|
|
# specified register pair (IX or IY)
|
|
|
|
generateddfdOpcodeSet = (prefix) ->
|
|
|
|
if prefix == 'DD'
|
|
|
|
rp = rpIX
|
|
|
|
rh = rIXH
|
|
|
|
rl = rIXL
|
|
|
|
|
|
|
|
rpn = 'IX'
|
|
|
|
rhn = 'IXH'
|
|
|
|
rln = 'IXL'
|
|
|
|
else # prefix == 'FD'
|
|
|
|
rp = rpIY
|
|
|
|
rh = rIYH
|
|
|
|
rl = rIYL
|
|
|
|
|
|
|
|
rpn = 'IY'
|
|
|
|
rhn = 'IYH'
|
|
|
|
rln = 'IYL'
|
|
|
|
return {
|
|
|
|
0x09: ADD_RR_RR(rp, rpBC) # ADD IX,BC
|
|
|
|
|
|
|
|
0x19: ADD_RR_RR(rp, rpDE) # ADD IX,DE
|
|
|
|
|
|
|
|
0x21: LD_RR_NN(rp) # LD IX,nnnn
|
|
|
|
0x22: LD_iNNi_RR(rp) # LD (nnnn),IX
|
|
|
|
0x23: INC_RR(rp) # INC IX
|
|
|
|
0x24: INC rhn # INC IXh
|
|
|
|
0x25: DEC rhn # DEC IXh
|
|
|
|
0x26: LD_R_N(rh) # LD IXh, nn
|
|
|
|
|
|
|
|
0x29: ADD_RR_RR(rp, rp) # ADD IX,IX
|
|
|
|
0x2A: LD_RR_iNNi(rp) # LD IX,(nnnn)
|
|
|
|
0x2B: DEC_RR(rp) # DEC IX
|
|
|
|
0x2C: INC rln # INC IXl
|
|
|
|
0x2D: DEC rln # DEC IXl
|
|
|
|
0x2E: LD_R_N(rl) # LD IXl, nn
|
|
|
|
|
|
|
|
0x34: INC "(#{rpn}+nn)" # INC (IX+nn)
|
|
|
|
0x35: DEC "(#{rpn}+nn)" # DEC (IX+nn)
|
|
|
|
0x36: LD_iRRpNNi_N(rp) # LD (IX+nn),nn
|
|
|
|
|
|
|
|
0x39: ADD_RR_RR(rp, rpSP) # ADD IX,SP
|
|
|
|
|
|
|
|
0x44: LD_R_R(rB, rh) # LD B,IXh
|
|
|
|
0x45: LD_R_R(rB, rl) # LD B,IXl
|
|
|
|
0x46: LD_R_iRRpNNi(rB, rp) # LD B,(IX+nn)
|
|
|
|
|
|
|
|
0x4C: LD_R_R(rC, rh) # LD C,IXh
|
|
|
|
0x4D: LD_R_R(rC, rl) # LD C,IXl
|
|
|
|
0x4E: LD_R_iRRpNNi(rC, rp) # LD C,(IX+nn)
|
|
|
|
|
|
|
|
0x54: LD_R_R(rD, rh) # LD D,IXh
|
|
|
|
0x55: LD_R_R(rD, rl) # LD D,IXl
|
|
|
|
0x56: LD_R_iRRpNNi(rD, rp) # LD D,(IX+nn)
|
|
|
|
|
|
|
|
0x5C: LD_R_R(rE, rh) # LD E,IXh
|
|
|
|
0x5D: LD_R_R(rE, rl) # LD E,IXl
|
|
|
|
0x5E: LD_R_iRRpNNi(rE, rp) # LD E,(IX+nn)
|
|
|
|
|
|
|
|
0x60: LD_R_R(rh, rB) # LD IXh,B
|
|
|
|
0x61: LD_R_R(rh, rC) # LD IXh,C
|
|
|
|
0x62: LD_R_R(rh, rD) # LD IXh,D
|
|
|
|
0x63: LD_R_R(rh, rE) # LD IXh,E
|
|
|
|
0x64: LD_R_R(rh, rh) # LD IXh,IXh
|
|
|
|
0x65: LD_R_R(rh, rl) # LD IXh,IXl
|
|
|
|
0x66: LD_R_iRRpNNi(rH, rp) # LD H,(IX+nn)
|
|
|
|
0x67: LD_R_R(rh, rA) # LD IXh,A
|
|
|
|
0x68: LD_R_R(rl, rB) # LD IXl,B
|
|
|
|
0x69: LD_R_R(rl, rC) # LD IXl,C
|
|
|
|
0x6A: LD_R_R(rl, rD) # LD IXl,D
|
|
|
|
0x6B: LD_R_R(rl, rE) # LD IXl,E
|
|
|
|
0x6C: LD_R_R(rl, rh) # LD IXl,IXh
|
|
|
|
0x6D: LD_R_R(rl, rl) # LD IXl,IXl
|
|
|
|
0x6E: LD_R_iRRpNNi(rL, rp) # LD L,(IX+nn)
|
|
|
|
0x6F: LD_R_R(rl, rA) # LD IXl,A
|
|
|
|
0x70: LD_iRRpNNi_R(rp, rB) # LD (IX+nn),B
|
|
|
|
0x71: LD_iRRpNNi_R(rp, rC) # LD (IX+nn),C
|
|
|
|
0x72: LD_iRRpNNi_R(rp, rD) # LD (IX+nn),D
|
|
|
|
0x73: LD_iRRpNNi_R(rp, rE) # LD (IX+nn),E
|
|
|
|
0x74: LD_iRRpNNi_R(rp, rH) # LD (IX+nn),H
|
|
|
|
0x75: LD_iRRpNNi_R(rp, rL) # LD (IX+nn),L
|
|
|
|
0x77: LD_iRRpNNi_R(rp, rA) # LD (IX+nn),A
|
|
|
|
|
|
|
|
0x7C: LD_R_R(rA, rh) # LD A,IXh
|
|
|
|
0x7D: LD_R_R(rA, rl) # LD A,IXl
|
|
|
|
0x7E: LD_R_iRRpNNi(rA, rp) # LD A,(IX+nn)
|
|
|
|
|
|
|
|
0x84: ADD_A rhn # ADD A,IXh
|
|
|
|
0x85: ADD_A rln # ADD A,IXl
|
|
|
|
0x86: ADD_A "(#{rpn}+nn)" # ADD A,(IX+nn)
|
|
|
|
|
|
|
|
0x8C: ADC_A rhn # ADC A,IXh
|
|
|
|
0x8D: ADC_A rln # ADC A,IXl
|
|
|
|
0x8E: ADC_A "(#{rpn}+nn)" # ADC A,(IX+nn)
|
|
|
|
|
|
|
|
0x94: SUB_A rhn # SUB IXh
|
|
|
|
0x95: SUB_A rln # SUB IXl
|
|
|
|
0x96: SUB_A "(#{rpn}+nn)" # SUB A,(IX+dd)
|
|
|
|
|
|
|
|
0x9C: SBC_A rhn # SBC IXh
|
|
|
|
0x9D: SBC_A rln # SBC IXl
|
|
|
|
0x9E: SBC_A "(#{rpn}+nn)" # SBC A,(IX+dd)
|
|
|
|
|
|
|
|
0xA4: AND_A rhn # AND IXh
|
|
|
|
0xA5: AND_A rln # AND IXl
|
|
|
|
0xA6: AND_A "(#{rpn}+nn)" # AND (IX+dd)
|
|
|
|
|
|
|
|
0xAC: XOR_A rhn # XOR IXh
|
|
|
|
0xAD: XOR_A rln # XOR IXl
|
|
|
|
0xAE: XOR_A "(#{rpn}+nn)" # XOR A,(IX+dd)
|
|
|
|
|
|
|
|
0xB4: OR_A rhn # OR IXh
|
|
|
|
0xB5: OR_A rln # OR IXl
|
|
|
|
0xB6: OR_A "(#{rpn}+nn)" # OR A,(IX+dd)
|
|
|
|
|
|
|
|
0xBC: CP_A rhn # CP IXh
|
|
|
|
0xBD: CP_A rln # CP IXl
|
|
|
|
0xBE: CP_A "(#{rpn}+nn)" # CP (IX+dd)
|
|
|
|
|
|
|
|
0xCB: SHIFT(prefix + 'CB') # shift code
|
|
|
|
|
|
|
|
0xDD: SHIFT('DD') # shift code
|
|
|
|
|
|
|
|
0xE1: POP_RR(rp) # POP IX
|
|
|
|
|
|
|
|
0xE3: EX_iSPi_RR(rp) # EX (SP),IX
|
|
|
|
|
|
|
|
0xE5: PUSH_RR(rp) # PUSH IX
|
|
|
|
|
|
|
|
0xE9: JP_RR(rp) # JP (IX)
|
|
|
|
|
|
|
|
0xF9: LD_RR_RR(rpSP, rp) # LD SP,IX
|
|
|
|
|
|
|
|
0xFD: SHIFT('FD') # shift code
|
|
|
|
|
|
|
|
0x100: 'dd'
|
|
|
|
}
|
|
|
|
|
|
|
|
OPCODE_RUN_STRINGS_DD = generateddfdOpcodeSet('DD')
|
|
|
|
|
|
|
|
OPCODE_RUN_STRINGS_ED = {
|
|
|
|
|
|
|
|
0x40: IN_R_iCi(rB) # IN B,(C)
|
|
|
|
0x41: OUT_iCi_R(rB) # OUT (C),B
|
|
|
|
0x42: SBC_HL_RR(rpBC) # SBC HL,BC
|
|
|
|
0x43: LD_iNNi_RR(rpBC) # LD (nnnn),BC
|
|
|
|
0x44: NEG() # NEG
|
|
|
|
0x45: RETN() # RETN
|
|
|
|
0x46: IM(0) # IM 0
|
|
|
|
0x47: LD_R_R(rI, rA) # LD I,A
|
|
|
|
0x48: IN_R_iCi(rC) # IN C,(C)
|
|
|
|
0x49: OUT_iCi_R(rC) # OUT (C),C
|
|
|
|
0x4A: ADC_HL_RR(rpBC) # ADC HL,BC
|
|
|
|
0x4B: LD_RR_iNNi(rpBC) # LD BC,(nnnn)
|
|
|
|
0x4C: NEG() # NEG
|
|
|
|
0x4D: RETN() # RETN
|
|
|
|
0x4E: IM(0) # IM 0
|
|
|
|
0x4F: LD_R_R(rR, rA) # LD R,A
|
|
|
|
0x50: IN_R_iCi(rD) # IN D,(C)
|
|
|
|
0x51: OUT_iCi_R(rD) # OUT (C),D
|
|
|
|
0x52: SBC_HL_RR(rpDE) # SBC HL,DE
|
|
|
|
0x53: LD_iNNi_RR(rpDE) # LD (nnnn),DE
|
|
|
|
0x54: NEG() # NEG
|
|
|
|
0x55: RETN() # RETN
|
|
|
|
0x56: IM(1) # IM 1
|
|
|
|
0x57: LD_R_R(rA, rI) # LD A,I
|
|
|
|
0x58: IN_R_iCi(rE) # IN E,(C)
|
|
|
|
0x59: OUT_iCi_R(rE) # OUT (C),E
|
|
|
|
0x5A: ADC_HL_RR(rpDE) # ADC HL,DE
|
|
|
|
0x5B: LD_RR_iNNi(rpDE) # LD DE,(nnnn)
|
|
|
|
0x5C: NEG() # NEG
|
|
|
|
0x5D: RETN() # RETN
|
|
|
|
0x5E: IM(2) # IM 2
|
|
|
|
0x5F: LD_R_R(rA, rR) # LD A,R
|
|
|
|
0x60: IN_R_iCi(rH) # IN H,(C)
|
|
|
|
0x61: OUT_iCi_R(rH) # OUT (C),H
|
|
|
|
0x62: SBC_HL_RR(rpHL) # SBC HL,HL
|
|
|
|
0x63: LD_iNNi_RR(rpHL) # LD (nnnn),HL
|
|
|
|
0x64: NEG() # NEG
|
|
|
|
0x65: RETN() # RETN
|
|
|
|
0x66: IM(0) # IM 0
|
|
|
|
0x67: RRD() # RRD
|
|
|
|
0x68: IN_R_iCi(rL) # IN L,(C)
|
|
|
|
0x69: OUT_iCi_R(rL) # OUT (C),L
|
|
|
|
0x6A: ADC_HL_RR(rpHL) # ADC HL,HL
|
|
|
|
0x6B: LD_RR_iNNi(rpHL, true) # LD HL,(nnnn)
|
|
|
|
0x6C: NEG() # NEG
|
|
|
|
0x6D: RETN() # RETN
|
|
|
|
0x6E: IM(0) # IM 0
|
|
|
|
0x6F: RLD() # RLD
|
|
|
|
0x70: IN_F_iCi() # IN F,(C)
|
|
|
|
0x71: OUT_iCi_0() # OUT (C),0
|
|
|
|
0x72: SBC_HL_RR(rpSP) # SBC HL,SP
|
|
|
|
0x73: LD_iNNi_RR(rpSP) # LD (nnnn),SP
|
|
|
|
0x74: NEG() # NEG
|
|
|
|
0x75: RETN() # RETN
|
|
|
|
0x76: IM(1) # IM 1
|
|
|
|
|
|
|
|
0x78: IN_R_iCi(rA) # IN A,(C)
|
|
|
|
0x79: OUT_iCi_R(rA) # OUT (C),A
|
|
|
|
0x7A: ADC_HL_RR(rpSP) # ADC HL,SP
|
|
|
|
0x7B: LD_RR_iNNi(rpSP) # LD SP,(nnnn)
|
|
|
|
0x7C: NEG() # NEG
|
|
|
|
0x7D: RETN() # RETN
|
|
|
|
0x7E: IM(2) # IM 2
|
|
|
|
|
|
|
|
0xA0: LDI() # LDI
|
|
|
|
0xA1: CPI() # CPI
|
|
|
|
0xA2: INI() # INI
|
|
|
|
0xA3: OUTI() # OUTI
|
|
|
|
|
|
|
|
0xA8: LDD() # LDD
|
|
|
|
0xA9: CPD() # CPD
|
|
|
|
0xAA: IND() # IND
|
|
|
|
0xAB: OUTD() # OUTD
|
|
|
|
|
|
|
|
0xB0: LDIR() # LDIR
|
|
|
|
0xb1: CPIR() # CPIR
|
|
|
|
0xB2: INIR() # INIR
|
|
|
|
0xB3: OTIR() # OTIR
|
|
|
|
|
|
|
|
0xB8: LDDR() # LDDR
|
|
|
|
0xb9: CPDR() # CPDR
|
|
|
|
0xBA: INDR() # INDR
|
|
|
|
0xBB: OTDR() # OTDR
|
|
|
|
|
|
|
|
0x100: 'ed'
|
|
|
|
}
|
|
|
|
|
|
|
|
OPCODE_RUN_STRINGS_FD = generateddfdOpcodeSet('FD')
|
|
|
|
|
|
|
|
OPCODE_RUN_STRINGS = {
|
|
|
|
0x00: NOP() # NOP
|
|
|
|
0x01: LD_RR_NN(rpBC) # LD BC,nnnn
|
|
|
|
0x02: LD_iRRi_R(rpBC, rA) # LD (BC),A
|
|
|
|
0x03: INC_RR(rpBC) # INC BC
|
|
|
|
0x04: INC "B" # INC B
|
|
|
|
0x05: DEC "B" # DEC B
|
|
|
|
0x06: LD_R_N(rB) # LD B,nn
|
|
|
|
0x07: RLCA() # RLCA
|
|
|
|
0x08: EX_RR_RR(rpAF, rpAF_) # EX AF,AF'
|
|
|
|
0x09: ADD_RR_RR(rpHL, rpBC) # ADD HL,BC
|
|
|
|
0x0A: LD_R_iRRi(rA, rpBC) # LD A,(BC)
|
|
|
|
0x0B: DEC_RR(rpBC) # DEC BC
|
|
|
|
0x0C: INC "C" # INC C
|
|
|
|
0x0D: DEC "C" # DEC C
|
|
|
|
0x0E: LD_R_N(rC) # LD C,nn
|
|
|
|
0x0F: RRCA() # RRCA
|
|
|
|
0x10: DJNZ_N() # DJNZ nn
|
|
|
|
0x11: LD_RR_NN(rpDE) # LD DE,nnnn
|
|
|
|
0x12: LD_iRRi_R(rpDE, rA) # LD (DE),A
|
|
|
|
0x13: INC_RR(rpDE) # INC DE
|
|
|
|
0x14: INC "D" # INC D
|
|
|
|
0x15: DEC "D" # DEC D
|
|
|
|
0x16: LD_R_N(rD) # LD D,nn
|
|
|
|
0x17: RLA() # RLA
|
|
|
|
0x18: JR_N() # JR nn
|
|
|
|
0x19: ADD_RR_RR(rpHL, rpDE) # ADD HL,DE
|
|
|
|
0x1A: LD_R_iRRi(rA, rpDE) # LD A,(DE)
|
|
|
|
0x1B: DEC_RR(rpDE) # DEC DE
|
|
|
|
0x1C: INC "E" # INC E
|
|
|
|
0x1D: DEC "E" # DEC E
|
|
|
|
0x1E: LD_R_N(rE) # LD E,nn
|
|
|
|
0x1F: RRA() # RRA
|
|
|
|
0x20: JR_C_N(FLAG_Z, false) # JR NZ,nn
|
|
|
|
0x21: LD_RR_NN(rpHL) # LD HL,nnnn
|
|
|
|
0x22: LD_iNNi_RR(rpHL) # LD (nnnn),HL
|
|
|
|
0x23: INC_RR(rpHL) # INC HL
|
|
|
|
0x24: INC "H" # INC H
|
|
|
|
0x25: DEC "H" # DEC H
|
|
|
|
0x26: LD_R_N(rH) # LD H,nn
|
|
|
|
0x27: DAA() # DAA
|
|
|
|
0x28: JR_C_N(FLAG_Z, true) # JR Z,nn
|
|
|
|
0x29: ADD_RR_RR(rpHL, rpHL) # ADD HL,HL
|
|
|
|
0x2A: LD_RR_iNNi(rpHL) # LD HL,(nnnn)
|
|
|
|
0x2B: DEC_RR(rpHL) # DEC HL
|
|
|
|
0x2C: INC "L" # INC L
|
|
|
|
0x2D: DEC "L" # DEC L
|
|
|
|
0x2E: LD_R_N(rL) # LD L,nn
|
|
|
|
0x2F: CPL() # CPL
|
|
|
|
0x30: JR_C_N(FLAG_C, false) # JR NC,nn
|
|
|
|
0x31: LD_RR_NN(rpSP) # LD SP,nnnn
|
|
|
|
0x32: LD_iNNi_A() # LD (nnnn),a
|
|
|
|
0x33: INC_RR(rpSP) # INC SP
|
|
|
|
0x34: INC "(HL)" # INC (HL)
|
|
|
|
0x35: DEC "(HL)" # DEC (HL)
|
|
|
|
0x36: LD_iRRi_N(rpHL) # LD (HL),nn
|
|
|
|
0x37: SCF() # SCF
|
|
|
|
0x38: JR_C_N(FLAG_C, true) # JR C,nn
|
|
|
|
0x39: ADD_RR_RR(rpHL, rpSP) # ADD HL,SP
|
|
|
|
0x3A: LD_A_iNNi() # LD A,(nnnn)
|
|
|
|
0x3B: DEC_RR(rpSP) # DEC SP
|
|
|
|
0x3C: INC "A" # INC A
|
|
|
|
0x3D: DEC "A" # DEC A
|
|
|
|
0x3E: LD_R_N(rA) # LD A,nn
|
|
|
|
0x3F: CCF() # CCF
|
|
|
|
0x40: LD_R_R(rB, rB) # LD B,B
|
|
|
|
0x41: LD_R_R(rB, rC) # LD B,C
|
|
|
|
0x42: LD_R_R(rB, rD) # LD B,D
|
|
|
|
0x43: LD_R_R(rB, rE) # LD B,E
|
|
|
|
0x44: LD_R_R(rB, rH) # LD B,H
|
|
|
|
0x45: LD_R_R(rB, rL) # LD B,L
|
|
|
|
0x46: LD_R_iRRi(rB, rpHL) # LD B,(HL)
|
|
|
|
0x47: LD_R_R(rB, rA) # LD B,A
|
|
|
|
0x48: LD_R_R(rC, rB) # LD C,B
|
|
|
|
0x49: LD_R_R(rC, rC) # LD C,C
|
|
|
|
0x4a: LD_R_R(rC, rD) # LD C,D
|
|
|
|
0x4b: LD_R_R(rC, rE) # LD C,E
|
|
|
|
0x4c: LD_R_R(rC, rH) # LD C,H
|
|
|
|
0x4d: LD_R_R(rC, rL) # LD C,L
|
|
|
|
0x4e: LD_R_iRRi(rC, rpHL) # LD C,(HL)
|
|
|
|
0x4f: LD_R_R(rC, rA) # LD C,A
|
|
|
|
0x50: LD_R_R(rD, rB) # LD D,B
|
|
|
|
0x51: LD_R_R(rD, rC) # LD D,C
|
|
|
|
0x52: LD_R_R(rD, rD) # LD D,D
|
|
|
|
0x53: LD_R_R(rD, rE) # LD D,E
|
|
|
|
0x54: LD_R_R(rD, rH) # LD D,H
|
|
|
|
0x55: LD_R_R(rD, rL) # LD D,L
|
|
|
|
0x56: LD_R_iRRi(rD, rpHL) # LD D,(HL)
|
|
|
|
0x57: LD_R_R(rD, rA) # LD D,A
|
|
|
|
0x58: LD_R_R(rE, rB) # LD E,B
|
|
|
|
0x59: LD_R_R(rE, rC) # LD E,C
|
|
|
|
0x5a: LD_R_R(rE, rD) # LD E,D
|
|
|
|
0x5b: LD_R_R(rE, rE) # LD E,E
|
|
|
|
0x5c: LD_R_R(rE, rH) # LD E,H
|
|
|
|
0x5d: LD_R_R(rE, rL) # LD E,L
|
|
|
|
0x5e: LD_R_iRRi(rE, rpHL) # LD E,(HL)
|
|
|
|
0x5f: LD_R_R(rE, rA) # LD E,A
|
|
|
|
0x60: LD_R_R(rH, rB) # LD H,B
|
|
|
|
0x61: LD_R_R(rH, rC) # LD H,C
|
|
|
|
0x62: LD_R_R(rH, rD) # LD H,D
|
|
|
|
0x63: LD_R_R(rH, rE) # LD H,E
|
|
|
|
0x64: LD_R_R(rH, rH) # LD H,H
|
|
|
|
0x65: LD_R_R(rH, rL) # LD H,L
|
|
|
|
0x66: LD_R_iRRi(rH, rpHL) # LD H,(HL)
|
|
|
|
0x67: LD_R_R(rH, rA) # LD H,A
|
|
|
|
0x68: LD_R_R(rL, rB) # LD L,B
|
|
|
|
0x69: LD_R_R(rL, rC) # LD L,C
|
|
|
|
0x6a: LD_R_R(rL, rD) # LD L,D
|
|
|
|
0x6b: LD_R_R(rL, rE) # LD L,E
|
|
|
|
0x6c: LD_R_R(rL, rH) # LD L,H
|
|
|
|
0x6d: LD_R_R(rL, rL) # LD L,L
|
|
|
|
0x6e: LD_R_iRRi(rL, rpHL) # LD L,(HL)
|
|
|
|
0x6f: LD_R_R(rL, rA) # LD L,A
|
|
|
|
0x70: LD_iRRi_R(rpHL, rB) # LD (HL),B
|
|
|
|
0x71: LD_iRRi_R(rpHL, rC) # LD (HL),C
|
|
|
|
0x72: LD_iRRi_R(rpHL, rD) # LD (HL),D
|
|
|
|
0x73: LD_iRRi_R(rpHL, rE) # LD (HL),E
|
|
|
|
0x74: LD_iRRi_R(rpHL, rH) # LD (HL),H
|
|
|
|
0x75: LD_iRRi_R(rpHL, rL) # LD (HL),L
|
|
|
|
0x76: HALT() # HALT
|
|
|
|
0x77: LD_iRRi_R(rpHL, rA) # LD (HL),A
|
|
|
|
0x78: LD_R_R(rA, rB) # LD A,B
|
|
|
|
0x79: LD_R_R(rA, rC) # LD A,C
|
|
|
|
0x7a: LD_R_R(rA, rD) # LD A,D
|
|
|
|
0x7b: LD_R_R(rA, rE) # LD A,E
|
|
|
|
0x7c: LD_R_R(rA, rH) # LD A,H
|
|
|
|
0x7d: LD_R_R(rA, rL) # LD A,L
|
|
|
|
0x7e: LD_R_iRRi(rA, rpHL) # LD A,(HL)
|
|
|
|
0x7f: LD_R_R(rA, rA) # LD A,A
|
|
|
|
0x80: ADD_A "B" # ADD A,B
|
|
|
|
0x81: ADD_A "C" # ADD A,C
|
|
|
|
0x82: ADD_A "D" # ADD A,D
|
|
|
|
0x83: ADD_A "E" # ADD A,E
|
|
|
|
0x84: ADD_A "H" # ADD A,H
|
|
|
|
0x85: ADD_A "L" # ADD A,L
|
|
|
|
0x86: ADD_A "(HL)" # ADD A,(HL)
|
|
|
|
0x87: ADD_A "A" # ADD A,A
|
|
|
|
0x88: ADC_A "B" # ADC A,B
|
|
|
|
0x89: ADC_A "C" # ADC A,C
|
|
|
|
0x8a: ADC_A "D" # ADC A,D
|
|
|
|
0x8b: ADC_A "E" # ADC A,E
|
|
|
|
0x8c: ADC_A "H" # ADC A,H
|
|
|
|
0x8d: ADC_A "L" # ADC A,L
|
|
|
|
0x8e: ADC_A "(HL)" # ADC A,(HL)
|
|
|
|
0x8f: ADC_A "A" # ADC A,A
|
|
|
|
0x90: SUB_A "B" # SUB A,B
|
|
|
|
0x91: SUB_A "C" # SUB A,C
|
|
|
|
0x92: SUB_A "D" # SUB A,D
|
|
|
|
0x93: SUB_A "E" # SUB A,E
|
|
|
|
0x94: SUB_A "H" # SUB A,H
|
|
|
|
0x95: SUB_A "L" # SUB A,L
|
|
|
|
0x96: SUB_A "(HL)" # SUB A,(HL)
|
|
|
|
0x97: SUB_A "A" # SUB A,A
|
|
|
|
0x98: SBC_A "B" # SBC A,B
|
|
|
|
0x99: SBC_A "C" # SBC A,C
|
|
|
|
0x9a: SBC_A "D" # SBC A,D
|
|
|
|
0x9b: SBC_A "E" # SBC A,E
|
|
|
|
0x9c: SBC_A "H" # SBC A,H
|
|
|
|
0x9d: SBC_A "L" # SBC A,L
|
|
|
|
0x9e: SBC_A "(HL)" # SBC A,(HL)
|
|
|
|
0x9f: SBC_A "A" # SBC A,A
|
|
|
|
0xa0: AND_A "B" # AND A,B
|
|
|
|
0xa1: AND_A "C" # AND A,C
|
|
|
|
0xa2: AND_A "D" # AND A,D
|
|
|
|
0xa3: AND_A "E" # AND A,E
|
|
|
|
0xa4: AND_A "H" # AND A,H
|
|
|
|
0xa5: AND_A "L" # AND A,L
|
|
|
|
0xa6: AND_A "(HL)" # AND A,(HL)
|
|
|
|
0xa7: AND_A "A" # AND A,A
|
|
|
|
0xA8: XOR_A "B" # XOR B
|
|
|
|
0xA9: XOR_A "C" # XOR C
|
|
|
|
0xAA: XOR_A "D" # XOR D
|
|
|
|
0xAB: XOR_A "E" # XOR E
|
|
|
|
0xAC: XOR_A "H" # XOR H
|
|
|
|
0xAD: XOR_A "L" # XOR L
|
|
|
|
0xAE: XOR_A "(HL)" # XOR (HL)
|
|
|
|
0xAF: XOR_A "A" # XOR A
|
|
|
|
0xb0: OR_A "B" # OR B
|
|
|
|
0xb1: OR_A "C" # OR C
|
|
|
|
0xb2: OR_A "D" # OR D
|
|
|
|
0xb3: OR_A "E" # OR E
|
|
|
|
0xb4: OR_A "H" # OR H
|
|
|
|
0xb5: OR_A "L" # OR L
|
|
|
|
0xb6: OR_A "(HL)" # OR (HL)
|
|
|
|
0xb7: OR_A "A" # OR A
|
|
|
|
0xb8: CP_A "B" # CP B
|
|
|
|
0xb9: CP_A "C" # CP C
|
|
|
|
0xba: CP_A "D" # CP D
|
|
|
|
0xbb: CP_A "E" # CP E
|
|
|
|
0xbc: CP_A "H" # CP H
|
|
|
|
0xbd: CP_A "L" # CP L
|
|
|
|
0xbe: CP_A "(HL)" # CP (HL)
|
|
|
|
0xbf: CP_A "A" # CP A
|
|
|
|
0xC0: RET_C(FLAG_Z, false) # RET NZ
|
|
|
|
0xC1: POP_RR(rpBC) # POP BC
|
|
|
|
0xC2: JP_C_NN(FLAG_Z, false) # JP NZ,nnnn
|
|
|
|
0xC3: JP_NN() # JP nnnn
|
|
|
|
0xC4: CALL_C_NN(FLAG_Z, false) # CALL NZ,nnnn
|
|
|
|
0xC5: PUSH_RR(rpBC) # PUSH BC
|
|
|
|
0xC6: ADD_A "nn" # ADD A,nn
|
|
|
|
0xC7: RST(0x0000) # RST 0x00
|
|
|
|
0xC8: RET_C(FLAG_Z, true) # RET Z
|
|
|
|
0xC9: RET() # RET
|
|
|
|
0xCA: JP_C_NN(FLAG_Z, true) # JP Z,nnnn
|
|
|
|
0xCB: SHIFT('CB') # shift code
|
|
|
|
0xCC: CALL_C_NN(FLAG_Z, true) # CALL Z,nnnn
|
|
|
|
0xCD: CALL_NN() # CALL nnnn
|
|
|
|
0xCE: ADC_A "nn" # ADC A,nn
|
|
|
|
0xCF: RST(0x0008) # RST 0x08
|
|
|
|
0xD0: RET_C(FLAG_C, false) # RET NC
|
|
|
|
0xD1: POP_RR(rpDE) # POP DE
|
|
|
|
0xD2: JP_C_NN(FLAG_C, false) # JP NC,nnnn
|
|
|
|
0xD3: OUT_iNi_A() # OUT (nn),A
|
|
|
|
0xD4: CALL_C_NN(FLAG_C, false) # CALL NC,nnnn
|
|
|
|
0xD5: PUSH_RR(rpDE) # PUSH DE
|
|
|
|
0xD6: SUB_A "nn" # SUB nn
|
|
|
|
0xD7: RST(0x0010) # RST 0x10
|
|
|
|
0xD8: RET_C(FLAG_C, true) # RET C
|
|
|
|
0xD9: EXX() # EXX
|
|
|
|
0xDA: JP_C_NN(FLAG_C, true) # JP C,nnnn
|
|
|
|
0xDB: IN_A_N() # IN A,(nn)
|
|
|
|
0xDC: CALL_C_NN(FLAG_C, true) # CALL C,nnnn
|
|
|
|
0xDD: SHIFT('DD') # shift code
|
|
|
|
0xDE: SBC_A "nn" # SBC A,nn
|
|
|
|
0xDF: RST(0x0018) # RST 0x18
|
|
|
|
0xE0: RET_C(FLAG_P, false) # RET PO
|
|
|
|
0xE1: POP_RR(rpHL) # POP HL
|
|
|
|
0xE2: JP_C_NN(FLAG_P, false) # JP PO,nnnn
|
|
|
|
0xE3: EX_iSPi_RR(rpHL) # EX (SP),HL
|
|
|
|
0xE4: CALL_C_NN(FLAG_P, false) # CALL PO,nnnn
|
|
|
|
0xE5: PUSH_RR(rpHL) # PUSH HL
|
|
|
|
0xE6: AND_A "nn" # AND nn
|
|
|
|
0xE7: RST(0x0020) # RST 0x20
|
|
|
|
0xE8: RET_C(FLAG_P, true) # RET PE
|
|
|
|
0xE9: JP_RR(rpHL) # JP (HL)
|
|
|
|
0xEA: JP_C_NN(FLAG_P, true) # JP PE,nnnn
|
|
|
|
0xEB: EX_RR_RR(rpDE, rpHL) # EX DE,HL
|
|
|
|
0xEC: CALL_C_NN(FLAG_P, true) # CALL PE,nnnn
|
|
|
|
0xED: SHIFT('ED') # shift code
|
|
|
|
0xEE: XOR_A "nn" # XOR nn
|
|
|
|
0xEF: RST(0x0028) # RST 0x28
|
|
|
|
0xF0: RET_C(FLAG_S, false) # RET P
|
|
|
|
0xF1: POP_RR(rpAF) # POP AF
|
|
|
|
0xF2: JP_C_NN(FLAG_S, false) # JP NZ,nnnn
|
|
|
|
0xF3: DI() # DI
|
|
|
|
0xF4: CALL_C_NN(FLAG_S, false) # CALL P,nnnn
|
|
|
|
0xF5: PUSH_RR(rpAF) # PUSH AF
|
|
|
|
0xF6: OR_A "nn" # OR nn
|
|
|
|
0xF7: RST(0x0030) # RST 0x30
|
|
|
|
0xF8: RET_C(FLAG_S, true) # RET M
|
|
|
|
0xF9: LD_RR_RR(rpSP, rpHL) # LD SP,HL
|
|
|
|
0xFA: JP_C_NN(FLAG_S, true) # JP M,nnnn
|
|
|
|
0xFB: EI() # EI
|
|
|
|
0xFC: CALL_C_NN(FLAG_S, true) # CALL M,nnnn
|
|
|
|
0xFD: SHIFT('FD') # shift code
|
|
|
|
0xFE: CP_A "nn" # CP nn
|
|
|
|
0xFF: RST(0x0038) # RST 0x38
|
|
|
|
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) {
|
|
|
|
var self = {};
|
|
|
|
|
|
|
|
#{setUpStateJS}
|
|
|
|
|
|
|
|
self.requestInterrupt = function(dataBus) {
|
|
|
|
interruptPending = true;
|
|
|
|
interruptDataBus = dataBus & 0xffff;
|
|
|
|
/* TODO: use event scheduling to keep the interrupt line active for a fixed
|
|
|
|
~48T window, to support retriggered interrupts and interrupt blocking via
|
|
|
|
chains of EI or DD/FD prefixes */
|
|
|
|
}
|
2017-01-17 17:26:08 +00:00
|
|
|
self.nonMaskableInterrupt = function() {
|
|
|
|
iff1 = 1;
|
|
|
|
self.requestInterrupt(0x66);
|
|
|
|
}
|
2017-01-14 02:31:04 +00:00
|
|
|
var z80Interrupt = function() {
|
|
|
|
if (iff1) {
|
|
|
|
if (halted) {
|
|
|
|
/* move PC on from the HALT opcode */
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
halted = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
iff1 = iff2 = 0;
|
|
|
|
|
|
|
|
/* push current PC in readiness for call to interrupt handler */
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rpPC}] >> 8);
|
|
|
|
regPairs[#{rpSP}]--; WRITEMEM(regPairs[#{rpSP}], regPairs[#{rpPC}] & 0xff);
|
|
|
|
|
|
|
|
/* TODO: R register */
|
|
|
|
|
|
|
|
switch (im) {
|
|
|
|
case 0:
|
|
|
|
regPairs[#{rpPC}] = interruptDataBus; // assume always RST
|
|
|
|
tstates += 6;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
regPairs[#{rpPC}] = 0x0038;
|
|
|
|
tstates += 7;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
inttemp = (regs[#{rI}] << 8) | (interruptDataBus & 0xff);
|
|
|
|
l = READMEM(inttemp);
|
|
|
|
inttemp = (inttemp+1) & 0xffff;
|
|
|
|
h = READMEM(inttemp);
|
|
|
|
console.log(hex(interruptDataBus), hex(inttemp), hex(l), hex(h));
|
|
|
|
regPairs[#{rpPC}] = (h<<8) | l;
|
|
|
|
tstates += 7;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
self.runFrame = function(frameLength) {
|
|
|
|
var lastOpcodePrefix, offset, opcode;
|
|
|
|
|
|
|
|
while (tstates < frameLength || opcodePrefix) {
|
|
|
|
if (interruptible && interruptPending) {
|
|
|
|
z80Interrupt();
|
|
|
|
interruptPending = false;
|
|
|
|
}
|
|
|
|
interruptible = true; /* unless overridden by opcode */
|
|
|
|
lastOpcodePrefix = opcodePrefix;
|
|
|
|
opcodePrefix = '';
|
|
|
|
switch (lastOpcodePrefix) {
|
|
|
|
case '':
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 4);
|
|
|
|
opcode = memory.read(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
regs[#{rR}] = ((regs[#{rR}] + 1) & 0x7f) | (regs[#{rR}] & 0x80);
|
|
|
|
#{opcodeSwitch(OPCODE_RUN_STRINGS, null, opts.traps)}
|
|
|
|
break;
|
|
|
|
case 'CB':
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 4);
|
|
|
|
opcode = memory.read(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
regs[#{rR}] = ((regs[#{rR}] + 1) & 0x7f) | (regs[#{rR}] & 0x80);
|
|
|
|
#{opcodeSwitch(OPCODE_RUN_STRINGS_CB)}
|
|
|
|
break;
|
|
|
|
case 'DD':
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 4);
|
|
|
|
opcode = memory.read(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
regs[#{rR}] = ((regs[#{rR}] + 1) & 0x7f) | (regs[#{rR}] & 0x80);
|
|
|
|
#{opcodeSwitch(OPCODE_RUN_STRINGS_DD, OPCODE_RUN_STRINGS)}
|
|
|
|
break;
|
|
|
|
case 'DDCB':
|
|
|
|
offset = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
if (offset & 0x80) offset -= 0x100;
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 3);
|
|
|
|
opcode = memory.read(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
#{opcodeSwitch(OPCODE_RUN_STRINGS_DDCB)}
|
|
|
|
break;
|
|
|
|
case 'ED':
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 4);
|
|
|
|
opcode = memory.read(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
regs[#{rR}] = ((regs[#{rR}] + 1) & 0x7f) | (regs[#{rR}] & 0x80);
|
|
|
|
#{opcodeSwitch(OPCODE_RUN_STRINGS_ED)}
|
|
|
|
break;
|
|
|
|
case 'FD':
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 4);
|
|
|
|
opcode = memory.read(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
regs[#{rR}] = ((regs[#{rR}] + 1) & 0x7f) | (regs[#{rR}] & 0x80);
|
|
|
|
#{opcodeSwitch(OPCODE_RUN_STRINGS_FD, OPCODE_RUN_STRINGS)}
|
|
|
|
break;
|
|
|
|
case 'FDCB':
|
|
|
|
offset = READMEM(regPairs[#{rpPC}]); regPairs[#{rpPC}]++;
|
|
|
|
if (offset & 0x80) offset -= 0x100;
|
|
|
|
CONTEND_READ(regPairs[#{rpPC}], 3);
|
|
|
|
opcode = memory.read(regPairs[#{rpPC}]);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
CONTEND_READ_NO_MREQ(regPairs[#{rpPC}], 1);
|
|
|
|
regPairs[#{rpPC}]++;
|
|
|
|
#{opcodeSwitch(OPCODE_RUN_STRINGS_FDCB)}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw("Unknown opcode prefix: " + lastOpcodePrefix);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (display.nextEventTime != null && display.nextEventTime <= tstates) display.doEvent();
|
|
|
|
};
|
|
|
|
|
|
|
|
self.reset = function() {
|
|
|
|
regPairs[#{rpPC}] = regPairs[#{rpIR}] = 0;
|
|
|
|
iff1 = 0; iff2 = 0; im = 0; halted = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.loadState = function(snapRegs) {
|
|
|
|
regPairs[#{rpAF}] = snapRegs['AF'];
|
|
|
|
regPairs[#{rpBC}] = snapRegs['BC'];
|
|
|
|
regPairs[#{rpDE}] = snapRegs['DE'];
|
|
|
|
regPairs[#{rpHL}] = snapRegs['HL'];
|
|
|
|
regPairs[#{rpAF_}] = snapRegs['AF_'];
|
|
|
|
regPairs[#{rpBC_}] = snapRegs['BC_'];
|
|
|
|
regPairs[#{rpDE_}] = snapRegs['DE_'];
|
|
|
|
regPairs[#{rpHL_}] = snapRegs['HL_'];
|
|
|
|
regPairs[#{rpIX}] = snapRegs['IX'];
|
|
|
|
regPairs[#{rpIY}] = snapRegs['IY'];
|
|
|
|
regPairs[#{rpSP}] = snapRegs['SP'];
|
|
|
|
regPairs[#{rpPC}] = snapRegs['PC'];
|
|
|
|
regPairs[#{rpIR}] = snapRegs['IR'];
|
|
|
|
iff1 = snapRegs['iff1'];
|
|
|
|
iff2 = snapRegs['iff2'];
|
|
|
|
im = snapRegs['im'];
|
|
|
|
halted = snapRegs['halted'];
|
|
|
|
tstates = snapRegs['tstates'];
|
|
|
|
interruptPending = snapRegs['intp'];
|
|
|
|
interruptDataBus = snapRegs['intd'];
|
|
|
|
};
|
|
|
|
|
|
|
|
self.saveState = function() {
|
|
|
|
return {
|
|
|
|
AF: regPairs[#{rpAF}],
|
|
|
|
BC: regPairs[#{rpBC}],
|
|
|
|
DE: regPairs[#{rpDE}],
|
|
|
|
HL: regPairs[#{rpHL}],
|
|
|
|
AF_: regPairs[#{rpAF_}],
|
|
|
|
BC_: regPairs[#{rpBC_}],
|
|
|
|
DE_: regPairs[#{rpDE_}],
|
|
|
|
HL_: regPairs[#{rpHL_}],
|
|
|
|
IX: regPairs[#{rpIX}],
|
|
|
|
IY: regPairs[#{rpIY}],
|
|
|
|
SP: regPairs[#{rpSP}],
|
|
|
|
PC: regPairs[#{rpPC}],
|
|
|
|
IR: regPairs[#{rpIR}],
|
|
|
|
iff1: iff1,
|
|
|
|
iff2: iff2,
|
|
|
|
im: im,
|
|
|
|
halted: halted,
|
|
|
|
tstates: tstates,
|
|
|
|
intp: interruptPending,
|
|
|
|
intd: interruptDataBus,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Register / flag accessors (used for tape trapping and test harness) */
|
|
|
|
self.getAF = function() {
|
|
|
|
return regPairs[#{rpAF}];
|
|
|
|
}
|
|
|
|
self.getBC = function() {
|
|
|
|
return regPairs[#{rpBC}];
|
|
|
|
}
|
|
|
|
self.getDE = function() {
|
|
|
|
return regPairs[#{rpDE}];
|
|
|
|
}
|
|
|
|
self.getHL = function() {
|
|
|
|
return regPairs[#{rpHL}];
|
|
|
|
}
|
|
|
|
self.getAF_ = function() {
|
|
|
|
return regPairs[#{rpAF_}];
|
|
|
|
}
|
|
|
|
self.getBC_ = function() {
|
|
|
|
return regPairs[#{rpBC_}];
|
|
|
|
}
|
|
|
|
self.getDE_ = function() {
|
|
|
|
return regPairs[#{rpDE_}];
|
|
|
|
}
|
|
|
|
self.getHL_ = function() {
|
|
|
|
return regPairs[#{rpHL_}];
|
|
|
|
}
|
|
|
|
self.getIX = function() {
|
|
|
|
return regPairs[#{rpIX}];
|
|
|
|
}
|
|
|
|
self.getIY = function() {
|
|
|
|
return regPairs[#{rpIY}];
|
|
|
|
}
|
|
|
|
self.getI = function() {
|
|
|
|
return regs[#{rI}];
|
|
|
|
}
|
|
|
|
self.getR = function() {
|
|
|
|
return regs[#{rR}];
|
|
|
|
}
|
|
|
|
self.getSP = function() {
|
|
|
|
return regPairs[#{rpSP}];
|
|
|
|
}
|
|
|
|
self.getPC = function() {
|
|
|
|
return regPairs[#{rpPC}];
|
|
|
|
}
|
|
|
|
self.getIFF1 = function() {
|
|
|
|
return iff1;
|
|
|
|
}
|
|
|
|
self.getIFF2 = function() {
|
|
|
|
return iff2;
|
|
|
|
}
|
|
|
|
self.getIM = function() {
|
|
|
|
return im;
|
|
|
|
}
|
|
|
|
self.getHalted = function() {
|
|
|
|
return halted;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.setAF = function(val) {
|
|
|
|
regPairs[#{rpAF}] = val;
|
|
|
|
}
|
|
|
|
self.setBC = function(val) {
|
|
|
|
regPairs[#{rpBC}] = val;
|
|
|
|
}
|
|
|
|
self.setDE = function(val) {
|
|
|
|
regPairs[#{rpDE}] = val;
|
|
|
|
}
|
|
|
|
self.setHL = function(val) {
|
|
|
|
regPairs[#{rpHL}] = val;
|
|
|
|
}
|
|
|
|
self.setAF_ = function(val) {
|
|
|
|
regPairs[#{rpAF_}] = val;
|
|
|
|
}
|
|
|
|
self.setBC_ = function(val) {
|
|
|
|
regPairs[#{rpBC_}] = val;
|
|
|
|
}
|
|
|
|
self.setDE_ = function(val) {
|
|
|
|
regPairs[#{rpDE_}] = val;
|
|
|
|
}
|
|
|
|
self.setHL_ = function(val) {
|
|
|
|
regPairs[#{rpHL_}] = val;
|
|
|
|
}
|
|
|
|
self.setIX = function(val) {
|
|
|
|
regPairs[#{rpIX}] = val;
|
|
|
|
}
|
|
|
|
self.setIY = function(val) {
|
|
|
|
regPairs[#{rpIY}] = val;
|
|
|
|
}
|
|
|
|
self.setI = function(val) {
|
|
|
|
regs[#{rI}] = val;
|
|
|
|
}
|
|
|
|
self.setR = function(val) {
|
|
|
|
regs[#{rR}] = val;
|
|
|
|
}
|
|
|
|
self.setSP = function(val) {
|
|
|
|
regPairs[#{rpSP}] = val;
|
|
|
|
}
|
|
|
|
self.setPC = function(val) {
|
|
|
|
regPairs[#{rpPC}] = val;
|
|
|
|
}
|
|
|
|
self.setIFF1 = function(val) {
|
|
|
|
iff1 = val;
|
|
|
|
}
|
|
|
|
self.setIFF2 = function(val) {
|
|
|
|
iff2 = val;
|
|
|
|
}
|
|
|
|
self.setIM = function(val) {
|
|
|
|
im = val;
|
|
|
|
}
|
|
|
|
self.setHalted = function(val) {
|
|
|
|
halted = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.getTstates = function() {
|
|
|
|
return tstates;
|
|
|
|
}
|
|
|
|
self.setTstates = function(val) {
|
|
|
|
tstates = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.getCarry_ = function() {
|
|
|
|
return regs[#{rF_}] & #{FLAG_C};
|
|
|
|
};
|
|
|
|
self.setCarry = function(val) {
|
|
|
|
if (val) {
|
|
|
|
regs[#{rF}] |= #{FLAG_C};
|
|
|
|
} else {
|
|
|
|
regs[#{rF}] &= #{~FLAG_C};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
self.getA_ = function() {
|
|
|
|
return regs[#{rA_}];
|
|
|
|
};
|
|
|
|
|
|
|
|
return self;
|
|
|
|
};
|
|
|
|
"""
|
|
|
|
# Apply macro expansions
|
|
|
|
defineZ80JS = defineZ80JS.replace(/READMEM\((.*?)\)/g, '(CONTEND_READ($1, 3), memory.read($1))');
|
|
|
|
defineZ80JS = defineZ80JS.replace(/WRITEMEM\((.*?),(.*?)\)/g, """
|
|
|
|
CONTEND_WRITE($1, 3);
|
|
|
|
while (display.nextEventTime != null && display.nextEventTime < tstates) display.doEvent();
|
|
|
|
memory.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);
|
|
|
|
var isULAPort = ioBus.isULAPort($1);
|
|
|
|
if (isContendedMemory) tstates += ioBus.contend($1, tstates);
|
|
|
|
tstates += 1;
|
|
|
|
while (display.nextEventTime != null && display.nextEventTime < tstates) display.doEvent();
|
|
|
|
""");
|
|
|
|
defineZ80JS = defineZ80JS.replace(/CONTEND_PORT_LATE\((.*?)\)/g,
|
|
|
|
"""
|
|
|
|
if (isContendedMemory || isULAPort) {
|
|
|
|
ioBus.contend($1);
|
|
|
|
tstates += 1;
|
|
|
|
if (!isULAPort) {
|
|
|
|
ioBus.contend($1); tstates += 1;
|
|
|
|
ioBus.contend($1); tstates += 1;
|
|
|
|
} else {
|
|
|
|
tstates += 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tstates += 3;
|
|
|
|
}
|
|
|
|
""");
|
|
|
|
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');
|
|
|
|
|
|
|
|
# console.log(defineZ80JS);
|
|
|
|
indirectEval = eval
|
|
|
|
indirectEval(defineZ80JS);
|