今日的行程:
讀書室:17:00 - 18:00
// 常用的 suffix
eq: 相等 (Z == 1)
ne: 不相等 (Z == 0)
cs/hs: 無號數溢位 (C == 1)
cc/lo: 沒有無號數溢位 (C == 0)
mi: 負數 (N == 1)
pl: 非負數 (N == 0)
vs: 溢位 (V == 1)
vc: 未溢位 (V == 0)
// CMP: 是用 SUBS 來實作的,會影響到 nzcv
cmp x1, x2 // subs xzr, x1, x2 ==> x1 + not(x2) + 1
b.cs label // if C bit is set, then branch to label
// CMN: 是用 ADDS 來實作的,用來比較一個數與另一個數的相反數
mov x1, #2
mov x2, #-2
1:
cmn x1, x2 // adds xzr, x1, x2 ==> x1 + x2
b.eq 1b // Z bit set, so branch to "1"
// CSEL, CSET, CSINC
CSEL <Xd>, <Xn>, <Xm>, <cond> // if (cond) ? (Xd = Xn) : (Xd = Xm)
ex.
unsigned long csel_test (unsigned long a, unsigned long b)
{
if (a >= b)
return b + 2;
else
return b - 1;
}
可以寫成
cmp x0, x1 // x0 == a, x1 == b
add x2, x1, #2
sub X3, x1, #1
csel x0, x2, x3, ge
CSET <Xd>, <cond> // if (cond) ? (Xd = 1) : (Xd = 0)
CSINC <Xd>, <Xn>, <Xm>, <cond> // if (cond) ? (Xd = Xn): (Xd = Xm + 1)
// B, B.cond, BL, BR, BLR
B <label> // 限制: PC +- 128 MB 範圍內
B.cond <label> // 限制: PC +- 1 MB 範圍內
BL <label> // branch and link: 會做 "LR(X30) = PC + 4"
BR <Xn> // branch 到 register 儲存的 address
BRL <Xn> // branch 到 register 儲存的 address, LR = PC + 4
// RET, ERET
RET // 跳到 LR register 儲存的位址
ERET // 從當前的 Exception Level 返回,用在 EL 的切換
// CBZ, CBNZ, TBZ, TBNZ
CBZ <Xt>, <label> // if (Xt == 0) then b label; (PC +- 1MB)
CBNZ <Xt>, <label> // if (Xt != 0) then b label; (PC +- 1MB)
TBZ R<t>, #imm, label // if (R[imm bit] == 0) then branch label; (PC +- 32KB)
TBNZ R<t>, #imm, label // if (R[imm bit] != 0) then branch label; (PC +- 32KB)
.global csel_test
cmp x0, 0
add x2, x1, 1
sub X3, x1, 2
csel x0, x3, x2, eq
ret
.global bl_test:
mov x0, 1
mov x1, 3
bl csel_test
ret
若有 function (A) 呼叫 bl_test,那麼會在 bl_test return 的時候,進入無限循環。
因為 bl 會修改 LR register 導致,bl_test return 回 A 的時候,跳到不預期的位址 (bl_test 的位址)
解決方法就是,進到一個 function 之後,會先把這個 function 的 LR 存到 stack 上
(function prologue 通常都會做這件事情)
JAL rd, address
: e.g. jal ra, 0x1234
(address 限制是 PC +- 1MB)JALR rd, offset(rs1)
: e.g. jalr ra, 0x8(a1)
(offset 限制是 -2048~2047)j label
: jal x0, label
jal label
: jal ra, label
jr rs
: jalr x0, 0(rs)
jalr rs
: jalr ra, 0(rs)
ret
: jalr x0, 0(ra)
call func
: auipc ra, offset[31:12] + offset[11]; jalr ra, offset[11:0](ra)
tail func
: auipc x6, offset[31:12] + offset[11]; jalr ra, offset[11:0](x6)