Ypsilon.Emulation.Processor.YCPU.BitPatternJMI C# (CSharp) Method

BitPatternJMI() private method

private BitPatternJMI ( ushort operand, ushort &address, uint &addressFar, bool &isFarJump ) : void
operand ushort
address ushort
addressFar uint
isFarJump bool
return void
        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;
            }
        }