>>>> DSK3A C3x DSP Starter Kit Assembler Rev 1.17
>>>> (c) Copyright 1994-1995 Texas Instruments Incorporated
>>>> Mon Oct 27 08:18:37 1997
>>>> MATH.ASM
>>>>
>>>>
>>>> PASS 1 Complete
>>>> Errors: 0  Warnings: 0
>>>>
0x00809802 nocode     ;---------------------------------------------------------------------
0x00809802 nocode     ; MATH.ASM
0x00809802 nocode     ; Keith Larson
0x00809802 nocode     ; TMS320 DSP Applications
0x00809802 nocode     ; (C) Copyright 1996
0x00809802 nocode     ; Texas Instruments Incorporated
0x00809802 nocode     ;
0x00809802 nocode     ; This is unsupported freeware with no implied warranties or
0x00809802 nocode     ; liabilities.  See the disclaimer document for details
0x00809802 nocode     ;---------------------------------------------------------------------;
0x00809802 nocode     ; This example shows several math algorithms implimented on the       ;
0x00809802 nocode     ; TMS320C3x.  For more information regarding these algorithm see      ;
0x00809802 nocode     ; the TMS320C3x users guide, applications manuals and designer        ;
0x00809802 nocode     ; notebook pages. (either download from the FTP or BBS sites or       ;
0x00809802 nocode     ; contact the product information center)                             ;
0x00809802 nocode     ;                                                                     ;
0x00809802 nocode     ; These functions are written for readability, not speed.  You can    ;
0x00809802 nocode     ; find more information in the see the C3x Users Guide, Applications  ;
0x00809802 nocode     ; Book, Designer Notebook Pages, Compiler manual or Textbooks.        ;
0x00809802 nocode     ;                                                                     ;
0x00809802 nocode     ; In this example, the value 3.0000 is continuously loaded into R0    ;
0x00809802 nocode     ; for each function.  Functions are then called and the result is     ;
0x00809802 nocode     ; returned in R0.  To view the registers in floating point you can    ;
0x00809802 nocode     ; use the F3 key, which always pop back to the default hex display,   ;
0x00809802 nocode     ; or you can view the contents of the floating point registers using  ;
0x00809802 nocode     ; the following two methods                                           ;
0x00809802 nocode     ;                                                                     ;
0x00809802 nocode     ; CMD>MEMF _F0      This will open a floating point memory window     ;
0x00809802 nocode     ;                   whose 'view' begins at the context storage area   ;
0x00809802 nocode     ;                >> _F0 is a symbol, and is therefor case sensitive <<;
0x00809802 nocode     ;                                                                     ;
0x00809802 nocode     ; From Windows, open another DOS prompt (DOS window), shrink it to    ;
0x00809802 nocode     ; be in the Windowed mode (alt enter).  The go to 'settings' and set  ;
0x00809802 nocode     ; the window to run as a background task.  At this time, you should   ;
0x00809802 nocode     ; also set the debugger to run as a background task.  Then execute    ;
0x00809802 nocode     ; the register view utility with NO reset arguments.  (If you do,     ;
0x00809802 nocode     ; comm link to the debugger will crash).  IE                          ;
0x00809802 nocode     ;                                                                     ;
0x00809802 nocode     ; From another DOS box, run the following program...                  ;
0x00809802 nocode     ;                                                                     ;
0x00809802 nocode     ; C:\DSKTOOLS\REGVIEW [LPTx]                                          ;
0x00809802 nocode     ;---------------------------------------------------------------------
0x00809802 nocode     ;  NOTES ABOUT FLOATING POINT NUMBERS
0x00809802 nocode     ;  ----------------------------------
0x00809802 nocode     ;  By knowing that the exponent and mantissa are both two's compliment values
0x00809802 nocode     ;  and also knowing that a floating point number is a very close approximation
0x00809802 nocode     ;  of the same number expressed in log2 form (see DNP #22), a quick inversions
0x00809802 nocode     ;  and square roots can be implimented with simple functions.  For example
0x00809802 nocode     ;  a quick inverse is calculated by negating the exponent and mantissa bits.
0x00809802 nocode     ;
0x00809802 nocode     ;  Furthermore a shift is all that is required to create a square root.
0x00809802 nocode     ;  Albeit that the sign bit that is in the middle of the bit field must
0x00809802 nocode     ;  be accounted for.  Also note the use of NOT mnemonic instead of NEGI.
0x00809802 nocode     ;  In this case a 1's compliment, which is very close to a 2's compliment
0x00809802 nocode     ;  is desired since there is no carry or modify of the sign bit.
0x00809802 nocode     ; --------------------------------------------------------------------;
0x00809802 nocode     ; This example does not use 0x809800 and 0x809801 since the           ;
0x00809802 nocode     ; bootloader uses these locations for mini call stack space during    ;
0x00809802 nocode     ; the boot process.  By avoiding these locations this file can be     ;
0x00809802 nocode     ; either loaded or bootloaded.  For this app this is unlikely to be   ;
0x00809802 nocode     ; a problem, but is included as a reminder.                           ;
0x00809802 nocode     ;---------------------------------------------------------------------;
0x00809802 directive          .start "CODE",0x809802 ; Start assembling CODE section here
0x00809802 directive          .sect  "CODE"          ;
0x00809802 directive          .entry  SAMPLE         ; Debugger entry point
0x00809802 nocode             ;----------------------
0x00809802 0x50700080 SAMPLE  ldp     @stack         ; Load a data page
0x00809803 0x08349861         ldi     @stack,SP      ; Load a stack pointer
0x00809804 0x07601400 OUTER   ldf     3.00,R0        ; Load value to send to function
0x00809805 0x6280980d         call    SQRT           ; Call function
0x00809806 0x07601400         ldf     3.00,R0        ;
0x00809807 0x62809826         call    INVF           ;
0x00809808 0x07601400         ldf     3.00,R0        ;
0x00809809 0x62809857         call    FLOG2          ;
0x0080980a 0x07601400         ldf     3.00,R0        ;
0x0080980b 0x62809833         call    LOG2           ;
0x0080980c 0x6a00fff7         b       OUTER          ; Do it again!
0x0080980d nocode     ******************************************************************************
0x0080980d nocode     * R0=SQRT(R0)
0x0080980d nocode     *   Calculates the square root of the value of R0 and
0x0080980d nocode     *   returns the result in R0.
0x0080980d nocode     ******************************************************************************
0x0080980d 0x04608000 SQRT:   cmpf    0.0,R0        ;
0x0080980e 0x43e0f800         ldflt   -1,R0         ; if x<0 return -1 (error)
0x0080980f 0x42e08000         ldfeq   0.0,R0        ; if x == 0, return 0
0x00809810 0x78880000         retsle                ; return if X<=0
0x00809811 nocode          ;  pushf   R1            ; R1,R2 used for temps
0x00809811 nocode          ;  pushf   R2            ;
0x00809811 0x07010000         ldf     R0,R1         ;
0x00809812 0x09e10001         lsh     1,R1          ; concatenate mantissa field to exponent
0x00809813 0x0fa10000         pushf   R1            ; Access R0's bit fields as integers
0x00809814 0x0e210000         pop     R1            ;
0x00809815 0x0d810001         not     R1,R1         ; invert bits, equivelent to log inverse
0x00809816 0x03e1ffff         ash     -1,R1         ; quick square root
0x00809817 0x0f210000         push    R1            ; put back as float
0x00809818 0x0ea10000         popf    R1            ;
0x00809819 0x09e1ffff         lsh     -1,R1         ; restore a sign bit
0x0080981a 0x0a60f000         mpyf    0.5,R0        ;
0x0080981b nocode             ;----------------------------------------------
0x0080981b nocode             ; Now iterate Newton Raphson reduction 5 times
0x0080981b nocode             ;----------------------------------------------
0x0080981b 0x087b0004         ldi     4,RC          ; Set up a block repeat (expand for speed!)
0x0080981c 0x64809820         rptb    NR_SQRT       ;
0x0080981d nocode             ;---------------------
0x0080981d 0x24820101         mpyf3   R1,R1,R2      ; R0 = x[0] * (v/2)
0x0080981e 0x0a020000         mpyf    R0,R2         ; R0 = (v/2) * x[0] * x[0]
0x0080981f 0x19620400         subrf   1.5,R2        ; R0 = 1.5 - (v/2) * x[0] * x[0]
0x00809820 0x0a010002 NR_SQRT mpyf    R2,R1         ; x[1] = x[0] * (1.5 - v/2 * x[0] * x[0])
0x00809821 nocode             ;---------------------
0x00809821 0x11010001         rnd     R1,R1
0x00809822 0x0a000001         mpyf    R1,R0         ; sqrt(x) = x * sqrt(1/x)
0x00809823 0x0a601000         mpyf    2.0,R0
0x00809824 nocode          ;  popf    R2            ; restore temps if used
0x00809824 nocode          ;  popf    R1            ;
0x00809824 0x78800000         RETS
0x00809825 nocode     ******************************************************************************
0x00809825 nocode     * R0=INVF(R0)
0x00809825 nocode     *   Calculates the inverse float of the value of R0 and
0x00809825 nocode     *   returns the result in R0.
0x00809825 nocode     ******************************************************************************
0x00809825 directive  MASK    .word   0xFF7FFFFF    ; Mask for fast inverse float
0x00809825 0xff7fffff <word>
0x00809826 nocode     INVF: ; pushf   R1            ; R1,R2 used for temps
0x00809826 nocode           ; pushf   R2            ;
0x00809826 0x07010000         ldf     R0,R1         ;
0x00809827 0x0fa10000         pushf   R1            ; Access R0's bit fields as integers
0x00809828 0x0e210000         pop     R1            ;
0x00809829 0x1aa19825         xor     @MASK,R1      ; invert bits. except sign, eq to log inverse
0x0080982a 0x0f210000         push    R1            ; put back as float
0x0080982b 0x0ea10000         popf    R1            ;
0x0080982c nocode             ;----------------------------------------------
0x0080982c nocode             ; Now iterate Newton Raphson reduction 5 times
0x0080982c nocode             ;----------------------------------------------
0x0080982c 0x087b0004         ldi     4,RC          ; Set up a block repeat (expand for speed!)
0x0080982d 0x64809830         rptb    NR_INV        ;
0x0080982e nocode             ;---------------------
0x0080982e 0x24820001         mpyf3   R1,R0,R2      ; R0 = v * x[0]
0x0080982f 0x19621000         subrf   2.0,R2        ; R0 = 2.0 - v * x[0]
0x00809830 0x0a010002 NR_INV  mpyf    R2,R1         ; R2 = x[1] = x[0] * (2.0 - v * x[0])
0x00809831 nocode             ;---------------------
0x00809831 0x07000001         ldf     R1,R0
0x00809832 0x78800000         rets
0x00809833 nocode     ;----------------------------------------
0x00809833 nocode     ; LOG2() FUNCTION USING DNP#22 METHOD
0x00809833 nocode     ;----------------------------------------
0x00809833 0x04608000 LOG2:   cmpf    0.0,R0         ; Exit if value is <= Zero
0x00809834 0x4460f800         ldfle   -1,R0          ; if x<=0 return -1 (error)
0x00809835 0x78880000         retsle                 ; return if X<=0
0x00809836 nocode             ;----------------------
0x00809836 0x087b0002         ldi     2,RC           ; Set up block repeat
0x00809837 0x64809840         rptb    LOG2B          ;
0x00809838 nocode             ;----------------------
0x00809838 0x0fa00000         pushf   R0             ; save all bits
0x00809839 0x06e00000         lde     1.0,R0         ; Set exp bits to zero leaving only mantissa
0x0080983a 0x0a000000         mpyf    R0,R0          ; M^2
0x0080983b 0x0a000000         mpyf    R0,R0          ; M^4
0x0080983c 0x0a000000         mpyf    R0,R0          ; M^8
0x0080983d 0x0a000000         mpyf    R0,R0          ; M^16
0x0080983e 0x0a000000         mpyf    R0,R0          ; M^32
0x0080983f 0x0a000000         mpyf    R0,R0          ; M^64
0x00809840 0x0a000000 LOG2B   mpyf    R0,R0          ; M^128  (M^256 not allowed... overflow)
0x00809841 0x0fa00000         pushf   R0
0x00809842 nocode             ;--------------------------------
0x00809842 nocode             ; Now reconstruct all bits...
0x00809842 nocode             ;--------------------------------
0x00809842 0x0e200000         pop     R0
0x00809843 0x09e0ffeb         lsh     -21,R0         ;
0x00809844 0x02a09856         and     @MSK4,R0       ;
0x00809845 0x0e210000         pop     R1             ;
0x00809846 0x09e1fff2         lsh     -14,R1         ;
0x00809847 0x02a19855         and     @MSK3,R1       ;
0x00809848 0x10000001         or      R1,R0          ;
0x00809849 0x0e210000         pop     R1             ;
0x0080984a 0x09e1fff9         lsh     -7,R1          ;
0x0080984b 0x02a19854         and     @MSK2,R1       ;
0x0080984c 0x10000001         or      R1,R0          ;
0x0080984d 0x0e210000         pop     R1             ; Original value
0x0080984e 0x02a19853         and     @MSK1,R1       ;
0x0080984f 0x10000001         or      R1,R0          ;
0x00809850 nocode             ;----------------------
0x00809850 0x05800000         float   R0,R0          ;
0x00809851 0x0a209860         mpyf    @FLOG2SC,R0    ; Mpy by scale factor
0x00809852 nocode             ;----------------------
0x00809852 0x78800000         rets
0x00809853 directive  MSK1   .word    0xFF000000
0x00809853 0xff000000 <word>
0x00809854 directive  MSK2   .word    0x00FE0000
0x00809854 0x00fe0000 <word>
0x00809855 directive  MSK3   .word    0x0001FC00
0x00809855 0x0001fc00 <word>
0x00809856 directive  MSK4   .word    0x000003FF
0x00809856 0x000003ff <word>
0x00809857 nocode     ;----------------------------------------
0x00809857 nocode     ; FLOG2() Ultra Fast LOG2 FUNCTION
0x00809857 nocode     ;----------------------------------------
0x00809857 0x04608000 FLOG2:  cmpf    0.0,R0         ; Exit if value is <= Zero
0x00809858 0x4460f800         ldfle   -1,R0          ; if x<=0 return -1 (error)
0x00809859 0x78880000         retsle                 ; return if X<=0
0x0080985a 0x09e00001         lsh     1,R0           ; Concatenate mantissa to exponent
0x0080985b 0x0fa00000         pushf   R0             ; Convert 'fast log' to int, then float
0x0080985c 0x0e200000         pop     R0             ; At this point result is 2^24 to large
0x0080985d 0x05800000         float   R0,R0          ;
0x0080985e 0x0a209860         mpyf    @FLOG2SC,R0    ; Mpy by scale factor
0x0080985f 0x78800000         rets                   ;
0x00809860 directive  FLOG2SC .float  pow(2.0,-24.0) ; Scale factor for properly scaled answer
0x00809860 0xe8000000 <float>
0x00809861 nocode     ;------------------------------
0x00809861 directive  stack   .word   0x809C00       ; Begin stack in second RAM block for speed
0x00809861 0x00809c00 <word>
0x00809862 directive          .end
>>>>
>>>> PASS 2 Complete
>>>> Errors: 0  Warnings: 0
>>>>
>>>> ENTRY 0x00809802
>>>>
>>>> Symbol reference table           Type  Addressable
>>>> ref     Default_sect 0x00809802  1     1
>>>> ref             CODE 0x00809802  1     1
>>>> ref           SAMPLE 0x00809802  1     1
>>>> ref            OUTER 0x00809804  1     1
>>>> ref             SQRT 0x0080980d  1     1
>>>> ref          NR_SQRT 0x00809820  1     1
>>>> ref             MASK 0x00809825  1     1
>>>> ref             INVF 0x00809826  1     1
>>>> ref           NR_INV 0x00809830  1     1
>>>> ref             LOG2 0x00809833  1     1
>>>> ref            LOG2B 0x00809840  1     1
>>>> ref             MSK1 0x00809853  1     1
>>>> ref             MSK2 0x00809854  1     1
>>>> ref             MSK3 0x00809855  1     1
>>>> ref             MSK4 0x00809856  1     1
>>>> ref            FLOG2 0x00809857  1     1
>>>> ref          FLOG2SC 0x00809860  2     1
>>>> ref            stack 0x00809861  1     1
>>>>
>>>>        Output section start       end         length
>>>> sect     Default_sect 0x00809802  0x00809802  0x00000000
>>>> sect             CODE 0x00809802  0x00809862  0x00000060
>>>>
>>>>
>>>> END DSK
