一、前言:MIPS與龍芯的淵源
MIPS(Microprocessor without Interlocked Pipelined Stages)是一種經典的RISC(精簡指令集)架構,以流水線高效、指令簡潔、低功耗為特點。龍芯(Loongson)系列處理器(如LS1E、LS1F、LS2K等)早期基于MIPS架構擴展設計,因此掌握MIPS匯編是理解龍芯底層驅動開發(如BSP、設備驅動)的基礎。本文結合龍芯硬件特性,從寄存器、指令格式到實戰示例,快速入門MIPS匯編。
二、核心基礎:MIPS寄存器架構
MIPS架構采用32個32位通用寄存器(GPR),部分寄存器有特殊用途。在龍芯開發中,需重點關注以下幾類:
1. 通用寄存器($0~$31)
寄存器編號 | 匯編名稱 | 用途說明(龍芯開發場景) |
---|---|---|
$0 | $zero | 恒為0,用于賦初值或比較 |
$8~$15 | $t0 ~ $t7 | “臨時寄存器" (Temporary) |
$16~$23 | $s0 ~ $s7 | “保存寄存器” (Saved),函數調用需保存 |
$gp | $28 | “全局指針” (Global Pointer) |
$sp | $sp | “棧指針” (Stack Pointer) |
$ra | $31 | “返回地址” (Return Address),用于函數調用 |
龍芯實戰意義:在驅動開發中(如vxbMipsInt.c的中斷處理),需嚴格遵守寄存器使用約定(如臨時寄存器無需保存,保存寄存器需入棧),避免破壞上層調用上下文。
2. 特殊寄存器(核心控制)
程序計數器(PC):存儲當前執行指令地址,MIPS指令按4字節對齊(PC+4指向下一條指令)。
狀態寄存器(CP0 Status):控制中斷使能(IE位)、異常處理等,龍芯中斷控制器(如mipsLsnIntCtlr)需通過修改該寄存器開關全局中斷。
異常基地址寄存器(CP0 EBase):指定異常/中斷處理程序入口,龍芯BSP初始化時需配置該寄存器指向中斷向量表。
三、指令格式:MIPS的3種基礎類型
MIPS指令長度固定為32位,按功能分為3類,格式如下:
1. R型(寄存器型)
格式:op(6位) | rs(5位) | rt(5位) | rd(5位) | shamt(5位) | funct(6位)
功能:寄存器間運算(如加法、邏輯運算)。
示例:
add $t0, $s0, $s1 ; $t0 = $s0 + $s1(op=0,funct=0x20)
2. I型(立即數型)
格式:op(6位) | rs(5位) | rt(5位) | immediate(16位)
功能:含立即數的運算、數據傳輸、條件分支。
示例:
lw $t0, 0x10($gp) ; 從地址$gp+0x10加載字到$t0(op=0x23,rt=$t0)
addiu $t1, $t0, 4 ; $t1 = $t0 + 4(無符號立即數加法,op=0x09)
beq $t0, $zero, loop ; 若$t0==0,跳轉到loop(op=0x04)
3. J型(跳轉型)
格式:op(6位) | target(26位)
功能:無條件跳轉、函數調用。
示例:
j main ; 跳轉到main標簽(op=0x02)
jal func ; 調用func函數,$ra = PC+4(op=0x03)
四、常用指令:從數據操作到控制流
1. 數據傳輸指令(核心!)
MIPS通過加載/存儲(Load/Store) 指令訪問內存,龍芯硬件(如UART、PCI控制器)的寄存器讀寫依賴此類指令。
指令 | 功能 | 示例(龍芯場景) |
---|---|---|
lw rt, imm(rs) | 從內存rs+imm加載32位字到rt | lw t0,0xbf002000(t0, 0xbf002000(t0,0xbf002000(zero) ; 讀取PCI控制器寄存器(地址0xbf002000) |
sw rt, imm(rs) | 將rt的32位字存儲到rs+imm | sw t0,0xbf003204(t0, 0xbf003204(t0,0xbf003204(zero) ; 寫入中斷邊沿觸發寄存器(如GS1SOC_INT_EDGE) |
lb/lh | 加載字節/半字(帶符號) | - |
sb/sh | 存儲字節/半字 | - |
2. 算術與邏輯指令
指令 | 功能 | 示例 |
---|---|---|
add rd, rs, rt | 加法(可能溢出) | add $t0, $s0, $s1 |
addu rd, rs, rt | 無符號加法(不溢出) | addu $t0, $t1, $t2 |
sub rd, rs, rt | 減法 | sub $t0, $s0, $s1 |
and/or/xor | 按位與/或/異或 | and $t0, $t1, $t2 |
sll/srl | 邏輯左移/右移 | sll $t0, $t1, 2 ; $t0 = $t1 << 2 |
3. 控制流指令
驅動中的條件判斷、循環、中斷處理依賴控制流指令:
指令 | 功能 | 示例(龍芯中斷處理) |
---|---|---|
beq rs, rt, label | 若rs==rt,跳轉到label | beq $t0, $zero, int_end ; 若中斷標志為0,結束處理 |
bne rs, rt, label | 若rs!=rt,跳轉 | bne $v0, $zero, error |
j label | 無條件跳轉 | j isr_handler ; 跳轉到中斷服務程序 |
jal label | 調用函數($ra=PC+4) | jal pci_int_ack ; 調用PCI中斷確認函數 |
jr rs | 從寄存器rs跳轉(用于函數返回) | jr $ra ; 返回到調用處 |
五、實戰示例:龍芯PCI中斷處理片段
PCI中斷處理邏輯,用MIPS匯編實現核心步驟(簡化版):
場景:清除PCI中斷標志(地址0xbf003214)
函數:clear_pci_int()
clear_pci_int:li $t0, 0xbf003214 ; $t0 = 中斷清除寄存器地址(GS1SOC_INT_CLR)li $t1, 0x10000 ; $t1 = PCI_INTA_STATUS(中斷標志位)sw $t1, 0($t0) ; 寫入寄存器,清除中斷jr $ra ; 返回
解析:
li $t0, 0xbf003214
:用立即數加載指令(偽指令,實際轉為lui+ori)將寄存器地址存入$t0。
sw $t1, 0($t0)
:通過存儲指令清除中斷標志,對應C代碼IO_WRITE32(GS1SOC_INT_CLR, PCI_INTA_STATUS)
。
六、龍芯開發注意事項
內存對齊:MIPS要求字(32位)訪問必須對齊到4字節邊界,否則觸發異常。龍芯硬件寄存器(如UART、PCI控制器)均按此設計,匯編中需確保lw/sw地址對齊。
中斷上下文:中斷服務程序(ISR)需快速執行,通常僅保存臨時寄存器(t0?t0~t0?t7),通過addiu $sp, $sp, -4*8入棧,處理完成后出棧恢復。
工具鏈:龍芯MIPS開發常用mipsel-linux-gcc編譯,objdump -d反匯編查看機器碼與匯編對應關系,輔助調試驅動中的匯編片段。
七、總結
MIPS匯編是龍芯底層開發的“語言鑰匙”,掌握寄存器架構、指令格式和常用操作,即可看懂BSP驅動(如hwconf.c的硬件配置)、優化中斷響應(ISR)。后續可深入學習MIPS異常處理、協處理器(CP0/CP1)編程,進一步理解龍芯硬件加速特性。從簡單的寄存器讀寫到復雜的驅動邏輯,MIPS匯編是連接軟件與龍芯硬件的橋梁。