arm汇编解析—qnnpack卷积实现
目錄
前言
基礎直通車
arm基礎知識
arm指令釋義
qnn匯編代碼解析
前言
最近在移植QNNPACK神經網絡加速庫,涉及到對卷積arm匯編的修改,這邊做個記錄,對匯編部分的內容進行注釋,順便學習一下匯編的語法。
?
基礎直通車
首先要補充arm匯編基礎知識,特別是如何傳參一定要搞清楚,另外對arm寄存器要了然于胸,剩下的就是指令的用法了:
利用堆棧入參參考:https://www.cnblogs.com/qq78292959/p/4013356.html
arm 32位NEON寄存器:https://blog.csdn.net/SoaringLee_fighting/article/details/81743505
ARM匯編器對ARM的寄存器預定義:https://blog.csdn.net/SoaringLee_fighting/article/details/81287824
ARM匯編指令:https://blog.csdn.net/zhangmiaoping23/article/details/8875193
?
arm基礎知識?
R0-R15和r0-r15
a1-a4(參數,結果或者臨時寄存器,與r0-r3同意)
v1-v8(變量寄存器,與r4-r11同意)
sb和SB(靜態基址寄存器,與r9同意)
sl和SL(堆棧限制寄存器,與r10同意)
fp和FP(幀指針,與r11同意)
ip和IP(過程調用中間臨時寄存器,與r12同意)
sp和SP(堆棧指針,與r13同意)
lr和LR(連接寄存器,與r14同意)
pc和PC(程序計數器,與r15同意)
cpsr和CPSR(程序狀態寄存器)
spsr和SPSR(程序狀態寄存器)
f0-f7和F0-F7(FPA寄存器)
s0-s31和S0-S31(VFP單精度寄存器)
d0-d15和D0-D15(VFP雙精度寄存器)
p0-p15(協處理器0-15)
c0-c15(協處理器寄存器0-15)
使用說明:
1、當參數少于4個時,子程序間通過寄存器R0~R3來傳遞參數;當參數個數多于4個時,將多余的參數通過數據棧進行傳遞,入棧順序與參數順序正好相反,子程序返回前無需恢復R0~R3的值;?
2、在子程序中,使用R4~R11保存局部變量,若使用需要入棧保存,子程序返回前需要恢復這些寄存器;R12是臨時寄存器,使用不需要保存。?
3、R13用作數據幀指針,記作SP;R14用作鏈接寄存器,記作LR,用于保存子程序返回時的地址;R15是程序計數器,記作PC。?
4、ATPCS規定堆棧是滿遞減堆棧FD;?
5、子程序返回32位的整數,使用R0返回;返回64位整數時,使用R0返回低位,R1返回高位。
Arm32位寄存器主要分為ARM寄存器和NEON寄存器。?
ARM32寄存器包括15個通用寄存器R0~R14和一個程序計數器PC,共16個,均為32位寬。?
ARM32位寄存器的調用規則:遵循ATPCS調用規則
32位 NEON寄存器:?
包括:32個S寄存器,S0~S31,(單字,32bit)?
32個D寄存器,D0~D31,(雙字,64bit)?
16個Q寄存器,Q0~Q15,(四字,128bit)?
寄存器的對應關系如下圖所示:?
使用說明:?
1、NEON寄存器將每個寄存器均視為一個向量,該向量又包含1,2,4,8或16個大小和類型均相同的元素。也可以將各個元素當做標量訪問。?
NEON的這三種寄存器是重疊的,物理地址是一樣的。?
2、NEON寄存器在使用時,如果用到d8~d15寄存器,需要先入棧保存vpush {d8-d15},使用完之后要出棧vpop {d8-d15}
arm指令釋義
條件分支:
CMP:算數處理指令,用于把一個寄存器的內容和另一個寄存器的內容或立即數進行減法比較,不存儲結果,都會更改標志位
BNE:?數據跳轉指令,標志寄存器中Z標志位不等于零時,?跳轉到BNE后標簽處
BNE 3f 0b f:forward,b:backward
BEQ:?數據跳轉指令,標志寄存器中Z標志位等于零時,?跳轉到BEQ后標簽處
BLO指令 ?小于(無符號數)跳轉
BLT:小于跳轉;
TEQ:用于把一個寄存器的內容和另一個寄存器的內容或立即數進行按位的異或運算,并根據運算結果更新CPSR中條件標志位的值。該指令通常用于比較操作數1和操作數2是否相等。(EOR指令也是實現異或運算,只是不更新CPSR)
LSL:邏輯左移,LSR:邏輯右移
| 助記符 | 含????義 |
| EQ | 相等equal |
| NE | 不相等not equal |
| CS | 無符號數大于或等于Carry Set |
| CC | 無符號數小于 |
| MI | 負數minus |
| PL | 正數或零plus |
| VS | 溢出 |
| VC | 沒有溢出 |
| HI | 無符號數大于high |
| LS | 無符號數小于或等于less |
| GE | 帶符號數大于或等于 |
| LT | 帶符號數小于less than |
| GT | 帶符號數大于great than |
| LE | 帶符號數小于或等于 |
| AL | 無條件執行all |
數據加載及存儲:
ldr ip,[sp],#4 將sp中內容存入ip,之后sp=sp+4;
ldr ip,[sp,#4] 將sp+4這個新地址下內容存入ip,之后sp值保持不變
ldr ip,[sp,#4]!將sp+4這個新地址下內容存入ip,之后sp=sp+4將新地址值賦給sp
str ip,[sp],#4 將ip存入sp地址處,之后sp=sp+4;
str ip,[sp,#4] 將ip存入sp+4這個新地址,之后sp值保持不變
str ip,[sp,#4]!將ip存入sp+4這個新地址,之后sp=sp+4將新地址值賦給sp
?
qnn匯編代碼解析
先對BEGIN_FUNCTION定義說明
#ifdef?__ELF__? ? //linux系統編譯宏.macro?BEGIN_FUNCTION?name.text.align?2.global?\name.type?\name,?%function\name:.endm.macro?END_FUNCTION?name.size?\name,?.-\name.endm#elif?defined(__MACH__)? //ios/machos系統編譯宏.macro?BEGIN_FUNCTION?name?.text.align?2.global?_\name.private_extern?_\name_\name:.endm.macro?END_FUNCTION?name.endm#endif卷積匯編代碼:?
/** Copyright (c) Facebook, Inc. and its affiliates.* All rights reserved.** This source code is licensed under the BSD-style license found in the* LICENSE file in the root directory of this source tree.*/.include "assembly.h".syntax unified# void q8conv_ukernel_4x8__aarch32_neon( # ? ? size_t mr, # ? ? size_t nr, # ? ? size_t kc, # ? ? size_t ks, # ? ? const uint8_t**restrict a, ###### r8 [sp, 96] ,3 # ? ? const void*restrict w, ###### ip [sp, 4] ,1 # ? ? uint8_t*restrict c, -> int32_t*restrict c, ###### r2, r3, [sp, 104] ,4 # ? ? size_t c_stride, # ? ? const union qnnp_conv_quantization_params quantization_params[restrict static 1])? ###### r9 [sp, 112] ,2#關于參數說明:從a開始的參數因為超過了4個,采用堆棧方式傳參,從最后一個參數params入棧,入棧方式為滿減棧(從上往下遞減)BEGIN_FUNCTION q8conv_ukernel_4x8__aarch32_neon.arm #ifndef __APPLE__.arch armv7-a.fpu neon #endif# Load w# - ip = w# ip==r12:temp register; sp==r13:top stack;# ip=sp+4=w,the 4 is size of?ptr a(地址偏移都以字節為單位)LDR ip, [sp, 4]PUSH {r4, r5, r6, r7, r8, r9, r10, r11}? ? #壓入棧中保存r4-r11的值。r4-r11用作局部變量VPUSH {d8-d15} #壓棧保存# Load bias0123, bias4567VLDM ip!, {d16-d19}? ?? ?# load bias:8xint32 = 4x64(d16-d19)# Load params:# - r9 = paramsLDR r9, [sp, 112]? ?#sizeof(r4-r11) + sizeof(d8-d15) +sizeof(a+w+c+c_stride)=32/8*8+64/8*8+4*4=112# q10 := vacc1x0123VMOV.I32 q10, q8? ? ?# mov 32x4 bias t0 q10(sizeof(q8)==128 bits)?MOV r4, 4# q11 := vacc1x4567VMOV.I32 q11, q9? ? ?# 將q9中的4個32賦值為q11# Load a# - r8 = aLDR r8, [sp, 96]??#sizeof(r4-r11) + sizeof(d8-d15) = 32/8*8 + 64/8*8=96# q12 := vacc2x0123VMOV.I32 q12, q8# q13 := vacc2x4567VMOV.I32 q13, q9# q14 := vacc3x0123VMOV.I32 q14, q8# Load b_zero_point:# - d15 = b_zero_point?? ?VLD1.8 {d15[]}, [r9], r4? ??# mov the value from r9 to all d15(per 8bit); r9=r9+r4(per 8bit)# q15 := vacc3x4567VMOV.I32 q15, q9# Load multiplier:# - d12 = vmultiplierVLD1.32 {d12[]}, [r9]!.p2align 5 0:SUBS r10, r2, 8# Load a0, a1, a2, a3# - r4 = a0# - r5 = a1# - r6 = a2# - r7 = a3LDM r8!, {r4-r7}BLO 2f1:# Load va0# - d1 = va0VLD1.8 {d1}, [r4]!# Load va1# - d3 = va1VLD1.8 {d3}, [r5]!# Load vb0-vb7 (channel 0)# - d9 = vb0-vb7VLD1.8 {d9}, [ip:64]!# Load va2# - d5 = va2VLD1.8 {d5}, [r6]!# q0 = va0 = a0VMOVL.U8 q0, d1# Load va3# - d7 = va3VLD1.8 {d7}, [r7]!# q1 = va1 = a1VMOVL.U8 q1, d3# q4 = b0:7 - vb_zero_point# - d8 = vb0123 (channel 0)# - d9 = vb4567 (channel 0)VSUBL.U8 q4, d9, d15# q2 = va2 = a2VMOVL.U8 q2, d5# q3 = va3 = a3VMOVL.U8 q3, d7### Channel 0 #### Load b0-b7 (channel 1)# - d11 = b0-b7VLD1.8 {d11}, [ip:64]!# vacc0x0123 += vb0123 * va0[0]VMLAL.S16 q8, d8, d0[0]# vacc0x4567 += vb4567 * va0[0]VMLAL.S16 q9, d9, d0[0]# vacc1x0123 += vb0123 * va1[0]VMLAL.S16 q10, d8, d2[0]# vacc1x4567 += vb4567 * va1[0]VMLAL.S16 q11, d9, d2[0]# vacc2x0123 += vb0123 * va2[0]VMLAL.S16 q12, d8, d4[0]# vacc2x4567 += vb4567 * va2[0]VMLAL.S16 q13, d9, d4[0]# q5 = b0:7 - vb_zero_point# - d10 = vb0123 (channel 1)# - d11 = vb4567 (channel 1)VSUBL.U8 q5, d11, d15# vacc3x0123 += vb0123 * va3[0]VMLAL.S16 q14, d8, d6[0]# vacc3x4567 += vb4567 * va3[0]VMLAL.S16 q15, d9, d6[0]### Channel 1 #### Load b0-b7 (channel 2)# - d9 = b0-b7VLD1.8 {d9}, [ip:64]!# vacc0x0123 += vb0123 * va0[1]VMLAL.S16 q8, d10, d0[1]# vacc0x4567 += vb4567 * va0[1]VMLAL.S16 q9, d11, d0[1]# vacc1x0123 += vb0123 * va1[1]VMLAL.S16 q10, d10, d2[1]# vacc1x4567 += vb4567 * va1[1]VMLAL.S16 q11, d11, d2[1]# vacc2x0123 += vb0123 * va2[1]VMLAL.S16 q12, d10, d4[1]# vacc2x4567 += vb4567 * va2[1]VMLAL.S16 q13, d11, d4[1]# q4 = b0:7 - vb_zero_point# - d8 = vb0123 (channel 2)# - d9 = vb4567 (channel 2)VSUBL.U8 q4, d9, d15# vacc3x0123 += vb0123 * va3[1]VMLAL.S16 q14, d10, d6[1]# vacc3x4567 += vb4567 * va3[1]VMLAL.S16 q15, d11, d6[1]### Channel 2 #### Load b0-b7 (channel 3)# - d11 = b0-b7VLD1.8 {d11}, [ip:64]!# vacc0x0123 += vb0123 * va0[2]VMLAL.S16 q8, d8, d0[2]# vacc0x4567 += vb4567 * va0[2]VMLAL.S16 q9, d9, d0[2]# vacc1x0123 += vb0123 * va1[2]VMLAL.S16 q10, d8, d2[2]# vacc1x4567 += vb4567 * va1[2]VMLAL.S16 q11, d9, d2[2]# vacc2x0123 += vb0123 * va2[2]VMLAL.S16 q12, d8, d4[2]# vacc2x4567 += vb4567 * va2[2]VMLAL.S16 q13, d9, d4[2]# q5 = b0:7 - vb_zero_point# - d10 = vb0123 (channel 3)# - d11 = vb4567 (channel 3)VSUBL.U8 q5, d11, d15# vacc3x0123 += vb0123 * va3[2]VMLAL.S16 q14, d8, d6[2]# vacc3x4567 += vb4567 * va3[2]VMLAL.S16 q15, d9, d6[2]### Channel 3 #### Load b0-b7 (channel 4)# - d9 = b0-b7VLD1.8 {d9}, [ip:64]!# vacc0x0123 += vb0123 * va0[3]VMLAL.S16 q8, d10, d0[3]# vacc0x4567 += vb4567 * va0[3]VMLAL.S16 q9, d11, d0[3]# vacc1x0123 += vb0123 * va1[3]VMLAL.S16 q10, d10, d2[3]# vacc1x4567 += vb4567 * va1[3]VMLAL.S16 q11, d11, d2[3]# vacc2x0123 += vb0123 * va2[3]VMLAL.S16 q12, d10, d4[3]# vacc2x4567 += vb4567 * va2[3]VMLAL.S16 q13, d11, d4[3]# q5 = b0:7 - vb_zero_point# - d10 = vb0123 (channel 4)# - d11 = vb4567 (channel 4)VSUBL.U8 q4, d9, d15# vacc3x0123 += vb0123 * va3[3]VMLAL.S16 q14, d10, d6[3]# vacc3x4567 += vb4567 * va3[3]VMLAL.S16 q15, d11, d6[3]### Channel 4 #### Load b0-b7 (channel 5)# - d11 = b0-b7VLD1.8 {d11}, [ip:64]!# vacc0x0123 += vb0123 * va0[4]VMLAL.S16 q8, d8, d1[0]# vacc0x4567 += vb4567 * va0[4]VMLAL.S16 q9, d9, d1[0]# vacc1x0123 += vb0123 * va1[4]VMLAL.S16 q10, d8, d3[0]# vacc1x4567 += vb4567 * va1[4]VMLAL.S16 q11, d9, d3[0]# vacc2x0123 += vb0123 * va2[4]VMLAL.S16 q12, d8, d5[0]# vacc2x4567 += vb4567 * va2[4]VMLAL.S16 q13, d9, d5[0]# q4 = b0:7 - vb_zero_point# - d8 = vb0123 (channel 5)# - d9 = vb4567 (channel 5)VSUBL.U8 q5, d11, d15# vacc3x0123 += vb0123 * va3[4]VMLAL.S16 q14, d8, d7[0]# vacc3x4567 += vb4567 * va3[4]VMLAL.S16 q15, d9, d7[0]### Channel 5 #### Load b0-b7 (channel 6)# - d9 = b0-b7VLD1.8 {d9}, [ip:64]!# vacc0x0123 += vb0123 * va0[5]VMLAL.S16 q8, d10, d1[1]# vacc0x4567 += vb4567 * va0[5]VMLAL.S16 q9, d11, d1[1]# vacc1x0123 += vb0123 * va1[5]VMLAL.S16 q10, d10, d3[1]# vacc1x4567 += vb4567 * va1[5]VMLAL.S16 q11, d11, d3[1]# vacc2x0123 += vb0123 * va2[5]VMLAL.S16 q12, d10, d5[1]# vacc2x4567 += vb4567 * va2[5]VMLAL.S16 q13, d11, d5[1]# q4 = b0:7 - vb_zero_point# - d8 = vb0123 (channel 6)# - d9 = vb4567 (channel 6)VSUBL.U8 q4, d9, d15# vacc3x0123 += vb0123 * va3[5]VMLAL.S16 q14, d10, d7[1]# vacc3x4567 += vb4567 * va3[5]VMLAL.S16 q15, d11, d7[1]### Channel 6 #### Load b0-b7 (channel 7)# - d11 = b0-b7VLD1.8 {d11}, [ip:64]!# vacc0x0123 += vb0123 * va0[6]VMLAL.S16 q8, d8, d1[2]# vacc0x4567 += vb4567 * va0[6]VMLAL.S16 q9, d9, d1[2]# vacc1x0123 += vb0123 * va1[6]VMLAL.S16 q10, d8, d3[2]# vacc1x4567 += vb4567 * va1[6]VMLAL.S16 q11, d9, d3[2]# vacc2x0123 += vb0123 * va2[6]VMLAL.S16 q12, d8, d5[2]# q5 = b0:7 - vb_zero_point# - d10 = vb0123 (channel 7)# - d11 = vb4567 (channel 7)VSUBL.U8 q5, d11, d15# vacc2x4567 += vb4567 * va2[6]VMLAL.S16 q13, d9, d5[2]# vacc3x0123 += vb0123 * va3[6]VMLAL.S16 q14, d8, d7[2]# vacc3x4567 += vb4567 * va3[6]VMLAL.S16 q15, d9, d7[2]### Channel 8 ###SUBS r10, r10, 8# vacc0x0123 += vb0123 * va0[7]VMLAL.S16 q8, d10, d1[3]# vacc0x4567 += vb4567 * va0[7]VMLAL.S16 q9, d11, d1[3]# vacc1x0123 += vb0123 * va1[7]VMLAL.S16 q10, d10, d3[3]# vacc1x4567 += vb4567 * va1[7]VMLAL.S16 q11, d11, d3[3]# vacc2x0123 += vb0123 * va2[7]VMLAL.S16 q12, d10, d5[3]# vacc2x4567 += vb4567 * va2[7]VMLAL.S16 q13, d11, d5[3]# vacc3x0123 += vb0123 * va3[7]VMLAL.S16 q14, d10, d7[3]# vacc3x4567 += vb4567 * va3[7]VMLAL.S16 q15, d11, d7[3]BHS 1b2:CMP r10, -8BEQ 3f# Adjust a0, a1, a2, a3ADD r4, r10ADD r5, r10ADD r6, r10ADD r7, r10# a_shift = 8 * k - 64LSL r10, r10, 3VDUP.32 d13, r10# Load va0# - d1 = va0VLD1.8 {d1}, [r4]# Load va1# - d3 = va1VLD1.8 {d3}, [r5]# Load b0-b7 (channel 0)# - d9 = b0-b7VLD1.8 {d9}, [ip:64]!# Load a2# - d5 = a2VLD1.8 {d5}, [r6]# q0 = va0 = a0VSHL.U64 d1, d1, d13VMOVL.U8 q0, d1# Load a3# - d7 = a3VLD1.8 {d7}, [r7]# q1 = va1 = a1VSHL.U64 d3, d3, d13VMOVL.U8 q1, d3# q4 = b0:7 - vb_zero_point# - d8 = vb0123 (channel 0)# - d9 = vb4567 (channel 0)VSUBL.U8 q4, d9, d15# q2 = va2 = a2VSHL.U64 d5, d5, d13VMOVL.U8 q2, d5# q3 = va3 = a3VSHL.U64 d7, d7, d13VMOVL.U8 q3, d7### Channel 0 #### vacc0x0123 += vb0123 * va0[0]VMLAL.S16 q8, d8, d0[0]# vacc0x4567 += vb4567 * va0[0]VMLAL.S16 q9, d9, d0[0]# vacc1x0123 += vb0123 * va1[0]VMLAL.S16 q10, d8, d2[0]# vacc1x4567 += vb4567 * va1[0]VMLAL.S16 q11, d9, d2[0]# vacc2x0123 += vb0123 * va2[0]VMLAL.S16 q12, d8, d4[0]# vacc2x4567 += vb4567 * va2[0]VMLAL.S16 q13, d9, d4[0]# vacc3x0123 += vb0123 * va3[0]VMLAL.S16 q14, d8, d6[0]# vacc3x4567 += vb4567 * va3[0]VMLAL.S16 q15, d9, d6[0]CMP r10, -48BLO 3f### Channel 1 #### Load b0-b7 (channel 1)# - d11 = b0-b7VLD1.8 {d11}, [ip:64]!# q5 = b0:7 - vb_zero_point# - d10 = vb0123 (channel 1)# - d11 = vb4567 (channel 1)VSUBL.U8 q5, d11, d15# vacc0x0123 += vb0123 * va0[1]VMLAL.S16 q8, d10, d0[1]# vacc0x4567 += vb4567 * va0[1]VMLAL.S16 q9, d11, d0[1]# vacc1x0123 += vb0123 * va1[1]VMLAL.S16 q10, d10, d2[1]# vacc1x4567 += vb4567 * va1[1]VMLAL.S16 q11, d11, d2[1]# vacc2x0123 += vb0123 * va2[1]VMLAL.S16 q12, d10, d4[1]# vacc2x4567 += vb4567 * va2[1]VMLAL.S16 q13, d11, d4[1]# vacc3x0123 += vb0123 * va3[1]VMLAL.S16 q14, d10, d6[1]# vacc3x4567 += vb4567 * va3[1]VMLAL.S16 q15, d11, d6[1]### Channel 2 ###BLS 3f# Load b0-b7 (channel 2)# - d9 = b0-b7VLD1.8 {d9}, [ip:64]!# q4 = b0:7 - vb_zero_point# - d8 = vb0123 (channel 2)# - d9 = vb4567 (channel 2)VSUBL.U8 q4, d9, d15# vacc0x0123 += vb0123 * va0[2]VMLAL.S16 q8, d8, d0[2]# vacc0x4567 += vb4567 * va0[2]VMLAL.S16 q9, d9, d0[2]# vacc1x0123 += vb0123 * va1[2]VMLAL.S16 q10, d8, d2[2]# vacc1x4567 += vb4567 * va1[2]VMLAL.S16 q11, d9, d2[2]# vacc2x0123 += vb0123 * va2[2]VMLAL.S16 q12, d8, d4[2]# vacc2x4567 += vb4567 * va2[2]VMLAL.S16 q13, d9, d4[2]# vacc3x0123 += vb0123 * va3[2]VMLAL.S16 q14, d8, d6[2]# vacc3x4567 += vb4567 * va3[2]VMLAL.S16 q15, d9, d6[2]### Channel 3 ###CMP r10, -32BLO 3f# Load b0-b7 (channel 3)# - d9 = b0-b7VLD1.8 {d11}, [ip:64]!# q4 = b0:7 - vb_zero_point# - d8 = vb0123 (channel 3)# - d9 = vb4567 (channel 3)VSUBL.U8 q5, d11, d15# vacc0x0123 += vb0123 * va0[3]VMLAL.S16 q8, d10, d0[3]# vacc0x4567 += vb4567 * va0[3]VMLAL.S16 q9, d11, d0[3]# vacc1x0123 += vb0123 * va1[3]VMLAL.S16 q10, d10, d2[3]# vacc1x4567 += vb4567 * va1[3]VMLAL.S16 q11, d11, d2[3]# vacc2x0123 += vb0123 * va2[3]VMLAL.S16 q12, d10, d4[3]# vacc2x4567 += vb4567 * va2[3]VMLAL.S16 q13, d11, d4[3]# vacc3x0123 += vb0123 * va3[3]VMLAL.S16 q14, d10, d6[3]# vacc3x4567 += vb4567 * va3[3]VMLAL.S16 q15, d11, d6[3]### Channel 4 ###BLS 3f# Load b0-b7 (channel 4)# - d11 = b0-b7VLD1.8 {d9}, [ip:64]!# q5 = b0:7 - vb_zero_point# - d10 = vb0123 (channel 4)# - d11 = vb4567 (channel 4)VSUBL.U8 q4, d9, d15# vacc0x0123 += vb0123 * va0[4]VMLAL.S16 q8, d8, d1[0]# vacc0x4567 += vb4567 * va0[4]VMLAL.S16 q9, d9, d1[0]# vacc1x0123 += vb0123 * va1[4]VMLAL.S16 q10, d8, d3[0]# vacc1x4567 += vb4567 * va1[4]VMLAL.S16 q11, d9, d3[0]# vacc2x0123 += vb0123 * va2[4]VMLAL.S16 q12, d8, d5[0]# vacc2x4567 += vb4567 * va2[4]VMLAL.S16 q13, d9, d5[0]# vacc3x0123 += vb0123 * va3[4]VMLAL.S16 q14, d8, d7[0]# vacc3x4567 += vb4567 * va3[4]VMLAL.S16 q15, d9, d7[0]### Channel 5 ###CMP r10, -16BLO 3f# Load b0-b7 (channel 5)# - d13 = b0-b7VLD1.8 {d11}, [ip:64]!# q5 = b0:7 - vb_zero_point# - d10 = vb0123 (channel 5)# - d11 = vb4567 (channel 5)VSUBL.U8 q5, d11, d15# vacc0x0123 += vb0123 * va0[5]VMLAL.S16 q8, d10, d1[1]# vacc0x4567 += vb4567 * va0[5]VMLAL.S16 q9, d11, d1[1]# vacc1x0123 += vb0123 * va1[5]VMLAL.S16 q10, d10, d3[1]# vacc1x4567 += vb4567 * va1[5]VMLAL.S16 q11, d11, d3[1]# vacc2x0123 += vb0123 * va2[5]VMLAL.S16 q12, d10, d5[1]# vacc2x4567 += vb4567 * va2[5]VMLAL.S16 q13, d11, d5[1]# vacc3x0123 += vb0123 * va3[5]VMLAL.S16 q14, d10, d7[1]# vacc3x4567 += vb4567 * va3[5]VMLAL.S16 q15, d11, d7[1]### Channel 6 ###BLS 3f# Load b0-b7 (channel 6)# - d9 = b0-b7VLD1.8 {d9}, [ip:64]!# q4 = b0:7 - vb_zero_point# - d8 = vb0123 (channel 6)# - d9 = vb4567 (channel 6)VSUBL.U8 q4, d9, d15# vacc0x0123 += vb0123 * va0[6]VMLAL.S16 q8, d8, d1[2]# vacc0x4567 += vb4567 * va0[6]VMLAL.S16 q9, d9, d1[2]# vacc1x0123 += vb0123 * va1[6]VMLAL.S16 q10, d8, d3[2]# vacc1x4567 += vb4567 * va1[6]VMLAL.S16 q11, d9, d3[2]# vacc2x0123 += vb0123 * va2[6]VMLAL.S16 q12, d8, d5[2]# vacc2x4567 += vb4567 * va2[6]VMLAL.S16 q13, d9, d5[2]# vacc3x0123 += vb0123 * va3[6]VMLAL.S16 q14, d8, d7[2]# vacc3x4567 += vb4567 * va3[6]VMLAL.S16 q15, d9, d7[2].p2align 4 3:SUBS r3, r3, 1BNE 0b# Load c, c_stride:# - r2 = c# - r3 = c_strideLDRD r2, r3, [sp, 104]# r3 = c_stride*4;MOV r3, r3, LSL 2ADD r4, r2, r3CMP r0, 2?#if r0<2 r4=r2MOVLO r4, r2?ADD r5, r4, r3#if r0==2 r5=r4MOVLS r5, r4CMP r0, 4ADD r3, r5, r3#if r0!=4 r3=r5MOVNE r3, r5CMP r1, 8BNE 5fVST1.I32 {d16-d19}, [r2]VST1.I32 {d20-d23}, [r4]VST1.I32 {d24-d27}, [r5]VST1.I32 {d28-d31}, [r3]VPOP {d8-d15}POP {r4, r5, r6, r7, r8, r9, r10, r11}BX lr.p2align 3 5:CMP r1, 4BLO 6fVST1.32 {d16-d17}, [r2:128]!VST1.32 {d20-d21}, [r4:128]!VST1.32 {d24-d25}, [r5:128]!VST1.32 {d28-d29}, [r3:128]!SUB r1, 4VMOV.I32 q8, q9VMOV.I32 q10, q11VMOV.I32 q12, q13VMOV.I32 q14, q156:CMP r1, 2BLO 7fVST1.32 {d16}, [r2:64]!VST1.32 {d20}, [r4:64]!VST1.32 {d24}, [r5:64]!VST1.32 {d28}, [r3:64]!SUB r1, 2VEXT.32 q8, q8, q8, 2VEXT.32 q10, q10, q10, 2VEXT.32 q12, q12, q12, 2VEXT.32 q14, q14, q14, 27:TEQ r1, 0BEQ 8fVST1.32 {d16}, [r2]VST1.32 {d20}, [r4]VST1.32 {d24}, [r5]VST1.32 {d28}, [r3]8:VPOP {d8-d15}?POP {r4, r5, r6, r7, r8, r9, r10, r11}BX lr #bx?lr?的作用等同于 mov pc,lr?即跳轉到lr中存放的地址處 END_FUNCTION q8conv_ukernel_4x8__aarch32_neon#ifdef __ELF__ .section ".note.GNU-stack","",%progbits #endif?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的arm汇编解析—qnnpack卷积实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于DRAM、SRAM、cache、cp
- 下一篇: NEON指令集释义