yading@10: /* yading@10: C-like prototype : yading@10: void j_rev_dct_arm(DCTBLOCK data) yading@10: yading@10: With DCTBLOCK being a pointer to an array of 64 'signed shorts' yading@10: yading@10: Copyright (c) 2001 Lionel Ulmer (lionel.ulmer@free.fr / bbrox@bbrox.org) yading@10: yading@10: Permission is hereby granted, free of charge, to any person obtaining a copy yading@10: of this software and associated documentation files (the "Software"), to deal yading@10: in the Software without restriction, including without limitation the rights yading@10: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell yading@10: copies of the Software, and to permit persons to whom the Software is yading@10: furnished to do so, subject to the following conditions: yading@10: yading@10: The above copyright notice and this permission notice shall be included in yading@10: all copies or substantial portions of the Software. yading@10: yading@10: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR yading@10: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, yading@10: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE yading@10: COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER yading@10: IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN yading@10: CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. yading@10: yading@10: */ yading@10: yading@10: #include "libavutil/arm/asm.S" yading@10: yading@10: #define FIX_0_298631336 2446 yading@10: #define FIX_0_541196100 4433 yading@10: #define FIX_0_765366865 6270 yading@10: #define FIX_1_175875602 9633 yading@10: #define FIX_1_501321110 12299 yading@10: #define FIX_2_053119869 16819 yading@10: #define FIX_3_072711026 25172 yading@10: #define FIX_M_0_390180644 -3196 yading@10: #define FIX_M_0_899976223 -7373 yading@10: #define FIX_M_1_847759065 -15137 yading@10: #define FIX_M_1_961570560 -16069 yading@10: #define FIX_M_2_562915447 -20995 yading@10: #define FIX_0xFFFF 0xFFFF yading@10: yading@10: #define FIX_0_298631336_ID 0 yading@10: #define FIX_0_541196100_ID 4 yading@10: #define FIX_0_765366865_ID 8 yading@10: #define FIX_1_175875602_ID 12 yading@10: #define FIX_1_501321110_ID 16 yading@10: #define FIX_2_053119869_ID 20 yading@10: #define FIX_3_072711026_ID 24 yading@10: #define FIX_M_0_390180644_ID 28 yading@10: #define FIX_M_0_899976223_ID 32 yading@10: #define FIX_M_1_847759065_ID 36 yading@10: #define FIX_M_1_961570560_ID 40 yading@10: #define FIX_M_2_562915447_ID 44 yading@10: #define FIX_0xFFFF_ID 48 yading@10: yading@10: function ff_j_rev_dct_arm, export=1 yading@10: push {r0, r4 - r11, lr} yading@10: yading@10: mov lr, r0 @ lr = pointer to the current row yading@10: mov r12, #8 @ r12 = row-counter yading@10: movrel r11, const_array @ r11 = base pointer to the constants array yading@10: row_loop: yading@10: ldrsh r0, [lr, # 0] @ r0 = 'd0' yading@10: ldrsh r2, [lr, # 2] @ r2 = 'd2' yading@10: yading@10: @ Optimization for row that have all items except the first set to 0 yading@10: @ (this works as the int16_t are always 4-byte aligned) yading@10: ldr r5, [lr, # 0] yading@10: ldr r6, [lr, # 4] yading@10: ldr r3, [lr, # 8] yading@10: ldr r4, [lr, #12] yading@10: orr r3, r3, r4 yading@10: orr r3, r3, r6 yading@10: orrs r5, r3, r5 yading@10: beq end_of_row_loop @ nothing to be done as ALL of them are '0' yading@10: orrs r3, r3, r2 yading@10: beq empty_row yading@10: yading@10: ldrsh r1, [lr, # 8] @ r1 = 'd1' yading@10: ldrsh r4, [lr, # 4] @ r4 = 'd4' yading@10: ldrsh r6, [lr, # 6] @ r6 = 'd6' yading@10: yading@10: ldr r3, [r11, #FIX_0_541196100_ID] yading@10: add r7, r2, r6 yading@10: ldr r5, [r11, #FIX_M_1_847759065_ID] yading@10: mul r7, r3, r7 @ r7 = z1 yading@10: ldr r3, [r11, #FIX_0_765366865_ID] yading@10: mla r6, r5, r6, r7 @ r6 = tmp2 yading@10: add r5, r0, r4 @ r5 = tmp0 yading@10: mla r2, r3, r2, r7 @ r2 = tmp3 yading@10: sub r3, r0, r4 @ r3 = tmp1 yading@10: yading@10: add r0, r2, r5, lsl #13 @ r0 = tmp10 yading@10: rsb r2, r2, r5, lsl #13 @ r2 = tmp13 yading@10: add r4, r6, r3, lsl #13 @ r4 = tmp11 yading@10: rsb r3, r6, r3, lsl #13 @ r3 = tmp12 yading@10: yading@10: push {r0, r2, r3, r4} @ save on the stack tmp10, tmp13, tmp12, tmp11 yading@10: yading@10: ldrsh r3, [lr, #10] @ r3 = 'd3' yading@10: ldrsh r5, [lr, #12] @ r5 = 'd5' yading@10: ldrsh r7, [lr, #14] @ r7 = 'd7' yading@10: yading@10: add r0, r3, r5 @ r0 = 'z2' yading@10: add r2, r1, r7 @ r2 = 'z1' yading@10: add r4, r3, r7 @ r4 = 'z3' yading@10: add r6, r1, r5 @ r6 = 'z4' yading@10: ldr r9, [r11, #FIX_1_175875602_ID] yading@10: add r8, r4, r6 @ r8 = z3 + z4 yading@10: ldr r10, [r11, #FIX_M_0_899976223_ID] yading@10: mul r8, r9, r8 @ r8 = 'z5' yading@10: ldr r9, [r11, #FIX_M_2_562915447_ID] yading@10: mul r2, r10, r2 @ r2 = 'z1' yading@10: ldr r10, [r11, #FIX_M_1_961570560_ID] yading@10: mul r0, r9, r0 @ r0 = 'z2' yading@10: ldr r9, [r11, #FIX_M_0_390180644_ID] yading@10: mla r4, r10, r4, r8 @ r4 = 'z3' yading@10: ldr r10, [r11, #FIX_0_298631336_ID] yading@10: mla r6, r9, r6, r8 @ r6 = 'z4' yading@10: ldr r9, [r11, #FIX_2_053119869_ID] yading@10: mla r7, r10, r7, r2 @ r7 = tmp0 + z1 yading@10: ldr r10, [r11, #FIX_3_072711026_ID] yading@10: mla r5, r9, r5, r0 @ r5 = tmp1 + z2 yading@10: ldr r9, [r11, #FIX_1_501321110_ID] yading@10: mla r3, r10, r3, r0 @ r3 = tmp2 + z2 yading@10: add r7, r7, r4 @ r7 = tmp0 yading@10: mla r1, r9, r1, r2 @ r1 = tmp3 + z1 yading@10: add r5, r5, r6 @ r5 = tmp1 yading@10: add r3, r3, r4 @ r3 = tmp2 yading@10: add r1, r1, r6 @ r1 = tmp3 yading@10: yading@10: pop {r0, r2, r4, r6} @ r0 = tmp10 / r2 = tmp13 / r4 = tmp12 / r6 = tmp11 yading@10: @ r1 = tmp3 / r3 = tmp2 / r5 = tmp1 / r7 = tmp0 yading@10: yading@10: @ Compute DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS) yading@10: add r8, r0, r1 yading@10: add r8, r8, #(1<<10) yading@10: mov r8, r8, asr #11 yading@10: strh r8, [lr, # 0] yading@10: yading@10: @ Compute DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS) yading@10: sub r8, r0, r1 yading@10: add r8, r8, #(1<<10) yading@10: mov r8, r8, asr #11 yading@10: strh r8, [lr, #14] yading@10: yading@10: @ Compute DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS) yading@10: add r8, r6, r3 yading@10: add r8, r8, #(1<<10) yading@10: mov r8, r8, asr #11 yading@10: strh r8, [lr, # 2] yading@10: yading@10: @ Compute DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS) yading@10: sub r8, r6, r3 yading@10: add r8, r8, #(1<<10) yading@10: mov r8, r8, asr #11 yading@10: strh r8, [lr, #12] yading@10: yading@10: @ Compute DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS) yading@10: add r8, r4, r5 yading@10: add r8, r8, #(1<<10) yading@10: mov r8, r8, asr #11 yading@10: strh r8, [lr, # 4] yading@10: yading@10: @ Compute DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS) yading@10: sub r8, r4, r5 yading@10: add r8, r8, #(1<<10) yading@10: mov r8, r8, asr #11 yading@10: strh r8, [lr, #10] yading@10: yading@10: @ Compute DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS) yading@10: add r8, r2, r7 yading@10: add r8, r8, #(1<<10) yading@10: mov r8, r8, asr #11 yading@10: strh r8, [lr, # 6] yading@10: yading@10: @ Compute DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS) yading@10: sub r8, r2, r7 yading@10: add r8, r8, #(1<<10) yading@10: mov r8, r8, asr #11 yading@10: strh r8, [lr, # 8] yading@10: yading@10: @ End of row loop yading@10: add lr, lr, #16 yading@10: subs r12, r12, #1 yading@10: bne row_loop yading@10: beq start_column_loop yading@10: yading@10: empty_row: yading@10: ldr r1, [r11, #FIX_0xFFFF_ID] yading@10: mov r0, r0, lsl #2 yading@10: and r0, r0, r1 yading@10: add r0, r0, r0, lsl #16 yading@10: str r0, [lr, # 0] yading@10: str r0, [lr, # 4] yading@10: str r0, [lr, # 8] yading@10: str r0, [lr, #12] yading@10: yading@10: end_of_row_loop: yading@10: @ End of loop yading@10: add lr, lr, #16 yading@10: subs r12, r12, #1 yading@10: bne row_loop yading@10: yading@10: start_column_loop: yading@10: @ Start of column loop yading@10: pop {lr} yading@10: mov r12, #8 yading@10: column_loop: yading@10: ldrsh r0, [lr, #( 0*8)] @ r0 = 'd0' yading@10: ldrsh r2, [lr, #( 4*8)] @ r2 = 'd2' yading@10: ldrsh r4, [lr, #( 8*8)] @ r4 = 'd4' yading@10: ldrsh r6, [lr, #(12*8)] @ r6 = 'd6' yading@10: yading@10: ldr r3, [r11, #FIX_0_541196100_ID] yading@10: add r1, r2, r6 yading@10: ldr r5, [r11, #FIX_M_1_847759065_ID] yading@10: mul r1, r3, r1 @ r1 = z1 yading@10: ldr r3, [r11, #FIX_0_765366865_ID] yading@10: mla r6, r5, r6, r1 @ r6 = tmp2 yading@10: add r5, r0, r4 @ r5 = tmp0 yading@10: mla r2, r3, r2, r1 @ r2 = tmp3 yading@10: sub r3, r0, r4 @ r3 = tmp1 yading@10: yading@10: add r0, r2, r5, lsl #13 @ r0 = tmp10 yading@10: rsb r2, r2, r5, lsl #13 @ r2 = tmp13 yading@10: add r4, r6, r3, lsl #13 @ r4 = tmp11 yading@10: rsb r6, r6, r3, lsl #13 @ r6 = tmp12 yading@10: yading@10: ldrsh r1, [lr, #( 2*8)] @ r1 = 'd1' yading@10: ldrsh r3, [lr, #( 6*8)] @ r3 = 'd3' yading@10: ldrsh r5, [lr, #(10*8)] @ r5 = 'd5' yading@10: ldrsh r7, [lr, #(14*8)] @ r7 = 'd7' yading@10: yading@10: @ Check for empty odd column (happens about 20 to 25 % of the time according to my stats) yading@10: orr r9, r1, r3 yading@10: orr r10, r5, r7 yading@10: orrs r10, r9, r10 yading@10: beq empty_odd_column yading@10: yading@10: push {r0, r2, r4, r6} @ save on the stack tmp10, tmp13, tmp12, tmp11 yading@10: yading@10: add r0, r3, r5 @ r0 = 'z2' yading@10: add r2, r1, r7 @ r2 = 'z1' yading@10: add r4, r3, r7 @ r4 = 'z3' yading@10: add r6, r1, r5 @ r6 = 'z4' yading@10: ldr r9, [r11, #FIX_1_175875602_ID] yading@10: add r8, r4, r6 yading@10: ldr r10, [r11, #FIX_M_0_899976223_ID] yading@10: mul r8, r9, r8 @ r8 = 'z5' yading@10: ldr r9, [r11, #FIX_M_2_562915447_ID] yading@10: mul r2, r10, r2 @ r2 = 'z1' yading@10: ldr r10, [r11, #FIX_M_1_961570560_ID] yading@10: mul r0, r9, r0 @ r0 = 'z2' yading@10: ldr r9, [r11, #FIX_M_0_390180644_ID] yading@10: mla r4, r10, r4, r8 @ r4 = 'z3' yading@10: ldr r10, [r11, #FIX_0_298631336_ID] yading@10: mla r6, r9, r6, r8 @ r6 = 'z4' yading@10: ldr r9, [r11, #FIX_2_053119869_ID] yading@10: mla r7, r10, r7, r2 @ r7 = tmp0 + z1 yading@10: ldr r10, [r11, #FIX_3_072711026_ID] yading@10: mla r5, r9, r5, r0 @ r5 = tmp1 + z2 yading@10: ldr r9, [r11, #FIX_1_501321110_ID] yading@10: mla r3, r10, r3, r0 @ r3 = tmp2 + z2 yading@10: add r7, r7, r4 @ r7 = tmp0 yading@10: mla r1, r9, r1, r2 @ r1 = tmp3 + z1 yading@10: add r5, r5, r6 @ r5 = tmp1 yading@10: add r3, r3, r4 @ r3 = tmp2 yading@10: add r1, r1, r6 @ r1 = tmp3 yading@10: yading@10: pop {r0, r2, r4, r6} @ r0 = tmp10 / r2 = tmp13 / r4 = tmp11 / r6 = tmp12 yading@10: @ r1 = tmp3 / r3 = tmp2 / r5 = tmp1 / r7 = tmp0 yading@10: yading@10: @ Compute DESCALE(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) yading@10: add r8, r0, r1 yading@10: add r8, r8, #(1<<17) yading@10: mov r8, r8, asr #18 yading@10: strh r8, [lr, #( 0*8)] yading@10: yading@10: @ Compute DESCALE(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) yading@10: sub r8, r0, r1 yading@10: add r8, r8, #(1<<17) yading@10: mov r8, r8, asr #18 yading@10: strh r8, [lr, #(14*8)] yading@10: yading@10: @ Compute DESCALE(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) yading@10: add r8, r4, r3 yading@10: add r8, r8, #(1<<17) yading@10: mov r8, r8, asr #18 yading@10: strh r8, [lr, #( 2*8)] yading@10: yading@10: @ Compute DESCALE(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) yading@10: sub r8, r4, r3 yading@10: add r8, r8, #(1<<17) yading@10: mov r8, r8, asr #18 yading@10: strh r8, [lr, #(12*8)] yading@10: yading@10: @ Compute DESCALE(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) yading@10: add r8, r6, r5 yading@10: add r8, r8, #(1<<17) yading@10: mov r8, r8, asr #18 yading@10: strh r8, [lr, #( 4*8)] yading@10: yading@10: @ Compute DESCALE(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) yading@10: sub r8, r6, r5 yading@10: add r8, r8, #(1<<17) yading@10: mov r8, r8, asr #18 yading@10: strh r8, [lr, #(10*8)] yading@10: yading@10: @ Compute DESCALE(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) yading@10: add r8, r2, r7 yading@10: add r8, r8, #(1<<17) yading@10: mov r8, r8, asr #18 yading@10: strh r8, [lr, #( 6*8)] yading@10: yading@10: @ Compute DESCALE(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) yading@10: sub r8, r2, r7 yading@10: add r8, r8, #(1<<17) yading@10: mov r8, r8, asr #18 yading@10: strh r8, [lr, #( 8*8)] yading@10: yading@10: @ End of row loop yading@10: add lr, lr, #2 yading@10: subs r12, r12, #1 yading@10: bne column_loop yading@10: beq the_end yading@10: yading@10: empty_odd_column: yading@10: @ Compute DESCALE(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) yading@10: @ Compute DESCALE(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) yading@10: add r0, r0, #(1<<17) yading@10: mov r0, r0, asr #18 yading@10: strh r0, [lr, #( 0*8)] yading@10: strh r0, [lr, #(14*8)] yading@10: yading@10: @ Compute DESCALE(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) yading@10: @ Compute DESCALE(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) yading@10: add r4, r4, #(1<<17) yading@10: mov r4, r4, asr #18 yading@10: strh r4, [lr, #( 2*8)] yading@10: strh r4, [lr, #(12*8)] yading@10: yading@10: @ Compute DESCALE(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) yading@10: @ Compute DESCALE(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) yading@10: add r6, r6, #(1<<17) yading@10: mov r6, r6, asr #18 yading@10: strh r6, [lr, #( 4*8)] yading@10: strh r6, [lr, #(10*8)] yading@10: yading@10: @ Compute DESCALE(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) yading@10: @ Compute DESCALE(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) yading@10: add r2, r2, #(1<<17) yading@10: mov r2, r2, asr #18 yading@10: strh r2, [lr, #( 6*8)] yading@10: strh r2, [lr, #( 8*8)] yading@10: yading@10: @ End of row loop yading@10: add lr, lr, #2 yading@10: subs r12, r12, #1 yading@10: bne column_loop yading@10: yading@10: the_end: yading@10: @ The end.... yading@10: pop {r4 - r11, pc} yading@10: endfunc yading@10: yading@10: const const_array yading@10: .word FIX_0_298631336 yading@10: .word FIX_0_541196100 yading@10: .word FIX_0_765366865 yading@10: .word FIX_1_175875602 yading@10: .word FIX_1_501321110 yading@10: .word FIX_2_053119869 yading@10: .word FIX_3_072711026 yading@10: .word FIX_M_0_390180644 yading@10: .word FIX_M_0_899976223 yading@10: .word FIX_M_1_847759065 yading@10: .word FIX_M_1_961570560 yading@10: .word FIX_M_2_562915447 yading@10: .word FIX_0xFFFF yading@10: endconst