;	Copyright 1983 by Thomas Fenwick and Manx Software Systems
; :ts=8
Dg	group	STATICS
Cg	group	CODESEG
CODESEG	segment	word public 'code'
	assume	cs:Cg,ds:Dg,ss:Dg,es:Dg
	public	$longs
$longs	proc near
;
	public	$lng		;negate primary
$lng:
	neg	dx
	neg	ax
	sbb	dx,0
	ret
;
	public	$lcmp		;compare primary and secondary
$lcmp:
	cmp	dx,bx
	jne	cmpdone
	cmp	ax,cx
	je	cmpdone
	ja	p_gt_s
	sub	ax,ax
	dec	ax
	ret
p_gt_s:
	sub	ax,ax
	inc	ax
cmpdone:
	ret
;
	public $lad		;add secondary to primary
$lad:
	add	ax,cx
	adc	dx,bx
	ret
;
	public	$lsb		;subtract secondary from primary
$lsb:
	sub	ax,cx
	sbb	dx,bx
	ret
;
	public	$lan		;and primary with secondary
$lan:
	and	ax,cx
	and	dx,bx
	ret
;
	public	$lor		;or primary with secondary
$lor:
	or	ax,cx
	or	dx,bx
	ret
;
	public	$lxr		;exclusive or primary with secondary
$lxr:
	xor	ax,cx
	xor	dx,bx
	ret
;
	public	$lcm		;complement primary
$lcm:
	not	ax
	not	dx
	ret
;
	public	$lls		;shift primary left by secondary
$lls:
	and	cl,03fH		;restrict to 63 bits
	jz	lsdone
lsloop:
	shl	ax,1
	rcl	dx,1
	loop	lsloop
lsdone:
	ret
;
	public	$lrs		;right shift primary by secondary bits
$lrs:
	and	cl,03fH		;restrict to 63 bits
	jz	rsdone
rsloop:
	sar	dx,1
	rcr	ax,1
	loop	rsloop
rsdone:
	ret
;
STATICS	segment	word public 'data'
sign	db	0	;sign of result
STATICS	ends
;
;
	public	$ldv
$ldv:		;long divide	(primary = primary/secondary)
	mov	Dg:sign,0		;mark result as positive
	test	dx,dx
	jns	prim_ok
	neg	dx
	neg	ax
	sbb	dx,0
	mov	Dg:sign,1		;mark as negative
prim_ok:
	test	bx,bx
	jns	sec_ok
	neg	bx
	neg	cx
	sbb	bx,0
	xor	Dg:sign,1		;flip sign of result
sec_ok:
	call	comdivide
chksign:
	test	Dg:sign,0
	jz	posres
	neg	dx
	neg	ax
	sbb	dx,0
posres:
	ret
;
	public	$lrm
$lrm:		;long remainder	(primary = primary%secondary)
	mov	Dg:sign,0		;mark result as positive
	test	dx,dx
	jns	rprim_ok
	neg	dx
	neg	ax
	sbb	dx,0
	mov	Dg:sign,1		;mark as negative
rprim_ok:
	test	bx,bx
	jns	rsec_ok
	neg	bx
	neg	cx
	sbb	bx,0
rsec_ok:
	call	comdivide
	mov	ax,cx
	mov	dx,bx
	jmp	chksign
;
; divide (dx,ax) by (bx,cx):
;	quotient in (dx,ax)
;	remainder in (bx,cx)
comdivide:
	test	bx,bx		;check for easy case
	jnz	hardldv
	cmp	cx,dx
	ja	veryeasy
	push	ax
	mov	ax,dx
	sub	dx,dx
	div	cx
	mov	bx,ax		;save high word of quotient
	pop	ax
	div	cx
	mov	cx,dx		;save remainder
	mov	dx,bx
	sub	bx,bx
	ret
veryeasy:
	div	cx
	mov	cx,dx		;save remainder
	mov	dx,bx		;bx is already zero if we are here
	ret
hardldv:
	push	bp
	push	di
	push	si
	mov	si,cx		;copy divisor (bx,cx) into (di,si)
	mov	di,bx
	sub	bx,bx		;clear out top half of dividend
	sub	bp,bp
	mov	cx,32		;set up loop count
hardloop:
	shl	ax,1		;shift dividend left one bit
	rcl	dx,1
	rcl	bp,1
	rcl	bx,1
	sub	bp,si		;subtract divisor till negative
	sbb	bx,di
	js	zerobit
onebit:
	inc	ax		;set bit in quotient
	loop	hardloop
	jmp	hard_done
zeroloop:
	shl	ax,1		;shift dividend left one bit
	rcl	dx,1
	rcl	bp,1
	rcl	bx,1
	add	bp,si		;add divisor till positive
	adc	bx,di
	jns	onebit
zerobit:
	loop	zeroloop
	add	bp,si		;add divisor in one more time
	adc	bx,di		;to fix remainder
hard_done:
	mov	cx,bp		;copy low part of rem.
	pop	si
	pop	di
	pop	bp
	ret
;
;
	public	$lml
$lml:		;long multiply	(primary = primary * secondary)
	push	ax		;save low word
	push	dx		;save high word
	mul	bx
	mov	bx,ax		;keep partial product
	pop	ax		;get high word
	mul	cx
	add	bx,ax		;add to partial product
	pop	ax		;get low word
	mul	cx
	add	dx,bx		;add in partial products
	ret
;
$longs	endp
CODESEG	ends
	end
