mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-04-26 12:18:08 +00:00
Commit DCMCP transcription as of 2013-02-02; continue debugging Processor character mode; implement store syllables; implement syllable decoding in SyllableDebugger.
This commit is contained in:
@@ -20550,3 +20550,89 @@ ST: H[2]:=LAB[2]; 28099800
|
||||
GO EXIT; 28101000
|
||||
EXIT: P(0,RDS,0,XCH,P&P[CTF],STF); 28101200
|
||||
END OF LIBRARYHELP; 28101400
|
||||
PROCEDURE LIBRARYTRANSFER; 28200000
|
||||
% 28200002
|
||||
%********************************************************************** 28200004
|
||||
% 28200006
|
||||
% 28200008
|
||||
% LIBRARYTRANSFER PERFORMS THE ACTUAL PHYSICAL TRANSFER OF FILES 28200010
|
||||
% BASED ON INFORMATION SUPPLIED BY LIBRARYCOPY. BASICALLY, ALL 28200012
|
||||
% LIBRARYTRANSFER NEEDS FROM LIBRARYCOPY IS "FA" (THE FILE ARRAY 28200014
|
||||
% WHICH CONTAINS THE NAME PAIRS TO BE TRANSFERRED), "FAINFO" 28200016
|
||||
% (THE FILE ARRAY INFORMATION, WHICH CONTAINS NECESSARY INFO. 28200018
|
||||
% ABOUT EACH NAME PAIR), AND "DESTIN" (THE USER SPECIFIED 28200020
|
||||
% DESTINATION). 28200022
|
||||
% 28200024
|
||||
% TRANSFERS MAY BE MADE FROM TAPE TO TAPE, TAPE TO DISK, OR 28200026
|
||||
% DISK TO TAPE. LIBRARYTRANSFER WILL ATTEMPT TO TRANSFER DATA 28200028
|
||||
% FROM THE INPUT SOURCE SPECIFIED IN THE "FAINFO" ENTRY TO THE 28200030
|
||||
% UNIT SPECIFIED THRU "DESTIN". THE BULK OF LIBRARYTRANSFER IS 28200032
|
||||
% JUST LOOPING THROUGH "FAINFO" USING ONE ENTRY AT A TIME UNTIL 28200034
|
||||
% THEY ARE EXHAUSTED. AT EACH CHANGE OF INPUT SOURCE THE FPB 28200036
|
||||
% IS FIXED UP DIFFERENTLY DEPENDING UPON WHETHER THE JOB WAS 28200038
|
||||
% FORKED OR NOT (REFER TO DOCUMENTATION). 28200040
|
||||
% 28200042
|
||||
% 28200044
|
||||
% DA CURRENT "FAINFO" ENTRY 28200046
|
||||
% .[CF] IF DISK THEN 18 28200048
|
||||
% IF TAPE THEN UNIT NUMBER OF THE TAPE 28200050
|
||||
% .[FF] IF DISK THEN DISK ADDRESS OF FILE HEADER 28200052
|
||||
% IF TAPE THEN NUMBER OF THIS FILE ON TAPE 28200054
|
||||
% .[5:1] SPECIFIES LATEST VERSION WANTED 28200056
|
||||
% .[6:1] FILE TO BE ADDED 28200058
|
||||
% .[8:1] FILE TO BE UNLOADED 28200060
|
||||
% .[13:1] FILE TO BE ADDED (NOT ON DISK) %160-28200061
|
||||
% 28200062
|
||||
% NOTE: ANY OPTIONS SET THAT DO NOT APPLY TO A PARTICULAR 28200064
|
||||
% CIRCUMSTANCE WILL BE IGNORED 28200066
|
||||
% 28200068
|
||||
% IU CURRENT INPUT UNIT 28200070
|
||||
% 28200072
|
||||
% OU " OUTPUT " 28200074
|
||||
% 28200076
|
||||
% IREEL CURRENT INPUT REEL NUMBER (IF TAPE) 28200078
|
||||
% 28200080
|
||||
% OREEL " OUTPUT " " " 28200082
|
||||
% 28200084
|
||||
% FA FILE ARRAY OF NAME PAIRS TO BE TRANSFERRED 28200086
|
||||
% 28200088
|
||||
% FAINFO TRANSFER INFO. FOR EACH NAME PAIR 28200090
|
||||
% 28200092
|
||||
% FPBPTR CURRENT FPB ENTRY INDEX 28200094
|
||||
% 28200096
|
||||
% H CURRENT FILE HEADER 28200098
|
||||
% 28200100
|
||||
% LAB LAST INPUT LABEL READ 28200102
|
||||
% 28200104
|
||||
% LBL LAST OUTPUT LABEL READ 28200106
|
||||
% 28200108
|
||||
% TOGS.[21:1] (BHS) INDICATES BAD HEADER 28200110
|
||||
% [23:1] (FORKED) NOT ORIGINATING LIBMAIN/DISK 28200112
|
||||
% [26:1] (OF) CURRENT <MFID>/<FID> HAS BEEN 28200114
|
||||
% OPENED EXCLUSIVE 28200116
|
||||
% 28200118
|
||||
% [28:1] (SOMECOPIED) AT LEAST ONE FILE HAS BEEN 28200120
|
||||
% TRANSFERED 28200122
|
||||
% [38:1] (COPYING) NOTES STAGE OF PROCESSING FOR 28200124
|
||||
% USE BY ABORT 28200126
|
||||
% [40:1] (SKIPFILE) USED TO INDICATE ABRUPT EXIT TO 28200128
|
||||
% NEXT FILE SHOULD BE TAKEN 28200130
|
||||
% 28200132
|
||||
% 28200134
|
||||
%********************************************************************** 28200136
|
||||
% 28200138
|
||||
BEGIN 28200200
|
||||
REAL COMMON=-4, 28200400
|
||||
MSCW=-1, RCW=+0, 28200800
|
||||
MFID=RCW+1, FID=MFID+1, 28201000
|
||||
XX1=FID+1, XX2=XX1+1, 28201200
|
||||
TMP=XX2+1, TEMP=TMP+1, 28201400
|
||||
FA=TEMP+1, FAINFO=FA+1, 28201600
|
||||
FASZ=FAINFO+1, FAIN=FASZ+1, 28201800
|
||||
IU=FAIN+1, T=IU+1, 28202000
|
||||
FPBPTR=T+1, IREEL=FPBPTR+1, 28202200
|
||||
NM1=IREEL+1, NM2=NM1+1, 28202400
|
||||
DESTIN=NM2+1, TOGS=DESTIN+1, 28202600
|
||||
DA=TOGS+1, OU=DA+1, 28202800
|
||||
OREEL=OU+1, N=OREEL+1, 28203000
|
||||
CNT=N+1, INC=CNT+1, 28203200
|
||||
|
||||
@@ -2358,6 +2358,22 @@ B5500Processor.prototype.computeRelativeAddr = function(offset, cEnabled) {
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.presenceTest = function(word) {
|
||||
/* Tests and returns the presence bit [2:1] of the "word" parameter. If
|
||||
0, the p-bit interrupt is set; otherwise no further action */
|
||||
|
||||
if (word % 0x400000000000 >= 0x200000000000) {
|
||||
return 1;
|
||||
} else {
|
||||
if (this.NCSF) {
|
||||
this.I = (this.I & 0x0F) | 0x70; // set I05/6/7: p-bit
|
||||
this.cc.signalInterrupt();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.indexDescriptor = function() {
|
||||
/* Indexes a descriptor and, if successful leaves the indexed value in
|
||||
@@ -2375,7 +2391,7 @@ B5500Processor.prototype.indexDescriptor = function() {
|
||||
this.adjustBFull();
|
||||
bw = this.B;
|
||||
xm = (bw % 0x8000000000);
|
||||
xe = (bw - xm)/8;
|
||||
xe = (bw - xm)/0x8000000000;
|
||||
xs = (xe >>> 7) & 0x01;
|
||||
xt = (xe >>> 6) & 0x01;
|
||||
xe = (xt ? -(xe & 0x3F) : (xe & 0x3F));
|
||||
@@ -2430,18 +2446,84 @@ B5500Processor.prototype.indexDescriptor = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.presenceTest = function(word) {
|
||||
/* Tests and returns the presence bit [2:1] of the "word" parameter. If
|
||||
0, the p-bit interrupt is set; otherwise no further action */
|
||||
B5500Processor.prototype.integerStore = function(conditional, destructive) {
|
||||
/* Store the value in the B register at the address in the A register (relative
|
||||
or descriptor) and marks the A register empty. "conditional" indicates that
|
||||
integerization is conditional on the type of word in A, and if a descriptor,
|
||||
whether it has the integer bit set */
|
||||
var aw; // local copy of A reg
|
||||
var bw; // local copy of B reg
|
||||
var be; // B exponent
|
||||
var bm; // B mantissa
|
||||
var bo; // last B octade shifted off
|
||||
var bs; // B mantissa sign
|
||||
var bt; // B exponent sign
|
||||
var doStore = 1; // okay to store
|
||||
var normalize = 1; // okay to integerize
|
||||
|
||||
if (word % 0x400000000000 >= 0x200000000000) {
|
||||
return 1;
|
||||
} else {
|
||||
if (this.NCSF) {
|
||||
this.I = (this.I & 0x0F) | 0x70; // set I05/6/7: p-bit
|
||||
this.cc.signalInterrupt();
|
||||
this.adjustABFull();
|
||||
aw = this.A;
|
||||
if (aw < 0x800000000000) { // it's an operand
|
||||
this.computeRelativeAddr(aw, 0);
|
||||
} else { // it's a descriptor
|
||||
if (this.presenceTest(aw)) {
|
||||
this.M = aw % 0x8000;
|
||||
if (conditional) {
|
||||
if (aw % 0x20000000 < 0x10000000) { // [19:1] is the integer bit
|
||||
normalize = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
doStore = normalize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (normalize) {
|
||||
bw = this.B;
|
||||
bm = (bw % 0x8000000000);
|
||||
be = (bw - bm)/0x8000000000;
|
||||
bs = (be >>> 7) & 0x01;
|
||||
bt = (be >>> 6) & 0x01;
|
||||
be = (bt ? -(be & 0x3F) : (be & 0x3F));
|
||||
|
||||
if (be != 0) {
|
||||
if (be < 0) { // B exponent is negative
|
||||
do {
|
||||
this.cycleCount++;
|
||||
bo = bm % 8;
|
||||
bm = (bm - bo)/8;
|
||||
} while (++be < 0);
|
||||
if (bs ? bo > 4 : bo >= 4) {
|
||||
bm++; // round the B mantissa
|
||||
}
|
||||
} else if (be > 0) { // B exponent is positive
|
||||
do {
|
||||
this.cycleCount++;
|
||||
if (bm < 0x1000000000) {
|
||||
bm *= 8;
|
||||
} else { // oops... integer overflow normalizing the mantisa
|
||||
doStore = 0;
|
||||
if (this.NCSF) {
|
||||
this.I = (this.I & 0x0F) | 0xC0; // set I07/8: int-overflow
|
||||
this.cc.signalInterrupt();
|
||||
break; // kill the loop
|
||||
}
|
||||
}
|
||||
} while (--be > 0);
|
||||
}
|
||||
if (doStore) {
|
||||
this.B = bs*0x400000000000 + bm;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (doStore) {
|
||||
this.storeBviaM();
|
||||
this.AROF = 0;
|
||||
if (destructive) {
|
||||
this.BROF = 0
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2528,7 +2610,8 @@ B5500Processor.prototype.enterCharModeInline = function() {
|
||||
this.A = this.B; // tank the DI address in A
|
||||
this.adjustBEmpty();
|
||||
} else {
|
||||
this.loadAviaS(); // A = [S]: tank the DI address
|
||||
this.loadAviaS(); // A = [S]: load the DI address
|
||||
this.AROF = 0;
|
||||
}
|
||||
this.B = this.buildRCW(0);
|
||||
this.BROF = 1;
|
||||
@@ -2540,25 +2623,16 @@ B5500Processor.prototype.enterCharModeInline = function() {
|
||||
this.CWMF = 1;
|
||||
this.X = this.S * 0x8000; // inserting S into X.[18:15], but X is zero at this point
|
||||
this.S = 0;
|
||||
this.V = 0;
|
||||
this.B = bw = this.A;
|
||||
this.BROF = 1;
|
||||
this.AROF = 0;
|
||||
this.V = this.K = 0;
|
||||
|
||||
// execute the portion of CM XX04=RDA operator starting at J=2
|
||||
if (bw < 0x800000000000) { // B contains an operand
|
||||
this.S = bw % 0x8000;
|
||||
this.S = bw % 0x8000;
|
||||
if (bw >= 0x800000000000) { // if it's a descriptor,
|
||||
this.K = 0; // force K to zero and
|
||||
this.presenceTest(bw); // just take the side effect of any p-bit interrupt
|
||||
} else {
|
||||
this.K = (bw % 0x40000) >>> 15;
|
||||
} else { // B contains a descriptor
|
||||
if (bw % 0x400000000000 < 0x200000000000) { // it's an absent descriptor
|
||||
if (this.NCSF) {
|
||||
// NOTE: docs do not mention if this is inhibited in control state, but we assume it is
|
||||
this.I = (this.I & 0x0F) | 0x70; // set I05/6/7: P-bit
|
||||
this.cc.signalInterrupt();
|
||||
}
|
||||
} else {
|
||||
this.S = bw % 0x8000;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2835,12 +2909,13 @@ B5500Processor.prototype.run = function() {
|
||||
this.V = 0;
|
||||
this.S = this.F - variant;
|
||||
this.loadBviaS(); // B = [S]
|
||||
this.S = this.B % 0x8000;
|
||||
if (this.B >= 0x800000000000) { // if it's a descriptor,
|
||||
this.BROF = 0;
|
||||
this.S = (t1 = this.B) % 0x8000;
|
||||
if (t1 >= 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
|
||||
this.presenceTest(t1); // just take the side effect of any p-bit interrupt
|
||||
} else {
|
||||
this.K = (this.B % 0x40000) >>> 15;
|
||||
this.K = (t1 % 0x40000) >>> 15;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3732,16 +3807,42 @@ B5500Processor.prototype.run = function() {
|
||||
|
||||
case 0x11: // XX21: load & store ops
|
||||
switch (variant) {
|
||||
case 0x01: // 0121: CID=Conditional integer store descructive
|
||||
case 0x01: // 0121: CID=Conditional integer store destructive
|
||||
this.integerStore(1, 1);
|
||||
break;
|
||||
|
||||
case 0x02: // 0221: CIN=Conditional integer store nondestructive
|
||||
this.integerStore(1, 0);
|
||||
break;
|
||||
|
||||
case 0x04: // 0421: STD=Store destructive
|
||||
this.adjustABFull();
|
||||
if (this.A < 0x800000000000) { // it's an operand
|
||||
this.computeRelativeAddr(this.A, 0);
|
||||
this.storeBviaM();
|
||||
this.AROF = this.BROF = 0;
|
||||
} else { // it's a descriptor
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.M = this.A % 0x8000;
|
||||
this.storeBviaM();
|
||||
this.AROF = this.BROF = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x08: // 1021: SND=Store nondestructive
|
||||
this.adjustABFull();
|
||||
if (this.A < 0x800000000000) { // it's an operand
|
||||
this.computeRelativeAddr(this.A, 0);
|
||||
this.storeBviaM();
|
||||
this.AROF = 0;
|
||||
} else { // it's a descriptor
|
||||
if (this.presenceTest(this.A)) {
|
||||
this.M = this.A % 0x8000;
|
||||
this.storeBviaM();
|
||||
this.AROF = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10: // 2021: LOD=Load operand
|
||||
@@ -3749,21 +3850,18 @@ B5500Processor.prototype.run = function() {
|
||||
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;
|
||||
} else if (this.presenceTest(this.A)) {
|
||||
this.M = this.A % 0x8000; // present descriptor
|
||||
this.loadAviaM();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x21: // 4121: ISD=Integer store destructive
|
||||
this.integerStore(0, 1);
|
||||
break;
|
||||
|
||||
case 0x22: // 4221: ISN=Integer store nondestructive
|
||||
this.integerStore(0, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -41,6 +41,163 @@ var BICtoANSI = [
|
||||
" ", "/", "S", "T", "U", "V", "W", "X",
|
||||
"Y", "Z", ",", "%", "!", "=", "]", "\""];
|
||||
|
||||
var wordOps = {
|
||||
"0000": "LITC" // Literal Call (XXX0 or XXX4)
|
||||
,"0002": "OPDC" // Operand Call (XXX2 or XXX6)
|
||||
,"0003": "DESC" // Descriptor Call (XXX3 or XXX7)
|
||||
,"0101": "ADD " // Single Precision Add
|
||||
,"0301": "SUB " // Single Precision Subtract
|
||||
,"0401": "MUL " // Single Precision Multiply
|
||||
,"1001": "DIV " // Single Precision Divide
|
||||
,"3001": "IDV " // Integer Divide
|
||||
,"7001": "RDV " // Remainder Divide
|
||||
,"0105": "DLA " // Double Precision Add
|
||||
,"0305": "DLS " // Double Precision Subtract
|
||||
,"0405": "DLM " // Double Precision Multiply
|
||||
,"1005": "DLD " // Double Precision Divide
|
||||
,"0111": "PRL " // Program Release
|
||||
,"0211": "ITI " // Interrogate Interrupt
|
||||
,"0411": "RTR " // Read Timer
|
||||
,"1011": "COM " // Communicate
|
||||
,"2111": "IOR " // I/O Release
|
||||
,"2211": "HP2 " // Halt P2
|
||||
,"2411": "ZPI " // Conditional Halt
|
||||
,"3011": "SFI " // Store for Interrupt
|
||||
,"3411": "SFT " // Store for Test
|
||||
,"4111": "IP1 " // Initiate P1
|
||||
,"4211": "IP2 " // Initiate P2
|
||||
,"4411": "IIO " // Initiate I/O
|
||||
,"5111": "IFT " // Initiate For Test
|
||||
,"0115": "LNG " // Logical Negate
|
||||
,"0215": "LOR " // Logical OR
|
||||
,"0415": "LND " // Logical AND
|
||||
,"1015": "LQV " // Logical EQV (Equivalence)
|
||||
,"2015": "MOP " // Reset Flag Bit (Make Operand)
|
||||
,"4015": "MDS " // Set Flag Bit (Make Descriptor)
|
||||
,"0121": "CID " // Conditional Integer Store Destructive
|
||||
,"0221": "CIN " // Conditional Integer Store Non-Destructive
|
||||
,"0421": "STD " // B Store Destructive
|
||||
,"1021": "SND " // B Store Non-Destructive
|
||||
,"2021": "LOD " // Load
|
||||
,"4121": "ISD " // Integer Store Destructive
|
||||
,"4221": "ISN " // Integer Store Non-Destructive
|
||||
,"0125": "GEQ " // B Greater Than or Equal To A
|
||||
,"0225": "GTR " // B Greater Than A
|
||||
,"0425": "NEQ " // B Not Equal To A
|
||||
,"1025": "XCH " // Exchange
|
||||
,"1425": "FTC " // F Field To Core Field
|
||||
,"2025": "DUP " // Duplicate
|
||||
,"3425": "FTF " // F Field To F Field
|
||||
,"4125": "LEQ " // B Less Than or Equal To A
|
||||
,"4225": "LSS " // B Less Than A
|
||||
,"4425": "EQL " // B Equal To A
|
||||
,"5425": "CTC " // Core Field to C Field
|
||||
,"7425": "CTF " // Core Field To F Field
|
||||
,"0131": "BBC " // Branch Backward Conditional
|
||||
,"0231": "BFC " // Branch Forward Conditional
|
||||
,"0431": "SSN " // Set Sign Bit
|
||||
,"1031": "CHS " // Change Sign Bit
|
||||
,"2031": "TOP " // Test Flag Bit (Test Operand)
|
||||
,"2131": "LBC " // Branch Backward Word Conditional
|
||||
,"2231": "LFC " // Branch Forward Word Conditional
|
||||
,"2431": "TUS " // Interroage Peripheral Status
|
||||
,"4131": "BBW " // Branch Backward Unconditional
|
||||
,"4231": "BFW " // Branch Forward Unconditional
|
||||
,"4431": "SSP " // Reset Sign Bit
|
||||
,"6131": "LBU " // Branch Backward Word Unconditional
|
||||
,"6231": "LFU " // Branch Forward Word Unconditional
|
||||
,"6431": "TIO " // Interrogate I/O Channel
|
||||
,"7031": "FBS " // Stack Search For Flag
|
||||
,"0135": "BRT " // Branch Return
|
||||
,"0235": "RTN " // Return Normal
|
||||
,"0435": "XIT " // Exit
|
||||
,"1235": "RTS " // Return Special
|
||||
,"0141": "INX " // Index
|
||||
,"0241": "COC " // Construct Operand Call
|
||||
,"0441": "MKS " // Mark Stack
|
||||
,"1241": "CDC " // Construct Descriptor Call
|
||||
,"2141": "SSF " // F & S Register Set/Store
|
||||
,"2541": "LLL " // Link List Lookup
|
||||
,"4441": "CMN " // Enter Character Mode In-line
|
||||
,"XX45": "ISO " // Variable Field Isolate (XX45)
|
||||
,"0051": "DEL " // Delete
|
||||
,"X051": "CFN " // Branch Forward Non-Destructive (X051 or X451)
|
||||
,"X151": "CBN " // Branch Backward Non-Destructive (X151 or X551)
|
||||
,"X251": "CFD " // Branch Forward Destructive (X251 ot X651)
|
||||
,"X351": "CBD " // Branch Backward Destructive (X351 or X751)
|
||||
,"0055": "NOP " // No Operation (DIA 0)
|
||||
,"XX55": "DIA " // Dial A (XX55)
|
||||
,"0061": "VARI" // Set Full R-Relative Address Mode (DIB 0)
|
||||
,"XX61": "DIB " // Dial B (XX61)
|
||||
,"XX65": "TRB " // Transfer Bits (XX65)
|
||||
,"XX71": "FCL " // Compare Field Low (XX71)
|
||||
,"XX75": "FCE " // Compare Field Equal (XX75)
|
||||
};
|
||||
|
||||
var charOps = {
|
||||
"0000": "EXC " // Exit character mode
|
||||
,"0100": "CMX " // In-line character mode exit
|
||||
,"0002": "BSD " // Skip Bit Destination
|
||||
,"0003": "BSS " // Skip Bit Source
|
||||
,"0004": "RDA " // Recall Destination Address
|
||||
,"0005": "TRW " // Transfer Words
|
||||
,"0006": "SED " // Set Destination Address
|
||||
,"0007": "TDA " // Transfer Destination Address
|
||||
,"2411": "ZPI " // Conditional Halt
|
||||
,"3011": "SFI " // Store for Interrupt
|
||||
,"3411": "SFT " // Store for Test
|
||||
,"0012": "TBN " // Transfer Blank for Non-Numerics
|
||||
,"0014": "SDA " // Store Destination Address
|
||||
,"0015": "SSA " // Store Source Address
|
||||
,"0016": "SFD " // Skip Forward Destination
|
||||
,"0017": "SRD " // Skip Reverse Destination
|
||||
,"0022": "SES " // Set Source Address
|
||||
,"0024": "TEQ " // Test For Equal
|
||||
,"0025": "TNE " // Test For Not Equal
|
||||
,"0026": "TEG " // Test For Greater or Equal
|
||||
,"0027": "TGR " // Test For Greater
|
||||
,"0030": "SRS " // Skip Reverse Source
|
||||
,"0031": "SFS " // Skip Forward Source
|
||||
,"0032": "FSUX" // Field Subtract (AUX)
|
||||
,"0033": "FADX" // Field Add (AUX)
|
||||
,"0034": "TEL " // Test For Equal or Less
|
||||
,"0035": "TLS " // Test For Less
|
||||
,"0036": "TAN " // Test For Alphanumeric
|
||||
,"0037": "BIT " // Test Bit
|
||||
,"0040": "INC " // Increase Tally
|
||||
,"0041": "STC " // Store Tally
|
||||
,"0042": "SEC " // Set Tally
|
||||
,"0043": "CRF " // Call Repeat Field
|
||||
,"0044": "JNC " // Jump Out of Loop Conditional
|
||||
,"0045": "JFC " // Jump Forward Conditional
|
||||
,"0046": "JNS " // Jump Out of Loop
|
||||
,"0047": "JFW " // Jump Forward Unconditional
|
||||
,"0050": "RCA " // Recall Control Address
|
||||
,"0051": "ENS " // End Loop
|
||||
,"0052": "BNS " // Begin Loop
|
||||
,"0053": "RSA " // Recall Source Address
|
||||
,"0054": "SCA " // Store Control Address
|
||||
,"0055": "JRC " // Jump Reverse Conditional
|
||||
,"0056": "TSA " // Transfer Source Address
|
||||
,"0057": "JRV " // Jump Reverse Unconditional
|
||||
,"0060": "CEQ " // Compare Equal
|
||||
,"0061": "CNE " // Compare Not Equal
|
||||
,"0062": "CEG " // Compare Greater or Equal
|
||||
,"0063": "CGR " // Compare Greater
|
||||
,"0064": "BIS " // Set Bit
|
||||
,"0065": "BIR " // Reset Bit
|
||||
,"0066": "OCV " // Output Convert
|
||||
,"0067": "ICV " // Input Convert
|
||||
,"0070": "CEL " // Compare Equal or Less
|
||||
,"0071": "CLS " // Compare Less
|
||||
,"0072": "FSU " // Field Subtract
|
||||
,"0073": "FAD " // Field Add
|
||||
,"0074": "TRP " // Transfer Program Characters
|
||||
,"0075": "TRN " // Transfer Numerics
|
||||
,"0076": "TRZ " // Transfer Zones
|
||||
,"0077": "TRS " // Transfer Source Characters
|
||||
};
|
||||
|
||||
function $$(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
@@ -121,12 +278,128 @@ function padOctal(value, octades) {
|
||||
var text = value.toString(8);
|
||||
var len = text.length;
|
||||
|
||||
while (len++ < octades) {
|
||||
text = "0" + text;
|
||||
if (value >= 0) {
|
||||
while (len++ < octades) {
|
||||
text = "0" + text;
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function decodeSyllable(syllable, mode, level, msff) {
|
||||
/* Decodes the B5500 operator "syllable" and returns a string formatted with the mnemonic description of that syllable.
|
||||
"mode" indicates word (0) or character (1) mode.
|
||||
"level" indicates program (0) or subroutine (1) level.
|
||||
"msff" indicates whether MSFF is set (mark-stack pending) */
|
||||
var opcode = padOctal(syllable, 4);
|
||||
var text = opcode + " = ";
|
||||
var v;
|
||||
|
||||
function decodeRelativeAddress(value, level, msff) {
|
||||
var text;
|
||||
|
||||
if (!level) {
|
||||
text = "R+" + padOctal(value, 4);
|
||||
} else if (value < 512) {
|
||||
text = "R+" + padOctal(value, 3);
|
||||
} else if (value%512 < 256) {
|
||||
if (msff) {
|
||||
text = "[R+7].[18:32]+" + padOctal(value%256, 3);
|
||||
} else {
|
||||
text = "F+" + padOctal(value%256, 3);
|
||||
}
|
||||
} else if (value%256 < 128) {
|
||||
text = "C+" + padOctal(value%128, 3);
|
||||
} else {
|
||||
if (msff) {
|
||||
text = "[R+7].[18:32]-" + padOctal(value%256, 3);
|
||||
} else {
|
||||
text = "F-" + padOctal(value%256, 3);
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
if (mode) { // CHARACTER MODE
|
||||
v = syllable >>> 6;
|
||||
switch (syllable % 64) {
|
||||
case 0:
|
||||
if (v == 1) {
|
||||
text += charOps[opcode];
|
||||
} else {
|
||||
text += charOps["0000"];
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
text += wordOps[opcode];
|
||||
break;
|
||||
default:
|
||||
text += charOps[padOctal(syllable % 64, 4)] + " " + padOctal(v, 2) + " (" + v + ")";
|
||||
break;
|
||||
} // switch on lower half of char-mode syllable
|
||||
|
||||
} else { // WORD MODE
|
||||
switch (syllable % 4) {
|
||||
case 0: // LITC: literal call
|
||||
v = syllable >>> 2;
|
||||
text += wordOps["0000"] + " " + padOctal(v, 4) + " (" + v + ")";
|
||||
break;
|
||||
case 2: // OPDC: operand call
|
||||
v = syllable >>> 2;
|
||||
text += wordOps["0002"] + " " + padOctal(v, 4) + " (" +
|
||||
decodeRelativeAddress(v, level, msff) + ")";
|
||||
break;
|
||||
case 3: // DESC: descriptor call
|
||||
v = syllable >>> 2;
|
||||
text += wordOps["0003"] + " " + padOctal(v, 4) + " (" +
|
||||
decodeRelativeAddress(v, level, msff) + ")";
|
||||
break;
|
||||
case 1: // all other operators
|
||||
v = syllable >>> 6;
|
||||
switch (syllable % 64) {
|
||||
case 37: // XX45: ISO
|
||||
text += wordOps["XX45"] + " (" + ((v >>> 3)*6 - v%8) + ")";
|
||||
break;
|
||||
case 41: // XX51: DEL, CFN, CBN, CFD, CBD
|
||||
if (v == 0) {
|
||||
text += wordOps[opcode];
|
||||
} else {
|
||||
v = v >>> 2;
|
||||
text += wordOps["X" + padOctal(syllable & 0xFF, 3)] + " (" + v + ")";
|
||||
}
|
||||
break;
|
||||
case 45: // XX55: NOP, DIA
|
||||
if (v == 0) {
|
||||
text += wordOps[opcode];
|
||||
} else {
|
||||
text += wordOps["XX55"] + " (" + ((v >>> 3)*8 + v%8) + ")";
|
||||
}
|
||||
break;
|
||||
case 49: // XX61: VARI, DIB
|
||||
if (v == 0) {
|
||||
text += wordOps[opcode];
|
||||
} else {
|
||||
text += wordOps["XX61"] + " (" + ((v >>> 3)*8 + v%8) + ")";
|
||||
}
|
||||
break;
|
||||
case 53: // XX65: TRB
|
||||
text += wordOps["XX65"] + " (" + v + ")";
|
||||
break;
|
||||
case 57: // XX71: FCL
|
||||
text += wordOps["XX71"] + " (" + v + ")";
|
||||
break;
|
||||
case 61: // XX75: FCE
|
||||
text += wordOps["XX75"] + " (" + v + ")";
|
||||
break;
|
||||
default:
|
||||
text += wordOps[opcode];
|
||||
break;
|
||||
}
|
||||
} // switch on low-order syllable bits
|
||||
} // if mode
|
||||
return text;
|
||||
}
|
||||
|
||||
function displayOctal(id, value, octades) {
|
||||
/* Formats the "value" as octal of length "octades" and sets the "id".value
|
||||
property with the result */
|
||||
@@ -243,6 +516,13 @@ function displayMemory() {
|
||||
}
|
||||
}
|
||||
|
||||
function displaySyllable() {
|
||||
/* Decodes the syllable in the T register and formats it for display in the
|
||||
"TMnemonic" table cell */
|
||||
|
||||
setText("TMnemonic", decodeSyllable(cc.P1.T, cc.P1.SALF, cc.P1.MSFF));
|
||||
}
|
||||
|
||||
function displayRegisters() {
|
||||
/* Displays the non-stack processor registers */
|
||||
|
||||
@@ -253,6 +533,7 @@ function displayRegisters() {
|
||||
$$("PROF").checked = (cc.P1.PROF != 0);
|
||||
displayOctal("TReg", cc.P1.T, 4);
|
||||
$$("TROF").checked = (cc.P1.TROF != 0);
|
||||
displaySyllable();
|
||||
displayOctal("EReg", cc.P1.E, 2);
|
||||
displayOctal("IReg", cc.P1.I, 3);
|
||||
displayOctal("QReg", cc.P1.Q, 4);
|
||||
@@ -484,7 +765,12 @@ function initialize() {
|
||||
cc.P1.PROF = ff_onChange(ev);
|
||||
};
|
||||
$$("TReg").onchange = function(ev) {
|
||||
var next = cc.P1.C*4 + cc.P1.L - 1; // back up the auto-L increment
|
||||
|
||||
cc.P1.T = reg_onChange(ev);
|
||||
cc.P1.L = next%4;
|
||||
cc.P1.C = (next - cc.P1.L)/4;
|
||||
displaySyllable();
|
||||
};
|
||||
$$("TROF").onclick = function(ev) {
|
||||
cc.P1.TROF = ff_onChange(ev);
|
||||
@@ -827,9 +1113,10 @@ window.onload = function() {
|
||||
<input id=PROF name=PROF type=checkbox value=1><label for=PROF>PROF</label>
|
||||
<tr>
|
||||
<td class=center>T
|
||||
<td colspan=5>
|
||||
<td>
|
||||
<input id=TReg name=TReg type=text class=number size=4 maxlength=4>
|
||||
<input id=TROF name=TROF type=checkbox value=1><label for=TROF>TROF</label>
|
||||
<td id=TMnemonic colspan=4>
|
||||
<tr>
|
||||
<td class=center>E
|
||||
<td>
|
||||
|
||||
Reference in New Issue
Block a user