// BNCG3.bcpl - BCPL Compiler
// Nova Code Generator, Stack and Register maintainance routines
// Copyright Xerox Corporation 1980
// Last modified on Fri 27 Oct 72 2202.15 by jec.
get "bncgx"
let Initstack(ssp) be
[ arg3 = argvec; arg2 = arg3 + argsize; arg1 = arg2 + argsize
SSP = ssp
Setarg(arg3, LOCAL, 0, SSP-3, SSP-3, 0)
Setarg(arg2, LOCAL, 0, SSP-2, SSP-2, 0)
Setarg(arg1, LOCAL, 0, SSP-1, SSP-1, 0)
]
and Push(t, r, l) be
[ arg3 = arg2; arg2 = arg1; arg1 = arg1 + argsize
if arg1 ge argvec + argvecsize do CGreport(2)
Setarg(arg1, t, r, l, SSP, 0)
SSP = SSP + 1
]
and SetName(n) be
[ name!arg1 = n
]
and Pop1() be
[ SSP = SSP - 1
test arg3 eq argvec
then [ Setarg(arg1, type!arg2, ref!arg2, loc!arg2, pos!arg2, name!arg2)
Setarg(arg2, type!arg3, ref!arg3, loc!arg3, pos!arg3, name!arg3)
Setarg(arg3, LOCAL, 0, SSP-3, SSP-3 , 0)
]
or [ arg1 = arg2; arg2 = arg3; arg3 = arg3 - argsize
]
]
and Pop2() be [ Pop1(); Pop1() ]
and Setarg(arg, t, r, l, p, n) be
[ type!arg, ref!arg, loc!arg, pos!arg, name!arg = t, r, l, p, n
]
and Copyarg(arga, argb) be
[ Setarg(argb, type!arga, ref!arga, loc!arga, pos!arga, name!arga)
]
and SetSSP(ssp) be
[ if ssp eq SSP return
test ssp ls SSP
then while ssp ls SSP do
[ if arg3 eq argvec & ssp ls SSP-3 do
[ Initstack(ssp); break ]
Pop1()
]
or while ssp gr SSP do
[ if ssp gr SSP+3 do
[ Clearstack(ssp-1); Initstack(ssp); break ]
Push(LOCAL, 0, SSP)
]
]
and Clearstack(ssp) be
[ let arg = argvec
until arg gr arg1 % pos!arg gr ssp do
[ CGstoreintemp(arg)
arg = arg + argsize
]
]
and freeac() = valof
[ let arg = argvec
let a1, a2 = 0, 0
until arg gr arg1 do
[ if type!arg eq AC do
test a1 eq 0 then a1 = arg or
test a2 eq 0 then a2 = arg or
CGreport(-2)
arg = arg + argsize
]
if a2 eq 0 do
test a1 eq 0 then resultis 0 or resultis (loc!a1 eq 0 ? 1, 0)
let ac = loc!a1
CGstoreintemp(a1)
resultis ac
]
and Clearac(ac) be
[ let arg = argvec
until arg gr arg1 do
[ if type!arg eq AC & loc!arg eq ac do
[ CGstoreintemp(arg); return ]
arg = arg + argsize
]
]
and CGload(reg, arg) be
[ test type!arg eq NUMBER
then [ let n = loc!arg
test n eq 0 then [ CGae(Isub, reg, reg)
if SWCode do WriteS(" (0)")
] or
test n eq 1 then [ CGae(Isubzl, reg, reg)
if SWCode do WriteS(" (1)")
] or
test n eq #100000 then [ CGae(Isubzr, reg, reg)
if SWCode do WriteS(" (100000)")
] or
test n eq #177777 then [ CGae(Iadc, reg, reg)
if SWCode do WriteS(" (177777)")
] or
test n eq #177776 then [ CGae(Iadczl, reg, reg)
if SWCode do WriteS(" (177776)")
] or
test n eq #077777 then [ CGae(Iadczr, reg, reg)
if SWCode do WriteS(" (77777)")
] or
CGlda(reg, arg)
]
or [ CGlda(reg, arg)
]
type!arg, ref!arg, loc!arg = (reg eq X ? XR, AC), 0, reg
]
and CGstore(reg, arg) be
[ CGsta(reg, arg)
]
and CGstoreintemp(arg) be CGstoreintempN(arg, pos!arg)
and CGstoreintempN(arg, N) be
[ if type!arg eq LOCAL & ref!arg eq 0 & loc!arg eq N return
CGloadreg(arg)
let ac = loc!arg
type!arg, ref!arg, loc!arg, name!arg = LOCAL, 0, N, 0
CGstore(ac, arg)
]
and CGloadac(arg) be
[ unless type!arg eq AC do CGload(freeac(), arg)
]
and CGloadreg(arg) be
[ unless type!arg eq AC do CGload(X, arg)
]
and CGloadxr(arg) be
[ test type!arg eq AC
then CGae(Imov, loc!arg, X)
or CGload(X, arg)
type!arg, ref!arg, loc!arg = XR, 0, X
]
and CGloadac0(arg) be
[ test type!arg eq AC
then unless loc!arg eq 0 do
[ Clearac(0)
CGae(Imov, loc!arg, 0)
loc!arg = 0
]
or [ Clearac(0)
CGload(0, arg)
]
]
and CGloadac1(arg) be
[ test type!arg eq AC
then unless loc!arg eq 1 do
[ Clearac(1)
CGae(Imov, loc!arg, 1)
loc!arg = 1
]
or [ Clearac(1)
CGload(1, arg)
]
]
and CGload01() be
[ if type!arg2 eq AC & type!arg1 eq AC do
[ unless loc!arg2 eq 0 & loc!arg1 eq 1 do
[ CGae(Imov, 0, X)
CGae(Imov, 1, 0)
CGae(Imov, X, 1)
]
loc!arg2, loc!arg1 = 0, 1
return
]
test type!arg1 eq AC
ifnot [ CGloadac0(arg2); CGloadac1(arg1) ]
ifso [ CGloadac1(arg1); CGloadac0(arg2) ]
]
and CGloadboth() be
[ CGloadac(arg2)
CGloadac(arg1)
]