www.pudn.com > Blackfin_Mpeg_2_4.zip > hpel_fs.asm


/******************************************************************************* 
Copyright(c) 2000 - 2002 Analog Devices. All Rights Reserved. 
Developed by Joint Development Software Application Team, IPDC, Bangalore, India 
for Blackfin DSPs  ( Micro Signal Architecture 1.0 specification). 
 
By using this module you agree to the terms of the Analog Devices License 
Agreement for DSP Software.  
******************************************************************************** 
Module Name     : hpel_fs.asm 
Label Name      : __hpel 
Version         :   1.0 
Change History  : 
 
                Version     Date          Author            Comments 
                1.0         07/02/2001    Vijay             Original  
 
Description     : The assembly function is used by the motion estimation routine 
                  to give a half pixel correction to the integer pixel motion  
                  vector. This will check whether any interpolated blocks with  
                  half pixel accuracy in all the 8 directions of the integer  
                  pixel motion vector is having a lesser MAD. If it finds a  
                  block with better MAD, it adds an offset to the X and Y  
                  ectors and will make that MAD as the current MAD. If X-vector  
                  is at the extreme negative end of the search range, the half  
                  pixel estimations with X-offset = -1 are skipped. Similarly,  
                  if Y-vector is at the extreme negative end of the search  
                  range, half pixel estimations with Y-offset = -1 are skipped. 
 
Prototype       : void _hpel(struct *input_parameters); 
 
                  Input : The input to this routine is a pointer to a structure  
                  containing the following elements 
 
                    Structure : 
                        struct { 
                                    int least_mad; 
                            -> The value of the least MAD after searching the  
                               search window fully  
                                    unsigned char *add_least_mad; 
                            -> Address of the block having the least MAD  
                                    int vert_mv; 
                            -> Vertical integer motion vector  
                                    int hor_mv; 
                            -> Horizontal integer motion vector  
                                    int curr_ver_mv_off; 
                            -> Current hpel offset for the vertical motion  
                               vector  
                                    int curr_hor_mv_off; 
                            -> Current hpel offset for the horizontal motion  
                               vector  
                                    int prev_ver_mv_off; 
                            -> Previous hpel offset for the vertical motion  
                               vector  
                                    int prev_hor_mv_off; 
                            -> Previous hpel offset for the horizontal motion  
                               vector  
                                    int hor_size; 
                            -> Horizontal size of the video frame  
                                    unsigned char *tgt_blk_add; 
                            -> Start address of the target block  
                                    int scaled_left_search_boundary; 
                            -> 2*2^(search_factor + 1);  
                                }input_parameters; 
 
                  The first four elements of the structure are obtained from the 
                  output structure of the mve_core routine. The next four  
                  elements are modified by this routine. The last three elements 
                  should have the appropriate values which can be obtained from  
                  the elements of the input structure of the mve_core routine. 
 
Registers used  : R0-R7, P0, P4, P5. 
 
Performance     : 
                Code size : 240 Bytes. 
*******************************************************************************/ 
.section L1_code; 
.align 8; 
.global _hpel; 
.extern __hpel_core2; 
.extern __hpel_core1; 
     
_hpel: 
 
    [--SP] = (R7:4, P5:4); 
    P4 = R0; 
    [--SP] = RETS; 
    P0 = 260; 
    SP -= P0; 
    R7 = SP;                // Address of the first temporary buffer 
    SP -= P0; 
    P5 = SP;                // Address of the second temporary buffer 
    R0 = R0 - R0 (NS) || R6 = [P4 + 40]; 
    R6 = R0 - R6 (NS) || R4 = [P4 + 8]; 
    R5 = [P4 + 12]; 
    CC = R5 == R6; 
    IF CC JUMP BRANCH1; 
     
/********************* HOR_OFFSET = -1    VER_OFFSET = 0 *******************/ 
     
    R0 = -1; 
    R0 = R0 - R0 (NS) || [P4 + 20] = R0; 
    [P4 + 16] = R0; 
    R0 = P4; 
    R1 = R7; 
    CALL __hpel_core1;      // Averages and stores into buffer 
                            // Finds MAD between averaged block(buffer1) and  
                            // target block 
BRANCH1: 
    CC = R4 == R6;          // If Vertical-offset == R6, skip 2nd,3rd,4th hpel  
                            // estimations(with Y = -1) 
    IF CC JUMP BRANCH4; 
    CC = R5 == R6; 
    IF CC JUMP BRANCH2; 
     
/****************************  HOR_OFFSET = -1   VER_OFFSET = -1 **************/ 
     
    R0 = -1; 
    [P4 + 20] = R0; 
    [P4 + 16] = R0; 
    R0 = P4; 
    R1 = R7; 
    R2 = P5; 
    CALL __hpel_core2;      // Averages and stores into buffer 
     
/********************  HOR_OFFSET = 0    VER_OFFSET = -1 **********************/ 
BRANCH2: 
    R0 = -1; 
    R0 = R0 - R0 (NS) || [P4 + 16] = R0; 
    [P4 + 20] = R0; 
    R0 = P4; 
    R1 = R7; 
    CALL __hpel_core1;      // Averages and stores into buffer 
                            // Finds MAD between averaged block(buffer1) and  
                            // target block 
     
/************************  HOR_OFFSET = 1    VER_OFFSET = -1 *****************/ 
     
    R0 = -1; 
    R0 = R0.L * R0.L (IS) || [P4 + 16] = R0; 
    [P4 + 20] = R0; 
    R0 = P4; 
    R1 = R7; 
    R2 = P5; 
    CALL __hpel_core2;      // Averages and stores into buffer 
     
/**********************  HOR_OFFSET = 1 VER_OFFSET = 0 ***********************/ 
     
BRANCH4: 
    R0 = 1; 
    R0 = R0 - R0 (NS) || [P4 + 20] = R0; 
    [P4 + 16] = R0; 
    R0 = P4; 
    R1 = R7; 
    CALL __hpel_core1;      // Averages and stores into buffer 
                            // Finds MAD between averaged block(buffer1) and  
                            // target block 
     
/**************************  HOR_OFFSET = 1     VER_OFFSET = 1 ****************/ 
    R0 = 1; 
    [P4 + 16] = R0; 
    [P4 + 20] = R0; 
    R0 = P4; 
    R1 = R7; 
    R2 = P5; 
    CALL __hpel_core2;      // Averages and stores into buffer 
     
     
/***************************  HOR_OFFSET = 0    VER_OFFSET = 1 ***************/ 
    R0 = 1; 
    R0 = R0 - R0 (NS) || [P4 + 16] = R0; 
    [P4 + 20] = R0; 
    R0 = P4; 
    R1 = R7; 
    CALL __hpel_core1;      // Averages and stores into buffer 
                            // Finds MAD between averaged block(buffer1) and  
                            // target block 
/*************************  HOR_OFFSET = -1   VER_OFFSET = 1 ******************/ 
    CC = R5 == R6;          // If Horizontal-offset == R6, skip last hpel  
                            // estimation(X = -1, Y = 1) 
    IF CC JUMP BRANCH8;              
    R0 = -1; 
    R0 = R0.L * R0.L (IS) || [P4 + 20] = R0; 
    [P4 + 16] = R0; 
    R0 = P4; 
    R1 = R7; 
    R2 = P5; 
    CALL __hpel_core2;      // Averages and stores into buffer 
     
BRANCH8: 
    R1 = [P4 + 12];         // Horizontal-vector before half pixel estimation 
    R2 = [P4 + 28]; 
    R1 = R1 + R2 (NS) || R0 = [P4 + 8]; 
                            // Half pixel estimation for Horizontal-vector added 
                            // to X-vector  
    R2 = [P4 + 24]; 
    R0 = R0 + R2;           // Half pixel estimation for Vertical-vector added  
                            // to Y-vector 
    P0 = 260; 
    SP = SP + P0; 
    SP = SP + P0; 
    RETS = [SP++];                   
    (R7:4, P5:4) = [SP++];  // Retrieve call save register 
    RTS; 
    NOP; 
_hpel.end: