一、前言: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位)
功能:寄存器间运算(如加法、逻辑运算)。
示例:
c
add $t0, $s0, $s1 ; $t0 = $s0 + $s1(op=0,funct=0x20)
2. I型(立即数型)
格式:op(6位) | rs(5位) | rt(5位) | immediate(16位)
功能:含立即数的运算、数据传输、条件分支。
示例:
c
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位)
功能:无条件跳转、函数调用。
示例:
c
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()
c
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汇编是连接软件与龙芯硬件的桥梁。