//D1TYPEIN.BCPL -- alternate keyboard input procedures for converting
// command line to DVec's for memories and registers
// Last edited: 17 December 1979
get "d1.d"
manifest [ get "d1regmem.d" ]
manifest [ get "d1instrs.d" ]
structure [ String↑0,100 byte ]
external [
// OS
Zero
// MASM
PutField; SymbKeyComp; MaskT
ResetsCSS; ResetsCS1; @WssCSS; WssCS1; PutsCSS; PutsCS1
// MIOC
SimpleTexttoDVec
// MCMD
ErrorAbort
// D1ASM
stNotInVM
// D1MEM
MGetMemData
// D1VM
LookUpAA; @VirtualP
// Defined here
WrdBytIn; InstructionIn
]
//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>>rh)
]
ifnot DVec!0 = V0!0
]
//X is IMXx, IMx, MIRx, IMBDx, LDRx, or sometimes MDATAx
//AVec is 0 for registers
and InstructionIn(X,AVec,DVec,TV,Radix) be
[ let ThisAddr = selecton X into
[ case IMx: DVec!3 & #7777
case IMXx:
case IMBDx: AVec!1
default: -1
]
//Last entry in Bit1Tab is used only for NBits computation
let Bit1Tab = table [ 0; 4; 8; 11; 14; 17; 18;
26; 34; 35; 36; 50; 51; 52; 64 ]
//Valid input syntax for field names is "LLL←nnn". FVec is array of
//field names. Standalone clauses are in OVec (currently only "RETURN").
//Other evaluations are of the form "LLL[nnn]"
let FVec,OVec,PVec = vec 14,vec 1,vec 7
FVec!0 = "RSTK"
FVec!1 = "ALUF"
FVec!2 = "BSEL"
FVec!3 = "LC"
FVec!4 = "ASEL"
FVec!5 = "BLOCK"
FVec!6 = "FF"
FVec!7 = "JCN"
FVec!8 = "PE020"
FVec!9 = "PE2141"
//Next four only allowed on X eq IMx
FVec!10 = "z"
FVec!11 = "EMUL"
//Made these two illegal
// FVec!12 = "UNDEF"
// FVec!13 = "AT"
OVec!0 = "RETURN"
//For IM, IMX, and IMBD, ThisAddr is known so automatic determination
//of global, local, or long forms, and "GOTO", "CALL", and "BRANCH"
//are translatable; for others ThisAddr unknown, so only "LONGGO",
//"GO", and "GCALL" forms are translatable.
PVec!0 = "LONGGO"
PVec!1 = "GO"
PVec!2 = "GCALL"
PVec!3 = "IFUJUMP"
PVec!4 = "GOTO"
PVec!5 = "CALL"
PVec!6 = "BRANCH"
switchon TV!1 into
[
case $[: MGetMemData(LDRx,DVec,table [ 0; NOOP/4 ] )
//"[" = start with NOOP
case $(: endcase //"(" = start with old val
case $?: ResetsCSS(); ResetsCS1()
WssCSS("X←n for X =")
for I = 0 to 9 do
[ PutsCSS($ ); WssCSS(FVec!I)
]
if X eq IMx then for I = 10 to 11 do
[ WssCS1(FVec!I); PutsCSS($ )
]
WssCS1("or")
for I = 0 to 0 do
[ PutsCS1($ ); WssCS1(OVec!I)
]
WssCS1(" or X[va] for X =")
for I = 0 to 2 do
[ PutsCS1($ ); WssCS1(PVec!I)
]
if ThisAddr > 0 then for I = 4 to 6 do
[ PutsCS1($ ); WssCS1(PVec!I)
]
WssCS1(" or IFUJUMP[n]")
ErrorAbort("")
default: ErrorAbort()
]
let P = 2
until P > TV!0 do
[ let SVec = vec 40
let Y = CollectAD(SVec,lv P,TV)
let N = nil
switchon Y into
[
//Invalid string
default: ErrorAbort()
//Separators
case $I-100B:
case $]:
case $,:
case $ : if SVec>>lh 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(26,8,DVec,107B); endcase
]
endcase
]
ErrorAbort()
//Field names are terminated by "←"
case $←: for I = 0 to (X eq IMx ? 11,9) do
if SymbKeyComp(SVec,FVec!I) eq 0 then
[ let Bit1 = Bit1Tab!I; let NBits = Bit1Tab!(I+1)-Bit1
N = CollectO(NBits,TV,lv P,Radix)
if N eq -1 then break
PutField(Bit1,NBits,DVec,N); endcase
]
ErrorAbort()
case $[: if SVec>>lh eq 0 then loop
for I = 0 to 6 do
if SymbKeyComp(SVec,PVec!I) eq 0 then
[ if (I > 3) & (ThisAddr < 0) then
ErrorAbort(SVec,
" illegal because instruction address unknown")
Y = CollectAD(SVec,lv P,TV)
//***Should handle "," and branch conditions here***
if Y ne $] then break
let IFJump = I eq 3
N = ConvertToBA(SVec,Radix,ThisAddr,IFJump)
switchon I into
[
//Long
case 0: PutField(18,8,DVec,N rshift 4)
PutField(26,8,DVec,N & 17B); endcase
//Local
case 1: if ThisAddr ne -1 do
[ if ((N xor ThisAddr) & 37700B) ne 0 then
ErrorAbort("target not on page")
]
PutField(26,8,DVec,(N & 77B)+200B); endcase
//Global
case 2: if (N & 77B) ne 0 then
ErrorAbort("target not global")
PutField(26,8,DVec,(N rshift 6)+300B)
endcase
//IFUJump
case 3: if (N & #177774) ne 0 then
ErrorAbort("IFUJUMP arg > 3")
PutField(26,8,DVec,(N lshift 3)+47B)
endcase
//GOTO
case 4: if (N & #17) eq 0 then
ErrorAbort("GOTO arg at call location")
docase(6)
//CALL
case 5: if (N & #17) ne 0 then
ErrorAbort("CALL arg at goto location")
//BRANCH
case 6: test (N & #77) eq 0
ifso docase(2)
ifnot test ((N xor ThisAddr) & #37700) eq 0
ifso docase(1)
ifnot docase(0)
]
endcase
]
ErrorAbort()
]
]
return
]
//Collect alphadecimal string in SVec, return terminator
//("+" and "-" also string constituents)
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
]
rv lvP = P; SVec>>lh = X; 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
if SimpleTexttoDVec(TV1,16,DVec,Radix) then
resultis DVec!0 & (MaskT!NBits)
resultis -1
]
//Convert the text in SVec to an absolute branch address
and ConvertToBA(SVec,Radix,ThisAddr,IFJump) = valof
[ let TV2,N,M = vec 80,0,0
let SB = "branch target "
for J = 0 to SVec>>lh do TV2!J = SVec>>String↑J
//Allow ".+n" and ".-n" args
if (ThisAddr ge 0) & (TV2!0 ge 1) & (TV2!1 eq $.) do
[ TV2!1 = TV2!0-1; TV2 = TV2+1; N = ThisAddr
]
if TV2!0 ge 1 then unless SimpleTexttoDVec(TV2,16,lv M,Radix) do
ErrorAbort(SB,"unevaluable")
N = N+M
if (ThisAddr ge 0) & not IFJump do
[ if VirtualP do
[ N = LookUpAA(N)
if N < 0 then ErrorAbort(SB,stNotInVM)
]
]
resultis N
]