/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define ENTRY(f) .text; .align 4; .globl f; .type f,#function; f: .fnstart #define PRIVATE(f) .text; .align 4; .type f,#function; f: .fnstart #define END(f) .fnend; .size f, .-f; .eabi_attribute 25,1 @Tag_ABI_align8_preserved .arm /* Number of fractional bits to preserve in intermediate results. The * intermediate storage is 16-bit, and we started with 8 bit data (the integer * part), so this should be between 0 and 8. */ .set FRACTION_BITS, 7 .set MAX_R, 25 /* A quick way of making a line of code conditional on some other condition. * Use `.set cc, 1` or `.set cc, 0` to enable or disable lines prefixed with * `ifcc`: */ .macro ifcc zzz:vararg .if cc \zzz .endif .endm /* Fetch 16 columns of bytes (regardless of image format), convolve these * vertically, and leave them in the register file. If working near the top or * bottom of an image then clamp the addressing while loading the data in. * * The convolution is fully unrolled for windows up to max_r, with the * outermost edges calculated first. This way it's possible to branch directly * into the relevant part of the code for an arbitrary convolution radius. Two * variants of the loop are produced; one eliminates the clamping code for a * slight speed advantage. * * Where the macro is called with reg=x, the specified register is taken to * contain a pre-calculated pointer into one of the two loops. * * Input: * r1 -- src * r2 -- pitch * r5 -- r * r6 -- rup * r7 -- rdn * r12 -- switch index * q0-q3 -- coefficient table * Output: * r1 += 16 * q10,q11 -- 16 convolved columns * Modifies: * r10 = upper row pointer * r11 = lower row pointer * q12-q15 = temporary sums */ .macro fetch, max_r=MAX_R, labelc=1, labelnc=2, reg=r12 /*{{{*/ .ifc \reg,r12 ; .set cc, 1 ; .else ; .set cc, 0 ; .endif vld1.8 {d30,d31}, [r1] mls r10, r2, r6, r1 vmovl.u8 q14, d30 pld [r1, #32] vmovl.u8 q15, d31 .if \max_r < 16 // approximate ifcc adr \reg, 1f .else ifcc ldr \reg, 2f 1: ifcc add \reg, \reg, pc .endif vmull.u16 q12, d28, d0[0] ifcc sub \reg, r5, LSL #6 vmull.u16 q13, d29, d0[0] mla r11, r2, r7, r1 vmull.u16 q14, d30, d0[0] add r1, r1, #16 vmull.u16 q15, d31, d0[0] bx \reg ifcc .align 2 2: ifcc .word 1f-1b-8 .irp rowclamp, 1, 0 .set cc, \rowclamp .align 4 .irp dreg, 6, 5, 4, 3, 2, 1, 0 ; .irp lane, 3, 2, 1, 0 .set i, \dreg * 4 + \lane .if 0 < i && i <= \max_r .if \rowclamp vld1.8 {d20,d21}, [r10] vld1.8 {d22,d23}, [r11] cmp r6, #i .else vld1.8 {d20,d21}, [r10], r2 vld1.8 {d22,d23}, [r11] sub r11, r11, r2 .endif vswp d21, d22 pld [r10, #32] vaddl.u8 q10, d20, d21 ifcc addhs r10, r10, r2 vaddl.u8 q11, d22, d23 ifcc cmp r7, #i vmlal.u16 q12, d20, d\dreg[\lane] pld [r11, #32] vmlal.u16 q13, d21, d\dreg[\lane] ifcc subhs r11, r11, r2 vmlal.u16 q14, d22, d\dreg[\lane] ifcc nop vmlal.u16 q15, d23, d\dreg[\lane] .endif .endr ; .endr .if \rowclamp == 1 1: \labelc : b 2f .else 2: \labelnc : .endif .endr vqrshrn.u32 d20, q12, #16 - FRACTION_BITS vqrshrn.u32 d21, q13, #16 - FRACTION_BITS vqrshrn.u32 d22, q14, #16 - FRACTION_BITS vqrshrn.u32 d23, q15, #16 - FRACTION_BITS .endm /*}}}*/ /* Some portion of the convolution window (as much as will fit, and all of it * for the uchar1 cases) is kept in the register file to avoid unnecessary * memory accesses. This forces the horizontal loops to be unrolled because * there's no indexed addressing into the register file. * * As in the fetch macro, the operations are ordered from outside to inside, so * that jumping into the middle of the block bypasses the unwanted window taps. * * There are several variants of the macro because of the fixed offets of the * taps -- the wider the maximum radius the further the centre tap is from the * most recently fetched data. This means that pre-filling the window requires * more data that won't be used and it means that rotating the window involves * more mov operations. * * When the buffer gets too big the buffer at [r9] is used. * * Input: * q4-q11 -- convoltion window * r9 -- pointer to additional convolution window data * Output: * r9 -- updated buffer pointer (if used) * d31 -- result to be stored * Modifies: * r12 -- temp buffer pointer * q12-q13 -- temporaries for load and vext operations. * q14-q15 -- intermediate sums */ #define TUNED_LIST1 8, 16 .macro hconv1_8/*{{{*/ vmull.u16 q14, d18, d0[0] vmull.u16 q15, d19, d0[0] ldr r12, [pc, r5, LSL #2] add pc, pc, r12 bkpt 100: .word 101f-100b .word 102f-100b .word 103f-100b .word 104f-100b .word 105f-100b .word 106f-100b .word 107f-100b .word 108f-100b 108: vmlal.u16 q14, d16, d2[0] vmlal.u16 q15, d17, d2[0] vmlal.u16 q14, d20, d2[0] vmlal.u16 q15, d21, d2[0] 107: vext.u16 q12, q8, q9, #1 vext.u16 q13, q9, q10, #7 vmlal.u16 q14, d24, d1[3] vmlal.u16 q15, d25, d1[3] vmlal.u16 q14, d26, d1[3] vmlal.u16 q15, d27, d1[3] 106: vext.u16 q12, q8, q9, #2 vext.u16 q13, q9, q10, #6 vmlal.u16 q14, d24, d1[2] vmlal.u16 q15, d25, d1[2] vmlal.u16 q14, d26, d1[2] vmlal.u16 q15, d27, d1[2] 105: vext.u16 q12, q8, q9, #3 vext.u16 q13, q9, q10, #5 vmlal.u16 q14, d24, d1[1] vmlal.u16 q15, d25, d1[1] vmlal.u16 q14, d26, d1[1] vmlal.u16 q15, d27, d1[1] 104: //vext.u16 q12, q8, q9, #4 //vext.u16 q13, q9, q10, #4 vmlal.u16 q14, d17, d1[0] vmlal.u16 q15, d18, d1[0] vmlal.u16 q14, d19, d1[0] vmlal.u16 q15, d20, d1[0] 103: vext.u16 q12, q8, q9, #5 vext.u16 q13, q9, q10, #3 vmlal.u16 q14, d24, d0[3] vmlal.u16 q15, d25, d0[3] vmlal.u16 q14, d26, d0[3] vmlal.u16 q15, d27, d0[3] 102: vext.u16 q12, q8, q9, #6 vext.u16 q13, q9, q10, #2 vmlal.u16 q14, d24, d0[2] vmlal.u16 q15, d25, d0[2] vmlal.u16 q14, d26, d0[2] vmlal.u16 q15, d27, d0[2] 101: vext.u16 q12, q8, q9, #7 vext.u16 q13, q9, q10, #1 vmlal.u16 q14, d24, d0[1] vmlal.u16 q15, d25, d0[1] vmlal.u16 q14, d26, d0[1] vmlal.u16 q15, d27, d0[1] vqrshrn.u32 d28, q14, #16 vqrshrn.u32 d29, q15, #16 vqrshrn.u16 d31, q14, #FRACTION_BITS vmov q8, q9 vmov q9, q10 vmov q10, q11 .endm/*}}}*/ .macro hconv1_16/*{{{*/ vmull.u16 q14, d16, d0[0] vmull.u16 q15, d17, d0[0] ldr r12, [pc, r5, LSL #2] add pc, pc, r12 bkpt 100: .word 101f-100b .word 102f-100b .word 103f-100b .word 104f-100b .word 105f-100b .word 106f-100b .word 107f-100b .word 108f-100b .word 109f-100b .word 110f-100b .word 111f-100b .word 112f-100b .word 113f-100b .word 114f-100b .word 115f-100b .word 116f-100b 116: //vext.u16 q12, q6, q7, #0 //vext.u16 q13, q10, q11, #0 vmlal.u16 q14, d12, d4[0] vmlal.u16 q15, d13, d4[0] vmlal.u16 q14, d20, d4[0] vmlal.u16 q15, d21, d4[0] 115: vext.u16 q12, q6, q7, #1 vext.u16 q13, q9, q10, #7 vmlal.u16 q14, d24, d3[3] vmlal.u16 q15, d25, d3[3] vmlal.u16 q14, d26, d3[3] vmlal.u16 q15, d27, d3[3] 114: vext.u16 q12, q6, q7, #2 vext.u16 q13, q9, q10, #6 vmlal.u16 q14, d24, d3[2] vmlal.u16 q15, d25, d3[2] vmlal.u16 q14, d26, d3[2] vmlal.u16 q15, d27, d3[2] 113: vext.u16 q12, q6, q7, #3 vext.u16 q13, q9, q10, #5 vmlal.u16 q14, d24, d3[1] vmlal.u16 q15, d25, d3[1] vmlal.u16 q14, d26, d3[1] vmlal.u16 q15, d27, d3[1] 112: //vext.u16 q12, q6, q7, #4 //vext.u16 q13, q9, q10, #4 vmlal.u16 q14, d13, d3[0] vmlal.u16 q15, d14, d3[0] vmlal.u16 q14, d19, d3[0] vmlal.u16 q15, d20, d3[0] 111: vext.u16 q12, q6, q7, #5 vext.u16 q13, q9, q10, #3 vmlal.u16 q14, d24, d2[3] vmlal.u16 q15, d25, d2[3] vmlal.u16 q14, d26, d2[3] vmlal.u16 q15, d27, d2[3] 110: vext.u16 q12, q6, q7, #6 vext.u16 q13, q9, q10, #2 vmlal.u16 q14, d24, d2[2] vmlal.u16 q15, d25, d2[2] vmlal.u16 q14, d26, d2[2] vmlal.u16 q15, d27, d2[2] 109: vext.u16 q12, q6, q7, #7 vext.u16 q13, q9, q10, #1 vmlal.u16 q14, d24, d2[1] vmlal.u16 q15, d25, d2[1] vmlal.u16 q14, d26, d2[1] vmlal.u16 q15, d27, d2[1] 108: //vext.u16 q12, q7, q8, #0 //vext.u16 q13, q9, q10, #0 vmlal.u16 q14, d14, d2[0] vmlal.u16 q15, d15, d2[0] vmlal.u16 q14, d18, d2[0] vmlal.u16 q15, d19, d2[0] 107: vext.u16 q12, q7, q8, #1 vext.u16 q13, q8, q9, #7 vmlal.u16 q14, d24, d1[3] vmlal.u16 q15, d25, d1[3] vmlal.u16 q14, d26, d1[3] vmlal.u16 q15, d27, d1[3] 106: vext.u16 q12, q7, q8, #2 vext.u16 q13, q8, q9, #6 vmlal.u16 q14, d24, d1[2] vmlal.u16 q15, d25, d1[2] vmlal.u16 q14, d26, d1[2] vmlal.u16 q15, d27, d1[2] 105: vext.u16 q12, q7, q8, #3 vext.u16 q13, q8, q9, #5 vmlal.u16 q14, d24, d1[1] vmlal.u16 q15, d25, d1[1] vmlal.u16 q14, d26, d1[1] vmlal.u16 q15, d27, d1[1] 104: //vext.u16 q12, q7, q8, #4 //vext.u16 q13, q8, q9, #4 vmlal.u16 q14, d15, d1[0] vmlal.u16 q15, d16, d1[0] vmlal.u16 q14, d17, d1[0] vmlal.u16 q15, d18, d1[0] 103: vext.u16 q12, q7, q8, #5 vext.u16 q13, q8, q9, #3 vmlal.u16 q14, d24, d0[3] vmlal.u16 q15, d25, d0[3] vmlal.u16 q14, d26, d0[3] vmlal.u16 q15, d27, d0[3] 102: vext.u16 q12, q7, q8, #6 vext.u16 q13, q8, q9, #2 vmlal.u16 q14, d24, d0[2] vmlal.u16 q15, d25, d0[2] vmlal.u16 q14, d26, d0[2] vmlal.u16 q15, d27, d0[2] 101: vext.u16 q12, q7, q8, #7 vext.u16 q13, q8, q9, #1 vmlal.u16 q14, d24, d0[1] vmlal.u16 q15, d25, d0[1] vmlal.u16 q14, d26, d0[1] vmlal.u16 q15, d27, d0[1] vqrshrn.u32 d28, q14, #16 vqrshrn.u32 d29, q15, #16 vqrshrn.u16 d31, q14, #FRACTION_BITS vmov q6, q7 vmov q7, q8 vmov q8, q9 vmov q9, q10 vmov q10, q11 .endm/*}}}*/ .macro hconv1_25/*{{{*/ vext.u16 q12, q6, q7, #7 vmull.u16 q14, d24, d0[0] vmull.u16 q15, d25, d0[0] ldr r12, [pc, r5, LSL #2] add pc, pc, r12 bkpt 100: .word 101f-100b .word 102f-100b .word 103f-100b .word 104f-100b .word 105f-100b .word 106f-100b .word 107f-100b .word 108f-100b .word 109f-100b .word 110f-100b .word 111f-100b .word 112f-100b .word 113f-100b .word 114f-100b .word 115f-100b .word 116f-100b .word 117f-100b .word 118f-100b .word 119f-100b .word 120f-100b .word 121f-100b .word 122f-100b .word 123f-100b .word 124f-100b .word 125f-100b 125: vext.u16 q12, q3, q4, #6 vext.u16 q13, q10, q11, #0 vmlal.u16 q14, d24, d6[1] vmlal.u16 q15, d25, d6[1] vmlal.u16 q14, d26, d6[1] vmlal.u16 q15, d27, d6[1] 124: vext.u16 q12, q3, q4, #7 vext.u16 q13, q9, q10, #7 vmlal.u16 q14, d24, d6[0] vmlal.u16 q15, d25, d6[0] vmlal.u16 q14, d26, d6[0] vmlal.u16 q15, d27, d6[0] 123: vext.u16 q12, q4, q5, #0 vext.u16 q13, q9, q10, #6 vmlal.u16 q14, d24, d5[3] vmlal.u16 q15, d25, d5[3] vmlal.u16 q14, d26, d5[3] vmlal.u16 q15, d27, d5[3] 122: vext.u16 q12, q4, q5, #1 vext.u16 q13, q9, q10, #5 vmlal.u16 q14, d24, d5[2] vmlal.u16 q15, d25, d5[2] vmlal.u16 q14, d26, d5[2] vmlal.u16 q15, d27, d5[2] 121: vext.u16 q12, q4, q5, #2 vext.u16 q13, q9, q10, #4 vmlal.u16 q14, d24, d5[1] vmlal.u16 q15, d25, d5[1] vmlal.u16 q14, d26, d5[1] vmlal.u16 q15, d27, d5[1] 120: vext.u16 q12, q4, q5, #3 vext.u16 q13, q9, q10, #3 vmlal.u16 q14, d24, d5[0] vmlal.u16 q15, d25, d5[0] vmlal.u16 q14, d26, d5[0] vmlal.u16 q15, d27, d5[0] 119: vext.u16 q12, q4, q5, #4 vext.u16 q13, q9, q10, #2 vmlal.u16 q14, d24, d4[3] vmlal.u16 q15, d25, d4[3] vmlal.u16 q14, d26, d4[3] vmlal.u16 q15, d27, d4[3] 118: vext.u16 q12, q4, q5, #5 vext.u16 q13, q9, q10, #1 vmlal.u16 q14, d24, d4[2] vmlal.u16 q15, d25, d4[2] vmlal.u16 q14, d26, d4[2] vmlal.u16 q15, d27, d4[2] 117: vext.u16 q12, q4, q5, #6 vext.u16 q13, q9, q10, #0 vmlal.u16 q14, d24, d4[1] vmlal.u16 q15, d25, d4[1] vmlal.u16 q14, d26, d4[1] vmlal.u16 q15, d27, d4[1] 116: vext.u16 q12, q4, q5, #7 vext.u16 q13, q8, q9, #7 vmlal.u16 q14, d24, d4[0] vmlal.u16 q15, d25, d4[0] vmlal.u16 q14, d26, d4[0] vmlal.u16 q15, d27, d4[0] 115: vext.u16 q12, q5, q6, #0 vext.u16 q13, q8, q9, #6 vmlal.u16 q14, d24, d3[3] vmlal.u16 q15, d25, d3[3] vmlal.u16 q14, d26, d3[3] vmlal.u16 q15, d27, d3[3] 114: vext.u16 q12, q5, q6, #1 vext.u16 q13, q8, q9, #5 vmlal.u16 q14, d24, d3[2] vmlal.u16 q15, d25, d3[2] vmlal.u16 q14, d26, d3[2] vmlal.u16 q15, d27, d3[2] 113: vext.u16 q12, q5, q6, #2 vext.u16 q13, q8, q9, #4 vmlal.u16 q14, d24, d3[1] vmlal.u16 q15, d25, d3[1] vmlal.u16 q14, d26, d3[1] vmlal.u16 q15, d27, d3[1] 112: vext.u16 q12, q5, q6, #3 vext.u16 q13, q8, q9, #3 vmlal.u16 q14, d24, d3[0] vmlal.u16 q15, d25, d3[0] vmlal.u16 q14, d26, d3[0] vmlal.u16 q15, d27, d3[0] 111: vext.u16 q12, q5, q6, #4 vext.u16 q13, q8, q9, #2 vmlal.u16 q14, d24, d2[3] vmlal.u16 q15, d25, d2[3] vmlal.u16 q14, d26, d2[3] vmlal.u16 q15, d27, d2[3] 110: vext.u16 q12, q5, q6, #5 vext.u16 q13, q8, q9, #1 vmlal.u16 q14, d24, d2[2] vmlal.u16 q15, d25, d2[2] vmlal.u16 q14, d26, d2[2] vmlal.u16 q15, d27, d2[2] 109: vext.u16 q12, q5, q6, #6 vext.u16 q13, q8, q9, #0 vmlal.u16 q14, d24, d2[1] vmlal.u16 q15, d25, d2[1] vmlal.u16 q14, d26, d2[1] vmlal.u16 q15, d27, d2[1] 108: vext.u16 q12, q5, q6, #7 vext.u16 q13, q7, q8, #7 vmlal.u16 q14, d24, d2[0] vmlal.u16 q15, d25, d2[0] vmlal.u16 q14, d26, d2[0] vmlal.u16 q15, d27, d2[0] 107: vext.u16 q12, q6, q7, #0 vext.u16 q13, q7, q8, #6 vmlal.u16 q14, d24, d1[3] vmlal.u16 q15, d25, d1[3] vmlal.u16 q14, d26, d1[3] vmlal.u16 q15, d27, d1[3] 106: vext.u16 q12, q6, q7, #1 vext.u16 q13, q7, q8, #5 vmlal.u16 q14, d24, d1[2] vmlal.u16 q15, d25, d1[2] vmlal.u16 q14, d26, d1[2] vmlal.u16 q15, d27, d1[2] 105: vext.u16 q12, q6, q7, #2 vext.u16 q13, q7, q8, #4 vmlal.u16 q14, d24, d1[1] vmlal.u16 q15, d25, d1[1] vmlal.u16 q14, d26, d1[1] vmlal.u16 q15, d27, d1[1] 104: vext.u16 q12, q6, q7, #3 vext.u16 q13, q7, q8, #3 vmlal.u16 q14, d24, d1[0] vmlal.u16 q15, d25, d1[0] vmlal.u16 q14, d26, d1[0] vmlal.u16 q15, d27, d1[0] 103: vext.u16 q12, q6, q7, #4 vext.u16 q13, q7, q8, #2 vmlal.u16 q14, d24, d0[3] vmlal.u16 q15, d25, d0[3] vmlal.u16 q14, d26, d0[3] vmlal.u16 q15, d27, d0[3] 102: vext.u16 q12, q6, q7, #5 vext.u16 q13, q7, q8, #1 vmlal.u16 q14, d24, d0[2] vmlal.u16 q15, d25, d0[2] vmlal.u16 q14, d26, d0[2] vmlal.u16 q15, d27, d0[2] 101: vext.u16 q12, q6, q7, #6 vext.u16 q13, q7, q8, #0 vmlal.u16 q14, d24, d0[1] vmlal.u16 q15, d25, d0[1] vmlal.u16 q14, d26, d0[1] vmlal.u16 q15, d27, d0[1] vqrshrn.u32 d28, q14, #16 vqrshrn.u32 d29, q15, #16 vqrshrn.u16 d31, q14, #FRACTION_BITS vmov d7, d9 vmov q4, q5 vmov q5, q6 vmov q6, q7 vmov q7, q8 vmov q8, q9 vmov q9, q10 vmov q10, q11 .endm/*}}}*/ #define TUNED_LIST4 6, 12 .macro hconv4_6/*{{{*/ vmull.u16 q14, d14, d0[0] vmull.u16 q15, d15, d0[0] ldr r12, [pc, r5, LSL #2] add pc, pc, r12 bkpt 100: .word 101f-100b .word 102f-100b .word 103f-100b .word 104f-100b .word 105f-100b .word 106f-100b 106: vmlal.u16 q14, d8, d1[2] vmlal.u16 q15, d9, d1[2] vmlal.u16 q14, d20, d1[2] vmlal.u16 q15, d21, d1[2] 105: vmlal.u16 q14, d9, d1[1] vmlal.u16 q15, d10, d1[1] vmlal.u16 q14, d19, d1[1] vmlal.u16 q15, d20, d1[1] 104: vmlal.u16 q14, d10, d1[0] vmlal.u16 q15, d11, d1[0] vmlal.u16 q14, d18, d1[0] vmlal.u16 q15, d19, d1[0] 103: vmlal.u16 q14, d11, d0[3] vmlal.u16 q15, d12, d0[3] vmlal.u16 q14, d17, d0[3] vmlal.u16 q15, d18, d0[3] 102: vmlal.u16 q14, d12, d0[2] vmlal.u16 q15, d13, d0[2] vmlal.u16 q14, d16, d0[2] vmlal.u16 q15, d17, d0[2] 101: vmlal.u16 q14, d13, d0[1] vmlal.u16 q15, d14, d0[1] vmlal.u16 q14, d15, d0[1] vmlal.u16 q15, d16, d0[1] vqrshrn.u32 d28, q14, #16 vqrshrn.u32 d29, q15, #16 vqrshrn.u16 d31, q14, #FRACTION_BITS vmov q4, q5 vmov q5, q6 vmov q6, q7 vmov q7, q8 vmov q8, q9 vmov q9, q10 vmov q10, q11 .endm/*}}}*/ .macro hconv4_12/*{{{*/ vmull.u16 q14, d8, d0[0] vmull.u16 q15, d9, d0[0] ldr r12, [pc, r5, LSL #2] add pc, pc, r12 bkpt 100: .word 101f-100b .word 102f-100b .word 103f-100b .word 104f-100b .word 105f-100b .word 106f-100b .word 107f-100b .word 108f-100b .word 109f-100b .word 110f-100b .word 111f-100b .word 112f-100b 112: add r12, r9, #0x1a0 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d3[0] vmlal.u16 q15, d25, d3[0] vmlal.u16 q14, d20, d3[0] vmlal.u16 q15, d21, d3[0] 111: add r12, r9, #0x1a8 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12:64] vmlal.u16 q14, d24, d2[3] vmlal.u16 q15, d25, d2[3] vmlal.u16 q14, d19, d2[3] vmlal.u16 q15, d20, d2[3] 110: add r12, r9, #0x1b0 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d2[2] vmlal.u16 q15, d25, d2[2] vmlal.u16 q14, d18, d2[2] vmlal.u16 q15, d19, d2[2] 109: add r12, r9, #0x1b8 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12:64] vmlal.u16 q14, d24, d2[1] vmlal.u16 q15, d25, d2[1] vmlal.u16 q14, d17, d2[1] vmlal.u16 q15, d18, d2[1] 108: add r12, r9, #0x1c0 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d2[0] vmlal.u16 q15, d25, d2[0] vmlal.u16 q14, d16, d2[0] vmlal.u16 q15, d17, d2[0] 107: add r12, r9, #0x1c8 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12:64] vmlal.u16 q14, d24, d1[3] vmlal.u16 q15, d25, d1[3] vmlal.u16 q14, d15, d1[3] vmlal.u16 q15, d16, d1[3] 106: add r12, r9, #0x1d0 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d1[2] vmlal.u16 q15, d25, d1[2] vmlal.u16 q14, d14, d1[2] vmlal.u16 q15, d15, d1[2] 105: add r12, r9, #0x1d8 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12:64] vmlal.u16 q14, d24, d1[1] vmlal.u16 q15, d25, d1[1] vmlal.u16 q14, d13, d1[1] vmlal.u16 q15, d14, d1[1] 104: add r12, r9, #0x1e0 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d1[0] vmlal.u16 q15, d25, d1[0] vmlal.u16 q14, d12, d1[0] vmlal.u16 q15, d13, d1[0] 103: add r12, r9, #0x1e8 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12:64] vmlal.u16 q14, d24, d0[3] vmlal.u16 q15, d25, d0[3] vmlal.u16 q14, d11, d0[3] vmlal.u16 q15, d12, d0[3] 102: add r12, r9, #0x1f0 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d0[2] vmlal.u16 q15, d25, d0[2] vmlal.u16 q14, d10, d0[2] vmlal.u16 q15, d11, d0[2] 101: add r12, r9, #0x1f8 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64] vmlal.u16 q14, d24, d0[1] vmlal.u16 q15, d8, d0[1] vmlal.u16 q14, d9, d0[1] vmlal.u16 q15, d10, d0[1] vqrshrn.u32 d28, q14, #16 vqrshrn.u32 d29, q15, #16 vqrshrn.u16 d31, q14, #FRACTION_BITS vst1.u8 {q4}, [r9:128]! bic r9, r9, #0x200 vmov q4, q5 vmov q5, q6 vmov q6, q7 vmov q7, q8 vmov q8, q9 vmov q9, q10 vmov q10, q11 .endm/*}}}*/ .macro hconv4_25/*{{{*/ add r12, r9, #0x198 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12:64] vmull.u16 q14, d24, d0[0] vmull.u16 q15, d25, d0[0] ldr r12, [pc, r5, LSL #2] add pc, pc, r12 bkpt 100: .word 101f-100b .word 102f-100b .word 103f-100b .word 104f-100b .word 105f-100b .word 106f-100b .word 107f-100b .word 108f-100b .word 109f-100b .word 110f-100b .word 111f-100b .word 112f-100b .word 113f-100b .word 114f-100b .word 115f-100b .word 116f-100b .word 117f-100b .word 118f-100b .word 119f-100b .word 120f-100b .word 121f-100b .word 122f-100b .word 123f-100b .word 124f-100b .word 125f-100b 125: add r12, r9, #0x0d0 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d6[1] vmlal.u16 q15, d25, d6[1] vmlal.u16 q14, d20, d6[1] vmlal.u16 q15, d21, d6[1] 124: add r12, r9, #0x0d8 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] vmlal.u16 q14, d24, d6[0] vmlal.u16 q15, d25, d6[0] vmlal.u16 q14, d19, d6[0] vmlal.u16 q15, d20, d6[0] 123: add r12, r9, #0x0e0 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d5[3] vmlal.u16 q15, d25, d5[3] vmlal.u16 q14, d18, d5[3] vmlal.u16 q15, d19, d5[3] 122: add r12, r9, #0x0e8 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] vmlal.u16 q14, d24, d5[2] vmlal.u16 q15, d25, d5[2] vmlal.u16 q14, d17, d5[2] vmlal.u16 q15, d18, d5[2] 121: add r12, r9, #0x0f0 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d5[1] vmlal.u16 q15, d25, d5[1] vmlal.u16 q14, d16, d5[1] vmlal.u16 q15, d17, d5[1] 120: add r12, r9, #0x0f8 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] vmlal.u16 q14, d24, d5[0] vmlal.u16 q15, d25, d5[0] vmlal.u16 q14, d15, d5[0] vmlal.u16 q15, d16, d5[0] 119: add r12, r9, #0x100 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d4[3] vmlal.u16 q15, d25, d4[3] vmlal.u16 q14, d14, d4[3] vmlal.u16 q15, d15, d4[3] 118: add r12, r9, #0x108 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] vmlal.u16 q14, d24, d4[2] vmlal.u16 q15, d25, d4[2] vmlal.u16 q14, d13, d4[2] vmlal.u16 q15, d14, d4[2] 117: add r12, r9, #0x110 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d4[1] vmlal.u16 q15, d25, d4[1] vmlal.u16 q14, d12, d4[1] vmlal.u16 q15, d13, d4[1] 116: add r12, r9, #0x118 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] vmlal.u16 q14, d24, d4[0] vmlal.u16 q15, d25, d4[0] vmlal.u16 q14, d11, d4[0] vmlal.u16 q15, d12, d4[0] 115: add r12, r9, #0x120 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d3[3] vmlal.u16 q15, d25, d3[3] vmlal.u16 q14, d10, d3[3] vmlal.u16 q15, d11, d3[3] 114: add r12, r9, #0x128 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] vmlal.u16 q14, d24, d3[2] vmlal.u16 q15, d25, d3[2] vmlal.u16 q14, d9, d3[2] vmlal.u16 q15, d10, d3[2] 113: add r12, r9, #0x130 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] vmlal.u16 q14, d24, d3[1] vmlal.u16 q15, d25, d3[1] vmlal.u16 q14, d8, d3[1] vmlal.u16 q15, d9, d3[1] 112: add r12, r9, #0x138 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] add r12, r9, #0x1f8 bic r12, r12, #0x200 vld1.u16 {d26}, [r12:64] vmlal.u16 q14, d24, d3[0] vmlal.u16 q15, d25, d3[0] vmlal.u16 q14, d26, d3[0] @ Could be d7, without the load, right? vmlal.u16 q15, d8, d3[0] 111: add r12, r9, #0x140 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] add r12, r9, #0x1f0 bic r12, r12, #0x200 vld1.u16 {d26,d27}, [r12:128] vmlal.u16 q14, d24, d2[3] vmlal.u16 q15, d25, d2[3] vmlal.u16 q14, d26, d2[3] vmlal.u16 q15, d27, d2[3] 110: add r12, r9, #0x148 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] add r12, r9, #0x1e8 bic r12, r12, #0x200 vld1.u16 {d26}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d27}, [r12:64] vmlal.u16 q14, d24, d2[2] vmlal.u16 q15, d25, d2[2] vmlal.u16 q14, d26, d2[2] vmlal.u16 q15, d27, d2[2] 109: add r12, r9, #0x150 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] add r12, r9, #0x1e0 bic r12, r12, #0x200 vld1.u16 {d26,d27}, [r12:128] vmlal.u16 q14, d24, d2[1] vmlal.u16 q15, d25, d2[1] vmlal.u16 q14, d26, d2[1] vmlal.u16 q15, d27, d2[1] 108: add r12, r9, #0x158 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] add r12, r9, #0x1d8 bic r12, r12, #0x200 vld1.u16 {d26}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d27}, [r12:64] vmlal.u16 q14, d24, d2[0] vmlal.u16 q15, d25, d2[0] vmlal.u16 q14, d26, d2[0] vmlal.u16 q15, d27, d2[0] 107: add r12, r9, #0x160 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] add r12, r9, #0x1d0 bic r12, r12, #0x200 vld1.u16 {d26,d27}, [r12:128] vmlal.u16 q14, d24, d1[3] vmlal.u16 q15, d25, d1[3] vmlal.u16 q14, d26, d1[3] vmlal.u16 q15, d27, d1[3] 106: add r12, r9, #0x168 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] add r12, r9, #0x1c8 bic r12, r12, #0x200 vld1.u16 {d26}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d27}, [r12:64] vmlal.u16 q14, d24, d1[2] vmlal.u16 q15, d25, d1[2] vmlal.u16 q14, d26, d1[2] vmlal.u16 q15, d27, d1[2] 105: add r12, r9, #0x170 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] add r12, r9, #0x1c0 bic r12, r12, #0x200 vld1.u16 {d26,d27}, [r12:128] vmlal.u16 q14, d24, d1[1] vmlal.u16 q15, d25, d1[1] vmlal.u16 q14, d26, d1[1] vmlal.u16 q15, d27, d1[1] 104: add r12, r9, #0x178 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] add r12, r9, #0x1b8 bic r12, r12, #0x200 vld1.u16 {d26}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d27}, [r12:64] vmlal.u16 q14, d24, d1[0] vmlal.u16 q15, d25, d1[0] vmlal.u16 q14, d26, d1[0] vmlal.u16 q15, d27, d1[0] 103: add r12, r9, #0x180 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128] add r12, r9, #0x1b0 bic r12, r12, #0x200 vld1.u16 {d26,d27}, [r12:128] vmlal.u16 q14, d24, d0[3] vmlal.u16 q15, d25, d0[3] vmlal.u16 q14, d26, d0[3] vmlal.u16 q15, d27, d0[3] 102: add r12, r9, #0x188 bic r12, r12, #0x200 vld1.u16 {d24}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d25}, [r12] add r12, r9, #0x1a8 bic r12, r12, #0x200 vld1.u16 {d26}, [r12:64]! bic r12, r12, #0x200 vld1.u16 {d27}, [r12:64] vmlal.u16 q14, d24, d0[2] vmlal.u16 q15, d25, d0[2] vmlal.u16 q14, d26, d0[2] vmlal.u16 q15, d27, d0[2] 101: add r12, r9, #0x190 bic r12, r12, #0x200 vld1.u16 {d24,d25}, [r12:128]! bic r12, r12, #0x200 vld1.u16 {d26,d27}, [r12:128] vmlal.u16 q14, d24, d0[1] vmlal.u16 q15, d25, d0[1] vmlal.u16 q14, d26, d0[1] vmlal.u16 q15, d27, d0[1] vqrshrn.u32 d28, q14, #16 vqrshrn.u32 d29, q15, #16 vqrshrn.u16 d31, q14, #FRACTION_BITS vst1.u8 {q4}, [r9:128]! bic r9, r9, #0x200 vmov q4, q5 vmov q5, q6 vmov q6, q7 vmov q7, q8 vmov q8, q9 vmov q9, q10 vmov q10, q11 .endm/*}}}*/ /* Dedicated function wrapper for the fetch macro, for the cases where * performance isn't that important, to keep code size down. */ PRIVATE(fetch_generic_asm) push {r10,r11} fetch pop {r10,r11} bx lr END(fetch_generic_asm) /* Given values in q10 and q11, and an index in r11, sweep the (r11&15)th value * across to fill the rest of the register pair. Used for filling the right * hand edge of the window when starting too close to the right hand edge of * the image. * Also returns a dup-ed copy of the last element in q12 for the tail-fill * case (this happens incidentally in common path, but must be done * deliberately in the fast-out path). */ PRIVATE(prefetch_clampright1) ands r12, r11, #15 beq 1f sub r12, r12, #1 sub sp, sp, #64 vst1.u16 {q10,q11}, [sp] add r12, sp, r12, LSL #1 vld1.u16 {d24[]}, [r12] vld1.u16 {d25[]}, [r12] vst1.u16 {q12}, [r12]! vst1.u16 {q12}, [r12] vld1.u16 {q10,q11}, [sp] add sp, sp, #64 bx lr 1: vdup.u16 q12, d23[3] bx lr END(prefetch_clampright1) PRIVATE(prefetch_clampright4) ands r12, r11, #15 beq 1f sub r12, r12, #4 sub sp, sp, #64 vst1.u16 {q10,q11}, [sp] add r12, sp, r12, LSL #1 vld1.u64 {d24}, [r12] vld1.u64 {d25}, [r12] vst1.u16 {q12}, [r12]! vst1.u16 {q12}, [r12] vld1.u16 {q10,q11}, [sp] add sp, sp, #64 bx lr 1: vmov.u16 d24, d23 vmov.u16 d25, d23 bx lr END(prefetch_clampright4) /* Helpers for prefetch, below. */ .macro prefetch_out qa, qb, store, qsa, qsb, qsb_hi .if \store > 0 .ifc \qsa,\qsb vst1.u16 {\qsa}, [r9:128]! vst1.u16 {\qsb}, [r9:128]! .else vst1.u16 {\qsa,\qsb}, [r9:256]! .endif .elseif \store == 0 vmov.u16 \qa, \qsa vmov.u16 \qb, \qsb .else vmov.u16 \qb, \qsb_hi .endif .endm .macro prefetch_one qa, qb, rem, c, store=0, step=1 .set i, (need - 16) - \rem .if i >= 0 1: cmp r10, #i+16 blo 2f prefetch_out \qa, \qb, \store, q9, q9, d19 b 1f 2: cmp r11, #i+16 bls 3f prefetch_out \qa, \qb, \store, q10, q11, d23 bl fetch_generic_asm b 2f 3: bl prefetch_clampright\step prefetch_out \qa, \qb, \store, q10, q11, d23 4: b 4f+4 @q12 contains pad word from prefetch_clampright call prefetch_out \qa, \qb, \store, q12, q12, d25 .if \rem > 0 b 4f+4 .else 1: 2: 3: 4: nop .endif .endif .endm /* Fill the convolution window with context data. The aim here is to load * exactly rlf + rrt columns, and in the main loop to read as many columns as * will be written. This is complicated by the need to handle cases when the * input starts very close to the left or right (or both) edges of the image, * and where these do not fall on 16-byte boundaries. * * Input: * r1 -- src * r2 -- pitch * r3 -- count * r4 -- inlen * r5 -- r * r6 -- rup * r7 -- rdn * r8 -- rlf * r9 -- buffer (if needed) * Output: * r1 += rlf + min(count, rrt) * Modifies: * r10 -- fill start index in the window * r11 -- fill stop index in the window * r12 -- scratch */ .macro prefetch step=1, max_r=25 .set need, ((\max_r + \max_r) * \step + 15) & ~15 .if \step == 1 rsb r10, r8, #need - (\max_r * \step) .else mov r10, r8, LSL #2 rsb r10, r10, #need - (\max_r * \step) .endif add r11, r10, r4 cmp r11, #need movhi r11, #need bl fetch_generic_asm .if \step == 1 vdup.u16 q9, d20[0] .else vmov.u16 d18, d20 vmov.u16 d19, d20 .endif ands r12, r10, #15 beq 2f sub sp, sp, #32 vst1.u16 {q10,q11}, [sp] sub r12, sp, r12, LSL #1 sub sp, sp, #16 vst1.u16 {q9}, [sp] sub sp, sp, #16 vst1.u16 {q9}, [sp] vld1.u16 {q10,q11}, [r12] add sp, sp, #64 sub r1, r1, r10 bic r10, r10, #15 add r1, r1, r10 2: .if \step > 1 /* it's only in the uchar2 and uchar4 cases where the register file * is insufficient (given MAX_R <= 25). */ prefetch_one xx, xx, 192, c=\max_r, step=\step, store=1 prefetch_one xx, xx, 176, c=\max_r, step=\step, store=1 prefetch_one xx, xx, 160, c=\max_r, step=\step, store=1 prefetch_one xx, xx, 144, c=\max_r, step=\step, store=1 prefetch_one xx, xx, 128, c=\max_r, step=\step, store=1 prefetch_one xx, xx, 112, c=\max_r, step=\step, store=1 prefetch_one xx, xx, 96, c=\max_r, step=\step, store=1 prefetch_one xx, xx, 80, c=\max_r, step=\step, store=1 prefetch_one xx, xx, 64, c=\max_r, step=\step, store=1 prefetch_one xx, xx, 48, c=\max_r, step=\step, store=1 .else /* q3 normally contains the coefficient table, but it's not fully * used. In the uchar1, r=25 case the other half of q3 is used for * the last two window taps to avoid falling out to memory. */ prefetch_one xx, d7, 48, c=\max_r, step=\step, store=-1 .endif prefetch_one q4, q5, 32, c=\max_r, step=\step, store=0 prefetch_one q6, q7, 16, c=\max_r, step=\step, store=0 prefetch_one q8, q9, 0, c=\max_r, step=\step, store=0 .if \step == 1 add r10, r8, #\max_r * \step .else mov r10, r8, LSL #2 add r10, r10, #\max_r * \step .endif subs r4, r4, r10 movlo r4, #0 .endm /* The main loop. * * Input: * r0 = dst * r1 = src * r2 = pitch * r3 = count * r4 = inlen * r5 = r * r6 = rup * r7 = rdn * r9 = buffer * Modifies * r8 = fetch code pointer */ .macro mainloop core, step=1, max_r=25, labelc="", labelnc="" ldr r8, 3f 1: add r8, r8, pc sub r8, r5, LSL #5 sub r8, r5, LSL #4 cmp r5, r6 cmpeq r5, r7 beq 5f /* if (r != rup || r != rdn) then the address-clamping table should * be used rather than the short-cut version. */ ldr r8, 3f+4 2: add r8, r8, pc sub r8, r5, LSL #6 b 5f .align 3 3: .word \labelnc-1b-8 .word \labelc-2b-8 .align 4 3: fetch max_r=\max_r, labelc=\labelc, labelnc=\labelnc, reg=r8 /* For each call to fetch two are made to \core. It would be * preferable to have twice the work done in \core, but the * register file is too small for this to be straightforward. */ \core vst1.u8 {d31}, [r0]! \core vst1.u8 {d31}, [r0]! sub r3, r3, #16 5: subs r4, r4, #16 bhs 3b adds r4, r4, #16 bne 1f .if \step==1 vdup.u16 q10, d19[3] vdup.u16 q11, d19[3] .else vmov.u64 d20, d19 vmov.u64 d21, d19 vmov.u64 d22, d19 vmov.u64 d23, d19 .endif b 4f 1: sub r1, r1, #16 add r1, r1, r4 bl fetch_generic_asm .if \step==1 vdup.u16 q12, d23[3] .else vmov.u64 d24, d23 vmov.u64 d25, d23 .endif rsb r4, r4, #0 tst r4, #8 beq 1f vmov q10, q11 vmov q11, q12 1: tst r4, #4 beq 1f vext.u16 q10, q10, q11, #4 vext.u16 q11, q11, q12, #4 1: tst r4, #2 beq 1f vext.u16 q10, q10, q11, #2 vext.u16 q11, q11, q12, #2 1: tst r4, #1 beq 4f vext.u16 q10, q10, q11, #1 vext.u16 q11, q11, q12, #1 4: cmp r3, #0 beq 5f 3: \core .if \step==1 vdup.u16 q11, d23[3] .else vmov.u64 d22, d23 .endif subs r3, r3, #8 blo 4f vst1.u8 {d31}, [r0]! beq 5f b 3b 4: tst r3, #4 beq 1f vst1.u32 {d31[0]}, [r0]! vext.u8 d31, d31, d31, #4 1: tst r3, #2 beq 1f vst1.u16 {d31[0]}, [r0]! vext.u8 d31, d31, d31, #2 1: tst r3, #1 beq 5f vst1.u8 {d31[0]}, [r0]! vext.u8 d31, d31, d31, #1 5: nop .endm .irep r, TUNED_LIST1, 25 PRIVATE(convolve1_\r) push {r12,lr} sub r1, r1, r8 prefetch step=1, max_r=\r mainloop core=hconv1_\r, step=1, max_r=\r, labelc=.Lcnv1_\r, labelnc=.Lcnvnc1_\r pop {r12,pc} END(convolve1_\r) .endr .irep r, TUNED_LIST4, 25 PRIVATE(convolve4_\r) sub r12, sp, #0x200 bic r9, r12, #0x3fc mov sp, r9 push {r12,lr} /* r9 now points to a buffer on the stack whose address has the low * 10 bits clear. This allows easy address calculation in the * wrap-around cases. */ sub r1, r1, r8, LSL #2 prefetch step=4, max_r=\r mainloop core=hconv4_\r, step=4, max_r=\r, labelc=.Lcnv4_\r, labelnc=.Lcnvnc4_\r pop {r12,lr} add sp, r12, #0x200 bx lr END(convolve4_\r) .endr /* void rsdIntrinsicBlurU1_K( * void *out, // r0 * void *in, // r1 * size_t w, // r2 * size_t h, // r3 * size_t p, // [sp] * size_t x, // [sp,#4] * size_t y, // [sp,#8] * size_t count, // [sp,#12] * size_t r, // [sp,#16] * uint16_t *tab); // [sp,#20] */ ENTRY(rsdIntrinsicBlurU1_K) push {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} vpush {d8-d15} ldr r5, [sp,#120] ldr r8, [sp,#108] ldr r6, [sp,#112] sub r9, r2, r8 sub r7, r3, r6 ldr r2, [sp,#104] ldr r3, [sp,#116] sub r9, r9, r3 sub r7, r7, #1 ldr r12, [sp,#124] add r1, r1, r8 cmp r6, r5 movhi r6, r5 cmp r7, r5 movhi r7, r5 cmp r8, r5 movhi r8, r5 cmp r9, r5 movhi r9, r5 add r4, r8, r9 add r4, r4, r3 vld1.u16 {d0,d1,d2,d3}, [r12]! vld1.u16 {d4,d5,d6}, [r12]! adr lr, 1f .irep r, TUNED_LIST1 cmp r5, #\r bls convolve1_\r .endr b convolve1_25 1: vpop {d8-d15} pop {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} END(rsdIntrinsicBlurU1_K) /* void rsdIntrinsicBlurU4_K( * void *out, // r0 * void *in, // r1 * size_t w, // r2 * size_t h, // r3 * size_t p, // [sp] * size_t x, // [sp,#4] * size_t y, // [sp,#8] * size_t count, // [sp,#12] * size_t r, // [sp,#16] * uint16_t *tab); // [sp,#20] */ ENTRY(rsdIntrinsicBlurU4_K) push {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} vpush {d8-d15} ldr r5, [sp,#120] ldr r8, [sp,#108] ldr r6, [sp,#112] sub r9, r2, r8 sub r7, r3, r6 ldr r2, [sp,#104] ldr r3, [sp,#116] sub r9, r9, r3 sub r7, r7, #1 ldr r12, [sp,#124] add r1, r1, r8, LSL #2 cmp r6, r5 movhi r6, r5 cmp r7, r5 movhi r7, r5 cmp r8, r5 movhi r8, r5 cmp r9, r5 movhi r9, r5 mov r3, r3, LSL #2 add r4, r8, r9 add r4, r3, r4, LSL #2 vld1.u16 {d0,d1,d2,d3}, [r12]! vld1.u16 {d4,d5,d6}, [r12]! adr lr, 1f .irep r, TUNED_LIST4 cmp r5, #\r bls convolve4_\r .endr b convolve4_25 1: vpop {d8-d15} pop {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} END(rsdIntrinsicBlurU4_K)