?? arm 指令格式和時(shí)序.htm
字號(hào):
</PRE>
<P>在 ARM6
和以后的處理器上有六個(gè)狀態(tài)寄存器。一個(gè)是當(dāng)前處理器狀態(tài)寄存器(CPSR),持有關(guān)于當(dāng)前處理器狀態(tài)的信息。其它五個(gè)是保存的程序狀態(tài)寄存器(SPSR):
每個(gè)特權(quán)模式都有一個(gè),持有完成在這個(gè)模式下的例外處理時(shí)處理器必須返回的關(guān)于狀態(tài)的信息。
<P>分別使用 MSR 和 MRS 指令來設(shè)置和讀取這些寄存器。
<P>
<HR>
<A name=Pipeline>
<H2>流水線</H2></A>
<P>不同于微編碼的處理器,ARM (保持它的 RISC 性)是完全硬布線的。
<P>為了加速 ARM 2 和 3 的執(zhí)行使用 3
階段流水線。第一階段持有從內(nèi)存中取回的指令。第二階段開始解碼,而第三階段實(shí)際執(zhí)行它。故此,程序計(jì)數(shù)器總是超出當(dāng)前執(zhí)行的指令兩個(gè)指令。(在為分支指令計(jì)算偏移量時(shí)必須計(jì)算在內(nèi))。
<P>因?yàn)橛羞@個(gè)流水線,在分支時(shí)丟失 2 個(gè)指令周期(因?yàn)橐匦绿頋M流水線)。所以最好利用條件執(zhí)行指令來避免浪費(fèi)周期。例如: <PRE> ...
CMP R0,#0
BEQ over
MOV R1,#1
MOV R2,#2
over
...
</PRE>可以寫為更有效的: <PRE> ...
CMP R0,#0
MOVNE R1,#1
MOVNE R2,#2
...
</PRE>
<P>
<HR>
<A name=Timings>
<H2>時(shí)序</H2></A>
<P>ARM 指令在時(shí)序上是 S、N、I 和 C 周期的混合。
<P>S 周期是 ARM 在其中訪問一個(gè)順序的內(nèi)存位置的周期。
<P>N 周期是 ARM 在其中訪問一個(gè)非順序的內(nèi)存位置的周期。
<P>I 周期是 ARM 在其中不嘗試訪問一個(gè)內(nèi)存位置或傳送一個(gè)字到/從一個(gè)協(xié)處理器的周期。
<P>C 周期是 ARM 在其中與一個(gè)協(xié)處理器之間在數(shù)據(jù)總線(對(duì)于無緩存的 ARM)或協(xié)處理器總線(對(duì)于有緩存的 ARM)上寫傳送一個(gè)字的周期。
<P>各種類型的周期都必須至少與 ARM 的時(shí)鐘周期一樣長。內(nèi)存系統(tǒng)可以伸展它們: 對(duì)于典型的 DRAM 系統(tǒng),結(jié)果是:
<UL>
<LI>N 周期變成最小長度的兩倍(主要因?yàn)?DRAM 在內(nèi)存訪問是非順序時(shí)要求更長的訪問協(xié)議)。
<LI>S 周期通常是最小長度,但偶爾也會(huì)被伸展成 N 周期的長度(在你從一個(gè)內(nèi)存“行”的最后一個(gè)字移動(dòng)到下一行的第一個(gè)字的時(shí)候<A
href="http://www.linuxforum.net/books/mhss/arm/ARMinstrs.html#Footnote1">[1]</A>)。
<LI>I 周期和 C 周期總是最小長度。 </LI></UL>
<P>對(duì)于典型的 SRAM 系統(tǒng),所有類型的周期典型的都是最小長度。
<P>在 Acorn Archimedes A440/1 使用的 8MHz ARM2 中,一個(gè) S (順序) 周期是 125ns 而一個(gè) N (非順序) 周期是
250ns。應(yīng)當(dāng)注意到這些時(shí)序不是 ARM 的屬性,而是內(nèi)存系統(tǒng)的屬性。例如,一個(gè) 8MHz ARM2 可以與一個(gè)給出 125ns 的 N 周期的 RAM
系統(tǒng)相連接。處理器的速率是 8MHz 只是簡單的意味著如果你使任何類型的周期在長度上小于 125ns 則它不保證能夠工作。
<P>有緩存的處理器: 所有給出的信息依據(jù) ARM 所見到的時(shí)鐘周期。它們不按固定的速率發(fā)生: 緩存控制邏輯在 cache 不中的時(shí)候改變提供給 ARM
的時(shí)鐘周期來源。
<P>典型的,有緩存的 ARM 有兩個(gè)時(shí)鐘輸入: “快速時(shí)鐘” FCLK 和“內(nèi)存時(shí)鐘”MCLK。 在 cache 命中的時(shí)候,ARM 的時(shí)鐘使用 FCLK
的速度并且所有類型的周期都是最小的長度: 從這點(diǎn)上看 cache 在效果上是某種 SRAM。在 cache 不中發(fā)生的時(shí)候,ARM 的時(shí)鐘同步為
MCLK,接著以 MCLK 速度進(jìn)行 cache 行添充(依賴于在處理器中涉及的 cache 行的長度使用 N+3S 或 N+7S 個(gè)周期),接著 ARM
的時(shí)鐘被同步回到 FCLK。
<P>在發(fā)生內(nèi)存訪問的時(shí)候,ARM 將守時(shí)操作(be clocked): 但是,可以使用一個(gè)叫 NWAIT 的輸入來導(dǎo)致涉及到的 ARM
周期不做任何事情,直到正確的字從內(nèi)存中到來,并在仍有余下的字到來的時(shí)候通常不做任何事情(為了避免在 cache 仍忙于重新填充 cache
行的時(shí)候得到進(jìn)一步的內(nèi)存請(qǐng)求)。有緩存的 ARM 可以被配置成使用 FCLK 和 MCLK 來相互同步(所以 FCLK 是準(zhǔn)確的 MCLK 倍數(shù),并且每個(gè)
MCLK 時(shí)鐘周期與一個(gè) FCLK 周期同時(shí)開始)或異步的(這種情況下 FCLK 和 MCLK 周期相互之間可以有任何關(guān)系)使情況更加復(fù)雜。
<P>情況非常復(fù)雜。這些行為的近似的描述是,在一個(gè) cache 行不中發(fā)生的時(shí)候,它所涉及的周期耗用以 MCLK 周期為單位的 cache
行重填充時(shí)間(例如,N+3S 或 N+7S),對(duì)于 N 周期和 S 周期可能按 DRAM
所描述的那樣被伸展,加上一些更多的周期用于重新同步階段。要得到詳情,你需要得到所涉及的處理器的 datasheet。
<P><A name=Footnote1>腳注</A><A name=Footnote1> 1:</A> 內(nèi)存控制器意圖使用這個(gè)簡單的策略: 如果請(qǐng)求一個(gè) N
周期,則把訪問作為不在同一行來對(duì)待;如果請(qǐng)求一個(gè) S 周期,除非它效果上是這行的最后一個(gè)字(可以被快速檢測(cè)出來),否則把訪問作為同行來對(duì)待。結(jié)果是一些 S
周期將持續(xù)與 N 周期相同的時(shí)間;如果我記得正確,在 Archimedes 上 S 周期所訪問的內(nèi)存被按 16 字節(jié)來分開。對(duì)于 Archimedes
代碼的實(shí)際后果是: (a) 大約 4 個(gè) S 周期中的 1 個(gè)變成一個(gè) N 周期,為此,所有地址都是字地址并按 4 來分開;(b)
有時(shí)值得仔細(xì)關(guān)照對(duì)齊代碼來避免這種效果并得到一些額外的性能。)
<P>
<HR>
<A name=Instructions>
<H2>指令</H2></A>
<P>每個(gè) ARM 指令都是 32 位寬,下面給出詳細(xì)的解釋。對(duì)于每個(gè)指令類,我們給出指令位圖(bitmap),和典型匯編器使用的語法的例子。
<P>一定要注意助記符的語法不是固定的;它是匯編器的特性,而不是 ARM 機(jī)器編碼的。
<P><A name=Condition>
<H3>條件代碼</H3></A>
<P>每個(gè)指令的頂端部分是一個(gè)條件代碼,所以可以有條件的運(yùn)行每個(gè)單一的 ARM 指令。
<P> <PRE> 條件
指令位圖 編號(hào) 條件代碼 所須標(biāo)志:
0000xxxx xxxxxxxx xxxxxxxx xxxxxxxx 0 EQ(等于,Equal) Z
0001xxxx xxxxxxxx xxxxxxxx xxxxxxxx 1 NE(不等于,Not Equal) ~Z
0010xxxx xxxxxxxx xxxxxxxx xxxxxxxx 2 CS(進(jìn)位設(shè)置,Carry Set) C
0011xxxx xxxxxxxx xxxxxxxx xxxxxxxx 3 CC(進(jìn)位清除,Carry Clear) ~C
0100xxxx xxxxxxxx xxxxxxxx xxxxxxxx 4 MI(負(fù)號(hào),MInus) N
0101xxxx xxxxxxxx xxxxxxxx xxxxxxxx 5 PL(正號(hào),PLus) ~N
0110xxxx xxxxxxxx xxxxxxxx xxxxxxxx 6 VS(溢出設(shè)置,oVerflow Set) V
0111xxxx xxxxxxxx xxxxxxxx xxxxxxxx 7 VC(溢出清除,oVerflow Clear) ~V
1000xxxx xxxxxxxx xxxxxxxx xxxxxxxx 8 HI(高于,HIgher) C and ~Z
1001xxxx xxxxxxxx xxxxxxxx xxxxxxxx 9 LS(低于或同于,Lower or Same) ~C and Z
1010xxxx xxxxxxxx xxxxxxxx xxxxxxxx A GE(大于等于,Greater or equal)N = V
1011xxxx xxxxxxxx xxxxxxxx xxxxxxxx B LT(小于,Less Than) N = ~V
1100xxxx xxxxxxxx xxxxxxxx xxxxxxxx C GT(大于,Greater Than) (N = V) and ~Z
1101xxxx xxxxxxxx xxxxxxxx xxxxxxxx D LE(小于等于,Less or equal) (N = ~V) or Z
1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx E AL(總是,Always) 永真
1111xxxx xxxxxxxx xxxxxxxx xxxxxxxx F NV(從不,Never) 永假
</PRE>
<P>在多數(shù)匯編器中,插入條件代碼到緊隨在助記符根代碼(stub)的后面;省略條件代碼缺省為使用 AL。
<P>在一些匯編器中把 HS (高于或同于) 和 LO (低于) 分別用做 CS 和 CC 的同義詞。
<P>條件 GT、GE、LT、LE 被成為有符號(hào)比較,而 HS、HI、LS、LO 被稱為無符號(hào)比較。
<P>把一個(gè)條件代碼與 1 進(jìn)行異或得到相反的條件的代碼。
<P>NB: ARM 廢棄使用 NV 條件代碼 - 假定你使用 MOV R0,R0 作為一個(gè)空指令而不是以前推薦的 MOVNV R0,R0
。將來的處理器可能重新使用 NV 條件來做其他事情。
<P>所須條件為假的指令執(zhí)行 1S 周期,使一個(gè)指令有條件執(zhí)行不招致時(shí)間處罰。
<P><A name=Data>
<H3>數(shù)據(jù)處理指令</H3></A><PRE>xxxx000a aaaSnnnn ddddcccc ctttmmmm 寄存器形式
xxxx001a aaaSnnnn ddddrrrr bbbbbbbb 立即數(shù)形式
</PRE>
<P>典型的匯編語法: <PRE> MOV Rd, #0
ADDEQS Rd, Rn, Rm, ASL Rc
ANDEQ Rd, Rn, Rm
TEQP Pn, #&80000000
CMP Rn, Rm
</PRE>
<P>在操作 a 下,組合 Rn 的內(nèi)容和 Op2,放置結(jié)果到 Rd 中。
<P>如果使用寄存器形式,則 Op2 被設(shè)置為依據(jù)下面描述的 t 來移位的 Rm 的內(nèi)容。如果使用立即數(shù)形式,則 Op2 = #b, ROR #2r。 <! center BOXED ; c l s lc l l l. ><PRE> t 匯編器 解釋
000 LSL #c 邏輯左移
001 LSL Rc 邏輯左移
010 LSR #c for c != 0 邏輯右移
LSR #32 for c = 0
011 LSR Rc 邏輯右移
100 ASR #c for c != 0 算術(shù)右移
ASR #32 for c = 0
101 ASR Rc 算術(shù)右移
110 ROR #c for c != 0 循環(huán)右移
RRX for c = 0 帶擴(kuò)展的循環(huán)右移一位
111 ROR Rc 循環(huán)右移
</PRE>
<P>在寄存器形式中,用位 8-11 表示 Rc;如果使用 Rc 則位 7 必須清除。(如果你編碼為 1,你將得到一個(gè)乘法、SWP
或未分配的指令而不是一個(gè)數(shù)據(jù)處理指令。)
<P>還有,只使用了 Rc 的底端字節(jié) - 如果 Rc = 256, 則移位將是零。
<P>“MOV[S] Ra,Rb,RLX” 可以通過 ADC[S] Ra,Rb,Rb 來完成,這里的 RLX 意思是帶擴(kuò)展的循環(huán)左移一位。
<P>多數(shù)匯編器允許使用 ASL 作為 LSL 的同義詞。因?yàn)閷?duì)算術(shù)左移是什么有不同的意見,最好使用術(shù)語 LSL。
<P>通過在 MOV、MVN 或邏輯指令中設(shè)置 S 位,(在寄存器或立即數(shù)形式中)把進(jìn)位標(biāo)志設(shè)置為最后移出的那一位。
<P>如果不做移位,則不影響進(jìn)位標(biāo)志。
<P>如果立即數(shù)有可選擇的多個(gè)形式(例如,#1 可以表示為 1 ROR #0、4 ROR #2、16 ROR #4 或 64 ROR
#6),則匯編器希望使用涉及零移位的那個(gè)形式,如果可獲得的話。所以,如果 0 <= const <= 255,則 MOVS Rn,#const
將保持進(jìn)位標(biāo)志不受影響,否則將改變它。
<P><! center BOXED ;c l l l. ><PRE>aaaa 匯編器 意思 P-Code
0000 AND 邏輯與 Rd = Rn AND Op2
0001 EOR 邏輯異或 Rd = Rn EOR Op2
0010 SUB 減法 Rd = Rn - Op2
0011 RSB 反向減法 Rd = Op2 - Rn
0100 ADD 加法 Rd = Rn + Op2
0101 ADC 帶進(jìn)位的加法 Rd = Rn + Op2 + C
0110 SBC 帶借位的減法 Rd = Rn - Op2 - (1-C)
0111 RSC 帶借位的反向減法 Rd = Op2 - Rn - (1-C)
1000 TST 測(cè)試位 Rn AND Op2
1001 TEQ 測(cè)試等同 Rn EOR Op2
1010 CMP 比較 Rn - Op2
1011 CMN 比較取負(fù) Rn + Op2
1100 ORR 邏輯或 Rd = Rn OR Op2
1101 MOV 傳送值 Rd = Op2
1110 BIC 位清除 Rd = Rn AND NOT Op2
1111 MVN 傳送取非 Rd = NOT Op2
</PRE>注意 MVN 和 CMN 不是象表面上的那種關(guān)系;MVN 使用直接的逐位(bitwise)非操作,把 Rn 設(shè)置為 Op2 對(duì) 1
的補(bǔ)碼(反碼)。CMN 把 Rn 與 Op2 對(duì) 2 的補(bǔ)碼進(jìn)行比較。
<P>這些指令可歸入 4 個(gè)子集:
<DL>
<DT>MOV, MVN
<DD>Rn 被忽略,并且應(yīng)當(dāng)是 0000。如果設(shè)置了 S 位,則在結(jié)果上設(shè)置 N 和 Z 標(biāo)志。并且如果使用了移位器,則 C
標(biāo)志被設(shè)置為被移出的最后一位。不影響 V 標(biāo)志。
<DT>
<DT>CMN, CMP, TEQ, TST
<DD>Rd 不被指令所設(shè)置,并且應(yīng)當(dāng)是 0000。必須設(shè)置 S 位(多數(shù)匯編器會(huì)自動(dòng)完成;如果沒有設(shè)置它,則這個(gè)指令將是
MRS、MSR、或一個(gè)未分配的指令。)
<P>算術(shù)操作(CMN, CMP)在結(jié)果上設(shè)置 N 和 Z 標(biāo)志,從 ALU 得到 C 和 V 標(biāo)志。
<P>邏輯操作(TEQ, TST)在結(jié)果上設(shè)置 N 和 Z 標(biāo)志,如果使用了移位器則從它得到 C 標(biāo)志(在這種情況下它變成被移出的最后一位),不影響 V
標(biāo)志。
<P>有一個(gè)特殊情況(對(duì)于 ARMs >= 6,只針對(duì) 26 位模式),dddd 字段是 1111
導(dǎo)致用結(jié)果的相應(yīng)的位設(shè)置標(biāo)志(在用戶模式下),或整個(gè) 26 位 PSR (在特權(quán)模式下)。這由給指令的 P 后綴來指示 - CMNP、
CMPP、TEQP、TSTP。常用 TEQP PC,#(新模式編號(hào)) 來改變模式。在 32 位模式,應(yīng)當(dāng)使用 MSR 來替代(因?yàn)?TEQP
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -