REGISTER | NAME | USAGE |
$0 | $zero | 常量0(constant value 0) |
$1 | $at | 保留给汇编器(Reserved for assembler) |
$2-$3 | $v0-$v1 | 函数调用返回值(values for results and expression evaluation) |
$4-$7 | $a0-$a3 | 函数调用参数(arguments) |
$8-$15 | $t0-$t7 | 暂时的(或随便用的) |
$16-$23 | $s0-$s7 | 保存的(或如果用,需要SAVE/RESTORE的)(saved) |
$24-$25 | $t8-$t9 | 暂时的(或随便用的) |
$28 | $gp | 全局指针(Global Pointer) |
$29 | $sp | 堆栈指针(Stack Pointer) |
$30 | $fp | 帧指针(Frame Pointer) |
$31 | $ra | 返回地址(return address) |
指令 | 功能 | 应用实例 |
LB | 从存储器中读取一个字节的数据到寄存器中 | LB R1, 0(R2) |
LH | 从存储器中读取半个字的数据到寄存器中 | LH R1, 0(R2) |
LW | 从存储器中读取一个字的数据到寄存器中 | LW R1, 0(R2) |
LD | 从存储器中读取双字的数据到寄存器中 | LD R1, 0(R2) |
L.S | 从存储器中读取单精度浮点数到寄存器中 | L.S R1, 0(R2) |
L.D | 从存储器中读取双精度浮点数到寄存器中 | L.D R1, 0(R2) |
LBU | 功能与LB指令相同,但读出的是不带符号的数据 | LBU R1, 0(R2) |
LHU | 功能与LH指令相同,但读出的是不带符号的数据 | LHU R1, 0(R2) |
LWU | 功能与LW指令相同,但读出的是不带符号的数据 | LWU R1, 0(R2) |
SB | 把一个字节的数据从寄存器存储到存储器中 | SB R1, 0(R2) |
SH | 把半个字节的数据从寄存器存储到存储器中 | SH R1,0(R2) |
SW | 把一个字的数据从寄存器存储到存储器中 | SW R1, 0(R2) |
SD | 把两个字节的数据从寄存器存储到存储器中 | SD R1, 0(R2) |
S.S | 把单精度浮点数从寄存器存储到存储器中 | S.S R1, 0(R2) |
S.D | 把双精度数据从存储器存储到存储器中 | S.D R1, 0(R2) |
DADD | 把两个定点寄存器的内容相加,也就是定点加 | DADD R1,R2,R3 |
DADDI | 把一个寄存器的内容加上一个立即数 | DADDI R1,R2,#3 |
DADDU | 不带符号的加 | DADDU R1,R2,R3 |
DADDIU | 把一个寄存器的内容加上一个无符号的立即数 | DADDIU R1,R2,#3 |
ADD.S | 把一个单精度浮点数加上一个双精度浮点数,结果是单精度浮点数 | ADD.S F0,F1,F2 |
ADD.D | 把一个双精度浮点数加上一个单精度浮点数,结果是双精度浮点数 | ADD.D F0,F1,F2 |
ADD.PS | 两个单精度浮点数相加,结果是单精度浮点数 | ADD.PS F0,F1,F2 |
DSUB | 两个寄存器的内容相减,也就是定点数的减 | DSUB R1,R2,R3 |
DSUBU | 不带符号的减 | DSUBU R1,R2,R3 |
SUB.S | 一个双精度浮点数减去一个单精度浮点数,结果为单精度 | SUB.S F1,F2,F3 |
SUB.D | 一个双精度浮点数减去一个单精度浮点数,结果为双精度浮点数 | SUB.D F1,F2,F3 |
SUB.PS | 两个单精度浮点数相减 | SUB.SP F1,F2,F3 |
DDIV | 两个定点寄存器的内容相除,也就是定点除 | DDIV R1,R2,R3 |
DDIVU | 不带符号的除法运算 | DDIVU R1,R2,R3 |
DIV.S | 一个双精度浮点数除以一个单精度浮点数,结果为单精度浮点数 | DIV.S F1,F2,F3 |
DIV.D | 一个双精度浮点数除以一个单精度浮点数,结果为双精度浮点数 | DIV.D F1,F2,F3 |
DIV.PS | 两个单精度浮点数相除,结果为单精度 | DIV.PS F1,F2,F3 |
DMUL | 两个定点寄存器的内容相乘,也就是定点乘 | DMUL R1,R2,R3 |
DMULU | 不带符号的乘法运算 | DMULU R1,R2,R3 |
MUL.S | 一个双精度浮点数乘以一个单精度浮点数,结果为单精度浮点数 | DMUL.S F1,F2,F3 |
MUL.D | 一个双精度浮点数乘以一个单精度浮点数,结果为双精度浮点数 | DMUL.D F1,F2,F3 |
MUL.PS | 两个单精度浮点数相乘,结果为单精度浮点数 | DMUL.PS F1,F2,F3 |
AND | 与运算,两个寄存器中的内容相与 | AND R1,R2,R3 |
ANDI | 一个寄存器中的内容与一个立即数相与 | ANDI R1,R2,#3 |
OR | 或运算,两个寄存器中的内容相或 | OR R1,R2,R3 |
ORI | 一个寄存器中的内容与一个立即数相或 | ORI R1,R2,#3 |
XOR | 异或运算,两个寄存器中的内容相异或 | XOR R1,R2,R3 |
XORI | 一个寄存器中的内容与一个立即数异或 | XORI R1,R2,#3 |
BEQZ | 条件转移指令,当寄存器中内容为0时转移发生 | BEQZ R1,0 |
BENZ | 条件转移指令,当寄存器中内容不为0时转移发生 | BNEZ R1,0 |
BEQ | 条件转移指令,当两个寄存器内容相等时转移发生 | BEQ R1,R2 |
BNE | 条件转移指令,当两个寄存器中内容不等时转移发生 | BNE R1,R2 |
J | 直接跳转指令,跳转的地址在指令中 | J name |
JR | 使用寄存器的跳转指令,跳转地址在寄存器中 | JR R1 |
JAL | 直接跳转指令,并带有链接功能,指令的跳转地址在指令中,跳转发生时要把返回地址存放到R31这个寄存器中 | JAL R1 name |
JALR | 使用寄存器的跳转指令,并且带有链接功能,指令的跳转地址在寄存器中,跳转发生时指令的放回地址放在R31这个寄存器中 | JALR R1 |
MOV.S | 把一个单精度浮点数从一个浮点寄存器复制到另一个浮点寄存器 | MOV.S F0,F1 |
MOV.D | 把一个双精度浮点数从一个浮点寄存器复制到另一个浮点寄存器 | MOV.D F0,F1 |
MFC0 | 把一个数据从通用寄存器复制到特殊寄存器 Move from coprocessor 0 |
MFC0 R1,R2 |
MTC0 | 把一个数据从特殊寄存器复制到通用寄存器 Move to coprocessor 0 |
MTC0 R1,R2 |
MFC1 | 把一个数据从定点寄存器复制到浮点寄存器 | MFC1 R1,F1 |
MTC1 | 把一个数据从浮点寄存器复制到定点寄存器 | MTC1 R1,F1 |
LUI | 把一个16位的立即数填入到寄存器的高16位,低16位补零 | LUI R1,#42 |
DSLL | 双字逻辑左移 | DSLL R1,R2,#2 |
DSRL | 双字逻辑右移 | DSRL R1,R2,#2 |
DSRA | 双字算术右移 | DSRA R1,R2,#2 |
DSLLV | 可变的双字逻辑左移 | DSLLV R1,R2,#2 |
DSRLV | 可变的双字罗伊右移 | DSRLV R1,R2,#2 |
DSRAV | 可变的双字算术右移 | DSRAV R1,R2,#2 |
SLT | 如果R2的值小于R3,那么设置R1的值为1,否则设置R1的值为0 | SLT R1,R2,R3 |
SLTI | 如果寄存器R2的值小于立即数,那么设置R1的值为1,否则设置寄存器R1的值为0 | SLTI R1,R2,#23 |
SLTU | 功能与SLT一致,但是带符号的 | SLTU R1,R2,R3 |
SLTUI | 功能与SLT一致,但不带符号 | SLTUI R1,R2,R3 |
MOVN | 如果第三个寄存器的内容为负,那么复制一个寄存器的内容到另外一个寄存器 | MOVN R1,R2,R3 |
MOVZ | 如果第三个寄存器的内容为0,那么复制一个寄存器的内容到另外一个寄存器 | MOVZ R1,R2,R3 |
TRAP | 根据地址向量转入管态 | |
ERET | 从异常中返回到用户态 | |
MADD.S | 一个双精度浮点数与单精度浮点数相乘加,结果为单精度 | |
MADD.D | 一个双精度浮点数与单精度浮点数相乘加,结果为双精度 | |
MADD.PS | 两个单精度浮点数相乘加,结果为单精度 |
eq. | Name | Brief | Actual Code | Space/Time | Description |
1 | abs Rd, Rs | Absolute Value | addu Rd, $0, Rs bgez Rs, 1 sub Rd, $0, Rs |
3/3 | |
2 | beqz Rs, Label | Branch if Equal to Zero | beq Rs, $0, Label | 1/1 | |
3 | bge Rs, Rt, Label | Branch if Greater than or Equal | slt $at, Rs, Rt 2/2 beq $at, $0, Label |
2/2 | If Reg.File[Rs] > = Reg.File[Rt] branch to Label Used to compare values represented in the two's complement number system. |
4 | bgeu Rs, Rt, Label | Branch if Greater than or Equal Unsigned | sltu $at, Rs, Rt beq $at, $0, Label |
2/2 | If Reg.File[Rs] > = Reg.File[Rt] branch to Label Used to compare addresses (unsigned values). |
5 | bgt Rs, Rt, Label | Branch if Greater Than | slt $at, Rt, Rs bne $at, $0, Label |
2/2 | If Reg.File[Rs] > Reg.File[Rt] branch to Label Used to compare values represented in the two's complement number system. |
6 | bgtu Rs, Rt, Label | Branch if Greater Than Unsigned | sltu $at, Rt, Rs bne $at, $0, Label |
2/2 | If Reg.File[Rs] > Reg.File[Rt] branch to Label Used to compare addresses (unsigned values). |
7 | ble Rs, Rt, Label | Branch if Less Than or Equal | slt $at, Rt, Rs beq $at, $0, Label |
2/2 | If Reg.File[Rs] < = Reg.File[Rt] branch to Label Used to compare values represented in the two's complement number system. |
8 | bleu Rs, Rt, Label | Branch if Less Than or Equal Unsigned | sltu $at, Rt, Rs beq $at, $0, Label |
2/2 | If Reg.File[Rs] < = Reg.File[Rt] branch to Label Used to compare addresses (unsigned values). |
9 | blt Rs, Rt, Label | Branch if Less Than | slt $at, Rs, Rt bne $at, $0, Label |
2/2 | If Reg.File[Rs] < Reg.File[Rt] branch to Label Used to compare values represented in the two's complement number system |
10 | bltu Rs, Rt, Label | Branch if Less Than Unsigned | sltu $at, Rs, Rt bne $at, $0, Label |
2/2 | If Reg.File[Rs] < Reg.File[Rt] branch to Label Used to compare addresses (unsigned values). |
11 | bnez Rs, Label | Branch if Not Equal to Zero | bne Rs, $0, Label | 1/1 | |
12 | b Label | Branch Unconditional | bgez $0, Label | 1/1 | |
13 | div Rd, Rs, Rt | Divide | bne Rt, $0, ok break $0 ok: div Rs, Rt mflo Rd |
4/41 | |
14 | divu Rd, Rs, Rt | Divide Unsigned | bne Rt, $0, ok break $0 ok: divu Rs, Rt mflo Rd |
4/41 | |
15 | la Rd, Label | Load Address | lui $at, Upper 16-bits of Label ori Rd, $at, Lower 16-bits of Label |
2/2 | Used to initialize pointers |
16 | li Rd, value | Load Immediate | lui $at, Upper 16-bits of value ori Rd, $at, Lower 16-bits of value |
2/2 | Initialize registers with negative constants and values greater than 32767. |
17 | li Rd, value | Load Immediate | ori Rt, $0, value | 1/1 | Initialize registers with positive constants less than 32768. |
18 | move Rd, Rs | Move | addu Rd, $0, Rs | 1/1 | |
19 | mul Rd, Rs, Rt | Multiply | mult Rs, Rt mflo Rd |
2/33 | |
20 | mulo Rd, Rs, Rt | Multiply (with overflow exception) | mult Rs, Rt mfhi $at mflo Rd sra Rd, Rd, 31 beq $at, Rd, ok break $0 ok: mflo Rd |
7/37 | |
21 | mulou Rd, Rs, Rt | Multiply Unsigned (with overflow exception) | multu Rs, Rt mfhi $at beq $at, $0, ok ok: break $0 mflo Rd |
5/35 | |
22 | neg Rd, Rs | Negate | sub Rd, $0, Rs | 1/1 | Two's complement negation. An exception is generated when there is an attempt to negate the most negative value: 2,147,483,648. |
23 | negu Rd, Rs | Negate Unsigned | subu Rd, $0, Rs | 1/1 | |
24 | nop | Nop | or $0, $0, $0 | 1/1 | |
25 | not Rd, Rs | Not | nor Rd, Rs, $0 | 1/1 | A bit-wise Boolean complement. |
26 | rem Rd, Rs, Rt | Remainder | bne Rt, $0, 8 break $0 div Rs, Rt mfhi Rd |
4/40 | |
27 | remu Rd, Rs, Rt | Remainder Unsigned | bne Rt, $0, ok break $0 ok: divu Rs, Rt mfhi Rd |
4/40 | |
28 | rol Rd, Rs, Rt | Rotate Left Variable | subu $at, $0, Rt srlv $at, Rs, $at sllv Rd, Rs, Rt or Rd, Rd, $at |
4/4 | The lower 5-bits in Rt specifys the shift amount. |
29 | ror Rd, Rs, Rt | Rotate Right Variable | subu $at, $0, Rt sllv $at, Rs, $at srlv Rd, Rs, Rt or Rd, Rd, $at |
4/4 | |
30 | rol Rd, Rs, sa | Rotate Left Constant | srl $at, Rs, 32-sa sll Rd, Rs, sa or Rd, Rd, $at |
3/3 | |
31 | ror Rd, Rs, sa | Rotate Right Constant | sll $at, Rs, 32-sa srl Rd, Rs, sa or Rd, Rd, $at |
3/3 | |
32 | seq Rd, Rs, Rt | Set if Equal | beq Rt, Rs, yes ori Rd, $0, 0 beq $0, $0, skip yes: ori Rd, $0, 1 skip: |
4/4 | |
33 | sge Rd, Rs, Rt | Set if Greater Than or Equal | bne Rt, Rs, yes ori Rd, $0, 1 beq $0, $0, skip yes: slt Rd, Rt, Rs skip: |
4/4 | |
34 | sgeu Rd, Rs, Rt | Set if Greater Than or Equal Unsigned | bne Rt, Rs, yes ori Rd, $0, 1 beq $0, $0, skip yes: sltu Rd, Rt, Rs skip: |
4/4 | |
35 | sgt Rd, Rs, Rt | Set if Greater Than | slt Rd, Rt, Rs | 1/1 | |
36 | sgtu Rd, Rs, Rt | Set if Greater Than Unsigned | sltu Rd, Rt, Rs | 1/1 | |
37 | sle Rd, Rs, Rt | Set if Less Than or Equal | bne Rt, Rs, yes ori Rd, $0, 1 beq $0, $0, skip yes: slt Rd, Rs, Rt skip: |
4/4 | |
38 | sleu Rd, Rs, Rt | Set if Less Than or Equal Unsigned | bne Rt, Rs, yes ori Rd, $0, 1 beq $0, $0, skip yes: sltu Rd, Rs, Rt skip: |
4/4 | |
39 | sne Rd, Rs, Rt | Set if Not Equal | beq Rt, Rs, yes ori Rd, $0, 1 beq $0, $0, skip yes: ori Rd, $0, 0 skip: |
4/4 | |
40 | ulh Rd, 3(Rs) | Unaligned Load Halfword Unsigned | lb Rd, 4(Rs) lbu $at, 3(Rs) sll Rd, Rd, 8 or Rd, Rd, $at |
4/4 | |
41 | ulhu Rd, 3(Rs) | Unaligned Load Halfword | lbu Rd, 4(Rs) lbu $at, 3(Rs) sll Rd, Rd, 8 or Rd, Rd, $at |
4/4 | |
42 | ulw Rd, 3(Rs) | Unaligned Load Word | lwl Rd, 6(Rs) lwr Rd, 3(Rs) |
2/2 | |
43 | ush Rd, 3(Rs) | Unaligned Store Halfword | sb Rd, 3(Rs) srl $at, Rd, 8 sb $at, 4(Rs) |
3/3 | |
44 | usw Rd, 3(Rs) | Unaligned Store Word | swl Rd, 6(Rs) swr Rd, 3(Rs) |
2/2 |
/*
********************************************************************
* Set up temporary stack.
********************************************************************
*/
li a0, CFG_INIT_SP_OFFSET
//bal mips_cache_lock
nop
li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET
la sp, 0(t0)
/* Initialize GOT pointer.
*/
#if 0
bal 1f
nop
.word _GLOBAL_OFFSET_TABLE_ - 1f + 4
1:
move gp, ra
lw t1, 0(ra)
add gp, t1
#else
/* winfred: a easier way to get gp value so that mipsel-linux-as can
* assemble correctly without -mips_allow_branch_to_undefined flag
*/
bal 1f
nop
.word _GLOBAL_OFFSET_TABLE_
1:
lw gp, 0(ra)
#endif
la t9, board_init_f
j t9
nop
/*
************************************************************************
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
* a0 = addr_sp
* a1 = gd
* a2 = destination address
************************************************************************
*/
.globl relocate_code
.ent relocate_code
relocate_code:
move sp, a0 /* Set new stack pointer */
li t0, CFG_MONITOR_BASE
la t3, in_ram
lw t2, -12(t3) /* t2 <-- uboot_end_data */
move t1, a2
/*
* Fix GOT pointer:
*
* New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
*/
move t6, gp
sub gp, CFG_MONITOR_BASE
add gp, a2 /* gp now adjusted */
sub t6, gp, t6 /* t6 <-- relocation offset */
/*
* t0 = source address
* t1 = target address
* t2 = source end address
*/
/* On the purple board we copy the code earlier in a special way
* in order to solve flash problems
*/
#ifndef CONFIG_PURPLE
1:
lw t3, 0(t0)
sw t3, 0(t1)
addu t0, 4
ble t0, t2, 1b
addu t1, 4 /* delay slot */
#endif
/* If caches were enabled, we would have to flush them here.
*/
/* Jump to where we've relocated ourselves.
*/
addi t0, a2, in_ram - _start
j t0
nop
.word uboot_end_data
.word uboot_end
.word num_got_entries
in_ram:
/* Now we want to update GOT.
*/
lw t3, -4(t0) /* t3 <-- num_got_entries */
addi t4, gp, 8 /* Skipping first two entries. */
li t2, 2
1:
lw t1, 0(t4)
beqz t1, 2f
add t1, t6
sw t1, 0(t4)
2:
addi t2, 1
blt t2, t3, 1b
addi t4, 4 /* delay slot */
/* Clear BSS.
*/
lw t1, -12(t0) /* t1 <-- uboot_end_data */
lw t2, -8(t0) /* t2 <-- uboot_end */
add t1, t6 /* adjust pointers */
add t2, t6
sub t1, 4
1: addi t1, 4
bltl t1, t2, 1b
sw zero, 0(t1) /* delay slot */
move a0, a1
la t9, board_init_r
j t9
move a1, a2 /* delay slot */
.end relocate_code
MIPS架构的汇编我就简单的说这些,我个人大约用了3个月的时间才勉强入门,希望大家看过这一期可以对MIPS进行架构进行更深入的学习。
----------------------------------------------------