6.2.1 異常中斷處理程序的方法種類(lèi)及其介紹
在 SWI 指令中包括一個(gè) 24 位的立即數,該立即數指示了用戶(hù)請求的特定的 SWI 功能。在
SWI
異常中斷處理程序要讀取該 24 位的立即數,這涉及到 SWI異常模式下對寄存器 LR的讀
取,并且要從存儲器讀取該 SWI 指令。這樣需要使用匯編程序來(lái)實(shí)現。通常 SWI異常中斷處
理程序分為兩級:第 1 級 SWI
異常中斷處理程序為匯編,用于確定 SWI 指令中的 24 位的立
即數;第 2級 SWI 異常中斷處理程序具體實(shí)現 SWI 的各個(gè)功能,它可以是匯編程序,也可以
時(shí) C 程序,下面我們分別介紹這兩級。
● SWI 異常中斷調用
① 在特權模式下調用 SWI
執行 SWI 指令后,系統將會(huì )把 CPSR 寄存器的內容保存到寄存器 SPSR_SVC 中,
將返回地址保存到寄存器 LR_svc 中。這樣如果執行 SWI 指令時(shí),系統已經(jīng)處于
特權模式下,這時(shí)寄存器 SPSR_svc 和寄存器 LR_svc 中的內容就會(huì )被破壞。因
此如果在特權模式下調用 SWI 功能,比如在一個(gè) SWI 異常中斷處理程序中執行
SWI指令,就必須將原始的寄存器SPSR_svc和寄存器LR_svc值保存在數據棧中。
程序6.1說(shuō)明在SWI中斷處理程序中如何保存寄存器SPSR_svc和寄存器LR_svc
值。
程序 6.1 在SWI 中斷處理程序中保存寄存器 SPSR_svc 和寄存器 LR_svc 值
;保存寄存器,包括寄存器 lr_svc
STMFD sp!(r0-r3,r12,lr)
;保存 SPSR_svc
MOV r1,sp
MRS r0,spsr
STMFD sp!,(r0)
;讀取SWI指令
LDR r0,(lr,#4)
;計算其中的 24 位立即數,并將其放入寄存器 R0 中
BIC r0,r0.#0xff000000
;調用C_SWI_Handler 完成相應的 SWI 功能
BL C_SWI_Handler
;恢復SPSR_svc 的值
LDMFD sp!,(r0)
MSB spsr_cf,r0
;恢復其他寄存器,包括寄存器 LR_svc
LDMFD sp!,(r0-r3,r12,pc)^
② 從應用程序中調用 SWI
這里分兩種情況考慮從應用程序中調用特定的 SWI 功能:一種考慮使用匯編指
令調用特定的 SWI 功能;一種考慮從 C 語(yǔ)言程序中調用特定的 SWI 功能。
使用匯編指令調用特定的 SWI 功能比較簡(jiǎn)單,將需要的參數按照 ATPCS 的要求
放在相應的寄存器中,然后在指令 SWI 中指定相應 24 位立即數即可。下面的例
子中,SWI 中斷處理程序需要的參數放在寄存器 R0 中,這里該參數為 100,然
后調用功能號為 0x0 的SWI 功能調用。
MOV R0,#100
SWI 0x0
從 C 語(yǔ)言程序中調用特定的 SWI 功能比較復雜,因為這時(shí)需要將一個(gè) C 程序的
子程序調用映射到一個(gè) SWI 異常中斷處理程序。這些被映射的 C 語(yǔ)言子程序使
用編譯器偽操作__SWI 來(lái)聲明。如果該子程序需要的參數和返回的結果只使用寄
存器 R0~R3,則該 SWI 可以被編譯成 inline 的,不需要使用子程序調用過(guò)程。
否則必須告訴編譯器通過(guò)結構數據類(lèi)型來(lái)返回參數,這時(shí)需要使用編譯器偽操
作_value_in_reg 聲明該C 語(yǔ)言子程序。
下面通過(guò)一個(gè)完整的例子來(lái)說(shuō)明如何從 C 程序中調用特定的 SWI 功能,該例子
是 ARM 公司的 ADS1.2 中所帶的。該例子提供的 4 個(gè)SWI 功能調用,功能號分別
為 0x0,0x1,0x2,0x3。其中 SWI 0x0及 SWI 0x1 使用兩個(gè)整形的輸入參數,并返
回一個(gè)結果值,SWI 0x2使用 4 個(gè)輸入參數,并返回一個(gè)結果值;SWI 0x3 使用
4 個(gè)輸入參數,并返回 4個(gè)結果值。
整個(gè) SWI 異常中斷處理程序分為兩級結構。第 1 級的 SWI 異常中斷處理程序是
匯編程序 SWI_HANDLER,它讀取 SWI 指令中的 24 位立即數,然后調用第 2 個(gè)級
SWI 異常中斷處理程序 C_SWI_HANDLER來(lái)實(shí)現具體的 SWI 功能。第 2 級SWI異常
中谷底你處理程序 C_SWI_HANDLER 為 C 語(yǔ)言程序。其中實(shí)現了功能號分別為
0x0,0x1,0x2,0x3的 SWI功能調用。
主程序中的子程序 multiply_two()對應著(zhù) SWI 0x0;add_two()對應著(zhù)
0x1;add_multiply_two()對應著(zhù) 0x2;many_operations()對應著(zhù) SWI 0x3。
Many_operations()返回 4 個(gè)結果,使用編譯器偽操作_valuc_in_reg 聲明。4
個(gè)子程序都使用編譯器偽操作__SWI來(lái)聲明。主程序使用 lnstall_Handler()來(lái)
安裝該 SWI異常中斷處理程序,lnstall_Handler()在前面已經(jīng)有詳細的介紹。
整個(gè)代碼如程序 6.2 所示。
程序 6.2 從C 程序中調用特定的 SWI功能
__swi(0) int multiply_two (int,int);
__swi(1) int add_two (int,int);
__swi(2) int add_multiply_two (int ,int ,int ,int );
Struct four_results
{
int a;
int b;
int c;
int d;
};
__swi(3) __value_in_regs struct four_results
Many operations (int ,int,int,int);
#include
#include “swi.h”
Unsigned *swi_vec=(unsigned *)0x08;
Unsigned install_Handler(unsigned routine, unsigned *vector)
{
Unsigned vec,old_vec;
Vec=(routine –(unsigned)vector-8)>>2;
If (vec & 0xff000000)
{
print(“Handler greter than 32Mbytes from vector”);
vec=0xea000000 |vec;
Old_vec=*vector;
*vector=vec;
Return(old_vec);
}
Int result1,result2;
Struct fcur_results result3;
Install_Handler ((unsigned) SWI_Handler,swi_vec);
Printf(“result1=mutiply_two (2,4)=%dn”,
Result1=multiply_two(2,4));
Printf(“result2=mutiply_two (3,6)=%dn”,
Result2=multiply_two(3,6));
Printf(“add_two(result1,result2 ) =%dn, add_two(result1,result2));
Printf(‘add_multiply_two(2,4,3,6)=&dn”,add_multiply_two(2,4,3,6));
Res_3=many_operations(12,4,3,1);
Printf(“res_3.a=&dn”,res_3.a);
Printf(“res_3.b=&dn”,res_3.b);
Printf(“res_3.c=&dn”,res_3.c);
Printf(“res_3.d=&dn”,res_3.d);
Return 0;
}
;第1 級SWI 異常中斷處理程序 SWI_Handler
;SWI_Handler 在前面已有詳細介紹
AREA SWI_Area, CODE,PEADONLY
EXPORT SWI_Handler
IMPORT C_SWI_Handler
T_bit EQU 0x2c
SWI_Handler
STMED sp!(r0-r3,r12,lr)
MOV r1,sp
MRS r0,spsr
STMFD sp!,(r0)
TST r0,#T_bit
LDRNEH r0(lr,#-2)
BTCNE r0,r0,#0xff00
LDREQ r0,(lr,#-4)
BICEQ r0,r0,#0xff000000
BL C_SWI_Handler
LDMFD sp!,(r0)
MSR spsr cf,r0
LDMFD sp!,(r0-r3,r12,pc)^
END
Void C_SWI_Handler (int swi_num,int *regs)
{
Switch (swi_num)
{
//對應于SWI 0x0
case 0:
regs[0]=regs[0]*regs[1];
break;
//對應于SWI 0x1
case 1:
regs[0]=regs[0]+ regs[1];
break;
//對應于SWI 0x2
case 2:
regs[0]=(regs[0]*regs[1]) +(regs[2]*regs[3]);
break;
//對應于SWI 0x3
case 3:
{int w,x,y,z;
w=regs[0];
x=regs[1];
y=regs[2];
z=regs[3];
regs[0]=w+x+y+z;
regs[1]=w-x-y-z;
regs[2]=w*x*y*z;
regs[3]=(w+x)*(y-z);
}
Break;
}
}
③ 從應用程序中動(dòng)態(tài)調用 SWI
在有些情況下,直到運行時(shí)才能夠確定需要調用的 SWI 功能號。這時(shí),有兩種
方法處理這種情況。
第 1 種方法是在運行時(shí)得到 SWI 功能號,然后構造出相應的 SWI 指令的編碼,
把這個(gè)指令的編碼保存在一個(gè)存儲器單元中,執行該指令即可。
第 2 種方法使用一個(gè)通用的 SWI 異常中斷處理程序,將運行時(shí)需要調用的 SWI
功能號作為參數傳遞給該通用的 SWI 異常中斷處理程序,通用的 SWI 異常中斷
處理程序根據參數值調用相應的 SWI 處理程序完成需要的操作。
在匯編程序中很容易實(shí)現第 2 中方法。在執行 SWI 指令之前先將需要調用的 SWI
功能號放在一個(gè)寄存器。在通用的 SWI 異常中斷處理程序讀取該寄存器值,決
定需要執行的操作,但有些 SWI 處理程序需要 SWI 指令的 24位立即數,因而上
述兩種方法常常組合使用。
在操作系統中通常使用一個(gè) SWI 功能號和一個(gè)寄存器來(lái)提供很多的 SWI 功能調
用。這樣可以將其他的 SWI 功能號留給用戶(hù)使用。在 DOS 系統中,DOS 提供功能
調用是 INT 21H ,這時(shí)通過(guò)指定寄存器 AX 的值,可以實(shí)現很多不同的功能調用。
ARM 體系中semihost 的實(shí)現也是一個(gè)例子。ARM 程序使用 SWI 0x123456 來(lái)實(shí)現
semilhost 功能調用;Thunb 程序使用SWI 0xAB 來(lái)實(shí)現 semihost 功能調用。在
下面的例子中,將子程序 WRITEC (unsigned op,char *c)映射到 semihost
功能調用,具體 semihost SWI 的子功能號通過(guò)參數 op 傳遞。
程序 6.3 從應用程序中動(dòng)態(tài)調用 SWI 功能
#ifdef_thumb
#else
#define semiSWI 0x123456
#endif
__swi (semiSWI) void semibosting (unsigned op,char *c);
Void write_a_character (int ch)
{
char tempth=ch;
writec (&tempch);
}
2.FIQ 和IRQ 異常中斷處理程序
ARM 提供的FIQ和 IRQ 異常中斷用于外部設備向 CPU 請求中斷服務(wù)。這兩個(gè)異常中斷的引腳
都是低電平有效的。當前程序狀態(tài)寄存器 CPSR 的 1 控制位可以屏蔽這兩個(gè)異常中斷請求;
當程序狀態(tài)寄存器 CPSR由 1 控制位位 0 時(shí),CPU正常響應 FIQ 和IRQ 異常中斷請求。
FIQ 異常中斷為快速異常中斷,它比 IRQ 異常中斷優(yōu)先級高,這主要表現在下面的兩個(gè)方
面:
● 當 FIQ 和IRQ 異常中斷同時(shí)產(chǎn)生時(shí),CPU 先處理 FIQ 異常中斷。
● 在 FIQ 異常中斷處理程序中 IRQ 異常中斷被禁止。
由于 FIQ 異常中斷通常用于系統對于響應時(shí)間要求比較苛刻的任務(wù),ARM 體系在設計上有
一些特別的安排,以盡量減少 FIQ 異常中斷響應時(shí)間。FIQ 異常中斷的中斷向量為 0x1c,位
于中斷向量表的最后。這樣 FIQ 異常中斷處理程序可以直接放在地址 0x1c 開(kāi)始的存儲單元,
這種安排省掉了中斷向量表的跳轉指令,從而也就節省了中斷響應時(shí)間。當系統中存在
cache 時(shí),可以把 FIQ 異常中斷向量以及處理程序一起鎖在 cache 中,從而大大地提高了
FIQ 異常中斷響應時(shí)間。除此之外,與其他的異常模式相比,FIQ 異常中斷還有額外的 5 個(gè)
物理寄存器,這樣在進(jìn)入 FIQ 處理程序時(shí)可以保存這 5 個(gè)寄存器,從而也提高了 FIQ 異常中
斷的執行速度。
在有些 IRQ/FIQ 異常中斷處理程序中,允許新的 IRQ/FIQ 異常中斷,這時(shí)將需要一些特
別的操作保證“老的”異常中斷的寄存器不會(huì )“新的”異常中斷破壞,這種 IRQ/FIQ 異常中
斷處理程序稱(chēng)為可重入的異常中斷處理程序。否則稱(chēng)為不可重入的異常中斷處理程序。
① 不可重入的 IRQ/FIQ 異常中斷處理程序
對于 C 語(yǔ)言不可重入的 IRQ/FIQ 異常中斷處理程序可以使用關(guān)鍵詞_irq來(lái)說(shuō)明。關(guān)鍵詞
_irq 可以實(shí)現下面的操作:
● 保存 APCS 規定的被破壞的寄存器。
● 保存其他中斷處理程序中用到的寄存器。
● 同時(shí)將(LD-4)賦予程序計數器 pc 實(shí)現中斷處理程序的返回,并且恢復 CPSR 寄
存器的內容。
當 IRQ/FIQ異常中斷處理程序調用了子程序時(shí),關(guān)鍵詞_irq可以使 IRQ/FIQ 異常中斷
處理程序返回時(shí)從其數據棧中讀取 LR_irq 值,并通過(guò) SUBS PC,LR,#4 實(shí)現返回。程序
6.4 說(shuō)明的關(guān)鍵詞_irq 的作用,其中列出了 C 語(yǔ)言程序及其對應的匯編程序,兩個(gè) C
語(yǔ)言程序中,第 1 個(gè)使用關(guān)鍵詞_irq 聲明,第2個(gè)沒(méi)有使用關(guān)鍵詞_irq聲明。
程序 6.4 關(guān)鍵詞_irq 的作用
;第1 個(gè)程序使用關(guān)鍵詞_irq 聲明
_irq void IRQHandler (void)
{
Volatile unsigned int *base=(unsigned int *)0x8000000;
If (*base 1)
{
//調用相應的 C 語(yǔ)言處理程序
C_int_Handler ();
}
//清除中斷標志
*(base=1)=0;
}
;第1 個(gè)C 語(yǔ)言程序對應的匯編程序
IRQHandler PROC
STMFD sp!,(r0-r4,r12,lr)
MOV r4,#0x8000000
LDR r0,(r4,#0)
SUB sp,sp,#4
CMP r0,#1
BLEQ Q_int_handler
MOV r0,#0
STR r0,(r4,#4)
ADD sp,sp,#4
LDMFD sp!,(r0-r4,r12,lr)
SUBS pc,lr,#4
ENDP
BXPORT IRQHandler
//第2 個(gè)程序沒(méi)有使用關(guān)鍵詞_irq 聲明
_irq void IRQHandler (void)
{
Volatile unsigned int *base=(unsigned int *) 0x80000;
If(*base 1)
{
//調用相應的 C 語(yǔ)言處理程序
C_int_handler();
}
//清除中斷標志
*(base+1)=0;
}
;第1 個(gè)C 語(yǔ)言程序對應的匯編程序
IRQHandler PROC
STMFD sp!(r4,lr)
MOV r4,#0x8000000
LDR r0,(r4,#0)
CMP r0,#1
SLEQ C_int_handler
MOV r0,#0
STR r0,(r4,#4)
LDMFD sp!(r4,pc)
ENDP
② 可重入的 IRQ/FIQ 異常中斷處理程序
如果在可重入的 IRQ/FIQ 異常中斷處理程序中調用了子程序,子程序的返回地址被保存
到寄存器的 LR_irq 中,這時(shí)如果發(fā)生了 IRQ/FIQ異常中斷,這個(gè) LR_irq寄存器的值將
被破壞,那么被調用的子程序將不能正確的返回。因此,對于可重入的 IRQ/FIQ異常中
斷處理程序一些需要特別的操作。下面列出了在可重入的 IRQ/FIQ 異常中斷處理程序中
需要的操作。這時(shí),第1 級中斷處理程序不能使用 C 語(yǔ)言,因為其中一些操作不能通過(guò)
C 語(yǔ)言實(shí)現:
● 將返回地址保存到 IRQ的數據棧中。
● 保存工作寄存器和 SPSR_irq。
● 清除中斷標志位。
● 將處理器切換到系統模式,重新使能中斷(IRQ/FIQ)。
● 保存用戶(hù)模式的 LR 寄存器和被調用者的不保存的寄存器。
● 調用 C 語(yǔ)言的 IRQ/FIQ異常中斷處理程序。
● 當 C 語(yǔ)言的 IRQ/FIQ 異常中斷程序返回后,恢復用戶(hù)模式的寄存器,并禁止中斷
(IRQ/FIQ)。
● 切換到 IRQ模式,禁止中斷。
● 恢復工作組寄存器和寄存器 LR_irq。
● 從 IRQ 異常中斷處理程序中返回。
下面程序 6.5 演示了這些操作的過(guò)程。
程序6.5 可重入的 IRQ/FIQ 異常中斷處理程序
AREA INTERRUPT ,CODE,PEADONJY
;引入C語(yǔ)言的 IRQ中斷處理程序 C_irq_handler
IMPORT C_irq_handler
IRQ
;保存返回 IRQ 處理程序地址
SUB lr,lr,#4
STMFD sp! ,(lr)
保存 SPSR_irq,及其他工作寄存器
MRS r14,SPSR
STMFD sp!,lr12,r14
;
;在這里添加指令,清除中斷標志位
;添加指令重新使能中斷
;
;切換到系統模式,并使能中斷
MSR CPSR_C,#0x1f
;保存用戶(hù)模式的 LR_usr 及被調用者不保存寄存器
STMFD sp!,(r0-r3,lr)
;跳轉到C 語(yǔ)言的中斷處理程序
BL C_irq_handler
;恢復用戶(hù)模式的寄存器
LDMFD sp!,(r0-r3,lr)
;切換到IRQ 模式,禁止 IRQ 中斷,FIQ 中斷允許
MSR CPSP_c,#0x92
;恢復工作寄存器和 SPSR_irq
LDMFD sp!,(pc)^
END
6.2.2 復位中的異常中斷處理程序
復位異常中斷處理程序在系統加電或復位時(shí)執行,它將進(jìn)行一些初始化的工作,具體內
容與復位系統相關(guān),然后程序控制權交給應用程序,因而復位異常中斷處理程序不需要返回。
下面時(shí)通常在復位異常中斷處理程序進(jìn)行的一些處理:
● 設置異常中斷向量表。
● 初始化數據棧和寄存器。
● 初始化存儲系統,如系統中的 MMU等。
● 初始化一些關(guān)鍵的 I/O設備。
● 使用中斷。
● 將處理器切換到會(huì )話(huà)模式。
● 初始化 C 語(yǔ)言環(huán)境變量,條狀到應用程序執行。
6.2.3 C 語(yǔ)言程序中的異常中斷處理程序
在程序運行過(guò)程中,也可以在 C 語(yǔ)言程序中安裝異常中斷處理程序。這時(shí)需要把相應的跳
轉指令或者數據讀取指令的編碼寫(xiě)到中斷向量表的響應位置。下面分別討論這兩種情況下安
裝異常中斷處理程序的方法。
1.中斷向量表中使用跳轉指令的情況
當中斷向量表中使用跳轉指令時(shí),在 C 程序中安裝異常中斷處理程序的操作如下:
(1) 讀取中斷處理程序的地址。
(2 ) 從上一步得到的地址中減去該異常中斷對應的中斷向量的地址。
(3) 從上一步得到的地址中減去 8,以允許指令的預取。
(4 ) 將上一步得到的地址右移 2 位,得到以字(32位)為單位的偏移量。
(5) 確保上一步得到的地址高 8 位為0,因為跳轉指令只允許 24位的偏移量。
(6) 將上一步得到的地址與數據 0xea000000 作邏輯或,從而得到將要寫(xiě)到中斷向
量表的跳轉指令的編碼。
以上具體操作通過(guò)程序 6.6 實(shí)現下面的 C 程序。其中參數 routine 是中斷處理程序
的地址,vector 為中斷向量的地址。
程序 6.6 使用跳轉指令的中斷向量表
Unsigned install_handler (unsigned routine ,unsigned *vector)
{ unsigned vec, oldvec;
vec=((routine-(unsigned)vector-0x8)>>2);
If (vec & 0xff000000)
{
Printf(“Installation of handler failed” )
exit (2);
}
vec=0xea000000|vec;
oldvec=^vector;
*vector=vec;
return (oldvec);
}
2. 中斷向量表中使用數據讀取指令的情況
當中斷向量表中使用數據讀取指令時(shí),在 C 程序中安裝異常中斷處理程序的操作序列如下
所示:
(1) 讀取中斷處理程序的地址。
(2) 從上一步得到的地址中減去該異常中斷對應的中斷向量的地址。
(3) 從上一步得到的地址中減去 8,允許指令預取。
(4) 將上一步得到的地址與數據 0xe59f000 作邏輯或,從而得到將要寫(xiě)到中斷向量
表中的數據讀取指令的編碼。
(5) 將中斷處理程序的地址放到相應的存儲單元。
程序 6.7中的 C 程序實(shí)現了上面的操作序列。其中參數 location 是一個(gè)存儲單元,其中
保存了中斷處理程序的地址;vector 為中斷向量的地址。
程序6.7 數據讀取指令的中斷向量表
Unsigned Install_Handler (unsigned location ,unsigned *vector)
{ unsigned vec ,oldvec;
Vec=((unsigned)location-(unsigned)vector-0x8) | (0xe59ff0000 oldvec -
*vector;
*vector=vec;
Return (oldvec);
}
下面的語(yǔ)句調用上面的代碼,在 C 程序中安裝中斷處理程序。
Unsigned *irqvec=(unsigned *)0x18;
Install_Handler ((unsigned)IRQHandler,irqvec);
6.3 其它種類(lèi)的異常中斷
1.數據訪(fǎng)問(wèn)中止異常中斷處理程序
如果系統不包含 MMU,數據訪(fǎng)問(wèn)中止異常中斷處理程序只是簡(jiǎn)單地報告錯誤,然后退出。如
果系統中包含 MMU,數據訪(fǎng)問(wèn)中止異常中斷處理程序要處理該數據訪(fǎng)問(wèn)中止。當發(fā)生數據訪(fǎng)
問(wèn)中止異常中斷的指令時(shí)。LR_abt 寄存器已經(jīng)被更新,它指向引起數據訪(fǎng)問(wèn)中止異常中斷
的指令后面第 2 條指令。此時(shí)要返回到引起數據訪(fǎng)問(wèn)中止異常中斷的指令。即(LR_abt)處。
下面3 種情況可能引起數據訪(fǎng)問(wèn)中止異常中斷。
① LDR/STR 指令
對于 ARM 數據訪(fǎng)問(wèn)中止異常中斷發(fā)生時(shí),LR_abt 寄存器已經(jīng)被更新,它指向引起數據訪(fǎng)問(wèn)
中止異常中斷的指令后面第 2 條指令,此時(shí)要返回到引起數據訪(fǎng)問(wèn)中止異常中斷的指令。
對于 ARM9、ARM10、strongARM 處理器,數據訪(fǎng)問(wèn)中止異常中斷發(fā)生后,處理器將程序計數
器設置稱(chēng)引起數據訪(fǎng)問(wèn)中止異常中斷的指令的地址,不需要用戶(hù)來(lái)完成這種程序計數器的設
置操作。
② SWAP 指令
SWAP 指令執行時(shí),未更新及存取 LR_abt.
③ LDM/STM 指令
對于 ARM6及 ARM7 處理器,如果寫(xiě)回機制使能的話(huà),基址寄存器將被更新。對于 ARM9、ARM10
及 strongARM 處理器,如果寫(xiě)回機制使能的話(huà),數據訪(fǎng)問(wèn)中止異常中斷發(fā)生時(shí),處理器將恢
復基址寄存器的值。
3.指令預取中止異常中斷處理程序
如果系統不包含 MMC,指令預取中止異常中斷處理程序只是簡(jiǎn)單地報告錯誤,然后退出。
如果系統中包含 MMU,則發(fā)生錯誤的指令觸發(fā)虛擬地址失效,在該失效處理程序中重新
讀取該指令。指令預取中止異常中斷是有錯的指令執行時(shí)被觸發(fā)是,這時(shí) LR_abt 寄存
器還沒(méi)有被更新,它指向該指令的下面一條指令。因為該有問(wèn)題的指令要被重新讀取,
因而應該返回到該有問(wèn)題的指令,即返回到(LR_abt-4)處。
4.未定義指令異常中斷
當 CPU 不認識當前指令時(shí),它將該指令發(fā)送到協(xié)處理器。如果所以的協(xié)處理器都不認識
該指令,這時(shí)將產(chǎn)生未定義指令異常中斷。在未定義指令異常中斷進(jìn)行響應的處理???wbr />
以看出這種機制可以用來(lái)通過(guò)軟件仿真系統中一些部件的功能。比如,如果系統中不包
含浮點(diǎn)運算部件,CPU 遇到浮點(diǎn)運算指令時(shí)。將發(fā)生未定義指令異常中斷,在該未定義
指令異常中斷的處理程序中可以通過(guò)其他指令序列仿真該浮點(diǎn)運算指令。
這種仿真的處理過(guò)程類(lèi)似有 SWI異常中斷的功能調用。在 SWI 異常中斷的功能調用中
通過(guò)讀取 SWI 指令中的 24 位的立即數。判斷具體請求的 SWI 功能。這種仿真機制的操
作過(guò)程如下:
① 將仿真程序設置成未定義指令異常中斷的中斷處理程序(鏈接到未定義指令異常中
斷的中斷處理程序鏈中),并保存原來(lái)的中斷處理程序。這是通過(guò)修改中斷向量表
中未定義指令異常中斷對應的中斷向量來(lái)實(shí)現的。
② 讀取該未定義的位[27:24],判斷該未定義指令是否是一個(gè)協(xié)處理器指令。當位
[27:24]為 0b1110 或 0b110x 時(shí),該未定義指令時(shí)一個(gè)協(xié)處理器指令。接著(zhù)讀取該
未定義的指令的位[11:8],如果位[11:8]指定通過(guò)仿真程序實(shí)現該未定義指令,則
相應的調用仿真程序實(shí)現該指令的功能,后來(lái)返回到用戶(hù)程序。
③ 如果不仿真該未定義指令,程序跳轉到原來(lái)的未定義指令異常中斷的中斷處理程序
執行。
Thumb 指令集中不包含協(xié)處理器指令,因而不需要這種仿真機制。
評論