;
; SYSLIB Module Name:  SMATH
; Author:  Richard Conn
; SYSLIB Version Number:  2.0
; Module Version Number:  1.0
; Module Entry Points:
;	ADDHD		SUBHD		MULHD		DIVHD
;	NEGH		CMPH		ROTLH		ROTRH
;	SHFTLH		SHFTRH		ANDHD		ORHD
;	XORHD
; Module External References:
;	None
;

;
;  ADDHD -- ADD DE TO HL, RESULT IN HL
;	RETURN WITH HL=RESULT, CARRY SET IF OVFL
;
ADDHD::
	PUSH	PSW
	MOV	A,E	; ADD L AND E
	ADD	L
	MOV	L,A
	MOV	A,D	; ADD H AND D
	ADC	H
	MOV	H,A
	JNC	OKRET
OVFLRET:
	POP	PSW	; GET PSW
	STC		; SET CARRY
	RET
OKRET:
	POP	PSW
	ORA	A	; CLEAR CARRY
	RET

;
;  SUBHD -- SUBTRACT DE FROM HL, RESULT IN HL
;	RETURN WITH HL=RESULT, CARRY SET IF HL<DE
;
SUBHD::
	PUSH	PSW
	MOV	A,L	; SUBTRACT LOW
	SUB	E
	MOV	L,A
	MOV	A,H	; SUBTRACT HIGH
	SBB	D
	MOV	H,A
	JNC	OKRET
	JMP	OVFLRET

;
;  ROTLH -- ROTATE LEFT HL 1 BIT POSITION
;
ROTLH::
	PUSH	PSW
	ANA	A	; CLEAR CARRY
ROTL:
	MOV	A,L	; SHIFT LOW
	RAL		; ROTATE 9-BIT ACC LEFT
	MOV	L,A
	MOV	A,H	; SHIFT HIGH
	RAL
	MOV	H,A
	MOV	A,L	; ADD IN CARRY
	ACI	0
	MOV	L,A
	POP	PSW
	RET

;
;  ROTRH -- ROTATE RIGHT HL 1 BIT POSITION
;
ROTRH::
	PUSH	PSW
	MOV	A,L	; GET LSB INTO CARRY
	RAR
	MOV	A,H	; SHIFT HIGH
	RAR		; ROTATE 9-BIT ACC RIGHT
	MOV	H,A
	MOV	A,L	; SHIFT LOW
	RAR
	MOV	L,A
	POP	PSW
	RET

;
;  SHFTLH -- SHIFT LEFT HL 1 BIT POSITION
;	CARRY CONTAINS MSB
;
SHFTLH::
	PUSH	PSW
	ANA	A	; CLEAR CARRY
SHFL:
	MOV	A,L	; SHIFT LOW
	RAL		; ROTATE 9-BIT ACC LEFT
	MOV	L,A
	MOV	A,H	; SHIFT HIGH
	RAL
	MOV	H,A
	JNC	OKRET
	JMP	OVFLRET
;  ROTATE HL LEFT, BUT ROTATE IN CARRY FLAG
SHFLCH:
	PUSH	PSW	; SAVE A
	JMP	SHFL

;
;  SHFTRH -- SHIFT RIGHT HL 1 BIT POSITION
;	CARRY CONTAINS LSB
;
SHFTRH::
	PUSH	PSW
	ANA	A	; CLEAR CARRY
	MOV	A,H	; SHIFT HIGH
	RAR		; ROTATE 9-BIT ACC RIGHT
	MOV	H,A
	MOV	A,L	; SHIFT LOW
	RAR
	MOV	L,A
	JNC	OKRET
	JMP	OVFLREG

;
;  ANDHD -- AND HL WITH DE, RESULT IN HL
;
ANDHD::
	PUSH	PSW
	MOV	A,L	; DO LOW
	ANA	E
	MOV	L,A
	MOV	A,H	; DO HIGH
	ANA	D
	MOV	H,A
	POP	PSW
	RET

;
;  ORHD -- OR HL WITH DE, RESULT IN HL
;
ORHD::
	PUSH	PSW
	MOV	A,L	; DO LOW
	ORA	E
	MOV	L,A
	MOV	A,H	; DO HIGH
	ORA	D
	MOV	H,A
	POP	PSW
	RET

;
;  XORHD -- XOR HL WITH DE, RESULT IN HL
;
XORHD::
	PUSH	PSW
	MOV	A,L	; DO LOW
	XRA	E
	MOV	L,A
	MOV	A,H	; DO HIGH
	XRA	D
	MOV	H,A
	POP	PSW
	RET

;
;  NEGH -- NEGATE (2'S COMP) HL
;
NEGH::
	CALL	CMPH	; 1'S COMP OF HL
	INX	H	; ADD 1 FOR 2'S COMP
	RET

;
;  CMPH -- COMPLEMENT (1'S COMP) HL
;
CMPH::
	PUSH	PSW
	MOV	A,L	; COMPLEMENT LOW
	CMA
	MOV	L,A
	MOV	A,H	; COMPLEMENT HIGH
	CMA
	MOV	H,A
	POP	PSW
	RET

;
;  MULHD -- MULTIPLY HL BY DE, RESULT IN HL
;	CARRY SET MEANS OVERFLOW
;	A IS DESTROYED
;
MULHD::
	PUSH	PSW
	PUSH	B	; SAVE REGS
	PUSH	D
	XRA	A	; SET NO OVFL
	STA	OVFL
	PUSH	H	; SAVE HL
	LXI	H,0	; ZERO LONG ACC
	SHLD	ACC
	POP	H	; GET HL
	MVI	B,16	; 16 LOOPS
MLHD:
	CALL	SHFTRH	; SHIFT RIGHT MULTIPLIER
	JNC	MLHD1	; DON'T ADD IN IF LSB IS ZERO
	PUSH	H	; SAVE VALUE
	LHLD	ACC
	MOV	A,L	; ADD IN MULTIPLICAND
	ADD	E
	MOV	L,A
	MOV	A,H
	ADC	D
	MOV	H,A
	SHLD	ACC	; NEW ACCUMULATED VALUE
	JNC	MLHD0
	MVI	A,0FFH	; SET OVFL FLAG
	STA	OVFL
MLHD0:
	POP	H	; GET VALUE
MLHD1:
	XCHG		; SHIFT LEFT MULTIPLICAND
	CALL	SHFTLH
	XCHG
	DCR	B	; COUNT DOWN
	JNZ	MLHD
	POP	D	; RESTORE REGS
	POP	B
	LHLD	ACC	; GET RESULT
	LDA	OVFL	; OVERFLOW?
	ORA	A	; 0=NO
	JZ	OKRET
	JMP	OVFLRET

;
;  BUFFERS
;
ACC:	DS	2	; TEMP ACCUMULATOR
OVFL:	DS	1	; OVERFLOW FLAG

;
;  DIVHD -- DIVIDE HL BY DE, RESULT IN HL
;
DIVHD::
	PUSH	PSW
	PUSH	B
	PUSH	H	; SAVE HL
	LXI	H,0
	SHLD	ACC	; ZERO ACCUMULATOR
	POP	H
;  CHECK TO MAKE SURE THAT HL > DE
	MOV	A,H
	CMP	D	; H > D?
	JC	DOVFL	; ZERO RESULT IF H < D
	JNZ	DNOVFL
	MOV	A,L
	CMP	E	; L > E?
	JC	DOVFL	; ZERO RESULT IF HL < DE
DNOVFL:
	MVI	B,16	; 16 LOOPS
DVHD:
	CALL	SHFTLH	; SHIFT DIVIDEND LEFT
	PUSH	H	; SAVE DIVIDEND
	LHLD	ACC	; GET ACC
	CALL	SHFLCH	; ROTATE ACC AND MOVE IN CARRY
	SHLD	ACC	; NEW ACC
	MOV	A,L	; LOW COMPARISON
	SUB	E	; COMPARE AND SUBTRACT
	MOV	L,A
	MOV	A,H	; HIGH COMPARISON
	SBB	D	; COMPARE AND SUBTRACT
	MOV	H,A
	JC	DVHD0
	SHLD	ACC	; SAVE NEW ACC
	POP	H	; GET DIVIDEND
	MOV	A,L	; PLACE IN A 1 TO QUOTIENT
	ORI	1
	MOV	L,A
	JMP	DVHD1
DVHD0:
	POP	H	; GET DIVIDEND AND LEAVE LSB AT ZERO
DVHD1:
	DCR	B	; COUNT DOWN
	JNZ	DVHD
DVRET:
	POP	B
	POP	PSW
	RET
DOVFL:
	LXI	H,0	; RESULT IS ZERO
	JMP	DVRET

	END
