//P R E U T I L
// utilities for PreScan pass

//outgoing procedures
external [ DoubleMult;GetExternalFile;EqStr;Rotor;Rotor8
	  ]

//incoming procedures
external
 [ DoubleAdd;DoubleCop;DblShift
 ]

//incoming statics
external [ ExternalFileList
	   ]

structure str :
 [ n		byte
   ch↑1,128	byte
 ]

let DoubleMult(dp, n) be
 [
   let sum=vec 1
   sum!0=0; sum!1=0
   while n do
     [
      if (n&1) ne 0 then DoubleAdd(sum, dp)
      n=n rshift 1
      DblShift(dp,-1)
     ]
   DoubleCop(dp, sum)
 ]

and GetExternalFile(name)=valof
 [ if ExternalFileList eq 0 then resultis 0//nothing declared
   let extName=ExternalFileList
   until extName!0 eq 0 do
    [ let nameLen=(extName!0 rshift 9)+1
      if EqStr(name,extName) then resultis extName+nameLen+1
      let xLen=extName!nameLen
      extName=extName+nameLen+1+xLen
    ] 
   resultis 0
 ]
and EqStr(n1,n2)=valof
 [ unless n1!0 eq n2!0 then resultis false
   for i=2 to n1>>str.n do 
      unless n1>>str.ch↑i eq n2>>str.ch↑i then resultis false
   resultis true
 ]

//Rotor(p)
// p=> a page of 16 16*16 bit squares.  All are rotated!
// ***** This routine to be in microcode *****

and Rotor(Page) be
 [
   let masktable=table [ 0;#125252;#146314;0;#170360;0;0;0;#177400]

   for square=1 to 16 do
    [
     let Pstep=8
       [
         let mask1=masktable!Pstep
         let mask2=not mask1
	let i=0		// Simulate for i=0 to 15 by Pstep*2 
	while i le 15 do
          [
           let j=Pstep-1
             [
	      let Word=Page+i+j
	      let Word2=Word+Pstep
	      let t1=Word!0
	      let t2=Word2!0

	      Word!0=(t1&mask1)+((t2 rshift Pstep)&mask2)

	      Word2!0=(t2&mask2)+((t1 lshift Pstep)&mask1)
	      j=j-1
             ] repeatuntil j ls 0
	   i=i+Pstep+Pstep
           ]
         Pstep=Pstep rshift 1
       ] repeatuntil Pstep eq 0
     Page=Page+16
    ]
 ]

//rotation used for 8 bit intensity sample files
and Rotor8(page) be
 [ manifest [ HighBits=#177400 ; LowBits=#377 ]

   let SwapHalves=table
    [ #101300		//MOVS 0,0
      #001401		//JMP 1,3
    ]

   //first, do the 2x2 byte swaps
   for y=0 to 15*8 by 2*8 do
    [ let y1=y+8
      for p=page to page+7 do
       [ let w1=p!y
	 let w2=p!y1
	 p!y=(w1&HighBits)+(SwapHalves(w2)&LowBits)
	 p!y1=(SwapHalves(w1)&HighBits)+(w2&LowBits)
       ]
    ]

   //now, reposition these 2x2 to form the correct 16x16
   for y=0 to 7 do
    [ let py16=page+y*16
      let py=page+y
      let p8y=py+8
      let p8y16=py16+8

      for x=y+1 to 7 do
       [ let x16=x*16

	 let t=py16!x
	       py16!x=py!x16
		       py!x16=t

	 t=p8y16!x
	   p8y16!x=p8y!x16
		     p8y!x16=t
       ]
    ]

 ]