mirror of
https://github.com/livingcomputermuseum/ContrAlto.git
synced 2026-01-17 08:34:15 +00:00
Refactored Task code into separate files for readability; added breakpoint support and basic Memory window to debugger. Initial implementation (mostly stubs) of Disk hardware and Tasks.
This commit is contained in:
parent
24d7a5a8fe
commit
08d6063def
@ -22,13 +22,15 @@ namespace Contralto.CPU
|
||||
DiskWord = 14,
|
||||
}
|
||||
|
||||
public class AltoCPU
|
||||
public partial class AltoCPU
|
||||
{
|
||||
public AltoCPU(AltoSystem system)
|
||||
{
|
||||
_system = system;
|
||||
|
||||
_tasks[(int)TaskType.Emulator] = new EmulatorTask(this);
|
||||
_tasks[(int)TaskType.DiskSector] = new DiskTask(this, true);
|
||||
_tasks[(int)TaskType.DiskWord] = new DiskTask(this, false);
|
||||
|
||||
Reset();
|
||||
}
|
||||
@ -78,7 +80,6 @@ namespace Contralto.CPU
|
||||
get { return _aluC0; }
|
||||
}
|
||||
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// Reset registers
|
||||
@ -169,769 +170,11 @@ namespace Contralto.CPU
|
||||
if (_tasks[i] != null && _tasks[i].Wakeup)
|
||||
{
|
||||
_nextTask = _tasks[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Task:
|
||||
// Base task class: provides implementation for non-task-specific microcode execution and
|
||||
// state. Task subclasses implement and execute Task-specific behavior and are called into
|
||||
// by the base class as necessary.
|
||||
public abstract class Task
|
||||
{
|
||||
public Task(AltoCPU cpu)
|
||||
{
|
||||
_wakeup = false;
|
||||
_mpc = 0xffff; // invalid, for sanity checking
|
||||
_taskType = TaskType.Invalid;
|
||||
_cpu = cpu;
|
||||
}
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return (int)_taskType; }
|
||||
}
|
||||
|
||||
public bool Wakeup
|
||||
{
|
||||
get { return _wakeup; }
|
||||
}
|
||||
|
||||
public ushort MPC
|
||||
{
|
||||
get { return _mpc; }
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
// From The Alto Hardware Manual (section 2, "Initialization"):
|
||||
// "...each task start[s] at the location which is its task number"
|
||||
//
|
||||
_mpc = (ushort)_taskType;
|
||||
}
|
||||
|
||||
public virtual void BlockTask()
|
||||
{
|
||||
_wakeup = false;
|
||||
}
|
||||
|
||||
public virtual void WakeupTask()
|
||||
{
|
||||
_wakeup = true;
|
||||
}
|
||||
|
||||
public bool ExecuteNext()
|
||||
{
|
||||
// TODO: cache microinstructions (or pre-decode them) to save consing all these up every time.
|
||||
MicroInstruction instruction = new MicroInstruction(UCodeMemory.UCodeROM[_mpc]);
|
||||
return ExecuteInstruction(instruction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ExecuteInstruction causes the Task to execute the next instruction (the one
|
||||
/// _mpc is pointing to). The base implementation covers non-task specific logic; subclasses may
|
||||
/// provide their own overrides.
|
||||
/// </summary>
|
||||
/// <returns>True if a task switch has been requested by a TASK instruction, false otherwise.</returns>
|
||||
protected virtual bool ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
bool nextTask = false;
|
||||
bool loadR = false;
|
||||
ushort aluData = 0;
|
||||
ushort nextModifier = 0;
|
||||
_loadS = false;
|
||||
_rSelect = 0;
|
||||
_busData = 0;
|
||||
|
||||
|
||||
Shifter.SetMagic(false);
|
||||
|
||||
//
|
||||
// Wait for memory state machine if a memory operation is requested by this instruction and
|
||||
// the memory isn't ready yet.
|
||||
// TODO: this needs to be seriously cleaned up.
|
||||
//
|
||||
if (instruction.BS == BusSource.ReadMD ||
|
||||
instruction.F1 == SpecialFunction1.LoadMAR ||
|
||||
instruction.F2 == SpecialFunction2.StoreMD)
|
||||
{
|
||||
|
||||
MemoryOperation op;
|
||||
|
||||
if (instruction.BS == BusSource.ReadMD)
|
||||
{
|
||||
op = MemoryOperation.Read;
|
||||
}
|
||||
else if(instruction.F1 == SpecialFunction1.LoadMAR)
|
||||
{
|
||||
op = MemoryOperation.LoadAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
op = MemoryOperation.Store;
|
||||
}
|
||||
|
||||
if (!_cpu._system.MemoryBus.Ready(op))
|
||||
{
|
||||
// Suspend operation for this cycle.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a modified next field from the last instruction, make sure it gets applied to this one.
|
||||
nextModifier = _nextModifier;
|
||||
_nextModifier = 0;
|
||||
|
||||
_rSelect = instruction.RSELECT;
|
||||
|
||||
// Give tasks the chance to modify parameters early on (like RSELECT)
|
||||
ExecuteSpecialFunction2Early((int)instruction.F2);
|
||||
|
||||
// Select BUS data.
|
||||
if (instruction.F1 != SpecialFunction1.Constant &&
|
||||
instruction.F2 != SpecialFunction2.Constant)
|
||||
{
|
||||
// Normal BUS data (not constant ROM access).
|
||||
switch (instruction.BS)
|
||||
{
|
||||
case BusSource.ReadR:
|
||||
_busData = _cpu._r[_rSelect];
|
||||
break;
|
||||
|
||||
case BusSource.LoadR:
|
||||
_busData = 0; // "Loading R forces the BUS to 0 so that an ALU function of 0 and T may be executed simultaneously"
|
||||
loadR = true;
|
||||
break;
|
||||
|
||||
case BusSource.None:
|
||||
_busData = 0xffff; // "Enables no source to the BUS, leaving it all ones"
|
||||
break;
|
||||
|
||||
case BusSource.TaskSpecific1:
|
||||
case BusSource.TaskSpecific2:
|
||||
_busData = GetBusSource((int)instruction.BS); // task specific -- call into specific implementation
|
||||
break;
|
||||
|
||||
case BusSource.ReadMD:
|
||||
_busData = _cpu._system.MemoryBus.ReadMD();
|
||||
break;
|
||||
|
||||
case BusSource.ReadMouse:
|
||||
//throw new NotImplementedException("ReadMouse bus source not implemented.");
|
||||
_busData = 0; // TODO: implement;
|
||||
break;
|
||||
|
||||
case BusSource.ReadDisp:
|
||||
// "The high-order bits of IR cannot be read directly, but the displacement field of IR (8 low order bits),
|
||||
// may be read with the <-DISP bus source. If the X field of the instruction is zero (i.e. it specifies page 0
|
||||
// addressing) then the DISP field of the instruction is put on BUS[8-15] and BUS[0-7] is zeroed. If the X
|
||||
// field of the instruction is nonzero (i.e. it specifies PC-relative or base-register addressing) then the DISP
|
||||
// field is sign-extended and put on the bus."
|
||||
// NB: the "X" field of the NOVA instruction is IR[6-7]
|
||||
_busData = (ushort)(_cpu._ir & 0xff);
|
||||
|
||||
if ((_cpu._ir & 0x300) != 0)
|
||||
{
|
||||
// sign extend if necessary
|
||||
if ((_cpu._ir & 0x80) == 0x80)
|
||||
{
|
||||
_busData |= (0xff00);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled bus source {0}.", instruction.BS));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// See also comments below.
|
||||
_busData = ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
|
||||
}
|
||||
|
||||
// Constant ROM access:
|
||||
// The constant memory is gated to the bus by F1=7, F2=7, or BS>4. The constant memory is addressed by the
|
||||
// (8 bit) concatenation of RSELECT and BS. The intent in enabling constants with BS>4 is to provide a masking
|
||||
// facility, particularly for the <-MOUSE and <-DISP bus sources. This works because the processor bus ANDs if
|
||||
// more than one source is gated to it. Up to 32 such mask contans can be provided for each of the four bus sources
|
||||
// > 4.
|
||||
// NOTE also:
|
||||
// "Note that the [emulator task F2] functions which replace the low bits of RSELECT with IR aaffect only the
|
||||
// selection of R; they do not affect the address supplied to the constant ROM."
|
||||
// Hence we use the unmodified RSELECT value here and above.
|
||||
if ((int)instruction.BS > 4 ||
|
||||
instruction.F1 == SpecialFunction1.Constant ||
|
||||
instruction.F2 == SpecialFunction2.Constant)
|
||||
{
|
||||
_busData &= ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
|
||||
}
|
||||
|
||||
// Do ALU operation
|
||||
aluData = ALU.Execute(instruction.ALUF, _busData, _cpu._t, _skip);
|
||||
|
||||
// Reset shifter op
|
||||
Shifter.SetOperation(ShifterOp.None, 0);
|
||||
|
||||
//
|
||||
// Do Special Functions
|
||||
//
|
||||
switch(instruction.F1)
|
||||
{
|
||||
case SpecialFunction1.None:
|
||||
// Do nothing. Well, that was easy.
|
||||
break;
|
||||
|
||||
case SpecialFunction1.LoadMAR:
|
||||
_cpu._system.MemoryBus.LoadMAR(aluData); // Start main memory reference
|
||||
break;
|
||||
|
||||
case SpecialFunction1.Task:
|
||||
nextTask = true; // Yield to other more important tasks
|
||||
break;
|
||||
|
||||
case SpecialFunction1.Block:
|
||||
// Technically this is to be invoked by the hardware device associated with a task.
|
||||
// That logic would be circituous and unless there's a good reason not to that is discovered
|
||||
// later, I'm just going to directly block the current task here.
|
||||
_cpu.BlockTask(this._taskType);
|
||||
break;
|
||||
|
||||
case SpecialFunction1.LLSH1:
|
||||
Shifter.SetOperation(ShifterOp.ShiftLeft, 1);
|
||||
break;
|
||||
|
||||
case SpecialFunction1.LRSH1:
|
||||
Shifter.SetOperation(ShifterOp.ShiftRight, 1);
|
||||
break;
|
||||
|
||||
case SpecialFunction1.LLCY8:
|
||||
Shifter.SetOperation(ShifterOp.RotateLeft, 8);
|
||||
break;
|
||||
|
||||
case SpecialFunction1.Constant:
|
||||
// Ignored here; handled by Constant ROM access logic above.
|
||||
break;
|
||||
|
||||
default:
|
||||
// Let the specific task implementation take a crack at this.
|
||||
ExecuteSpecialFunction1((int)instruction.F1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(instruction.F2)
|
||||
{
|
||||
case SpecialFunction2.None:
|
||||
// Nothing!
|
||||
break;
|
||||
|
||||
case SpecialFunction2.BusEq0:
|
||||
if (_busData == 0)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SpecialFunction2.ShLt0:
|
||||
//
|
||||
// Note:
|
||||
// "the value of SHIFTER OUTPUT is determined by the value of L as the microinstruction
|
||||
// *begins* execution and the shifter function specified during the *current* microinstruction.
|
||||
//
|
||||
// Since we haven't modifed L yet, and we've selected the shifter function above, we're good to go here.
|
||||
//
|
||||
if ((short)Shifter.DoOperation(_cpu._l, _cpu._t) < 0)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SpecialFunction2.ShEq0:
|
||||
// See note above.
|
||||
if (Shifter.DoOperation(_cpu._l, _cpu._t) == 0)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SpecialFunction2.Bus:
|
||||
// Select bits 6-15 (bits 0-9 in modern parlance) of the bus
|
||||
_nextModifier = (ushort)(_busData & 0x3ff);
|
||||
break;
|
||||
|
||||
case SpecialFunction2.ALUCY:
|
||||
// ALUC0 is the carry produced by the ALU during the most recent microinstruction
|
||||
// that loaded L. It is *not* the carry produced during the execution of the microinstruction
|
||||
// that contains the ALUCY function.
|
||||
_nextModifier = _cpu._aluC0;
|
||||
break;
|
||||
|
||||
case SpecialFunction2.StoreMD:
|
||||
_cpu._system.MemoryBus.LoadMD(_busData);
|
||||
break;
|
||||
|
||||
case SpecialFunction2.Constant:
|
||||
// Ignored here; handled by Constant ROM access logic above.
|
||||
break;
|
||||
|
||||
default:
|
||||
// Let the specific task implementation take a crack at this.
|
||||
ExecuteSpecialFunction2((int)instruction.F2);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Write back to registers:
|
||||
//
|
||||
|
||||
// Load T
|
||||
if (instruction.LoadT)
|
||||
{
|
||||
// Does this operation change the source for T?
|
||||
bool loadTFromALU = false;
|
||||
switch(instruction.ALUF)
|
||||
{
|
||||
case AluFunction.Bus:
|
||||
case AluFunction.BusOrT:
|
||||
case AluFunction.BusPlus1:
|
||||
case AluFunction.BusMinus1:
|
||||
case AluFunction.BusPlusTPlus1:
|
||||
case AluFunction.BusPlusSkip:
|
||||
case AluFunction.AluBusAndT:
|
||||
loadTFromALU = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_cpu._t = loadTFromALU ? aluData : _busData;
|
||||
}
|
||||
|
||||
// Do writeback to selected R register from shifter output
|
||||
if (loadR)
|
||||
{
|
||||
_cpu._r[_rSelect] = Shifter.DoOperation(_cpu._l, _cpu._t);
|
||||
}
|
||||
|
||||
// Do writeback to selected R register from M
|
||||
if (_loadS)
|
||||
{
|
||||
_cpu._s[_cpu._rb][_rSelect] = _cpu._m;
|
||||
}
|
||||
|
||||
// Load L (and M) from ALU
|
||||
if (instruction.LoadL)
|
||||
{
|
||||
_cpu._l = aluData;
|
||||
_cpu._m = aluData;
|
||||
|
||||
// Save ALUC0 for use in the next ALUCY special function.
|
||||
_cpu._aluC0 = (ushort)ALU.Carry;
|
||||
}
|
||||
|
||||
//
|
||||
// Select next address, using the address modifier from the last instruction.
|
||||
//
|
||||
_mpc = (ushort)(instruction.NEXT | nextModifier);
|
||||
return nextTask;
|
||||
}
|
||||
|
||||
protected abstract ushort GetBusSource(int bs);
|
||||
protected abstract void ExecuteSpecialFunction1(int f1);
|
||||
|
||||
/// <summary>
|
||||
/// Used to allow Task-specific F2s that need to modify RSELECT to do so.
|
||||
/// </summary>
|
||||
/// <param name="f2"></param>
|
||||
protected virtual void ExecuteSpecialFunction2Early(int f2)
|
||||
{
|
||||
// Nothing by default.
|
||||
}
|
||||
|
||||
protected abstract void ExecuteSpecialFunction2(int f2);
|
||||
|
||||
//
|
||||
// Per uInstruction Task Data:
|
||||
// Modified by both the base Task implementation and any subclasses
|
||||
//
|
||||
// TODO: maybe instead of these being shared (which feels kinda bad)
|
||||
// these could be encapsulated in an object and passed to subclass implementations?
|
||||
protected ushort _busData; // Data placed onto the bus (ANDed from multiple sources)
|
||||
protected ushort _nextModifier; // Bits ORed onto the NEXT field of the current instruction
|
||||
protected uint _rSelect; // RSELECT field from current instruction, potentially modified by task
|
||||
protected bool _loadS; // Whether to load S from M at and of cycle
|
||||
|
||||
|
||||
//
|
||||
// Global Task Data
|
||||
//
|
||||
protected AltoCPU _cpu;
|
||||
protected ushort _mpc;
|
||||
protected TaskType _taskType;
|
||||
protected bool _wakeup;
|
||||
|
||||
// Emulator Task-specific data. This is placed here because it is used by the ALU and it's easier to reference in the
|
||||
// base class even if it does break encapsulation. See notes in the EmulatorTask class for meaning.
|
||||
protected int _skip;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EmulatorTask provides emulator (NOVA instruction set) specific operations.
|
||||
/// </summary>
|
||||
private class EmulatorTask : Task
|
||||
{
|
||||
public EmulatorTask(AltoCPU cpu) : base(cpu)
|
||||
{
|
||||
_taskType = TaskType.Emulator;
|
||||
|
||||
// The Wakeup signal is always true for the Emulator task.
|
||||
_wakeup = true;
|
||||
}
|
||||
|
||||
public override void BlockTask()
|
||||
{
|
||||
throw new InvalidOperationException("The emulator task cannot be blocked.");
|
||||
}
|
||||
|
||||
public override void WakeupTask()
|
||||
{
|
||||
throw new InvalidOperationException("The emulator task is always in wakeup state.");
|
||||
}
|
||||
|
||||
protected override ushort GetBusSource(int bs)
|
||||
{
|
||||
EmulatorBusSource ebs = (EmulatorBusSource)bs;
|
||||
|
||||
switch(ebs)
|
||||
{
|
||||
case EmulatorBusSource.ReadSLocation:
|
||||
return _cpu._s[_cpu._rb][_rSelect];
|
||||
|
||||
case EmulatorBusSource.LoadSLocation:
|
||||
_loadS = true;
|
||||
return 0; // TODO: technically this is an "undefined value" not zero.
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction1(int f1)
|
||||
{
|
||||
EmulatorF1 ef1 = (EmulatorF1)f1;
|
||||
switch (ef1)
|
||||
{
|
||||
case EmulatorF1.RSNF:
|
||||
// TODO: make configurable
|
||||
// "...decoded by the Ethernet interface, which gates the host address wired on the
|
||||
// backplane onto BUS[8-15]. BUS[0-7] is not driven and will therefore be -1. If
|
||||
// no Ethernet interface is present, BUS will be -1.
|
||||
//
|
||||
_busData &= (0xff00 | 0x42);
|
||||
break;
|
||||
|
||||
case EmulatorF1.STARTF:
|
||||
// Dispatch function to I/O based on contents of AC0... (TBD: what are these?)
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
|
||||
case EmulatorF1.SWMODE:
|
||||
// nothing! for now.
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled emulator F1 {0}.", ef1));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction2Early(int f2)
|
||||
{
|
||||
EmulatorF2 ef2 = (EmulatorF2)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."
|
||||
_rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x1800) >> 11) ^ 3);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction2(int f2)
|
||||
{
|
||||
EmulatorF2 ef2 = (EmulatorF2)f2;
|
||||
switch (ef2)
|
||||
{
|
||||
case EmulatorF2.LoadIR:
|
||||
// based on block diagram, this always comes 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."
|
||||
// TODO: is this an AND or an OR operation? (how is the "merge" done?)
|
||||
// Assuming for now this is an OR operation like everything else that modifies NEXT.
|
||||
_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
|
||||
// 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...)
|
||||
if ((_cpu._ir & 0x8000) != 0)
|
||||
{
|
||||
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
|
||||
}
|
||||
else if((_cpu._ir & 0x6000) == 0)
|
||||
{
|
||||
_nextModifier = (ushort)((_cpu._ir & 0x1800) >> 11);
|
||||
}
|
||||
else if((_cpu._ir & 0x6000) == 0x4000)
|
||||
{
|
||||
_nextModifier = 4;
|
||||
}
|
||||
else if ((_cpu._ir & 0x6000) == 0x6000)
|
||||
{
|
||||
_nextModifier = 5;
|
||||
}
|
||||
else if ((_cpu._ir & 0x0f00) == 0)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
else if ((_cpu._ir & 0x0f00) == 0x0100)
|
||||
{
|
||||
_nextModifier = 0;
|
||||
}
|
||||
else if ((_cpu._ir & 0x0f00) == 0x0600)
|
||||
{
|
||||
_nextModifier = 0xe;
|
||||
}
|
||||
else if ((_cpu._ir & 0x0f00) == 0x0e00)
|
||||
{
|
||||
_nextModifier = 0x6;
|
||||
}
|
||||
else
|
||||
{
|
||||
_nextModifier = (ushort)((_cpu._ir & 0x0f00) >> 8);
|
||||
}
|
||||
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
|
||||
if ((_cpu._ir & 0x8000) != 0)
|
||||
{
|
||||
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
|
||||
}
|
||||
else if ((_cpu._ir & 0xc000) == 0xc000)
|
||||
{
|
||||
_nextModifier = (ushort)((_cpu._ir & 0x400) >> 10);
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0)
|
||||
{
|
||||
_nextModifier = 2;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0100)
|
||||
{
|
||||
_nextModifier = 5;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0200)
|
||||
{
|
||||
_nextModifier = 3;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0300)
|
||||
{
|
||||
_nextModifier = 6;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0400)
|
||||
{
|
||||
_nextModifier = 7;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0900)
|
||||
{
|
||||
_nextModifier = 4;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0a00)
|
||||
{
|
||||
_nextModifier = 4;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0e00)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x1f00)
|
||||
{
|
||||
_nextModifier = 0xf;
|
||||
}
|
||||
else
|
||||
{
|
||||
_nextModifier = 0xe;
|
||||
}
|
||||
break;
|
||||
|
||||
case EmulatorF2.ACDEST:
|
||||
// Handled in early handler
|
||||
break;
|
||||
|
||||
case EmulatorF2.BUSODD:
|
||||
// "...merges BUS[15] into NEXT[9]."
|
||||
// TODO: is this an AND or an OR?
|
||||
_nextModifier |= (ushort)(_busData & 0x1);
|
||||
break;
|
||||
|
||||
case EmulatorF2.MAGIC:
|
||||
Shifter.SetMagic(true);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled emulator F2 {0}.", ef2));
|
||||
}
|
||||
}
|
||||
|
||||
// From Section 3, Pg. 31:
|
||||
// "The emulator has two additional bits of state, the SKIP and CARRY flip flops. CARRY is distinct from the
|
||||
// microprocessor’s ALUC0 bit, tested by the ALUCY function. CARRY is set or cleared as a function of IR and
|
||||
// many other things(see section 3.1) when the DNS<-(do novel shifts, F2= 12B) function is executed. In
|
||||
// particular, if IR[12] is true, CARRY will not change. DNS also addresses R from (3-IR[3 - 4]), causes a store
|
||||
// into R unless IR[12] is set, and sets the SKIP flip flop if appropriate(see section 3.1). The emulator
|
||||
// microcode increments PC by 1 at the beginning of the next emulated instruction if SKIP is set, using
|
||||
// BUS+SKIP(ALUF= 13B). IR_ clears SKIP."
|
||||
//
|
||||
// NB: _skip is in the encapsulating AltoCPU class to make it easier to reference since the ALU needs to know about it.
|
||||
private int _carry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DiskSectorTask provides implementation for disk-specific special functions
|
||||
/// </summary>
|
||||
private class DiskSectorTask : Task
|
||||
{
|
||||
public DiskSectorTask(AltoCPU cpu) : base(cpu)
|
||||
{
|
||||
_taskType = TaskType.DiskSector;
|
||||
_wakeup = false;
|
||||
}
|
||||
|
||||
protected override ushort GetBusSource(int bs)
|
||||
{
|
||||
DiskBusSource dbs = (DiskBusSource)bs;
|
||||
|
||||
switch (dbs)
|
||||
{
|
||||
case DiskBusSource.ReadKSTAT:
|
||||
return _cpu._system.DiskController.KSTAT;
|
||||
|
||||
case DiskBusSource.ReadKDATA:
|
||||
return _cpu._system.DiskController.KDATA;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction1(int f1)
|
||||
{
|
||||
DiskF1 df1 = (DiskF1)f1;
|
||||
|
||||
switch(df1)
|
||||
{
|
||||
case DiskF1.LoadKDATA:
|
||||
// "The KDATA register is loaded from BUS[0-15]."
|
||||
_cpu._system.DiskController.KDATA = _busData;
|
||||
break;
|
||||
|
||||
case DiskF1.LoadKADR:
|
||||
// "This causes the KADR register to be loaded from BUS[8-14].
|
||||
// in addition, it causes the head address bit to be loaded from KDATA[13]."
|
||||
// TODO: do the latter (likely inside the controller)
|
||||
_cpu._system.DiskController.KADR = (ushort)((_busData & 0xfe) >> 1);
|
||||
break;
|
||||
|
||||
case DiskF1.LoadKCOMM:
|
||||
_cpu._system.DiskController.KCOM = (ushort)((_busData & 0x7c00) >> 10);
|
||||
break;
|
||||
|
||||
case DiskF1.CLRSTAT:
|
||||
_cpu._system.DiskController.ClearStatus();
|
||||
break;
|
||||
|
||||
case DiskF1.INCRECNO:
|
||||
_cpu._system.DiskController.IncrementRecord();
|
||||
break;
|
||||
|
||||
case DiskF1.LoadKSTAT:
|
||||
// "KSTAT[12-15] are loaded from BUS[12-15]. (Actually BUS[13] is ORed onto
|
||||
// KSTAT[13].)"
|
||||
|
||||
// OR in BUS[12-15] after masking in KSTAT[13] so it is ORed in properly.
|
||||
_cpu._system.DiskController.KSTAT = (ushort)(((_cpu._system.DiskController.KSTAT & 0xfff4)) | (_busData & 0xf));
|
||||
break;
|
||||
|
||||
case DiskF1.STROBE:
|
||||
_cpu._system.DiskController.Strobe();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled disk special function 1 {0}", df1));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction2(int f2)
|
||||
{
|
||||
DiskF2 df2 = (DiskF2)f2;
|
||||
|
||||
switch(df2)
|
||||
{
|
||||
case DiskF2.INIT:
|
||||
// "NEXT<-NEXT OR (if WDTASKACT AND WDINIT) then 37B else 0
|
||||
// TODO: figure out how WDTASKACT and WDINIT work.
|
||||
throw new NotImplementedException("INIT not implemented.");
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled disk special function 2 {0}", df2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// AltoCPU registers
|
||||
ushort _t;
|
||||
ushort _l;
|
||||
|
||||
108
Contralto/CPU/Tasks/DiskTask.cs
Normal file
108
Contralto/CPU/Tasks/DiskTask.cs
Normal file
@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Contralto.Memory;
|
||||
|
||||
namespace Contralto.CPU
|
||||
{
|
||||
public partial class AltoCPU
|
||||
{
|
||||
/// <summary>
|
||||
/// DiskTask provides implementation for disk-specific special functions
|
||||
/// (for both Disk Sector and Disk Word tasks, since the special functions are
|
||||
/// identical between the two)
|
||||
/// </summary>
|
||||
private class DiskTask : Task
|
||||
{
|
||||
public DiskTask(AltoCPU cpu, bool diskSectorTask) : base(cpu)
|
||||
{
|
||||
_taskType = diskSectorTask ? TaskType.DiskSector : TaskType.DiskWord;
|
||||
_wakeup = false;
|
||||
}
|
||||
|
||||
protected override ushort GetBusSource(int bs)
|
||||
{
|
||||
DiskBusSource dbs = (DiskBusSource)bs;
|
||||
|
||||
switch (dbs)
|
||||
{
|
||||
case DiskBusSource.ReadKSTAT:
|
||||
return _cpu._system.DiskController.KSTAT;
|
||||
|
||||
case DiskBusSource.ReadKDATA:
|
||||
return _cpu._system.DiskController.KDATA;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction1(int f1)
|
||||
{
|
||||
DiskF1 df1 = (DiskF1)f1;
|
||||
|
||||
switch (df1)
|
||||
{
|
||||
case DiskF1.LoadKDATA:
|
||||
// "The KDATA register is loaded from BUS[0-15]."
|
||||
_cpu._system.DiskController.KDATA = _busData;
|
||||
break;
|
||||
|
||||
case DiskF1.LoadKADR:
|
||||
// "This causes the KADR register to be loaded from BUS[8-14].
|
||||
// in addition, it causes the head address bit to be loaded from KDATA[13]."
|
||||
// (the latter is done by DiskController)
|
||||
_cpu._system.DiskController.KADR = (ushort)((_busData & 0xfe) >> 1);
|
||||
break;
|
||||
|
||||
case DiskF1.LoadKCOMM:
|
||||
_cpu._system.DiskController.KCOM = (ushort)((_busData & 0x7c00) >> 10);
|
||||
break;
|
||||
|
||||
case DiskF1.CLRSTAT:
|
||||
_cpu._system.DiskController.ClearStatus();
|
||||
break;
|
||||
|
||||
case DiskF1.INCRECNO:
|
||||
_cpu._system.DiskController.IncrementRecord();
|
||||
break;
|
||||
|
||||
case DiskF1.LoadKSTAT:
|
||||
// "KSTAT[12-15] are loaded from BUS[12-15]. (Actually BUS[13] is ORed onto
|
||||
// KSTAT[13].)"
|
||||
|
||||
// OR in BUS[12-15] after masking in KSTAT[13] so it is ORed in properly.
|
||||
_cpu._system.DiskController.KSTAT = (ushort)(((_cpu._system.DiskController.KSTAT & 0xfff4)) | (_busData & 0xf));
|
||||
break;
|
||||
|
||||
case DiskF1.STROBE:
|
||||
_cpu._system.DiskController.Strobe();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled disk special function 1 {0}", df1));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction2(int f2)
|
||||
{
|
||||
DiskF2 df2 = (DiskF2)f2;
|
||||
|
||||
switch (df2)
|
||||
{
|
||||
case DiskF2.INIT:
|
||||
// "NEXT<-NEXT OR (if WDTASKACT AND WDINIT) then 37B else 0
|
||||
// TODO: figure out how WDTASKACT and WDINIT work.
|
||||
throw new NotImplementedException("INIT not implemented.");
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled disk special function 2 {0}", df2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
278
Contralto/CPU/Tasks/EmulatorTask.cs
Normal file
278
Contralto/CPU/Tasks/EmulatorTask.cs
Normal file
@ -0,0 +1,278 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Contralto.Memory;
|
||||
|
||||
namespace Contralto.CPU
|
||||
{
|
||||
public partial class AltoCPU
|
||||
{
|
||||
/// <summary>
|
||||
/// EmulatorTask provides emulator (NOVA instruction set) specific operations.
|
||||
/// </summary>
|
||||
private class EmulatorTask : Task
|
||||
{
|
||||
public EmulatorTask(AltoCPU cpu) : base(cpu)
|
||||
{
|
||||
_taskType = TaskType.Emulator;
|
||||
|
||||
// The Wakeup signal is always true for the Emulator task.
|
||||
_wakeup = true;
|
||||
}
|
||||
|
||||
public override void BlockTask()
|
||||
{
|
||||
throw new InvalidOperationException("The emulator task cannot be blocked.");
|
||||
}
|
||||
|
||||
public override void WakeupTask()
|
||||
{
|
||||
throw new InvalidOperationException("The emulator task is always in wakeup state.");
|
||||
}
|
||||
|
||||
protected override ushort GetBusSource(int bs)
|
||||
{
|
||||
EmulatorBusSource ebs = (EmulatorBusSource)bs;
|
||||
|
||||
switch (ebs)
|
||||
{
|
||||
case EmulatorBusSource.ReadSLocation:
|
||||
return _cpu._s[_cpu._rb][_rSelect];
|
||||
|
||||
case EmulatorBusSource.LoadSLocation:
|
||||
_loadS = true;
|
||||
return 0; // TODO: technically this is an "undefined value," not zero.
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction1(int f1)
|
||||
{
|
||||
EmulatorF1 ef1 = (EmulatorF1)f1;
|
||||
switch (ef1)
|
||||
{
|
||||
case EmulatorF1.RSNF:
|
||||
// TODO: make configurable
|
||||
// "...decoded by the Ethernet interface, which gates the host address wired on the
|
||||
// backplane onto BUS[8-15]. BUS[0-7] is not driven and will therefore be -1. If
|
||||
// no Ethernet interface is present, BUS will be -1.
|
||||
//
|
||||
_busData &= (0xff00 | 0x42);
|
||||
break;
|
||||
|
||||
case EmulatorF1.STARTF:
|
||||
// Dispatch function to I/O based on contents of AC0... (TBD: what are these?)
|
||||
throw new NotImplementedException();
|
||||
break;
|
||||
|
||||
case EmulatorF1.SWMODE:
|
||||
// nothing! for now.
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled emulator F1 {0}.", ef1));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction2Early(int f2)
|
||||
{
|
||||
EmulatorF2 ef2 = (EmulatorF2)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."
|
||||
_rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x1800) >> 11) ^ 3);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExecuteSpecialFunction2(int f2)
|
||||
{
|
||||
EmulatorF2 ef2 = (EmulatorF2)f2;
|
||||
switch (ef2)
|
||||
{
|
||||
case EmulatorF2.LoadIR:
|
||||
// based on block diagram, this always comes 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."
|
||||
// TODO: is this an AND or an OR operation? (how is the "merge" done?)
|
||||
// Assuming for now this is an OR operation like everything else that modifies NEXT.
|
||||
_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
|
||||
// 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...)
|
||||
if ((_cpu._ir & 0x8000) != 0)
|
||||
{
|
||||
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
|
||||
}
|
||||
else if ((_cpu._ir & 0x6000) == 0)
|
||||
{
|
||||
_nextModifier = (ushort)((_cpu._ir & 0x1800) >> 11);
|
||||
}
|
||||
else if ((_cpu._ir & 0x6000) == 0x4000)
|
||||
{
|
||||
_nextModifier = 4;
|
||||
}
|
||||
else if ((_cpu._ir & 0x6000) == 0x6000)
|
||||
{
|
||||
_nextModifier = 5;
|
||||
}
|
||||
else if ((_cpu._ir & 0x0f00) == 0)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
else if ((_cpu._ir & 0x0f00) == 0x0100)
|
||||
{
|
||||
_nextModifier = 0;
|
||||
}
|
||||
else if ((_cpu._ir & 0x0f00) == 0x0600)
|
||||
{
|
||||
_nextModifier = 0xe;
|
||||
}
|
||||
else if ((_cpu._ir & 0x0f00) == 0x0e00)
|
||||
{
|
||||
_nextModifier = 0x6;
|
||||
}
|
||||
else
|
||||
{
|
||||
_nextModifier = (ushort)((_cpu._ir & 0x0f00) >> 8);
|
||||
}
|
||||
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
|
||||
if ((_cpu._ir & 0x8000) != 0)
|
||||
{
|
||||
_nextModifier = (ushort)(3 - ((_cpu._ir & 0xc0) >> 6));
|
||||
}
|
||||
else if ((_cpu._ir & 0xc000) == 0xc000)
|
||||
{
|
||||
_nextModifier = (ushort)((_cpu._ir & 0x400) >> 10);
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0)
|
||||
{
|
||||
_nextModifier = 2;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0100)
|
||||
{
|
||||
_nextModifier = 5;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0200)
|
||||
{
|
||||
_nextModifier = 3;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0300)
|
||||
{
|
||||
_nextModifier = 6;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0400)
|
||||
{
|
||||
_nextModifier = 7;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0900)
|
||||
{
|
||||
_nextModifier = 4;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0a00)
|
||||
{
|
||||
_nextModifier = 4;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x0e00)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
else if ((_cpu._ir & 0x1f00) == 0x1f00)
|
||||
{
|
||||
_nextModifier = 0xf;
|
||||
}
|
||||
else
|
||||
{
|
||||
_nextModifier = 0xe;
|
||||
}
|
||||
break;
|
||||
|
||||
case EmulatorF2.ACDEST:
|
||||
// Handled in early handler
|
||||
break;
|
||||
|
||||
case EmulatorF2.BUSODD:
|
||||
// "...merges BUS[15] into NEXT[9]."
|
||||
// TODO: is this an AND or an OR?
|
||||
_nextModifier |= (ushort)(_busData & 0x1);
|
||||
break;
|
||||
|
||||
case EmulatorF2.MAGIC:
|
||||
Shifter.SetMagic(true);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled emulator F2 {0}.", ef2));
|
||||
}
|
||||
}
|
||||
|
||||
// From Section 3, Pg. 31:
|
||||
// "The emulator has two additional bits of state, the SKIP and CARRY flip flops. CARRY is distinct from the
|
||||
// microprocessor’s ALUC0 bit, tested by the ALUCY function. CARRY is set or cleared as a function of IR and
|
||||
// many other things(see section 3.1) when the DNS<-(do novel shifts, F2= 12B) function is executed. In
|
||||
// particular, if IR[12] is true, CARRY will not change. DNS also addresses R from (3-IR[3 - 4]), causes a store
|
||||
// into R unless IR[12] is set, and sets the SKIP flip flop if appropriate(see section 3.1). The emulator
|
||||
// microcode increments PC by 1 at the beginning of the next emulated instruction if SKIP is set, using
|
||||
// BUS+SKIP(ALUF= 13B). IR_ clears SKIP."
|
||||
//
|
||||
// NB: _skip is in the encapsulating AltoCPU class to make it easier to reference since the ALU needs to know about it.
|
||||
private int _carry;
|
||||
}
|
||||
}
|
||||
}
|
||||
413
Contralto/CPU/Tasks/Task.cs
Normal file
413
Contralto/CPU/Tasks/Task.cs
Normal file
@ -0,0 +1,413 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Contralto.Memory;
|
||||
|
||||
namespace Contralto.CPU
|
||||
{
|
||||
public partial class AltoCPU
|
||||
{
|
||||
// Task:
|
||||
// Base task class: provides implementation for non-task-specific microcode execution and
|
||||
// state. Task subclasses implement and execute Task-specific behavior and are called into
|
||||
// by the base class as necessary.
|
||||
public abstract class Task
|
||||
{
|
||||
public Task(AltoCPU cpu)
|
||||
{
|
||||
_wakeup = false;
|
||||
_mpc = 0xffff; // invalid, for sanity checking
|
||||
_taskType = TaskType.Invalid;
|
||||
_cpu = cpu;
|
||||
}
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return (int)_taskType; }
|
||||
}
|
||||
|
||||
public bool Wakeup
|
||||
{
|
||||
get { return _wakeup; }
|
||||
}
|
||||
|
||||
public ushort MPC
|
||||
{
|
||||
get { return _mpc; }
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
// From The Alto Hardware Manual (section 2, "Initialization"):
|
||||
// "...each task start[s] at the location which is its task number"
|
||||
//
|
||||
_mpc = (ushort)_taskType;
|
||||
}
|
||||
|
||||
public virtual void BlockTask()
|
||||
{
|
||||
_wakeup = false;
|
||||
}
|
||||
|
||||
public virtual void WakeupTask()
|
||||
{
|
||||
_wakeup = true;
|
||||
}
|
||||
|
||||
public bool ExecuteNext()
|
||||
{
|
||||
// TODO: cache microinstructions (or pre-decode them) to save consing all these up every time.
|
||||
MicroInstruction instruction = new MicroInstruction(UCodeMemory.UCodeROM[_mpc]);
|
||||
return ExecuteInstruction(instruction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ExecuteInstruction causes the Task to execute the next instruction (the one
|
||||
/// _mpc is pointing to). The base implementation covers non-task specific logic; subclasses may
|
||||
/// provide their own overrides.
|
||||
/// </summary>
|
||||
/// <returns>True if a task switch has been requested by a TASK instruction, false otherwise.</returns>
|
||||
protected virtual bool ExecuteInstruction(MicroInstruction instruction)
|
||||
{
|
||||
bool nextTask = false;
|
||||
bool loadR = false;
|
||||
ushort aluData = 0;
|
||||
ushort nextModifier = 0;
|
||||
_loadS = false;
|
||||
_rSelect = 0;
|
||||
_busData = 0;
|
||||
|
||||
|
||||
Shifter.SetMagic(false);
|
||||
|
||||
//
|
||||
// Wait for memory state machine if a memory operation is requested by this instruction and
|
||||
// the memory isn't ready yet.
|
||||
// TODO: this needs to be seriously cleaned up.
|
||||
//
|
||||
if (instruction.BS == BusSource.ReadMD ||
|
||||
instruction.F1 == SpecialFunction1.LoadMAR ||
|
||||
instruction.F2 == SpecialFunction2.StoreMD)
|
||||
{
|
||||
|
||||
MemoryOperation op;
|
||||
|
||||
if (instruction.BS == BusSource.ReadMD)
|
||||
{
|
||||
op = MemoryOperation.Read;
|
||||
}
|
||||
else if (instruction.F1 == SpecialFunction1.LoadMAR)
|
||||
{
|
||||
op = MemoryOperation.LoadAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
op = MemoryOperation.Store;
|
||||
}
|
||||
|
||||
if (!_cpu._system.MemoryBus.Ready(op))
|
||||
{
|
||||
// Suspend operation for this cycle.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a modified next field from the last instruction, make sure it gets applied to this one.
|
||||
nextModifier = _nextModifier;
|
||||
_nextModifier = 0;
|
||||
|
||||
_rSelect = instruction.RSELECT;
|
||||
|
||||
// Give tasks the chance to modify parameters early on (like RSELECT)
|
||||
ExecuteSpecialFunction2Early((int)instruction.F2);
|
||||
|
||||
// Select BUS data.
|
||||
if (instruction.F1 != SpecialFunction1.Constant &&
|
||||
instruction.F2 != SpecialFunction2.Constant)
|
||||
{
|
||||
// Normal BUS data (not constant ROM access).
|
||||
switch (instruction.BS)
|
||||
{
|
||||
case BusSource.ReadR:
|
||||
_busData = _cpu._r[_rSelect];
|
||||
break;
|
||||
|
||||
case BusSource.LoadR:
|
||||
_busData = 0; // "Loading R forces the BUS to 0 so that an ALU function of 0 and T may be executed simultaneously"
|
||||
loadR = true;
|
||||
break;
|
||||
|
||||
case BusSource.None:
|
||||
_busData = 0xffff; // "Enables no source to the BUS, leaving it all ones"
|
||||
break;
|
||||
|
||||
case BusSource.TaskSpecific1:
|
||||
case BusSource.TaskSpecific2:
|
||||
_busData = GetBusSource((int)instruction.BS); // task specific -- call into specific implementation
|
||||
break;
|
||||
|
||||
case BusSource.ReadMD:
|
||||
_busData = _cpu._system.MemoryBus.ReadMD();
|
||||
break;
|
||||
|
||||
case BusSource.ReadMouse:
|
||||
//throw new NotImplementedException("ReadMouse bus source not implemented.");
|
||||
_busData = 0; // TODO: implement;
|
||||
break;
|
||||
|
||||
case BusSource.ReadDisp:
|
||||
// "The high-order bits of IR cannot be read directly, but the displacement field of IR (8 low order bits),
|
||||
// may be read with the <-DISP bus source. If the X field of the instruction is zero (i.e. it specifies page 0
|
||||
// addressing) then the DISP field of the instruction is put on BUS[8-15] and BUS[0-7] is zeroed. If the X
|
||||
// field of the instruction is nonzero (i.e. it specifies PC-relative or base-register addressing) then the DISP
|
||||
// field is sign-extended and put on the bus."
|
||||
// NB: the "X" field of the NOVA instruction is IR[6-7]
|
||||
_busData = (ushort)(_cpu._ir & 0xff);
|
||||
|
||||
if ((_cpu._ir & 0x300) != 0)
|
||||
{
|
||||
// sign extend if necessary
|
||||
if ((_cpu._ir & 0x80) == 0x80)
|
||||
{
|
||||
_busData |= (0xff00);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled bus source {0}.", instruction.BS));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// See also comments below.
|
||||
_busData = ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
|
||||
}
|
||||
|
||||
// Constant ROM access:
|
||||
// The constant memory is gated to the bus by F1=7, F2=7, or BS>4. The constant memory is addressed by the
|
||||
// (8 bit) concatenation of RSELECT and BS. The intent in enabling constants with BS>4 is to provide a masking
|
||||
// facility, particularly for the <-MOUSE and <-DISP bus sources. This works because the processor bus ANDs if
|
||||
// more than one source is gated to it. Up to 32 such mask contans can be provided for each of the four bus sources
|
||||
// > 4.
|
||||
// NOTE also:
|
||||
// "Note that the [emulator task F2] functions which replace the low bits of RSELECT with IR aaffect only the
|
||||
// selection of R; they do not affect the address supplied to the constant ROM."
|
||||
// Hence we use the unmodified RSELECT value here and above.
|
||||
if ((int)instruction.BS > 4 ||
|
||||
instruction.F1 == SpecialFunction1.Constant ||
|
||||
instruction.F2 == SpecialFunction2.Constant)
|
||||
{
|
||||
_busData &= ConstantMemory.ConstantROM[(instruction.RSELECT << 3) | ((uint)instruction.BS)];
|
||||
}
|
||||
|
||||
// Do ALU operation
|
||||
aluData = ALU.Execute(instruction.ALUF, _busData, _cpu._t, _skip);
|
||||
|
||||
// Reset shifter op
|
||||
Shifter.SetOperation(ShifterOp.None, 0);
|
||||
|
||||
//
|
||||
// Do Special Functions
|
||||
//
|
||||
switch (instruction.F1)
|
||||
{
|
||||
case SpecialFunction1.None:
|
||||
// Do nothing. Well, that was easy.
|
||||
break;
|
||||
|
||||
case SpecialFunction1.LoadMAR:
|
||||
_cpu._system.MemoryBus.LoadMAR(aluData); // Start main memory reference
|
||||
break;
|
||||
|
||||
case SpecialFunction1.Task:
|
||||
nextTask = true; // Yield to other more important tasks
|
||||
break;
|
||||
|
||||
case SpecialFunction1.Block:
|
||||
// Technically this is to be invoked by the hardware device associated with a task.
|
||||
// That logic would be circituous and unless there's a good reason not to that is discovered
|
||||
// later, I'm just going to directly block the current task here.
|
||||
_cpu.BlockTask(this._taskType);
|
||||
break;
|
||||
|
||||
case SpecialFunction1.LLSH1:
|
||||
Shifter.SetOperation(ShifterOp.ShiftLeft, 1);
|
||||
break;
|
||||
|
||||
case SpecialFunction1.LRSH1:
|
||||
Shifter.SetOperation(ShifterOp.ShiftRight, 1);
|
||||
break;
|
||||
|
||||
case SpecialFunction1.LLCY8:
|
||||
Shifter.SetOperation(ShifterOp.RotateLeft, 8);
|
||||
break;
|
||||
|
||||
case SpecialFunction1.Constant:
|
||||
// Ignored here; handled by Constant ROM access logic above.
|
||||
break;
|
||||
|
||||
default:
|
||||
// Let the specific task implementation take a crack at this.
|
||||
ExecuteSpecialFunction1((int)instruction.F1);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (instruction.F2)
|
||||
{
|
||||
case SpecialFunction2.None:
|
||||
// Nothing!
|
||||
break;
|
||||
|
||||
case SpecialFunction2.BusEq0:
|
||||
if (_busData == 0)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SpecialFunction2.ShLt0:
|
||||
//
|
||||
// Note:
|
||||
// "the value of SHIFTER OUTPUT is determined by the value of L as the microinstruction
|
||||
// *begins* execution and the shifter function specified during the *current* microinstruction.
|
||||
//
|
||||
// Since we haven't modifed L yet, and we've selected the shifter function above, we're good to go here.
|
||||
//
|
||||
if ((short)Shifter.DoOperation(_cpu._l, _cpu._t) < 0)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SpecialFunction2.ShEq0:
|
||||
// See note above.
|
||||
if (Shifter.DoOperation(_cpu._l, _cpu._t) == 0)
|
||||
{
|
||||
_nextModifier = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SpecialFunction2.Bus:
|
||||
// Select bits 6-15 (bits 0-9 in modern parlance) of the bus
|
||||
_nextModifier = (ushort)(_busData & 0x3ff);
|
||||
break;
|
||||
|
||||
case SpecialFunction2.ALUCY:
|
||||
// ALUC0 is the carry produced by the ALU during the most recent microinstruction
|
||||
// that loaded L. It is *not* the carry produced during the execution of the microinstruction
|
||||
// that contains the ALUCY function.
|
||||
_nextModifier = _cpu._aluC0;
|
||||
break;
|
||||
|
||||
case SpecialFunction2.StoreMD:
|
||||
_cpu._system.MemoryBus.LoadMD(_busData);
|
||||
break;
|
||||
|
||||
case SpecialFunction2.Constant:
|
||||
// Ignored here; handled by Constant ROM access logic above.
|
||||
break;
|
||||
|
||||
default:
|
||||
// Let the specific task implementation take a crack at this.
|
||||
ExecuteSpecialFunction2((int)instruction.F2);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Write back to registers:
|
||||
//
|
||||
// Do writeback to selected R register from shifter output
|
||||
if (loadR)
|
||||
{
|
||||
_cpu._r[_rSelect] = Shifter.DoOperation(_cpu._l, _cpu._t);
|
||||
}
|
||||
|
||||
// Do writeback to selected R register from M
|
||||
if (_loadS)
|
||||
{
|
||||
_cpu._s[_cpu._rb][_rSelect] = _cpu._m;
|
||||
}
|
||||
|
||||
// Load T
|
||||
if (instruction.LoadT)
|
||||
{
|
||||
// Does this operation change the source for T?
|
||||
bool loadTFromALU = false;
|
||||
switch (instruction.ALUF)
|
||||
{
|
||||
case AluFunction.Bus:
|
||||
case AluFunction.BusOrT:
|
||||
case AluFunction.BusPlus1:
|
||||
case AluFunction.BusMinus1:
|
||||
case AluFunction.BusPlusTPlus1:
|
||||
case AluFunction.BusPlusSkip:
|
||||
case AluFunction.AluBusAndT:
|
||||
loadTFromALU = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_cpu._t = loadTFromALU ? aluData : _busData;
|
||||
}
|
||||
|
||||
// Load L (and M) from ALU outputs.
|
||||
if (instruction.LoadL)
|
||||
{
|
||||
_cpu._l = aluData;
|
||||
_cpu._m = aluData;
|
||||
|
||||
// Save ALUC0 for use in the next ALUCY special function.
|
||||
_cpu._aluC0 = (ushort)ALU.Carry;
|
||||
}
|
||||
|
||||
//
|
||||
// Select next address, using the address modifier from the last instruction.
|
||||
//
|
||||
_mpc = (ushort)(instruction.NEXT | nextModifier);
|
||||
return nextTask;
|
||||
}
|
||||
|
||||
protected abstract ushort GetBusSource(int bs);
|
||||
protected abstract void ExecuteSpecialFunction1(int f1);
|
||||
|
||||
/// <summary>
|
||||
/// Used to allow Task-specific F2s that need to modify RSELECT to do so.
|
||||
/// </summary>
|
||||
/// <param name="f2"></param>
|
||||
protected virtual void ExecuteSpecialFunction2Early(int f2)
|
||||
{
|
||||
// Nothing by default.
|
||||
}
|
||||
|
||||
protected abstract void ExecuteSpecialFunction2(int f2);
|
||||
|
||||
//
|
||||
// Per uInstruction Task Data:
|
||||
// Modified by both the base Task implementation and any subclasses
|
||||
//
|
||||
// TODO: maybe instead of these being shared (which feels kinda bad)
|
||||
// these could be encapsulated in an object and passed to subclass implementations?
|
||||
protected ushort _busData; // Data placed onto the bus (ANDed from multiple sources)
|
||||
protected ushort _nextModifier; // Bits ORed onto the NEXT field of the current instruction
|
||||
protected uint _rSelect; // RSELECT field from current instruction, potentially modified by task
|
||||
protected bool _loadS; // Whether to load S from M at and of cycle
|
||||
|
||||
|
||||
//
|
||||
// Global Task Data
|
||||
//
|
||||
protected AltoCPU _cpu;
|
||||
protected ushort _mpc;
|
||||
protected TaskType _taskType;
|
||||
protected bool _wakeup;
|
||||
|
||||
// Emulator Task-specific data. This is placed here because it is used by the ALU and it's easier to reference in the
|
||||
// base class even if it does break encapsulation. See notes in the EmulatorTask class for meaning.
|
||||
protected int _skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -48,8 +48,11 @@
|
||||
<Compile Include="CPU\ConstantMemory.cs" />
|
||||
<Compile Include="CPU\CPU.cs" />
|
||||
<Compile Include="CPU\Disassembler.cs" />
|
||||
<Compile Include="CPU\Tasks\DiskTask.cs" />
|
||||
<Compile Include="CPU\Tasks\EmulatorTask.cs" />
|
||||
<Compile Include="CPU\MicroInstruction.cs" />
|
||||
<Compile Include="CPU\Shifter.cs" />
|
||||
<Compile Include="CPU\Tasks\Task.cs" />
|
||||
<Compile Include="CPU\UCodeMemory.cs" />
|
||||
<Compile Include="Debugger.cs">
|
||||
<SubType>Form</SubType>
|
||||
|
||||
456
Contralto/Debugger.Designer.cs
generated
456
Contralto/Debugger.Designer.cs
generated
@ -28,38 +28,41 @@
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle5 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle6 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle7 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle8 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle9 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle10 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle11 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle12 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle13 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle14 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle18 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle19 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle20 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle21 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle22 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle15 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle16 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle17 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle23 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle24 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle25 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle26 = new System.Windows.Forms.DataGridViewCellStyle();
|
||||
this.Microcode = new System.Windows.Forms.GroupBox();
|
||||
this._sourceViewer = new System.Windows.Forms.DataGridView();
|
||||
this.Breakpoint = new System.Windows.Forms.DataGridViewCheckBoxColumn();
|
||||
this.T = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Addr = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Source = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.StepButton = new System.Windows.Forms.Button();
|
||||
this.button2 = new System.Windows.Forms.Button();
|
||||
this.button3 = new System.Windows.Forms.Button();
|
||||
this.button4 = new System.Windows.Forms.Button();
|
||||
this._registerData = new System.Windows.Forms.DataGridView();
|
||||
this.RegNum = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.R = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.S = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.StepButton = new System.Windows.Forms.Button();
|
||||
this.AutoStep = new System.Windows.Forms.Button();
|
||||
this.RunButton = new System.Windows.Forms.Button();
|
||||
this.StopButton = new System.Windows.Forms.Button();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this._taskData = new System.Windows.Forms.DataGridView();
|
||||
this.TaskName = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.TaskState = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.TaskPC = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.T = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Addr = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Source = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.groupBox3 = new System.Windows.Forms.GroupBox();
|
||||
this._otherRegs = new System.Windows.Forms.DataGridView();
|
||||
this.Reg = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
@ -68,6 +71,14 @@
|
||||
this._memoryData = new System.Windows.Forms.DataGridView();
|
||||
this.Address = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Data = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.ExecutionStateLabel = new System.Windows.Forms.Label();
|
||||
this.JumpToAddress = new System.Windows.Forms.TextBox();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.groupBox5 = new System.Windows.Forms.GroupBox();
|
||||
this._diskData = new System.Windows.Forms.DataGridView();
|
||||
this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Microcode.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this._sourceViewer)).BeginInit();
|
||||
this.groupBox1.SuspendLayout();
|
||||
@ -78,10 +89,14 @@
|
||||
((System.ComponentModel.ISupportInitialize)(this._otherRegs)).BeginInit();
|
||||
this.groupBox4.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this._memoryData)).BeginInit();
|
||||
this.groupBox5.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this._diskData)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// Microcode
|
||||
//
|
||||
this.Microcode.Controls.Add(this.label2);
|
||||
this.Microcode.Controls.Add(this.JumpToAddress);
|
||||
this.Microcode.Controls.Add(this._sourceViewer);
|
||||
this.Microcode.Location = new System.Drawing.Point(3, 3);
|
||||
this.Microcode.Name = "Microcode";
|
||||
@ -96,11 +111,12 @@
|
||||
this._sourceViewer.AllowUserToDeleteRows = false;
|
||||
this._sourceViewer.AllowUserToResizeColumns = false;
|
||||
this._sourceViewer.AllowUserToResizeRows = false;
|
||||
dataGridViewCellStyle14.BackColor = System.Drawing.Color.Silver;
|
||||
this._sourceViewer.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle14;
|
||||
dataGridViewCellStyle1.BackColor = System.Drawing.Color.Silver;
|
||||
this._sourceViewer.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
|
||||
this._sourceViewer.CellBorderStyle = System.Windows.Forms.DataGridViewCellBorderStyle.SingleVertical;
|
||||
this._sourceViewer.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this._sourceViewer.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.Breakpoint,
|
||||
this.T,
|
||||
this.Addr,
|
||||
this.Source});
|
||||
@ -109,14 +125,14 @@
|
||||
this._sourceViewer.Name = "_sourceViewer";
|
||||
this._sourceViewer.ReadOnly = true;
|
||||
this._sourceViewer.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single;
|
||||
dataGridViewCellStyle18.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle18.BackColor = System.Drawing.SystemColors.Control;
|
||||
dataGridViewCellStyle18.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle18.ForeColor = System.Drawing.SystemColors.WindowText;
|
||||
dataGridViewCellStyle18.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle18.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle18.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
|
||||
this._sourceViewer.RowHeadersDefaultCellStyle = dataGridViewCellStyle18;
|
||||
dataGridViewCellStyle5.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle5.BackColor = System.Drawing.SystemColors.Control;
|
||||
dataGridViewCellStyle5.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle5.ForeColor = System.Drawing.SystemColors.WindowText;
|
||||
dataGridViewCellStyle5.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle5.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle5.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
|
||||
this._sourceViewer.RowHeadersDefaultCellStyle = dataGridViewCellStyle5;
|
||||
this._sourceViewer.RowHeadersVisible = false;
|
||||
this._sourceViewer.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing;
|
||||
this._sourceViewer.RowTemplate.Height = 18;
|
||||
@ -124,9 +140,58 @@
|
||||
this._sourceViewer.ShowCellErrors = false;
|
||||
this._sourceViewer.ShowEditingIcon = false;
|
||||
this._sourceViewer.ShowRowErrors = false;
|
||||
this._sourceViewer.Size = new System.Drawing.Size(584, 600);
|
||||
this._sourceViewer.Size = new System.Drawing.Size(584, 571);
|
||||
this._sourceViewer.TabIndex = 1;
|
||||
this._sourceViewer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellContentClick);
|
||||
this._sourceViewer.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.SourceViewCellClick);
|
||||
//
|
||||
// Breakpoint
|
||||
//
|
||||
this.Breakpoint.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells;
|
||||
this.Breakpoint.FalseValue = "false";
|
||||
this.Breakpoint.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||
this.Breakpoint.HeaderText = "B";
|
||||
this.Breakpoint.IndeterminateValue = "null";
|
||||
this.Breakpoint.Name = "Breakpoint";
|
||||
this.Breakpoint.ReadOnly = true;
|
||||
this.Breakpoint.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.Breakpoint.TrueValue = "true";
|
||||
this.Breakpoint.Width = 20;
|
||||
//
|
||||
// T
|
||||
//
|
||||
this.T.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
|
||||
dataGridViewCellStyle2.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.T.DefaultCellStyle = dataGridViewCellStyle2;
|
||||
this.T.HeaderText = "T";
|
||||
this.T.Name = "T";
|
||||
this.T.ReadOnly = true;
|
||||
this.T.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.T.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
this.T.Width = 5;
|
||||
//
|
||||
// Addr
|
||||
//
|
||||
this.Addr.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
|
||||
dataGridViewCellStyle3.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Addr.DefaultCellStyle = dataGridViewCellStyle3;
|
||||
this.Addr.HeaderText = "Addr";
|
||||
this.Addr.Name = "Addr";
|
||||
this.Addr.ReadOnly = true;
|
||||
this.Addr.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.Addr.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
this.Addr.Width = 5;
|
||||
//
|
||||
// Source
|
||||
//
|
||||
this.Source.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
dataGridViewCellStyle4.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Source.DefaultCellStyle = dataGridViewCellStyle4;
|
||||
this.Source.HeaderText = "Source Code";
|
||||
this.Source.Name = "Source";
|
||||
this.Source.ReadOnly = true;
|
||||
this.Source.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.Source.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
@ -138,64 +203,27 @@
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "General Registers";
|
||||
//
|
||||
// StepButton
|
||||
//
|
||||
this.StepButton.Location = new System.Drawing.Point(3, 634);
|
||||
this.StepButton.Name = "StepButton";
|
||||
this.StepButton.Size = new System.Drawing.Size(44, 23);
|
||||
this.StepButton.TabIndex = 3;
|
||||
this.StepButton.Text = "Step";
|
||||
this.StepButton.UseVisualStyleBackColor = true;
|
||||
this.StepButton.Click += new System.EventHandler(this.OnStepButtonClicked);
|
||||
//
|
||||
// button2
|
||||
//
|
||||
this.button2.Location = new System.Drawing.Point(54, 634);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(47, 23);
|
||||
this.button2.TabIndex = 4;
|
||||
this.button2.Text = "Auto";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// button3
|
||||
//
|
||||
this.button3.Location = new System.Drawing.Point(108, 634);
|
||||
this.button3.Name = "button3";
|
||||
this.button3.Size = new System.Drawing.Size(53, 23);
|
||||
this.button3.TabIndex = 5;
|
||||
this.button3.Text = "Run";
|
||||
this.button3.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// button4
|
||||
//
|
||||
this.button4.Location = new System.Drawing.Point(168, 634);
|
||||
this.button4.Name = "button4";
|
||||
this.button4.Size = new System.Drawing.Size(49, 23);
|
||||
this.button4.TabIndex = 6;
|
||||
this.button4.Text = "Stop";
|
||||
this.button4.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// _registerData
|
||||
//
|
||||
this._registerData.AllowUserToAddRows = false;
|
||||
this._registerData.AllowUserToDeleteRows = false;
|
||||
this._registerData.AllowUserToResizeColumns = false;
|
||||
this._registerData.AllowUserToResizeRows = false;
|
||||
dataGridViewCellStyle19.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this._registerData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle19;
|
||||
dataGridViewCellStyle6.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this._registerData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle6;
|
||||
this._registerData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this._registerData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.RegNum,
|
||||
this.R,
|
||||
this.S});
|
||||
dataGridViewCellStyle20.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle20.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle20.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle20.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle20.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle20.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle20.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this._registerData.DefaultCellStyle = dataGridViewCellStyle20;
|
||||
dataGridViewCellStyle7.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle7.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle7.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle7.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle7.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle7.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle7.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this._registerData.DefaultCellStyle = dataGridViewCellStyle7;
|
||||
this._registerData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
|
||||
this._registerData.Location = new System.Drawing.Point(7, 19);
|
||||
this._registerData.MultiSelect = false;
|
||||
@ -242,6 +270,46 @@
|
||||
this.S.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
this.S.Width = 50;
|
||||
//
|
||||
// StepButton
|
||||
//
|
||||
this.StepButton.Location = new System.Drawing.Point(0, 954);
|
||||
this.StepButton.Name = "StepButton";
|
||||
this.StepButton.Size = new System.Drawing.Size(44, 23);
|
||||
this.StepButton.TabIndex = 3;
|
||||
this.StepButton.Text = "Step";
|
||||
this.StepButton.UseVisualStyleBackColor = true;
|
||||
this.StepButton.Click += new System.EventHandler(this.OnStepButtonClicked);
|
||||
//
|
||||
// AutoStep
|
||||
//
|
||||
this.AutoStep.Location = new System.Drawing.Point(50, 954);
|
||||
this.AutoStep.Name = "AutoStep";
|
||||
this.AutoStep.Size = new System.Drawing.Size(47, 23);
|
||||
this.AutoStep.TabIndex = 4;
|
||||
this.AutoStep.Text = "Auto";
|
||||
this.AutoStep.UseVisualStyleBackColor = true;
|
||||
this.AutoStep.Click += new System.EventHandler(this.OnAutoStepButtonClicked);
|
||||
//
|
||||
// RunButton
|
||||
//
|
||||
this.RunButton.Location = new System.Drawing.Point(103, 954);
|
||||
this.RunButton.Name = "RunButton";
|
||||
this.RunButton.Size = new System.Drawing.Size(53, 23);
|
||||
this.RunButton.TabIndex = 5;
|
||||
this.RunButton.Text = "Run";
|
||||
this.RunButton.UseVisualStyleBackColor = true;
|
||||
this.RunButton.Click += new System.EventHandler(this.RunButton_Click);
|
||||
//
|
||||
// StopButton
|
||||
//
|
||||
this.StopButton.Location = new System.Drawing.Point(164, 954);
|
||||
this.StopButton.Name = "StopButton";
|
||||
this.StopButton.Size = new System.Drawing.Size(49, 23);
|
||||
this.StopButton.TabIndex = 6;
|
||||
this.StopButton.Text = "Stop";
|
||||
this.StopButton.UseVisualStyleBackColor = true;
|
||||
this.StopButton.Click += new System.EventHandler(this.OnStopButtonClicked);
|
||||
//
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.Controls.Add(this._taskData);
|
||||
@ -256,21 +324,21 @@
|
||||
//
|
||||
this._taskData.AllowUserToAddRows = false;
|
||||
this._taskData.AllowUserToDeleteRows = false;
|
||||
dataGridViewCellStyle21.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this._taskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle21;
|
||||
dataGridViewCellStyle8.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this._taskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle8;
|
||||
this._taskData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this._taskData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.TaskName,
|
||||
this.TaskState,
|
||||
this.TaskPC});
|
||||
dataGridViewCellStyle22.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle22.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle22.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle22.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle22.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle22.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle22.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this._taskData.DefaultCellStyle = dataGridViewCellStyle22;
|
||||
dataGridViewCellStyle9.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle9.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle9.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle9.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle9.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle9.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle9.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this._taskData.DefaultCellStyle = dataGridViewCellStyle9;
|
||||
this._taskData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
|
||||
this._taskData.Location = new System.Drawing.Point(7, 19);
|
||||
this._taskData.MultiSelect = false;
|
||||
@ -312,42 +380,6 @@
|
||||
this.TaskPC.Name = "TaskPC";
|
||||
this.TaskPC.ReadOnly = true;
|
||||
//
|
||||
// T
|
||||
//
|
||||
this.T.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
|
||||
dataGridViewCellStyle15.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle15.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.T.DefaultCellStyle = dataGridViewCellStyle15;
|
||||
this.T.HeaderText = "T";
|
||||
this.T.Name = "T";
|
||||
this.T.ReadOnly = true;
|
||||
this.T.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.T.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
this.T.Width = 5;
|
||||
//
|
||||
// Addr
|
||||
//
|
||||
this.Addr.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
|
||||
dataGridViewCellStyle16.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Addr.DefaultCellStyle = dataGridViewCellStyle16;
|
||||
this.Addr.HeaderText = "Addr";
|
||||
this.Addr.Name = "Addr";
|
||||
this.Addr.ReadOnly = true;
|
||||
this.Addr.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.Addr.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
this.Addr.Width = 5;
|
||||
//
|
||||
// Source
|
||||
//
|
||||
this.Source.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
dataGridViewCellStyle17.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.Source.DefaultCellStyle = dataGridViewCellStyle17;
|
||||
this.Source.HeaderText = "Source Code";
|
||||
this.Source.Name = "Source";
|
||||
this.Source.ReadOnly = true;
|
||||
this.Source.Resizable = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this.Source.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
|
||||
//
|
||||
// groupBox3
|
||||
//
|
||||
this.groupBox3.Controls.Add(this._otherRegs);
|
||||
@ -362,20 +394,20 @@
|
||||
//
|
||||
this._otherRegs.AllowUserToAddRows = false;
|
||||
this._otherRegs.AllowUserToDeleteRows = false;
|
||||
dataGridViewCellStyle23.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this._otherRegs.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle23;
|
||||
dataGridViewCellStyle10.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this._otherRegs.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle10;
|
||||
this._otherRegs.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this._otherRegs.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.Reg,
|
||||
this.RegValue});
|
||||
dataGridViewCellStyle24.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle24.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle24.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle24.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle24.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle24.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle24.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this._otherRegs.DefaultCellStyle = dataGridViewCellStyle24;
|
||||
dataGridViewCellStyle11.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle11.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle11.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle11.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle11.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle11.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle11.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this._otherRegs.DefaultCellStyle = dataGridViewCellStyle11;
|
||||
this._otherRegs.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
|
||||
this._otherRegs.Location = new System.Drawing.Point(7, 19);
|
||||
this._otherRegs.MultiSelect = false;
|
||||
@ -416,9 +448,9 @@
|
||||
// groupBox4
|
||||
//
|
||||
this.groupBox4.Controls.Add(this._memoryData);
|
||||
this.groupBox4.Location = new System.Drawing.Point(223, 634);
|
||||
this.groupBox4.Location = new System.Drawing.Point(319, 634);
|
||||
this.groupBox4.Name = "groupBox4";
|
||||
this.groupBox4.Size = new System.Drawing.Size(240, 344);
|
||||
this.groupBox4.Size = new System.Drawing.Size(144, 344);
|
||||
this.groupBox4.TabIndex = 8;
|
||||
this.groupBox4.TabStop = false;
|
||||
this.groupBox4.Text = "Memory";
|
||||
@ -427,22 +459,22 @@
|
||||
//
|
||||
this._memoryData.AllowUserToAddRows = false;
|
||||
this._memoryData.AllowUserToDeleteRows = false;
|
||||
dataGridViewCellStyle25.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this._memoryData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle25;
|
||||
dataGridViewCellStyle12.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this._memoryData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle12;
|
||||
this._memoryData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this._memoryData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.Address,
|
||||
this.Data});
|
||||
dataGridViewCellStyle26.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle26.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle26.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle26.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle26.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle26.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle26.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this._memoryData.DefaultCellStyle = dataGridViewCellStyle26;
|
||||
dataGridViewCellStyle13.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle13.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle13.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle13.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle13.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle13.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle13.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this._memoryData.DefaultCellStyle = dataGridViewCellStyle13;
|
||||
this._memoryData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
|
||||
this._memoryData.Location = new System.Drawing.Point(7, 19);
|
||||
this._memoryData.Location = new System.Drawing.Point(6, 19);
|
||||
this._memoryData.MultiSelect = false;
|
||||
this._memoryData.Name = "_memoryData";
|
||||
this._memoryData.ReadOnly = true;
|
||||
@ -454,7 +486,7 @@
|
||||
this._memoryData.ShowCellToolTips = false;
|
||||
this._memoryData.ShowEditingIcon = false;
|
||||
this._memoryData.ShowRowErrors = false;
|
||||
this._memoryData.Size = new System.Drawing.Size(227, 319);
|
||||
this._memoryData.Size = new System.Drawing.Size(132, 319);
|
||||
this._memoryData.TabIndex = 0;
|
||||
//
|
||||
// Address
|
||||
@ -474,17 +506,116 @@
|
||||
this.Data.Name = "Data";
|
||||
this.Data.ReadOnly = true;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(0, 935);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(85, 13);
|
||||
this.label1.TabIndex = 9;
|
||||
this.label1.Text = "Execution State:";
|
||||
//
|
||||
// ExecutionStateLabel
|
||||
//
|
||||
this.ExecutionStateLabel.AutoSize = true;
|
||||
this.ExecutionStateLabel.Location = new System.Drawing.Point(92, 935);
|
||||
this.ExecutionStateLabel.Name = "ExecutionStateLabel";
|
||||
this.ExecutionStateLabel.Size = new System.Drawing.Size(33, 13);
|
||||
this.ExecutionStateLabel.TabIndex = 10;
|
||||
this.ExecutionStateLabel.Text = "unset";
|
||||
//
|
||||
// JumpToAddress
|
||||
//
|
||||
this.JumpToAddress.Location = new System.Drawing.Point(59, 596);
|
||||
this.JumpToAddress.Name = "JumpToAddress";
|
||||
this.JumpToAddress.Size = new System.Drawing.Size(48, 20);
|
||||
this.JumpToAddress.TabIndex = 12;
|
||||
this.JumpToAddress.KeyDown += new System.Windows.Forms.KeyEventHandler(this.OnJumpAddressKeyDown);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(11, 599);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(47, 13);
|
||||
this.label2.TabIndex = 13;
|
||||
this.label2.Text = "Jump to:";
|
||||
//
|
||||
// groupBox5
|
||||
//
|
||||
this.groupBox5.Controls.Add(this._diskData);
|
||||
this.groupBox5.Location = new System.Drawing.Point(3, 634);
|
||||
this.groupBox5.Name = "groupBox5";
|
||||
this.groupBox5.Size = new System.Drawing.Size(163, 298);
|
||||
this.groupBox5.TabIndex = 11;
|
||||
this.groupBox5.TabStop = false;
|
||||
this.groupBox5.Text = "Disk";
|
||||
//
|
||||
// _diskData
|
||||
//
|
||||
this._diskData.AllowUserToAddRows = false;
|
||||
this._diskData.AllowUserToDeleteRows = false;
|
||||
dataGridViewCellStyle14.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
|
||||
this._diskData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle14;
|
||||
this._diskData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this._diskData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.dataGridViewTextBoxColumn1,
|
||||
this.dataGridViewTextBoxColumn2});
|
||||
dataGridViewCellStyle15.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
|
||||
dataGridViewCellStyle15.BackColor = System.Drawing.SystemColors.Window;
|
||||
dataGridViewCellStyle15.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
dataGridViewCellStyle15.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||
dataGridViewCellStyle15.SelectionBackColor = System.Drawing.SystemColors.Highlight;
|
||||
dataGridViewCellStyle15.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
dataGridViewCellStyle15.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
|
||||
this._diskData.DefaultCellStyle = dataGridViewCellStyle15;
|
||||
this._diskData.EditMode = System.Windows.Forms.DataGridViewEditMode.EditProgrammatically;
|
||||
this._diskData.Location = new System.Drawing.Point(6, 19);
|
||||
this._diskData.MultiSelect = false;
|
||||
this._diskData.Name = "_diskData";
|
||||
this._diskData.ReadOnly = true;
|
||||
this._diskData.RowHeadersVisible = false;
|
||||
this._diskData.RowTemplate.DefaultCellStyle.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this._diskData.RowTemplate.Height = 18;
|
||||
this._diskData.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
|
||||
this._diskData.ShowCellErrors = false;
|
||||
this._diskData.ShowCellToolTips = false;
|
||||
this._diskData.ShowEditingIcon = false;
|
||||
this._diskData.ShowRowErrors = false;
|
||||
this._diskData.Size = new System.Drawing.Size(147, 273);
|
||||
this._diskData.TabIndex = 1;
|
||||
//
|
||||
// dataGridViewTextBoxColumn1
|
||||
//
|
||||
this.dataGridViewTextBoxColumn1.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCells;
|
||||
this.dataGridViewTextBoxColumn1.HeaderText = "Data";
|
||||
this.dataGridViewTextBoxColumn1.MinimumWidth = 16;
|
||||
this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
|
||||
this.dataGridViewTextBoxColumn1.ReadOnly = true;
|
||||
this.dataGridViewTextBoxColumn1.Width = 55;
|
||||
//
|
||||
// dataGridViewTextBoxColumn2
|
||||
//
|
||||
this.dataGridViewTextBoxColumn2.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
|
||||
this.dataGridViewTextBoxColumn2.HeaderText = "Value";
|
||||
this.dataGridViewTextBoxColumn2.MinimumWidth = 16;
|
||||
this.dataGridViewTextBoxColumn2.Name = "dataGridViewTextBoxColumn2";
|
||||
this.dataGridViewTextBoxColumn2.ReadOnly = true;
|
||||
//
|
||||
// Debugger
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(753, 997);
|
||||
this.Controls.Add(this.groupBox5);
|
||||
this.Controls.Add(this.ExecutionStateLabel);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.groupBox4);
|
||||
this.Controls.Add(this.groupBox3);
|
||||
this.Controls.Add(this.groupBox2);
|
||||
this.Controls.Add(this.button4);
|
||||
this.Controls.Add(this.button3);
|
||||
this.Controls.Add(this.button2);
|
||||
this.Controls.Add(this.StopButton);
|
||||
this.Controls.Add(this.RunButton);
|
||||
this.Controls.Add(this.AutoStep);
|
||||
this.Controls.Add(this.StepButton);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.Microcode);
|
||||
@ -492,6 +623,7 @@
|
||||
this.Text = "Debugger";
|
||||
this.Load += new System.EventHandler(this.Debugger_Load);
|
||||
this.Microcode.ResumeLayout(false);
|
||||
this.Microcode.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this._sourceViewer)).EndInit();
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this._registerData)).EndInit();
|
||||
@ -501,7 +633,10 @@
|
||||
((System.ComponentModel.ISupportInitialize)(this._otherRegs)).EndInit();
|
||||
this.groupBox4.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this._memoryData)).EndInit();
|
||||
this.groupBox5.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this._diskData)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
@ -511,9 +646,9 @@
|
||||
private System.Windows.Forms.DataGridView _sourceViewer;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.Button StepButton;
|
||||
private System.Windows.Forms.Button button2;
|
||||
private System.Windows.Forms.Button button3;
|
||||
private System.Windows.Forms.Button button4;
|
||||
private System.Windows.Forms.Button AutoStep;
|
||||
private System.Windows.Forms.Button RunButton;
|
||||
private System.Windows.Forms.Button StopButton;
|
||||
private System.Windows.Forms.DataGridView _registerData;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn RegNum;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn R;
|
||||
@ -523,9 +658,6 @@
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn TaskName;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn TaskState;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn TaskPC;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn T;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Addr;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Source;
|
||||
private System.Windows.Forms.GroupBox groupBox3;
|
||||
private System.Windows.Forms.DataGridView _otherRegs;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Reg;
|
||||
@ -534,5 +666,17 @@
|
||||
private System.Windows.Forms.DataGridView _memoryData;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Address;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Data;
|
||||
private System.Windows.Forms.DataGridViewCheckBoxColumn Breakpoint;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn T;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Addr;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Source;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label ExecutionStateLabel;
|
||||
private System.Windows.Forms.TextBox JumpToAddress;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.GroupBox groupBox5;
|
||||
private System.Windows.Forms.DataGridView _diskData;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,7 @@ using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using Contralto.CPU;
|
||||
using System.Threading;
|
||||
|
||||
namespace Contralto
|
||||
{
|
||||
@ -17,6 +18,7 @@ namespace Contralto
|
||||
public Debugger(AltoSystem system)
|
||||
{
|
||||
_system = system;
|
||||
_breakpointEnabled = new bool[1024];
|
||||
|
||||
InitializeComponent();
|
||||
InitControls();
|
||||
@ -39,6 +41,7 @@ namespace Contralto
|
||||
SourceLine src = new SourceLine(line);
|
||||
|
||||
int i = _sourceViewer.Rows.Add(
|
||||
false, // breakpoint
|
||||
GetTextForTask(src.Task),
|
||||
src.Address,
|
||||
src.Text);
|
||||
@ -80,7 +83,7 @@ namespace Contralto
|
||||
_taskData.Rows[i].Cells[0].Value = GetTextForTask((TaskType)i);
|
||||
_taskData.Rows[i].Cells[1].Value = GetTextForTaskState(_system.CPU.Tasks[i]);
|
||||
_taskData.Rows[i].Cells[2].Value =
|
||||
_system.CPU.Tasks[i] != null ? OctalHelpers.ToOctal(_system.CPU.Tasks[i].MPC, 4) : String.Empty;
|
||||
_system.CPU.Tasks[i] != null ? OctalHelpers.ToOctal(_system.CPU.Tasks[i].MPC, 4) : String.Empty;
|
||||
}
|
||||
|
||||
// Other registers
|
||||
@ -93,17 +96,48 @@ namespace Contralto
|
||||
_otherRegs.Rows[6].Cells[1].Value = OctalHelpers.ToOctal(_system.MemoryBus.MD, 6);
|
||||
_otherRegs.Rows[7].Cells[1].Value = OctalHelpers.ToOctal(_system.MemoryBus.Cycle, 2);
|
||||
|
||||
// Find the right source line
|
||||
foreach(DataGridViewRow row in _sourceViewer.Rows)
|
||||
// Disk info
|
||||
_diskData.Rows[0].Cells[1].Value = _system.DiskController.ClocksUntilNextSector.ToString("0.00");
|
||||
_diskData.Rows[1].Cells[1].Value = _system.DiskController.Cylinder.ToString();
|
||||
_diskData.Rows[2].Cells[1].Value = _system.DiskController.SeekCylinder.ToString();
|
||||
_diskData.Rows[3].Cells[1].Value = _system.DiskController.Head.ToString();
|
||||
_diskData.Rows[4].Cells[1].Value = _system.DiskController.Sector.ToString();
|
||||
_diskData.Rows[5].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KDATA, 6);
|
||||
_diskData.Rows[6].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KADR, 6);
|
||||
_diskData.Rows[7].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KCOM, 6);
|
||||
_diskData.Rows[8].Cells[1].Value = OctalHelpers.ToOctal(_system.DiskController.KSTAT, 6);
|
||||
_diskData.Rows[9].Cells[1].Value = _system.DiskController.RECNO.ToString();
|
||||
|
||||
for (ushort i = 0; i < 1024; i++)
|
||||
{
|
||||
if (row.Tag != null &&
|
||||
(ushort)(row.Tag) == _system.CPU.CurrentTask.MPC)
|
||||
{
|
||||
_sourceViewer.ClearSelection();
|
||||
row.Selected = true;
|
||||
_sourceViewer.CurrentCell = row.Cells[0];
|
||||
_memoryData.Rows[i].Cells[1].Value = OctalHelpers.ToOctal(_system.MemoryBus.DebugReadWord(i), 6);
|
||||
}
|
||||
|
||||
// Find the right source line
|
||||
HighlightSourceLine(_system.CPU.CurrentTask.MPC);
|
||||
|
||||
// Exec state
|
||||
switch(_execState)
|
||||
{
|
||||
case ExecutionState.Stopped:
|
||||
ExecutionStateLabel.Text = "Stopped";
|
||||
break;
|
||||
|
||||
case ExecutionState.SingleStep:
|
||||
ExecutionStateLabel.Text = "Stepping";
|
||||
break;
|
||||
|
||||
case ExecutionState.AutoStep:
|
||||
ExecutionStateLabel.Text = "Stepping (auto)";
|
||||
break;
|
||||
|
||||
case ExecutionState.Running:
|
||||
ExecutionStateLabel.Text = "Running";
|
||||
break;
|
||||
|
||||
case ExecutionState.BreakpointStop:
|
||||
ExecutionStateLabel.Text = "Stopped (bkpt)";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,11 +153,11 @@ namespace Contralto
|
||||
_taskData.Rows.Add("0", "0", "0");
|
||||
}
|
||||
|
||||
/*
|
||||
for (int i=0;i<65536;i++)
|
||||
|
||||
for (ushort i=0;i<1024;i++)
|
||||
{
|
||||
_memoryData.Rows.Add();
|
||||
} */
|
||||
_memoryData.Rows.Add(OctalHelpers.ToOctal(i, 6), OctalHelpers.ToOctal(_system.MemoryBus.DebugReadWord(i), 6));
|
||||
}
|
||||
|
||||
_otherRegs.Rows.Add("L", "0");
|
||||
_otherRegs.Rows.Add("T", "0");
|
||||
@ -133,11 +167,61 @@ namespace Contralto
|
||||
_otherRegs.Rows.Add("MAR", "0");
|
||||
_otherRegs.Rows.Add("MD", "0");
|
||||
_otherRegs.Rows.Add("MCycle", "0");
|
||||
|
||||
_diskData.Rows.Add("Cycles", "0");
|
||||
_diskData.Rows.Add("Cylinder", "0");
|
||||
_diskData.Rows.Add("D.Cylinder", "0");
|
||||
_diskData.Rows.Add("Head", "0");
|
||||
_diskData.Rows.Add("Sector", "0");
|
||||
_diskData.Rows.Add("KDATA", "0");
|
||||
_diskData.Rows.Add("KADR", "0");
|
||||
_diskData.Rows.Add("KCOM", "0");
|
||||
_diskData.Rows.Add("KSTAT", "0");
|
||||
_diskData.Rows.Add("RECNO", "0");
|
||||
|
||||
}
|
||||
|
||||
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
|
||||
/// <summary>
|
||||
/// Handle breakpoint placement on column 0.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void SourceViewCellClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
// Check for breakpoint column click.
|
||||
if (e.ColumnIndex == 0)
|
||||
{
|
||||
// See if this is a source line, if so check/uncheck the box
|
||||
// and set/unset a breakpoint for the line
|
||||
if (_sourceViewer.Rows[e.RowIndex].Tag != null)
|
||||
{
|
||||
bool value = (bool)_sourceViewer.Rows[e.RowIndex].Cells[0].Value;
|
||||
_sourceViewer.Rows[e.RowIndex].Cells[0].Value = !value;
|
||||
|
||||
ModifyBreakpoint((UInt16)_sourceViewer.Rows[e.RowIndex].Tag, !value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void HighlightSourceLine(UInt16 address)
|
||||
{
|
||||
foreach (DataGridViewRow row in _sourceViewer.Rows)
|
||||
{
|
||||
if (row.Tag != null &&
|
||||
(ushort)(row.Tag) == address)
|
||||
{
|
||||
_sourceViewer.ClearSelection();
|
||||
row.Selected = true;
|
||||
_sourceViewer.CurrentCell = row.Cells[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ModifyBreakpoint(UInt16 address, bool set)
|
||||
{
|
||||
_breakpointEnabled[address] = set;
|
||||
}
|
||||
|
||||
private string GetTextForTaskState(AltoCPU.Task task)
|
||||
@ -148,8 +232,16 @@ namespace Contralto
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: block status
|
||||
return task.Wakeup ? "W" : String.Empty;
|
||||
// Wakeup bit
|
||||
string status = task.Wakeup ? "W" : String.Empty;
|
||||
|
||||
// Run bit
|
||||
if (task == _system.CPU.CurrentTask)
|
||||
{
|
||||
status += "R";
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,17 +423,177 @@ namespace Contralto
|
||||
|
||||
}
|
||||
|
||||
private void JumpToButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
UInt16 address = Convert.ToUInt16(JumpToAddress.Text, 8);
|
||||
|
||||
// find the source address that matches this, if any.
|
||||
HighlightSourceLine(address);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// eh, just do nothing for now
|
||||
}
|
||||
}
|
||||
|
||||
private void OnJumpAddressKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Return ||
|
||||
e.KeyCode == Keys.Enter)
|
||||
{
|
||||
try
|
||||
{
|
||||
UInt16 address = Convert.ToUInt16(JumpToAddress.Text, 8);
|
||||
|
||||
// find the source address that matches this, if any.
|
||||
HighlightSourceLine(address);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// eh, just do nothing for now
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStepButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
SetExecutionState(ExecutionState.SingleStep);
|
||||
ExecuteStep();
|
||||
SetExecutionState(ExecutionState.Stopped);
|
||||
}
|
||||
|
||||
private void OnAutoStepButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
//
|
||||
// Continuously step (and update the UI)
|
||||
// until the "Stop" button is pressed or something bad happens.
|
||||
//
|
||||
_execThread = new Thread(new System.Threading.ParameterizedThreadStart(ExecuteProc));
|
||||
_execThread.Start(ExecutionType.Auto);
|
||||
SetExecutionState(ExecutionState.AutoStep);
|
||||
}
|
||||
|
||||
private void RunButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
//
|
||||
// Continuously execute, but do not update UI
|
||||
// until the "Stop" button is pressed or something bad happens.
|
||||
//
|
||||
_execThread = new Thread(new System.Threading.ParameterizedThreadStart(ExecuteProc));
|
||||
_execThread.Start(ExecutionType.Normal);
|
||||
SetExecutionState(ExecutionState.Running);
|
||||
}
|
||||
|
||||
private void OnStopButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
if (_execThread != null &&
|
||||
_execThread.IsAlive)
|
||||
{
|
||||
// Signal for the exec thread to end
|
||||
_execAbort = true;
|
||||
|
||||
// Wait for the thread to exit.
|
||||
_execThread.Join();
|
||||
|
||||
_execThread = null;
|
||||
}
|
||||
|
||||
SetExecutionState(ExecutionState.Stopped);
|
||||
}
|
||||
|
||||
private void ExecuteStep()
|
||||
{
|
||||
_system.SingleStep();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void ExecuteProc(object param)
|
||||
{
|
||||
ExecutionType execType = (ExecutionType)param;
|
||||
|
||||
StepDelegate refUI = new StepDelegate(RefreshUI);
|
||||
StepDelegate inv = new StepDelegate(Invalidate);
|
||||
while (true)
|
||||
{
|
||||
if (execType == ExecutionType.Auto)
|
||||
{
|
||||
// Execute a single step, then update UI and
|
||||
// sleep to give messages time to run.
|
||||
_system.SingleStep();
|
||||
|
||||
this.BeginInvoke(refUI);
|
||||
this.BeginInvoke(inv);
|
||||
System.Threading.Thread.Sleep(10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just execute one step, do not update UI.
|
||||
_system.SingleStep();
|
||||
}
|
||||
|
||||
if (_execAbort ||
|
||||
_breakpointEnabled[_system.CPU.CurrentTask.MPC])
|
||||
{
|
||||
// Stop here as we've hit a breakpoint or have been stopped Update UI
|
||||
// to indicate where we stopped.
|
||||
this.BeginInvoke(refUI);
|
||||
this.BeginInvoke(inv);
|
||||
|
||||
if (!_execAbort)
|
||||
{
|
||||
SetExecutionState(ExecutionState.BreakpointStop);
|
||||
}
|
||||
|
||||
_execAbort = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetExecutionState(ExecutionState state)
|
||||
{
|
||||
_execState = state;
|
||||
this.BeginInvoke(new StepDelegate(RefreshUI));
|
||||
}
|
||||
|
||||
|
||||
private enum ExecutionType
|
||||
{
|
||||
None = 0,
|
||||
Step,
|
||||
Auto,
|
||||
Normal,
|
||||
}
|
||||
|
||||
private enum ExecutionState
|
||||
{
|
||||
Stopped = 0,
|
||||
SingleStep,
|
||||
AutoStep,
|
||||
Running,
|
||||
BreakpointStop,
|
||||
}
|
||||
|
||||
private delegate void StepDelegate();
|
||||
|
||||
private AltoSystem _system;
|
||||
|
||||
// Unicode character for the Arrow used by Alto microcode
|
||||
private const char _arrowChar = (char)0x2190;
|
||||
|
||||
|
||||
// Thread used for execution other than single-step
|
||||
private Thread _execThread;
|
||||
private bool _execAbort;
|
||||
private ExecutionState _execState;
|
||||
|
||||
|
||||
|
||||
// Debugger breakpoints; one entry per address since we only need
|
||||
// to worry about a 10 bit address space, this is fast and uses little memory.
|
||||
private bool[] _breakpointEnabled;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,6 +117,9 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="Breakpoint.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="T.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
@ -156,4 +159,10 @@
|
||||
<metadata name="Data.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="dataGridViewTextBoxColumn1.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="dataGridViewTextBoxColumn2.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@ -659,7 +659,7 @@ EM00517> INXE: T<-EIOffset, :INXCom; ***X21 addition.
|
||||
|
||||
EM00520> INXCom: MAR<-T<-IR<- SAD+T; *** X21 addition.
|
||||
EM00521> PC<- L, L<- 0+T+1; *** X21 change.
|
||||
EM00522> INXB: SAD<- L;
|
||||
EM00522> INXB: SAD<- L; **NB (JDersch 9/14 -- this is actually MD<-PC !)
|
||||
EM00523> SINK<- DISP, BUS,TASK;
|
||||
EM00524> SAD<- L, :Q0;
|
||||
|
||||
|
||||
@ -41,7 +41,12 @@ namespace Contralto.IO
|
||||
{
|
||||
_kCom = value;
|
||||
|
||||
//
|
||||
// Read control bits (pg. 47 of hw manual)
|
||||
_xferOff = (_kCom & 0x10) == 0x10;
|
||||
_wdInhib = (_kCom & 0x08) == 0x08;
|
||||
_bClkSource = (_kCom & 0x04) == 0x04;
|
||||
_wffo = (_kCom & 0x02) == 0x02;
|
||||
_sendAdr = (_kCom & 0x01) == 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +61,36 @@ namespace Contralto.IO
|
||||
get { return _recMap[_recNo]; }
|
||||
}
|
||||
|
||||
public int Cylinder
|
||||
{
|
||||
get { return _cylinder; }
|
||||
}
|
||||
|
||||
public int SeekCylinder
|
||||
{
|
||||
get { return _destCylinder; }
|
||||
}
|
||||
|
||||
public int Head
|
||||
{
|
||||
get { return _head; }
|
||||
}
|
||||
|
||||
public int Sector
|
||||
{
|
||||
get { return _sector; }
|
||||
}
|
||||
|
||||
public int Drive
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public double ClocksUntilNextSector
|
||||
{
|
||||
get { return _sectorClocks - _elapsedSectorTime; }
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ClearStatus();
|
||||
@ -100,7 +135,7 @@ namespace Contralto.IO
|
||||
{
|
||||
_cylinder++;
|
||||
}
|
||||
else
|
||||
else if (_cylinder > _destCylinder)
|
||||
{
|
||||
_cylinder--;
|
||||
}
|
||||
@ -113,6 +148,33 @@ namespace Contralto.IO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Select data word based on elapsed time in this sector, if data transfer is not inhibited.
|
||||
// On a new word, wake up the disk word task if not inhibited
|
||||
// TODO: the exact mechanics of this are still kind of mysterious.
|
||||
// Things to examine the schematics / uCode for:
|
||||
// - Use of WFFO bit -- is this related to the "sync word" that the docs mention?
|
||||
// - how does WFFO work -- I assume the "1 bit" mentioned in the docs indicates the MFM bit
|
||||
// and indicates the start of the next data word (or is at least used to wait for the next
|
||||
// data word)
|
||||
// - How does the delaying work
|
||||
// The microcode word-copying code works basically as:
|
||||
// On wakeup:
|
||||
// - read word, store into memory.
|
||||
// - block task (remove wakeup)
|
||||
// - task switch (let something else run)
|
||||
// - repeat until all words read
|
||||
// that is, the microcode expects to be woken up on a per-word basis, and it only reads in one word
|
||||
// per wakeup.
|
||||
//
|
||||
// pseudocode so far:
|
||||
// if (elapsed word time > word time)
|
||||
// {
|
||||
// elapsed word time = 0 (modulo remainder)
|
||||
// _kData = next word
|
||||
// if (!_wdInhib) DiskSectorTask.Wakeup();
|
||||
// }
|
||||
}
|
||||
|
||||
public void ClearStatus()
|
||||
@ -148,16 +210,16 @@ namespace Contralto.IO
|
||||
// sanity check: see if SENDADR bit is set, if not we'll signal an error (since I'm trusting that
|
||||
// the official Xerox uCode is doing the right thing, this will help ferret out emulation issues.
|
||||
// eventually this can be removed.)
|
||||
if ((_kCom & 0x1) != 1)
|
||||
if (!_sendAdr)
|
||||
{
|
||||
throw new InvalidOperationException("STROBE while SENDADR bit of KCOMM not 1. Unexpected.");
|
||||
throw new InvalidOperationException("STROBE while SENDADR bit of KCOM not 1. Unexpected.");
|
||||
}
|
||||
|
||||
_destCylinder = (_kData & 0x0ff8) >> 3;
|
||||
|
||||
// set "seek fail" bit based on selected cylinder (if out of bounds) and do not
|
||||
// commence a seek if so.
|
||||
if (_destCylinder < 203)
|
||||
if (_destCylinder > 202)
|
||||
{
|
||||
_kStat |= 0x0080;
|
||||
}
|
||||
@ -202,6 +264,13 @@ namespace Contralto.IO
|
||||
0, 2, 3, 1
|
||||
};
|
||||
|
||||
// KCOM bits
|
||||
private bool _xferOff;
|
||||
private bool _wdInhib;
|
||||
private bool _bClkSource;
|
||||
private bool _wffo;
|
||||
private bool _sendAdr;
|
||||
|
||||
// Current disk position
|
||||
private int _cylinder;
|
||||
private int _destCylinder;
|
||||
|
||||
@ -73,6 +73,15 @@ namespace Contralto.Memory
|
||||
get { return _memoryOperationActive; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for debugging only -- returns the (correctly mapped)
|
||||
/// word at the specified address
|
||||
/// </summary>
|
||||
public ushort DebugReadWord(ushort address)
|
||||
{
|
||||
return ReadFromBus(address);
|
||||
}
|
||||
|
||||
public void Clock()
|
||||
{
|
||||
_memoryCycle++;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user