diff --git a/emulator/B5500Processor.js b/emulator/B5500Processor.js index 089d539..94592f1 100644 --- a/emulator/B5500Processor.js +++ b/emulator/B5500Processor.js @@ -977,7 +977,7 @@ B5500Processor.prototype.streamSourceToDest = function(count, transform) { bBit = this.K*6; // B-bit number do { this.Y = this.cc.fieldIsolate(this.A, aBit, 6); - transform(bBit, count) + transform.call(this, bBit, count) count--; if (bBit < 42) { bBit += 6; @@ -1022,7 +1022,7 @@ B5500Processor.prototype.streamToDest = function(count, transform) { this.cycleCount += count; // approximate the timing bBit = this.K*6; // B-bit number do { - if (transform(bBit, count)) { + if (transform.call(this, bBit, count)) { count = 0; } else { count--; @@ -1339,6 +1339,9 @@ B5500Processor.prototype.preset = function(runAddr) { this.loadPviaC(); // load the program word to P this.T = this.cc.fieldIsolate(this.P, 0, 12); this.TROF = 1; + this.R = 0; + this.S = 0; + }; /**************************************/ @@ -2347,6 +2350,12 @@ B5500Processor.prototype.computeRelativeAddr = function(offset, cEnabled) { } else { this.M = (this.R*64) + (offset & 0x3FF); } + + // Reset variant-mode R-relative addressing, if enabled + if (this.VARF) { + this.SALF = 1; + this.VARF = 0; + } }; /**************************************/ @@ -2399,13 +2408,13 @@ B5500Processor.prototype.indexDescriptor = function() { // Now we have an integerized index value in xm if (!interrupted) { - if (xs) { // oops... negative index + if (xs && xm) { // oops... negative index interrupted = 1; if (this.NCSF) { this.I = (this.I & 0x0F) | 0x90; // set I05/8: invalid-index this.cc.signalInterrupt(); } - } else if (xm >= this.cc.fieldIsolate(aw, 8, 10)) { + } else if (xm % 0x0400 >= this.cc.fieldIsolate(aw, 8, 10)) { interrupted = 1; // oops... index out of bounds if (this.NCSF) { this.I = (this.I & 0x0F) | 0x90; // set I05/8: invalid-index @@ -2522,6 +2531,7 @@ B5500Processor.prototype.enterCharModeInline = function() { this.loadAviaS(); // A = [S]: tank the DI address } this.B = this.buildRCW(0); + this.BROF = 1; this.adjustBEmpty(); this.MSFF = 0; this.SALF = 1; @@ -2554,7 +2564,7 @@ B5500Processor.prototype.enterCharModeInline = function() { /**************************************/ B5500Processor.prototype.enterSubroutine = function(descriptorCall) { - /* Enters a subroutine via the present program descriptor in A as part + /* Enters a subroutine via the present Program Descriptor in A as part of an OPDC or DESC syllable. Also handles accidental entry */ var aw = this.A; // local copy of word in A reg var bw; // local copy of word in B reg @@ -2562,7 +2572,7 @@ B5500Processor.prototype.enterSubroutine = function(descriptorCall) { var mode = this.cc.bit(aw, 4); // descriptor mode bit (1-char mode) if (arg && !this.MSFF) { - ; // just leave the PD on TOS + ; // just leave the Program Descriptor on TOS } else if (mode && !arg) { ; // ditto } else { @@ -2577,6 +2587,7 @@ B5500Processor.prototype.enterSubroutine = function(descriptorCall) { // Push a RCW this.B = this.buildRCW(descriptorCall); + this.BROF = 1; this.adjustBEmpty(); // Fetch the first word of subroutine code @@ -2653,10 +2664,9 @@ B5500Processor.prototype.operandCall = function() { /* OPDC, the moral equivalent of "load accumulator" on lesser machines. Assumes the syllable has already loaded a word into A. See Figures 6-1, 6-3, and 6-4 in the B5500 Reference Manual */ - var aw; // local copy of A reg value + var aw = this.A; // local copy of A reg value var interrupted = 0; // interrupt occurred - aw = this.A; if (aw >= 0x800000000000) { // It's not a simple operand switch (this.cc.fieldIsolate(aw, 1, 3)) { @@ -2699,12 +2709,6 @@ B5500Processor.prototype.operandCall = function() { break; } } - - // Reset variant-mode R-relative addressing, if enabled - if (this.VARF && !interrupted) { - this.SALF = 1; - this.VARF = 0; - } }; /**************************************/ @@ -2754,12 +2758,6 @@ B5500Processor.prototype.descriptorCall = function() { break; } } - - // Reset variant-mode R-relative addressing, if enabled - if (this.VARF && !interrupted) { - this.SALF = 1; - this.VARF = 0; - } }; /**************************************/ @@ -2834,15 +2832,15 @@ B5500Processor.prototype.run = function() { this.storeBviaS(); // [S] = B this.BROF = 0; } + this.V = 0; this.S = this.F - variant; this.loadBviaS(); // B = [S] this.S = this.B % 0x8000; - this.V = 0; if (this.B >= 0x800000000000) { // if it's a descriptor, this.K = 0; // force K to zero and this.presenceTest(this.B); // just take the side effect of any p-bit interrupt } else { - this.K = this.cc.fieldIsolate(this.B, 18, 3); + this.K = (this.B % 0x40000) >>> 15; } break; @@ -2990,7 +2988,7 @@ B5500Processor.prototype.run = function() { this.storeBviaS(); // will skip off the current word, this.BROF = 0; // so store and invalidate B } - t1 = this.S*8 + this.K - variant; + t1 = this.S*8 + this.K + variant; this.S = t1 >>> 3; this.K = t1 & 0x07; break; @@ -3276,15 +3274,15 @@ B5500Processor.prototype.run = function() { this.cycleCount += variant; this.A = this.B; // save B this.AROF = this.BROF; + this.H = 0; this.M = this.F - variant; this.loadBviaM(); // B = [M] this.M = this.B % 0x8000; - this.H = 0; if (this.B >= 0x800000000000) { // if it's a descriptor, this.G = 0; // force G to zero and this.presenceTest(this.B); // just take the side effect of any p-bit interrupt - } else { - this.G = this.cc.fieldIsolate(this.B, 18, 3); + } else { // it's an operand + this.G = (this.B % 0x40000) >>> 15; } this.B = this.A; // restore B from A this.BROF = this.AROF; @@ -3489,14 +3487,16 @@ B5500Processor.prototype.run = function() { case 2: // OPDC: Operand Call this.adjustAEmpty(); this.computeRelativeAddr(opcode >>> 2, 1); - this.loadAviaM(); // A = [M] - this.operandCall(); + this.loadAviaM(); + if (this.A >= 0x800000000000) { // a small optimization for the + this.operandCall(); // common case when TOS is an operand + } break; case 3: // DESC: Descriptor (name) Call this.adjustAEmpty(); this.computeRelativeAddr(opcode >>> 2, 1); - this.loadAviaM(); // A = [M] + this.loadAviaM(); this.descriptorCall(); break; @@ -3745,6 +3745,19 @@ B5500Processor.prototype.run = function() { break; case 0x10: // 2021: LOD=Load operand + this.adjustAFull(); + if (this.A < 0x800000000000) { // simple operand + this.computeRelativeAddr(this.A, 1); + this.loadAviaM(); + } else if (this.A < 0xC00000000000) { // absent descriptor + if (this.NCSF) { + this.I = (this.I & 0x0F) | 0x70;// set I05/6/7: p-bit + this.cc.signalInterrupt(); + } + } else { // present descriptor + this.M = this.A % 0x8000; + this.loadAviaM(); + } break; case 0x21: // 4121: ISD=Integer store destructive diff --git a/webUI/tools/tests/CHARMODE b/webUI/tools/tests/CHARMODE index e59c973..ac0a8d6 100644 Binary files a/webUI/tools/tests/CHARMODE and b/webUI/tools/tests/CHARMODE differ diff --git a/webUI/tools/tests/CHARMODE.esp_m b/webUI/tools/tests/CHARMODE.esp_m new file mode 100644 index 0000000..a6f1620 --- /dev/null +++ b/webUI/tools/tests/CHARMODE.esp_m @@ -0,0 +1,47 @@ +$ SET $ LIST PRT DEBUGN 00000100 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%00000200 +%% %%00000300 +%% RETRO-B5500 EMULATOR CHARACTER MODE TESTS %%00000400 +%% %%00000500 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%00000600 +% 2013-01-26 P.KIMPEL 00000700 +% ORIGINAL VERSION 00000800 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%00099900 + 00100000 +BEGIN 00100100 +INTEGER I; 00100200 +REAL R; 00100300 +ARRAY S[16]:= 00100400 + "01234567","89ABCDEF","GHIJKLMN","OPQRSTUV","WXYZ +-/", 00100500 + "NOW IS T","HE TIME ","FOR ALL ","GOOD MEN"," TO COME", 00100600 + " TO THE ","AID OF T","HEIR PAR","TY. ","1234567Q","12345678"; 00100700 +ARRAY D[16]; 00100800 +LABEL ENTRY, START; 00100900 + 00400000 +ENTRY:@20: GO TO START; 00400100 + 00500000 +START:*: 00500100 + 00500200 +D[0]:= 76543210; 00500300 + 00520000 +STREAM(R:=D[0]: S:=S, D:=D); 00520100 + BEGIN 00520200 + SI:= S; 00520300 + SI:= SI+51; 00520400 + DI:= DI+6; 00520500 + DS:= 5 CHR; 00520600 + 00520700 + SI:= LOC R; 00520800 + DI:= D; 00520900 + DI:= DI+32; 00521000 + DS:= 8 DEC; 00521100 + 00521200 + SI:= SI-8; 00521300 + DI:= D; 00521400 + 2(DI:= DI+40); 00521500 + DI:= DI+32; 00521600 + DS:= 8 OCT; 00521700 + END STREAM; 00521800 + 00999700 +GO TO START; 00999800 +END. 00999900