Exemple #1
0
 public OpCodeTable()
 {
     // initialize the entire table with new records
     for (ushort ii = 0; ii < _opCodeTable.Length; ii++)
     {
         _opCodeTable[ii] = new OpCodeRecord(OpCodeNotImplemented);
     }
 }
Exemple #2
0
 public OpCodeTable()
 {
     // initialize the entire table with new records
     for (ushort ii = 0; ii < _opCodeTable.Length; ii++)
     {
         _opCodeTable[ii] = new OpCodeRecord(OpCodeNotImplemented);
     }
 }
Exemple #3
0
        private void InitOpCodeTable()
        {
            _opTable[0x00] = new OpCodeRecord(ExecuteADD_General);
            _opTable[0x01] = new OpCodeRecord(ExecuteADD_General);
            _opTable[0x02] = new OpCodeRecord(ExecuteADD_General);
            _opTable[0x03] = new OpCodeRecord(ExecuteADD_General);
            _opTable[0x04] = new OpCodeRecord(ExecuteADD_Immediate);
            _opTable[0x05] = new OpCodeRecord(ExecuteADD_Immediate);
            _opTable[0x06] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x07] = new OpCodeRecord(Execute_POP);
            _opTable[0x08] = new OpCodeRecord(ExecuteLogical_General);      // OR
            _opTable[0x09] = new OpCodeRecord(ExecuteLogical_General);
            _opTable[0x0a] = new OpCodeRecord(ExecuteLogical_General);
            _opTable[0x0b] = new OpCodeRecord(ExecuteLogical_General);
            _opTable[0x0c] = new OpCodeRecord(ExecuteLogical_Immediate);
            _opTable[0x0d] = new OpCodeRecord(ExecuteLogical_Immediate);
            _opTable[0x0e] = new OpCodeRecord(Execute_PUSH);
            // POP CS is not a valid instruction
            _opTable[0x0f] = new OpCodeRecord(() => { });
            _opTable[0x10] = new OpCodeRecord(ExecuteADD_General);
            _opTable[0x11] = new OpCodeRecord(ExecuteADD_General);
            _opTable[0x12] = new OpCodeRecord(ExecuteADD_General);
            _opTable[0x13] = new OpCodeRecord(ExecuteADD_General);
            _opTable[0x14] = new OpCodeRecord(ExecuteADD_Immediate);
            _opTable[0x15] = new OpCodeRecord(ExecuteADD_Immediate);
            _opTable[0x16] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x17] = new OpCodeRecord(Execute_POP);
            _opTable[0x18] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x19] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x1a] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x1b] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x1c] = new OpCodeRecord(ExecuteSUB_Immediate);
            _opTable[0x1d] = new OpCodeRecord(ExecuteSUB_Immediate);
            _opTable[0x1e] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x1f] = new OpCodeRecord(Execute_POP);
            _opTable[0x20] = new OpCodeRecord(ExecuteLogical_General);     // AND
            _opTable[0x21] = new OpCodeRecord(ExecuteLogical_General);
            _opTable[0x22] = new OpCodeRecord(ExecuteLogical_General);
            _opTable[0x23] = new OpCodeRecord(ExecuteLogical_General);
            _opTable[0x24] = new OpCodeRecord(ExecuteLogical_Immediate);
            _opTable[0x25] = new OpCodeRecord(ExecuteLogical_Immediate);
            //_opTable[0x26]  segment override is processed in the NextInstruction() method
            _opTable[0x27] = new OpCodeRecord(Execute_DecimalAdjustADD);
            _opTable[0x28] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x29] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x2a] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x2b] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x2c] = new OpCodeRecord(ExecuteSUB_Immediate);
            _opTable[0x2d] = new OpCodeRecord(ExecuteSUB_Immediate);
            //_opTable[0x2e]  segment override is processed in the NextInstruction() method
            _opTable[0x2f] = new OpCodeRecord(Execute_DecimalAdjustSUB);
            _opTable[0x30] = new OpCodeRecord(ExecuteLogical_General);  // XOR
            _opTable[0x31] = new OpCodeRecord(ExecuteLogical_General);
            _opTable[0x32] = new OpCodeRecord(ExecuteLogical_General);
            _opTable[0x33] = new OpCodeRecord(ExecuteLogical_General);
            _opTable[0x34] = new OpCodeRecord(ExecuteLogical_Immediate);
            _opTable[0x35] = new OpCodeRecord(ExecuteLogical_Immediate);
            //_opTable[0x36]  segment override is processed in the NextInstruction() method
            _opTable[0x37] = new OpCodeRecord(Execute_AsciiAdjustADD);
            _opTable[0x38] = new OpCodeRecord(ExecuteSUB_General);       // CMP
            _opTable[0x39] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x3a] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x3b] = new OpCodeRecord(ExecuteSUB_General);
            _opTable[0x3c] = new OpCodeRecord(ExecuteSUB_Immediate);
            _opTable[0x3d] = new OpCodeRecord(ExecuteSUB_Immediate);
            //_opTable[0x3e]  segment override is processed in the NextInstruction() method
            _opTable[0x3f] = new OpCodeRecord(Execute_AsciiAdjustSUB);
            _opTable[0x40] = new OpCodeRecord(ExecuteINC);
            _opTable[0x41] = new OpCodeRecord(ExecuteINC);
            _opTable[0x42] = new OpCodeRecord(ExecuteINC);
            _opTable[0x43] = new OpCodeRecord(ExecuteINC);
            _opTable[0x44] = new OpCodeRecord(ExecuteINC);
            _opTable[0x45] = new OpCodeRecord(ExecuteINC);
            _opTable[0x46] = new OpCodeRecord(ExecuteINC);
            _opTable[0x47] = new OpCodeRecord(ExecuteINC);
            _opTable[0x48] = new OpCodeRecord(ExecuteDEC);
            _opTable[0x49] = new OpCodeRecord(ExecuteDEC);
            _opTable[0x4a] = new OpCodeRecord(ExecuteDEC);
            _opTable[0x4b] = new OpCodeRecord(ExecuteDEC);
            _opTable[0x4c] = new OpCodeRecord(ExecuteDEC);
            _opTable[0x4d] = new OpCodeRecord(ExecuteDEC);
            _opTable[0x4e] = new OpCodeRecord(ExecuteDEC);
            _opTable[0x4f] = new OpCodeRecord(ExecuteDEC);
            _opTable[0x50] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x51] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x52] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x53] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x54] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x55] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x56] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x57] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x58] = new OpCodeRecord(Execute_POP);
            _opTable[0x59] = new OpCodeRecord(Execute_POP);
            _opTable[0x5a] = new OpCodeRecord(Execute_POP);
            _opTable[0x5b] = new OpCodeRecord(Execute_POP);
            _opTable[0x5c] = new OpCodeRecord(Execute_POP);
            _opTable[0x5d] = new OpCodeRecord(Execute_POP);
            _opTable[0x5e] = new OpCodeRecord(Execute_POP);
            _opTable[0x5f] = new OpCodeRecord(Execute_POP);
            _opTable[0x60] = new OpCodeRecord(Execute_PUSHA);
            _opTable[0x61] = new OpCodeRecord(Execute_POPA);
            _opTable[0x62] = new OpCodeRecord(Execute_Bound);
            _opTable[0x63] = new OpCodeRecord(() => { throw new InvalidOperationException("Instruction 0x63 is not implemented"); });
            _opTable[0x64] = new OpCodeRecord(() => { throw new InvalidOperationException("Instruction 0x64 is not implemented"); });
            _opTable[0x65] = new OpCodeRecord(() => { throw new InvalidOperationException("Instruction 0x65 is not implemented"); });
            _opTable[0x66] = new OpCodeRecord(() => { throw new InvalidOperationException("Instruction 0x66 is not implemented"); });
            _opTable[0x67] = new OpCodeRecord(() => { throw new InvalidOperationException("Instruction 0x67 is not implemented"); });
            _opTable[0x68] = new OpCodeRecord(() =>  // PUSH imm-16
            {
                Push(GetImmediate16());
            });
            _opTable[0x69] = new OpCodeRecord(() => // IMUL REG-16, RM-16, Imm
            {
                byte mod = 0, reg = 0, rm = 0;
                SplitAddrByte(_bus.NextIP(), ref mod, ref reg, ref rm);

                int word_size = GetWordSize();
                int direction = GetDirection();

                ushort oper1 = (ushort)GetSourceData(direction, word_size, mod, reg, rm);
                ushort oper2 = GetImmediate16();

                uint oper1ext = SignExtend32(oper1);
                uint oper2ext = SignExtend32(oper2);

                uint result = oper1ext * oper2ext;

                SaveToDestination((ushort)(result & 0xffff), direction, word_size, mod, reg, rm);

                if( (result & 0xffff0000) != 0 )
                {
                    _creg.CarryFlag = true;
                    _creg.OverflowFlag = true;
                }
                else
                {
                    _creg.CarryFlag = false;
                    _creg.OverflowFlag = false;
                }

            });
            _opTable[0x6a] = new OpCodeRecord(() =>  // PUSH imm-8
            {
                Push(_bus.NextIP());
            });
            _opTable[0x6b] = new OpCodeRecord(() =>
            {
                byte mod = 0, reg = 0, rm = 0;
                SplitAddrByte(_bus.NextIP(), ref mod, ref reg, ref rm);

                int word_size = GetWordSize();
                int direction = GetDirection();

                ushort oper1 = (ushort)GetSourceData(direction, word_size, mod, reg, rm);
                ushort oper2 = _bus.NextIP();

                uint oper1ext = SignExtend32(oper1);
                uint oper2ext = SignExtend32(oper2);

                uint result = oper1ext * oper2ext;

                SaveToDestination((ushort)(result & 0xffff), direction, word_size, mod, reg, rm);

                if ((result & 0xffff0000) != 0)
                {
                    _creg.CarryFlag = true;
                    _creg.OverflowFlag = true;
                }
                else
                {
                    _creg.CarryFlag = false;
                    _creg.OverflowFlag = false;
                }
            });

            _opTable[0x6c] = new OpCodeRecord(() => // INSB
            {
                // if repetition is on but CX is 0 then do nothing
                if( ( _repeat ) && ( _reg.CX == 0 ) )
                {
                }
                else
                {
                    do
                    {
                        Execute_IN_String();

                        if (_creg.DirectionFlag)
                            _reg.DI--;
                        else
                            _reg.DI++;

                        if (_repeat)
                            _reg.CX--;
                    } while (_reg.CX != 0);
                    _repeat = false;
                }
            });
            _opTable[0x6d] = new OpCodeRecord(() => // INSW
            {
                // if repetition is on but CX is 0 then do nothing
                if ((_repeat) && (_reg.CX == 0))
                {
                }
                else
                {
                    do
                    {
                        Execute_IN_String();

                            if (_creg.DirectionFlag)
                                _reg.DI -= 2;
                            else
                                _reg.DI += 2;

                        if (_repeat)
                            _reg.CX--;
                    } while (_reg.CX != 0);
                    _repeat = false;
                }
            });
            _opTable[0x6e] = new OpCodeRecord(() => // OUTSB
            {
                // if repetition is on but CX is 0 then do nothing
                if ((_repeat) && (_reg.CX == 0))
                {
                }
                else
                {
                    do
                    {
                        Execute_OUT_String();

                        if (_creg.DirectionFlag)
                            _reg.SI -= 1;
                        else
                            _reg.SI += 1;

                        if (_repeat)
                            _reg.CX--;
                    } while (_reg.CX != 0);
                    _repeat = false;
                }
            });
            _opTable[0x6f] = new OpCodeRecord(() => // OUTSW
            {
                // if repetition is on but CX is 0 then do nothing
                if ((_repeat) && (_reg.CX == 0))
                {
                }
                else
                {
                    do
                    {
                        Execute_OUT_String();

                        if (_creg.DirectionFlag)
                            _reg.SI -= 2;
                        else
                            _reg.SI += 2;

                        if (_repeat)
                            _reg.CX--;
                    } while (_reg.CX != 0);
                    _repeat = false;
                }
            });
            _opTable[0x70] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x71] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x72] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x73] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x74] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x75] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x76] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x77] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x78] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x79] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x7a] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x7b] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x7c] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x7d] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x7e] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x7f] = new OpCodeRecord(Execute_CondJump);
            _opTable[0x80] = new OpCodeRecord(Execute_Group1);
            _opTable[0x81] = new OpCodeRecord(Execute_Group1);
            _opTable[0x82] = new OpCodeRecord(Execute_Group1);
            _opTable[0x83] = new OpCodeRecord(Execute_Group1);
            _opTable[0x84] = new OpCodeRecord(ExecuteLogical_General);  // TEST
            _opTable[0x85] = new OpCodeRecord(ExecuteLogical_General);  // TEST
            _opTable[0x86] = new OpCodeRecord(ExecuteXCHG_General);
            _opTable[0x87] = new OpCodeRecord(ExecuteXCHG_General);
            _opTable[0x88] = new OpCodeRecord(ExecuteMOV_General);
            _opTable[0x89] = new OpCodeRecord(ExecuteMOV_General);
            _opTable[0x8a] = new OpCodeRecord(ExecuteMOV_General);
            _opTable[0x8b] = new OpCodeRecord(ExecuteMOV_General);
            _opTable[0x8c] = new OpCodeRecord(ExecuteMOV_SReg);
            _opTable[0x8d] = new OpCodeRecord(Execute_LEA);
            _opTable[0x8e] = new OpCodeRecord(ExecuteMOV_SReg);  // MOV CS - this should never be used in practice
            _opTable[0x8f] = new OpCodeRecord(Execute_POP);
            _opTable[0x90] = new OpCodeRecord(ExecuteXCHG_AX);
            _opTable[0x91] = new OpCodeRecord(ExecuteXCHG_AX);
            _opTable[0x92] = new OpCodeRecord(ExecuteXCHG_AX);
            _opTable[0x93] = new OpCodeRecord(ExecuteXCHG_AX);
            _opTable[0x94] = new OpCodeRecord(ExecuteXCHG_AX);
            _opTable[0x95] = new OpCodeRecord(ExecuteXCHG_AX);
            _opTable[0x96] = new OpCodeRecord(ExecuteXCHG_AX);
            _opTable[0x97] = new OpCodeRecord(ExecuteXCHG_AX);
            _opTable[0x98] = new OpCodeRecord(Execute_CBW);
            _opTable[0x99] = new OpCodeRecord(Execute_CWD);
            _opTable[0x9a] = new OpCodeRecord(Execute_CallFar);
            _opTable[0x9b] = new OpCodeRecord(() => { }); // WAIT (for now NOP)
            _opTable[0x9c] = new OpCodeRecord(Execute_PUSH);
            _opTable[0x9d] = new OpCodeRecord(Execute_POP);
            // SAHF - Store SH to flags
            _opTable[0x9e] = new OpCodeRecord(() => { _creg.Register = new DataRegister16((byte)(_creg.Register >> 8), _reg.AH); });
            // LAHF - Load AH from flags
            _opTable[0x9f] = new OpCodeRecord( () => { _reg.AH = (byte)(_creg.Register & 0x00ff); });
            _opTable[0xa0] = new OpCodeRecord(ExecuteMOV_Mem);
            _opTable[0xa1] = new OpCodeRecord(ExecuteMOV_Mem);
            _opTable[0xa2] = new OpCodeRecord(ExecuteMOV_Mem);
            _opTable[0xa3] = new OpCodeRecord(ExecuteMOV_Mem);
            _opTable[0xa4] = new OpCodeRecord(Execute_MoveString);
            _opTable[0xa5] = new OpCodeRecord(Execute_MoveString);
            _opTable[0xa6] = new OpCodeRecord(Execute_CompareString);
            _opTable[0xa7] = new OpCodeRecord(Execute_CompareString);
            _opTable[0xa8] = new OpCodeRecord(ExecuteLogical_Immediate);
            _opTable[0xa9] = new OpCodeRecord(ExecuteLogical_Immediate);
            _opTable[0xaa] = new OpCodeRecord(Execute_StoreString);
            _opTable[0xab] = new OpCodeRecord(Execute_StoreString);
            _opTable[0xac] = new OpCodeRecord(Execute_LoadString);
            _opTable[0xad] = new OpCodeRecord(Execute_LoadString);
            _opTable[0xae] = new OpCodeRecord(Execute_ScanString);
            _opTable[0xaf] = new OpCodeRecord(Execute_ScanString);
            _opTable[0xb0] = new OpCodeRecord(ExecuteMOV_Imm8);
            _opTable[0xb1] = new OpCodeRecord(ExecuteMOV_Imm8);
            _opTable[0xb2] = new OpCodeRecord(ExecuteMOV_Imm8);
            _opTable[0xb3] = new OpCodeRecord(ExecuteMOV_Imm8);
            _opTable[0xb4] = new OpCodeRecord(ExecuteMOV_Imm8);
            _opTable[0xb5] = new OpCodeRecord(ExecuteMOV_Imm8);
            _opTable[0xb6] = new OpCodeRecord(ExecuteMOV_Imm8);
            _opTable[0xb7] = new OpCodeRecord(ExecuteMOV_Imm8);
            _opTable[0xb8] = new OpCodeRecord(ExecuteMOV_Imm16);
            _opTable[0xb9] = new OpCodeRecord(ExecuteMOV_Imm16);
            _opTable[0xba] = new OpCodeRecord(ExecuteMOV_Imm16);
            _opTable[0xbb] = new OpCodeRecord(ExecuteMOV_Imm16);
            _opTable[0xbc] = new OpCodeRecord(ExecuteMOV_Imm16);
            _opTable[0xbd] = new OpCodeRecord(ExecuteMOV_Imm16);
            _opTable[0xbe] = new OpCodeRecord(ExecuteMOV_Imm16);
            _opTable[0xbf] = new OpCodeRecord(ExecuteMOV_Imm16);
            // GRP2 rm-8 imm-8 (80186)
            _opTable[0xc0] = new OpCodeRecord(Execute_RotateAndShift);
            // GRP2 rm-16 imm-16 (80186)
            _opTable[0xc1] = new OpCodeRecord(Execute_RotateAndShift);

            _opTable[0xc2] = new OpCodeRecord(() => // ret imm-16
            {
                ushort oper = GetImmediate16();
                _bus.IP = Pop();
                _reg.SP += oper;
            });
            _opTable[0xc3] = new OpCodeRecord(() => // ret
            {
                _bus.IP = Pop();
            });
            _opTable[0xc4] = new OpCodeRecord(Execute_LDS_LES);
            _opTable[0xc5] = new OpCodeRecord(Execute_LDS_LES);
            _opTable[0xc6] = new OpCodeRecord(ExecuteMOV_c6);
            _opTable[0xc7] = new OpCodeRecord(ExecuteMOV_c7);
            _opTable[0xc8] = new OpCodeRecord(() => { throw new InvalidOperationException("Instruction 0xc8 is not implemented"); });
            _opTable[0xc9] = new OpCodeRecord(() => { throw new InvalidOperationException("Instruction 0xc9 is not implemented"); });
            _opTable[0xca] = new OpCodeRecord(() => // retf imm-16
            {
                ushort oper = GetImmediate16();
                _bus.IP = Pop();
                _bus.CS = Pop();
                _reg.SP += oper;
            });
            _opTable[0xcb] = new OpCodeRecord(() => // retf
            {
                _bus.IP = Pop();
                _bus.CS = Pop();
            });
            _opTable[0xcc] = new OpCodeRecord(() => { Interrupt(3); });
            _opTable[0xcd] = new OpCodeRecord(() => { Interrupt(_bus.NextIP()); });
            _opTable[0xce] = new OpCodeRecord(() => { if (_creg.OverflowFlag) Interrupt(4); });
            _opTable[0xcf] = new OpCodeRecord(() => // iret
            {
                _bus.IP = Pop();
                _bus.CS = Pop();
                _creg.Register = Pop();
            });
            _opTable[0xd0] = new OpCodeRecord(Execute_RotateAndShift);
            _opTable[0xd1] = new OpCodeRecord(Execute_RotateAndShift);
            _opTable[0xd2] = new OpCodeRecord(Execute_RotateAndShift);
            _opTable[0xd3] = new OpCodeRecord(Execute_RotateAndShift);
            _opTable[0xd4] = new OpCodeRecord(Execute_AsciiAdjustMUL);
            _opTable[0xd5] = new OpCodeRecord(Execute_AsciiAdjustDIV);
            // undocumented SALC instruction
            _opTable[0xd6] = new OpCodeRecord(() => { if (_creg.CarryFlag) _reg.AL = 0xff; else _reg.AL = 0x00; });
            _opTable[0xd7] = new OpCodeRecord(Execute_XLAT);

            // D8-DF ESC OPCODE,SOURCE (to math co-processor)
            // these are unsupported but they use the address byte so this should read
            _opTable[0xd8] = new OpCodeRecord(() => { _bus.NextIP(); } );
            _opTable[0xd9] = new OpCodeRecord(() => { _bus.NextIP(); });
            _opTable[0xda] = new OpCodeRecord(() => { _bus.NextIP(); });
            _opTable[0xdb] = new OpCodeRecord(() => { _bus.NextIP(); });
            _opTable[0xdc] = new OpCodeRecord(() => { _bus.NextIP(); });
            _opTable[0xdd] = new OpCodeRecord(() => { _bus.NextIP(); });
            _opTable[0xde] = new OpCodeRecord(() => { _bus.NextIP(); });
            _opTable[0xdf] = new OpCodeRecord(() => { _bus.NextIP(); });

            _opTable[0xe0] = new OpCodeRecord(Execute_Loop);
            _opTable[0xe1] = new OpCodeRecord(Execute_Loop);
            _opTable[0xe2] = new OpCodeRecord(Execute_Loop);
            _opTable[0xe3] = new OpCodeRecord(Execute_JumpCXZ);
            _opTable[0xe4] = new OpCodeRecord(Execute_IN);
            _opTable[0xe5] = new OpCodeRecord(Execute_IN);
            _opTable[0xe6] = new OpCodeRecord(Execute_OUT);
            _opTable[0xe7] = new OpCodeRecord(Execute_OUT);
            _opTable[0xe8] = new OpCodeRecord(Execute_CallNear);
            _opTable[0xe9] = new OpCodeRecord(Execute_JumpNear);
            _opTable[0xea] = new OpCodeRecord(Execute_JumpFar);
            _opTable[0xeb] = new OpCodeRecord(Execute_JumpShort);
            _opTable[0xec] = new OpCodeRecord(Execute_IN);
            _opTable[0xed] = new OpCodeRecord(Execute_IN);
            _opTable[0xee] = new OpCodeRecord(Execute_OUT);
            _opTable[0xef] = new OpCodeRecord(Execute_OUT);
            _opTable[0xf0] = new OpCodeRecord(() => { }); // LOCK
            _opTable[0xf1] = new OpCodeRecord(() => { }); // officially undocumented opcode
            // F2 REPNE/REPNZ
            _opTable[0xf2] = new OpCodeRecord(() =>
            {
                _repeat = true;
                _repeatType = 1;
            });
            // F3 REP/E/Z
            _opTable[0xf3] = new OpCodeRecord(() =>
            {
                _repeat = true;
                _repeatType = 2;
            });
            _opTable[0xf4] = new OpCodeRecord(() => // F4 HLT
            {
                _bus.IP--;
                Halted = true;
            });
            _opTable[0xf5] = new OpCodeRecord(() => { _creg.CarryFlag = !_creg.CarryFlag; });  // CMC - complement carry flag
            _opTable[0xf6] = new OpCodeRecord(Execute_Group3);
            _opTable[0xf7] = new OpCodeRecord(Execute_Group3);
            _opTable[0xf8] = new OpCodeRecord(() => { _creg.CarryFlag = false; });  // F8 CLC - clear carry flag
            _opTable[0xf9] = new OpCodeRecord(() => { _creg.CarryFlag = true; });  // F9 STC - set carry flag
            _opTable[0xfa] = new OpCodeRecord(() => { _creg.InterruptEnable = false; });  // FA CLI - clear interrupt flag
            _opTable[0xfb] = new OpCodeRecord(() => { _creg.InterruptEnable = true; });  // FB STI - set interrupt flag
            _opTable[0xfc] = new OpCodeRecord(() => { _creg.DirectionFlag = false; });  // FC CLD - clear direction flag
            _opTable[0xfd] = new OpCodeRecord(() => { _creg.DirectionFlag = true; });  // FD STD - set direction flag
            _opTable[0xfe] = new OpCodeRecord(Execute_Group4);
            _opTable[0xff] = new OpCodeRecord(Execute_Group5);
        }