// BNCG2.bcpl - BCPL Compiler -- Nova Code Generator, Pure stream processor
// Copyright Xerox Corporation 1980
//   Last modified on Wed 01 Nov 72 0041.49 by  jec.
//   Swinehart, 5-10-77: fast getframe, return -- docase exp
//  Paxton, 9-14-78: unsigned compares

// last modified by Butterfield, May 30, 1979  4:32 PM
// - ScanPures ENTRY:, CG(Iifsgetframe) if SWStackStrings - 5/30
// - ScanPures END:, ENTRY:, and  ENDFRAME:; SWStackStrings - 5/9/79

get "bncgx"

let ScanPures() be
 [pures
Next:
  let Op = Readop()
Continue:
  CGcheckconstants(0)
  switchon Op into
    [items
default:
[ Op = CGothers(Op)
  test Op eq -1 then goto Next or goto Continue
]

case END:
[ CGoutconstants(#200)
  if SWNoxios do
	if (PC & #1) ne 0 do
	 [ CGn(0)
	   if SWCode do WriteS("//force code to be an even length")
	 ]
  if SWCode do WriteS("*n")
  if SWStackStrings ne 0 & SWStackStrings ne -1 then CGreport(-5203);
  return
]

case PLINE:
[ Curline = ReadN()
  if SWList do
     [ if SWCode do [ WW($*n); WW($*n) ]
        WriteLine(Curline)
     ]
  goto Next
]

case LINE:
[ Curline = ReadN()
  goto Next
]

case WSUB:
case BSUB:
case NQUAL:
case WQUAL:
case XQUAL:
case WBQUAL:
case STNQUAL:
case STWQUAL:
case STXQUAL:
case STWBQUAL:
case YQUAL:
case STYQUAL:
[ Op = CGqual(Op)
  test Op eq -1 then goto Next or goto Continue
]

case PLUS:
[ Op = CGplus(Op)
  test Op eq -1 then goto Next or goto Continue
]

case MINUS:	CGsub(); goto Next
case MULT:	CGmul(); goto Next
case DIV:	CGdiv(); goto Next
case REM:	CGrem(); goto Next
case LSHIFT:	CGlsh(); goto Next
case RSHIFT:	CGrsh(); goto Next
case LOGAND:	CGand(); goto Next
case LOGOR:	CGior(); goto Next
case EQV:	CGeqv(); goto Next
case NEQV:	CGxor(); goto Next
case NEG:	CGneg(); goto Next
case NOT:	CGnot(); goto Next

case EQ:
case NE:
case LS:
case LE:
case GR:
case GE:
case ULS:
case ULE:
case UGR:
case UGE:
[ Op = CGrel(Op)
  test Op eq -1 then goto Next or goto Continue
]

case JT:
case JF:
[ Clearstack(SSP-2)
  CGloadreg(arg1)
  CGtest((Op eq JT ? Iseq0, Isne0), loc!arg1, loc!arg1, ReadL())
  Pop1()
  goto Next
]

case JUMP:
[ Clearstack(SSP-1)
  CGjmp(ReadL())
  CGoutconstants(0)
  goto Next
]

case LAB:
[ Clearstack(SSP-1)
  Initstack(SSP)
  CGlabdef(ReadL())
  LabelDef = true
  goto Next
]

case GOTO:
[ Clearstack(SSP-2)
  CGjumpandsave()
  Pop1()
  Initstack(SSP)
  CGoutconstants(0)
  goto Next
]

case STACK:
[ SetSSP(ReadN())
  goto Next
]

case STORE:
[ Clearstack(SSP-1)
  Initstack(SSP)
  goto Next
]

case SWITCHLOAD:
[ Clearstack(SSP-2) // store temps
  CGloadac0(arg1) // switchon index
  CGcheckconstants(#200)
  Initstack(SSP-1)
  goto Next ] 

case SWITCHON:
[ CGswitch()
  goto Next
]

case FINISH:
[ CG(Ifinish)
  if SWCode do WriteS("   (FINISH)")
  CGoutconstants(0)
  goto Next
]

case ABORT:
[ CG(Iabort)
  if SWCode do WriteS("   (ABORT)")
  CGoutconstants(0)
  goto Next
]

case RTCALL:
case FNCALL:
case PARAM:
case RTAP:
case FNAP:
[ Op = CGcall(Op)
  test Op eq -1 then goto Next or goto Continue
]


case ENTRY:
case LENTRY:
[ let l = ReadL()
  let m = ReadL()
  Clearstack(SSP-1)
  Initstack(SSP)
  if SWNoxios do
	if (PC & #1) ne 0 do
	 [  CG(Ijmp + (R lshift 8) + 1)
	    if SWCode do WriteS("// force even address for static label*n")
	 ]
  elabelvec!l = m; eaddrvec!l = PC
  unless Op eq ENTRY goto Next
  if MaxSSP ls 0 then CGreport(-5201);
  if SWStackStrings gr 0 then
   [ SWStackStrings = not SWStackStrings; MaxSSP = not MaxSSP; ]
  framestack!framestackp = MaxSSP
  framestack!(framestackp+1) = MaxVecSSP
  framestackp = framestackp + 2
  MaxSSP, MaxVecSSP = ReadN(), ReadN()
  if MaxSSP ls framespacemin do
    MaxSSP = framespacemin	//leave frame space for header+two args
				//  since first 2 args are stored always
  if SWCode do
    [	WriteS("// frame size is ")
	WriteOct(MaxSSP+MaxVecSSP); WriteS(" words (")
	WriteOct(MaxSSP); WW($+); WriteOct(MaxVecSSP); WW($))
    ]


  Push(LOCAL, 0, SSPtemp1)
  test SWFastFrame then // issue microcode getframe call?
	[
	CG(SWFastFrame) // switch contains microcode trap instr.
	if SWCode do WriteS(" Fast stack frame allocation call")
	]
   or
  	[
	CGstore(X, arg1)
  	if SWCode do WriteS(" of last frame is the return address")
	]
  Pop1()

  test SWStackStrings
    ifso [ CG(Iifsgetframe); if SWCode do WriteS("   (IFS GETNEWFRAME)") ]
    ifnot [ CG(Igetframe); if SWCode do WriteS("   (GETNEWFRAME)") ]
  CGn(MaxSSP + MaxVecSSP)

  CG(Istoreargs)
  if SWCode do WriteS("   (STOREARGS) if more than 3")

  Op = Readop()
  unless Op eq SAVE do CGreport(-14)
  Initstack(ReadN())

  Op = Readop()
  unless Op eq NUMARGS goto Continue

  Push(LOCAL, 0, SSP); SetName(ReadL())
  CGstore(0, arg1)
  if SWCode do WriteS(" is NUMARGS")
  goto Next
]

case ENDFRAME:
[ 
  if SWStackStrings gr 0 then
     [
     let n = 0; let pc = SWStackStrings;
     until pc le 0 do
      [ n = n+1; if pc gr Codelimit then pc = pc - Codelimit; pc = Code!pc; ]
     if n ge 128 then CGreport(-5202);
     let i = 0;
     until SWStackStrings le 0 do
        [
        i = i + 1; pc = SWStackStrings; let tableFlag = 0; 
        if pc gr Codelimit then [ pc = pc - Codelimit; tableFlag = #200; ]
        SWStackStrings = Code!pc; Code!pc = n lshift 8 + tableFlag + i;
        ]
     ]
  framestackp = framestackp - 2
  MaxSSP, MaxVecSSP = framestack!framestackp, framestack!(framestackp+1)
  if MaxSSP ls 0 then
   [ SWStackStrings = not SWStackStrings; MaxSSP = not MaxSSP; ]
  goto Next
]

case RTRN:
case FNRN:
[ if Op eq FNRN do [ CGloadac0(arg1); Pop1() ]
  CG(SWFastFrame? SWFastFrame+#400, Ireturn) // procedure call or fast op-code
  if SWCode do WriteS("   (RETURN)")
  CGoutconstants(0)
  Clearstack(SSP-1)
  Initstack(SSP)
  goto Next
]

case RES:
[ Clearstack(SSP-2)
  CGloadac0(arg1)
  Pop1()
  CGjmp(ReadL())
  if SWCode do WriteS("(RESULT IN AC0)")
  CGoutconstants(0)
  goto Next
]

case RSTACK:
[ SetSSP(ReadN())
  Push(AC, 0, 0)
  goto Next
]
     ]items

  ]pures