**
**
** $VER: Encoder.asm 1.2 (21.08.2000)
**
**

        OPT P=68030/68882,ALINK


        INCLUDE "Exec/Types.i"
        INCLUDE "Exec.i"


*----------------------------------------------------------------------------------------------------*
*======================================= Fonctions optimisées =======================================*
*----------------------------------------------------------------------------------------------------*

        IFNE CPU_TYPE-68020

;** ScaleFactorCalc_double

        SECTION "_ScaleFactorCalc_double:0",CODE

        XDEF    _ScaleFactorCalc_double


;void ScaleFactorCalc_double(UBYTE *pbScalar, REAL pdSample[12][32], ULONG iSBLimit)

_ScaleFactorCalc_double:

                PUSH    d2/a2,ScaleFactorCalc_DBL

                DEFINE  ScaleFactorCalc_DBL
                ULONG   sfcD_pbScalar
                ULONG   sfcD_pdSample
                ULONG   sfcD_iSBLimit

                move.l  sfcD_iSBLimit(sp),d2    ; iSBLimit
                move.l  sfcD_pbScalar(sp),a0    ; pbScalar
                move.l  sfcD_pdSample(sp),a1    ; pdSample

                subq.w  #1,d2

        ;------ Boucle principale (i)

.i_loop         movea.l a1,a2
                fabs.d  (a1)+,fp0               ; ds = fabs(*pSamples)

        ;------ Boucle interne (j)

                moveq   #10,d0

.j_loop         adda.w  #32*8,a2                ; pSamples += SBLIMIT
                fabs.d  (a2),fp1                ; d = fabs(*pSamples)

        ;------ if (ds < d) ds = d;

                fcmp.x  fp1,fp0
                fboge   .j_end

                fmove.x fp1,fp0

.j_end          dbra    d0,.j_loop

                fmove.d fp0,-(sp)               ; u.f = real;
                move.w  (sp),d1
                andi.w  #$7FF0,d1
                move.w  #$400,d0
                lsr.w   #4,d1
                sub.w   d1,d0                   ; e = ( 1024 - ((u.s[0] & 0x7FF0) >> 4) ) * 3

        IFEQ    CPU_TYPE-68060
                muls.w  #3,d0
        ELSE
                move.w  d0,d1
                add.w   d0,d0
                add.w   d1,d0                   ; d0 = 3.d0
        ENDC

                move.w  (sp),d1
                andi.w  #$F,d1
                ori.w   #$41D0,d1
                move.w  d1,(sp)                 ; u.s[0] = (u.s[0] & 0x000F) | NEW_EXP
                fmove.d (sp)+,fp0
                fmove.l fp0,d1                  ; m = (int) u.f

        ;------ if (m > 1704458901) e -= 3

                cmpi.l  #$6597FA95,d1
                bls.s   .Check_m2

                subq.l  #3,d0
                bra.s   .Adjust_exp

        ;------ else if (m > 1352829926) e -= 2

.Check_m2       cmpi.l  #$50A28BE6,d1
                bls.s   .Check_m3

                subq.l  #2,d0
                bra.s   .Adjust_exp

        ;------ else if (m > 1073741824) e -= 1

.Check_m3       cmpi.l  #$40000000,d1
                bls.s   .Adjust_exp

                subq.l  #1,d0

        ;------ if (e < 0) e = 0

.Adjust_exp     bpl.s   .Limit_exp

                moveq   #0,d0

        ;------ if (e > SCALE_RANGE - 2) e = SCALE_RANGE - 2

.Limit_exp      cmpi.l  #$3E,d0
                bls.s   .End

                moveq   #$3E,d0

.End            move.b  d0,(a0)+                ; *pbScalar++ = GetIndex(ds);
                dbra    d2,.i_loop

.Exit           POP     ScaleFactorCalc_DBL
                rts

;**

        ENDC

;** PutBitsASM (C)

        SECTION "PutBitsASM",CODE

;void CoderC::PutBitsASM(s_OutputStream *pStreamDatas, UWORD *buffer, UWORD *lastpos)

        XDEF    PutBitsASM__CoderC__TP22s_OutputStream__CoderCPUsPUs
        XREF    WriteBuffer__CoderC__T

    STRUCTURE   s_OutputStream
        ULONG   pOutputBuffer
        ULONG   iOB_BitIndex
        ULONG   iOB_TotalBits
        ULONG   iOB_BitsFree
    ENDSTRUCT   s_OutputStream

PutBitsASM__CoderC__TP22s_OutputStream__CoderCPUsPUs:

                PUSH    d2-d6/a2-a4/a6,PutBitsASM

                DEFINE  PutBitsASM
                APTR    ClassBase
                APTR    pStreamDatas
                APTR    pBuffer
                APTR    pLastPos

                movea.l pBuffer(sp),a3
                movea.l pLastPos(sp),a4
                movea.l pStreamDatas(sp),a2
                move.l  iOB_BitsFree(a2),d5
                move.l  iOB_BitIndex(a2),d6
                movea.l pOutputBuffer(a2),a6

.start          move.w  (a3)+,d2                ; Bitfield length
                ext.l   d2
                move.l  d2,d3                   ; iFieldSize = iLength
                move.w  (a3)+,d4                ; Value.
                ext.l   d4
                move.l  d4,d0
                sub.l   d5,d3
                ble.s   .Insert

        ;------ si iReminder > 0

                sub.l   d3,d2                   ; iFieldSize -= iReminder
                lsr.l   d3,d0                   ; iValue >> iReminder

.Insert         bfins   d0,(a6){d6:d2}          ; Insérer les nouveaux bits.
                add.l   d2,d6                   ; pStreamDatas->iOB_BitIndex += iFieldSize
                sub.l   d2,d5                   ; pStreamDatas->iOB_BitsFree -= iFieldSize
                bne.s   .DoReminder

        ;------ Tampon plein.

                move.l  d6,iOB_BitIndex(a2)

                move.l  ClassBase(sp),-(sp)
                jsr     WriteBuffer__CoderC__T
                addq.w  #4,sp

                clr.l   d6
                move.l  iOB_TotalBits(a2),d5

        ;------ Traiter le reste s'il existe.

.DoReminder     tst.l   d3
                ble.s   .EndLoop

                bfins   d4,(a6){0:d3}

                add.l   d3,d6
                sub.l   d3,d5

.EndLoop        cmpa.l  a4,a3
                bcs.s   .start

                move.l  d5,iOB_BitsFree(a2)
                move.l  d6,iOB_BitIndex(a2)

.End            POP     PutBitsASM
                rts

;**
;** UpdateCRC

        SECTION "_UpdateCRC:0",CODE

;UWORD UpdateCRC(ULONG iData, UWORD wLength, UWORD wCRC)

        XDEF    _UpdateCRC

_UpdateCRC:     PUSH    d2-d4,UpdateCRC

; NOTE : Le prototype de la fonction permet au compilateur de placer les données requises
;        directement dans les bons registres.
;
;               d2  crc_Checksum
;               d1  crc_Length
;               d0  crc_Data

                ror.l   d1,d0                   ; Justifier "data" à gauche.
                subq.w  #1,d1

.CRCLoop        moveq   #0,d3
                asl.w   #1,d2                   ; wCRC <<= 1, sr[carry] placé.
                addx.l  d3,d3                   ; iCarry = sr[carry]
                moveq   #0,d4
                asl.l   #1,d0                   ; sr[carry] = Bit suivant de "data"
                addx.l  d4,d4                   ; Bit suivant de "data" (= sr[carry]
                eor.l   d4,d3
                beq.b   .EndLoop                ; !iCarry ^ !(iData & iMasking) == FALSE
                                                ; <==> iCarry ^ (idata & iMasking) == FALSE

                eori.w  #$8005,d2               ; wCRC ^= 0x8005

.EndLoop        dbra    d1,.CRCLoop

                move.w  d2,d0
                POP     UpdateCRC
                rts

;**

        END

