// 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)
  ]