// BNCG4.bcpl - BCPL Compiler // Nova Code Generator, Instruction generation routines // Copyright Xerox Corporation 1980 // Last modified on Sat 28 Oct 72 0246.15 by jec. get "bncgx" let CGlda(reg, arg) be [ CGmemref(Ilda + (reg lshift 11), arg) ] and CGsta(reg, arg) be [ CGmemref(Ista + (reg lshift 11), arg) ] and CGmemref(op, arg) be [ let addr = 0 test ref!arg ne 0 then [ unless type!arg eq XR do [ let a = vec argsize-1 type!a, ref!a, loc!a, name!a = type!arg, 0, loc!arg, name!arg CGlda(X, a) ] if (ref!arg & #100000) ne 0 do addr = addr + Ideferbit addr = addr + (X lshift 8) + (ref!arg & #377) ] or switchon type!arg into [ case RVNUMBER: if (loc!arg & #177400) eq 0 do [ addr = addr + loc!arg endcase ] if (not SWAlto)&(loc!arg & #177400) eq #100000 do [ addr = addr + (loc!arg & #377) + Ideferbit endcase ] addr = addr + Ideferbit case NUMBER: addr = addr + (R lshift 8) + CGconst(Nconst, loc!arg, name!arg) endcase case RVLOCAL: addr = addr + Ideferbit case LOCAL: addr = addr + (P lshift 8) + Bval(loc!arg + SSPoffset) if loc!arg gr MaxSSP do CGreport(1) endcase case LABEL: addr = addr + Ideferbit case LVLABEL: addr = addr + (R lshift 8) + CGconst(Lconst, loc!arg, name!arg) endcase case RVLABEL: if SWAlto do CGreport(-99) addr = addr + Ideferbit + (R lshift 8) + CGconst(Dconst, loc!arg, name!arg) endcase case LVCOMMON: addr = addr + (R lshift 8) + CGconst(Zconst, loc!arg, name!arg) endcase case RVCOMMON: addr = addr + Ideferbit case COMMON: addr = addr + (Z lshift 8) + CGzchain(loc!arg) endcase default: CGreport(-3) ] CG(op + addr) unless SWCode return if ref!arg ne 0 return test (addr & Ideferbit) eq 0 then WriteS(" ") or test type!arg eq LABEL then WriteS(" ") or WriteS(" @") WW($() switchon type!arg into [ case RVNUMBER: case NUMBER: if name!arg ne 0 do [ WriteName(name!arg); WriteS(" = ") ] WW($#); WriteOct(loc!arg) endcase case RVLOCAL: case LOCAL: test name!arg eq 0 then [ WriteS("TEMP") WriteOct(loc!arg) ] or WriteName(name!arg) endcase case LVLABEL: WriteS("lv ") case RVLABEL: case LABEL: WriteName(name!arg) endcase case LVCOMMON: WriteS("lv ") case RVCOMMON: case COMMON: WriteName(name!arg) endcase ] WW($)) ] and CGjumpandsave() be [ if SWAlto & (type!arg1 eq RVCOMMON & ref!arg1 eq 0) do // @<common> becomes <common>!0 on Alto // (CGrv() already does this for non-common <static> ) [ type!arg1 = COMMON ref!arg1 = #40000 ] if SWNoxios & SWAlto & (type!arg1 ne XR & ref!arg1 eq #40000) do // @<static> or <simple-expression>!0 on Alto should generate // JSRII temp,2 for Noxios. [ ref!arg1 = 0 //remove the indirection unless type!arg1 eq LOCAL do CGstoreintemp(arg1) //store in frame type!arg1 = RVLOCAL //restore the indirection ] unless ref!arg1 eq 0 do // Other complex things are done normally [ CGrv() CGmemref(Ijsr, arg1) return ] if type!arg1 eq RVNUMBER & (loc!arg1 & #177400) eq 0 do // @<constant page-zero address> is special [ CGmemref(Ijsr+Ideferbit, arg1) return ] unless SWAlto & (type!arg1 eq RVNUMBER % type!arg1 eq LABEL % (SWNoxios & type!arg1 eq RVLOCAL)) do // Unless we can do a JSRII, do it normally // (JSRII .+n for any Alto if <static> or <constant> // JSRII n,2 for Noxios only) [ CGrv() CGmemref(Ijsr, arg1) return ] let op = type!arg1 eq RVLOCAL ? Ajsr2, Ajsr1 let addr = type!arg1 eq LABEL ? CGconst(Lconst, loc!arg1, name!arg1), type!arg1 eq RVNUMBER ? CGconst(Nconst, loc!arg1, name!arg1), loc!arg1 CG(op+addr) if SWCode do [ WriteS(" @(") unless name!arg1 eq 0 do [ WriteName(name!arg1); WW($*s) ] if type!arg1 eq RVNUMBER do [ WW($#); WriteOct(loc!arg1) ] WW($)) ] ] and CGmakememref(arg) be [ if type!arg eq AC do CGreport(-9) if ref!arg ne 0 do unless type!arg eq XR do [ let r = ref!arg ref!arg = 0 CGloadxr(arg) ref!arg = r ] ] and CGae(op, reg1, reg2) be [ reg1 = reg1 lshift 13 reg2 = reg2 lshift 11 CG(op + reg1 + reg2) ] and CGconst(ctype, cdata, cname) = valof [ let p = 0 while p ls ctablep do [ if ctypetable!p eq ctype & cdatatable!p eq cdata do unless (caddrtable!p & #100000) eq 0 & PC - caddrtable!p ge #200 break p = p + 1 ] test p eq ctablep then [ ctypetable!p = ctype cdatatable!p = cdata caddrtable!p = PC + #100000 cnametable!p = cname ctablep = ctablep + 1 if ctablep ge ctablesize do CGreport(-5) constcount = constcount + (ctype eq Jconst ? 2, 1) if constreflimit gr PC do constreflimit = PC resultis 0 ] or test (caddrtable!p & #100000) eq 0 then [ resultis Bval(caddrtable!p - PC) ] or [ let pc = caddrtable!p & #77777 [ if PassTwo break let t = Code!pc & #377 if t eq 0 break pc = pc + Wval(t) ] repeat unless PassTwo do Code!pc = (Code!pc & #177400) + Bval(PC - pc) resultis 0 ] ] and CGoutconstants(n) be [ if constcount eq 0 return if n eq 0 do n = PCparameter let l = PC + constcount + 1 + n constreflimit = #77777 let firstconst = true let p = 0 while p ls ctablep do [ if (caddrtable!p & #100000) ne 0 do [ let pc = caddrtable!p & #77777 if l - pc le #177 - Cparameter do [ if constreflimit gr pc do constreflimit = pc p = p + 1; loop ] [ if PassTwo break let t = Code!pc & #377 Code!pc = (Code!pc & #177400) + Bval(PC - pc) if t eq 0 break pc = pc + Wval(t) ] repeat caddrtable!p = PC if SWCode & firstconst do WriteS("*n*n*t// literals //*n") firstconst = false test ctypetable!p eq Nconst then [ CGn(cdatatable!p) if SWCode do [ WriteS(" = ") if cnametable!p ne 0 do [ WriteName(cnametable!p); WriteS(" = ") ] WW($#); WriteOct(cdatatable!p) ] ] or test ctypetable!p eq Lconst then [ CGn(CGlchain(cdatatable!p)) if SWCode do [ WriteS(" = "); WriteName(cnametable!p) ] ] or test ctypetable!p eq Dconst then [ CGn(CGlchain(cdatatable!p) + #100000) if SWAlto do CGreport(-98) if SWCode do [ WriteS(" ="); WW($@); WriteName(cnametable!p) ] ] or test ctypetable!p eq Zconst then [ CGn(CGzchain(cdatatable!p)) if SWCode do [ WriteS(" = "); WriteName(cnametable!p) ] ] or test ctypetable!p eq Jconst then [ CG(Ilongjump) if SWCode do [ WriteS(" = LONGJUMP to LAB") WriteOct(plabdefvec!(cdatatable!p)) ] CGn(CGpchain(cdatatable!p)) ] or CGreport(-4) constcount = constcount - (ctypetable!p eq Jconst ? 2, 1) ] p = p + 1 ] if SWCode do WW($*n) p = 0 while (caddrtable!p & #100000) eq 0 & PC - caddrtable!p gr #200 do p = p + 1 unless p eq 0 do [ for q = p to ctablep-1 do [ ctypetable!(q-p) = ctypetable!q cdatatable!(q-p) = cdatatable!q caddrtable!(q-p) = caddrtable!q cnametable!(q-p) = cnametable!q ] ctablep = ctablep - p ] ] and CGcheckconstants(n) be [ if constcount eq 0 return if constreflimit eq #77777 do CGreport(-6) if n eq 0 do n = PCparameter let l = PC + constcount + 1 + n if l - constreflimit le #177 return let pc = PC CG(Ijmp + (R lshift 8) + 0) CGoutconstants(n) unless PassTwo do Code!pc = Code!pc + Bval(PC - pc) ] and CGjmp(l) be [ if PassTwo do [ if -#200 le (plabdefvec!l - PC) & (plabdefvec!l - PC) le #177 do Code!PC = (Code!PC & #177400) + Bval(plabdefvec!l - PC) ] test pchainvec!l ne 0 & (pchainvec!l & #100000) eq 0 & PC-pchainvec!l le #200 then [ CG(Ijmp + (R lshift 8) + Bval(pchainvec!l - PC)) ] or [ CG(Ijmp + (R lshift 8) + CGconst(Jconst, l, 0)) ] if SWCode do WriteLabel(l) ] and CGtest(skip, ac1, ac2, l) be [ CGae(skip, ac1, ac2) if SWCode do WriteSkip(Code!(PC-1)) CGjmp(l) ] and CGlabdef(l) be [ if pchainvec!l ne 0 & (pchainvec!l & #100000) ne 0 do [ unless PassTwo do [ let pc = pchainvec!l & #77777 [ let t = Code!pc Code!pc = Nval(PC - pc) if t eq 0 break pc = t ] repeat ] ] pchainvec!l = PC plabdefvec!l = PC if constcount eq 0 return let p = 0 while p ls ctablep do [ if ctypetable!p eq Jconst & cdatatable!p eq l do if (caddrtable!p & #100000) ne 0 do [ let pc = caddrtable!p & #77777 [ if PassTwo break let t = Code!pc & #377 Code!pc = (Code!pc & #177400) + Bval(PC - pc) if t eq 0 break pc = pc + Wval(t) ] repeat ctablep = ctablep - 1 for q = p to ctablep - 1 do [ ctypetable!q = ctypetable!(q+1) cdatatable!q = cdatatable!(q+1) caddrtable!q = caddrtable!(q+1) cnametable!q = cnametable!(q+1) ] constcount = constcount - 2 constreflimit = #77777 for q = 0 to ctablep-1 do [ if (caddrtable!q & #100000) eq 0 loop if (caddrtable!q & #77777) ls constreflimit do [ constreflimit = caddrtable!q & #77777 ] ] break ] p = p + 1 ] ] and CGpchain(l) = valof [ if pchainvec!l eq 0 do [ pchainvec!l = PC+ #100000 resultis 0 ] if (pchainvec!l & #100000) ne 0 do [ let pc = pchainvec!l & #77777 pchainvec!l = PC + #100000 resultis pc ] resultis Nval(pchainvec!l - PC) ] and CGlchain(l) = valof [ let pc = lchainvec!l lchainvec!l = PC resultis pc ] and CGzchain(l) = valof [ if lchainvec!l eq 0 do [ lchainvec!l = PC + #100000 resultis 0 ] let n = PC - (lchainvec!l & #77777) if n le #377 do [ lchainvec!l = PC + #100000 resultis n ] PCmax = PCmax - 2 if PCmax le PC do CGreport(0) zlabelt = zlabelt + 1 Code!PCmax = l Code!(PCmax+1) = lchainvec!l lchainvec!l = PC + #100000 resultis 0 ] and CGrv() be [ unless type!arg1 eq AC do [ if ref!arg1 eq 0 do switchon type!arg1 into [ case LVLABEL: type!arg1 = LABEL; return case LVCOMMON: type!arg1 = COMMON; return case NUMBER: type!arg1 = RVNUMBER; return case LOCAL: type!arg1 = RVLOCAL; return case COMMON: type!arg1 = RVCOMMON; return case LABEL: test SWAlto then ref!arg1 = #40000 or type!arg1 = RVLABEL return default: ] if (ref!arg1 & #140000) eq #40000 do [ ref!arg1 = ref!arg1 + #100000; return ] ] CGstoreintemp(arg1) type!arg1 = RVLOCAL ] and CGsubscr(j) be [ if j eq 0 do if type!arg1 eq NUMBER do if (loc!arg1 & #177600) eq 0 % (loc!arg1 & #177600) eq #177600 do [ let i = (loc!arg1 & #377) + #40000 if ref!arg2 eq 0 do switchon type!arg2 into [ case RVLABEL: if SWAlto do CGreport(-97) case RVNUMBER: case LOCAL: case RVLOCAL: case LVLABEL: case LABEL: case LVCOMMON: case COMMON: case RVCOMMON: Pop1() ref!arg1 = i return case NUMBER: [ let a = loc!arg1 + loc!arg2 if SWAlto % (a & #100000) eq 0 do [ Pop1() type!arg1 = RVNUMBER loc!arg1 = a return ] ] default: ] CGloadxr(arg2) Pop1() ref!arg1 = i return ] test type!arg2 eq AC then [ CGloadxr(arg1) CGae(Iadd, loc!arg2, X) ] or [ CGloadac(arg1) CGloadxr(arg2) CGae(Iadd, loc!arg1, X) ] Pop2() Push(XR, (j eq 0 ? #40000, j), X) ]