ZHCU947E June 2015 – January 2023
$LABEL_DIFF(x,y) 运算符可应用于 32 位数据定义指令(例如,.word)的参数。该运算符仅计算在同一段中定义的两个标签之间的差值。在为 Switch 语句生成与位置无关的代码时,Linux ABI 中的编译器(--linux 编译器选项)有时会使用此运算符。
例如,在生成带有偏移 Switch Case 标签的 Switch 表 中,会生成 Switch 表,其中包含 Switch Case 标签的 PC 相对偏移量:
.asg A15, FP
.asg B14, DP
.asg B15, SP
.sect ".text"
.clink
.global myfunc
;******************************************************************************
;* 函数名称:myfunc *
;******************************************************************************
myfunc:
;** --------------------------------------------------------------------------*
B .S1 $C$L10
|| SUB .L2X A4,10,B5
|| STW .D2T2 B3,*SP--(16)
CMPGTU .L2 B5,7,B0
|| STW .D2T1 A4,*+SP(12)
|| MV .S2X A4,B4
[ B0] BNOP .S1 $C$L9,3
; BRANCH OCCURS {$C$L10} ; |6|
;** --------------------------------------------------------------------------*
$C$L1:
<case 0 code>
...
;** --------------------------------------------------------------------------*
$C$L2:
<case 1 code>
...
;** --------------------------------------------------------------------------*
$C$L3:
<case 2 code>
...
;** --------------------------------------------------------------------------*
$C$L4:
<case 3 code>
...
;** --------------------------------------------------------------------------*
$C$L5:
<case 4 code>
...
;** --------------------------------------------------------------------------*
$C$L6:
<case 5 code>
...
;** --------------------------------------------------------------------------*
$C$L7:
<case 6 code>
...
;** --------------------------------------------------------------------------*
$C$L8:
<case 7 code>
...
;** --------------------------------------------------------------------------*
$C$L9:
<default case code>
...
;** --------------------------------------------------------------------------*
$C$L10:
NOP 2
; BRANCHCC OCCURS {$C$L9} {-9} ;
;** --------------------------------------------------------------------------*
SUB .L2 B4,10,B5 ; Norm switch value -> switch table index
|| ADDKPC .S2 $C$SW1,B4,0 ; Load address of switch table to B4
LDW .D2T2 *+B4[B5],B5 ; Load PC-relative offset from switch table
NOP 4
ADD .L2 B5,B4,B4 ; Combine to get case label into B5
BNOP .S2 B4,5 ; Branch to case label
; BRANCH OCCURS {B4} ;
; Switch table definition
.align 32
.clink
$C$SW1: .nocmp
.word $LABEL_DIFF($C$L1,$C$SW1) ; 10
.word $LABEL_DIFF($C$L2,$C$SW1) ; 11
.word $LABEL_DIFF($C$L3,$C$SW1) ; 12
.word $LABEL_DIFF($C$L4,$C$SW1) ; 13
.word $LABEL_DIFF($C$L5,$C$SW1) ; 14
.word $LABEL_DIFF($C$L6,$C$SW1) ; 15
.word $LABEL_DIFF($C$L7,$C$SW1) ; 16
.word $LABEL_DIFF($C$L8,$C$SW1) ; 17
.align 32
.sect ".text"
...
生成带有偏移 Switch Case 标签的 Switch 表 将数据混合到代码段。在汇编时,标签差值必须解析为常数值,因此对包含 $LABEL_DIFF() 运算符的代码段禁用压缩。