;***************************************************************** ;* * ;* Integer Maths Subroutines for the 8051 microcontroller * ;* W.G.Marshall 2005 Vsn 1.2 * ;* * ;***************************************************************** ; All parameters in user-set register bank ; DIV32 requires the use of register bank 1 as well BSEG SignX: dbit 1 SignY: dbit 1 ;================================================================= ; subroutine Cr0 ; 8-Bit 2's Complement -> magnitude / Sign Bit Conversion ; ; input: r0 = signed byte ; ; output: r0 = magnitude ; Bit SignX = sign (SignX is set if r0 is a negative number) ; ; alters: ;================================================================= Cr0: xch a, r0 ; read X into accumulator clr SignX ; clear sign flag jnb acc.7, Cr0a ; X is negative if bit 7 is 1 cpl a ; X negative, find abs value inc a ; X = complement(X)+1 setb SignX ; set sign flag Cr0a: xch a, r0 ; save magnitude ret ;================================================================= ; subroutine Cr1 ; 8-Bit 2's Complement -> magnitude / Sign Bit Conversion ; ; input: r1 = signed byte ; ; output: r1 = magnitude ; Bit SignY = sign (SignY is set if r1 is a negative number) ; ; alters: ;================================================================= Cr1: xch a, r1 ; read Y into accumulator clr SignY ; clear sign flag jnb acc.7, Cr1a ; Y is negative if bit 7 is 1 cpl a ; Y negative, find abs value inc a ; Y = complement(Y)+1 setb SignY ; set sign flag Cr1a: xch a, r1 ; save magnitude ret ;=================================================================== ; subroutine Cr0r1 ; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion ; ; input: r1, r0 = signed word ; ; output: r1, r0 = magnitude ; Bit SignX = sign (SignX is set if negative number) ; ; alters: C ;=================================================================== Cr0r1: xch a, r1 clr SignX ; clear sign flag jnb acc.7, C0a ; high byte negative? setb SignX ; set sign flag xch a, r0 ; number is negative cpl a ; complement add a, #1 ; and add +1 xch a, r0 ; get MS byte cpl a ; complement addc a, #0 C0a: xch a, r1 ret ;==================================================================== ; subroutine Cr2r3 ; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion ; ; input: r3, r2 = signed word ; ; output: r3, r2 = magnitude ; Bit SignY = sign (SignY is set if negative number) ; ; alters: acc, C ;==================================================================== Cr2r3: mov a, r3 clr SignY ; clear sign flag jnb acc.7, C1a ; high byte negative? setb SignY ; set sign flag xch a, r2 ; number is negative cpl a ; complement add a, #1 ; and add +1 xch a, r2 ; get MS byte cpl a ; complement addc a, #0 mov r3, a C1a: ret ;==================================================================== ; subroutine Cr4r5 ; 16-Bit 2's Complement -> magnitude / Sign Bit Conversion ; ; input: r5, r4 = signed word ; ; output: r5, r4 = magnitude ; Bit SignY = sign (SignY is set if negative number) ; ; alters: acc, C ;==================================================================== Cr4r5: mov a, r5 clr SignY ; clear sign flag jnb acc.7, C4a ; high byte negative? setb SignY ; set sign flag xch a, r4 ; number is negative cpl a ; complement add a, #1 ; and add +1 xch a, r4 ; get MS byte cpl a ; complement addc a, #0 mov r5, a C4a: 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 SignX = sign (SignX is set if negative number) ; ; alters: acc ;==================================================================== Cr0r3: mov a, r3 clr SignX jnb acc.7, C2a ; negative if bit 7 is 1 setb SignX ; 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 C2a: ret ;================================================================== ; subroutine Mr0 ; 8-Bit magnitude / Sign Bit -> 2's Complement Conversion ; ; input: r0 = magnitude ; Bits SignX & SignY = sign bits of operands X and Y ; (set if negative) ; ; output: r0 = signed byte ; ; alters: ;================================================================== Mr0: jb SignX, Mr0b ; test X sign jb SignY, Mr0a ; test Y sign ret Mr0b: jnb SignY, Mr0a ret Mr0a: xch a, r0 ; if r0 negative, get abs value cpl a ; complement magnitude of X inc a ; r0 = complement(r0)+1 xch a, r0 ; save in 2's complement ret ; done ;==================================================================== ; subroutine Mr0r1 ; 16-Bit magnitude / Sign Bit -> 2's Complement Conversion ; ; input: r1, r0 = magnitude ; Bits SignX & SignY = sign bits of operands X and Y ; (set if negative) ; ; output: r1, r0 = signed word ; ; alters: C ;==================================================================== Mr0r1: jb SignX, Mr0r1b ; test X sign jb SignY, Mr0r1a ; test Y sign ret Mr0r1b: jnb SignY, Mr0r1a ret Mr0r1a: xch a, r0 ; negate number cpl a ; complement add a, #1 ; and add +1 xch a, r0 xch a, r1 ; get next byte cpl a ; complement addc a, #0 xch a, r1 ret ;==================================================================== ; subroutine Mr0r3 ; 32-Bit magnitude / Sign Bit -> 2's Complement Conversion ; ; input: r3, r2, r1, r0 = magnitude ; Bits SignX & SignY = sign bits of operands X and Y ; (set if negative) ; ; output: r3, r2, r1, r0 = signed word ; ; alters: acc, C ;==================================================================== Mr0r3: jb SignX, Mr0r3b ; test X sign jb SignY, Mr0r3a ; test Y sign ret Mr0r3b: jnb SignY, 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: ;==================================================================== CONV816: xch A, r0 mov r1, #0 jnb acc.7, Pos dec r1 Pos: xch a, r0 ret ;==================================================================== ; subroutine MAG16 ; 16-Bit Signed number to Magnitude conversion ; ; input: r1, r0 = X ; ; output: r1, r0 = |X| ; ; alters: C ;==================================================================== MAG16: xch a, r1 ; high byte into accumulator jnb acc.7, Mag1 ; exit if positive xch a, r0 ; number is negative cpl a ; complement add a, #1 ; add +1 xch a, r0 ; get MS byte cpl a ; complement addc a, #0 Mag1: xch a, r1 ret ;==================================================================== ; subroutine NEG16 ; 16-Bit Negate ; ; input: r1, r0 = X ; ; output: r1, r0 = -X ; ; alters: C ;==================================================================== NEG16: xch a, r0 cpl a ; complement add a, #1 ; add +1 xch a, r0 xch a, r1 ; get MS byte cpl a ; complement addc a, #0 xch a, r1 ret ;==================================================================== ; subroutine LADD8 ; 8-Bit Signed (2's Complement) Addition with Limiter ; ; input: r0 = X ; r1 = Y ; ; output: r0 = signed sum S = X + Y ; 80h < S < 7Fh ; ; alters: C, OV ;==================================================================== LADD8: xch a, r0 ; load X into acc add a, r1 ; add Y jnb OV, PosLim8 ; Exit if no overflow mov a, #7fh jnc PosLim8 ; Max positive? add a, #01h ; Limit to max negative PosLim8: xch a, r0 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 ; SignX is set if the result has a carry out ; SignY is set if the result is out of range ; ; alters: C, OV ;==================================================================== ADD16: xch a, r0 ; load X low byte into acc add a, r2 ; add Y low byte xch a, r0 ; put result in Z low byte xch a, r1 ; load X high byte into acc addc a, r3 ; add Y high byte with carry xch a, r1 ; save result in Z high byte mov SignX, C ; SignX = Carry flag mov C, OV mov SignY, C ; SignY = Overflow flag ret ;==================================================================== ; subroutine LADD16 ; 16-Bit Signed (2's Complement) Addition with Limiter ; ; input: r1, r0 = X ; r3, r2 = Y ; ; output: r1, r0 = signed sum S = X + Y ; 8000h < Z < 7FFFh ; ; alters: C, OV ;==================================================================== LADD16: call ADD16 jnb SignY, NoOver ; Exit if no overflow jnb SignX, PosLim mov r0, #00h ; Limit to max negative mov r1, #80h ret PosLim: mov r0, #0FFh ; Limit to max positive mov r1, #7fh NoOver: 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 ; SignX is set if the result has a carry out ; SignY is set if the result is out of range ; ; alters: C, OV ;==================================================================== ADD32: xch a, r0 ; load X low byte into acc add a, r4 ; add Y low byte xch a, r0 ; save result xch a, r1 ; load X next byte into acc addc a, r5 ; add Y next byte with carry xch a, r1 ; save result xch a, r2 ; load X next byte into acc addc a, r6 ; add Y next byte xch a, r2 ; save result xch a, r3 ; load X high byte into acc addc a, r7 ; add Y high byte with carry xch a, r3 mov SignX, C ; SignX = Carry flag mov C, OV mov SignY, C ; SignY = Overflow flag 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: 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: 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: C, Bits SignX & SignY ;================================================================== MUL8: 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: ;================================================================== UMUL8: push b xch a, r0 ; read X and ... mov b, r1 ; ... Y mul ab ; multiply X and Y mov r1, b ; save result high ... xch a, r0 ; ... 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, r4, Bits SignX & SignY ;==================================================================== MUL816: push b acall Cr0 ; 2's comp -> Mag/Sign acall Cr2r3 ; 2's comp -> Mag/Sign mov a, r0 ; load X into acc mov b, r2 ; load Y low into B mul ab ; multiply xch a, r0 ; save X*YL low, reload X mov r4, b ; temp save X*YL high mov b, r3 ; load Y high into B mul ab ; multiply add a, r4 ; add X*YL high and X*YH low mov r1, a ; save result clr a addc a, b ; X*YH high + 0 + carry flag mov r2, a ; save result mov r3, #0 ; MS result = 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 SignX & SignY ;==================================================================== MUL16: 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 push dph mov a, r0 mov b, r2 mul ab ; multiply XL x YL mov dpl, b ; temp save XLYL h xch a, r0 ; save XLYL l, reload XL mov b, r3 mul ab ; multiply XL x YH add a, dpl mov dpl, a ; temp save XLYH l + XLYL h clr a addc a, b mov dph, a ; temp save XLYH h + C mov a, r2 mov b, r1 mul ab ; multiply XH x YL add a, dpl mov dpl, a ; save XLYH l + XLYL h + XHYL l mov a, dph addc a, b ; (XLYH h + C) + XHYL h mov dph, a mov f0, C ; save intermediate carry mov a, r3 mov b, r1 mul ab ; multiply XH x YH add a, dph ; (XLYH h + C) + XHYL h + XHYH l mov r2, a clr a addc a, b ; XHYH h + C mov C, f0 ; retrieve intermediate carry addc a, #0 mov r3, a mov r1, dpl pop dph 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 SignX & SignY ;==================================================================== MAC16: acall MUL16 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 SignX & SignY ;=============================================================== DIV8: 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 SignX & SignY ;==================================================================== DIV16: 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 SignX & SignY ;==================================================================== DIV32: 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 08H ; Save Register Bank 1 push 09H push 0AH push 0BH push 0CH push 0DH push 0EH push 0FH push dpl push dph push B push psw setb RS0 ; Select Register Bank 1 clr RS1 mov r7, #0 ; clear partial remainder mov r6, #0 mov r5, #0 mov r4, #0 mov B, #32 ; set loop count div_lp32: pop psw 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 push psw setb RS0 ; Select Register Bank 1 clr RS1 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 pop psw ; partial remainder clr C subb a, r4 mov dpl, a mov a, 0DH subb a, r5 mov dph, a mov a, 0EH subb a, #0 mov r6, a mov a, 0FH subb a, #0 mov r7, a cpl C ; complement external borrow jnc div_321 ; update partial remainder if ; borrow mov 0FH, r7 ; update partial remainder mov 0EH, r6 mov 0DH, dph mov 0CH, dpl div_321: push psw setb RS0 ; Select Register Bank 1 clr RS1 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 pop psw mov r7, 0FH ; retrieve remainder, saved mov r6, 0EH ; before the last subtraction mov r5, 0DH mov r4, 0CH mov r3, 0BH ; retrieve quotient mov r2, 0AH mov r1, 09H mov r0, 08H pop B pop dph pop dpl pop 0FH ; Retrieve Register Bank 1 pop 0EH pop 0DH pop 0CH pop 0BH pop 0AH pop 09H pop 08H 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 SignX & SignY ;==================================================================== MULDIV: 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 SignX, 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 SignY, divn ; test Y sign setb SignY 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 SignX & 22H ;==================================================================== MACD16: 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 ; 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 acc ; Now move x data mov r1, a pop acc mov r0, a pop acc mov r3, a pop acc mov r2, a mov a, r0 push acc mov a, r1 push acc 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