//D0TYPEIN.BCPL -- alternate keyboard input procedures for converting // command line to DVec's for memories and registers // Last edited: 19 October 1981 get "d0.d" manifest [ get "d0regmem.d" ] structure [ String↑0,100 byte ] external [ // OS Zero // MIDAS MidasSwat // MASM ResetsCSS; ResetsCS1; @WssCSS; WssCS1; PutsCSS; PutsCS1 PutField; SymbKeyComp; MaskT // MIOC SimpleTexttoDVec // MCMD ErrorAbort // D0ASM stNotInVM // D0VM LookUpAA; @VirtualP // Defined here InstructionIn; WrdBytIn ] //Accepts "nnn,,nnn" or "nnnnnn" input forms and evaluates for storage //into 16-bit DVec. let WrdBytIn(X,AVec,DVec,TV,Radix) be [ let TV0,TV1 = vec 80,vec 80 TV0!0,TV1!0 = 0,0 let GotComma1,GotComma2 = false,false for I = 1 to TV!0 do [ let C = TV!I test C ne $, ifso [ if GotComma1 then unless GotComma2 do ErrorAbort() test GotComma2 ifso [ TV1!0 = TV1!0+1; TV1!(TV1!0) = C ] ifnot [ TV0!0 = TV0!0+1; TV0!(TV0!0) = C ] ] ifnot test GotComma2 ifso ErrorAbort() ifnot test GotComma1 ifso GotComma2 = true ifnot GotComma1 = true ] let V0,V1 = vec 1,vec 1 unless SimpleTexttoDVec(TV0,16,V0,Radix) do ErrorAbort() test GotComma2 ifso [ unless SimpleTexttoDVec(TV1,16,V1,Radix) do ErrorAbort() DVec!0 = (V0!0 lshift 8)+(V1!0 & #377) ] ifnot DVec!0 = V0!0 ] //AVec is 0 for registers //This is called for IM, IMX, MIM, and sometimes MDATA (when IMX has been //tested). and InstructionIn(X,AVec,DVec,TV,Radix) be [ //Valid input syntax for field names is "LLL←nnn". FVec is array of //three-word entries with names in first word, bit1 in 2nd word, nbits //in 3rd word. let FVec = table [ //Both kinds of instructions have these fields 0; 2; 4 //RSEL--**kludge for this field which is split** 0; 25; 6 //JA--**kludge for this field which is split** 0; 0; 1 //MEMINST 0; 18; 4 //F2 0; 22; 3 //JC //Regular instructions have these fields 0; 1; 1 //RMOD 0; 6; 4 //ALUF 0; 10; 2 //BSEL 0; 12; 4 //F1 0; 16; 1 //LR 0; 17; 1 //LT //Memory instructions have these fields 0; 1; 1 //DF2 0; 6; 4 //TYPE 0; 10; 8 //SRCDEST ] FVec!0 = "RSEL" FVec!3 = "JA" FVec!6 = "MI" FVec!9 = "F2" FVec!12 = "JC" FVec!15 = "RMOD" FVec!18 = "ALUF" FVec!21 = "BSEL" FVec!24 = "F1" FVec!27 = "LR" FVec!30 = "LT" FVec!33 = "DF2" FVec!36 = "TYPE" FVec!39 = "SRCDEST" //Stuff for branch conditions let BCtab = table [ 0; 0; 0 //ALU#0, ALU=0 0; 0; 1 //CARRY, CARRY' 0; 0; 2 //ALU<0, ALU>=0 0; 0; 3 //H2BIT8', H2BIT8 0; 0; 4 //R<0, R>=0 0; 0; 5 //RODD, REVEN 0; 0; 6 //IOATTN', IOATTN 0; 0; 7 //MB,MB' 0; 0; #100000 //INTPENDING,INTPENDING' 0; 0; #100001 //OVF', OVF 0; 0; #100002 //BPCCHK, BPCCHK' 0; 0; #100003 //SPARE, SPARE' 0; 0; #100004 //QW0, QW0' 0; 0; #100005 //TIMEOUT, TIMEOUT' ] BCtab!0 = "ALU#0" BCtab!1 = "ALU=0" BCtab!3 = "CARRY" BCtab!4 = "CARRY'" BCtab!6 = "ALU<0" BCtab!7 = "ALU>=0" BCtab!9 = "H2BIT8'" BCtab!10 = "H2BIT8" BCtab!12 = "R<0" BCtab!13 = "R>=0" BCtab!15 = "RODD" BCtab!16 = "REVEN" BCtab!18 = "IOATTN'" BCtab!19 = "IOATTN" BCtab!21 = "MB" BCtab!22 = "MB'" BCtab!24 = "INTPENDING" BCtab!25 = "INTPENDING'" BCtab!27 = "OVF'" BCtab!28 = "OVF" BCtab!30 = "BPCCHK" BCtab!31 = "BPCCHK'" BCtab!33 = "SPARE" BCtab!34 = "SPARE'" BCtab!36 = "QW0" BCtab!37 = "QW0'" BCtab!39 = "TIMEOUT" BCtab!40 = "TIMEOUT'" //Standalone clauses are in OVec (currently only "RETURN"). let OVec = vec 1 OVec!0 = "RETURN" //Other evaluations are of the form "LLL[nnn]" let PVec = vec 4 PVec!0 = "GOTO" PVec!1 = "CALL" PVec!2 = "GOTOP" PVec!3 = "CALLP" //"[" = start with no-op //"(" = start with old value switchon TV!1 into [ //Start with no-op: MI←0, RMOD←0, RSEL←0, ALUF←0, BSEL←2, F1←10, //F2←12, LR←0, LT←0, JC←4, JA←0 case $[: DVec!0 = #000010; DVec!1 = #025000; DVec!2 = DVec!2 & #7777 //Start with current microinstruction case $(: endcase case $?: ResetsCSS(); ResetsCS1() WssCSS("X←n for X =") for I = 0 to 39 by 3 do [ PutsCSS($ ); WssCSS(FVec!I) ] PutsCSS($,) for I = 0 to 0 do [ if I ne 0 then PutsCS1($*S) WssCS1(OVec!I) ] WssCS1(", X[va] for X =") for I = 0 to 3 do [ PutsCS1($*S); WssCS1(PVec!I) ] WssCS1(", or X[va,bc] for X = GOTO GOTOP") ErrorAbort("") default: ErrorAbort() ] let P = 2 until P > TV!0 do [ let SVec = vec 40 //Collect next token in SVec, terminator in Y let Y = CollectAD(SVec,lv P,TV) switchon Y into [ //Invalid string default: ErrorAbort() //Separators case -1: case $I-100B: case $]: case $,: case $ : if (SVec!0 rshift 8) eq 0 then loop //Standalone clauses terminated by separators for I = 0 to 0 do if SymbKeyComp(SVec,OVec!I) eq 0 do [ switchon I into [ case 0: PutField(22,3,DVec,6); endcase default: MidasSwat(OVecBug) ] endcase ] ErrorAbort() //Field names are terminated by "←" case $←: for I = 0 to 39 by 3 do if SymbKeyComp(SVec,FVec!I) eq 0 then [ let Bit1 = FVec!(I+1); let NBits = FVec!(I+2) let XNBits = (I ne 0) & (I ne 3) ? NBits,NBits+2 let N = CollectO(XNBits,TV,lv P,Radix) if N eq -1 then break test I eq 0 ifso //RSEL kludge [ PutField(32,2,DVec,N & 3) N = (N xor #60) rshift 2 ] ifnot if I eq 3 do //JA kludge [ PutField(34,2,DVec,N rshift 6) N = N & #77 ] PutField(Bit1,NBits,DVec,N) endcase ] ErrorAbort() case $[: if (SVec!0 rshift 8) eq 0 then loop for I = 0 to 3 do if SymbKeyComp(SVec,PVec!I) eq 0 then [ Y = CollectAD(SVec,lv P,TV) //Here compute: // ThisAA = absolute address of this mi needed for on-page checks. // ThisDot = "." for ".+n" and ".-n" expressions; this will be a VA for // IM, AA for IMX, or undefined for MIM. // DotVA = true if ThisDot is virtual, else false. let ThisAA = selecton X into [ case IMx: DVec!3 & #7777 case IMXx: AVec!1 case MIMx: DVec!2 & #7777 default: -1 //MDATA ] let ThisDot = selecton X into [ case IMx: case IMXx: case MIMx: AVec!1 default: -1 ] let DotVA = X eq IMx ? true,false let OffPageOK = I ge 2 let N = ConvertToBA(SVec,Radix,ThisAA,ThisDot,DotVA,OffPageOK) let JC = nil test (I eq 0) % (I eq 2) ifso //GOTO or GOTOP [ test Y eq $, ifso //Branch condition [ Y = CollectAD(SVec,lv P,TV) let Match,Inverted = false,0 if (N & 1) eq 0 then Inverted = 1 N = N & #376 for K = 0 to 39 by 3 do [ test SymbKeyComp(SVec,BCtab!(K+Inverted)) eq 0 ifso [ Match = true let bcstuff = BCtab!(K+2) if bcstuff < 0 then PutField(18,4,DVec,#10) JC = (bcstuff rshift 1) & 3 N = N+(bcstuff & 1) break ] ifnot if SymbKeyComp(SVec, BCtab!(K+(Inverted xor 1))) eq 0 then ErrorAbort("BC inverted for target") ] if not Match then ErrorAbort("Bad BC") ] ifnot JC = 4 ] ifnot //Call [ JC = 5 ] if Y ne $] then break PutField(22,3,DVec,JC) PutField(34,2,DVec,(N & #377) rshift 6) PutField(25,6,DVec,N & #77) endcase ] ErrorAbort() ] ] ] //Collect alphadecimal string ("+", "-", ".", "@", and "$" also string //constituents) in SVec, return terminator or -1 if terminated by //end-of-string. and CollectAD(SVec,lvP,TV) = valof [ let P = rv lvP let X,C = 0,-1 while P le TV!0 do //Build the string [ C = TV!P; P = P+1 if (C < $@ % C > $Z) & (C < $0 % C > $9) & (C ne $+) & (C ne $-) & (C ne $.) & (C ne $$) then break X = X+1; SVec>>String↑X = C C = -1 //End-of-string char ] rv lvP = P; SVec!0 = (SVec!0 & #377)+(X lshift 8); resultis C ] //Collect octal number < NBits in size and CollectO(NBits,TV,lvP,Radix) = valof [ let TV1 = vec 80; TV1!0 = 0 let Value,P,X = 0,rv lvP,0 while P le TV!0 do [ let C = TV!P; P = P+1 if (C eq $,) % (C eq $ ) % (C eq $]) then break X = X+1; TV1!X = C ] TV1!0 = X rv lvP = P let DVec = vec 4 resultis SimpleTexttoDVec(TV1,16,DVec,Radix) ? DVec!0 & (MaskT!NBits),-1 ] //Return absolute address of branch target after error-checking. and ConvertToBA(SVec,Radix,ThisAA,ThisDot,DotVA,OffPageOK) = valof [ let TV2,N,M = vec 80,0,0 let SB = "Branch target " for J = 0 to SVec!0 rshift 8 do TV2!J = SVec>>String↑J //Allow ".+n" and ".-n" args if (TV2!0 ge 1) & (TV2!1 eq $.) do [ test ThisDot < 0 ifso ErrorAbort(SB,". not allowed for this memory") ifnot [ TV2!1 = TV2!0-1; TV2 = TV2+1; N = ThisDot ] ] if TV2!0 ge 1 then unless SimpleTexttoDVec(TV2,16,lv M,Radix) do ErrorAbort(SB,"unevaluable") N = N+M if ThisDot ge 0 do [ if DotVA do [ N = LookUpAA(N) if N < 0 then ErrorAbort(SB,stNotInVM) ] if not OffPageOK then if ((N xor ThisAA) & #177400) ne 0 then ErrorAbort(SB,"off page") ] resultis N ]