ZHCAEQ3 November 2024 F29H850TU , F29H859TU-Q1
在實時應用中,飽和類型代碼十分常見。以下展示了在 C 語言中通過兩種不同方式實現(xiàn)飽和的總結。
下面的代碼塊顯示了基于 if..else 實現(xiàn)飽和的方法。C29 需要 11 個周期且不依賴輸入,性能優(yōu)于 Cortex-M7(需要 14-27 個周期,且依賴輸入)。在 C29 上,if () 是通過條件分支指令 (BC) 實現(xiàn)的,而對于剩余的兩條路徑(elseif 和 else),則依次使用了比較指令 (CMPF) 和條件指令 (XCP),從而避免了分支。
volatile float in;
volatile float out;
const float max =1.0f;
const float min = -1.0f;
if(in > max)
out = max;
else if(in < min)
out = min;
else
out = in;
C29 Implementation
LD.32 M1,@in
||ONEF M0
CMPF TDM0,M.GT,M1,M0
ONEF M1
|| BC @($LBB0_2),TDM0.NZ
LD.32 M1,@in
|| NEGONEF M2
CMPF TDM0,M.LT,M1,M2
XCP #0x1,TDM0.Z
|| LD.32 M1,@in
SELECT TDM0,M1,M2,M1
$LBB0_2:
ST.32 @out,M1
M7 Implementation
MOVW R0,#in2
MOVT R0,#in2
MOVS R1,#+1
MOVT R1,#+16256
VLDR S0,[R0, #0]
VMOV S1,R1
VCMP.F32 S0,S1
FMSTAT
BLT.N saturation_0
MOV R2,#+1065353216
STR R2,[R0, #+4]
B saturation_2
saturation_0:
VMOV.F32 S0,#-1.0
VLDR S1,[R0, #0]
VCMP.F32 S1,S0
FMSTAT
BPL.N saturation1_1
VSTR S0,[R0, #+4]
B saturation_2
saturation_1:
LDR R1,[R0, #+0]
STR R1,[R0, #+4]
saturation_2:
下面的代碼塊顯示了基于三元運算符 '?' 實現(xiàn)飽和的方法。C29 通過 MINMAXF 指令實現(xiàn),且無需分支,需要 3 個周期且不依賴輸入,性能優(yōu)于 Cortex-M7(需要 18-22 個周期,且依賴輸入)。
volatile float in;
volatile float out;
const float max =1.0f;
const float min = -1.0f;
float temp = in;
temp = (temp > max)? max: ((temp < min)? min: temp);
out = temp;
C29 Implementation
ONEF M0 || LD.32 M1,@in || NEGONEF M2 MINMAXF M1,M0,M2 ST.32 @out,M1
M7 Implementation
MOVW R0,#in2
MOVS R1,#+1
MOVT R0,#in2
MOVT R1,#+16256
VMOV S2,R1
VLDR S0,[R0, #0]
VCMP.F32 S0,S2
VMOV.F32 S1,S0
FMSTAT
IT GE
VMOVGE.F32 S1,#1.0
BGE.N saturation_0
VMOV.F32 S2,#-1.0
VCMP.F32 S0,S2
FMSTAT
IT MI
VMOVMI.F32 S1,S2
saturation_0:
VSTR S1,[R0, #+8]
C29 編譯器經(jīng)過優(yōu)化,能夠在 if..else 或三元運算符實現(xiàn)方式之間,生成相同性能的代碼。
|| 表示與上述指令并行執(zhí)行的指令。