Beispiel #1
0
            protected override void ExecuteSpecialFunction2Early(MicroInstruction instruction)
            {
                EmulatorF2 ef2 = (EmulatorF2)instruction.F2;

                switch (ef2)
                {
                case EmulatorF2.ACSOURCE:
                    // Early: modify R select field:
                    // "...it replaces the two-low order bits of the R select field with
                    // the complement of the SrcAC field of IR, (IR[1-2] XOR 3), allowing the emulator
                    // to address its accumulators (which are assigned to R0-R3)."
                    _rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x6000) >> 13) ^ 3);
                    break;

                case EmulatorF2.ACDEST:
                // "...causes (IR[3-4] XOR 3) to be used as the low-order two bits of the RSELECT field.
                // This address the accumulators from the destination field of the instruction.  The selected
                // register may be loaded or read."
                case EmulatorF2.LoadDNS:
                    //
                    // "...DNS also addresses R from (3-IR[3 - 4])..."
                    //
                    _rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x1800) >> 11) ^ 3);
                    break;
                }
            }
Beispiel #2
0
        private static string DisassembleEmulatorSpecialFunction2(MicroInstruction instruction)
        {
            EmulatorF2 ef2 = (EmulatorF2)instruction.F2;

            switch (ef2)
            {
            case EmulatorF2.ACDEST:
                return("ACDEST ");

            case EmulatorF2.ACSOURCE:
                return("ACSOURCE ");

            case EmulatorF2.MAGIC:
                return("MAGIC ");

            case EmulatorF2.LoadDNS:
                return("DNS← ");

            case EmulatorF2.BUSODD:
                return("BUSODD ");

            case EmulatorF2.LoadIR:
                return("IR← ");

            case EmulatorF2.IDISP:
                return("IDISP ");

            default:
                return(String.Format("F2 {0}", Conversion.ToOctal((int)ef2)));
            }
        }
Beispiel #3
0
            protected override void ExecuteSpecialFunction2Late(MicroInstruction instruction)
            {
                EmulatorF2 ef2 = (EmulatorF2)instruction.F2;

                switch (ef2)
                {
                case EmulatorF2.LoadDNS:
                    //
                    // Set SKIP and CARRY flip-flops based on the final result of the operation after having
                    // passed through the shifter.
                    //
                    ushort result = Shifter.Output;
                    int    carry  = Shifter.DNSCarry;
                    switch (_cpu._ir & 0x7)
                    {
                    case 0:
                        // None, SKIP is reset
                        _skip = 0;
                        break;

                    case 1:             // SKP
                        // Always skip
                        _skip = 1;
                        break;

                    case 2:             // SZC
                        // Skip if carry result is zero
                        _skip = (carry == 0) ? 1 : 0;
                        break;

                    case 3:             // SNC
                        // Skip if carry result is nonzero
                        _skip = carry;
                        break;

                    case 4:             // SZR
                        _skip = (result == 0) ? 1 : 0;
                        break;

                    case 5:             // SNR
                        _skip = (result != 0) ? 1 : 0;
                        break;

                    case 6:             // SEZ
                        _skip = (result == 0 || carry == 0) ? 1 : 0;
                        break;

                    case 7:             // SBN
                        _skip = (result != 0 && carry != 0) ? 1 : 0;
                        break;
                    }

                    if (_loadR)
                    {
                        // Write carry flag back.
                        _carry = carry;
                    }

                    break;
                }
            }
Beispiel #4
0
            protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
            {
                EmulatorF2 ef2 = (EmulatorF2)instruction.F2;

                switch (ef2)
                {
                case EmulatorF2.LoadIR:
                    // Load IR from the bus
                    _cpu._ir = _busData;

                    // "IR<- also merges bus bits 0, 5, 6 and 7 into NEXT[6-9] which does a first level
                    // instruction dispatch."
                    _nextModifier |= (ushort)(((_busData & 0x8000) >> 12) | ((_busData & 0x0700) >> 8));

                    // "IR<- clears SKIP"
                    _skip = 0;
                    break;

                case EmulatorF2.IDISP:
                    // "The IDISP function (F2=15B) does a 16 way dispatch under control of a PROM and a
                    // multiplexer.  The values are tabulated below:
                    //   Conditions             ORed onto NEXT          Comment
                    //
                    //   if IR[0] = 1           3-IR[8-9]               complement of SH field of IR
                    //   elseif IR[1-2] = 0     IR[3-4]                 JMP, JSR, ISZ, DSZ              ; dispatch selects register
                    //   elseif IR[1-2] = 1     4                       LDA
                    //   elseif IR[1-2] = 2     5                       STA
                    //   elseif IR[4-7] = 0     1
                    //   elseif IR[4-7] = 1     0
                    //   elseif IR[4-7] = 6     16B                     CONVERT
                    //   elseif IR[4-7] = 16B   6
                    //   else                   IR[4-7]
                    // NB: as always, Xerox labels bits in the opposite order from modern convention;
                    // (bit 0 is the msb...)
                    //
                    // NOTE: The above table is accurate and functions correctly; using the PROM is faster.
                    //
                    if ((_cpu._ir & 0x8000) != 0)
                    {
                        _nextModifier |= (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
                    }
                    else
                    {
                        _nextModifier |= ControlROM.ACSourceROM[((_cpu._ir & 0x7f00) >> 8) + 0x80];
                    }
                    break;

                case EmulatorF2.ACSOURCE:
                    // Late:
                    // "...a dispatch is performed:
                    //   Conditions             ORed onto NEXT          Comment
                    //
                    //   if IR[0] = 1           3-IR[8-9]               complement of SH field of IR
                    //   if IR[1-2] != 3        IR[5]                   the Indirect bit of R
                    //   if IR[3-7] = 0         2                       CYCLE
                    //   if IR[3-7] = 1         5                       RAMTRAP
                    //   if IR[3-7] = 2         3                       NOPAR -- parameterless opcode group
                    //   if IR[3-7] = 3         6                       RAMTRAP
                    //   if IR[3-7] = 4         7                       RAMTRAP
                    //   if IR[3-7] = 11B       4                       JSRII
                    //   if IR[3-7] = 12B       4                       JSRIS
                    //   if IR[3-7] = 16B       1                       CONVERT
                    //   if IR[3-7] = 37B       17B                     ROMTRAP -- used by Swat, the debugger
                    //   else                   16B                     ROMTRAP

                    //
                    // NOTE: The above table is accurate and functions correctly; using the PROM is faster.
                    //
                    if ((_cpu._ir & 0x8000) != 0)
                    {
                        // 3-IR[8-9] (shift field of arithmetic instruction)
                        _nextModifier |= (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
                    }
                    else
                    {
                        // Use the PROM.
                        _nextModifier |= ControlROM.ACSourceROM[((_cpu._ir & 0x7f00) >> 8)];
                    }

                    break;

                case EmulatorF2.ACDEST:
                    // Handled in early handler, nothing to do here.
                    break;

                case EmulatorF2.BUSODD:
                    // "...merges BUS[15] into NEXT[9]."
                    _nextModifier |= (ushort)(_busData & 0x1);
                    break;

                case EmulatorF2.MAGIC:
                    Shifter.SetModifier(ShifterModifier.Magic);
                    break;

                case EmulatorF2.LoadDNS:
                    // DNS<- does the following:
                    // - modifies the normal shift operations to perform Nova-style shifts (done here)
                    // - addresses R from 3-IR[3-4] (destination AC)  (see Early LoadDNS handler)
                    // - stores into R unless IR[12] is set (done here)
                    //   [NOTE: This overrides a LoadR BS field if present -- that is, if IR[12] is set and
                    //    BS=LoadR, no load into R will take place.  Note also that the standard
                    //    microcode apparently always specifies a LoadR BS for LoadDNS microinstructions.  Need to
                    //    look at the schematics more closely to see if this is required or just a convention
                    //    of the PARC microassembler.]
                    // - calculates Nova-style CARRY bit (done here)
                    // - sets the SKIP and CARRY flip-flops appropriately (see Late LoadDNS handler)
                    int carry = 0;

                    // Also indicates modifying CARRY
                    _loadR = (_cpu._ir & 0x0008) == 0;

                    // At this point the ALU has already done its operation but the shifter has not yet run.
                    // We need to set the CARRY bit that will be passed through the shifter appropriately.

                    // Select carry input value based on carry control
                    switch ((_cpu._ir & 0x30) >> 4)
                    {
                    case 0x0:
                        // Nothing; CARRY unaffected.
                        carry = _carry;
                        break;

                    case 0x1:
                        carry = 0;          // Z
                        break;

                    case 0x2:
                        carry = 1;          // O
                        break;

                    case 0x3:
                        carry = (~_carry) & 0x1;          // C
                        break;
                    }

                    // Now modify the result based on the current ALU result
                    switch ((_cpu._ir & 0x700) >> 8)
                    {
                    case 0x0:
                    case 0x2:
                    case 0x7:
                        // COM, MOV, AND - Carry unaffected
                        break;

                    case 0x1:
                    case 0x3:
                    case 0x4:
                    case 0x5:
                    case 0x6:
                        // NEG, INC, ADC, SUB, ADD - invert the carry bit
                        if (_cpu._aluC0 != 0)
                        {
                            carry = (~carry) & 0x1;
                        }
                        break;
                    }

                    // Tell the Shifter to do a Nova-style shift with the
                    // given carry bit.
                    Shifter.SetModifier(ShifterModifier.DNS);
                    Shifter.DNSCarry = carry;

                    break;

                default:
                    throw new InvalidOperationException(String.Format("Unhandled emulator F2 {0}.", ef2));
                }
            }