blob: 45a6980072be3a94b254a22a07a45468bcfb140d [file] [log] [blame]
// Copyright (c) Facebook, Inc. and its affiliates.
// All rights reserved.
//
// Copyright 2019 Google LLC
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.
#include <xnnpack/assembly.h>
.syntax unified
# void xnn_q8_dwconv_ukernel_up8x9__aarch32_neon(
# size_t channels,
# size_t output_width,
# const uint8_t** input,
# const void* weights,
# uint8_t* output,
# size_t input_stride,
# size_t output_increment,
# const union xnn_q8_gemm_params params[restrict static 1])
BEGIN_FUNCTION xnn_q8_dwconv_ukernel_up8x9__aarch32_neon
.arm
#ifndef __APPLE__
.arch armv7-a
.fpu neon
#endif
# Load params
# - r12 = params
LDR r12, [sp, 12]
PUSH {r4, r5, r6, r7, r8, r9, r10, r11, lr}
VPUSH {d8-d15}
STR r0, [sp, #-8]
STR r3, [sp, #-4]
MOV r4, 4
# Load o:
# - lr = o = output
LDR lr, [sp, 100]
# Load kernel zero point:
# - d31 = vkernel_zero_point
VLD1.8 {d31[]}, [r12], r4
# Load multiplier:
# - q14 = d28:d29 = vmultiplier
VLD1.32 {d28[], d29[]}, [r12]!
# Load right shift:
# - q13 = d26:d27 = vright_shift
VLD1.32 {d26[], d27[]}, [r12]!
# Load output zero point:
# - q12 = d24:d25 = voutput_zero_point
VLD1.16 {d24[], d25[]}, [r12]!
# Compute vzero_shift_mask
# - q11 = vzero_shift_mask
VCEQ.S32 q11, q13, 0
# Load output max:
# - d20 = voutput_max
VLD1.8 {d20[]}, [r12]!
# Load output min:
# - d21 = voutput_min
VLD1.8 {d21[]}, [r12]
.p2align 3
0:
# Load input stride
# - r3 = input_stride
LDR r3, [sp, 104]
# Load c:
# - r0 = c = channels
LDR r0, [sp, #-8]
# Load i0, i1, i2, i3, i4, i5, i6, i7, i8
# - r4 = i0
# - r5 = i1
# - r6 = i2
# - r7 = i3
# - r8 = i4
# - r9 = i5
# - r10 = i6
# - r11 = i7
# - r12 = i8
LDM r2, {r4, r5, r6, r7, r8, r9, r10, r11, r12}
# Pre-decrement c
SUBS r0, r0, 8
# Increment input by input stride
# - input = r2 := input + input_stride
ADD r2, r2, r3
# Load w:
# - r3 = w = weights
LDR r3, [sp, #-4]
BLO 2f
.p2align 4
1:
VLDM r3!, {d0-d3}
VLD1.8 {d4}, [r4]!
VLD1.8 {d6}, [r3]!
VLD1.8 {d8}, [r5]!
VLD1.8 {d10}, [r3]!
VMOVL.U8 q2, d4
VSUBL.U8 q3, d6, d31
VLD1.8 {d12}, [r6]!
VLD1.8 {d14}, [r3]!
VMOVL.U8 q4, d8
VSUBL.U8 q5, d10, d31
VMLAL.S16 q0, d4, d6
VMLAL.S16 q1, d5, d7
VLD1.8 {d4}, [r7]!
VLD1.8 {d6}, [r3]!
VMOVL.U8 q6, d12
VSUBL.U8 q7, d14, d31
VMLAL.S16 q0, d8, d10
VMLAL.S16 q1, d9, d11
VLD1.8 {d8}, [r8]!
VLD1.8 {d10}, [r3]!
VMOVL.U8 q2, d4
VSUBL.U8 q3, d6, d31
VMLAL.S16 q0, d12, d14
VMLAL.S16 q1, d13, d15
VLD1.8 {d12}, [r9]!
VLD1.8 {d14}, [r3]!
VMOVL.U8 q4, d8
VSUBL.U8 q5, d10, d31
VMLAL.S16 q0, d4, d6
VMLAL.S16 q1, d5, d7
VLD1.8 {d4}, [r10]!
VLD1.8 {d6}, [r3]!
VMOVL.U8 q6, d12
VSUBL.U8 q7, d14, d31
VMLAL.S16 q0, d8, d10
VMLAL.S16 q1, d9, d11
VLD1.8 {d8}, [r11]!
VLD1.8 {d10}, [r3]!
VMOVL.U8 q2, d4
VSUBL.U8 q3, d6, d31
VMLAL.S16 q0, d12, d14
VMLAL.S16 q1, d13, d15
VLD1.8 {d12}, [r12]!
VLD1.8 {d14}, [r3]!
VMOVL.U8 q4, d8
VSUBL.U8 q5, d10, d31
VMLAL.S16 q0, d4, d6
VMLAL.S16 q1, d5, d7
VMOVL.U8 q6, d12
VSUBL.U8 q7, d14, d31
VMLAL.S16 q0, d8, d10
VMLAL.S16 q1, d9, d11
VMLAL.S16 q0, d12, d14
VMLAL.S16 q1, d13, d15
VQRDMULH.S32 q0, q0, q14
VQRDMULH.S32 q1, q1, q14
VBIC q2, q0, q11
VBIC q3, q1, q11
VSRA.S32 q0, q2, 31
VSRA.S32 q1, q3, 31
VRSHL.S32 q0, q0, q13
VRSHL.S32 q1, q1, q13
VQMOVN.S32 d0, q0
VQMOVN.S32 d1, q1
VQADD.S16 q0, q12
VQMOVUN.S16 d0, q0
VMIN.U8 d0, d0, d20
VMAX.U8 d0, d0, d21
VST1.8 {d0}, [lr]!
SUBS r0, r0, 8
BHS 1b
2:
CMP r0, -8
BEQ 5f
VLDM r3!, {d0-d3}
VLD1.8 {d4}, [r4]!
VLD1.8 {d6}, [r3]!
VLD1.8 {d8}, [r5]!
VLD1.8 {d10}, [r3]!
VMOVL.U8 q2, d4
VSUBL.U8 q3, d6, d31
VLD1.8 {d12}, [r6]!
VLD1.8 {d14}, [r3]!
VMOVL.U8 q4, d8
VSUBL.U8 q5, d10, d31
VMLAL.S16 q0, d4, d6
VMLAL.S16 q1, d5, d7
VLD1.8 {d4}, [r7]!
VLD1.8 {d6}, [r3]!
VMOVL.U8 q6, d12
VSUBL.U8 q7, d14, d31
VMLAL.S16 q0, d8, d10
VMLAL.S16 q1, d9, d11
VLD1.8 {d8}, [r8]!
VLD1.8 {d10}, [r3]!
VMOVL.U8 q2, d4
VSUBL.U8 q3, d6, d31
VMLAL.S16 q0, d12, d14
VMLAL.S16 q1, d13, d15
VLD1.8 {d12}, [r9]!
VLD1.8 {d14}, [r3]!
VMOVL.U8 q4, d8
VSUBL.U8 q5, d10, d31
VMLAL.S16 q0, d4, d6
VMLAL.S16 q1, d5, d7
VLD1.8 {d4}, [r10]!
VLD1.8 {d6}, [r3]!
VMOVL.U8 q6, d12
VSUBL.U8 q7, d14, d31
VMLAL.S16 q0, d8, d10
VMLAL.S16 q1, d9, d11
VLD1.8 {d8}, [r11]!
VLD1.8 {d10}, [r3]!
VMOVL.U8 q2, d4
VSUBL.U8 q3, d6, d31
VMLAL.S16 q0, d12, d14
VMLAL.S16 q1, d13, d15
VLD1.8 {d12}, [r12]!
VLD1.8 {d14}, [r3]!
VMOVL.U8 q4, d8
VSUBL.U8 q5, d10, d31
VMLAL.S16 q0, d4, d6
VMLAL.S16 q1, d5, d7
VMOVL.U8 q6, d12
VSUBL.U8 q7, d14, d31
VMLAL.S16 q0, d8, d10
VMLAL.S16 q1, d9, d11
VMLAL.S16 q0, d12, d14
VMLAL.S16 q1, d13, d15
VQRDMULH.S32 q0, q0, q14
VQRDMULH.S32 q1, q1, q14
VBIC q2, q0, q11
VBIC q3, q1, q11
VSRA.S32 q0, q2, 31
VSRA.S32 q1, q3, 31
VRSHL.S32 q0, q0, q13
VRSHL.S32 q1, q1, q13
VQMOVN.S32 d0, q0
VQMOVN.S32 d1, q1
VQADD.S16 q0, q12
VQMOVUN.S16 d0, q0
VMIN.U8 d0, d0, d20
VMAX.U8 d0, d0, d21
TST r0, 4
BEQ 3f
VST1.32 {d0[0]}, [lr]!
VEXT.8 d0, d0, 4
3:
TST r0, 2
BEQ 4f
VST1.16 {d0[0]}, [lr]!
VEXT.8 d0, d0, 2
4:
TST r0, 1
BEQ 5f
VST1.8 {d0[0]}, [lr]!
5:
# Load output increment
# - r3 = output_increment
LDR r3, [sp, 108]
# Decrement output width
SUBS r1, r1, 1
# Increment output by output_increment
ADD lr, lr, r3
# If output width is non-zero, process another pixel
BNE 0b
VPOP {d8-d15}
POP {r4, r5, r6, r7, r8, r9, r10, r11, pc}
END_FUNCTION xnn_q8_dwconv_ukernel_up8x9__aarch32_neon
#ifdef __ELF__
.section ".note.GNU-stack","",%progbits
#endif