// MICRO Word Accumulation
// last edited July 7, 1980 9:19 AM
// Copyright Xerox Corporation 1979, 1980
get "micdecl.d"
external // O.S.
[ MoveBlock; SetBlock; Zero
]
// Static storage
// DO NOT REORDER, see mempush and mempop
static
[ awstk // chain word
aword // word being assembled
awused // bits already stored into
awmem // current memory
awxlb // listing buffer or 0
awflag // true if any stores done
awloc // current location
awtep // location counter ep
]
manifest
[ lasr = 8
]
let clraw(ep) be
// Clear Assembled Word
[ if awmem ne 0 then
[ let nb = awmem!mswidth
let nw = (nb+15) rshift 4
if awxlb ne 0 then Zero(awxlb, nb)
MoveBlock(aword, awmem!msdflt + fstop, nw)
Zero(awused, nw)
awmem!msltag = 0
]
awflag = false
awtep = ep
awloc = ep!asval
]
and initacc() be
//Initialize accumulator
[ awmem = 0
awstk = 0
clraw(0)
if targsym ne 0 then targset(targsym+fstop)
]
and produce() be
// Produce assembled word
[ if awloc ge awmem!mssize then
[ errx("STORE OUT OF RANGE TO @V IN @S",false,awloc,awmem)
return
]
wword(aword,awmem,awloc)
if awxlb ne 0 then
[ let opt = awmem!mslist
if (opt & LFany) ne 0 then
lstword(aword,awxlb,awmem,awloc,opt)
]
awtep = adef(awtep,awmem,awloc+1)
]
and stfield(ep,val,set) be
// Store val into field with name ep. Message if something is
// field already, value too big for field, or field too big
// for memory.
test awmem eq 0
ifso errx("NO TARGET FOR FIELD SET",true)
ifnot
[ let n = ep!fsbits
let bitno = n rshift 8
n = n & #377
test bitno+n gr awmem!mswidth ifso
errx("FIELD @S DOES NOT FIT IN MEMORY @S",false,ep,awmem)
ifnot test (val rshift n) ne 0 ifso
errx("VALUE @V DOES NOT FIT IN FIELD @S",false,val,ep)
ifnot
[ let used = getbits(awused, bitno, n)
test set
ifso
test (used ne 0) & ((getbits(aword, bitno, n)&used) ne (val&used))
ifso
errx("FIELD @S ALREADY SET",false,ep)
ifnot
[ setbits(awused, bitno, n, -1)
setbits(aword,bitno,n,val)
]
ifnot
if used ne (1 lshift n)-1 then
setbits(aword, bitno, n, (used eq 0? val,
(getbits(aword, bitno, n)&used)+(val¬ used)))
]
awflag = true
if awxlb ne 0 then awxlb!bitno = ep
]
and gtfield(ep) = valof
test awmem eq 0
ifso errx("NO TARGET FOR 'FVAL'", true)
ifnot resultis getbits(aword, ep!fsbits rshift 8, ep!fsbits & #377)
and mempush(mem) be
// Push current accumulator
[ if awmem ne 0 then
[ let rp = alloc(lasr)
MoveBlock(rp, lv awstk, lasr)
awstk = rp
]
awmem = mem
let nb = awmem!mswidth
let nw = (nb+15) rshift 4
aword = alloc(nw)
awused = alloc(nw)
awxlb = (xlistflag & ((awstk eq 0) % (ltoflag eq false))? alloc(nb), 0)
]
and mempop() be
// Pop old accumulator
[ if awmem ne 0 then
[ if awxlb ne 0 then dalloc(awxlb) // LIFO works best
dalloc(awused)
dalloc(aword)
]
test awstk ne 0
ifso
[ let rp = awstk
MoveBlock(lv awstk, rp, lasr)
dalloc(rp)
]
ifnot
[ awmem = 0
awflag = false
]
]
and targset(ep) be
// Set target address
test awstk ne 0
ifso errx("'TARGET' NOT LEGAL INSIDE STORE",true)
ifnot
[ if awflag then errx("'TARGET' GIVEN AFTER FIELD SET",true)
mempop()
mempush(ep!asmem + fstop)
clraw(ep)
targsym = ep-fstop
]
and aldef(ep) be
// Define Label
[ if ep eq 0 then ep = putin(awmem-fstop)
ep = adef(ep,awmem,awloc)
if awstk eq 0 then
[ lbsym = ep
lblct = stlct
]
]
and assem() be
// Assemble top level word
[ if awmem ne 0 then clraw(awtep)
pr1(accmode,false)
if awflag then
[ if awmem!mspost ne 0 then apost(awmem)
produce()
]
]
and auref(fep,ep) be
// Write undefined reference
test awtep eq 0
ifso errx("UNDEFINED SYMBOL @S IN 'DEFAULT'",false,ep)
ifnot
[ wfixup(awmem,awloc,fep,ep)
awflag = true
]
and aused(ep) =
// Test if field has been set
0 ne getbits(awused, ep!fsbits rshift 8, ep!fsbits & #377)
and dosta(ep, ap, l) be
// Store builtin
[ let mem = ep!asmem + fstop
mempush(mem)
clraw(ep)
process(ap,l,accmode)
if mem!mspost ne 0 then apost(mem)
produce()
mempop()
]
and defaultbi(mem,ap,l) be
// Default Builtin
[ mempush(mem)
clraw(0)
process(ap,l,accmode)
MoveBlock((mem!msdflt)+fstop,aword,((awmem!mswidth)+15) rshift 4)
mempop()
]
and setlfbi(mem, ap, l) be
// Set list fields builtin
[ mempush(mem)
clraw(0)
process(ap, l, accmode)
let map = mem!mslfields+fstop
let mw = mem!mswidth
let bn = 0
while bn ne mw do
[ let bn1 = bn
[ bn = bn+1 ] repeatuntil (bn eq mw) % (getbits(aword, bn-1, 1) ne 0)
@map = bn-bn1
map = map+1
]
mempop()
]
and apost(mem) be
// Do the post-macro for memory mem
[ let old = tlbot
@sttop = endc // set end mark
sttop = sttop+1
mcall(mem!mspost+fstop, 0)
pr1(accmode, false)
tlbot = old
]