home *** CD-ROM | disk | FTP | other *** search
- ; \|/
- ; O O
- ; --------------------------------oOO--U--OOo--------------------------------
- ; | |
- ; | 'Maths' Macros Library. |
- ; | By Alain BROBECKER. (aka Baah) |
- ; | September 1995 |
- ; ---------------------------------------------------------------------------
- ;
- ; * This library was created in order to perform high precision fixed point
- ; calculi. I won' t explain what fixed point is in here.
- ; * A 64 bits integer is symbolised by [a|b] where a represents the 32
- ; upperbits of the integer, and b represents the 32 lowerbits.
- ; * Most of the routines are unsigned. (symbolised by 'u' being the first
- ; letter of the routine name) This was chosen because you often have operands
- ; which are always positive, so you can gain some cycles. Here is a small
- ; example to show you how to perform a signed multiplication of r0 by r1...
- ; movS r2,r0
- ; rsbMI r2,r2,#0 ; r2=Abs(r0).
- ; movS r3,r1
- ; rsbMI r3,r3,#0 ; r3=Abs(r1).
- ; umul64(r2,r3,r2,r3,r4,r5,r6) ; [r2|r3]=Abs(r0)*Abs(r1).
- ; adjust64(r2,r2,r3,premul_cst) ; r2=Abs(r0)*Abs(r1).
- ; teq r0,r1 ; Flags=r0 eor r1=Sgn(r0*r1).
- ; rsbMI r2,r2,#0 ; r2=Sgn(r0*r1)*Abs(r0)*Abs(r1)=r0*r1.
- ; * The udiv64 routine performs a 64 by 32 bits division. But if
- ; [m1|m2]>m3*2^32, (so, if m1>m3), normally an overflow shall be generated.
- ; My routine does not handle this, so beware. (it does not happen very often)
- ; To understand the udiv64 rout in details, you must know that the CS
- ; condition is equivalent to an unsigned higher or same.
- ; * Each macro has a header which contains...
- ; IN ----- Entry parameters and constants.
- ; OUT ---- Shows what is the result, and where it is stored.
- ; KILL --- Lists all registers modified by the function.
- ; EXTRA -- Sometimes, some IN registers can be the same as some
- ; temporary or OUT registers. This will tell it to you.
-
-
- ; ---------------------------------------------------------------------------
- ; IN ----- m2. (positive)
- ; OUT ---- [m0|m1]=sqr(m2).
- ; KILL --- [m0|m1],m3,m4,flags.
- ; EXTRA -- m2=m0 or m3 or m4.
- macro usqr64 m0,m1,m2,m3,m4
- { mov m1,m2,lsr #16 ; m1=up(m2).
- sub m3,m2,m1,lsl #16 ; m3=down(m2).
- mul m0,m1,m1 ; m0=up(m2)*up(m2).
- mul m4,m3,m1 ; m4=up(m2)*down(m2).
- mul m1,m3,m3 ; m1=down(m2)*down(m2).
- addS m1,m1,m4,lsl #17
- adc m0,m0,m4,lsr #15 ; [m0|m1]=64 bits result.
- }
-
-
- ; ---------------------------------------------------------------------------
- ; IN ----- m2,m3. (positive)
- ; OUT ---- [m0|m1]=m2*m3.
- ; KILL --- [m0|m1],m4,m5,m6,flags.
- ; EXTRA -- [m2|m3]=[m0|m1].
- macro umul64 m0,m1,m2,m3,m4,m5,m6
- { mov m4,m2,lsr #16 ; m4=up(m2).
- sub m5,m2,m4,lsl #16 ; m5=down(m2).
- mov m0,m3,lsr #16 ; m0=up(m3).
- sub m1,m3,m0,lsl #16 ; m1=down(m3).
- mul m6,m5,m0 ; m6=down(m2)*up(m3).
- mul m0,m4,m0 ; m0=up(m2)*up(m3).
- mlaS m6,m1,m4,m6 ; Carry+m6=up(m2)*down(m3)+down(m2)*up(m3).
- adc m0,m0,m6,lsr #16
- mul m1,m5,m1 ; m1=down(m2)*down(m3).
- addS m1,m1,m6,lsl #16
- adc m0,m0,#0 ; [m0|m1]=m2*m3.
- }
-
-
- ; ---------------------------------------------------------------------------
- ; IN ----- [m1|m2],m3. (positive)
- ; OUT ---- m0=[m1|m2]/m3.
- ; KILL --- m0,m4,m5.
- ; EXTRA -- [m1|m2]=[m4|m5].
- macro udiv64 m0,m1,m2,m3,m4,m5
- { mov m0,#0 ; m0=0.
- addS m5,m2,m2 ; Perform a 'movS [m4|m5],[m1|m2],lsl #1'.
- adcS m4,m1,m1
- #set N=31
- #rept 31
- cmpCC m4,m3 ; If CC, then flags=m4-m3.
- subCS m4,m4,m3 ; If m4+Carry>m3 then substract m3.
- addCS m0,m0,#1<<N ; And quotient=quotient+1<<N.
- addS m5,m5,m5 ; Perform a 'movS [m4|m5],[m4|m5],lsl #1'.
- adcS m4,m4,m4
- #set N=N-1
- #endr
- cmpCC m4,m3 ; If CC, then flags=m4-m3.
- addCS m0,m0,#1 ; If m4+Carry>m3 quotient+=1.
- }
-
-
- ; ---------------------------------------------------------------------------
- ; IN ----- m1,m2. And c0=constant is the premultiplication factor.
- ; OUT ---- m0=[m1|m2]>>c0.
- ; KILL --- m0.
- ; EXTRA -- m1=m0.
- macro adjust64 m0,m1,m2,c0
- { mov m0,m1,lsl #32-c0
- add m0,m0,m2,lsr #c0
- }
-
-
- ; ---------------------------------------------------------------------------
- ; IN ----- [m2|m3],[m4|m5].
- ; OUT ---- [m0|m1]=[m2|m3]+[m4|m5].
- ; KILL --- [m0|m1],flags.
- ; EXTRA -- [m2|m3] or [m4|m5]=[m0|m1].
- macro add64 m0,m1,m2,m3,m4,m5
- { addS m1,m3,m5
- adc m0,m2,m4
- }
-
-
- ; ---------------------------------------------------------------------------
- ; IN ----- [m2|m3],[m4|m5].
- ; OUT ---- [m0|m1]=[m2|m3]-[m4|m5].
- ; KILL --- [m0|m1],flags.
- ; EXTRA -- [m2|m3] or [m4|m5]=[m0|m1].
- macro sub64 m0,m1,m2,m3,m4,m5
- { subS m1,m3,m5
- sbc m0,m2,m4
- }
-