#define __read_32bit_c0_register(s,sel) \
({ int __res;
if(0 == sel)\
__asm__ __volatile__(\
"mfc0 \t %0, " #s "\n\t"
:"=r" (__res)));\
else\
__asm__ __volatile__(\
".set \t mips32 \n\t"
"mfc0\t%0, " #s "," #sel "\n\t"
".set\tmips0\n\t\"
:"=r" (__res)));\
__res;\
})
1)\n\t 换行 空一个tab的距离
2) mfc0 把一个数据从通用寄存器拷贝到特殊寄存器(MTC0做相反的操作)
以下来源于:https://blog.youkuaiyun.com/adaptiver/article/details/6760220
.set push --> save all settings
.set reorder/noreorder --> let/don't let assembler reorder instructions
.set at/noat --> let/don't let assembler use the register $at in instruction aliases (li,la, etc.)
.set pop --> restore saved settings
.set mipsn。n是一个从0到5的数字,或是数字32或64。1到5,32或64使汇编器从源程序中的这一点开始接受相应ISA级别的指令。 .set mipsn 不仅影响允许使用那些指令,还影响到某些宏如何被扩展。 .set mips0保持原本的ISA级别:这个级别是您通过命令行选项选择的,或者是您的配置的默认值。您可以通过这个特性在32位汇编模式中使用r4000的指令。小心使用这个命令!
命令‘.set mips16’使汇编器进入MIPS 16模式,传统的汇编器不支持这个命令
伪操作 .set mips3 告诉汇编器下面的指令是MIPS IV(64位指令集,兼容32位指令)中的指令。
1..set noreorder/reorder
默认汇编器处在reorder的模式下,该模式允许汇编器对指令进行重新排序,以避免流水线堵塞并获得更好的性能,在这种模式下,是不允许在代码中插入 nop指令的。反之,在noreorder模式下,指令的顺序不会被改变也不会对代码进行任何优化。这样做的优点是程序员可以完全控制代码的执行顺序,缺点是必须手工对指令排序,并在分支和加载指令的延迟槽中填上有用的指令或nop指令.比如:
.set noreorder
lw t0, 0(a0)
nop #加载指令延迟槽
sub t0, 1
bne t0, zero, loop
nop #分支指令延迟槽
.set reorder
2. .set volatile/novolatile
处在volatile区的所有存取指令都不会被移动位置(特别是存取指令之间的相对位置)。这一点对访问内存映射设备的寄存器非常重要。因为对于外围设备而言,读写的次序十分重要。另外对读状态寄存器也非常重要。因为想得到的状态都是最新的。举例来说,如果下列代码没有使用.set volatile,那么汇编器很有可能会对第二个lw指令移到指令的前面,因为这样可以填充第一条lw指令的延迟槽:
.set volatile
lw t0, 0(a0)
sw t0, 0(a1)
lw t0, 4(a0)
.set novalatile
避免流水线堵塞的操作以及其他各种优化措施不受该设定的影响.