1
0
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:
paul
2012-06-17 16:50:12 +00:00
parent beaf621394
commit f4bbcecb17
4 changed files with 199 additions and 79 deletions

View File

@@ -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

View File

@@ -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
}
/**************************************/

View File

@@ -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);
}

View File

@@ -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