ART世界探險(3) - ARM 64位CPU的架構(gòu)快餐教程
前面我們說過虑瀑,Dalvik如果沒有JIT的話般渡,可以做到架構(gòu)無關孩饼,讓Dalvik指令都解釋執(zhí)行。但是ART是AOT微服,要編譯成針對芯片具體的機器指令。
所以缨历,研究Dalvik的時候可以不用太關心目標指令以蕴,而我們研究ART必須對目前最流行的微處理器的架構(gòu)有個基本的了解。
在上一講我們對于ART從java byte code到ARM64 v8指令的整個流程有了一個大概的了解之后戈二,我們就目前最流行的ARM64位芯片的知識進行一些探索舒裤。
我們的目的不是寫一個操作系統(tǒng),所以我們盡可能挑實用的講觉吭。
ARM架構(gòu)簡史
我們用NDK編譯一個jni庫之后會發(fā)現(xiàn)腾供,生成了armeabi,armeabi-v7a,arm64-v8a三個目錄。這三個目錄鲜滩,代表了ARM目前最流行的三種架構(gòu)的指令集伴鳖。
ARM芯片從1985年誕生以來,經(jīng)歷了主要6次大的架構(gòu)調(diào)整徙硅。
- ARMv4及之前:只使用32位的ARM指令集榜聂。
- ARMv4T,在32位ARM指令集的基礎上嗓蘑,增加了16位的Thumb指令集须肆。這是第一個被廣泛使用的架構(gòu)匿乃,代表芯片ARM7TDMI和ARM9TDMI。
- ARMv5TE豌汇,增加了DSP操作幢炸,飽和算法,ARM和Thumb切換拒贱。代表芯片:ARM926EJ-S宛徊。
- ARM v6,對內(nèi)存訪問的架構(gòu)有所調(diào)整逻澳,支持SIMD指令闸天。代表芯片:ARM1136JF-S。這一代Thumb2成為可選項斜做。
- ARM v7-A苞氮,將v6時可選的Thumb2指令集變成必選項,支持NEON指令瓤逼。代表芯片Cortex-A8, A9, A15, A17葱淳。
- ARMv8-A,支持兩種架構(gòu)抛姑,64位的AArch64和AArch32赞厕。其中,AArch32跟原有的v7-A架構(gòu)是基本一樣的定硝。代表芯片為A57, A53, A73, A72.
我們通常見到的armeabi皿桑,實際上對應的是ARM v4T~v6的指令。為了節(jié)省空間蔬啡,我們基本上都編成16位的Thumb指令诲侮。armeabi-v7a,對應v7-A架構(gòu)箱蟆。arm64-v8a對應ARM v8-A的AArch64指令沟绪。
我們習慣上,把ARM v4之前就有的基礎的32位ARM指令集稱為A32指令集空猜,16位的Thumb指令稱為T16指令集绽慈,AArch64指令集稱為A64指令集。
其中辈毯,Thumb/Thumb2和A32指令集是兼容的坝疼。Thumb和Thumb2比較節(jié)省空間,但是有些A32指令的功能是沒有的谆沃。
這時候钝凶,只要從Thumb狀態(tài)切換到ARM狀態(tài)下就好了,執(zhí)行完A32才有的指令唁影,回去再執(zhí)行T16指令就好了耕陷。
但是A64指令是不兼容Thumb的掂名,在這種狀態(tài)下,只有A64指令這一種指令可以用哟沫。
Android所用的ARM芯片簡史
在Android剛出來的時候铆隘,HTC G1所用的高通MSM7201芯片,基于ARM11,用的是ARM v6指令集南用。
后來德州儀器的OMAP 3430第一次將Cortex-A系列的第一個架構(gòu)Cortex-A8,引入現(xiàn)實世界中掏湾。開啟了ARM v7a的時代裹虫。這個時代的代表機型就是Moto Droid/MileStone,開啟了第一批百萬級的Android手機融击。
隨后筑公,從NVidia的Tegra 2開始,我們進入了A9和雙核的時代尊浪。Tegra 3使用Cortex-A15匣屡,在32位上達到一個高峰。
同時拇涤,以MediaTek為代表的中低端廠商開始將低端的Cortex-A7發(fā)揮到極致捣作,MT6577是兩個A7,MT6589為4個A7鹅士,MT6592是8個A7.
進入64位時代的代表芯片券躁,就是Qualcomm的SnapDragon 810芯片,4個Cortex-A57的發(fā)熱問題困擾了無數(shù)廠商去年整整一年掉盅。
MediaTek繼續(xù)發(fā)揮低端的威力也拜,升級成64位的Cortex-A53。MT6735芯片4個A53趾痘,MT6753芯片8個A53慢哈。幸好最近的Helix X25/20開始用A72+A53了,我們總算是在MTK芯片上見到一次大核的身影永票。
從芯片的廣泛性上考慮卵贱,我們這個講座的目標芯片就放在Cortex-A53上。
Cortex-A57和Cortex-A53芯片對比
我們簡單列一下A57與A53的對比侣集,大家有個直觀印象就好艰赞。
Cortex-A53 | Cortex-A57 | |
---|---|---|
典型時鐘 | 2GHz, 28nm工藝 | 1.5~2.5GHz, 20nm工藝 |
執(zhí)行順序 | 順序 | 亂序、投機問題肚吏、超標量 |
核心數(shù) | 1~4 | 1~4 |
峰值整數(shù)能力 | 2.3MIPS/MHz | 4.1~4.76MIPS/MHz |
浮點單元 | 有 | 有 |
半精度 | 有 | 有 |
硬件除法 | 有 | 有 |
融合乘法累加 | 有 | 有 |
流水線 | 8級 | 15級+ |
返回棧條目 | 4 | 8 |
通用中斷控制 | 外部 | 外部 |
AMBA接口 | 64位 AMBA 4/5 | 128位 AMBA 4/5 |
L1指令緩存 | 8K ~ 64KB | 48KB |
L1數(shù)據(jù)緩存 | 8K ~ 64KB | 32KB |
L2緩存 | 可選 | 集成 |
L2緩存 | 128K~2M | 512K~2M |
主TLB | 512 | 1024 |
uTLB | 10 | 48指令方妖,32數(shù)據(jù) |
對我們理解后續(xù)知識有影響的主要有兩條:一是Cortex-A53不支持亂序執(zhí)行,這將影響未來的優(yōu)化策略罚攀;另一個是A53的流水線沒有A57深党觅,只有8級雌澄。
ARM v8a架構(gòu)簡介
異常等級
ARM v8a引入了異常等級的概念。一共有從EL0到EL3四種異常等級杯瞻,等級越高镐牺,特權(quán)越高。我們的應用一般都運行于EL0魁莉。操作系統(tǒng)內(nèi)核運行于EL1睬涧,EL2和EL3可以留給安全監(jiān)控軟件和KVM之類的虛擬化軟件使用。
AArch64與AArch32
ARM芯片曾經(jīng)指令集比x86容易學的重要原因是歷史包袱少旗唁,不需要兼容歷史上的指令集∑枧ǎ現(xiàn)在ARM 64位芯片也不得不做起兼容自己以前的重任。ARM的做法是將運行狀態(tài)分成AArch64和AArch32兩種狀態(tài)检疫。AArch64就是我們后面重點學習的64位的指令集的運行態(tài)讶请,而AArch32是兼容Arm-v7a的狀態(tài),所有Arm-v7a以及更早的軟件都可以在這個狀態(tài)上正常運行屎媳。
對于我們應用來講夺溢,EL0是沒有權(quán)限進行AArch64和AArch32狀態(tài)切換的,所以我們只能一條道走到黑地用一處狀態(tài)烛谊。這也是我們的A64指令無法切換到A32,T16指令的原因风响。
寄存器
通用寄存器
在AArch64運行態(tài)下,在所有的異常級下丹禀,都可以訪問31個64位通用寄存器钞诡,它們的命名是X0~X30。
這31個64位寄存器也可以通過W0~W30來訪問低32位湃崩。
讀Wn時荧降,不會影響到高32位的值。寫Wn時攒读,會將高32位全部清0.
我們來看一段之前看過的例子:
str x0, [sp, #-32]!
str lr, [sp, #24]
str w1, [sp, #40]
str w2, [sp, #44]
str x0是使用第0個64位寄存器朵诫。
str w1是只使用第1個64位寄存器的低32位
特殊寄存器
- 零寄存器:XZR/WZR,寫該寄存器會被忽略薄扁,讀該寄存器會得到全0值剪返。
- PC:程序指針寄存器,64位邓梅。注意脱盲,還是叫PC,不叫XPC叭沼А钱反!在ARMv7之前,PC可以做為R15,當成通用寄存器來使用面哥,在ARMv8上哎壳,不允許直接訪問。
- SP:棧寄存器尚卫,64位归榕。對應的32位為WSP,但是64位的這個就叫SP不叫XSP爸ㄉ妗刹泄!SP是每個EL對應一個(反正咱們只有EL0這個)。
- ELR(Exception Link Register):異常鏈接寄存器怎爵,EL1~EL3各有一個特石。存儲了從中斷返回的地址,這個咱們應用沒權(quán)限用疙咸,本系列中學不到
- SPSR:(Saved Processor State):EL1~EL3各有一個。保存了發(fā)生異常時的狀態(tài)信息风科,這個咱們也用不著撒轮。
狀態(tài)域
在AArch64運行態(tài)下,沒有對應CPSR(Current Program Status Register)的寄存器贼穆。每種狀態(tài)現(xiàn)在需要分別訪問题山。
這些狀態(tài)有:
- N – 負數(shù)
- Z – 0
- C – 進位
- V – 溢出
- D – 調(diào)試位
- A – Serror
- I – IRQ
- F – FIQ
- SS – 軟件單步跟蹤
- IL – 無效運行態(tài)
- EL – Exception Level
- nRW – 執(zhí)行態(tài),0為64位故痊,1為32位
- SP – 棧指針選擇顶瞳,0為EL0,n為ELn愕秫。
N, Z, C, V四種狀態(tài)是可以在EL0級別被訪問的慨菱,其它的都需要EL1以上級別。所以戴甩,咱們寫應用只需要知道前4個就行了符喝,多省心:)
系統(tǒng)寄存器
系統(tǒng)配置是通過MRS和MSR指令去訪問系統(tǒng)寄存器來實現(xiàn)的。
NEON寄存器
在通用寄存器之外甜孤,ARMv8還提供了32個128位NEON浮點寄存器协饲,V0~V31。它們也可以被當作半精度寄存器H<n>缴川,單精度寄存器S<n>和雙精度寄存器D<n>茉稠。
A64 ATPCS支持最多傳8個參數(shù),通過X0X7把夸。而A32和T32只支持4個而线。說人話就是,如果一個函數(shù)調(diào)用要傳8個參數(shù),就可以放到X0X7這8個64位寄存器里吞获。
ARM v8a小結(jié)
ARM v8a支持AArch64和AArch32兩種運行態(tài)况凉,在應用運行的EL0權(quán)限下不能切換,只能選一種各拷。AArch64狀態(tài)下只能運行A64這一種指令集刁绒,而AArch32運行態(tài)下,可以執(zhí)行A32和Thumb2兩種指令集烤黍,這兩種之間可以自由切換知市。
在AArch64運行態(tài)下,我們有31個64位通用寄存器(X0~X30),32個128位NEON浮點寄存器速蕊,一個零寄存器用于寫無用數(shù)據(jù)嫂丙,一個PC指令指針,一個SP棧指針规哲,狀態(tài)位只需要記4個:N負Z零C進行V溢出跟啤。
既然是快餐文,就講這么多唉锌。大家能對上面小結(jié)的了解清楚隅肥,我們就可以正式向指令集前進了?