mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-04-28 04:55:59 +00:00
1. Commit DCMCP transcription as of 2013-03-02.
2. Debugging mods to complete single-stepping through KERNEL bootstrap. 3. Implement FBS and LLL in Processor. 4. Delete old this.access() logic in Processor.
This commit is contained in:
@@ -21943,3 +21943,75 @@ END; % OF LIBRARYZERO 28892000
|
||||
GO INITIATE; 31023000
|
||||
END; END; 31024000
|
||||
END ERRORFIXER; 31025000
|
||||
PROCEDURE JOBMESS(MIX,Q,A,B,C,D); VALUE MIX,Q,A,B,C,D;% 32000000
|
||||
REAL MIX,Q,A,B,C,D;% 32000100
|
||||
COMMENT : THIS PROCEDURE CAN BE USED TO BUILD AND SPOUT A MESSAGE 32000110
|
||||
THAT IS TO BE PRECEEDED BY A <JOB SPECIFIER> WHICH IT 32000120
|
||||
BUILDS AUTOMATICALLY FOR THE MIX GIVEN; 32000130
|
||||
BEGIN REAL BUF,T;% 32000200
|
||||
$ SET OMIT = NOT(PACKETS) 32000249
|
||||
REAL UNITNO; 32000250
|
||||
$ POP OMIT 32000251
|
||||
LABEL EXIT; 32000280
|
||||
BUF ~ SPACE(9); 32000300
|
||||
IF MIX = 0 THEN 32000400
|
||||
BEGIN T:=SPACE(30);DISKWAIT(-T,30,0); 32000500
|
||||
STREAM(M:=M[T+10+5|SYSNO],F:=M[T+11+5|SYSNO],BUF); 32000510
|
||||
BEGIN DS:=3 LIT" D:"; SI:=LOC M; SI:=SI+1; DS:=7 CHR; 32000520
|
||||
DS:=LIT"/";SI:=SI+1;DS:=7CHR;DS:=3LIT"= 0"; 32000530
|
||||
END; 32000540
|
||||
FORGETSPACE(T); 32000600
|
||||
T:=(BUF+2)&5[30:45:3]; 32000650
|
||||
END ELSE% 32000700
|
||||
IF JARROW[MIX[!0 THEN 32000750
|
||||
BEGIN; STREAM(C!0:R~ IF (T~ PRYOR[MIX])<0 THEN T ELSE T INX 0, 32000800
|
||||
J ~ JARROW[MIX],MIX,A ~ IF JAR[MIX,0]<0 THEN JAR[MIX,30] 32000810
|
||||
ELSE 0,BUF); 32000812
|
||||
BEGIN DS ~ LIT " "; SI ~ LOC R; DS ~ 6 DEC;% 32000850
|
||||
DI ~ DI-6; DS ~ 5 FILL; DI ~ BUF; DI ~ DI+7;% 32001000
|
||||
DS ~ LIT ":"; SI ~ J; 32001100
|
||||
IF SC="+" THEN 32001120
|
||||
BEGIN SI ~ SI+1; DS ~ 7 CHR; DS ~ LIT " "; 32001140
|
||||
SI ~ SI+1; DS ~ 7 CHR; DS ~ LIT "/"; 32001160
|
||||
SI ~ LOC A; SI ~ SI+1; DS ~ 7 CHR; 32001180
|
||||
END ELSE 32001200
|
||||
BEGIN SI ~ SI+1; DS ~ 7 CHR; DS ~ LIT "/"; 32001220
|
||||
SI ~ SI+1; DS ~ 7 CHR; 32001240
|
||||
END; 32001260
|
||||
DS ~ LIT "="; SI ~ LOC MIX; DS ~ 2 DEC;% 32001300
|
||||
C ~ DI; DI ~ DI -2; DS ~ 2 FILL;% 32001400
|
||||
END STREAM; 32001450
|
||||
T := POLISH; 32001475
|
||||
$ SET OMIT = NOT(PACKETS) 32001499
|
||||
IF Q.[CF]=MIX THEN UNITNO:=PSEUDOMIX[MIX]; 32001500
|
||||
$ POP OMIT 32001501
|
||||
END ELSE % NO SUCH MIX 32001550
|
||||
BEGIN FORGETSPACE(BUF); 32001575
|
||||
GO TO EXIT; 32001600
|
||||
END; 32001625
|
||||
STREAM(A~[A],Z~0,T);% 32001700
|
||||
BEGIN SI ~ A; DS ~ LIT " ";% 32001800
|
||||
4(IF SC ! "+" THEN 32001900
|
||||
BEGIN TALLY ~ 7; SI ~ SI +1; % 32001910
|
||||
6(L: IF SC = "0" THEN% 32001920
|
||||
BEGIN TALLY ~ TALLY + 63; SI ~ SI + 1; 32002000
|
||||
END ELSE JUMP OUT);% 32002050
|
||||
Z ~ TALLY; DS ~ Z CHR;% 32002070
|
||||
END ELSE SI ~ SI + 8);% 32002090
|
||||
DS ~ LIT "~";% 32002100
|
||||
END STREAM;% 32002200
|
||||
SPOUTER(BUF & Q[9:9:9],UNITNO,1); 32002300
|
||||
EXIT: 32002350
|
||||
END JOBMESS;% 32002400
|
||||
PROCEDURE MIXPRINT(Q); VALUE Q; REAL Q; 32100000
|
||||
COMMENT THIS PROCEDURE INVOKES JOBMESS TO TYPE THE JOB SPECIFIERS 32100010
|
||||
OF EACH ACTIVE MIX;% 32100020
|
||||
BEGIN REAL T,I; 32100100
|
||||
FOR I~1 STEP 1 UNTIL MIXMAX DO 32100200
|
||||
IF JAR[I,*] ! 0 THEN% 32100300
|
||||
BEGIN JOBMESS(I,Q,-0,-0,-0,-0); T ~ 1 END;% 32100350
|
||||
IF NOT T THEN% NULL MIX 32100400
|
||||
BEGIN; STREAM(T~T~SPACE(2)); DS~11LIT " NULL MIX~";% 32100500
|
||||
SPOUT(T & Q[9:9:9]);% 32100600
|
||||
END NULL MIX; 32100700
|
||||
END MIXPRINT;% 32100800
|
||||
|
||||
@@ -54,10 +54,10 @@ function B5500IOUnit(ioUnitID, cc) {
|
||||
MPED: 0, // Truthy if memory parity error
|
||||
MAED: 0 // Truthy if memory address/inhibit error
|
||||
};
|
||||
|
||||
|
||||
// Establish a buffer for the peripheral modules to use during their I/O.
|
||||
// The size is sufficient for 63 disk sectors, rounded up to the next 8KB.
|
||||
this.bufferArea = new ArrayBuffer(16384);
|
||||
this.bufferArea = new ArrayBuffer(16384);
|
||||
this.buffer = new Uint8Array(this.bufferArea);
|
||||
|
||||
this.clear(); // Create and initialize the processor state
|
||||
@@ -65,7 +65,7 @@ function B5500IOUnit(ioUnitID, cc) {
|
||||
|
||||
/**************************************/
|
||||
|
||||
B5500IOUnit.timeSlice = 5000; // Standard run() timeslice, about 5ms (we hope)
|
||||
B5500IOUnit.timeSlice = 5000; // Standard run() timeslice, about 5ms (we hope)
|
||||
B5500IOUnit.memCycles = 6; // assume 6 us memory cycle time (the other option was 4 usec)
|
||||
|
||||
B5500IOUnit.BICtoANSI = [ // Index by 6-bit BIC to get 8-bit ANSI code
|
||||
@@ -87,7 +87,7 @@ B5500IOUnit.BICtoBCLANSI = [ // Index by 6-bit BIC to get 8-bit BCL-a
|
||||
0x51,0x52,0x2A,0x2D,0x7C,0x29,0x3B,0x7B, // 28-2F, @50-57
|
||||
0x2B,0x41,0x42,0x43,0x44,0x45,0x46,0x47, // 30-37, @60-67
|
||||
0x48,0x49,0x5B,0x26,0x2E,0x28,0x3C,0x7E]; // 38-3F, @70-77
|
||||
|
||||
|
||||
B5500IOUnit.ANSItoBIC = [ // Index by 8-bit ANSI to get 6-bit BIC (upcased, invalid=>"?")
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 00-0F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 10-1F
|
||||
@@ -105,7 +105,7 @@ B5500IOUnit.ANSItoBIC = [ // Index by 8-bit ANSI to get 6-bit BIC
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // D0-DF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // E0-EF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C]; // F0-FF
|
||||
|
||||
|
||||
B5500IOUnit.BCLANSItoBIC = [ // Index by 8-bit BCL-as-ANSI to get 6-bit BIC (upcased, invalid=>"?")
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 00-0F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 10-1F
|
||||
@@ -131,16 +131,16 @@ B5500IOUnit.prototype.clear = function() {
|
||||
this.W = 0; // Memory buffer register
|
||||
this.D = 0; // I/O descriptor (control) register
|
||||
this.clearD(); // clear the D-register exploded fields
|
||||
|
||||
|
||||
this.CC = 0; // Character counter (3 bits)
|
||||
this.IB = 0; // Input buffer register (6 bits+parity)
|
||||
this.IB = 0; // Input buffer register (6 bits+parity)
|
||||
this.IR = 0; // Tape read register (6 bits+parity)
|
||||
this.OB = 0; // Output buffer register (6 bits+parity)
|
||||
this.WB = 0; // Tape write register (6 bits+parity)
|
||||
this.LP = 0; // Longitudinal parity register (6 bits+parity)
|
||||
this.SC = 0; // Sequence counter (4 bits)
|
||||
this.SC = 0; // Sequence counter (4 bits)
|
||||
this.PC = 0; // Pulse counter register (6 bits, 1MHz rate)
|
||||
|
||||
|
||||
this.AOFF = 0; // Address overflow FF
|
||||
this.EXNF = 0; // W-contents FF (0=has address, 1=has descriptor)
|
||||
this.HOLF = 0; // Hold-over FF (for alpha vs. binary card read)
|
||||
@@ -150,21 +150,21 @@ B5500IOUnit.prototype.clear = function() {
|
||||
this.MAOF = 0; // Memory access obtained FF
|
||||
this.OBCF = 0; // (unknown)
|
||||
this.STRF = 0; // Strobe FF
|
||||
|
||||
this.BKWF = 0; // Tape control FF
|
||||
this.FWDF = 0; // Tape control FF
|
||||
this.IM1F = 0; // Tape control FF
|
||||
this.IMFF = 0; // Tape control FF
|
||||
this.PUCF = 0; // Tape control FF
|
||||
this.RCNF = 0; // Tape control FF
|
||||
this.SHOF = 0; // Tape control FF
|
||||
this.SKFF = 0; // Tape control FF
|
||||
this.VRCF = 0; // Tape control FF
|
||||
|
||||
|
||||
this.BKWF = 0; // Tape control FF
|
||||
this.FWDF = 0; // Tape control FF
|
||||
this.IM1F = 0; // Tape control FF
|
||||
this.IMFF = 0; // Tape control FF
|
||||
this.PUCF = 0; // Tape control FF
|
||||
this.RCNF = 0; // Tape control FF
|
||||
this.SHOF = 0; // Tape control FF
|
||||
this.SKFF = 0; // Tape control FF
|
||||
this.VRCF = 0; // Tape control FF
|
||||
|
||||
this.IMCF = 0; // (unknown)
|
||||
this.RECF = 0; // (unknown)
|
||||
this.REMF = 1; // Remote FF (0=local, 1=remote and available)
|
||||
|
||||
|
||||
this.busy = 0; // I/O Unit is busy
|
||||
this.busyUnit = 0; // Peripheral unit index currently assigned to the I/O Unit
|
||||
|
||||
@@ -173,7 +173,7 @@ B5500IOUnit.prototype.clear = function() {
|
||||
this.totalCycles = 0; // Total cycles executed on this I/O Unit
|
||||
this.ioUnitTime = 0; // Total I/O Unit running time, based on cycles executed
|
||||
this.ioUnitSlack = 0; // Total I/O Unit throttling delay, milliseconds
|
||||
|
||||
|
||||
if (this.forkHandle) {
|
||||
clearTimeout(this.forkHandle);
|
||||
}
|
||||
@@ -182,7 +182,7 @@ B5500IOUnit.prototype.clear = function() {
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.clearD = function() {
|
||||
/* Clears the D-register and the exploded field variables used internally */
|
||||
|
||||
|
||||
this.D = 0;
|
||||
this.Dunit = 0; // Unit designate field (5 bits)
|
||||
this.DwordCount = 0; // Word count field (10 bits)
|
||||
@@ -211,7 +211,7 @@ B5500IOUnit.prototype.fetch = function(addr) {
|
||||
this.cc.fetch(acc);
|
||||
this.W = acc.word;
|
||||
|
||||
this.cycleCount += B5500IOUnit.memCycles;
|
||||
this.cycleCount += B5500IOUnit.memCycles;
|
||||
if (acc.MAED) {
|
||||
this.D26F = 1; // set memory address error
|
||||
return 1;
|
||||
@@ -233,7 +233,7 @@ B5500IOUnit.prototype.store = function(addr) {
|
||||
acc.word = this.W;
|
||||
this.cc.store(acc);
|
||||
|
||||
this.cycleCount += B5500IOUnit.memCycles;
|
||||
this.cycleCount += B5500IOUnit.memCycles;
|
||||
if (acc.MAED) {
|
||||
this.D26F = 1; // set memory address error
|
||||
return 1;
|
||||
@@ -245,9 +245,9 @@ B5500IOUnit.prototype.store = function(addr) {
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.fetchBuffer = function(mode, words) {
|
||||
/* Fetches words from memory starting at this.Daddress and coverts the
|
||||
BIC characters to ANSI or BCLANSI in this.buffer. "mode": 0=BCLANSI, 1=ANSI;
|
||||
"words": maximum number of words to transfer. At exit, updates this.Daddress
|
||||
with the final transfer address+1. If this.D23F, updates this.wordCount
|
||||
BIC characters to ANSI or BCLANSI in this.buffer. "mode": 0=BCLANSI, 1=ANSI;
|
||||
"words": maximum number of words to transfer. At exit, updates this.Daddress
|
||||
with the final transfer address+1. If this.D23F, updates this.wordCount
|
||||
with any remaining count.
|
||||
Returns the number of characters fetched into the buffer */
|
||||
var addr = this.Daddress; // local copy of memory address
|
||||
@@ -259,7 +259,7 @@ B5500IOUnit.prototype.fetchBuffer = function(mode, words) {
|
||||
var s; // character shift counter
|
||||
var table = (mode ? B5500IOUnit.BICtoANSI : B5500IOUnit.BICtoBCLANSI);
|
||||
var w; // local copy of this.W
|
||||
|
||||
|
||||
do { // loop through the words
|
||||
if (words <= 0) {
|
||||
done = true;
|
||||
@@ -270,7 +270,7 @@ B5500IOUnit.prototype.fetchBuffer = function(mode, words) {
|
||||
this.D26F = 1; // address overflow: set invalid address error
|
||||
done = true;
|
||||
} else if (!this.fetch(addr)) { // fetch the next word from memory
|
||||
w = this.W; // fill the buffer with this word's characters
|
||||
w = this.W; // fill the buffer with this word's characters
|
||||
for (s=0; s<8; s++) {
|
||||
c = (w - (w %= 0x40000000000))/0x40000000000;
|
||||
buf[count++] = table[c];
|
||||
@@ -284,7 +284,7 @@ B5500IOUnit.prototype.fetchBuffer = function(mode, words) {
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
|
||||
this.Daddress = addr;
|
||||
if (this.D23F) {
|
||||
this.DwordCount = words & 0x1FF;
|
||||
@@ -295,10 +295,10 @@ B5500IOUnit.prototype.fetchBuffer = function(mode, words) {
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.fetchBufferWithGM = function(mode, words) {
|
||||
/* Fetches words from memory starting at this.Daddress and coverts the
|
||||
BIC characters to ANSI or BCLANSI in this.buffer. "mode": 0=BCLANSI, 1=ANSI;
|
||||
"words": maximum number of words to transfer. The transfer can be terminated
|
||||
by a group-mark code in memory. At exit, updates this.Daddress with the
|
||||
final transfer address+1. If this.D23F, updates this.wordCount
|
||||
BIC characters to ANSI or BCLANSI in this.buffer. "mode": 0=BCLANSI, 1=ANSI;
|
||||
"words": maximum number of words to transfer. The transfer can be terminated
|
||||
by a group-mark code in memory. At exit, updates this.Daddress with the
|
||||
final transfer address+1. If this.D23F, updates this.wordCount
|
||||
with any remaining count.
|
||||
Returns the number of characters fetched into the buffer */
|
||||
var addr = this.Daddress; // local copy of memory address
|
||||
@@ -310,7 +310,7 @@ B5500IOUnit.prototype.fetchBufferWithGM = function(mode, words) {
|
||||
var s; // character shift counter
|
||||
var table = (mode ? B5500IOUnit.BICtoANSI : B5500IOUnit.BICtoBCLANSI);
|
||||
var w; // local copy of this.W
|
||||
|
||||
|
||||
do { // loop through the words
|
||||
if (words <= 0) {
|
||||
done = true;
|
||||
@@ -321,11 +321,11 @@ B5500IOUnit.prototype.fetchBufferWithGM = function(mode, words) {
|
||||
this.D26F = 1; // address overflow: set invalid address error
|
||||
done = true;
|
||||
} else if (!this.fetch(addr)) { // fetch the next word from memory
|
||||
w = this.W; // fill the buffer with this word's characters
|
||||
w = this.W; // fill the buffer with this word's characters
|
||||
for (s=0; s<8; s++) {
|
||||
c = (w - (w %= 0x40000000000))/0x40000000000;
|
||||
if (c == 0x1F) {
|
||||
done = true; // group-mark detected
|
||||
if (c == 0x1F) {
|
||||
done = true; // group-mark detected
|
||||
break;
|
||||
} else {
|
||||
buf[count++] = table[c];
|
||||
@@ -340,7 +340,7 @@ B5500IOUnit.prototype.fetchBufferWithGM = function(mode, words) {
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
|
||||
this.Daddress = addr;
|
||||
if (this.D23F) {
|
||||
this.DwordCount = words & 0x1FF;
|
||||
@@ -352,9 +352,9 @@ B5500IOUnit.prototype.fetchBufferWithGM = function(mode, words) {
|
||||
B5500IOUnit.prototype.storeBuffer = function(chars, offset, mode, words) {
|
||||
/* Converts characters in this.buffer from ANSI or BCLANSI to BIC, assembles
|
||||
them into words, and stores the words into memory starting at this.Daddress.
|
||||
"chars": the number of characters to store, starting at "offset" in the buffer;
|
||||
"mode": 0=BCLANSI, 1=ANSI; "words": maximum number of words to transfer.
|
||||
At exit, updates this.Daddress with the final transfer address+1.
|
||||
"chars": the number of characters to store, starting at "offset" in the buffer;
|
||||
"mode": 0=BCLANSI, 1=ANSI; "words": maximum number of words to transfer.
|
||||
At exit, updates this.Daddress with the final transfer address+1.
|
||||
If this.D23F, updates this.wordCount with any remaining count.
|
||||
Returns the number of characters stored into memory from the buffer */
|
||||
var addr = this.Daddress; // local copy of memory address
|
||||
@@ -367,7 +367,7 @@ B5500IOUnit.prototype.storeBuffer = function(chars, offset, mode, words) {
|
||||
var s = 0; // character shift counter
|
||||
var table = (mode ? B5500IOUnit.ANSItoBIC : B5500IOUnit.BCLANSItoBIC);
|
||||
var w = 0; // local copy of this.W
|
||||
|
||||
|
||||
while (!done) { // loop through the words
|
||||
if (count >= chars) {
|
||||
done = true;
|
||||
@@ -412,7 +412,7 @@ B5500IOUnit.prototype.storeBuffer = function(chars, offset, mode, words) {
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.Daddress = addr;
|
||||
if (this.D23F) {
|
||||
this.DwordCount = words & 0x1FF;
|
||||
@@ -424,11 +424,11 @@ B5500IOUnit.prototype.storeBuffer = function(chars, offset, mode, words) {
|
||||
B5500IOUnit.prototype.storeBufferWithGM = function(chars, offset, mode, words) {
|
||||
/* Converts characters in this.buffer from ANSI to BIC, assembles them into
|
||||
words, and stores the words into memory starting at this.Daddress.
|
||||
"chars": the number of characters to store, starting at "offset" in the buffer;
|
||||
"mode": 0=BCLANSI, 1=ANSI; "words": maximum number of words to transfer.
|
||||
The final character stored from the buffer is followed in memory by a group-mark,
|
||||
assuming the word count is not exhausted. At exit, updates this.Daddress with the
|
||||
final transfer address+1.
|
||||
"chars": the number of characters to store, starting at "offset" in the buffer;
|
||||
"mode": 0=BCLANSI, 1=ANSI; "words": maximum number of words to transfer.
|
||||
The final character stored from the buffer is followed in memory by a group-mark,
|
||||
assuming the word count is not exhausted. At exit, updates this.Daddress with the
|
||||
final transfer address+1.
|
||||
If this.D23F, updates this.wordCount with any remaining count.
|
||||
Returns the number of characters stored into memory from the buffer, plus one
|
||||
for the group-mark */
|
||||
@@ -442,7 +442,7 @@ B5500IOUnit.prototype.storeBufferWithGM = function(chars, offset, mode, words) {
|
||||
var s = 0; // character shift counter
|
||||
var table = (mode ? B5500IOUnit.ANSItoBIC : B5500IOUnit.BCLANSItoBIC);
|
||||
var w = 0; // local copy of this.W
|
||||
|
||||
|
||||
while (!done) { // loop through the words
|
||||
if (count >= chars) {
|
||||
done = true;
|
||||
@@ -472,7 +472,7 @@ B5500IOUnit.prototype.storeBufferWithGM = function(chars, offset, mode, words) {
|
||||
}
|
||||
}
|
||||
} // while !done
|
||||
|
||||
|
||||
w += 0x1F*power; // set group mark in register
|
||||
s++;
|
||||
count++;
|
||||
@@ -491,7 +491,7 @@ B5500IOUnit.prototype.storeBufferWithGM = function(chars, offset, mode, words) {
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.Daddress = addr;
|
||||
if (this.D23F) {
|
||||
this.DwordCount = words & 0x1FF;
|
||||
@@ -503,8 +503,8 @@ B5500IOUnit.prototype.storeBufferWithGM = function(chars, offset, mode, words) {
|
||||
B5500IOUnit.prototype.finish = function () {
|
||||
/* Called to finish an I/O operation on this I/O Unit. Constructs and stores
|
||||
the result descriptor, sets the appropriate I/O Finished interrupt in CC */
|
||||
|
||||
this.W = this.D =
|
||||
|
||||
this.W = this.D =
|
||||
this.Dunit * 0x10000000000 +
|
||||
this.DwordCount * 0x40000000 +
|
||||
this.D18F * 0x20000000 +
|
||||
@@ -520,7 +520,7 @@ B5500IOUnit.prototype.finish = function () {
|
||||
this.D31F * 0x10000 +
|
||||
this.D32F * 0x8000 +
|
||||
this.Daddress;
|
||||
|
||||
|
||||
switch(this.ioUnitID) {
|
||||
case "1":
|
||||
this.store(0x0C);
|
||||
@@ -539,9 +539,9 @@ B5500IOUnit.prototype.finish = function () {
|
||||
this.cc.CCI08F = 1; // set I/O Finished #4
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
this.busy = 0; // zero so CC won't think I/O unit is busy
|
||||
this.busyUnit = 0;
|
||||
this.busyUnit = 0;
|
||||
this.cc.signalInterrupt();
|
||||
};
|
||||
|
||||
@@ -549,7 +549,7 @@ B5500IOUnit.prototype.finish = function () {
|
||||
B5500IOUnit.prototype.makeFinish = function(f) {
|
||||
/* Utility function to create a closure for I/O finish handlers */
|
||||
var that = this;
|
||||
|
||||
|
||||
return function(mask, length) {return f.call(that, mask, length)};
|
||||
};
|
||||
|
||||
@@ -559,7 +559,7 @@ B5500IOUnit.prototype.finishGeneric = function(errorMask, length) {
|
||||
transfer is needed. Can also be used to apply common error mask posting
|
||||
at the end of specialized finish handlers. Note that this turns off the
|
||||
busyUnit mask bit in CC */
|
||||
|
||||
|
||||
if (errorMask & 0x01) {this.D32F = 1}
|
||||
if (errorMask & 0x02) {this.D31F = 1}
|
||||
if (errorMask & 0x04) {this.D30F = 1}
|
||||
@@ -574,7 +574,7 @@ B5500IOUnit.prototype.finishGeneric = function(errorMask, length) {
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.finishSPORead = function(errorMask, length) {
|
||||
/* Handles I/O finish for a SPO keyboard input operation */
|
||||
|
||||
|
||||
this.storeBufferWithGM(length, 0, 1, 0x7FFF);
|
||||
this.finishGeneric(errorMask, length);
|
||||
};
|
||||
@@ -584,7 +584,7 @@ B5500IOUnit.prototype.finishDiskRead = function(errorMask, length) {
|
||||
/* Handles I/O finish for a DFCU data read operation */
|
||||
var segWords = Math.floor((length+7)/8);
|
||||
var memWords = (this.D23F ? this.DwordCount : segWords);
|
||||
|
||||
|
||||
if (segWords < memWords) {
|
||||
memWords = segWords;
|
||||
}
|
||||
@@ -599,14 +599,14 @@ B5500IOUnit.prototype.initiateDiskIO = function(u) {
|
||||
check and interrogate operations are determined from their respective IOD bits. If
|
||||
it's a read data operation, we request the specified number of segments from the disk
|
||||
and will sort out word count issues in finishDiskRead(). If it's a write data operation,
|
||||
we truncate or pad the data from memory as appropriate and request a write of the
|
||||
we truncate or pad the data from memory as appropriate and request a write of the
|
||||
specified number of segments */
|
||||
var c; // address char
|
||||
var memWords; // number of memory words to transfer
|
||||
var p = 1; // address digit power
|
||||
var w; // current memory word value
|
||||
var x; // temp variable
|
||||
|
||||
|
||||
var segAddr = 0; // disk segment address
|
||||
var segs = this.LP; // I/O size in segments
|
||||
var segWords = segs*30; // I/O size in words
|
||||
@@ -640,7 +640,7 @@ B5500IOUnit.prototype.initiateDiskIO = function(u) {
|
||||
this.fetchBuffer(this.D21F, segWords);
|
||||
} else { // transfer size is limited by word count
|
||||
x = this.fetchBuffer(this.D21F, memWords);
|
||||
c = (this.D21F ? 0x00 : 0x2B); // pad "0" if binary, " " if alpha (as BCL)
|
||||
c = (this.D21F ? 0x30 : 0x2B); // pad "0" if binary, "#" if alpha (for BCL " ")
|
||||
while (x < segChars) { // pad remainder of buffer up to seg count
|
||||
this.buffer[x++] = c;
|
||||
}
|
||||
@@ -660,7 +660,7 @@ B5500IOUnit.prototype.forkIO = function forkIO() {
|
||||
var x; // temp number variable
|
||||
|
||||
this.forkHandle = null; // clear the setTimeout() handle
|
||||
|
||||
|
||||
x = this.D; // explode the D-register into its fields
|
||||
this.Dunit = this.cc.fieldIsolate(x, 3, 5);
|
||||
this.DwordCount = this.cc.fieldIsolate(x, 8, 10);
|
||||
@@ -685,13 +685,13 @@ B5500IOUnit.prototype.forkIO = function forkIO() {
|
||||
u = this.cc.unit[index];
|
||||
switch(this.Dunit) {
|
||||
// disk designates
|
||||
case 6:
|
||||
case 6:
|
||||
case 12:
|
||||
this.initiateDiskIO(u);
|
||||
break;
|
||||
|
||||
// printer designates
|
||||
case 22:
|
||||
case 22:
|
||||
case 26:
|
||||
this.D30F = 1; this.finish(); // >>> temp until implemented <<<
|
||||
break;
|
||||
@@ -722,19 +722,19 @@ B5500IOUnit.prototype.forkIO = function forkIO() {
|
||||
break;
|
||||
|
||||
// magnetic tape designates
|
||||
case 1: case 3: case 5: case 7: case 9: case 11: case 13: case 15:
|
||||
case 1: case 3: case 5: case 7: case 9: case 11: case 13: case 15:
|
||||
case 17: case 19: case 21: case 23: case 25: case 27: case 29: case 31:
|
||||
this.D30F = 1; this.finish(); // >>> temp until implemented <<<
|
||||
break;
|
||||
|
||||
// drum designates
|
||||
case 4:
|
||||
case 4:
|
||||
case 8:
|
||||
this.D30F = 1; this.finish(); // >>> temp until implemented <<<
|
||||
break;
|
||||
|
||||
// paper tape designates
|
||||
case 18:
|
||||
case 18:
|
||||
case 20:
|
||||
this.D30F = 1; this.finish(); // >>> temp until implemented <<<
|
||||
break;
|
||||
@@ -754,12 +754,12 @@ B5500IOUnit.prototype.initiate = function() {
|
||||
it calls the CentralControl.initiateIO() function, which selects an idle I/O Unit and
|
||||
calls this function for that unit. Thus, at entry we are still running on top of the
|
||||
processor. This routine merely fetches the IOD from memory and then schedules forkIO()
|
||||
to run asynchronously. Then we exit back through CC and into P1, thus allowing the
|
||||
to run asynchronously. Then we exit back through CC and into P1, thus allowing the
|
||||
actual I/O operation to run asynchronously from the processor. Of course, in a browser
|
||||
environment, all of the Javascript action occurs on one thread, so this allows us to
|
||||
environment, all of the Javascript action occurs on one thread, so this allows us to
|
||||
multiplex what are supposed to be asynchronous operations on that thread */
|
||||
var that = this; // Establish object context for the callback
|
||||
|
||||
|
||||
this.clearD();
|
||||
this.AOFF = 0;
|
||||
this.EXNF = 0;
|
||||
@@ -773,7 +773,7 @@ B5500IOUnit.prototype.initiate = function() {
|
||||
this.finish();
|
||||
} else {
|
||||
this.D31F = 0; // reset the IOD-fetch error condition
|
||||
this.D = this.W;
|
||||
this.D = this.W;
|
||||
this.forkHandle = setTimeout(function() {that.forkIO()}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -241,31 +241,34 @@ window.onload = function() {
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function stringToANSI(text, bytes, bx) {
|
||||
function stringToANSI(text, bytes, bx, asBinary) {
|
||||
/* Translates the characters in a string to upper case, and then to ANSI
|
||||
byte-array format. "text" is the input string, "bytes" is the Uint8Array
|
||||
output buffer, and "bx" is the offset into that output buffer */
|
||||
output buffer, and "bx" is the offset into that output buffer. If "asBinary" is
|
||||
truthy, the translation is binary, otherwise it is done as BCLANSI */
|
||||
var len = text.length;
|
||||
var table1 = (asBinary ? BICtoANSI : BICtoBCLANSI);
|
||||
var utxt = text.toUpperCase();
|
||||
var x;
|
||||
|
||||
bx = bx || 0;
|
||||
for (x=0; x<len; x++) {
|
||||
bytes[bx++] = utxt.charCodeAt(x) & 0xFF;
|
||||
bytes[bx++] = table1[ANSItoBIC[utxt.charCodeAt(x) & 0xFF]];
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function wordsToANSI(words, wx, wLength, bytes, bx) {
|
||||
function wordsToANSI(words, wx, wLength, bytes, bx, asBinary) {
|
||||
/* Translates an array of B5500 words to ANSI byte-array format.
|
||||
"words" = the array of words
|
||||
"wx" = the starting index in "words"
|
||||
"wLength" = the number of words to translate: if this is negative, then binary
|
||||
translation is done; otherwise B5500 BCLANSI translation is done
|
||||
"wLength" = the number of words to translate
|
||||
"bytes" = a Uint8Array array
|
||||
"bx" = the starting index in "bytes" to store the translated data */
|
||||
"bx" = the starting index in "bytes" to store the translated data
|
||||
"asBinary" = if truthy, then binary translation is done; otherwise
|
||||
B5500 BCLANSI translation is done */
|
||||
var c;
|
||||
var table = (wLength < 0 ? BICtoANSI : BICtoBCLANSI);
|
||||
var table = (asBinary ? BICtoANSI : BICtoBCLANSI);
|
||||
var w;
|
||||
var x;
|
||||
var y;
|
||||
@@ -287,17 +290,18 @@ window.onload = function() {
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function ANSItoWords(bytes, bx, bLength, words, wx) {
|
||||
function ANSItoWords(bytes, bx, bLength, words, wx, asBinary) {
|
||||
/* Translates a portion of an ANSI byte array to a sequence of B5500 words.
|
||||
"bytes" = the Uint8Array byte array
|
||||
"bx" = 0-relative offset into "bytes"
|
||||
"bLength" = number of bytes to translate: if this is negative, then binary
|
||||
translation is done; otherwise B5500 BCLANSI translation is done
|
||||
"bLength" = number of bytes to translate
|
||||
"words" = the word array
|
||||
"wx" = 0-relative offset into "words" to store the translated data */
|
||||
"wx" = 0-relative offset into "words" to store the translated data
|
||||
"asBinary" = if truthy, then binary translation is done; otherwise
|
||||
B5500 BCLANSI translation is done */
|
||||
var cx = 0;
|
||||
var w = 0;
|
||||
var table = (bLength < 0 ? ANSItoBIC : BCLANSItoBIC);
|
||||
var table = (asBinary ? ANSItoBIC : BCLANSItoBIC);
|
||||
var x;
|
||||
|
||||
wx = wx || 0;
|
||||
@@ -443,7 +447,7 @@ window.onload = function() {
|
||||
/**************************************/
|
||||
function writeDiskWords(eu, addr, words, wx, wLength) {
|
||||
/* Translates the B5500 words in "words" starting at "wx" for "wLength" words
|
||||
to ANSI and writes the block one segment at a time to the "eu", starting at
|
||||
to BCLANSI and writes the block one segment at a time to the "eu", starting at
|
||||
segment "addr" */
|
||||
var segment = new Uint8Array(240);
|
||||
|
||||
@@ -456,7 +460,7 @@ window.onload = function() {
|
||||
}
|
||||
wordsToANSI(words, wx, wLength, segment, 0);
|
||||
for (wx=wLength*8; wx<240; wx++) {
|
||||
segment[wx] = 0x30; // fill partial seg with ASCII "0" => BCL "0" => @00
|
||||
segment[wx] = 0x26; // fill partial seg with ASCII "&" => BCL " " => BIC @60
|
||||
}
|
||||
eu.put(segment, addr);
|
||||
}
|
||||
@@ -1049,9 +1053,9 @@ window.onload = function() {
|
||||
nameParts = tapeDir[fileNr].split("/");
|
||||
mfid = "0" + padToLength(nameParts[0] || " ", 7);
|
||||
fid = "0" + padToLength(nameParts[1] || " ", 7);
|
||||
stringToANSI(mfid, buf, 0);
|
||||
stringToANSI(fid, buf, 8);
|
||||
ANSItoWords(buf, 0, -16, names, 0);
|
||||
stringToANSI(mfid, buf, 0, true);
|
||||
stringToANSI(fid, buf, 8, true);
|
||||
ANSItoWords(buf, 0, 16, names, 0, true);
|
||||
mfid = names[0];
|
||||
fid = names[1];
|
||||
loadAsMCP = $$("AsMCP_" + fileNr).checked;
|
||||
@@ -1830,8 +1834,9 @@ window.onload = function() {
|
||||
function dumpDisk() {
|
||||
/* Dumps the initial and directory portions of the disk */
|
||||
var txn = disk.transaction("EU0");
|
||||
var endKey = directoryTop+100;
|
||||
var eu = txn.objectStore("EU0");
|
||||
var range = IDBKeyRange.upperBound(directoryTop+20);
|
||||
var range = IDBKeyRange.upperBound(endKey);
|
||||
var req = eu.openCursor(range);
|
||||
var lastKey = -1;
|
||||
|
||||
@@ -1847,6 +1852,9 @@ window.onload = function() {
|
||||
lastKey = cursor.key;
|
||||
cursor.continue();
|
||||
} else {
|
||||
if (endKey > lastKey) {
|
||||
spout("----- " + (endKey-lastKey) + " unallocated segments thru " + endKey + " -----");
|
||||
}
|
||||
spout("===== END OF DISK DUMP =====");
|
||||
}
|
||||
};
|
||||
@@ -1879,7 +1887,7 @@ window.onload = function() {
|
||||
$$("ColdstartBtn").disabled = false;
|
||||
$$("FileSelector").disabled = false;
|
||||
|
||||
// dumpDisk(); // <<<<<<<<<<<<<< DEBUG <<<<<<<<<<<<<<<<<
|
||||
dumpDisk(); // <<<<<<<<<<<<<< DEBUG <<<<<<<<<<<<<<<<<
|
||||
|
||||
disk.transaction("CONFIG").objectStore("CONFIG").get(0).onsuccess = function(ev) {
|
||||
config = ev.target.result;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* addressable unit to the B5500. This module manages the Electronic Units (EU)
|
||||
* and Storage Units (SU) that make up the physical disk storage facility.
|
||||
*
|
||||
* Physical storage in this implementation is provided by a W3C IndexedDB
|
||||
* Physical storage in this implementation is provided by a W3C IndexedDB
|
||||
* database local to the browser in which the emulator is running. This database
|
||||
* must have been previously initialized; see tools/B5500ColdLoader.html.
|
||||
*
|
||||
@@ -24,9 +24,9 @@
|
||||
*
|
||||
* Within an EU, segments are represented in the database as 240-byte Uint8Array
|
||||
* objects, each with a database key corresponding to its numeric segment address.
|
||||
* The segments are an EU are not pre-allocated, but are created as they are
|
||||
* The segments are an EU are not pre-allocated, but are created as they are
|
||||
* written to by IDB put() methods. When reading, any unallocated segments are
|
||||
* returned with their bytes set to binary zero, which will be translated to
|
||||
* returned with their bytes set to binary zero, which will be translated to
|
||||
* BIC "?" by the IOU for both binary and alpha modes.
|
||||
*
|
||||
* At present, disk write lockout is not supported. When there are two DFCUs in
|
||||
@@ -43,9 +43,9 @@
|
||||
* and assumes the IOU does any necessary translation.
|
||||
*
|
||||
* The starting disk segment address for an I/O is passed in the "control"
|
||||
* parameter to each of the I/O methods. This is an an alphanumeric value in
|
||||
* parameter to each of the I/O methods. This is an an alphanumeric value in
|
||||
* the B5500 memory and I/O Unit. The I/O unit translates this value to binary
|
||||
* for the "control" parameter. The low-order six decimal digits of the value
|
||||
* for the "control" parameter. The low-order six decimal digits of the value
|
||||
* comprise the segment address within the EU. The seventh decimal digit is the
|
||||
* EU number. Any other portion of the value is ignored.
|
||||
*
|
||||
@@ -54,12 +54,12 @@
|
||||
* error reporting for the read check is deferred until the next I/O operation
|
||||
* (typically an interrogate) against the unit. Therefore, the error mask is
|
||||
* cleared at the end of each disk I/O operation (except for read check) instead
|
||||
* of at the beginning, and new errors are OR-ed with any errors persisting from
|
||||
* of at the beginning, and new errors are OR-ed with any errors persisting from
|
||||
* the prior operation.
|
||||
*
|
||||
* This module attempts to simulate actual disk activity times by delaying the
|
||||
* finish() call by an amount of time computed from the numbers of sectors
|
||||
* requested and the Model I SU's average 96KC transfer rate, plus a random
|
||||
* requested and the Model I SU's average 96KC transfer rate, plus a random
|
||||
* distribution across its 40ms max rotational latency time.
|
||||
************************************************************************
|
||||
* 2013-01-19 P.Kimpel
|
||||
@@ -76,7 +76,7 @@ function B5500DiskUnit(mnemonic, index, designate, statusChange, signal) {
|
||||
this.designate = designate; // IOD unit designate number
|
||||
this.statusChange = statusChange; // external function to call for ready-status change
|
||||
this.signal = signal; // external function to call for special signals (e.g,. SPO input request)
|
||||
|
||||
|
||||
this.clear();
|
||||
}
|
||||
|
||||
@@ -94,14 +94,14 @@ B5500DiskUnit.prototype.clear = function() {
|
||||
this.ready = false; // ready status
|
||||
this.busy = false; // busy status
|
||||
this.activeIOUnit = 0; // I/O unit currently using this device
|
||||
|
||||
|
||||
this.errorMask = 0; // error mask for finish()
|
||||
this.finish = null; // external function to call for I/O completion
|
||||
this.startStamp = null; // I/O starting timestamp
|
||||
this.startStamp = null; // I/O starting timestamp
|
||||
|
||||
this.config = null; // copy of CONFIG store contents
|
||||
this.disk = null; // the IDB database object
|
||||
|
||||
|
||||
this.openDatabase(); // attempt to open the IDB database
|
||||
};
|
||||
|
||||
@@ -121,13 +121,13 @@ B5500DiskUnit.prototype.copySegment = function(seg, buffer, offset) {
|
||||
/* Copies the bytes from a single segment Uint8Array object to "buffer" starting
|
||||
at "offset" for 240 bytes. If "seg" is undefined, copies zero bytes instead */
|
||||
var x;
|
||||
|
||||
|
||||
if (seg) {
|
||||
for (x=0; x<240; x++) {
|
||||
buffer[offset+x] = seg[x];
|
||||
}
|
||||
} else {
|
||||
for (x=offset+239; x>=0; x--) {
|
||||
for (x=offset+239; x>=offset; x--) {
|
||||
buffer[x] = 0;
|
||||
}
|
||||
}
|
||||
@@ -162,10 +162,10 @@ B5500DiskUnit.prototype.openDatabase = function() {
|
||||
that.disk.onerror = function(ev) {
|
||||
alert("Database for \"" + this.mnemonic + "\" open error: " + ev.target.result.error);
|
||||
};
|
||||
|
||||
|
||||
that.disk.transaction("CONFIG").objectStore("CONFIG").get(0).onsuccess = function(ev) {
|
||||
that.config = ev.target.result;
|
||||
that.statusChange(1); // report the DFCU as ready to Central Control
|
||||
that.statusChange(1); // report the DFCU as ready to Central Control
|
||||
// Set up the generic error handler
|
||||
that.disk.onerror = function(ev) {
|
||||
that.genericIDBError(ev);
|
||||
@@ -192,7 +192,7 @@ B5500DiskUnit.prototype.read = function(finish, buffer, length, mode, control) {
|
||||
var euNumber = (control % 10000000 - segAddr)/1000000;
|
||||
var euName = this.euPrefix + euNumber;
|
||||
var endAddr = segAddr+segs-1; // ending seg address
|
||||
|
||||
|
||||
euSize = this.config[euName];
|
||||
if (!euSize) { // EU does not exist
|
||||
finish(this.errorMask | 0x20, 0); // set D27F for EU not ready
|
||||
@@ -207,16 +207,13 @@ B5500DiskUnit.prototype.read = function(finish, buffer, length, mode, control) {
|
||||
length = segs*240; // recompute length and ending seg address
|
||||
endAddr = euSize-1;
|
||||
}
|
||||
finishTime = new Date().getTime() +
|
||||
finishTime = new Date().getTime() +
|
||||
(Math.random()*this.maxLatency + segs*240/this.charXferRate)*1000;
|
||||
|
||||
// No length specified, so just finish the I/O
|
||||
if (segs < 1) {
|
||||
finish(this.errorMask, 0);
|
||||
|
||||
if (segs < 1) { // No length specified, so just finish the I/O
|
||||
finish(this.errorMask, 0);
|
||||
this.errorMask = 0;
|
||||
|
||||
// A single-segment read
|
||||
} else if (segs < 2) {
|
||||
} else if (segs < 2) { // A single-segment read
|
||||
req = this.disk.transaction(euName).objectStore(euName).get(segAddr);
|
||||
req.onsuccess = function(ev) {
|
||||
that.copySegment(ev.target.result, buffer, 0);
|
||||
@@ -224,13 +221,11 @@ B5500DiskUnit.prototype.read = function(finish, buffer, length, mode, control) {
|
||||
finish(that.errorMask, length);
|
||||
that.errorMask = 0;
|
||||
}, finishTime - new Date().getTime());
|
||||
};
|
||||
|
||||
// A multi-segment read
|
||||
} else {
|
||||
}
|
||||
} else { // A multi-segment read
|
||||
range = window.IDBKeyRange.bound(segAddr, endAddr);
|
||||
txn = this.disk.transaction(euName);
|
||||
|
||||
|
||||
req = txn.objectStore(euName).openCursor(range);
|
||||
req.onsuccess = function(ev) {
|
||||
var cursor = ev.target.result;
|
||||
@@ -289,7 +284,7 @@ B5500DiskUnit.prototype.write = function(finish, buffer, length, mode, control)
|
||||
var euNumber = (control % 10000000 - segAddr)/1000000;
|
||||
var euName = this.euPrefix + euNumber;
|
||||
var endAddr = segAddr+segs-1; // ending seg address
|
||||
|
||||
|
||||
euSize = this.config[euName];
|
||||
if (!euSize) { // EU does not exist
|
||||
finish(this.errorMask | 0x20, 0); // set D27F for EU not ready
|
||||
@@ -304,16 +299,16 @@ B5500DiskUnit.prototype.write = function(finish, buffer, length, mode, control)
|
||||
length = segs*240; // recompute length and ending seg address
|
||||
endAddr = euSize-1;
|
||||
}
|
||||
finishTime = new Date().getTime() +
|
||||
finishTime = new Date().getTime() +
|
||||
(Math.random()*this.maxLatency + segs*240/this.charXferRate)*1000;
|
||||
|
||||
|
||||
// No length specified, so just finish the I/O
|
||||
if (segs < 1) {
|
||||
finish(this.errorMask, 0);
|
||||
if (segs < 1) {
|
||||
finish(this.errorMask, 0);
|
||||
this.errorMask = 0;
|
||||
|
||||
|
||||
// Do the write
|
||||
} else {
|
||||
} else {
|
||||
txn = this.disk.transaction(euName, "readwrite")
|
||||
txn.oncomplete = function(ev) {
|
||||
setTimeout(function() {
|
||||
@@ -333,21 +328,21 @@ B5500DiskUnit.prototype.write = function(finish, buffer, length, mode, control)
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.erase = function(finish, length) {
|
||||
/* Initiates an erase operation on the unit */
|
||||
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.rewind = function(finish) {
|
||||
/* Initiates a rewind operation on the unit */
|
||||
|
||||
|
||||
finish(0x04, 0); // report unit not ready
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DiskUnit.prototype.readCheck = function(finish, length, control) {
|
||||
/* Initiates a read check operation on the unit. "length" is in characters;
|
||||
segment address is in "control". "mode" is ignored. This is essentially a
|
||||
/* Initiates a read check operation on the unit. "length" is in characters;
|
||||
segment address is in "control". "mode" is ignored. This is essentially a
|
||||
read without any data transfer to memory. Note that the errorMask is NOT
|
||||
zeroed at the end of the I/O -- it will be reported with the next I/O */
|
||||
var euSize; // max seg size for EU
|
||||
@@ -363,7 +358,7 @@ B5500DiskUnit.prototype.readCheck = function(finish, length, control) {
|
||||
var euNumber = (control % 10000000 - segAddr)/1000000;
|
||||
var euName = this.euPrefix + euNumber;
|
||||
var endAddr = segAddr+segs-1; // ending seg address
|
||||
|
||||
|
||||
this.errorMask = 0; // clear any prior error mask
|
||||
euSize = this.config[euName];
|
||||
if (!euSize) { // EU does not exist
|
||||
@@ -379,19 +374,16 @@ B5500DiskUnit.prototype.readCheck = function(finish, length, control) {
|
||||
length = segs*240; // recompute length and ending seg address
|
||||
endAddr = euSize-1;
|
||||
}
|
||||
finishTime = new Date().getTime() +
|
||||
finishTime = new Date().getTime() +
|
||||
(Math.random()*this.maxLatency + segs*240/this.charXferRate)*1000;
|
||||
|
||||
// No length specified, so just finish the I/O
|
||||
if (segs < 1) {
|
||||
finish(this.errorMask, 0);
|
||||
|
||||
if (segs < 1) { // No length specified, so just finish the I/O
|
||||
finish(this.errorMask, 0);
|
||||
// DO NOT clear the error mask -- will return it on the next interrogate
|
||||
|
||||
// A multi-segment read
|
||||
} else {
|
||||
} else { // A multi-segment read
|
||||
range = window.IDBKeyRange.bound(segAddr, endAddr);
|
||||
txn = this.disk.transacation(euName);
|
||||
|
||||
|
||||
req = txn.objectStore(euName).openCursor(range);
|
||||
req.onsuccess = function(ev) {
|
||||
var cursor = ev.target.result;
|
||||
@@ -421,7 +413,7 @@ B5500DiskUnit.prototype.readInterrogate = function(finish, control) {
|
||||
var euNumber = (control % 10000000 - segAddr)/1000000;
|
||||
var euName = this.euPrefix + euNumber;
|
||||
var that = this;
|
||||
|
||||
|
||||
this.finish = finish; // for global error handler
|
||||
euSize = this.config[euName];
|
||||
if (!euSize) { // EU does not exist
|
||||
@@ -445,16 +437,16 @@ B5500DiskUnit.prototype.writeInterrogate = function (finish, control) {
|
||||
read check operation. This implementation assumes completion will be delayed
|
||||
by a random amount of time based on rotational latency for the EU to search for
|
||||
the address */
|
||||
|
||||
|
||||
/* Note: until disk write lockout is implemented, this operation is identical
|
||||
to readInterrogate() */
|
||||
|
||||
|
||||
var euSize; // max seg size for EU
|
||||
var segAddr = control % 1000000; // starting seg address
|
||||
var euNumber = (control % 10000000 - segAddr)/1000000;
|
||||
var euName = this.euPrefix + euNumber;
|
||||
var that = this;
|
||||
|
||||
|
||||
this.finish = finish; // for global error handler
|
||||
euSize = this.config[euName];
|
||||
if (!euSize) { // EU does not exist
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
f<!DOCTYPE html>
|
||||
<head>
|
||||
<title>B5500 Processor Syllable Debugger</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
@@ -941,7 +941,7 @@ function initialize() {
|
||||
cc.P1.R = 0x005; // PRT at @500 (R has addr div 64)
|
||||
|
||||
cc.P1.C = 0x10; // execute from address @20
|
||||
cc.P1.access(0x30); // P = [C]
|
||||
cc.P1.loadPviaC();
|
||||
cc.P1.T = cc.fieldIsolate(cc.P1.P, 0, 12);
|
||||
cc.P1.TROF = 1;
|
||||
cc.P1.L = 1; // point to the next instruction
|
||||
|
||||
Reference in New Issue
Block a user