private void MoveToNextCAMHalfWord() { if (_camHalf == ImmediateHalf.Second) { _pc++; _camWord = _mem.Fetch(_pc); _camHalf = ImmediateHalf.First; // Update the instruction cache with the type of instruction (to aid in debugging). PDS4DisplayInstruction instruction = GetCachedInstruction(_pc, DisplayProcessorMode.CompactAddressing); } else { _camHalf = ImmediateHalf.Second; } }
private void MoveToNextHalfWord() { if (_immediateHalf == ImmediateHalf.Second) { _pc++; _immediateWord = _mem.Fetch(_pc); _immediateHalf = ImmediateHalf.First; // Update the instruction cache with the type of instruction (to aid in debugging). PDS4DisplayInstruction instruction = GetCachedInstruction(_pc, DisplayProcessorMode.Increment); } else { _immediateHalf = ImmediateHalf.Second; } }
public override void InitializeCache() { _instructionCache = new PDS4DisplayInstruction[Memory.Size]; }
private void ExecuteProcessor() { PDS4DisplayInstruction instruction = GetCachedInstruction(_pc, DisplayProcessorMode.Processor); instruction.UsageMode = DisplayProcessorMode.Processor; switch (instruction.Opcode) { case DisplayOpcode.DEIM: _mode = DisplayProcessorMode.Increment; _immediateWord = instruction.Data; _immediateHalf = ImmediateHalf.Second; if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "Enter increment mode"); } break; case DisplayOpcode.DJMP: if (!_dadr) { // DADR off, use only 12 bits _pc = (ushort)((instruction.Data & 0xfff) | _block); } else { _pc = (ushort)(instruction.Data | _block); } break; case DisplayOpcode.DJMS: Push(); if (!_dadr) { // DADR off, use only 12 bits _pc = (ushort)((instruction.Data & 0xfff) | _block); } else { _pc = (ushort)(instruction.Data | _block); } break; case DisplayOpcode.DOPR: // Each of bits 4-11 can be combined in any fashion // to do a number of operations simultaneously; we walk the bits // and perform the operations as set. if ((instruction.Data & 0x800) == 0) { // DHLT -- halt the display processor. other micro-ops in this // instruction are still run. HaltProcessor(); } // Used to modify DSTS or DSTB operation bool bit5 = (instruction.Data & 0x400) != 0; if ((instruction.Data & 0x200) != 0) { // DIXM -- increment X DAC MSB X += MSBIncrement; _system.Display.MoveAbsolute(X, Y, DrawingMode.Off); if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "DIXM, X is now {0}", X); } } if ((instruction.Data & 0x100) != 0) { // DIYM -- increment Y DAC MSB Y += MSBIncrement; _system.Display.MoveAbsolute(X, Y, DrawingMode.Off); if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "DIYM, Y is now {0}", Y); } } if ((instruction.Data & 0x80) != 0) { // DDXM - decrement X DAC MSB X -= MSBIncrement; _system.Display.MoveAbsolute(X, Y, DrawingMode.Off); if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "DDXM, X is now {0}", X); } } if ((instruction.Data & 0x40) != 0) { // DDYM - decrement y DAC MSB Y -= MSBIncrement; _system.Display.MoveAbsolute(X, Y, DrawingMode.Off); if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "DDYM, Y is now {0}", Y); } } if ((instruction.Data & 0x20) != 0) { // DRJM - return from display subroutine ReturnFromDisplaySubroutine(); _pc--; // hack (we add +1 at the end...) } if ((instruction.Data & 0x10) != 0) { // DDSP -- intensify point on screen for 1.8us (one instruction) // at the current position. _system.Display.DrawPoint(X, Y); if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "DDSP at {0},{1}", X, Y); } } // F/C ops: int f = (instruction.Data & 0xc) >> 2; int c = instruction.Data & 0x3; switch (f) { case 0x0: // if bit 15 is set, the MIT mods flip the DADR bit. if (Configuration.MITMode && (c == 1)) { _dadr = !_dadr; } break; case 0x1: // Set scale based on C and Bit 5. _scale = c + (bit5 ? 4 : 0); if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "Scale set to {0}", _scale); } break; case 0x2: _block = (ushort)((c + (bit5 ? 4 : 0) << 12)); break; case 0x3: // TODO: light pen sensitize if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "Light pen, stub!"); } break; } _pc++; break; case DisplayOpcode.DLXA: X = instruction.Data; DrawingMode mode; if (_fxyOn && _fxyBeamOn) { if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "SGR-1 X set to {0}", X); } mode = DrawingMode.SGR1; } else { mode = DrawingMode.Off; if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "X set to {0}", X); } } _system.Display.MoveAbsolute(X, Y, mode); if (_fxyDRJMOn) { ReturnFromDisplaySubroutine(); } else { _pc++; } break; case DisplayOpcode.DLYA: Y = instruction.Data; if (_fxyOn && _fxyBeamOn) { if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "SGR-1 Y set to {0}", Y); } mode = DrawingMode.SGR1; } else { if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "Y set to {0}", Y); } mode = DrawingMode.Off; } _system.Display.MoveAbsolute(X, Y, mode); if (_fxyDRJMOn) { ReturnFromDisplaySubroutine(); } else { _pc++; } break; case DisplayOpcode.DLVH: DrawLongVector(instruction.Data); break; case DisplayOpcode.DFXY: _fxyOn = (instruction.Data & 0x1) != 0; _fxyDRJMOn = (instruction.Data & 0x2) != 0; _fxyBeamOn = (instruction.Data & 0x4) != 0; if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "SGR-1 instruction: Enter {0} BeamOn {1} DRJM {2}", _fxyOn, _fxyBeamOn, _fxyDRJMOn); } _pc++; break; case DisplayOpcode.DVIC: _system.Display.SetIntensity(instruction.Data); _pc++; break; case DisplayOpcode.DCAM: // Enter Compact Addressing Mode, this is supposedly illegal if // we're already in that mode, so we'll throw here to help with debugging if (_camEnabled) { throw new InvalidOperationException("DCAM while in Compact Addressing Mode."); } _camEnabled = true; // subroutine table address is the next word. Low 8-bits should be zero, we'll // sanity check it. _caBase = _mem.Fetch(++_pc); if ((_caBase & 0xff) != 0) { throw new InvalidOperationException( String.Format("CAM subroutine base address {0} not on a 256-word boundary!", Helpers.ToOctal(_caBase))); } // start things off by fetching the first subroutine word. This is not strictly // accurate with respect to timing. (Ok, it's not accurate at all.) // TODO: refactor Immediate halfword routines here (share w/short vectors?) _camWord = _mem.Fetch(++_pc); _camHalf = ImmediateHalf.First; if (Trace.TraceOn) { Trace.Log(LogType.DisplayProcessor, "Enter Compact Addressing mode, base address {0}", Helpers.ToOctal(_caBase)); } _mode = DisplayProcessorMode.CompactAddressing; break; case DisplayOpcode.DBLI: _system.Display.SetBlink((instruction.Data) != 0); _pc++; break; default: throw new NotImplementedException(String.Format("Unimplemented Display Processor Opcode {0}, ({1}), operands {1}", instruction.Opcode, Helpers.ToOctal((ushort)instruction.Opcode), Helpers.ToOctal(instruction.Data))); } // If the next instruction has a breakpoint set we'll halt at this point, before executing it. if (BreakpointManager.TestBreakpoint(BreakpointType.Display, _pc)) { _state = ProcessorState.BreakpointHalt; } }