* (c) 2001 University of Florida * Department of Electrical and Computer Engineering * * Computational NeuroEngineering Laboratory * in conjuction with the Wireless LAN Research Laboratory * * Author: Scott A. Morrison * E-Mail: morrisos@ufl.edu * * Advisor: Dr. Jose Principe * E-Mail: principe@cnel.ufl.edu * * Advisor: Dr. Karl Gugel * E-Mail: gugel@ecel.ufl.edu * * Date Created: 16 February 2002 * ********************************************************************** * filename = lms_sub.asm .include "lms_glb.asm" ; global variables file .sect ".subr" ********************************************************************** ********************************************************************** ************************ support routines ************************** ********************************************************************** ********************************************************************* * PROGRAM: FPINV * * WRITTEN BY: GARY A. SITTON * GAS LIGHT SOFTWARE * HOUSTON, TEXAS * MARCH 1989. * * FLOATING POINT INVERSE: R0 <= 1/R0 * * APPROXIMATE ACCURACY: 8 DECIMAL DIGITS. * INPUT RESTRICTIONS: R0 != 0.0. * REGISTERS FOR INPUT: R0. * REGISTERS USED AND RESTORED: DP AND SP. * REGISTERS ALTERED: R0-2 AND R4. * REGISTERS FOR OUTPUT: R0. * ROUTINES NEEDED: NONE. * EXECUTION CYCLES (MIN, MAX): 33 , 33. ********************************************************************** FPINV: LDF R0,R0 ; TEST F RETSZ ; RETURN NOW IF F = 0 * GET APPROXIMATION TO 1/F. FOR F = (1+M) * 2**E * AND 0 <= M < 1, USE: X[0] = (1-M/2) * 2**-E PUSH DP ; SAVE DATA PAGE POINTER LDP @MSK ; LOAD DATA PAGE POINTER PUSHF R0 ; SAVE AS FLT. PT. F = (1+M) * 2**E POP R1 ; FETCH BACK AS INTEGER XOR @MSK,R1 ; COMPLEMENT E & M BUT NOT SIGN BIT PUSH R1 ; SAVE AS INTEGER, AND BY MAGIC... POPF R1 ; R1 <= X[0] = (1-M/2) * 2**-E. POP DP ; UNSAVE DP * NEWTON ITERATION FOR: Y(X) = X - 1/F = 0 ... MPYF R1,R0,R4 ; R4 <= F * X[0] SUBRF TWO,R4 ; R4 <= 2 - F * X[0] MPYF R4,R1 ; R1 <= X[1] = X[0] * (2 - F * X[0]) MPYF R1,R0,R4 ; R4 <= F * X[1] SUBRF TWO,R4 ; R4 <= 2 - F * X[1] MPYF R4,R1 ; R1 <= X[2] = X[1] * (2 - F * X[1]) MPYF R1,R0,R4 ; R4 <= F * X[2] SUBRF TWO,R4 ; R4 <= 2 - F * X[2] MPYF R4,R1 ; R1 <= X[3] = X[2] * (2 - F * X[2]) * FOR THE LAST ITERATION: X[4] = (X[3] * (1 - (F * X[3]))) + X[3] RND R0,R4 ; ROUND F BEFORE LAST MULTIPLY RND R1,R0 ; ROUND X[3] BEFORE MULTIPLIES MPYF R0,R4 ; R4 <= F * X[3] = 1 + EPS * FINISH ITERATION AND RETURN POP R2 ; R2 <= RETURN ADDRESS BUD R2 ; RETURN (DELAYED) SUBRF ONE,R4 ; R4 <= 1 - F * X[3] = EPS MPYF R0,R4 ; R4 <= X[3] * EPS ADDF R4,R1,R0 ; R0 <= X[4] = (X[3]*(1 - (F*X[3]))) + X[3] **************************************************************************** **************************************************************************** * PROGRAM: LMS * * LMS == LMS ADAPTIVE FILTER * * EQUATIONS: y(n) = h(n,0)*x(n) + h(n,1)*x(n-1) + ... + h(n,N-1)*x(n-(N-1)) * for (i = 0; i < N; i++) * h(n+1,i) = h(n,i) + tmuerr * x(n-i) * * TYPICAL CALLING SEQUENCE: * * load R4 * load AR0 * load AR1 * load RC * load BK * CALL FIR * * ARGUMENT ASSIGNMENTS: * argument | function * ---------+----------------------- * R4 | scale factor (2 * mu * err) * AR0 | address of h(n,N-1) * AR1 | address of x(n-(N-1)) * RC | length of filter - 2 (N-2) * BK | length of filter (N) * * REGISTERS USED AS INPUT: R4, AR0, AR1, RC, BK * REGISTERS MODIFIED: R0, R1, R2, AR0, AR1, RC * REGISTER CONTAINING RESULT: R0 * * PROGRAM SIZE: 10 words * * EXECUTION CYCLES: 12 + 3(N-1) * *============================================================================== * * setup (i = 0) * ; initialize R0: LMS: MPYF3 *AR0, *AR1, R0 ; h(n,N-1) * x(n-(N-1)) -> R0 LDF 0.0,R2 ; initialize R2. * * ; initialize R1: MPYF3 *AR1++(1)%,R4,R1 ; x(n-(N-1)) * tmuerr -> R1 ADDF3 *AR0++(1),R1,R1 ; h(n,N-1) + x(n-(N-1)) * tmuerr -> R1 * * filter and update ( 1 <= i < N) * RPTB LOOP ; setup the repeat block. * * ; filter: MPYF3 *AR0--(1),*AR1,R0 ; h(n,N-1-i) * x(n-(N-1-i)) -> R0 || ADDF3 R0,R2,R2 ; multiply and add operation. * * ; update: MPYF3 *AR1++(1)%,R4,R1 ; x(n-(N-1-i)) * tmuerr -> R1 || STF R1, *AR0++(1) ; R1 -> h(n+1,N-1-(i-1)) * LOOP ADDF3 *AR0++(1),R1,R1 ; h(n,N-1-i) + x(n-(N-1-i))*tmuerr -> R1 * ADDF3 R0,R2,R0 ; add last product. STF R1,*-AR0(1) ; h(n,0) + x(n) * tmuerr -> h(n+1,0) * * return sequence * RETS ; return ******************************************************************************* * PROGRAM: MAT * * MAT == MATRIX TIMES A VECTOR OPERATION * * TYPICAL CALLING SEQUENCE: * * load AR0 * load AR1 * load AR2 * load AR3 * load R1 * CALL MAT * * * ARGUMENT ASSIGNMENTS: * argument | function * ---------+----------------------- * AR0 | address of m(0,0) * AR1 | address of v(0) * AR2 | address of p(0) * AR3 | number of rows - 1 (numrows-1) * R1 | number of columns - 2 (numcols-2) * * REGISTERS USED AS INPUT: AR0, AR1, AR2, AR3, R1 * REGISTERS MODIFIED: R0, R2, AR0, AR1, AR2, AR3, IR0, * RC, RSA, REA * * * PROGRAM SIZE: 11 * * EXECUTION CYCLES: 6 + 10 * numrows + numrows * (numcols - 1) * *============================================================================== * * setup * MAT LDI R1,IR0 ; number of columns-2 -> IR0 ADDI 2,IR0 ; IR0 = numcols * * for (i = 0; i < numrows; i++) loop over the rows. * ROWS LDF 0.0,R2 ; initialize R2 MPYF3 *AR0++(1),*AR1++(1),R0 ; m(i,0) * v(0) -> R0 * * for (j = 1; j < numcols; j++) do dot product over columns * RPTS R1 ; multiply a row by a column. * MPYF3 *AR0++(1),*AR1++(1),R0 ; m(i,j) * v(j) -> R0. || ADDF3 R0,R2,R2 ; m(i,j-1) * v(j-1) + R2 -> R2. * DBD AR3,ROWS ; counts the number of rows left. * ADDF R0,R2 ; last accumulate. STF R2,*AR2++(1) ; result -> p(i) NOP *--AR1(IR0) ; set AR1 to point to v(0). * !!! delayed branch happens here !!! * * return sequence * RETS ; return *============================================================================== * SUBROUTINE FMIEEE1 (Complete Version) * * FUNCTION: Conversion between the IEEE format and the 320C30 floating point * numbers. The number to be converted is in the lower 32 bits of R0. * The result is stored in the upper 32 bits of R0. * * Upon entering the routine, AR1 points to the following table: * (0) 0xFF800000 <-- AR1 * (1) 0xFF000000 * (2) 0x7F000000 * (3) 0x80000000 * (4) 0x81000000 * (5) 0x7F800000 * (6) 0x00400000 * (7) 0x007FFFFF * (8) 0x7F7FFFFF * * ARGUMENT ASSIGNMENTS: * argument | function * ---------+----------------------- * R0 | number to be converted * AR1 | pointer to table with constants * * REGISTERS USED AS INPUT: R0, AR1 * REGISTERS MODIFIED: R0, R1 * REGISTER CONTAINING RESULT: R0 * * NOTE: Since the stack pointer SP is used, make sure to initialize it * in the calling program. * * * CYCLES: 23 (worst case) WORDS: 34 *============================================================================= .global FMIEEE1 * FMIEEE1 LDI R0,R1 AND *+AR1(5),R1 BZ UNNORM ; If e=0, number is either 0 or unnormalized XOR *+AR1(5),R1 BNZ NORMAL ; If e<255, use regular routine * Handle NaN and infinity TSTB *+AR1(7),R0 RETSNZ ; Return if NaN LDI R0,R0 LDFGT *+AR1(8),R0 ; If positive, infinity=most positive number LDFN *+AR1(5),R0 ; If negative, infinity= most negative number RETS * Handle zeros and unnormalized numbers UNNORM TSTB *+AR1(6),R0 ; Is the msb of f equal to 1? LDFZ *+AR1(3),R0 ; If not, force the number to zero RETSZ ; and return XOR *+AR1(6),R0 ; If (msb of f)=1, make it 0 BND NEG1 LSH 1,R0 ; Eliminate sign bit and line up mantissa SUBI *+AR1(2),R0 ; Make e=-127 PUSH R0 POPF R0 ; Put number in floating point format RETS NEG1 POPF R0 NEGF R0,R0 ; If negative, negate R0 RETS * Handle the regular cases NORMAL AND3 R0,*AR1,R1 ; Replace fraction with 0 BND NEG ; Test sign ADDI R0,R1 ; Shift sign and exponent inserting 0 SUBI *+AR1(2),R1 ; Unbias exponent PUSH R1 POPF R0 ; Load this as a flt. pt. number RETS NEG POPF R0 ; Load this as a flt. pt. number NEGF R0,R0 ; Negate if original sign negative RETS * *============================================================================== * SUBROUTINE TOIEEE1 * * FUNCTION: Conversion between the 320C30 format and the IEEE floating point * numbers. The number to be converted is in the upper 32 bits of R0. * The result will be in the lower 32 bits of R0. * * Upon entering the routine, AR1 points to the following table: * (0) 0xFF800000 <-- AR1 * (1) 0xFF000000 * (2) 0x7F000000 * (3) 0x80000000 * (4) 0x81000000 * (5) 0x7F800000 * (6) 0x00400000 * (7) 0x007FFFFF * (8) 0x7F7FFFFF * * ARGUMENT ASSIGNMENTS: * argument | function * ---------+----------------------- * R0 | number to be converted * AR1 | pointer to table with constants * * REGISTERS USED AS INPUT: R0, AR1 * REGISTERS MODIFIED: R0 * REGISTER CONTAINING RESULT: R0 * * NOTE: Since the stack pointer SP is used, make sure to initialize it * in the calling program. * * * CYCLES: 31 (worst case) WORDS: 25 *============================================================================= .global TOIEEE1 * TOIEEE1 LDF R0,R0 ; Determine the sign of the number LDFZ *+AR1(4),R0 ; If zero, load appropriate number BND NEG2 ; Branch to NEG if negative (delayed) ABSF R0 ; Take the absolute value of the number LSH 1,R0 ; Eliminate the sign bit in R0 PUSHF R0 POP R0 ; Place number in lower 32 bits of R0 ADDI *+AR1(2),R0 ; Add exponent bias (127) LSH -1,R0 ; Add the positive sign CONT TSTB *+AR1(5),R0 RETSNZ ; If e>0, return TSTB *+AR1(7),R0 RETSZ ; If e=0 & f=0, return PUSH R0 POPF R0 LSH -1,R0 ; Move f right by one bit PUSHF R0 POP R0 ADDI *+AR1(6),R0 ; Add to f an msb of 1 RETS NEG2 POP R0 ; Place number in lower 32 bits of R0 BRD CONT ADDI *+AR1(2),R0 ; Add exponent bias (127) LSH -1,R0 ; Make space for the sign ADDI *+AR1(3),R0 ; Add the negative sign RETS ********************* .end ********************* ************************************************************* * PROGRAM: *VECMULT * * * * WRITTEN BY: GARY A. SITTON * * GAS LIGHT SOFTWARE * * HOUSTON, TEXAS * * FEBRUARY 1989. * * * * SCALAR - VECTOR MULTIPLY: X[I] <= X[I]*C, C IS A * * CONSTANT AND THE ARRAY X IS OF LENGTH N >= 1. * * * * MVECMULT ENTRY PROTOCOL: * * VARIABLES FOR INPUT: * * $IAD1 -> X[0], $N = N (LENGTH), * * $CNST = C, $PARMS = DATA PAGE. * * INPUT RESTRICTIONS: $N > 0. * * REGISTERS ALTERED: RC, DP, AR0 AND R0-1. * * * * RVECMULT ENTRY PROTOCOL: * * REGISTERS FOR INPUT: * * AR0 -> X[0], R0 = C, RC = N (LENGTH). * * INPUT RESTRICTIONS: RC > 0. * * REGISTERS ALTERED: RC, AR0 AND R1. * * * * REGISTERS USED AND RESTORED: SP. * * REGISTERS FOR OUTPUT: NONE. * * ROUTINES NEEDED: NONE. * ************************************************************* ; EXTERNAL MEMORY ADDRESSES .GLOBL $PARMS ; PARAMETER PAGE ADDRESS ; EXTERNAL VARIABLE ADDRESSES .GLOBL $N ; ARRAY LENGTH N .GLOBL $CNST ; ADDRESS OF CONSTANT C .GLOBL $IAD1 ; ADDRESS OF INPUT X ; EXTERNAL PROGRAM NAMES .GLOBL MVECMULT ; MEMORY ENTRY FOR SCALAR - VECTOR MULTIPLY .GLOBL RVECMULT ; REGISTER ENTRY FOR SCALAR - VECTOR MULTIPLY ; START OF PROGRAM AREA .TEXT ; MEMORY BASED PARAMETER ENTRY MVECMULT: LDP @$PARMS ; LOAD DATA PAGE POINTER LDI @$N,RC ; RC <= N LDI @$IAD1,AR0 ; AR0 -> X[0] LDF @$CNST,R0 ; R0 <= C ; REGISTER BASED PARAMETER ENTRY RVECMULT: SUBI 2,RC ; RC <= N - 2 MPYF R0,*AR0,R1 ; R1 <= C*X[0] CMPI 0,RC ; COMPARE RC TO 0 BLT SKIP1 ; IF RC < 0 THEN SKIP LOOP ; SCALAR - VECTOR MULTIPLY LOOP RPTS RC ; REPEAT INST. N-1 TIMES MPYF R0,*++AR0,R1 ; R1 <= C*X[I+1] || STF R1,*AR0 ; X[I] <= C*X[I] SKIP1: STF R1,*AR0 ; X[N-1] <= C*X[N-1] RETS ; RETURN ************************************************************* * PROGRAM: *CONMOV * * * * WRITTEN BY: GARY A. SITTON * * GAS LIGHT SOFTWARE * * HOUSTON, TEXAS * * FEBRUARY 1989. * * * * SCALAR -> VECTOR MOVE: X[I] <= C, C IS A * * CONSTANT AND THE ARRAY X IS OF LENGTH N. * * * * MCONMOV ENTRY PROTOCOL: * * VARIABLES FOR INPUT: * * $IAD1 -> X[0], $N = N (LENGTH), * * $CNST = C, $PARMS = DATA PAGE. * * INPUT RESTRICTIONS: $N > 0. * * REGISTERS ALTERED: RC, DP, AR0, AND R0. * * * * RCONMOV ENTRY PROTOCOL: * * REGISTERS FOR INPUT: * * AR0 -> X[0], R0 = C, RC = N (LENGTH). * * INPUT RESTRICTIONS: RC > 0. * * REGISTERS ALTERED: RC, AR0. * * * * REGISTERS USED AND RESTORED: SP. * * REGISTERS FOR OUTPUT: NONE. * * ROUTINES NEEDED: NONE. * ************************************************************* ; EXTERNAL MEMORY ADDRESSES .GLOBL $PARMS ; PARAMETER PAGE ADDRESS ; EXTERNAL VARIABLE ADDRESSES .GLOBL $N ; ARRAY LENGTH N .GLOBL $CNST ; ADDRESS OF CONSTANT C .GLOBL $IAD1 ; ADDRESS OF INPUT X ; EXTERNAL PROGRAM NAMES .GLOBL MCONMOV ; MEMORY ENTRY FOR CONSTANT TO VECTOR MOVE .GLOBL RCONMOV ; REGISTER ENTRY FOR CONSTANT TO VECTOR MOVE ; START OF PROGRAM AREA .TEXT ; MEMORY BASED PARAMETER ENTRY MCONMOV: LDP @$PARMS ; LOAD DATA PAGE POINTER LDI @$N,RC ; RC <= N LDI @$IAD1,AR0 ; AR0 -> X[0] LDF @$CNST,R0 ; R0 <= C ; REGISTER BASED PARAMETER ENTRY RCONMOV: SUBI 1,RC ; RC <= N - 1 ; SCALAR TO VECTOR MOVE LOOP RPTS RC ; REPEAT INST. N TIMES STF R0,*AR0++ ; X[I] <= C RETS ; RETURN ************************************************************* * PROGRAM: *VECMOV * * * * WRITTEN BY: GARY A. SITTON * * GAS LIGHT SOFTWARE * * HOUSTON, TEXAS * * FEBRUARY 1989. * * * * VECTOR MOVE: Y[I] <= X[I], I = 0,...,N-1 (N >= 1). * * * * MVECMOV ENTRY PROTOCOL: * * VARIABLES FOR INPUT: * * $IAD1 -> X[0], $IAD2 -> Y[0], * * $N = N (LENGTH), $PARMS = DATA PAGE. * * INPUT RESTRICTIONS: $N > 0. * * REGISTERS ALTERED: RC, DP, AR0-1, AND R0. * * * * RVECMOV ENTRY PROTOCOL: * * REGISTERS FOR INPUT: * * AR0 -> X[0], AR1 -> Y[0], RC = N (LENGTH). * * INPUT RESTRICTIONS: RC > 0. * * REGISTERS ALTERED: RC, AR0-1, AND R0. * * * * REGISTERS USED AND RESTORED: SP. * * REGISTERS FOR OUTPUT: NONE. * * ROUTINES NEEDED: NONE. * ************************************************************* ; EXTERNAL MEMORY ADDRESSES .GLOBL $PARMS ; PARAMETER PAGE ADDRESS ; EXTERNAL VARIABLE ADDRESSES .GLOBL $N ; ARRAY LENGTH N .GLOBL $IAD1 ; ADDRESS OF INPUT X .GLOBL $IAD2 ; ADDRESS OF INPUT Y ; EXTERNAL PROGRAM NAMES .GLOBL MVECMOV ; MEMORY ENTRY FOR VECTOR TO VECTOR MOVE .GLOBL RVECMOV ; REGISTER ENTRY FOR VECTOR TO VECTOR MOVE ; START OF PROGRAM AREA .TEXT ; MEMORY BASED PARAMETER ENTRY MVECMOV: LDP @$PARMS ; LOAD DATA PAGE POINTER LDI @$N,RC ; RC <= N LDI @$IAD1,AR0 ; AR0 -> X[0] LDI @$IAD2,AR1 ; AR1 -> Y[0] ; REGISTER BASED PARAMETER ENTRY RVECMOV: SUBI 2,RC ; RC <= N - 2 LDF *AR0++,R0 ; R0 <= X[0] CMPI 0,RC ; COMPARE RC TO 0 BLT SKIP2 ; IF RC < 0 THEN SKIP LOOP ; VECTOR MOVE LOOP RPTS RC ; REPEAT INST. N-1 TIMES LDF *AR0++,R0 ; R0 <= X[I+1] || STF R0,*AR1++ ; MOVE X[I] TO Y[I] SKIP2: STF R0,*AR1 ; MOVE X[N-1] TO Y[N-1] RETS ; RETURN .END