>>>> 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 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 0x00809854 directive MSK2 .word 0x00FE0000 0x00809854 0x00fe0000 0x00809855 directive MSK3 .word 0x0001FC00 0x00809855 0x0001fc00 0x00809856 directive MSK4 .word 0x000003FF 0x00809856 0x000003ff 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 0x00809861 nocode ;------------------------------ 0x00809861 directive stack .word 0x809C00 ; Begin stack in second RAM block for speed 0x00809861 0x00809c00 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