home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
DRI-archive
/
roche
/
INTARITH.ASM
< prev
next >
Wrap
Assembly Source File
|
2009-12-11
|
9KB
|
423 lines
; INTARITH.ASM
; ------------
;
; See FALCONER.WS4 for doc.
;
; (Retyped by Emmanuel ROCHE.)
;
;--------------------------------
; Allowable entry points
;
entry imul,idiv,mul.div
;
;--------------------------------
; Entry points for utility routines
;
entry stadr.ldes,lbcs.las ; Stack addressing
entry bclz,bclc,bcra,bcrc ; Shifts and complements
entry dhlz,dera,derc ;
entry c2bc.c1bc,c2de,c1de,c2dhl
entry mul10,dten,dquik ; Fast arithmetic
;
;--------------------------------
; Macro definition
;
; "Return" and check stack level zero
;
rtn macro
if .lvl
error "0"+.lvl
.lvl set 0
endif
ret
endm
;
;--------------------------------
; Utility routines
;--------------------------------
;
; Stack addressing routines operate on an input stack level,
; supplied via the A-register. This specifies the stack level
; with respect to the calling routine, derived by counting
; "pushes" since the item was pushed. If the item was stored
; by the last "push", its address is zero. The address may
; not exceed 252.
;
; Generate stack absolute address for stack addressing routines
; A,F,H,L
;
stadr: lxi h,3 ; Allow for push H and 2 RETs
add l ; Max stack level is 252
mov l,a ;
dad h ; Convert to byte address
dad sp ; Memory address formed
rtn ;
;
; Load (DE) from stack level (A)
; A,F,D,E
;
ldes: push h ;
call stadr ; Get absolute address
mov e,m ;
inx h ;
mov d,m ;
pop h ;
rtn ;
;
; Load (BC) from stack level (A)
; (A) is stack level W.R.T. calling routine
; A,F,B,C
;
lbcs: push h ;
call stadr ; Form absolute address
mov c,m ;
inx h ;
mov b,m ;
pop h ;
rtn ;
;
; Load (A) from stack level (A)
; Value was stored by push psw
; A,F
;
las: push h ;
call stadr ; Form absolut address
inx h ;
mov a,m ;
pop h ;
rtn ;
;
; Shift (DEHL) register left, insert 0
; Original high order bit to Carry
; A,F,D,E,H,L (A=D on exit)
;
dhlz: dad h ;
mov a,e ;
ral ;
mov e,a ;
mov a,d ;
ral ;
mov d,a ;
rtn ;
;
; (BC) left shift, zero insert, leave (B) in (A)
; A,F,B,C
;
bclz: ora a ; Clear Carry
;
; (BC) left shift, Carry insert, leave (B) in (A)
; A,F,B,C
;
bclc: mov a,c ;
ral ;
mov c,a ;
mov a,b ;
ral ;
mov b,a ;
rtn ;
;
; Arith shift right (BC), leave (C) in (A)
; A,F,B,C
;
bcra: mov a,b ;
ral ;
;
; (BC) right shift, Carry in, leave (C) in (A)
; A,F,B,C
;
bcrc: mov a,b ;
rar ;
mov b,a ;
mov a,c ;
rar ;
mov c,a ;
rtn ;
;
; Arithmetic right shift (DE), leave (E) in (A)
; A,F,D,E
;
dera: mov a,d ;
ral ;
;
; (DE) right shift, Carry insert, leave (E) in (A)
; A,F,D,E
;
derc: mov a,d ;
rar ;
mov d,a ;
mov a,e ;
rar ;
mov e,a ;
rtn ;
;
; 2's complement (BC), leave (B) in (A)
; A,B,C
;
c2bc: dcx b ;
;
; 1's complement (DE), leave (B) in (A)
; A,D,E
;
c1bc: mov a,c ;
cma ;
mov c,a ;
mov a,b ;
cma ;
mov b,a ;
rtn ;
;
; 2's complement (DE), leave (D) in (A)
; A,D,E
;
c2de: dcx d ;
;
; 1's complement (DE), leave (D) in (A)
; A,D,E
;
c1de: mov a,e ;
cma ;
mov e,a ;
mov a,d ;
cma ;
mov d,a ;
rtn ;
;
; 2's complement (DEHL)
; A,F,D,E,H,L
;
c2dhl: xchg ;
call c2de ;
xchg ;
call c1de ;
mov a,h ;
ora l ;
rnz ;
inx d ; Propagate Carry
rtn ;
;
; Multiply (HL) by 10 (modulo 65536)
; No overflow signal
; F,H,L
;
mul10: push d ;
mov d,h ;
mov e,l ; Copy HL to DE
dad d ; 2*
dad h ; 4*
dad d ; 5*
dad h ; 10*
pop d ; Restore DE
rtn ;
;
; Divide integer (HL) by 10
; Remainder appears in (A) with flags set
; A,F,H,L
;
dten: push b ; Save BC
mvi c,10 ; Divisor
dten1: xra a ; Clear
mvi b,-16 ; Iteration count
dten2: dad h ;
ral ; Shift off into (A)
jc dten3 ; Allow for DQUIK
cmp c ; Test
jc dten4 ; No bit
dten3: sub c ; Bit = 1
inx h ;
dten4: inr b ; Done?
jm dten2 ; No
ora a ; Set flags for RDR., clear Carry
pop b ; Restore
rtn ;
;
; *** This routine is not used in the FLTARITH system ***
; Integer divide 16 by 0 bit quantities
; (HL)/(A) => (HL); remainder => (A)
; Set Carry for division by zero. Preserve HL
; A,F,H,L
;
dquik: ora a ;
stc ;
rz ; Division by zero
push b ;
.lvl set .lvl-1 ;
mov c,a ;
jmp dten1 ;
;
; *** End utility routines ***
; ----------------------------
;
; Integer (pos.) multiply DE*BC -> DEHL
; Operand range 0 to 65535
; D,E,H,L
;
imul: push psw ;
lxi h,0 ; Clear Accumulator
mvi a,-16 ; Iteration count
imul1: push psw ; Save iteration count
dad h ; Left shift, Carry out
mov a,e ; Left sh m'plier, insert o'flow
ral ;
mov e,a ;
mov a,d ;
ral ;
mov d,a ;
jnc imul2 ; No bit
dad b ; Add in multiplicand
jnc imul2 ; No overflow
imul2: pop psw ; Iteration count
inr a ;
jm imul1 ; Do again
pop psw ; Restore
rtn ;
;
; Integer (pos.) divide (DEHL)/(BC)=>(DE)
; Remainder appears in (HL)
; Carry for overflow, when registers unchanged
; Divisor, remainder and quotient range 0 to 65535
; Dividend range 0 to 4295*10^6 (approx.)
; F,D,E,H,L
;
idiv: push psw ;
mov a,e ; Check for overflow
sub c ;
mov a,d ;
sbb b ;
jc idiv1 ; No overflow
pop psw ; Restore (A)
stc ; Mark overflow
rtn ;
.lvl set .lvl+1 ;
idiv1: push b ;
call c2bc ; Change (BC) sign
xchg ; Do arithmetic in (HL)
mvi a,-16 ; Iteration count
idiv2: push psw ; Save iteration count
dad h ; Left shift (HLDE)
rar ; Save Carry out
xchg ;
dad h ;
xchg ;
jnc idiv3 ; No Carry into L
inx h ;
idiv3: ral ; Regain Carry from H
jc idiv4 ; Yes, generate quotient bit
mov a,l ;
add c ; Test for quotient bit
mov a,h ;
adc b ;
jnc idiv5 ; No bit
idiv4: dad b ; Subtract
inx d ; Insert quotient bit
idiv5: pop psw ; Get iteration count
inr a ;
jm idiv2 ; Not done
pop b ; Restore BC
pop psw ; Restore A
ora a ; Clear any Carry, no overflow
rtn ;
;
; *** This routine is not used in the FLTARITH system ***
; Signed multiply (DE)*(BC)->(DEHL)
; F,D,E,H,L
;
mul: push psw ;
push b ;
mov a,d ;
ora a ;
jm mul3 ; (DE) -ve (negative)
mov a,b ;
ora a ;
jp mul4 ; Both +ve (positive)
mul1: call c2bc ; 2's complement BC
mul2: call imul ; Result -ve
call c2dhl ; 2's complement DEHL
jmp mul5 ;
mul3: call c2de ; (DE) -ve
mov a,e ;
ora a ;
jp mul2 ; (DE) -ve, (BC) +ve
call c2bc ; (DE) -ve, (BC) -ve
mul4: call imul ; Result +ve
mul5: pop b ;
pop psw ;
ora a ; Reset Carry, no overflow
rtn ;
;
; *** This routine is not used in the FLTARITH system ***
; Do IDIV on signed + ho's & check overflow
; Expecting +ve result
; A,F,D,E,H,L
;
idivq: call idiv ;
rc ;
mov a,d ;
ral ;
rtn ; Result should be +ve
;
; *** This routine is not used in the FLTARITH system ***
; Do IDIV on signed + ho's & check overflow
; Inputs may include 8000H
; Expecting -ve result, allow 8000H
; A,F,D,E,H,L
;
idivn: call idiv ;
rc ; Overflow
call c2de ; Complement quotient
ral ; Result should be -ve
cmc ;
rtn ;
;
; *** This routine is not used in the FLTARITH system ***
; Signed divide (DEHL)/(BC)->(DE)
; Remainder appears in (HL)
; Carry indicates overflow when
; inputs are preserved, except flags
; F,D,E,H,L (9)
;
div: push psw ;
push b ;
push d ;
push h ; Save in case of overflow
mov a,d ;
ora d ;
jm div4 ; Dividend negative
ora b ;
@01 set .lvl ;
jm div2 ; +/-
call idivq ; +/+
jc div3 ; Overflow
div1: pop b ; Purge stack, no overflow
pop b ;
pop b ;
pop psw ;
ora a ; Reset Carry, no overflow
rtn ;
.lvl set @01 ;
div2: call c2bc ; +/-, complement BC
call idivn ;
jnc div1 ; No overflow
div3: pop h ; Restore entry, overflow
pop d ;
pop b ;
pop psw ;
stc ; Mark overflow wit Carry
rtn ;
div4: call c2dhl ; -/?, complement DEHL
mov a,b ;
ora a ;
jm div7 ; -/-
call idivn ;
div5: jc div3 ; Overflow
div6: xchg ;
call c2de ;
xchg ; Complement remainder
jmp div1 ;
div7: call c2bc ; -/-, complement BC
call idivq ;
jmp div5 ;
;
;--------------------------------
;
END ; of INTARITH.ASM