private void BitPatternJMI(ushort operand, out ushort address, out uint addressFar, out bool isFarJump)
{
ushort nextword;
// Decode the operand word's constituent bits. FEDC BA98 7654 3210
// SAAA rrrF OOOO ORRR
int addressingMode = (operand & 0x7000) >> 12;
RegGeneral source = (RegGeneral)((operand & 0x0E00) >> 9);
SegmentIndex dataSeg = (operand & 0x8000) != 0 ? SegmentIndex.ES : SegmentIndex.DS;
addressFar = 0;
isFarJump = (operand & 0x0100) != 0; // F = far jump mode
switch (addressingMode) // will always be between 0x0 and 0xf
{
case 0: // Immediate (r == 0) or Absolute (r == 1)
if (source == 0) {
address = ReadMemInt16(PC, SegmentIndex.CS);
PC += 2; // advance PC two bytes because we're reading an immediate value.
if (isFarJump) {
addressFar = ReadMemInt16(PC, SegmentIndex.CS);
PC += 2; // advance PC two bytes because we're reading an immediate value.
addressFar |= (uint)ReadMemInt16(PC, SegmentIndex.CS) << 16;
PC += 2; // advance PC two bytes because we're reading an immediate value.
}
}
else {
nextword = ReadMemInt16(PC, SegmentIndex.CS);
PC += 2; // advance PC two bytes because we're reading an immediate value.
address = ReadMemInt16(nextword, dataSeg);
if (isFarJump) {
addressFar = ReadMemInt16((ushort)(nextword + 2), dataSeg);
addressFar |= (uint)ReadMemInt16((ushort)(nextword + 4), dataSeg) << 16;
}
}
break;
case 1: // Register
address = R[(int)source];
break;
case 2: // Indirect
address = ReadMemInt16(R[(int)source], dataSeg);
if (isFarJump) {
addressFar = ReadMemInt16((ushort)(R[(int)source] + 2), dataSeg);
addressFar |= (uint)ReadMemInt16((ushort)(R[(int)source] + 4), dataSeg) << 16;
}
break;
case 3: // Indirect Offset AKA Absolute Offset
nextword = ReadMemInt16(PC, SegmentIndex.CS);
PC += 2; // advance PC two bytes because we're reading an immediate value.
address = ReadMemInt16((ushort)(R[(int)source] + nextword), dataSeg);
if (isFarJump) {
addressFar = ReadMemInt16((ushort)(R[(int)source] + nextword + 2), dataSeg);
addressFar |= (uint)ReadMemInt16((ushort)(R[(int)source] + nextword + 4), dataSeg) << 16;
}
break;
default: // 0x04 - 0x07 are Indirect Indexed
int indexRegister = (operand & 0x7000) >> 12; // bit pattern is 1ii, indicating R4 - R7
address = ReadMemInt16((ushort)(R[(int)source] + R[indexRegister]), dataSeg);
if (isFarJump) {
addressFar = ReadMemInt16((ushort)(R[(int)source] + R[indexRegister] + 2), dataSeg);
addressFar |= (uint)ReadMemInt16((ushort)(R[(int)source] + R[indexRegister] + 4), dataSeg) << 16;
}
break;
}
}