mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-02-14 04:04:29 +00:00
Commit DCMCP transcription and emulator WIP as of 2012-06-17.
This commit is contained in:
@@ -3804,3 +3804,110 @@ BEGIN 04668400
|
||||
END ELSE 04673350
|
||||
GO XIO; 04673400
|
||||
END; 04673450
|
||||
RESULT.[27:1] ~ 1; MODE ~ 32; 04673500
|
||||
XIO: END DOIONOW; 04673550
|
||||
% 04673600
|
||||
U ~ SAVEU ~ OIOD.[3:4]; 04673650
|
||||
% SAVE OFF ORIGINAL UNIT FOR DS-ING. 04673700
|
||||
OLDU ~ UNIT[U]; 04673750
|
||||
% SAVE OFF ORIGINAL UNIT TABLE ENTRY 04673800
|
||||
MIX ~ RDCTABLE[U].[8:6]; 04673850
|
||||
MODE ~ 16; 04673900
|
||||
% SET MODE TO FLAG PARITY, MODE WILL BE SET TO ZERO IF CHANGE OK 04673950
|
||||
LABELA ~ M[(TOPIOD~PRNTABLE[U].[15:15])-2] & @05000[CTF]; 04674000
|
||||
FIB ~ M[TOPIOD-3]; 04674050
|
||||
PBT ~ FIB[4].[8:4]=7; 04674100
|
||||
FNUM ~ FIB[4].[13.11]; 04674150
|
||||
BSIZE ~ IF PBT THEN 90 ELSE FIB[18].[3:15]; 04674200
|
||||
NUMRECS ~ IF PBT THEN 5 ELSE BSIZE DIV FIB[18].[33:15]; 04674225
|
||||
REEL ~ FIB[13].[28:10]+1; 04674250
|
||||
ALFA ~ (NOT FIB[13]).[24:1]; 04674300
|
||||
LABELED ~ (NOT FIB[4]).[2:1]; 04674350
|
||||
NUMBUFFS ~ FIB[13].[10:9]; 04674400
|
||||
TANK ~ [M[TOPIOD]] & NUMBUFFS[8:38:10]; 04674450
|
||||
HALT; 04674500
|
||||
% STOP NORMAL STATE PROCESSING. 04674550
|
||||
IF RC THEN 04674600
|
||||
IF TANK[0].[24:1] THEN 04674650
|
||||
BEGIN 04674700
|
||||
STREAM(T~T2~SPACE(5)); 04674750
|
||||
DS ~ 40 LIT"#REEL SWITCH NOT POSSIBLE ON INPUT FILE~"; 04674800
|
||||
SPOUTER(T2,UNITNO,1); 04674850
|
||||
GO EXIT; 04674900
|
||||
END; 04674950
|
||||
STREAM(A~TINU[U], T~T2~SPACE(5)); 04675000
|
||||
BEGIN 04675050
|
||||
DS ~ 34 LIT"#REEL SWITCH TO BE ATTEMPTED FROM "; 04675100
|
||||
SI ~ LOC A; SI ~ SI+5; DS ~ 3 CHR; DS ~ LIT"~"; 04675150
|
||||
END; 04675200
|
||||
SPOUTER(T2,UNITNO,1); 04675250
|
||||
IF PBT THEN 04675300
|
||||
BEGIN 04675350
|
||||
LABELA.[8:10] ~ 8; % PRINTER LABELS ARE 15 WORDS 04675400
|
||||
LABELA[1] ~ MULTITABLE[U].[3:45]; 04675450
|
||||
LABELA[2] ~ LABELTABLE[U].[3:45]; 04675500
|
||||
END; 04675550
|
||||
IF RC THEN GO L1; 04675600
|
||||
FIRSTREC ~ GETSPACE(BSIZE+4,0,1)+4; 04675650
|
||||
SECREC ~ GETSPACE(BSIZE+4,0,1)+4; 04675700
|
||||
% GETSPACE ON TWO BUFFERS FOR BACKWARD READ. 04675750
|
||||
IF ALFA THEN 04675800
|
||||
BEGIN 04675850
|
||||
IOD ~ @340000000 & OIOD[3:3:5] & [T2][CTC]; 04675900
|
||||
DOIONOW; DOIONOW; 04675950
|
||||
IOD ~ OIOD & 1[24:47:1] & FIRSTREC[CTC]; 04676000
|
||||
DOIONOW; 04676050
|
||||
IF RESULT.[27:2]!0 THEN GO ERROROUT; 04676100
|
||||
IOD ~ IOD & SECREC[CTC]; 04676150
|
||||
DOIONOW; 04676200
|
||||
IF RESULT.[27:2]!0 THEN GO ERROROUT; 04676250
|
||||
IOD ~ @340000000 & OIOD[3:3:5] & [T2][CTC]; 04676300
|
||||
DOIONOW; DOIONOW; 04676350
|
||||
GO L1; 04676400
|
||||
END; 04676450
|
||||
IOD ~ OIOD & (SECREC+BSIZE-1)[CTC] & 5[22:45:3]; 04676500
|
||||
DOIONOW; 04676550
|
||||
% BUILD BACKWARD DESCRIPTOR AND EXECUTE FIRST BACKWARD READ. 04676600
|
||||
IF RESULT.[27:2]!0 THEN GO ERROROUT; 04676650
|
||||
IF (TEMP ~ M[IOD INX 1])!BSIZE THEN 04676700
|
||||
% VARIABLE LENGTH BLOCK. 04676750
|
||||
SECRECIO ~ ((IOD INX 1)-TEMP) & TEMP[8:38:10]; 04676800
|
||||
IOD ~ IOD & (FIRSTREC+BSIZE-1)[CTC]; 04676850
|
||||
DOIONOW; 04676900
|
||||
% NEXT BACKWARD READ. 04676950
|
||||
IF RESULT.[27:2]!0 THEN GO ERROROUT; 04677000
|
||||
IF (TEMP ~ M[IOD INX 1])!BSIZE THEN 04677050
|
||||
% VARIABLE LENGTH BLOCK. 04677100
|
||||
FIRSTRECIO ~ ((IOD INX 1)-TEMP) & TEMP[8:38:10]; 04677150
|
||||
L1: 04677200
|
||||
FOR I ~ 0 STEP 1 UNTIL NUMBUFFS-1 DO 04677250
|
||||
IF (NOT TANK[I]).[19:1] THEN HOLDCT ~ HOLDCT+1; 04677300
|
||||
% SCAN FOR THE NUMBER OF FILLED BUFFERS. 04677350
|
||||
FIB[6] ~ FIB[6]-((RC=0)|2)-HOLDCT; 04677400
|
||||
LOGICLRC ~ FIB[7] MOD NUMRECS; 04677450
|
||||
% DETERMINE THE NUMBER OF LOGICAL RECORDS WRITTEN. 04677500
|
||||
FIB[7] ~ FIB[6] | NUMRECS; 04677550
|
||||
% LOAD FIB WITH RECORD COUNT FOR TRAILER LABEL. 04677600
|
||||
IF HOLDCT=NUMBUFFS THEN 04677650
|
||||
BEGIN 04677700
|
||||
NOPROCESSTOG ~ NOPROCESSTOG-1; 04677750
|
||||
NORMALPROCESS ~ 1; 04677800
|
||||
END; 04677850
|
||||
% IF THERE ARE NO UNFILLED BUFFERS THEN ALLOW NORMAL STATE 04677900
|
||||
% PROCESSING TO CONTINUE. 04677950
|
||||
% FLAG THE RELEASE OF NORMAL STATE. 04678000
|
||||
% THE CHANCE OF UNFILLED BUFFERS IS VERY REMOTE, BUT JUST IN CASE 04678050
|
||||
P1MIX ~ MIX; 04678100
|
||||
% LOAD P1MIX FOR CONSOLE MESSAGES. 04678150
|
||||
TEMP ~ U; 04678200
|
||||
% SAVE OFF CURRENT UNIT IN CASE DS CALLED AT THIS POINT. 04678250
|
||||
RETRY: 04678300
|
||||
IF TERMSET(MIX) THEN 04678350
|
||||
BEGIN 04678400
|
||||
U ~ (-1); 04678450
|
||||
GO ERROROUT; 04678500
|
||||
END; 04678550
|
||||
TEMP ~ U; 04678600
|
||||
TM ~ @ 1737000000000000; 04678650
|
||||
% TAPE MARK. 04678700
|
||||
IOD ~ NFLAG([TM]) & OIOD[3:3:5]; 04678750
|
||||
|
||||
@@ -40,10 +40,10 @@ function B5500CentralControl() {
|
||||
this.timer = null; // Reference to the RTC setTimeout id.
|
||||
this.loadTimer = null; // Reference to the load setTimeout id.
|
||||
|
||||
this.clear(); // Create and initialize the Central Control state
|
||||
|
||||
this.tock.that = this; // Establish contexts for when called from setTimeout().
|
||||
this.loadComplete.that = this;
|
||||
|
||||
this.clear(); // Create and initialize the Central Control state
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
|
||||
@@ -19,8 +19,8 @@ function B5500DDLamp(x, y) {
|
||||
|
||||
this.state = 0; // current lamp state, 0=off
|
||||
|
||||
this.element = // visible DOM element
|
||||
document.createElement("div");
|
||||
// visible DOM element
|
||||
this.element = document.createElement("div");
|
||||
this.element.className = "ddLamp";
|
||||
this.element.style.left = String(x) + "px";
|
||||
this.element.style.top = String(y) + "px";
|
||||
@@ -47,21 +47,47 @@ B5500DDLamp.prototype.set = function(v) {
|
||||
/***********************************************************************
|
||||
* Panel Register *
|
||||
***********************************************************************/
|
||||
B5500DDRegister(bits, x, y, rows, deltax, deltay) {
|
||||
/* Constructor for the register objects used within D&D.
|
||||
B5500DDRegister(bits, x, y, rows, caption) {
|
||||
/* Constructor for the register objects used within D&D:
|
||||
bits: number of bits in register
|
||||
x: horizontal coordinate of upper-left corner [hSpacing increments]
|
||||
y: vertical coordinate of upper-left corner [vSpacing increments]
|
||||
rows: number of rows used to display the bit lamps
|
||||
*/
|
||||
var cols = Math.floor((bits+rows-1)/rows);
|
||||
var height = rows*this.vSpacing;
|
||||
var width = cols*this.hSpacing;
|
||||
var b;
|
||||
var cx = Math.floor((x-0.25)*this.hSpacing);
|
||||
var cy = Math.floor((y-0.25)*this.vSpacing);
|
||||
var lamp;
|
||||
|
||||
this.bits = bits; // number of bits in the register
|
||||
this.left = x; // horizontal offset relative to container
|
||||
this.top = y; // vertical offset relative to container
|
||||
this.element = // visible DOM element
|
||||
document.createElement("div");
|
||||
this.left = cx; // horizontal offset relative to container
|
||||
this.top = cy; // vertical offset relative to container
|
||||
this.caption = caption; // panel caption
|
||||
this.lamps = new Array(bits+1); // bit lamps
|
||||
|
||||
// visible DOM element
|
||||
this.element = document.createElement("div");
|
||||
this.element.className = "ddRegister";
|
||||
this.element.style.left = String(x) + "px";
|
||||
this.element.style.top = String(y) + "px";
|
||||
this.element.style.left = String(cx) + "px";
|
||||
this.element.style.top = String(cy) + "px";
|
||||
this.element.style.width = width;
|
||||
this.element.style.height = height;
|
||||
|
||||
cx = (x+cols)*this.hSpacing;
|
||||
for (b=1; b<=bits; b++) {
|
||||
if ((b-1)%rows == 0) {
|
||||
cy = (y+rows-1)*this.vSpacing;
|
||||
cx -= this.xSpacing;
|
||||
} else {
|
||||
cy -= this.vSpacing;
|
||||
}
|
||||
lamp = new B5500DDLamp(cx, cy);
|
||||
this.lamps[b] = lamp;
|
||||
this.element.appendChild(lamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
@@ -79,12 +105,14 @@ function B5500DistributionAndDisplay() {
|
||||
|
||||
/* Global system modules */
|
||||
|
||||
this.nextTimeStamp = 0; // Next actual Date.getTime() expected
|
||||
this.nextRefresh = 0; // Next actual Date.getTime() expected
|
||||
this.timer = null; // Reference to the RTC setTimeout id.
|
||||
|
||||
this.clear(); // Create and initialize the Central Control state
|
||||
this.panels = {}; // D&D panel object collection
|
||||
|
||||
this.tock.that = this; // Establish contexts for when called from setTimeout().
|
||||
this.updateDisplay.that = this; // Establish contexts for when called from setTimeout().
|
||||
|
||||
this.clear(); // Create and initialize the Central Control state
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
@@ -102,52 +130,38 @@ B5500DistributionAndDisplay.prototype.clear = function() {
|
||||
|
||||
this.nextTimeStamp = new Date().getTime() + this.rtcTick;
|
||||
this.timer = setTimeout(this.tock, this.rtcTick);
|
||||
|
||||
this.IAR = 0; // Interrupt address register
|
||||
this.TM = 0; // Real-time clock (6 bits, 60 ticks per second)
|
||||
|
||||
this.CCI03F = 0; // Time interval interrupt
|
||||
this.CCI04F = 0; // I/O busy interrupt
|
||||
this.CCI05F = 0; // Keyboard request interrupt
|
||||
this.CCI06F = 0; // Printer 1 finished interrupt
|
||||
this.CCI07F = 0; // Printer 2 finished interrupt
|
||||
this.CCI08F = 0; // I/O unit 1 finished interrupt (RD in @14)
|
||||
this.CCI09F = 0; // I/O unit 2 finished interrupt (RD in @15)
|
||||
this.CCI10F = 0; // I/O unit 3 finished interrupt (RD in @16)
|
||||
this.CCI11F = 0; // I/O unit 4 finished interrupt (RD in @17)
|
||||
this.CCI12F = 0; // P2 busy interrupt
|
||||
this.CCI13F = 0; // Remote inquiry request interrupt
|
||||
this.CCI14F = 0; // Special interrupt #1 (not used)
|
||||
this.CCI15F = 0; // Disk file #1 read check finished
|
||||
this.CCI16F = 0; // Disk file #2 read check finished
|
||||
|
||||
this.MCYF = 0; // Memory cycle FFs (one bit per M0..M7)
|
||||
this.PAXF = 0; // PA memory exchange select (M0..M7)
|
||||
this.PBXF = 0; // PB memory exchange select (M0..M7)
|
||||
this.I1XF = 0; // I/O unit 1 exchange select (M0..M7)
|
||||
this.I2XF = 0; // I/O unit 2 exchange select (M0..M7)
|
||||
this.I3XF = 0; // I/O unit 3 exchange select (M0..M7)
|
||||
this.I4XF = 0; // I/O unit 4 exchange select (M0..M7)
|
||||
|
||||
this.AD1F = 0; // I/O unit 1 busy
|
||||
this.AD2F = 0; // I/O unit 2 busy
|
||||
this.AD3F = 0; // I/O unit 3 busy
|
||||
this.AD4F = 0; // I/O unit 4 busy
|
||||
|
||||
this.LOFF = 0; // Load button pressed on console
|
||||
this.CTMF = 0; // Commence timing FF
|
||||
this.P2BF = 0; // Processor 2 busy FF
|
||||
this.HP2F = 1; // Halt processor 2 FF
|
||||
|
||||
if (this.PA) {
|
||||
this.PA.clear();
|
||||
}
|
||||
if (this.PB) {
|
||||
this.PB.clear();
|
||||
}
|
||||
this.P1 = (this.PB1L ? this.PB : this.PA);
|
||||
this.P2 = (this.PB1L ? this.PA : this.PB);
|
||||
if (!this.P2) {
|
||||
this.P2BF = 1; // mark non-existent P2 as busy
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500DistributionAndDisplay.prototype.openProcessorPanel(p, caption) {
|
||||
/* Creates a D&D panel window for a processor */
|
||||
var x;
|
||||
var panel = this.panels[caption];
|
||||
|
||||
if (panel) {
|
||||
win = panel.window;
|
||||
} else {
|
||||
win = window.open("B5500ProcessorPanel.html", "P"+caption,
|
||||
"resizable=yes,scrollbars=yes");
|
||||
panel = {module:p, window:win, caption:caption};
|
||||
this.panels[caption] = panel;
|
||||
}
|
||||
|
||||
win.appendChild(new B5500DDRegister(39, 1, 1, 3, "X REG"));
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500DistributionAndDisplay.prototype.updateDisplay = function updateDisplay() {
|
||||
/* Schedules itself to update the display on a periodic basis. */
|
||||
var delayTime;
|
||||
var that = updateDisplay.that;
|
||||
var thisTime = new Date().getTime();
|
||||
|
||||
// Schedule ourself for the next refresh period
|
||||
that.nextRefresh += that.refreshPeriod;
|
||||
delayTime = that.nextRefresh - thisTime;
|
||||
that.timer = setTimeout(that.updateDisplay, (delayTime < 0 ? 0 : delayTime);
|
||||
|
||||
|
||||
}
|
||||
@@ -22,9 +22,9 @@ function B5500Processor() {
|
||||
MPED: 0, // Truthy if memory parity error
|
||||
MAED: 0}; // Truthy if memory address/inhibit error
|
||||
|
||||
this.clear(); // Create and initialize the processor state
|
||||
|
||||
this.schedule.that = this; // Establish context for when called from setTimeout()
|
||||
|
||||
this.clear(); // Create and initialize the processor state
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
@@ -61,7 +61,7 @@ B5500Processor.prototype.clear = function() {
|
||||
this.P = 0; // Current program instruction word register
|
||||
this.PROF = 0; // P contents valid
|
||||
this.Q = 0; // Misc. FFs (bits 1-9 only: Q07F=hardware-induced interrupt, Q09F=enable parallel adder for R-relative addressing)
|
||||
this.R = 0; // PRT base address (low-order 6 bits are always zero in word mode)
|
||||
this.R = 0; // High-order 9 bits of PRT base address (TALLY in char mode)
|
||||
this.S = 0; // Top-of-stack memory address (DI.w in CM)
|
||||
this.SALF = 0; // Program/subroutine state FF (1=subroutine)
|
||||
this.T = 0; // Current program syllable register
|
||||
@@ -174,12 +174,12 @@ B5500Processor.prototype.adjustAEmpty = function() {
|
||||
|
||||
if (this.AROF} {
|
||||
if (this.BROF) {
|
||||
if (this.S < this.R || !this.NCSF) {
|
||||
this.S++;
|
||||
this.access(0x0B); // [S] = B
|
||||
} else {
|
||||
if ((this.S >>> 6) == this.R || !this.NCSF) {
|
||||
this.I |= 0x04; // set I03F: stack overflow
|
||||
cc.signalInterrupt();
|
||||
} else {
|
||||
this.S++;
|
||||
this.access(0x0B); // [S] = B
|
||||
}
|
||||
}
|
||||
this.B = this.A;
|
||||
@@ -213,12 +213,12 @@ B5500Processor.prototype.adjustBEmpty = function() {
|
||||
contents of B into memory, as necessary. */
|
||||
|
||||
if (this.BROF) {
|
||||
if (this.S < this.R || !this.NCSF) {
|
||||
this.S++;
|
||||
this.access(0x0B); // [S] = B
|
||||
} else {
|
||||
if ((this.S >>> 6) = this.R || !this.NCSF) {
|
||||
this.I |= 0x04; // set I03F: stack overflow
|
||||
cc.signalInterrupt();
|
||||
} else {
|
||||
this.S++;
|
||||
this.access(0x0B); // [S] = B
|
||||
}
|
||||
// else we're done -- B is already empty
|
||||
}
|
||||
@@ -278,7 +278,7 @@ B5500Processor.storeForInterrupt = function(forTest) {
|
||||
this.VARF * 0x1000000 +
|
||||
this.SALF * 0x40000000 +
|
||||
this.MSFF * 0x80000000 +
|
||||
(this.CWMF ? this.R : this.R >>> 6) * 0x200000000 +
|
||||
this.R * 0x200000000 +
|
||||
0xC00000000000;
|
||||
this.access(0x0B); // [S] = B
|
||||
|
||||
@@ -300,7 +300,7 @@ B5500Processor.storeForInterrupt = function(forTest) {
|
||||
this.access(0x03); // B = [S]: get last RCW
|
||||
this.S = ((this.B % 0x40000000) >>> 15) & 0x7FFF;
|
||||
this.access(0x03); // B = [S]: get last MSCW
|
||||
this.R = (Math.Floor(this.B / 0x200000000) % 0x200) << 6;
|
||||
this.R = Math.Floor(this.B / 0x200000000) % 0x200;
|
||||
this.S = this.F;
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ B5500Processor.storeForInterrupt = function(forTest) {
|
||||
this.MWOF = 0;
|
||||
}
|
||||
|
||||
this.M = this.R + 0x08; // store initiate word at R+@10
|
||||
this.M = (this.R << 6) + 0x08; // store initiate word at R+@10
|
||||
this.access(0x0D); // [M] = B
|
||||
|
||||
this.M = 0;
|
||||
@@ -413,8 +413,7 @@ B5500Processor.initiate = function(forTest) {
|
||||
this.VARF = Math.floor(this.B / 0x1000000) % 0x02;
|
||||
this.SALF = Math.floor(this.B / 0x40000000) % 0x02;
|
||||
this.MSFF = Math.floor(this.B / 0x80000000) % 0x02;
|
||||
temp = (Math.floor(this.B / 0x200000000) % 0x200);
|
||||
this.R = (this.CWMF ? temp & 0x3F : temp << 6);
|
||||
this.R = (Math.floor(this.B / 0x200000000) % 0x200);
|
||||
|
||||
if (this.CWMF || forTest) {
|
||||
this.M = this.B % 0x8000;
|
||||
@@ -759,7 +758,7 @@ B5500Processor.prototype.run = function() {
|
||||
case 0x10: // 1011: COM=Communicate
|
||||
if (this.NCSF) { // no-op in control state
|
||||
this.adjustAFull();
|
||||
this.M = this.R + 0x09; // address = R+@11
|
||||
this.M = (this.R << 6) + 0x09; // address = R+@11
|
||||
this.access(0x0C); // [M] = A
|
||||
this.AROF = 0;
|
||||
this.I = (this.I & 0x0F) | 0x40; // set I07
|
||||
|
||||
Reference in New Issue
Block a user