mirror of
https://github.com/DoctorWkt/unix-jun72.git
synced 2026-04-11 23:12:59 +00:00
the s1-bits tape. Doug has provided as11.s as12.s as13.s as14.s as15.s as16.s as17.s as18.s as19.s as21.s as22.s as23.s as24.s as25.s as26.s as27.s as28.s as29.s, and Warren has compared against his production, and against V5 (to determine the correct trailing blank line). These files can be considered authentic. The other file's are Warren's production only, so we need to compare against Doug's versions to ensure correctness.
373 lines
5.4 KiB
ArmAsm
373 lines
5.4 KiB
ArmAsm
/
|
|
/
|
|
/ here to allocate a new block
|
|
/
|
|
/ mov ...,r0
|
|
/ jsr pc,allocate
|
|
/ mov r1,...
|
|
/
|
|
/ requested size in bytes in r0
|
|
/ pointer to header of allocated block returned in r1
|
|
/ r0 is preserved
|
|
/
|
|
/ convert to words, adjust for header, round up
|
|
/ to a power of two
|
|
/
|
|
/ each block has a four-word header
|
|
/ W - write ptr (also used as link ptr in frlist)
|
|
/ R - read ptr
|
|
/ A - pointer to head of data
|
|
/ L - ptr to (end+1) of data
|
|
W=0
|
|
R=2
|
|
A=4
|
|
L=6
|
|
/
|
|
allocate:
|
|
clr garbage
|
|
mov r0,-(sp)
|
|
mov r2,-(sp)
|
|
tst stats
|
|
bne 1f
|
|
jsr pc,init
|
|
1:
|
|
inc stats
|
|
bne 9f; inc stats; 9:
|
|
cmp r0,$strend-strbuf
|
|
blo 9f; 4; 9:
|
|
1:
|
|
sub $1,r0
|
|
bmi 1f
|
|
jsr pc,log2
|
|
add $1,r0
|
|
1: asl r0 /bite to word
|
|
mov r0,-(sp)
|
|
add $2,r0
|
|
cmp r0,$frend-frlist+2
|
|
blo zzz
|
|
4
|
|
/
|
|
/ look on free list for block of required size
|
|
/
|
|
zzz:
|
|
mov (sp),r0
|
|
tst frlist(r0)
|
|
beq xxx
|
|
/
|
|
/ found it, allocate and return
|
|
/
|
|
mov frlist(r0),r1
|
|
mov (r1),frlist(r0)
|
|
mov a(r1),r0
|
|
mov r0,w(r1) /W
|
|
mov r0,r(r1) /R
|
|
tst (sp)+
|
|
mov (sp)+,r2
|
|
mov (sp)+,r0
|
|
rts pc
|
|
/
|
|
/ no block of required size
|
|
/ look for larger block
|
|
/
|
|
xxx:
|
|
tst frlist-2
|
|
beq www
|
|
tst (r0)+
|
|
cmp r0,$frend-frlist
|
|
bhis www
|
|
tst frlist(r0)
|
|
bne yyy
|
|
br xxx
|
|
/
|
|
/ there are no larger blocks; must garbage collect
|
|
/
|
|
www: jsr pc,collect
|
|
tst r0
|
|
bne zzz
|
|
/
|
|
/ out of space
|
|
/
|
|
mov $1,r0
|
|
sys write; 1f; 2f-1f
|
|
sys exit
|
|
1: <Out of space.\n>
|
|
2: .even
|
|
/
|
|
/ split larger block into two smaller pieces and
|
|
/ link together as smaller blocks in the free list.
|
|
/
|
|
yyy:
|
|
mov frlist(r0),r1
|
|
mov (r1),frlist(r0)
|
|
mov hdrptr,r2
|
|
beq www
|
|
mov (r2),hdrptr
|
|
clr (r2)
|
|
mov r2,(r1)
|
|
mov r1,frlist-2(r0)
|
|
mov l(r1),l(r2)
|
|
mov l(r1),r0
|
|
sub a(r1),r0
|
|
asr r0
|
|
add a(r1),r0
|
|
mov r0,l(r1)
|
|
mov r0,a(r2)
|
|
br zzz
|
|
/
|
|
/
|
|
/ here to release a block
|
|
/
|
|
/ mov ...,r1
|
|
/ jsr pc,release
|
|
/
|
|
/ pointer to block in r1
|
|
/
|
|
release:
|
|
/
|
|
/ discover that this is a plausible pointer
|
|
/
|
|
mov r0,-(sp)
|
|
jsr pc,preposterous
|
|
/
|
|
/ find free list index and link block to that entry
|
|
/
|
|
inc stats+2
|
|
mov frlist(r0),(r1)
|
|
clr r(r1)
|
|
mov r1,frlist(r0)
|
|
clr r1 /self-defense
|
|
mov (sp)+,r0
|
|
rts pc
|
|
/
|
|
/
|
|
/ jsr pc,collect
|
|
/
|
|
/ coalesce free storage by rejoining paired blocks
|
|
/ on the free list.
|
|
/ zero is returned in r0 if no paired blocks were found.
|
|
/
|
|
collect:
|
|
mov r1,-(sp)
|
|
mov r2,-(sp)
|
|
mov r3,-(sp)
|
|
mov r4,-(sp)
|
|
clr useful
|
|
inc stats+4.
|
|
clr r0 /start with smallest blocks
|
|
/r0 contains frlist index
|
|
loop1: mov $frlist,r1
|
|
add r0,r1
|
|
/
|
|
/ try next list member at this level
|
|
/
|
|
loop2: mov (r1),r3
|
|
beq advance /list is empty
|
|
tst *(r1) /W
|
|
beq advance /only one list element
|
|
/
|
|
/ calculate address of buddy
|
|
/
|
|
mov a(r3),r4
|
|
sub $strbuf,r4
|
|
bit exp2(r0),r4
|
|
beq 2f
|
|
bic exp2(r0),r4
|
|
br 1f
|
|
2: bis exp2(r0),r4
|
|
1: add $strbuf,r4
|
|
/
|
|
/ and search for him
|
|
/
|
|
loop3: tst 0(r3)
|
|
beq nocoal
|
|
mov (r3),r2
|
|
cmp a(r2),r4
|
|
beq coal
|
|
mov (r3),r3
|
|
br loop3
|
|
/
|
|
/ have found a pair; remove both blocks from list,
|
|
/ coalesce them, and put them on next higher list
|
|
/
|
|
coal: inc useful
|
|
mov (r3),r4
|
|
mov (r4),(r3) /remove him from list
|
|
mov (r1),r2
|
|
mov (r2),(r1) /remove the other one
|
|
cmp a(r2),a(r4)
|
|
bgt 1f
|
|
mov r2,-(sp)
|
|
mov r4,r2
|
|
mov (sp)+,r4
|
|
1: add exp2(r0),l(r4)
|
|
clr r(r4)
|
|
mov frlist+2(r0),(r4)
|
|
mov r4,frlist+2(r0)
|
|
mov frlist-2,(r2)
|
|
mov r2,frlist-2
|
|
clr r(r2)
|
|
mov $strbuf,a(r2)
|
|
mov $strbuf,l(r2)
|
|
br loop2
|
|
/
|
|
/ no buddy found, try next block on this list
|
|
/
|
|
nocoal:
|
|
mov (r1),r1
|
|
br loop2
|
|
/
|
|
/ advance to next free list
|
|
/
|
|
advance:
|
|
tst (r0)+
|
|
cmp r0,$frend-frlist
|
|
blo loop1
|
|
mov useful,r0
|
|
/
|
|
/ do we have enough headers to continue?
|
|
/
|
|
tst garbage
|
|
beq 1f
|
|
mov $1,r0
|
|
sys write; 4f; 5f-4f
|
|
sys exit
|
|
/
|
|
4: <Out of headers.\n>
|
|
5: .even
|
|
/
|
|
/
|
|
/ restore registers and return
|
|
/
|
|
1:
|
|
inc garbage
|
|
mov (sp)+,r4
|
|
mov (sp)+,r3
|
|
mov (sp)+,r2
|
|
mov (sp)+,r1
|
|
rts pc
|
|
/
|
|
garbage: .=.+2
|
|
/
|
|
/ routine to find integer part of log2(x)
|
|
/
|
|
/ jsr pc,log2
|
|
/
|
|
/ r0 = log2(r0)
|
|
/
|
|
log2:
|
|
mov r0,-(sp)
|
|
bge 9f; 4; 9:
|
|
mov $15.,r0
|
|
1:
|
|
rol (sp)
|
|
bmi 1f
|
|
sob r0,1b
|
|
1:
|
|
dec r0
|
|
tst (sp)+
|
|
rts pc
|
|
/
|
|
0 /Don't move me, I'm exp(-1)
|
|
exp2:
|
|
1;2;4;10;20;40;100;200;400;1000;2000;4000;
|
|
10000;20000;40000;100000
|
|
/
|
|
/ routine to discover whether r1 points to
|
|
/ a plausible header - to avoid ruination.
|
|
/
|
|
/ r1 is preserved and r0 gets a suitable index for frlist
|
|
/
|
|
/ jsr pc,preposterous
|
|
/
|
|
preposterous:
|
|
cmp r1,$headers
|
|
bhis 9f; 4; 9:
|
|
cmp r1,$headend
|
|
blo 9f; 4; 9:
|
|
cmp a(r1),$strbuf /A
|
|
bhis 9f; 4; 9:
|
|
cmp l(r1),$strend /L
|
|
blos 9f; 4; 9:
|
|
mov l(r1),r0 /L
|
|
sub a(r1),r0 /A
|
|
mov r0,-(sp)
|
|
jsr pc,log2
|
|
asl r0
|
|
cmp exp2(r0),(sp)
|
|
beq 9f; 4; 9:
|
|
add $2,r0
|
|
cmp r0,$frend-frlist+2
|
|
blo 9f; 4; 9:
|
|
sub $2,r0
|
|
mov r0,(sp)
|
|
mov frlist(r0),r0
|
|
1: beq 1f
|
|
cmp r0,r1
|
|
bne 9f; 4; 9:
|
|
mov (r0),r0
|
|
br 1b
|
|
1: mov (sp)+,r0
|
|
rts pc
|
|
/
|
|
/
|
|
/ routine to initialize storage area, headers and
|
|
/ free list upon first call to allocate a block.
|
|
/ The entire storage area is formed into a single block.
|
|
/
|
|
init:
|
|
mov r0,-(sp)
|
|
mov r1,-(sp)
|
|
/
|
|
/ form all the headers into a single list.
|
|
/
|
|
mov $headers,r0
|
|
mov r0,frlist-2
|
|
1: add $8,r0
|
|
mov r0,-8(r0)
|
|
cmp r0,$headend-8
|
|
blos 1b
|
|
clr -8(r0)
|
|
mov $frlist,r0
|
|
1: clr (r0)+
|
|
cmp r0,$frend
|
|
blo 1b
|
|
/
|
|
mov frlist-2,r1
|
|
mov (r1),frlist-2
|
|
clr w(r1)
|
|
mov $strbuf,r0
|
|
mov r0,a(r1)
|
|
mov $strend-strbuf,r0
|
|
jsr pc,log2
|
|
asl r0
|
|
cmp r0,$frend-frlist
|
|
blo 9f; 4; 9:
|
|
mov r1,frlist(r0)
|
|
mov exp2(r0),r0
|
|
add $strbuf,r0
|
|
mov r0,l(r1)
|
|
mov $frlist-2,r1
|
|
1: mov (r1),r1
|
|
tst r1
|
|
beq 1f
|
|
mov $strbuf,a(r1)
|
|
mov $strbuf,l(r1)
|
|
br 1b
|
|
1:
|
|
mov (sp)+,r1
|
|
mov (sp)+,r0
|
|
rts pc
|
|
/
|
|
/
|
|
.bss
|
|
stats: .=.+16.
|
|
useful: .=.+2
|
|
hdrptr: .=.+2 /do not move me
|
|
frlist: .=hdrptr+32.
|
|
frend:
|
|
headers:.=hdrptr+512.
|
|
headend:
|
|
strbuf: .=.+4000
|
|
strend:
|
|
end:
|