MIPS汇编快速入门 【龙芯】

一、前言: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汇编是连接软件与龙芯硬件的桥梁。