mirror of
https://github.com/livingcomputermuseum/ContrAlto.git
synced 2026-01-27 12:31:52 +00:00
A few fixes to DNS<- behavior and some tweaks to the disk controller. Boot code is progressing further.
This commit is contained in:
@@ -41,6 +41,9 @@ namespace Contralto
|
||||
{
|
||||
_cpu.Reset();
|
||||
_memBus.Reset();
|
||||
_mem.Reset();
|
||||
ALU.Reset();
|
||||
Shifter.Reset();
|
||||
_diskController.Reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace Contralto.CPU
|
||||
get { return _aluC0; }
|
||||
}
|
||||
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// Reset registers
|
||||
|
||||
@@ -26,11 +26,18 @@ namespace Contralto.CPU
|
||||
public static class Shifter
|
||||
{
|
||||
static Shifter()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
_op = ShifterOp.Invalid;
|
||||
_count = 0;
|
||||
_output = 0;
|
||||
_magic = false;
|
||||
_dns = false;
|
||||
_dnsCarry = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -71,6 +78,12 @@ namespace Contralto.CPU
|
||||
/// <param name="dns"></param>
|
||||
public static void SetDNS(bool dns, int carry)
|
||||
{
|
||||
// Sanity check
|
||||
if (carry != 0 && carry != 1)
|
||||
{
|
||||
throw new InvalidOperationException("carry can only be 0 or 1.");
|
||||
}
|
||||
|
||||
_dns = dns;
|
||||
_dnsCarry = carry;
|
||||
}
|
||||
@@ -109,7 +122,16 @@ namespace Contralto.CPU
|
||||
}
|
||||
else if (_dns)
|
||||
{
|
||||
throw new NotImplementedException("DNS LSH 1");
|
||||
//
|
||||
// "Rotate the 17 input bits left by one bit. This has the effect of rotating
|
||||
// bit 0 left into the carry position and the carry bit into bit 15."
|
||||
//
|
||||
|
||||
// Put input carry into bit 15.
|
||||
_output = (ushort)(_output | _dnsCarry);
|
||||
|
||||
// update carry
|
||||
_dnsCarry = ((input & 0x8000) >> 15);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -124,7 +146,16 @@ namespace Contralto.CPU
|
||||
}
|
||||
else if (_dns)
|
||||
{
|
||||
throw new NotImplementedException("DNS RSH 1");
|
||||
//
|
||||
// "Rotate the 17 bits right by one bit. Bit 15 is rotated into the carry position
|
||||
// and the carry bit into bit 0."
|
||||
//
|
||||
|
||||
// Put input carry into bit 0.
|
||||
_output |= (ushort)(_output | (_dnsCarry << 15));
|
||||
|
||||
// update carry
|
||||
_dnsCarry = input & 0x1;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -138,8 +169,11 @@ namespace Contralto.CPU
|
||||
}
|
||||
|
||||
if (_dns)
|
||||
{
|
||||
throw new NotImplementedException("DNS LCY");
|
||||
{
|
||||
//
|
||||
// "Swap the 8-bit halves of the 16-bit result. The carry is not affected."
|
||||
//
|
||||
_output = (ushort)(((input & 0xff00) >> 8) | ((input & 0x00ff) << 8));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Contralto.Memory;
|
||||
using Contralto.Logging;
|
||||
|
||||
namespace Contralto.CPU
|
||||
{
|
||||
@@ -61,6 +62,7 @@ namespace Contralto.CPU
|
||||
{
|
||||
case DiskF1.LoadKDATA:
|
||||
// "The KDATA register is loaded from BUS[0-15]."
|
||||
Log.Write(LogComponent.DiskController, "KDATA loaded with {0}", OctalHelpers.ToOctal(_busData));
|
||||
_cpu._system.DiskController.KDATA = _busData;
|
||||
break;
|
||||
|
||||
@@ -69,6 +71,7 @@ namespace Contralto.CPU
|
||||
// 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);
|
||||
Log.Write(LogComponent.DiskController, "KADR bus data is {0}", OctalHelpers.ToOctal(_busData));
|
||||
break;
|
||||
|
||||
case DiskF1.LoadKCOMM:
|
||||
@@ -173,6 +176,10 @@ namespace Contralto.CPU
|
||||
// "NEXT <- NEXT OR (IF disk not ready to accept command THEN 1 ELSE 0)
|
||||
// for now, always zero (not sure when this would be 1 yet)
|
||||
_nextModifier |= GetInitModifier(instruction);
|
||||
if (!_cpu._system.DiskController.Ready)
|
||||
{
|
||||
_nextModifier |= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -283,7 +283,7 @@ namespace Contralto.CPU
|
||||
case 0x500:
|
||||
case 0x600:
|
||||
// NEG, INC, ADC, SUB, ADD, AND - invert the carry bit
|
||||
if (ALU.Carry != 0)
|
||||
if (_cpu._aluC0 != 0)
|
||||
{
|
||||
carry = (~carry) & 0x1;
|
||||
}
|
||||
|
||||
@@ -339,13 +339,19 @@ namespace Contralto.CPU
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// We always do the shifter operation; DNS may need its output.
|
||||
//
|
||||
Shifter.DoOperation(_cpu._l, _cpu._t);
|
||||
|
||||
//
|
||||
// Write back to registers:
|
||||
//
|
||||
// Do writeback to selected R register from shifter output
|
||||
// Do writeback to selected R register from shifter output.
|
||||
//
|
||||
if (_loadR)
|
||||
{
|
||||
_cpu._r[_rSelect] = Shifter.DoOperation(_cpu._l, _cpu._t);
|
||||
{
|
||||
_cpu._r[_rSelect] = Shifter.Output;
|
||||
}
|
||||
|
||||
// Do writeback to selected R register from M
|
||||
|
||||
@@ -96,6 +96,8 @@ namespace Contralto
|
||||
_otherRegs.Rows[2].Cells[1].Value = OctalHelpers.ToOctal(_system.CPU.M, 6);
|
||||
_otherRegs.Rows[3].Cells[1].Value = OctalHelpers.ToOctal(_system.CPU.IR, 6);
|
||||
_otherRegs.Rows[4].Cells[1].Value = OctalHelpers.ToOctal(_system.CPU.ALUC0, 1);
|
||||
//_otherRegs.Rows[4].Cells[1].Value = OctalHelpers.ToOctal(_system.CPU.Carry, 1);
|
||||
//_otherRegs.Rows[4].Cells[1].Value = OctalHelpers.ToOctal(_system.CPU.Skip, 1);
|
||||
_otherRegs.Rows[5].Cells[1].Value = OctalHelpers.ToOctal(_system.MemoryBus.MAR, 6);
|
||||
_otherRegs.Rows[6].Cells[1].Value = OctalHelpers.ToOctal(_system.MemoryBus.MD, 6);
|
||||
_otherRegs.Rows[7].Cells[1].Value = OctalHelpers.ToOctal(_system.MemoryBus.Cycle & 0x3f, 2);
|
||||
@@ -183,9 +185,11 @@ namespace Contralto
|
||||
_otherRegs.Rows.Add("M", "0");
|
||||
_otherRegs.Rows.Add("IR", "0");
|
||||
_otherRegs.Rows.Add("ALUC0", "0");
|
||||
//_otherRegs.Rows.Add("CARRY", "0");
|
||||
//_otherRegs.Rows.Add("SKIP", "0");
|
||||
_otherRegs.Rows.Add("MAR", "0");
|
||||
_otherRegs.Rows.Add("MD", "0");
|
||||
_otherRegs.Rows.Add("MCycle", "0");
|
||||
_otherRegs.Rows.Add("MCycle", "0");
|
||||
|
||||
_diskData.Rows.Add("Cycles", "0");
|
||||
_diskData.Rows.Add("Cylinder", "0");
|
||||
@@ -492,6 +496,8 @@ namespace Contralto
|
||||
|
||||
private void OnStepButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
StopExecThread();
|
||||
|
||||
SetExecutionState(ExecutionState.SingleStep);
|
||||
ExecuteStep();
|
||||
SetExecutionState(ExecutionState.Stopped);
|
||||
@@ -499,6 +505,7 @@ namespace Contralto
|
||||
|
||||
private void OnAutoStepButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
StopExecThread();
|
||||
//
|
||||
// Continuously step (and update the UI)
|
||||
// until the "Stop" button is pressed or something bad happens.
|
||||
@@ -510,6 +517,7 @@ namespace Contralto
|
||||
|
||||
private void RunButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
StopExecThread();
|
||||
//
|
||||
// Continuously execute, but do not update UI
|
||||
// until the "Stop" button is pressed or something bad happens.
|
||||
@@ -524,6 +532,7 @@ namespace Contralto
|
||||
|
||||
private void RunToNextTaskButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
StopExecThread();
|
||||
//
|
||||
// Continuously execute until the next task switch but do not update UI
|
||||
// until the "Stop" button is pressed or something bad happens.
|
||||
@@ -546,6 +555,8 @@ namespace Contralto
|
||||
/// <param name="e"></param>
|
||||
private void NovaStep_Click(object sender, EventArgs e)
|
||||
{
|
||||
StopExecThread();
|
||||
|
||||
{
|
||||
_execThread = new Thread(new System.Threading.ParameterizedThreadStart(ExecuteProc));
|
||||
_execThread.Start(ExecutionType.NextNovaInstruction);
|
||||
@@ -554,6 +565,27 @@ namespace Contralto
|
||||
}
|
||||
|
||||
private void OnStopButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
StopExecThread();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
private void ResetButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
StopExecThread();
|
||||
_system.Reset();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void ExecuteStep()
|
||||
{
|
||||
StopExecThread();
|
||||
_system.SingleStep();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void StopExecThread()
|
||||
{
|
||||
if (_execThread != null &&
|
||||
_execThread.IsAlive)
|
||||
@@ -570,17 +602,6 @@ namespace Contralto
|
||||
SetExecutionState(ExecutionState.Stopped);
|
||||
}
|
||||
|
||||
private void ResetButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
_system.Reset();
|
||||
}
|
||||
|
||||
private void ExecuteStep()
|
||||
{
|
||||
_system.SingleStep();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void ExecuteProc(object param)
|
||||
{
|
||||
ExecutionType execType = (ExecutionType)param;
|
||||
|
||||
329
Contralto/Disassembly/boot block disassembly.txt
Normal file
329
Contralto/Disassembly/boot block disassembly.txt
Normal file
@@ -0,0 +1,329 @@
|
||||
000:000000 - JMP 000
|
||||
001:000345 - JMP 345 ; Entrypoint
|
||||
|
||||
002:000354 - JMP 354 ; Unused (version info, overwritten by disk status by microcode.
|
||||
003:000403 - JMP .+3 ;(6) ; Ditto
|
||||
004:120064 - COMC 1,0,SZR ; Build date
|
||||
005:064330 - NIOP 1,30
|
||||
|
||||
|
||||
006:004415 - JSR .+15 ;(23) ; JSR to zero-length routine at 23; side effect is loading 24 into AC3 (starting offset of data storage)
|
||||
007:171000 - MOV 3,2 ; copy address 24 into AC2
|
||||
010:020410 - LDA 0,.+10 ;(20) ; Load AC0 with 44120 ; disk command (command seal, check header, check label, read data, xfer on, drive 0)
|
||||
011:024411 - LDA 1,.+11 ;(22) ; Load AC1 with 402 ; address ?
|
||||
012:004540 - JSR .+140 ;(152) ; jump to subroutine at 152; copy label from 402 to 40 and 62.
|
||||
013:020406 - LDA 0,.+6 ;(21) ; AC0 gets 400
|
||||
014:041007 - STA 0,AC2+7 ; store 400 at 33
|
||||
015:004210 - JSR 210 ; jump to subroutine at 210;
|
||||
016:064401 - DIA 1,1 ; we die here; this is a JSRII instruction which indirects to 0... assume this should actually start real code
|
||||
|
||||
; data ?
|
||||
017:176776 - SUBSC# 3,3,SEZ
|
||||
|
||||
; data
|
||||
020:044120 - STA 1,120
|
||||
021:000400 - JMP .+0 ;(21)
|
||||
022:000402 - JMP .+2 ;(24)
|
||||
|
||||
023:005400 - JSR AC3+0 ; Return from zero-length routine
|
||||
|
||||
; Appear to be used as pointers to DCBs at 26 and 50; swapped by routine at 112
|
||||
024:176217 - ADCR# 3,3,SBN
|
||||
025:176175 - ADCLC# 3,3,SNR
|
||||
|
||||
; beginning of first DCB
|
||||
026:176217 - ADCR# 3,3,SBN ; Pointer to next DCB
|
||||
027:027400 - LDA@ 1,AC3+0 ; Disk Status
|
||||
030:044130 - STA 1,130 ; Disk command
|
||||
031:176205 - ADCR 3,3,SNR ; Header address
|
||||
032:176207 - ADCR 3,3,SBN ; Label address
|
||||
033:175550 - INCLO# 3,3 ; Data address (gets 400 (STA at 14))
|
||||
034:000000 - JMP 0 ; non-error interrupt mask
|
||||
035:000000 - JMP 0 ; error interrupt mask
|
||||
036:000000 - JMP 0 ; reserved
|
||||
037:000000 - JMP 0 ; disk address
|
||||
|
||||
; 1st copy of label block at 402 starts here
|
||||
040:130374 - COMSC# 1,2,SZR ; 000400 - disk address (?)
|
||||
041:000000 - JMP 0 ; 120374 - previous disk address
|
||||
042:000000 - JMP 0 ; 000000 - blank
|
||||
043:000000 - JMP 0 ; 001000 - num chars
|
||||
044:176007 - ADC 3,3,SBN ; 000001 - page number
|
||||
045:000001 - JMP 1 ; 000001 - version
|
||||
046:000000 - JMP 0 ; 000000 - sn high
|
||||
047:000176 - JMP 176 ; 000176 - sn low
|
||||
; ends here
|
||||
|
||||
; beginning of 2nd DCB
|
||||
050:000000 - JMP 0 ; Pointer to next DCB
|
||||
051:000000 - JMP 0 ; Disk Status
|
||||
052:044130 - STA 1,130 ; Disk command
|
||||
053:176227 - ADCRZ 3,3,SBN ; Header address
|
||||
054:176231 - ADCRZ# 3,3,SKP ; Label address
|
||||
055:176150 - ADCLO# 3,3 ; Data address
|
||||
056:000000 - JMP 0 ; non-error interrupt mask
|
||||
057:000000 - JMP 0 ; error interrupt mask
|
||||
060:000000 - JMP 0 ; reserved
|
||||
061:130374 - COMSC# 1,2,SZR ; disk address
|
||||
|
||||
; 2nd copy of label block at 402 starts here (and magically matches
|
||||
; what's already there!)
|
||||
062:000400 - JMP .+0 ;(62) ; 000400 - disk address (?)
|
||||
063:120374 - COMSC# 1,0,SZR ; 120374 - previous disk address
|
||||
064:000000 - JMP 0 ; 000000 - blank
|
||||
065:001000 - JMP AC2+0 ; 001000 - num chars
|
||||
066:000001 - JMP 1 ; 000001 - page number
|
||||
067:000001 - JMP 1 ; 000001 - version
|
||||
070:000000 - JMP 0 ; 000000 - sn high
|
||||
071:000176 - JMP 176 ; 000176 - sn low
|
||||
; ends here
|
||||
|
||||
; temp locations used for return addresses, etc.
|
||||
072:000000 - JMP 0
|
||||
073:176016 - ADC# 3,3,SEZ
|
||||
074:176147 - ADCLO 3,3,SBN
|
||||
075:176310 - ADCS# 3,3
|
||||
076:000536 - JMP .+136 ;(234)
|
||||
|
||||
; subroutine
|
||||
077:055051 - STA 3,AC2+51 ; save return address
|
||||
100:035000 - LDA 3,AC2+0 ; AC3 gets 26
|
||||
101:021405 - LDA 0,AC3+5 ; AC0 gets 400 from 33
|
||||
102:024717 - LDA 1,.+-61 ;(21) ; AC1 gets 400 from 21
|
||||
103:123000 - ADD 1,0 ; AC0 gets AC0+AC1 (1000)
|
||||
104:024404 - LDA 1,.+4 ;(110) ; AC1 gets -1000 (176777)
|
||||
105:106032 - ADCZ# 0,1,SZC ; Add 1s cmpl of AC0 (176777) and AC1 (no writeback), skip if carry is zero
|
||||
106:011051 - ISZ AC2+51 ; increment return address
|
||||
107:003051 - JMP@ AC2+51 ; return to ret address (+1 added if carry is nonzero)
|
||||
|
||||
; data
|
||||
110:176777 - SUBSC# 3,3,SBN
|
||||
111:000420 - JMP .+20 ;(131)
|
||||
|
||||
; subroutine; apparently we're too cool to save our return address.
|
||||
112:021000 - LDA 0,AC2+0 ; swap contents of locations 24 & 25
|
||||
113:025001 - LDA 1,AC2+1
|
||||
114:045000 - STA 1,AC2+0
|
||||
115:041001 - STA 0,AC2+1
|
||||
116:001400 - JMP AC3+0 ; return
|
||||
|
||||
; subroutine.
|
||||
117:055050 - STA 3,AC2+50 ; save ret
|
||||
120:176460 - SUBC 3,3 ; get zero
|
||||
121:055046 - STA 3,AC2+46 ; write zero to 72
|
||||
122:000551 - JMP .+151 ;(273) ; continue at 273
|
||||
|
||||
;subroutine
|
||||
123:055050 - STA 3,AC2+50 ; save return address
|
||||
124:035000 - LDA 3,AC2+0 ; AC3 gets DCB address (26 or 50)
|
||||
125:021412 - LDA 0,AC3+12 ; AC0 gets word 0 of label block @ 40
|
||||
126:025411 - LDA 1,AC3+11 ; AC1 gets word at 37 (disk address, word 11 of 1st DCB)
|
||||
127:035001 - LDA 3,AC2+1 ; AC3 gets other DCB address (@25 - 50 or 26)
|
||||
130:041411 - STA 0,AC3+11 ; write word 0 of label block to 61
|
||||
131:045413 - STA 1,AC3+13 ; write zero to 63
|
||||
132:102460 - SUBC 0,0 ; AC0 gets 0
|
||||
133:041400 - STA 0,AC3+0 ; zero out 50, 51 (pointer to next DCB, disk status)
|
||||
134:041401 - STA 0,AC3+1
|
||||
135:041412 - STA 0,AC3+12 ; zero out 62, 66 (label words)
|
||||
136:041416 - STA 0,AC3+16
|
||||
137:005053 - JSR AC2+53 ; 77 ; do subroutine at 77; this appears to check if loading is done
|
||||
140:000405 - JMP .+5 ;(145) ;
|
||||
141:035001 - LDA 3,AC2+1 ; AC3 gets address of 2nd DCB (50 or 26)
|
||||
142:041405 - STA 0,AC3+5 ; write 0 to DCB data address
|
||||
143:057000 - STA@ 3,AC2+0
|
||||
144:003050 - JMP@ AC2+50 ; return
|
||||
|
||||
; jumped here from 140
|
||||
145:004752 - JSR .+-26 ;(117)
|
||||
146:003047 - JMP@ AC2+47 ; wait, what? 47? return to.... caller of 210, at 16. This is the end of the loader routine.
|
||||
|
||||
; data
|
||||
147:000521 - JMP .+121 ;(270) ; KBLK address (pointer to first DCB used by disk hardware)
|
||||
|
||||
; data
|
||||
150:177756 - ANDSO# 3,3,SEZ
|
||||
151:000377 - JMP 377
|
||||
|
||||
; subroutine: copy label block from 402 twice, to 40 and 62. Initialize DCBs at 26 and 50.
|
||||
; on entry:
|
||||
; AC0 contains disk command
|
||||
; AC1 contains 402 (label address for sector 0, where microcode boot copied it originally)
|
||||
; AC2 contains 24 (offset for all data)
|
||||
; on exit:
|
||||
; Label record at 402 (8 bytes long) copied to locs 40-47 and 62-71;
|
||||
; DCB interrupt masks and addresses zeroed out (at 34-37, 56-61)
|
||||
; loc 25 points to DCB at 50
|
||||
|
||||
152:055047 - STA 3,AC2+47 ; save return address @ 73
|
||||
153:045051 - STA 1,AC2+51 ; write label address to 75 (AC1 loaded with 402 by caller)
|
||||
154:015051 - DSZ AC2+51 ; decrement address at 75 (401)
|
||||
155:041004 - STA 0,AC2+4 ; write 44120 to 30 ; DCB commands
|
||||
156:041026 - STA 0,AC2+26 ; write 44120 to 52
|
||||
157:034561 - LDA 3,.+161 ;(340) ; load AC3 with 2
|
||||
160:055050 - STA 3,AC2+50 ; write 2 to 74 - loop counter used at 202
|
||||
161:157000 - ADD 2,3 ; 24 + 2, result in AC3
|
||||
162:055000 - STA 3,AC2+0 ; store 26 at 24 (top of data structure pointed by AC2)
|
||||
|
||||
; top of loop
|
||||
163:102460 - SUBC 0,0 ; put a zero in AC0
|
||||
164:041406 - STA 0,AC3+6 ; zero out values at 34, 35, 36, 37 and 56, 57, 60, 61 (DCB entries)
|
||||
165:041407 - STA 0,AC3+7 ;
|
||||
166:041410 - STA 0,AC3+10
|
||||
167:041411 - STA 0,AC3+11
|
||||
170:024417 - LDA 1,.+17 ;(207) ; AC1 gets 177770 (-10)
|
||||
171:136400 - SUB 1,3 ; subtract AC3 from AC1, result in AC3 (26 minus -10 = 36) (calculate label offset)?
|
||||
172:055773 - STA 3,AC3+-5 ; store AC3 in AC3-5 (31)
|
||||
173:165400 - INC 3,1 ; inc AC3, store in AC1 (37)
|
||||
174:125400 - INC 1,1 ; Inc AC1 (AC1 now AC3 + 2 = 40)
|
||||
175:045774 - STA 1,AC3+-4 ; store AC1 at AC3-4 (32)
|
||||
176:021051 - LDA 0,AC2+51 ; AC0 gets AC2+51 (24+51) ; blt source (label address -1 = 401)
|
||||
177:034410 - LDA 3,.+10 ;(207) ; AC3 gets 177770 ; blt count (8 words)
|
||||
200:166000 - ADC 3,1 ; AC1 gets complement of AC1+AC3 ; blt dest (47 or 61)
|
||||
201:061005 - BLT ; block transfer -- copy label block from 402 to destination.
|
||||
202:015050 - DSZ AC2+50 ; decrement copy counter at AC2+50 (74), skip next if zero
|
||||
203:135401 - INC 1,3,SKP ; Increment AC1 (copy destination), stow in AC3, skip next instruction.
|
||||
204:003047 - JMP@ AC2+47 ; RTS: exit from DSZ at 202, jump to AC2+47 (@73 -- return from subroutine)
|
||||
205:055001 - STA 3,AC2+1 ; get here from 203; AC3 stored at AC2 + 1 (25 -- end address + 1 of copied label)
|
||||
206:000755 - JMP .+-23 ;(163) ; loop back to 163...
|
||||
|
||||
207:177770 - ANDSC# 3,3 ; data - BLT word count (complement)
|
||||
|
||||
210:055047 - STA 3,AC2+47 ; save return address
|
||||
211:004712 - JSR .+-66 ;(123) ; JSR to 123
|
||||
212:004700 - JSR .+-100 ;(112) ; JSR to 112 - swap DCBs @ 24,25
|
||||
|
||||
; loop here; wait for disk
|
||||
213:035000 - LDA 3,AC2+0 ; AC3 gets current DCB address
|
||||
214:025412 - LDA 1,AC3+12 ; AC1 gets label data (previous disk address)
|
||||
215:022732 - LDA@ 0,.+-46 ;(147) ; Load AC0 with contents KBLK (check controller status)
|
||||
216:101014 - MOV# 0,0,SZR ; if zero (error or idle) then go to 199
|
||||
217:000406 - JMP .+6 ;(225) ; not idle, go to 225
|
||||
220:021401 - LDA 0,AC3+1
|
||||
221:101014 - MOV# 0,0,SZR
|
||||
222:000406 - JMP .+6 ;(230)
|
||||
223:056724 - STA@ 3,.+-54 ;(147)
|
||||
224:000767 - JMP .+-11 ;(213)
|
||||
|
||||
225:125014 - MOV# 1,1,SZR ; we get here when the disk controller is not idle; see if prev. addr is zero
|
||||
226:000403 - JMP .+3 ;(231) ; not zero, go to 231
|
||||
227:000764 - JMP .+-14 ;(213) ; zero, loop at 213.
|
||||
230:004667 - JSR .+-111 ;(117)
|
||||
231:004672 - JSR .+-106 ;(123) ; next DCB?
|
||||
232:004665 - JSR .+-113 ;(117) ;
|
||||
233:000757 - JMP .+-21 ;(212)
|
||||
|
||||
|
||||
234:174400 - NEG 3,3
|
||||
235:160000 - COM 3,0
|
||||
236:024501 - LDA 1,.+101 ;(337)
|
||||
237:034711 - LDA 3,.+-67 ;(150)
|
||||
240:061005 - BLT
|
||||
241:004416 - JSR .+16 ;(257)
|
||||
|
||||
; data
|
||||
242:111111 - MOVL# 0,2,SKP
|
||||
243:000006 - JMP 6
|
||||
244:000000 - JMP 0
|
||||
245:000015 - JMP 15
|
||||
246:000200 - JMP 200
|
||||
247:000012 - JMP 12
|
||||
250:100022 - COMZ 0,0,SZC
|
||||
251:000016 - JMP 16
|
||||
252:000001 - JMP 1
|
||||
253:000000 - JMP 0
|
||||
254:100022 - COMZ 0,0,SZC
|
||||
255:000040 - JMP 40
|
||||
256:000001 - JMP 1
|
||||
|
||||
257:161000 - MOV 3,0
|
||||
260:024765 - LDA 1,.+-13 ;(245)
|
||||
261:034411 - LDA 3,.+11 ;(272)
|
||||
262:061005 - BLT
|
||||
263:020757 - LDA 0,.+-21 ;(242)
|
||||
264:024457 - LDA 1,.+57 ;(343)
|
||||
265:034663 - LDA 3,.+-115 ;(150)
|
||||
266:061006 - BLKS
|
||||
267:020451 - LDA 0,.+51 ;(340)
|
||||
270:042621 - STA@ 0,.+-157 ;(111)
|
||||
271:000400 - JMP .+0 ;(271)
|
||||
|
||||
;
|
||||
272:177764 - ANDSC 3,3,SZR
|
||||
|
||||
; continuation of subroutine at 122
|
||||
273:035000 - LDA 3,AC2+0
|
||||
274:021401 - LDA 0,AC3+1
|
||||
275:101015 - MOV# 0,0,SNR
|
||||
276:000775 - JMP .+-3 ;(273)
|
||||
277:024652 - LDA 1,.+-126 ;(151)
|
||||
300:107405 - AND 0,1,SNR
|
||||
301:003050 - JMP@ AC2+50 ; return
|
||||
302:011046 - ISZ AC2+46
|
||||
303:025046 - LDA 1,AC2+46
|
||||
304:020433 - LDA 0,.+33 ;(337)
|
||||
305:122532 - SUBLZ# 1,0,SZC
|
||||
306:001052 - JMP AC2+52
|
||||
307:102460 - SUBC 0,0
|
||||
310:041401 - STA 0,AC3+1
|
||||
311:041410 - STA 0,AC3+10
|
||||
312:041412 - STA 0,AC3+12
|
||||
313:041413 - STA 0,AC3+13
|
||||
314:041414 - STA 0,AC3+14
|
||||
315:041415 - STA 0,AC3+15
|
||||
316:041416 - STA 0,AC3+16
|
||||
317:020417 - LDA 0,.+17 ;(336)
|
||||
320:107405 - AND 0,1,SNR
|
||||
321:000403 - JMP .+3 ;(324)
|
||||
322:056625 - STA@ 3,.+-153 ;(147)
|
||||
323:000750 - JMP .+-30 ;(273)
|
||||
324:054421 - STA 3,.+21 ;(345)
|
||||
325:021411 - LDA 0,AC3+11
|
||||
326:024412 - LDA 1,.+12 ;(340)
|
||||
327:123400 - AND 1,0
|
||||
330:125400 - INC 1,1
|
||||
331:044413 - STA 1,.+13 ;(344)
|
||||
332:004770 - JSR .+-10 ;(322)
|
||||
|
||||
; data
|
||||
333:000000 - JMP 0
|
||||
334:000000 - JMP 0
|
||||
335:044002 - STA 1,2
|
||||
336:000007 - JMP 7
|
||||
337:000037 - JMP 37
|
||||
340:000002 - JMP 2
|
||||
341:000000 - JMP 0
|
||||
342:000000 - JMP 0
|
||||
343:000061 - JMP 61
|
||||
344:000001 - JMP 1
|
||||
|
||||
345:102000 - ADC 0,0 ; set up first BLT of all memory to reset Parity
|
||||
346:024110 - LDA 1,110
|
||||
347:134000 - COM 1,3
|
||||
350:061005 - BLT ; do BLT
|
||||
351:056111 - STA@ 3,111 ; write R3 to 420, reset display list (disable display)
|
||||
352:000003 - JMP 3 ; continue @3
|
||||
|
||||
353:000000 - JMP 0
|
||||
354:000000 - JMP 0
|
||||
355:000000 - JMP 0
|
||||
356:000000 - JMP 0
|
||||
|
||||
; data
|
||||
357:040463 - STA 0,.+63 ;(442)
|
||||
360:044463 - STA 1,.+63 ;(443)
|
||||
361:054476 - STA 3,.+76 ;(457)
|
||||
362:004401 - JSR .+1 ;(363)
|
||||
363:024471 - LDA 1,.+71 ;(454)
|
||||
364:167000 - ADD 3,1
|
||||
365:034470 - LDA 3,.+70 ;(455)
|
||||
366:020470 - LDA 0,.+70 ;(456)
|
||||
367:061005 - BLT
|
||||
370:034466 - LDA 3,.+66 ;(456)
|
||||
371:021605 - LDA 0,AC3+-173
|
||||
372:040452 - STA 0,.+52 ;(444)
|
||||
373:021665 - LDA 0,AC3+-113
|
||||
374:040445 - STA 0,.+45 ;(441)
|
||||
375:021640 - LDA 0,AC3+-140
|
||||
376:101100 - MOVL 0,0
|
||||
377:040446 - STA 0,.+46 ;(445)
|
||||
400:102460 - SUBC 0,0
|
||||
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
using Contralto.Memory;
|
||||
using System.IO;
|
||||
using Contralto.Logging;
|
||||
|
||||
namespace Contralto.IO
|
||||
{
|
||||
@@ -24,10 +25,7 @@ namespace Contralto.IO
|
||||
|
||||
_pack.Load(fs);
|
||||
|
||||
fs.Close();
|
||||
|
||||
// Wakeup the sector task first thing
|
||||
_system.CPU.WakeupTask(CPU.TaskType.DiskSector);
|
||||
fs.Close();
|
||||
}
|
||||
|
||||
public ushort KDATA
|
||||
@@ -36,7 +34,10 @@ namespace Contralto.IO
|
||||
{
|
||||
return _kData;
|
||||
}
|
||||
set { _kData = value; }
|
||||
set
|
||||
{
|
||||
_kData = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ushort KADR
|
||||
@@ -53,6 +54,25 @@ namespace Contralto.IO
|
||||
// "0 normally, 1 if the command is to terminate immediately after the correct cylinder
|
||||
// position is reached (before any data is transferred)."
|
||||
_dataXfer = (_kAdr & 0x2) != 0x2;
|
||||
|
||||
Log.Write(LogComponent.DiskController, "KADR set to {0} (Seal {1}, Header {2}, Label {3}, Data {4}, Xfer {5}, Drive {6})",
|
||||
OctalHelpers.ToOctal(_kAdr),
|
||||
OctalHelpers.ToOctal((_kAdr & 0xff00) >> 8),
|
||||
OctalHelpers.ToOctal((_kAdr & 0xc0) >> 6),
|
||||
OctalHelpers.ToOctal((_kAdr & 0x30) >> 4),
|
||||
OctalHelpers.ToOctal((_kAdr & 0xc) >> 2),
|
||||
_dataXfer,
|
||||
_kAdr & 0x1);
|
||||
|
||||
Log.Write(LogComponent.DiskController, " Disk Address is C/H/S {0}/{1}/{2}, Drive {3} Restore {4}",
|
||||
(_kData & 0x0ff8) >> 3,
|
||||
(_kData & 0x4) >> 2,
|
||||
(_kData & 0xf000) >> 12,
|
||||
((_kData & 0x2) >> 1),
|
||||
(_kData & 0x1));
|
||||
|
||||
Log.Write(LogComponent.DiskController, " Selected disk is {0}", ((_kData & 0x2) >> 1) ^ (_kAdr & 0x1));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,15 +168,27 @@ namespace Contralto.IO
|
||||
get { return _sectorClocks - _elapsedSectorTime; }
|
||||
}
|
||||
|
||||
|
||||
public bool Ready
|
||||
{
|
||||
get
|
||||
{
|
||||
// Not ready if we're in the middle of a seek.
|
||||
return (_kStat & 0x0040) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ClearStatus();
|
||||
_recNo = 0;
|
||||
_elapsedSectorTime = 0.0;
|
||||
_cylinder = 0;
|
||||
_cylinder = _destCylinder = 0;
|
||||
_sector = 0;
|
||||
_head = 0;
|
||||
_kStat = 0;
|
||||
_kData = 0;
|
||||
_sendAdr = false;
|
||||
|
||||
_wdInhib = true;
|
||||
_xferOff = true;
|
||||
@@ -164,8 +196,13 @@ namespace Contralto.IO
|
||||
_wdInit = false;
|
||||
|
||||
_diskBitCounterEnable = false;
|
||||
_sectorWordIndex = 0;
|
||||
_sectorWordTime = 0;
|
||||
|
||||
InitSector();
|
||||
|
||||
// Wakeup the sector task first thing
|
||||
_system.CPU.WakeupTask(CPU.TaskType.DiskSector);
|
||||
}
|
||||
|
||||
public void Clock()
|
||||
@@ -219,11 +256,15 @@ namespace Contralto.IO
|
||||
_cylinder--;
|
||||
}
|
||||
|
||||
Log.Write(LogComponent.DiskController, "Seek progress: cylinder {0} reached.", _cylinder);
|
||||
|
||||
// Are we *there* yet?
|
||||
if (_cylinder == _destCylinder)
|
||||
{
|
||||
// clear Seek bit
|
||||
_kStat &= 0xffbf;
|
||||
|
||||
Log.Write(LogComponent.DiskController, "Seek to {0} completed.", _cylinder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,6 +323,8 @@ namespace Contralto.IO
|
||||
{
|
||||
throw new InvalidOperationException("STROBE while SENDADR bit of KCOM not 1. Unexpected.");
|
||||
}
|
||||
|
||||
Log.Write(LogComponent.DiskController, "STROBE: Seek initialized.");
|
||||
|
||||
_destCylinder = (_kData & 0x0ff8) >> 3;
|
||||
|
||||
@@ -290,6 +333,8 @@ namespace Contralto.IO
|
||||
if (_destCylinder > 202)
|
||||
{
|
||||
_kStat |= 0x0080;
|
||||
|
||||
Log.Write(LogComponent.DiskController, "Seek failed, specified cylinder {0} is out of range.", _destCylinder);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -304,6 +349,8 @@ namespace Contralto.IO
|
||||
// And figure out how long this will take.
|
||||
_seekClocks = CalculateSeekTime();
|
||||
_elapsedSeekTime = 0.0;
|
||||
|
||||
Log.Write(LogComponent.DiskController, "Seek to {0} from {1} commencing. Will take {2} clocks.", _destCylinder, _cylinder, _seekClocks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +427,8 @@ namespace Contralto.IO
|
||||
if (_wffo || _diskBitCounterEnable)
|
||||
{
|
||||
if (!_xferOff)
|
||||
{
|
||||
{
|
||||
Log.Write(LogComponent.DiskWordTask, "Word {0} read into KDATA", OctalHelpers.ToOctal(diskWord));
|
||||
_kData = diskWord;
|
||||
}
|
||||
|
||||
@@ -403,6 +451,7 @@ namespace Contralto.IO
|
||||
|
||||
if (bWakeup)
|
||||
{
|
||||
Log.Write(LogComponent.DiskWordTask, "Sector task awoken.");
|
||||
_system.CPU.WakeupTask(CPU.TaskType.DiskWord);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Contralto.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -9,6 +10,11 @@ namespace Contralto.Memory
|
||||
public class Memory : IMemoryMappedDevice
|
||||
{
|
||||
public Memory()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_mem = new ushort[0x10000];
|
||||
}
|
||||
@@ -19,7 +25,8 @@ namespace Contralto.Memory
|
||||
}
|
||||
|
||||
public void Load(int address, ushort data)
|
||||
{
|
||||
{
|
||||
//Log.Write(LogComponent.DiskWordTask, "Word {0} written to {1}", OctalHelpers.ToOctal(data), OctalHelpers.ToOctal(address));
|
||||
_mem[address] = data;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user