Codificación de Instrucciones



Ciencias de la Computación III

Diego José Figueroa




Programa almacenado


Programa almacenado


  • Las instrucciones se tratan igual que los datos.
  • Las instrucciones se representan como secuencias de bits.
  • Leemos y cargamos programas completos, como si fueran datos.
  • ¿Consecuencias?

Direcciones


  • Para que esto funcione, necesitamos una forma de ubicar una instrucción en memoria.

  • A cada instrucción se le asigna una dirección.

  • Program Counter ($pc)
    • IAC (Instruction Address Counter) para Intel.

RISC


  • Optamos por un diseño simple
    • Pocas instrucciones
    • Muchos registros
    • Operaciones sencillas
    • Codificación de instrucciones simple
      • Las instrucciones se codifican más o menos igual.
      • Utilizan un tamaño fijo
      • En general, bastante sencillo.
    • Lo contrario de CISC

¿Por qué muchos registros?


  • Ventajoso para los compiladores
    • Permite implementar optimizaciones complejas.
    • Cálculos intermedios.
    • Valores temporales.
    • Mejorar la calidad del programa.

  • Ventajoso para los programadores/diseñadores
    • Permite realizar más cálculos sin recurrir a memoria.
    • Computadoras con mejor rendimiento.

Más razones...


  • ILP (Instruction Level Parallelism)
    • Si dos instrucciones no utilizan los mismos registros, se pueden ejecutar en paralelo.
    • Con más registros, es más fácil para el compilador lograr esto.
    • Con más registros, la probabilidad de repetir registros disminuye.




¿Por qué preferimos 

instrucciones simples?

Instrucciones Simples


  • Hacer poco, pero hacerlo bien.

  • Pocas instrucciones, pero que se ejecuten muy rápido.
    • Escogemos instrucciones que permitan hacer composiciones.
    • Más fácil si tenemos muchos registros.

  • La mayor parte del assembler lo escribe un compilador
    • Los compiladores usan instrucciones simples mayormente.
    • Instrucciones complejas no las aprovechan.

Más razones...


  • El hardware es difícil y costoso de diseñar
    • Mientras más complejo es el diseño
      • se complica la construcción
      • se incrementan los costos
      • no necesariamente se mejora el desempeño







    add $s0 $s0 $0

¿Por qué codificar?


  • El procesador NO entiende assembler.

  • El assembler es una abstracción, facilita pasar de alto nivel a bajo nivel.

  • Es necesario traducirlo a algo que el procesador pueda manejar.

El procesador sólo entiende 0s y 1s

¿Cómo codificar?



  • Queremos un sistema simple

  • Tamaño fijo
    • Todas las instrucciones ocupen la misma cantidad de bits.
    • 32 bits es un buen número.

  • Formato de 3 registros
    • 1 destino, y 2 operandos

¿Cómo codificar?


  • Además, debe ser fácil de decodificar
    • Las instrucciones se deben codificar de forma parecida.
    • A esto se le llama formato.

  • Dividir la codificación en campos
    • Una parte para el destino, otra para los operandos, etc.

  • Suficiente espacio para valores inmediatos
    • 16 bits es un buen tamaño
    • Ej: offsets para los corrimientos, lecturas/escrituras de memoria.




Codificación de 

instrucciones de MIPS

3 formatos


Cosas en común


  • Los 3 formatos ocupan 32 bits.

  • Los primeros 6 bits indican la operación:
    • Además, nos indican qué formato utilizar
    • Quedan códigos libres, para agregar instrucciones.

Tipo J




  • 6 bits para la operación (opcode)
  • 26 bits para la dirección destino
    • Estas instrucciones deben ( y están) alinearse en fronteras de 4 bytes (word aligned).
    • ¿26 bits? ¿direcciones de 32 bits?
      • bits 28 - 31 se copian de $PC (MSB)
      • bits   0 - 1 son siempre 0.

¿Para qué se usa Tipo J?


  • Saltos incondicionales
    • No hay espacio para registros
    • Por lo que no nos sirve para branches.
    • Pero sirve bien para saltos incondicionales.

  • Ejemplo:
    • j label
    • jal label

Tipo R




  • 6 bits para la operación (0 para Tipo R)
  • 5 bits para el 1er registro fuente (rs)
  • 5 bits para el 2do registro fuente (rt)
  • 5 bits para el registro destino (rd)
  • 5 bits para la cantidad de bits a correr (shift amount)
  • 6 bits que identifica la función a ejecutar

Tipo R


  • El opcode SIEMPRE es 0, (00000).
  • El primer registro fuente es un valor entre 0 y 31.
    • Tenemos 32 registros, lo justo con 5 bits.
  • El 2do registro fuente también ocupa 5 bits.
  • Lo mismo para el registro destino.

  • Número de bits a correr (shamt)
    • Utilizado en instrucciones de corrimiento.
    • 0 en cualquier otro caso.

  • 6 bits para indicar la función
    • Podemos tener hasta 64 funciones
    • La suma por ejemplo, es el func-code 32.

Tipo R


  • El func-code nos permite tener hasta 127 instrucciones
    • 63 indicadas por el opcode
    • 64 indicadas por el func-code (todas Tipo R)

  • shamt, 5 bits son suficientes
    • Nunca corremos más de 32 bits.
    • Sólo se usa para corrimientos constantes.
    • Corrimientos variables, se determina en base a un registro.

Ejemplo


          add $t0 $t1 $t2

opcode    = 0
rd        = 8
rs        = 9
rt        = 10
shamt     = 0
func-code = 32

Tipo I




  • 6 bits para opcode
  • 5 bits para registro fuente (rs)
  • 5 bits para registro destino (rt)
  • 16 bits para una constante
    • Puede ser una dirección o un valor inmediato.

Tipo I


  • Utilizado para instrucciones con valores inmediatos
    • add $rt $rs imm

  • También para branches
    • beq $rt $rs label

  • También para accesos a memoria
    • lw $rt offset($rs)

Branches


  • Utiliza un inmediato de 16 bits en notación con signo.
  • Si no se cumple la condición,
    • $PC = $PC + 4
  • Si se cumple la condición,
    • $PC = $PC + 4 + imm << 2

  • Salto relativo a la instrucción siguiente
    • Imm indica la cantidad de instrucciones a saltar
    • hacia arriba, o hacia abajo.

Ejemplo


        $addi $t0 $t1 -50


opcode     = 8
rt         = 9
rs         = 8
imm        = -50


Más ejemplos...


        addi $12 $10 0xf3d
       001000 01010 01110 0000 111100111101


           add $3 $4 $5
       000000 00100 00101 00011 00000 10000


      jal foo (foo = 0xf0f0f0)
       000011 0000 1111 0000 1111 0000 1111 00

Decodificación


  • ¿Cómo pasamos de 0s y 1s a ensamblador?

  • Primero:
    • Identificar el formato en base al opcode.
    • Utilizar el formato adecuado, para identificar los campos.
    • Escribir la instrucción de MIPS correspondiente.

Ejemplo


[0x00400000] 0x00001025
[0x00400004] 0x0005402A
[0x00400008] 0x11000003
[0x0040000C] 0x00441020
[0x00400010] 0x20A5FFFF
[0x00400014] 0x08100001

Ejemplo


00000000000000000001000000100101
00000000000001010100000000101010
00010001000000000000000000000011
00000000010001000001000000100000
00100000101001011111111111111111
00001000000100000000000000000001

Ejemplo


Identificar el tipo

00000000000000000001000000100101
00000000000001010100000000101010
00010001000000000000000000000011
00000000010001000001000000100000
00100000101001011111111111111111
00001000000100000000000000000001

Ejemplo


R  000000 00000 00000 00010 00000 100101
R 000000 00000 00101 01000 00000101010
J 000100 01000 00000 0000000000000011
R 000000 00010 00100 00010 00000 100000
I 001000 00101 00101 1111111111111111
J 000010 00000100000000000000000001

Ejemplo


Ejemplo


[0x00400000] 	or	$2, $0, $0
[0x00400004] slt $8, $0, $5
[0x00400008] beq $8, $0, 3
[0x0040000C] add $2, $2, $4
[0x00400010] addi $5, $5, -1
[0x00400014] j 0x00400004

Ejemplo


or		$v0, $0, $0
loop:
slt $t0, $0, $5
beq $t0, $0, exit
add $v0, $v0, $a0
addi $a1, $a1, -1
j loop
exit:

TAL vs MAL


  • True Assembly Language
  • MIPS Assembly Language

  • MAL incluye pseudo-instrucciones
    • move
    • la
    • ror
    • mul
    • ...

  • Sólo instrucciones de TAL tienen una traducción a binario.

TAL vs MAL


  • la $rd label

  • Si el valor de label cabe en 16 bits
    • addi  $rd $0 *label

  • Si el valor de label NO cabe en 16 bits
    • lui $rd <parte_alta_de_label>
    • ori $rd <parte_baja_de_label>

TAL vs MAL


  • ¿Cómo identifica el ensamblador una pseudo instrucción?
    • Lista de instrucciones no existentes (move, ror, etc.)
    • Casos especiales (operador incorrecto, etc.)

  • ¿Cómo convierte la instrucción a MAL?
    • Reemplaza por una composición de instrucciones reales.
    • Utiliza $at como registro temporal de ser necesario.

TAL vs MAL




addi $t0, $t1, 40000
beq $s0, 10, exit
sub $t0, $t1, 1


¿Cuáles son reales?

TAL vs MAL




addi $t0, $t1, 40000
beq $s0, 10, exit
sub $t0, $t1, 1

TAL vs MAL




addi $t0, $t1, 40000
beq $s0, 10, exit
sub $t0, $t1, 1

TAL vs MAL




addi $t0, $t1, 40000
beq $s0, 10, exit
sub $t0, $t1, 1

Title

12 - Codificación de Instrucciones

By Diego Figueroa

12 - Codificación de Instrucciones

  • 4,475