; MDasm -- assembly language utilities
; last edited December 12, 1979  1:21 PM

	.titl MDasm

	.ent AndBlock
	.ent CountBits
	.ent FirstBitPos
	.ent Get1Bit
	.ent MakeRunMask
	.ent Set1Bit

	.srel

AndBlock:	.andb
CountBits:	.cbits
Get1Bit:	.g1bit
FirstBitPos:	.fbitpos
MakeRunMask:	.mrm
Set1Bit:	.s1bit

; Bcpl frame
	link=1
	temp=2
	arg3=3

	.nrel


; AndBlock(base, len) = valof
;[	let m = -1
;	for i = 0 to len-1 do m = m & base!i
;	resultis m
;]

.andb:
	sta 3 link,2
	mov 0 3
	sta 1 temp,2
	adc 0 0
.andb1:
	lda 1 0,3
	and 1 0
	inc 3,3
	dsz temp,2
	  jmp .andb1
	lda 3 link,2
	jmp 1,3


; CountBits(wd) = valof
;[	let n = 0
;	while wd ne 0 do n, wd = n+1, (wd-1) & wd
;	resultis n
;]

.cbits:
	sta 3 link,2
	sub 1 1
	jmp .cb2
.cb1:
	inc 1 1
	com 3 3	; ac3 ← ac0-1
	and 3 0
.cb2:
	neg 0 3 szr
	  jmp .cb1
	lda 3 link,2
	mov 1 0
	jmp 1,3


; FirstBitPos(wd) = valof
;[	let firstBitTab = table[ -16; 4; 3;3; 2;2;2;2; 1;1;1;1;1;1;1;1;
;	  0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0 ]
;	resultis (wd ls 0? 0,
;	 wd ge 2000b? firstBitTab!(wd rshift 10) + 1,
;	 wd ge 40b? firstBitTab!(wd rshift 5) + 6,
;	 firstBitTab!wd + 11)
;]

.mask10:	177400
.c10:	10
.mask4:	170000
.c4:	4
.fbitpos:
	sta 3 link,2
	sub 1 1
	lda 3 .mask10
	and# 3 0 szr
	  jmp .fb1
	lda 1 .c10
	movs 0 0
.fb1:
	lda 3 .mask4
	and# 3 0 szr
	  jmp .fb2
	lda 3 .c4
	add 3 1
	addzl 0 0
	addzl 0 0
.fb2:
	movl 0 0 szc
	  jmp .fbr0
	movl 0 0 szc
	  jmp .fbr1
	movl 0 0 snc
	  inc 1 1
	inc 1 1
.fbr1:
	inc 1 0 skp
.fbr0:
	mov 1 0
	lda 3 link,2
	jmp 1,3


; Get1Bit(base, bitpos) =
;	(base!(bitpos rshift 4) lshift (bitpos&17b)) rshift 15

c177760:	177760
c17:	17
.g1bit:
	sta 3 link,2
	lda 3 c177760
	andzr 1 3
	movzr 3 3
	movzr 3 3
	movzr 3 3
	add 0 3
	lda 0 0,3
	lda 3 c17
	and 3 1
	cycle 0
	movzl 0 0	; put bit into carry
	subcl 0 0	; move carry to bit 15
	lda 3 link,2
	jmp 1,3


;MakeRunMask(mask, len) = valof
;[	for i = 2 to len do
;	  mask = (mask lshift 1) & mask
;	resultis mask
;]

.mrm:
	sta 3 link,2
	neg 1 3
	jmp .mr2
.mr1:
	movzl 0 1
	and 1 0
.mr2:
	inc 3 3 szr
	  jmp .mr1
	lda 3 link,2
	jmp 1,3


; Set1Bit(base, bitpos, val) be
;[	let m = 100000b rshift (bitpos&17b)
;	let p = base+(bitpos rshift 4)
;	@p = ((val&1) eq 0? @p & not m, @p % m)
;]

.s1bit:
	sta 3 link,2
	lda 3 c177760
	andzr 1 3
	movzr 3 3
	movzr 3 3
	movzr 3 3
	add 0 3	; ac3 ← p
	lda 0 c17
	com 1 1
	and 0 1	; left cycle count = 15-(bitpos&17b)
	adczl 0 0	; ac0 ← not 1
	cycle 0	; 0 in selected bit position
	lda 1 arg3,2
	movr 1 1	; carry ← val
	lda 1 0,3
	and 0 1 szc	; clear the bit, skip if val=0
	  adc 0 1	; and set it if val=1
	sta 1 0,3
	lda 3 link,2
	jmp 1,3


	.end