private void ComputeFlagsForIOBlockInstruction(IOBlockInstructionType instructionType)
        {
            // The out instructions behave differently than the in instructions, which doesn’t make the CPU very symmetrical.
            // First of all, all instructions affect the following flags:
            F = 0;

            // SF, ZF, YF, XF flags Affected by decreasing register B, as in DEC B.
                // For OUT instructions, B has already been decremented when we compute flags
                byte decB = B;
                // For IN instructions, B has not yet been decremented when we compute flags, so we consider B-1
                if (instructionType == IOBlockInstructionType.IND || instructionType == IOBlockInstructionType.INI)
                {
                    decB = (byte)(B - 1);
                }
                // Flags bit 7 - SF flag - Set if the 2-complement value is negative. It's simply a copy of the most signifcant bit of the result.
                F |= (byte)(decB & B10000000);
                // Flags bit 6 - ZF flag Set if the result is zero.
                if (decB == 0) F |= B01000000;
                // Flags bit 5 - YF flag - A copy of bit 5 of the result.
                // Flags bit 3 - XF flag - A copy of bit 3 of the result.
                F |= (byte)(decB & B00101000);

            // NF flag A copy of bit 7 of the value read from or written to an I/O port.
            NF = (InternalDataBus & B10000000) != 0;

            int k = 0;
            // And now the for OUTI/OTIR/OUTD/OTDR instructions.
            if (instructionType == IOBlockInstructionType.OUT)
            {
                // Take state of the L after the increment or decrement of HL; add the value written to the I/O port to; call that k for now.
                // HF and CF Both set if ((HL) + L > 255)
                // PF The parity of ((((HL) + L) & 7) xor B)
                k = InternalDataBus + L;
            }
            else
            {
                // INI/INIR/IND/INDR use the C register in stead of the L register.
                // There is a catch though, because not the value of C is used, but C + 1 if it’s INI/INIR or C - 1 if it’s IND/INDR.

                // So, first of all INI/INIR:
                if (instructionType == IOBlockInstructionType.INI)
                {
                    // HF and CF Both set if ((HL) + ((C + 1) & 255) > 255)
                    // PF The parity of (((HL) + ((C + 1) & 255)) & 7) xor B)
                    k = InternalDataBus + ((C + 1) & 255);
                }
                // And last IND/INDR:
                else if (instructionType == IOBlockInstructionType.IND)
                {
                    // HF and CF Both set if ((HL) + ((C - 1) & 255) > 255)
                    // PF The parity of (((HL) + ((C - 1) & 255)) & 7) xor B)
                    k = InternalDataBus + ((C - 1) & 255);
                }
            }

            // If k > 255, then the CF and HF flags are set.
            // HF and CF Both set if ((HL) + L > 255)
            CF = k > 255;
            HF = k > 255;

            // The PF flags is set like the parity of k bitwise and’ed with 7, bitwise xor’ed with B.
            // PF The parity of ((((HL) + L) & 7) xor B)
            PF = numberOfBitsInByteParityTable[(byte)((k & 7) ^ decB)];

            if (TraceMicroInstructions)
            {
                TraceMicroInstruction(new MicroInstruction(Z80MicroInstructionTypes.FlagsOperationComputeFlagsForIOBlockInstruction));
            }
        }
Exemplo n.º 2
0
        private void ComputeFlagsForIOBlockInstruction(IOBlockInstructionType instructionType)
        {
            // The out instructions behave differently than the in instructions, which doesn’t make the CPU very symmetrical.
            // First of all, all instructions affect the following flags:
            F = 0;

            // SF, ZF, YF, XF flags Affected by decreasing register B, as in DEC B.
            // For OUT instructions, B has already been decremented when we compute flags
            byte decB = B;

            // For IN instructions, B has not yet been decremented when we compute flags, so we consider B-1
            if (instructionType == IOBlockInstructionType.IND || instructionType == IOBlockInstructionType.INI)
            {
                decB = (byte)(B - 1);
            }
            // Flags bit 7 - SF flag - Set if the 2-complement value is negative. It's simply a copy of the most signifcant bit of the result.
            F |= (byte)(decB & B10000000);
            // Flags bit 6 - ZF flag Set if the result is zero.
            if (decB == 0)
            {
                F |= B01000000;
            }
            // Flags bit 5 - YF flag - A copy of bit 5 of the result.
            // Flags bit 3 - XF flag - A copy of bit 3 of the result.
            F |= (byte)(decB & B00101000);

            // NF flag A copy of bit 7 of the value read from or written to an I/O port.
            NF = (InternalDataBus & B10000000) != 0;

            int k = 0;

            // And now the for OUTI/OTIR/OUTD/OTDR instructions.
            if (instructionType == IOBlockInstructionType.OUT)
            {
                // Take state of the L after the increment or decrement of HL; add the value written to the I/O port to; call that k for now.
                // HF and CF Both set if ((HL) + L > 255)
                // PF The parity of ((((HL) + L) & 7) xor B)
                k = InternalDataBus + L;
            }
            else
            {
                // INI/INIR/IND/INDR use the C register in stead of the L register.
                // There is a catch though, because not the value of C is used, but C + 1 if it’s INI/INIR or C - 1 if it’s IND/INDR.

                // So, first of all INI/INIR:
                if (instructionType == IOBlockInstructionType.INI)
                {
                    // HF and CF Both set if ((HL) + ((C + 1) & 255) > 255)
                    // PF The parity of (((HL) + ((C + 1) & 255)) & 7) xor B)
                    k = InternalDataBus + ((C + 1) & 255);
                }
                // And last IND/INDR:
                else if (instructionType == IOBlockInstructionType.IND)
                {
                    // HF and CF Both set if ((HL) + ((C - 1) & 255) > 255)
                    // PF The parity of (((HL) + ((C - 1) & 255)) & 7) xor B)
                    k = InternalDataBus + ((C - 1) & 255);
                }
            }

            // If k > 255, then the CF and HF flags are set.
            // HF and CF Both set if ((HL) + L > 255)
            CF = k > 255;
            HF = k > 255;

            // The PF flags is set like the parity of k bitwise and’ed with 7, bitwise xor’ed with B.
            // PF The parity of ((((HL) + L) & 7) xor B)
            PF = numberOfBitsInByteParityTable[(byte)((k & 7) ^ decB)];

            if (TraceMicroInstructions)
            {
                TraceMicroInstruction(new MicroInstruction(Z80MicroInstructionTypes.FlagsOperationComputeFlagsForIOBlockInstruction));
            }
        }