private void BitPatternALU(ushort operand, out ushort value, out RegGeneral destination)
{
ushort address;
// Decode the operand word's constituent bits. FEDC BA98 7654 3210
// SAAA rrrE OOOO ORRR
int addressingMode = (operand & 0x7000) >> 12;
RegGeneral source = (RegGeneral)((operand & 0x0E00) >> 9);
bool eightBitMode = (operand & 0x0100) != 0;
destination = (RegGeneral)(operand & 0x0007); // R = destination register
SegmentIndex dataSeg = (operand & 0x8000) != 0 ? SegmentIndex.ES : SegmentIndex.DS;
switch (addressingMode) // will always be between 0x0 and 0x7
{
case 0: // Addressing mode: Immediate (r == 0), Absolute (r == 1), else Control Register.
if (source == 0) // Immediate
{
value = eightBitMode ? ReadMemInt8(PC, SegmentIndex.CS) : ReadMemInt16(PC, SegmentIndex.CS);
PC += 2; // advance PC two bytes because we're reading an immediate value.
}
else if ((int)source == 1) // Absolute
{
address = ReadMemInt16(PC, SegmentIndex.CS);
PC += 2; // advance PC two bytes because we're reading an immediate value.
value = eightBitMode ? ReadMemInt8(address, dataSeg) : ReadMemInt16(address, dataSeg);
}
else // Control Register
{
RegControl cr = (RegControl)((operand & 0x0700) >> 8);
value = ReadControlRegister(operand, cr);
}
break;
case 1: // Addressing mode: Register
value = R[(int)source];
break;
case 2: // Addressing mode: Indirect
value = eightBitMode ? ReadMemInt8(R[(int)source], dataSeg) : ReadMemInt16(R[(int)source], dataSeg);
break;
case 3: // Addressing mode: Absolute Offset AKA Indirect Offset
address = (ushort)(R[(int)source] + ReadMemInt16(PC, SegmentIndex.CS));
PC += 2; // advance PC two bytes because we're reading an immediate value.
value = eightBitMode ? ReadMemInt8(address, dataSeg) : ReadMemInt16(address, dataSeg);
break;
default: // addressing of 0x4 ~ 0x7 is an Indirect Indexed operation.
int indexRegister = addressingMode; // bit pattern is 1ii, where ii = r4 - r7.
address = (ushort)(R[(int)source] + R[indexRegister]);
value = eightBitMode ? ReadMemInt8(address, dataSeg) : ReadMemInt16(address, dataSeg);
break;
}
}