From: http://www.microshadow.com/page8051.php?page=7
Full math routine library from the same place routine_library.zip
;*****************************************************************
;* *
;* Maths Subroutines for the 8051 microcontroller *
;* W.G.Marshall 2002 *
;* *
;*****************************************************************
; All parameters in Register bank 0, (r0 to r7)
; Bits 21H and 22H reserved for sign bits
;=================================================================
; subroutine Cr0
; 8-Bit 2's Complement -> magnitude / Sign Bit Conversion
;
; input: r0 = signed byte
;
; output: r0 = magnitude
; Bit 21H = sign (21H is set if r0 is a negative number)
;
; alters: acc
;=================================================================
Cr0: mov a, r0 ; read X into accumulator
jb acc.7, Cr0a ; X is negative if bit 7 is 1
clr 21H ; clear sign bit if 'positive'
ret ; done
Cr0a: cpl a ; X negative, find abs value
inc a ; XA = complement(XT)+1
mov r0, a ; save magnitude
setb 21H ; set sign bit if 'negative'
ret
;=================================================================
; subroutine Cr1
; 8-Bit 2's Complement -> magnitude / Sign Bit Conversion
;
; input: r1 = signed byte
;
; output: r1 = magnitude
; Bit 22H = sign (22H is set if r1 is a negative number)
;
; alters: acc
;=================================================================
Cr1: mov a, r1 ; read X into accumulator
jb acc.7, Cr1a ; X is negative if bit 7 is 1
clr 22H ; clear sign bit if 'positive'
ret ; done
Cr1a: cpl a ; X negative, find abs value
inc a ; XA = complement(XT)+1
mov r1, a ; save magnitude
setb 22H ; set sign bit if 'negative'
ret
;===================================================================
; subroutine Cr0r1
; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion
;
; input: r1, r0 = signed word
;
; output: r1, r0 = magnitude
; Bit 21H = sign (21H is set if negative number)
;
; alters: acc, C
;===================================================================
Cr0r1: mov a, r1 ; high byte into accumulator
jb acc.7, c0a ; negative if bit 7 is 1
clr 21H ; clear sign bit if 'positive'
ret ; done
c0a: setb 21H ; set sign flag
mov a, r0 ; number is negative
cpl a ; complement
add a, #1 ; and add +1
mov r0, a
mov a, r1 ; get next byte
cpl a ; complement
addc a, #0
mov r1, a
ret
;====================================================================
; subroutine Cr2r3
; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion
;
; input: r3, r2 = signed word
;
; output: r3, r2 = magnitude
; Bit 22H = sign (22H is set if negative number)
;
; alters: acc, C
;====================================================================
Cr2r3: mov a, r3 ; read high into accumulator
jb acc.7, c1a ; negative if bit 7 is 1
clr 22H ; clear sign bit if 'positive'
ret ; done
c1a: setb 22H ; set sign flag
mov a, r2 ; number is negative
cpl a ; complement
add a, #1 ; and add +1
mov r2, a
mov a, r3 ; get next byte
cpl a ; complement
addc a, #0
mov r3, a
ret
;====================================================================
; subroutine Cr4r5
; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion
;
; input: r5, r4 = signed word
;
; output: r5, r4 = magnitude
; Bit 22H = sign (22H is set if negative number)
;
; alters: acc, C
;====================================================================
Cr4r5: mov a, r5 ; read high into accumulator
jb acc.7, c3a ; negative if bit 7 is 1
clr 22H ; clear sign bit if 'positive'
ret ; done
c3a: setb 22H ; set sign flag
mov a, r4 ; number is negative
cpl a ; complement
add a, #1 ; and add +1
mov r4, a
mov a, r5 ; get next byte
cpl a ; complement
addc a, #0
mov r5, a
ret
;====================================================================
; subroutine Cr0r3
; 32-Bit 2's Complement -> magnitude / Sign Bit Conversion
;
; input: r3, r2, r1, r0 = signed word
;
; output: r3, r2, r1, r0 = magnitude
; Bit 21H = sign (21H is set if negative number)
;
; alters: acc
;====================================================================
Cr0r3: mov a, r3 ; read high into accumulator
jb acc.7, c2a ; negative if bit 7 is 1
clr 21H ; clear sign flag if 'positive'
ret ; done
c2a: setb 21H ; set sign flag
mov a, r0 ; number is negative
cpl a ; complement
add a, #1 ; and add +1
mov r0, a
mov a, r1 ; get next byte
cpl a ; complement
addc a, #0
mov r1,a
mov a, r2 ; get next byte
cpl a ; complement
addc a, #0
mov r2,a
mov a, r3 ; get next byte
cpl a ; complement
addc a, #0
mov r3, a
ret ; done
;==================================================================
; subroutine Mr0
; 8-Bit magnitude / Sign Bit -> 2's Complement Conversion
;
; input: r0 = magnitude
; Bits 21H & 22H = sign bits of operands X and Y
; (set if negative)
;
; output: r0 = signed byte
;
; alters: acc
;==================================================================
Mr0: jb 21H, Mr0b ; test X sign
jb 22H, Mr0a ; test Y sign
ret
Mr0b: jnb 22H, Mr0a
ret
Mr0a: mov a, r0 ; if r0 negative, get abs value
cpl a ; complement magnitude of X
inc a ; r0 = complement(r0)+1
mov r0, a ; save in 2's complement
ret ; done
;====================================================================
; subroutine Mr0r1
; 16-Bit magnitude / Sign Bit -> 2's Complement Conversion
;
; input: r1, r0 = magnitude
; Bits 21H & 22H = sign bits of operands X and Y
; (set if negative)
;
; output: r1, r0 = signed word
;
; alters: acc, C
;====================================================================
Mr0r1: jb 21H, Mr0r1b ; test X sign
jb 22H, Mr0r1a ; test Y sign
ret
Mr0r1b: jnb 22H, Mr0r1a
ret
Mr0r1a: mov a, r0 ; negate number
cpl a ; complement
add a, #1 ; and add +1
mov r0, a
mov a, r1 ; get next byte
cpl a ; complement
addc a, #0
mov r1, a
ret
;====================================================================
; subroutine Mr0r3
; 32-Bit magnitude / Sign Bit -> 2's Complement Conversion
;
; input: r3, r2, r1, r0 = magnitude
; Bits 21H & 22H = sign bits of operands X and Y
; (set if negative)
;
; output: r3, r2, r1, r0 = signed word
;
; alters: acc, C
;====================================================================
Mr0r3: jb 21H, Mr0r3b ; test X sign
jb 22H, Mr0r3a ; test Y sign
ret
Mr0r3b: jnb 22H, Mr0r3a
ret
Mr0r3a: mov a, r0 ; negate number
cpl a ; complement
add a, #1 ; and add +1
mov r0, a
mov a, r1 ; get next byte
cpl a ; complement
addc a, #0
mov r1, a
mov a, r2 ; get next byte
cpl a ; complement
addc a, #0
mov r2, a
mov a, r3 ; get next byte
cpl a ; complement
addc a, #0
mov r3, a
ret ; done
;====================================================================
; subroutine CONV816
; 8-bit Signed number to 16-Bit Signed number conversion
;
; input: r0 = X
;
; output: r1, r0 = X with sign extended to 16 bits
;
; alters: acc
;====================================================================
CONV816: mov A, r0
jnb acc.7, Pos
mov r1, #0FFH
ret
Pos: mov r1, #0
ret
;====================================================================
; subroutine ADD16
; 16-Bit Signed (2's Complement) Addition
;
; input: r1, r0 = X
; r3, r2 = Y
;
; output: r1, r0 = signed sum S = X + Y
; Carry C is set if the result (S) is out of range
;
; alters: acc, C, OV
;====================================================================
ADD16: anl PSW, #0E7H ; Register Bank 0
mov a, r0 ; load X low byte into acc
add a, r2 ; add Y low byte
mov r0, a ; put result in Z low byte
mov a, r1 ; load X high byte into acc
addc a, r3 ; add Y high byte with carry
mov r1, a ; save result in Z high byte
mov C, OV
ret
;====================================================================
; subroutine ADD32
; 32-Bit Signed (2's Complement) Addition
;
; input: r3, r2, r1, r0 = X
; r7, r6, r5, r4 = Y
;
; output: r3, r2, r1, r0 = signed sum S = X + Y
; Carry C is set if the result (S) is out of range
;
; alters: acc, C, OV
;====================================================================
ADD32: anl PSW, #0E7H ; Register Bank 0
mov a, r0 ; load X low byte into acc
add a, r4 ; add Y low byte
mov r0, a ; save result
mov a, r1 ; load X next byte into acc
addc a, r5 ; add Y next byte with carry
mov r1, a ; save result
mov a, r2 ; load X next byte into acc
addc a, r6 ; add Y next byte
mov r2, a ; save result
mov a, r3 ; load X high byte into acc
addc a, r7 ; add Y high byte with carry
mov r3, a
mov C, OV
ret
;====================================================================
; subroutine SUB16
; 16-Bit Signed (2's Complement) Subtraction
;
; input: r1, r0 = X
; r3, r2 = Y
;
; output: r1, r0 = signed difference D = X - Y
; Carry C is set if the result (D) is out of range.
;
; alters: acc, C, OV
;====================================================================
SUB16: anl PSW, #0E7H ; Register Bank 0
mov a, r0 ; load X low byte into acc
clr C ; clear carry flag
subb a, r2 ; subract Y low byte
mov r0, a ; put result in Z low byte
mov a, r1 ; load X high into accumulator
subb a, r3 ; subtract Y high with borrow
mov r1, a ; save result in Z high byte
mov C, OV
ret
;====================================================================
; subroutine SUB32
; 32-Bit Signed (2's Complement) subtraction
;
; input: r3, r2, r1, r0 = X
; r7, r6, r5, r4 = Y
;
; output: r3, r2, r1, r0 = signed difference D = X - Y
; Carry C is set if the result (D) is out of range.
;
; alters: acc, C, OV
;====================================================================
SUB32: anl PSW, #0E7H ; Register Bank 0
mov a, r0 ; load X low byte into acc
clr C ; clear carry flag
subb a, r4 ; subract Y low byte
mov r0, a ; put result in Z low byte
mov a, r1 ; repeat with other bytes...
subb a, r5
mov r1, a
mov a, r2
subb a, r6
mov r2, a
mov a, r3
subb a, r7
mov r3, a
mov C, OV ; set C if external borrow
ret
;==================================================================
; subroutine MUL8
; 8-Bit x 8-Bit to 16-Bit Product Signed Multiply
; 2's Complement format
;
; input: r0 = multiplicand X
; r1 = multiplier Y
;
; output: r1, r0 = product P = X x Y.
;
; calls: UMUL8, Cr0, Cr1, Mr0r1
;
; alters: acc, C, Bits 21H & 22H
;==================================================================
MUL8: anl PSW, #0E7H ; Register Bank 0
acall Cr0 ; 2's comp -> Mag/Sign
acall Cr1 ; 2's comp -> Mag/Sign
acall UMUL8
acall Mr0r1 ; Mag/Sign -> 2's Comp
ret
;==================================================================
; subroutine UMUL8
; 8-Bit x 8-Bit to 16-Bit Product Unsigned Multiply
;
; input: r0 = multiplicand X
; r1 = multiplier Y
;
; output: r1, r0 = product P = X x Y.
;
; alters: acc
;==================================================================
UMUL8: push b
mov a, r0 ; read X and ...
mov b, r1 ; ... Y
mul ab ; multiply X and Y
mov r1, b ; save result high ...
mov r0, a ; ... and low
pop b
ret
;====================================================================
; subroutine MUL816
; 8-Bit x 16-Bit to 32-Bit Product signed Multiply
; 2's Complement format
;
; input: r0 = multiplicand X
; r3, r2 = multiplier Y
;
; output: r3, r2, r1, r0 = product P = X x Y (r3 = sign extension)
;
; calls: Cr0, Cr2r3, Mr0r3
;
; alters: acc, C, Bits 21H & 22H
;====================================================================
MUL816: push b
anl PSW, #0E7H ; Register Bank 0
acall Cr0 ; 2's comp -> Mag/Sign
acall Cr2r3 ; 2's comp -> Mag/Sign
mov a, r0 ; load X low byte into acc
mov b, r2 ; load Y low byte into B
mul ab ; multiply
push acc ; stack result low byte
push b ; stack result high byte
mov a, r0 ; load X into acc again
mov b, r3 ; load Y high byte into B
mul ab ; multiply
pop 00H ; recall X*YL high byte
add a, r0 ; add X*YL high and X*YH low
mov r1, a ; save result
clr a ; clear accumulator
addc a, b ; a = b + carry flag
mov r2, a ; save result
pop 00H ; get low result
mov r3, #0
acall Mr0r3 ; Mag/Sign -> 2's Comp
pop b
ret
;====================================================================
; subroutine MUL16
; 16-Bit x 16-Bit to 32-Bit Product Signed Multiply
; 2's Complement format
;
; input: r1, r0 = multiplicand X
; r3, r2 = multiplier Y
;
; output: r3, r2, r1, r0 = product P = X x Y
;
; calls: UMUL16, Cr0r1, Cr2r3, Mr0r3
;
; alters: acc, C, Bits 21H & 22H
;====================================================================
MUL16: anl PSW, #0E7H ; Register Bank 0
acall Cr0r1 ; 2's comp -> Mag/Sign
acall Cr2r3 ; 2's comp -> Mag/Sign
acall UMUL16
acall Mr0r3 ; Mag/Sign -> 2's Comp
ret
;====================================================================
; subroutine UMUL16
; 16-Bit x 16-Bit to 32-Bit Product Unsigned Multiply
;
; input: r1, r0 = multiplicand X
; r3, r2 = multiplier Y
;
; output: r3, r2, r1, r0 = product P = X x Y
;
; alters: acc, C
;====================================================================
UMUL16: push B
push dpl
mov a, r0
mov b, r2
mul ab ; multiply XL x YL
push acc ; stack result low byte
push b ; stack result high byte
mov a, r0
mov b, r3
mul ab ; multiply XL x YH
pop 00H
add a, r0
mov r0, a
clr a
addc a, b
mov dpl, a
mov a, r2
mov b, r1
mul ab ; multiply XH x YL
add a, r0
mov r0, a
mov a, dpl
addc a, b
mov dpl, a
clr a
addc a, #0
push acc ; save intermediate carry
mov a, r3
mov b, r1
mul ab ; multiply XH x YH
add a, dpl
mov r2, a
pop acc ; retrieve carry
addc a, b
mov r3, a
mov r1, 00H
pop 00H ; retrieve result low byte
pop dpl
pop B
ret
;====================================================================
; subroutine MAC16
; 16-Bit x 16-Bit to 32-Bit Product signed Multiply-Accumulate
; 2's Complement format
;
; input: r1, r0 = multiplicand X
; r3, r2 = multiplier Y
; r7, r6, r5, r4 = 32-bit accumulator Ar
;
; output: r7, r6, r5, r4 = accumulated result Ar = Ar + (X x Y)
; r3, r2, r1, r0 = multiply result M = X x Y
; Carry C set if overflow
;
; calls: MUL16
;
; alters: acc, C, Bits 21H & 22H
;====================================================================
MAC16: anl PSW, #0E7H ; Register Bank 0
acall MUL16+3
mov A, r4
add A, r0
mov r4, A
mov A, r5
addc A, r1
mov r5, A
mov A, r6
addc A, r2
mov r6, A
mov A, r7
addc A, r3
mov r7, A
mov C, OV
ret
;===============================================================
; subroutine DIV8
; 8-Bit / 8-Bit to 8-Bit Quotient & Remainder signed Divide
; 2's Complement Format
;
; input: r0 = Dividend X
; r1 = Divisor Y
;
; output: r0 = quotient Q of division Q = X / Y
; r1 = remainder
;
; calls: Cr0, Cr1, Mr0
;
; alters: acc, C, Bits 21H & 22H
;===============================================================
DIV8: anl PSW, #0E7H ; Register Bank 0
acall Cr0 ; 2's comp -> Mag/Sign
acall Cr1 ; 2's comp -> Mag/Sign
acall UDIV8
acall Mr0 ; Mag/Sign -> 2's Comp
ret
;===============================================================
; subroutine UDIV8
; 8-Bit / 8-Bit to 8-Bit Quotient & Remainder Unsigned Divide
;
; input: r0 = Dividend X
; r1 = Divisor Y
;
; output: r0 = quotient Q of division Q = X / Y
; r1 = remainder
; ;
; alters: acc, C
;===============================================================
UDIV8: push b
mov a, r0 ; read X and ...
mov b, r1 ; ... Y
div ab ; divide X and Y
mov r0, a ; save result quotient
mov r1, b ; save remainder
pop b
ret
;====================================================================
; subroutine DIV16
; 16-Bit / 16-Bit to 16-Bit Quotient & remainder signed Divide
; 2's Complement Format
;
; input: r1, r0 = Dividend X
; r3, r2 = Divisor Y
;
; output: r1, r0 = quotient Q of division Q = X / Y
; r3, r2 = remainder
; Carry C is set if Y = 0, i.e. divide by 0 attempted
;
; calls: UDIV16, Cr0r1, Cr2r3, Mr0r1
;
; alters: acc, r4, r5, r6, r7, flags, Bits 21H & 22H
;====================================================================
DIV16: anl PSW, #0E7H ; Register Bank 0
mov a, r3 ; get divisor high byte
orl a, r2 ; OR with low byte
jnz div_OK ; divisor OK if not 0
setb C ; else, overflow
ret
div_OK: push dpl
push dph
push b
acall Cr0r1 ; 2's comp -> Mag/Sign
acall Cr2r3 ; 2's comp -> Mag/Sign
acall UDIV16
acall Mr0r1 ; Mag/Sign -> 2's Comp
clr C
pop b
pop dph
pop dpl
ret ; done
;====================================================================
; subroutine UDIV16
; 16-Bit / 16-Bit to 16-Bit Quotient & Remainder Unsigned Divide
;
; input: r1, r0 = Dividend X
; r3, r2 = Divisor Y
;
; output: r1, r0 = quotient Q of division Q = X / Y
; r3, r2 = remainder
;
; alters: acc, B, dpl, dph, r4, r5, r6, r7, flags
;====================================================================
UDIV16: mov r7, #0 ; clear partial remainder
mov r6, #0
mov B, #16 ; set loop count
div_loop: clr C ; clear carry flag
mov a, r0 ; shift the highest bit of
rlc a ; the dividend into...
mov r0, a
mov a, r1
rlc a
mov r1, a
mov a, r6 ; ... the lowest bit of the
rlc a ; partial remainder
mov r6, a
mov a, r7
rlc a
mov r7, a
mov a, r6 ; trial subtract divisor
clr C ; from partial remainder
subb a, r2
mov dpl, a
mov a, r7
subb a, r3
mov dph, a
cpl C ; complement external borrow
jnc div_1 ; update partial remainder if
; borrow
mov r7, dph ; update partial remainder
mov r6, dpl
div_1: mov a, r4 ; shift result bit into partial
rlc a ; quotient
mov r4, a
mov a, r5
rlc a
mov r5, a
djnz B, div_loop
mov a, r5 ; put quotient in r0, and r1
mov r1, a
mov a, r4
mov r0, a
mov a, r7 ; get remainder, saved before the
mov r3, a ; last subtraction
mov a, r6
mov r2, a
ret
;====================================================================
; subroutine DIV32
; 32-Bit / 16-Bit to 32-Bit Quotient & remainder signed Divide
; 2's Complement Format
;
; input: r3, r2, r1, r0 = Dividend X
; r5, r4 = Divisor Y
;
; output: r3, r2, r1, r0 = quotient Q of division Q = X / Y
; r7, r6, r5, r4 = remainder
; Carry C is set if Y = 0, i.e. divide by 0 attempted
;
; calls: UDIV32, Cr0r3, Cr4r5, Mr0r3
;
; alters: acc, flags, Bits 21H & 22H
;====================================================================
DIV32: anl PSW, #0E7H ; Register Bank 0
mov a, r4 ; get divisor high byte
orl a, r5 ; OR with low byte
jnz div32_OK ; divisor OK if not 0
setb C ; else, overflow
ret
div32_OK: acall Cr0r3 ; 2's comp -> Mag/Sign
acall Cr4r5 ; 2's comp -> Mag/Sign
acall UDIV32
acall Mr0r3 ; Mag/Sign -> 2's Comp
clr C ; divisor is not 0
ret ; done
;====================================================================
; subroutine UDIV32
; 32-Bit / 16-Bit to 32-Bit Quotient & Remainder Unsigned Divide
;
; input: r3, r2, r1, r0 = Dividend X
; r5, r4 = Divisor Y
;
; output: r3, r2, r1, r0 = quotient Q of division Q = X / Y
; r7, r6, r5, r4 = remainder
;;
; alters: acc, flags
;====================================================================
UDIV32: push 08 ; Save Register Bank 1
push 09
push 0AH
push 0BH
push 0CH
push 0DH
push 0EH
push 0FH
push dpl
push dph
push B
setb RS0 ; Select Register Bank 1
mov r7, #0 ; clear partial remainder
mov r6, #0
mov r5, #0
mov r4, #0
mov B, #32 ; set loop count
div_lp32: clr RS0 ; Select Register Bank 0
clr C ; clear carry flag
mov a, r0 ; shift the highest bit of the
rlc a ; dividend into...
mov r0, a
mov a, r1
rlc a
mov r1, a
mov a, r2
rlc a
mov r2, a
mov a, r3
rlc a
mov r3, a
setb RS0 ; Select Register Bank 1
mov a, r4 ; ... the lowest bit of the
rlc a ; partial remainder
mov r4, a
mov a, r5
rlc a
mov r5, a
mov a, r6
rlc a
mov r6, a
mov a, r7
rlc a
mov r7, a
mov a, r4 ; trial subtract divisor from
clr C ; partial remainder
subb a, 04
mov dpl, a
mov a, r5
subb a, 05
mov dph, a
mov a, r6
subb a, #0
mov 06, a
mov a, r7
subb a, #0
mov 07, a
cpl C ; complement external borrow
jnc div_321 ; update partial remainder if
; borrow
mov r7, 07 ; update partial remainder
mov r6, 06
mov r5, dph
mov r4, dpl
div_321: mov a, r0 ; shift result bit into partial
rlc a ; quotient
mov r0, a
mov a, r1
rlc a
mov r1, a
mov a, r2
rlc a
mov r2, a
mov a, r3
rlc a
mov r3, a
djnz B, div_lp32
mov 07, r7 ; put remainder, saved before the
mov 06, r6 ; last subtraction, in bank 0
mov 05, r5
mov 04, r4
mov 03, r3 ; put quotient in bank 0
mov 02, r2
mov 01, r1
mov 00, r0
clr RS0
pop B
pop dph
pop dpl
pop 0FH ; Retrieve Register Bank 1
pop 0EH
pop 0DH
pop 0CH
pop 0BH
pop 0AH
pop 09
pop 08
ret
;====================================================================
; subroutine MULDIV
; 16-Bit x 16-Bit to 32-Bit Product Signed Multiply followed by
; 32-Bit / 16-Bit to 32-Bit Quotient & remainder signed Divide
; 2's Complement Format
;
; input: r1, r0 = multiplicand X
; r3, r2 = multiplier Y
; r5, r4 = divisor Z
;
; output: r3, r2, r1, r0 = quotient Q of division Q = (X x Y) / Z
; r7, r6, r5, r4 = remainder
; Carry C is set if Z = 0, i.e. divide by 0 attempted
;
; calls: UMUL16, UDIV32, Cr0r1, Cr2r3, Cr4r5, Mr0r3
;
; alters: acc, flags, Bits 21H & 22H
;====================================================================
MULDIV: anl PSW, #0E7H ; Register Bank 0
mov a, r4 ; get divisor high byte
orl a, r5 ; OR with low byte
jnz muld_OK ; divisor OK if not 0
setb C ; else, overflow
ret
muld_OK: lcall Cr0r1 ; 2's comp -> Mag/Sign
lcall Cr2r3 ; 2's comp -> Mag/Sign
lcall UMUL16
jb 21H, divn1 ; test X sign
divn: lcall Cr4r5 ; 2's comp -> Mag/Sign
lcall UDIV32
lcall Mr0r3 ; Mag/Sign -> 2's Comp
clr C ; divisor is not 0
ret
divn1: jbc 22H, divn ; test Y sign
setb 22H
sjmp divn
;====================================================================
; subroutine MACD16
; 16-Bit x 16-Bit to 32-Bit Product signed Multiply-Accumulate
; with table data and data move.
; y(n) = x(n)*h0 + x(n-1)*h1 + x(n-2)*h2 + ......
; Note: Assumes shared program/data space. i.e. PSEN and RD are OR-ed
; together on the board.
; 2's Complement format
;
; input: B = No. of 16-bit data items in tables (max 63)
; DPTR --> New Input data (e.g. from ADC)
; DPTR+2 --> Base of Data Table (x)
; DPTR+128 --> Base of Multiplier Table (h)
;
; output: r7, r6, r5, r4 = 32-bit accumulated result
;
; calls: MUL16
;
; alters: acc, flags, Bits 21H & 22H
;====================================================================
MACD16: anl PSW, #0E7H
mov r4, #0 ; Clear Accumulator
mov r5, #0
mov r6, #0
mov r7, #0
movx a, @DPTR
push acc ; Save XNEWL
inc DPTR
movx a, @DPTR
push acc ; Save XNEWH
inc DPTR
Macd1: movx a, @DPTR ; Get x(n)L
mov r0, a
push acc ; Save x(n)L
mov a, #80H
movc a, @a+DPTR ; Get h(n)L
mov r2, a
inc DPTR
movx a, @DPTR ; Get x(n)H
mov r1, a
push acc ; Save x(n)H
mov a, #80H
movc a, @a+DPTR ; Get h(n)H
mov r3, a
lcall MUL16+3 ; Do Multiply...
mov A, r4 ; then Accumulate..
add A, r0
mov r4, A
mov A, r5
addc A, r1
mov r5, A
mov A, r6
addc A, r2
mov r6, A
mov A, r7
addc A, r3
mov r7, A
pop 01 ; Now move x data
pop 00
pop 03
pop 02
push 00
push 01
mov a, r3 ; Move up x(n)H
movx @DPTR, a
mov a, #0FFH
add a, dpl
mov dpl, a
mov a, #0FFH
addc a, dph
mov dph, a
mov a, r2 ; Move up x(n)L
movx @DPTR, a
inc DPTR
inc DPTR
djnz b, Macd1 ; Whole table processed?
dec SP
dec SP
ret
;==================================================================
; subroutine DELAY
;
; input: r0, r1, r2 = delay loop constants, r0 = coarse loop
;==================================================================
DELAY: push dpl
push dph
mov dpl, r1
mov dph, r2
Delay1: mov r1, dpl
Delay2: mov r2, dph
djnz r2, $
djnz r1, Delay2
djnz r0, Delay1
pop dph
pop dpl
ret
end