📄 msvc_block_decode_asm.h
字号:
__asm ADD ESI,EDX /* Add D to A */ \ __asm ADD ECX,EDX /* Add D to C */ \ __asm JL run_bit0_Clt0 \ /* Upper sub-interval selected */ \ __asm CMP ESI,0x00560100 \ __asm JGE run_bit0_renorm \ __asm ADD EAX,1 \ __asm JMP run_bit0_renorm \ __asm run_bit0_Clt0: \ /* Lower sub-interval selected */ \ __asm ADD ECX,0x00560100 \ __asm CMP ESI,0x00560100 \ __asm MOV ESI,0x00560100 \ __asm JL run_bit0_renorm \ __asm ADD EAX,1 \ __asm run_bit0_renorm: \ /* At this point, EBX holds A, ECX holds C and EDX and ESI are free */ \ __asm MOV EBX,t_var \ __asm run_bit0_renorm_once: \ /* Come back here repeatedly until we have shifted enough bits out. */ \ __asm TEST EBX,EBX \ __asm JNZ run_bit0_have_more_bits \ /* Begin `fill_lsbs' procedure */ \ __asm MOV EDX,temp_var \ __asm CMP EDX,0xFF \ __asm JNZ run_bit0_no_ff \ __asm MOV EBX,store_var \ __asm MOVZX EDX,byte ptr [EBX] /* New `temp' in EDX */ \ __asm CMP EDX,0x8F \ __asm JLE run_bit0_temp_le8F \ /* Reached a termination marker. Don't update `store_var' */ \ __asm MOV EDX,0xFF \ __asm MOV EBX,S_var \ __asm ADD EBX,1 \ __asm MOV S_var,EBX \ __asm MOV EBX,8 /* New value of t */ \ __asm JMP run_bit0_complete_fill_lsbs \ __asm run_bit0_temp_le8F: \ /* No termination marker, but bit stuff required */ \ __asm ADD ECX,EDX /* Add `temp' once; another later */ \ __asm ADD EBX,1 \ __asm MOV store_var,EBX /* Increments the `store' pointer */ \ __asm MOV EBX,7 /* New value of t. */ \ __asm JMP run_bit0_complete_fill_lsbs \ __asm run_bit0_no_ff: \ __asm MOV EBX,store_var \ __asm MOVZX EDX,byte ptr [EBX] /* New `temp' in EDX */ \ __asm ADD EBX,1 \ __asm MOV store_var,EBX /* Increments the `store' pointer */ \ __asm MOV EBX,8 /* New value of t. */ \ __asm run_bit0_complete_fill_lsbs: \ __asm ADD ECX,EDX /* Add `temp' to C */ \ __asm MOV temp_var,EDX /* Save `temp' */ \ /* End `fill_lsbs' procedure */ \ __asm run_bit0_have_more_bits: \ __asm ADD ESI,ESI /* Shift A register left */ \ __asm ADD ECX,ECX /* Shift C register left */ \ __asm SUB EBX,1 /* Decrement t */ \ __asm TEST ESI,0x00800000 /* Compare with MQD_A_MIN (test bit 23) */ \ __asm JZ run_bit0_renorm_once \ __asm MOV t_var,EBX /* Save t */ \ /* Renormalization is complete. Recompute D and save A and C. */ \ __asm MOV EDX,ESI /* Load EDX with A */ \ __asm SUB EDX,0x00800000 /* Subtract MQD_A_MIN */ \ __asm CMP ECX,EDX \ __asm CMOVL EDX,ECX /* Move C to EDX if C < A-MQD_A_MIN */ \ __asm SUB ESI,EDX \ __asm SUB ECX,EDX \ __asm run_finished: \ __asm MOV C_var,ECX/* ========================================================================= *//* Coding Pass Functions *//* ========================================================================= *//*****************************************************************************//* STATIC asm_decode_sig_prop_pass *//*****************************************************************************/static void asm_decode_sig_prop_pass(mq_decoder &coder, mqd_state states[], int p, bool causal, int orientation, kdu_int32 *samples, kdu_int32 *contexts, int width, int num_stripes, int context_row_gap){ if ((num_stripes <= 0) || (width <= 0)) return; kdu_int32 A_var, C_var, D_var, t_var, temp_var; kdu_byte *store_var; int S_var; coder.check_out(A_var,C_var,D_var,t_var,temp_var,store_var,S_var); kdu_byte *sig_lut = significance_luts[orientation]; kdu_int32 one_point_five = 1<<p; one_point_five += (one_point_five>>1); int is_causal = (causal)?1:0; context_row_gap <<= 2; // Convert to number of bytes width <<= 2; // Convert to number of bytes /* The following offsets are used to convert a context word pointer to a sample pointer. The offsets are correct for the first stripe and must be adjusted from stripe to stripe by the addition of 3*width-EXTRA_DECODE_CWORDS. */ int cp_to_sp0 = ((int) samples)-((int) contexts); // Offset for row 0 int cp_to_sp1 = cp_to_sp0+width; // Offset for row 1 int cp_to_sp2 = cp_to_sp1+width; // Offset for row 2 int cp_to_sp3 = cp_to_sp2+width; // Offset for row 3 int cp_to_sp_adjust = 3*width-4*EXTRA_DECODE_CWORDS; kdu_int32 *stripe_end; // Points to context word beyond end of current stripe __asm { MOV EDI,contexts // Set EDI aside to hold the context word pointer MOV EDX,D_var // Set EDX aside to hold the critical MQ variable, D MOV ESI,A_var // Set ESI aside to hold the MQ coder's A registernext_stripe: MOV EAX,width ADD EAX,EDI MOV stripe_end,EAX // Set end pointer for this stripenext_stripe_column: MOV ECX,[EDI] TEST ECX,ECX JNZ row0speedup_loop: // Invoke speedup trick to skip over runs of all-zero neighbourhoods MOV ECX,[EDI+12] ADD EDI,12 TEST ECX,ECX JZ speedup_loop SUB EDI,8 CMP EDI,stripe_end JNZ next_stripe_column JMP advance_striperow0: // Test for coding pass membership MOV EBX,ECX AND EBX,__NBRHD_MASK*1 JZ row1 TEST ECX,__SIG_PROP_MEMBER_MASK*1 JNZ row1 OR ECX,__PI_BIT*1 MOV [EDI],ECX // Save context word indicating that sample belongs to pass // Find pointer to the relevant context state record AND ECX,__NBRHD_MASK ADD ECX,sig_lut MOVZX ECX,byte ptr [ECX] MOV EBX,states LEA ECX,[EBX+8*ECX] // decode symbol MOV EAX,[ECX] // Get `p_bar_mps' to EAX SUB EDX,EAX AND EAX,1 // Get MPS identity in LSB of EAX ADD EDX,EAX // Correct for the effect of the MPS JGE significance_test0 CALL mq_non_cdpsignificance_test0: MOV ECX,[EDI] // Get context word back again TEST EAX,EAX // If symbol != 0 JZ row1 // If we get here, we know that stripe row 0 is newly significant AND ECX,__CHI_BIT/8+__SIGMA_CC_BIT/8+__CHI_BIT*8+__SIGMA_CC_BIT*8 SHR ECX,1 MOV EAX,[EDI-4] // Get context word on left AND EAX,__CHI_BIT+__SIGMA_CC_BIT SHR EAX,2 ADD ECX,EAX MOV EAX,[EDI+4] // Get context word on right AND EAX,__CHI_BIT+__SIGMA_CC_BIT ADD ECX,EAX MOV EAX,ECX SHR EAX,CHI_POS-1-SIGMA_CC_POS OR ECX,EAX AND ECX,0x000000FF MOVZX ECX,byte ptr [sign_lut+ECX] MOV EAX,ECX // Save the sign LUT result in EAX SHR ECX,1 // Get context label part of the LUT result MOV EBX,states LEA ECX,[EBX+8*ECX+8*KAPPA_SIGN_BASE] // ECX has pointer to context state MOV EBX,[ECX] // Get `p_bar_mps' to EBX XOR EAX,EBX AND EAX,1 // Leaves EAX with the MPS sign value in its LSB. BTR EBX,0 // Leaves `p_bar' in EBX SUB EDX,EBX JGE row0_broadcast CALL mq_non_cdprow0_broadcast: // Process newly significant sample; sign is in LSB of EAX // Broadcast significance and sign to last row of previous stripe MOV EBX,is_causal TEST EBX,EBX JNZ row0_skip_non_causal MOV EBX,EDI SUB EBX,context_row_gap MOV ECX,[EBX-4] OR ECX,__SIGMA_BR_BIT*512 MOV [EBX-4],ECX MOV ECX,EAX SHL ECX,NEXT_CHI_POS OR ECX,[EBX] OR ECX,__SIGMA_BC_BIT*512 MOV [EBX],ECX MOV ECX,[EBX+4] OR ECX,__SIGMA_BL_BIT*512 MOV [EBX+4],ECXrow0_skip_non_causal: // Broadcast significance to left and right neighbours MOV ECX,[EDI-4] OR ECX,__SIGMA_CR_BIT*1 MOV [EDI-4],ECX MOV ECX,[EDI+4] OR ECX,__SIGMA_CL_BIT*1 MOV [EDI+4],ECX // Recover and update context word, using ECX register MOV ECX,EAX SHL ECX,CHI_POS OR ECX,[EDI] OR ECX,__SIGMA_CC_BIT*1 MOV [EDI],ECX // Write newly significant sample value SHL EAX,31 // Get sign bit of result into right position ADD EAX,one_point_five MOV EBX,cp_to_sp0 MOV [EDI+EBX],EAXrow1: // Test for coding pass membership MOV EBX,ECX AND EBX,__NBRHD_MASK*8 JZ row2 TEST ECX,__SIG_PROP_MEMBER_MASK*8 JNZ row2 OR ECX,__PI_BIT*8 MOV [EDI],ECX // Save context word indicating that sample belongs to pass // Find pointer to the relevant context state record SHR ECX,3 AND ECX,__NBRHD_MASK ADD ECX,sig_lut MOVZX ECX,byte ptr [ECX] MOV EBX,states LEA ECX,[EBX+8*ECX] // Decode symbol MOV EAX,[ECX] // Get `p_bar_mps' to EAX SUB EDX,EAX AND EAX,1 // Get MPS identity in LSB of EAX ADD EDX,EAX // Correct for the effect of the MPS JGE significance_test1 CALL mq_non_cdpsignificance_test1: MOV ECX,[EDI] // Get context word back again TEST EAX,EAX // If symbol != 0 JZ row2 // If we get here, we know that stripe row 1 is newly significant AND ECX,__CHI_BIT+__SIGMA_CC_BIT+__CHI_BIT*64+__SIGMA_CC_BIT*64 SHR ECX,4 MOV EAX,[EDI-4] // Get context word on left AND EAX,__CHI_BIT*8+__SIGMA_CC_BIT*8 SHR EAX,5 ADD ECX,EAX MOV EAX,[EDI+4] // Get context word on right AND EAX,__CHI_BIT*8+__SIGMA_CC_BIT*8 SHR EAX,3 ADD ECX,EAX MOV EAX,ECX SHR EAX,CHI_POS-1-SIGMA_CC_POS OR ECX,EAX AND ECX,0x000000FF MOVZX ECX,byte ptr [sign_lut+ECX] MOV EAX,ECX // Save the sign LUT result in EAX SHR ECX,1 // Get context label part of the LUT result MOV EBX,states LEA ECX,[EBX+8*ECX+8*KAPPA_SIGN_BASE] // ECX has pointer to context state MOV EBX,[ECX] // Get `p_bar_mps' to EBX XOR EAX,EBX AND EAX,1 // Leaves EAX with the MPS sign value in its LSB. BTR EBX,0 // Leaves `p_bar' in EBX SUB EDX,EBX JGE row1_broadcast CALL mq_non_cdprow1_broadcast: // Process newly significant sample; sign is in LSB of EAX // Broadcast significance to left and right neighbours MOV ECX,[EDI-4] OR ECX,__SIGMA_CR_BIT*8 MOV [EDI-4],ECX MOV ECX,[EDI+4] OR ECX,__SIGMA_CL_BIT*8 MOV [EDI+4],ECX // Recover and update context word, using ECX register MOV ECX,EAX SHL ECX,CHI_POS+3 OR ECX,[EDI] OR ECX,__SIGMA_CC_BIT*8 MOV [EDI],ECX // Write new significant sample value SHL EAX,31 // Get sign bit of result into right position ADD EAX,one_point_five
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -