Diferencia entre revisiones de «MIPS»

De Jose Castillo Aliaga
Ir a la navegación Ir a la búsqueda
Línea 315: Línea 315:




Traurer la mitjana aritmètica de tres números en registres:
Traure la mitjana aritmètica de tres números en registres:


  .text
  .text
Línea 329: Línea 329:
  div $t4,$t5
  div $t4,$t5
  mflo $t6
  mflo $t6
Sumar els elements d'un array de memòria:
.data
array: .word 10,20,30,40,50
count: .word 5
.text
.globl main
main:
la $t0,array
la $t1, count
lw $t2, 0($t1)
addi $t5,$0,0
loop:
addi $t2,$t2,-1
lw $t3, 0($t0)
add $t5,$t5,$t3
addi $t0,$t0,4
bne $t2,$0,loop

Revisión del 16:54 24 oct 2014

Amb el nom de MIPS (Microprocessor without Interlocked Pipeline Stages) es coneix a tota una família de microprocessadors d'arquitectura RISC desenvolupats per MIPS Technologies.

Els dissenys del MIPS són utilitzats en la línia de productes informàtics de SGI, en molts sistemes encastats, en dispositius per a Windows CE, routers Cisco, i videoconsoles com la Nintendo 64 o les Sony PlayStation, PlayStation 2 i PlayStation Portable.

Les primeres arquitectures MIPS van ser implementades en 32 bits (generalment rutes de dades i registres de 32 bits d'ample), si bé versions posteriors van ser implementades en 64 bits. Existeixen cinc revisions compatibles cap enrere del conjunt d'instruccions del MIPS, anomenades MIPS I, MIPS II, MIPS III, MIPS IV i MIPS 32/64. En l'última d'elles, la MIPS 32/64 Release 2, es defineix a majors un conjunt de control de registres. Així mateix estan disponibles diverses "extensions", com ara la MIPS-3D, consistent en un simple conjunt d'instruccions SIMD en coma flotant dedicades a tasques 3D comuns, la MDMX (MaDMaX) composta per un conjunt més extens d'instruccions SIMD senceres que utilitzen els registres de coma flotant de 64 bits, la MIPS16 que afegeix compressió al flux d'instruccions per fer que els programes ocupin menys espai (presumptament com a resposta a la tecnologia de compressió Thumb de l'arquitectura ARM) o la recent MIPS MT que afegeix funcionalitats multithreading similars a la tecnologia HyperThreading dels processadors Intel Pentium 4.

A causa que els dissenyadors van crear un conjunt d'instruccions tan clar, els cursos sobre arquitectura de computadors en universitats i escoles tècniques sovint es basen en l'arquitectura MIPS. El disseny de la família de CPU MIPS influiria de manera important en altres arquitectures RISC posteriors com els DEC Alpha.

MIPS en la Wikipedia

Descripció

El processador MIPS va ser desenvolupat per a tindre un gran rendiment gràcies a la segmentació. La segmentació consisteix en dividir una instrucció en etapes i poder fer les primeres etape

Format d'instruccions

Type -31-                                 format (bits)                                 -0-
R opcode (6) rs (5) rt (5) rd (5) shamt (5) funct (6)
I opcode (6) rs (5) rt (5) immediate (16)
J opcode (6) address (26)

Llenguatge

Category Name Instruction syntax Meaning Format/opcode/funct Notes/Encoding
Arithmetic Add add $d,$s,$t $d = $s + $t R 0 2016 adds two registers, executes a trap on overflow
000000ss sssttttt ddddd--- --100000
Add unsigned addu $d,$s,$t $d = $s + $t R 0 2116 as above but ignores an overflow
000000ss sssttttt ddddd--- --100001
Subtract sub $d,$s,$t $d = $s - $t R 0 2216 subtracts two registers, executes a trap on overflow
000000ss sssttttt ddddd--- --100010
Subtract unsigned subu $d,$s,$t $d = $s - $t R 0 2316 as above but ignores an overflow
000000ss sssttttt ddddd000 00100011
Add immediate addi $t,$s,C $t = $s + C (signed) I 816 - Used to add sign-extended constants (and also to copy one register to another: addi $1, $2, 0), executes a trap on overflow
001000ss sssttttt CCCCCCCC CCCCCCCC
Add immediate unsigned addiu $t,$s,C $t = $s + C (signed) I 916 - as above but ignores an overflow
001001ss sssttttt CCCCCCCC CCCCCCCC
Multiply mult $s,$t LO = (($s * $t) << 32) >> 32;
HI = ($s * $t) >> 32;
R 0 1816 Multiplies two registers and puts the 64-bit result in two special memory spots - LO and HI. Alternatively, one could say the result of this operation is: (int HI,int LO) = (64-bit) $s * $t . See mfhi and mflo for accessing LO and HI regs.
Multiply unsigned multu $s,$t LO = (($s * $t) << 32) >> 32;
HI = ($s * $t) >> 32;
R 0 1916 Multiplies two registers and puts the 64-bit result in two special memory spots - LO and HI. Alternatively, one could say the result of this operation is: (int HI,int LO) = (64-bit) $s * $t . See mfhi and mflo for accessing LO and HI regs.
Divide div $s, $t LO = $s / $t     HI = $s % $t R 0 1A16 Divides two registers and puts the 32-bit integer result in LO and the remainder in HI.<ref name="uidaho"/>
Divide unsigned divu $s, $t LO = $s / $t     HI = $s % $t R 0 1B16 Divides two registers and puts the 32-bit integer result in LO and the remainder in HI.
Data Transfer
Load word lw $t,C($s) $t = Memory[$s + C] I 2316 - loads the word stored from: MEM[$s+C] and the following 3 bytes.
Load halfword lh $t,C($s) $t = Memory[$s + C] (signed) I 2116 - loads the halfword stored from: MEM[$s+C] and the following byte. Sign is extended to width of register.
Load halfword unsigned lhu $t,C($s) $t = Memory[$s + C] (unsigned) I 2516 - As above without sign extension.
Load byte lb $t,C($s) $t = Memory[$s + C] (signed) I 2016 - loads the byte stored from: MEM[$s+C].
Load byte unsigned lbu $t,C($s) $t = Memory[$s + C] (unsigned) I 2416 - As above without sign extension.
Store word sw $t,C($s) Memory[$s + C] = $t I 2B16 - stores a word into: MEM[$s+C] and the following 3 bytes. The order of the operands is a large source of confusion.
Store half sh $t,C($s) Memory[$s + C] = $t I 2916 - stores the least-significant 16-bit of a register (a halfword) into: MEM[$s+C].
Store byte sb $t,C($s) Memory[$s + C] = $t I 2816 - stores the least-significant 8-bit of a register (a byte) into: MEM[$s+C].
Load upper immediate lui $t,C $t = C << 16 I F16 - loads a 16-bit immediate operand into the upper 16-bits of the register specified. Maximum value of constant is 216-1
Move from high mfhi $d $d = HI R 0 1016 Moves a value from HI to a register. Do not use a multiply or a divide instruction within two instructions of mfhi (that action is undefined because of the MIPS pipeline).
Move from low mflo $d $d = LO R 0 1216 Moves a value from LO to a register. Do not use a multiply or a divide instruction within two instructions of mflo (that action is undefined because of the MIPS pipeline).
Move from Control Register mfcZ $t, $d $t = Coprocessor[Z].ControlRegister[$d] R 0 Moves a 4 byte value from Coprocessor Z Control register to a general purpose register. Sign extension.
Move to Control Register mtcZ $t, $d Coprocessor[Z].ControlRegister[$d] = $t R 0 Moves a 4 byte value from a general purpose register to a Coprocessor Z Control register. Sign extension.
Logical And and $d,$s,$t $d = $s & $t R 0 2416 Bitwise and
000000ss sssttttt ddddd--- --100100
And immediate andi $t,$s,C $t = $s & C I C16 - Leftmost 16 bits are padded with 0's
001100ss sssttttt CCCCCCCC CCCCCCCC
Or or $d,$s,$t $d = $s | $t R 0 2516 Bitwise or
Or immediate ori $t,$s,C $t = $s | C I D16 - Leftmost 16 bits are padded with 0's
Exclusive or xor $d,$s,$t $d = $s ^ $t R 0 2616
Nor nor $d,$s,$t $d = ~ ($s | $t) R 0 2716 Bitwise nor
Set on less than slt $d,$s,$t $d = ($s < $t) R 0 2A16 Tests if one register is less than another.
Set on less than immediate slti $t,$s,C $t = ($s < C) I A16 - Tests if one register is less than a constant.
Bitwise Shift Shift left logical sll $d,$t,shamt $d = $t << shamt R 0 0 shifts shamt number of bits to the left (multiplies by <math>2^{shamt} </math>)
Shift right logical srl $d,$t,shamt $d = $t >> shamt R 0 216 shifts shamt number of bits to the right - zeros are shifted in (divides by <math>2^{shamt} </math>). Note that this instruction only works as division of a two's complement number if the value is positive.
Shift right arithmetic sra $d,$t,shamt <math>\scriptstyle $d = $t >> shamt + \left(\left(\sum_{n=1}^{\text{shamt}}2^{32-n}\right)\cdot \left($t>>31\right)\right) </math> R 0 316 shifts shamt number of bits - the sign bit is shifted in (divides 2's complement number by <math>2^{shamt} </math>)
Conditional branch Branch on equal beq $s,$t,C if ($s == $t) go to PC+4+4*C I 416 - Goes to the instruction at the specified address if two registers are equal.
000100ss sssttttt CCCCCCCC CCCCCCCC
Branch on not equal bne $s,$t,C if ($s != $t) go to PC+4+4*C I 516 - Goes to the instruction at the specified address if two registers are not equal.
Unconditional jump Jump j C PC = PC+4[31:28] . C*4 J 216 - Unconditionally jumps to the instruction at the specified address.
Jump register jr $s goto address $s R 0 816 Jumps to the address contained in the specified register
Jump and link jal C $31 = PC + 4; PC = PC+4[31:28] . C*4 J 316 - For procedure call - used to call a subroutine, $31 holds the return address; returning from a subroutine is done by: jr $31. Return address is PC + 8, not PC + 4 due to the use of a branch delay slot which forces the instruction after the jump to be executed

Note: In MIPS assembly code, the offset for branching instructions can be represented by a label elsewhere in the code.

Note: There is no corresponding load lower immediate instruction; this can be done by using addi (add immediate, see below) or ori (or immediate) with the register $0 (whose value is always zero). For example, both addi $1, $0, 100 and ori $1, $0, 100 load the decimal value 100 into register $1.

Note: Subtracting an immediate can be done with adding the negation of that value as the immediate.

MIPS has 32 floating-point registers. Two registers are paired for double precision numbers. Odd numbered registers cannot be used for arithmetic or branching, just as part of a double precision register pair.

Category Name Instruction syntax Meaning Format/opcode/funct Notes/Encoding
Arithmetic FP add single add.s $x,$y,$z $x = $y + $z Floating-Point add (single precision)
FP subtract single sub.s $x,$y,$z $x = $y - $z Floating-Point subtract (single precision)
FP multiply single mul.s $x,$y,$z $x = $y * $z Floating-Point multiply (single precision)
FP divide single div.s $x,$y,$z $x = $y / $z Floating-Point divide (single precision)
FP add double add.d $x,$y,$z $x = $y + $z Floating-Point add (double precision)
FP subtract double sub.d $x,$y,$z $x = $y - $z Floating-Point subtract (double precision)
FP multiply double mul.d $x,$y,$z $x = $y * $z Floating-Point multiply (double precision)
FP divide double div.d $x,$y,$z $x = $y / $z Floating-Point divide (double precision)
Data Transfer Load word coprocessor lwcZ $x,CONST ($y) Coprocessor[Z].DataRegister[$x] = Memory[$y + CONST] I Loads the 4 byte word stored from: MEM[$y+CONST] into a Coprocessor data register. Sign extension.
Store word coprocessor swcZ $x,CONST ($y) Memory[$y + CONST] = Coprocessor[Z].DataRegister[$x] I Stores the 4 byte word held by a Coprocessor data register into: MEM[$y+CONST]. Sign extension.
Logical FP compare single (eq,ne,lt,le,gt,ge) c.lt.s $f2,$f4 if ($f2 < $f4) cond=1; else cond=0 Floating-point compare less than single precision
FP compare double (eq,ne,lt,le,gt,ge) c.lt.d $f2,$f4 if ($f2 < $f4) cond=1; else cond=0 Floating-point compare less than double precision
Branch branch on FP true bc1t 100 if (cond == 1) go to PC+4+100 PC relative branch if FP condition
branch on FP false bc1f 100 if (cond == 0) go to PC+4+100 PC relative branch if not condition


These instructions are accepted by the MIPS assembler, although they are not real instructions within the MIPS instruction set. Instead, the assembler translates them into sequences of real instructions.

Name instruction syntax Real instruction translation meaning
Move move $rt,$rs addi $rt,$rs,0 R[rt]=R[rs]
Clear clear $rt add $rt,$zero,$zero R[rt]=0
Not not $rt, $rs nor $rt, $rs, $zero R[rt]=~R[rs]
Load Address la $rd, LabelAddr lui $rd, LabelAddr[31:16]; ori $rd,$rd, LabelAddr[15:0] $rd = Label Address
Load Immediate li $rd, IMMED[31:0] lui $rd, IMMED[31:16]; ori $rd,$rd, IMMED[15:0] $rd = 32 bit Immediate value
Branch unconditionally b Label beq $zero,$zero,Label if(R[rs]==R[rt]) PC=Label
Branch and link bal $rs,Label bgezal $zero,Label if(R[rs]>=0) PC=Label
Branch if greater than bgt $rs,$rt,Label slt $at,$rt,$rs; bne $at,$zero,Label if(R[rs]>R[rt]) PC=Label
Branch if less than blt $rs,$rt,Label slt $at,$rs,$rt; bne $at,$zero,Label if(R[rs]<R[rt]) PC=Label
Branch if greater than or equal bge $rs,$rt,Label slt $at,$rs,$rt; beq $at,$zero,Label if(R[rs]>=R[rt]) PC=Label
Branch if less than or equal ble $rs,$rt,Label slt $at,$rt,$rs; beq $at,$zero,Label if(R[rs]<=R[rt]) PC=Label
Branch if greater than unsigned bgtu $rs,$rt,Label if(R[rs]>R[rt]) PC=Label
Branch if greater than zero bgtz $rs,Label if(R[rs]>0) PC=Label
Branch if equal to zero beqz $rs,Label if(R[rs]==0) PC=Label
Multiplies and returns only first 32 bits mul $d, $s, $t mult $s, $t; mflo $d $d = $s * $t
Divides and returns quotient div $d, $s, $t div $s, $t; mflo $d $d = $s / $t
Divides and returns remainder rem $d, $s, $t div $s, $t; mfhi $d $d = $s % $t

The hardware architecture specifies that:

  • General purpose register $0 always returns a value of 0.
  • General purpose register $31 is used as the link register for jump and link instructions.
  • HI and LO are used to access the multiplier/divider results, accessed by the mfhi (move from high) and mflo commands.

These are the only hardware restrictions on the usage of the general purpose registers.

The various MIPS tool-chains implement specific calling conventions that further restrict how the registers are used. These calling conventions are totally maintained by the tool-chain software and are not required by the hardware.

Registers for O32 Calling Convention
Name Number Use Callee must preserve?
$zero $0 constant 0 Plantilla:N/A
$at $1 assembler temporary Plantilla:No
$v0–$v1 $2–$3 values for function returns and expression evaluation Plantilla:No
$a0–$a3 $4–$7 function arguments Plantilla:No
$t0–$t7 $8–$15 temporaries Plantilla:No
$s0–$s7 $16–$23 saved temporaries Plantilla:Yes
$t8–$t9 $24–$25 temporaries Plantilla:No
$k0–$k1 $26–$27 reserved for OS kernel Plantilla:N/A
$gp $28 global pointer Plantilla:Yes
$sp $29 stack pointer Plantilla:Yes
$fp $30 frame pointer Plantilla:Yes
$ra $31 return address Plantilla:N/A
Registers for N32 and N64 Calling Conventions<ref>ftp://ftp.linux-mips.org/pub/linux/mips/doc/ABI2/MIPS-N32-ABI-Handbook.pdf</ref>
Name Number Use Callee must preserve?
$zero $0 constant 0 Plantilla:N/A
$at $1 assembler temporary Plantilla:No
$v0–$v1 $2–$3 values for function returns and expression evaluation Plantilla:No
$a0–$a7 $4–$11 function arguments Plantilla:No
$t4–$t7 $12–$15 temporaries Plantilla:No
$s0–$s7 $16–$23 saved temporaries Plantilla:Yes
$t8–$t9 $24–$25 temporaries Plantilla:No
$k0–$k1 $26–$27 reserved for OS kernel Plantilla:N/A
$gp $28 global pointer Plantilla:Yes
$sp $29 stack pointer Plantilla:Yes
$s8 $30 frame pointer Plantilla:Yes
$ra $31 return address Plantilla:N/A

Registers that are preserved across a call are registers that (by convention) will not be changed by a system call or procedure (function) call. For example, $s-registers must be saved to the stack by a procedure that needs to use them, and $sp and $fp are always incremented by constants, and decremented back after the procedure is done with them (and the memory they point to). By contrast, $ra is changed automatically by any normal function call (ones that use jal), and $t-registers must be saved by the program before any procedure call (if the program needs the values inside them after the call).

Exemples d'assemblador per a MIPS

Aquests exemples estan fets per a funcionar en el simulador Simula3ms. És possible que en altres simuladors no siga exàctament aquesta sintaxi.

Hola Mundo:

 .data
 hola: .asciiz "hola mundo"
 .text
 .globl main
 main:   
 la $a0, hola        #$a0=dirección de memoria donde empieza "cadena"
 li $v0, 4             #Cargamos el código de operación de impresión 
                      #de cadenas de texto
 syscall              #print_string


Traure la mitjana aritmètica de tres números en registres:

.text
.globl main
main:
addi $t1,$0,20
addi $t2,$0,30
addi $t3,$0,40
add $t4,$0,$t1
add $t4,$t4,$t2
add $t4,$t4,$t3
addi $t5,$t5,3
div $t4,$t5
mflo $t6

Sumar els elements d'un array de memòria:

.data
array: .word 10,20,30,40,50
count: .word 5

.text
.globl main
main:
	la $t0,array 
	la $t1, count
	lw $t2, 0($t1)
	addi $t5,$0,0
loop:
	addi $t2,$t2,-1
	lw $t3, 0($t0)
	add $t5,$t5,$t3
	addi $t0,$t0,4
	bne $t2,$0,loop