Saltar al contenido

¿Cómo calcular la dirección de destino de salto y la dirección de destino de rama?

Presta atención porque en este artículo hallarás el resultado que buscas.

Solución:

(En los diagramas y el texto a continuación, PC es la dirección de la propia instrucción de bifurcación. PC+4 es el final de la propia instrucción de bifurcación y el inicio de la ranura de retardo de bifurcación. Excepto en el diagrama de salto absoluto.)

1. Cálculo de la dirección de la sucursal

En la rama MIPS, la instrucción solo tiene un desplazamiento de 16 bits para determinar la siguiente instrucción. Necesitamos un registro agregado a este valor de 16 bits para determinar la siguiente instrucción y este registro está realmente implícito en la arquitectura. Es un registro de PC, ya que la PC se actualiza (PC + 4) durante el ciclo de búsqueda para que contenga la dirección de la siguiente instrucción.

También limitamos la distancia de la rama a -2^15 to +2^15 - 1 instrucción de la (instrucción después de la) instrucción de bifurcación. Sin embargo, esto no es un problema real ya que la mayoría de las sucursales son locales de todos modos.

Así que paso a paso:

  • Sign amplía el valor de desplazamiento de 16 bits para conservar su valor.
  • Multiplique el valor resultante por 4. La razón detrás de esto es que si vamos a bifurcar alguna dirección y la PC ya está alineada con la palabra, entonces el valor inmediato también tiene que estar alineado con la palabra. Sin embargo, no tiene sentido alinear la palabra inmediata porque estaríamos desperdiciando dos bits bajos al forzarlos a ser 00.
  • Ahora tenemos un desplazamiento relativo de 32 bits. Agregue este valor a PC + 4 y esa es la dirección de su sucursal.

Cálculo de la dirección de la sucursal


2. Cálculo de dirección de salto

Para la instrucción de salto, MIPS tiene solo 26 bits para determinar la ubicación del salto. Los saltos son relativos a PC en MIPS. Al igual que la rama, el valor de salto inmediato debe estar alineado con la palabra; por lo tanto, necesitamos multiplicar la dirección de 26 bits por cuatro.

De nuevo paso a paso:

  • Multiplique el valor de 26 bits por 4.
  • Dado que estamos saltando en relación con el valor de PC + 4, concatenamos los primeros cuatro bits del valor de PC + 4 a la izquierda de nuestra dirección de salto.
  • La dirección resultante es el valor de salto.

En otras palabras, reemplace los 28 bits inferiores del PC + 4 con los 26 bits inferiores de la instrucción recuperada desplazados a la izquierda en 2 bits.

ingrese la descripción de la imagen aquí

Los saltos están relacionados con la región de la ranura de retardo de rama, no necesariamente la rama en sí. En el diagrama anterior, la PC ya ha avanzado a la ranura de retardo de rama antes del cálculo del salto. (En un pipeline de 5 etapas de RISC clásico, el BD se extrajo en el mismo ciclo en el que se decodifica el salto, de modo que la siguiente dirección de instrucción de PC + 4 ya está disponible para saltos y bifurcaciones, y el cálculo relativo a la propia dirección del salto sería han requerido trabajo extra para guardar esa dirección).

Fuente: Diapositivas del curso CS 224 de la Universidad Bilkent

Por lo general, no tiene que preocuparse por calcularlos, ya que su ensamblador (o enlazador) se encargará de hacer los cálculos correctamente. Digamos que tienes una pequeña función:


func:
  slti $t0, $a0, 2
  beq $t0, $zero, cont
  ori $v0, $zero, 1
  jr $ra
cont:
  ...
  jal func
  ... 

Al traducir el código anterior en un flujo binario de instrucciones, el ensamblador (o el enlazador si primero lo ensambló en un archivo de objeto) se determinará en qué parte de la memoria residirá la función (ignoremos el código independiente de la posición por ahora). El lugar en la memoria donde residirá generalmente se especifica en el ABI o se le proporciona si está usando un simulador (como SPIM, que carga el código en 0x400000 – tenga en cuenta que el enlace también contiene una buena explicación del proceso).

Suponiendo que estamos hablando del caso SPIM y nuestra función es la primera en la memoria, el slti la instrucción residirá en 0x400000, el beq en 0x400004 y así. ¡Ya casi llegamos! Para el beq instruir el dirección de destino de la sucursal es el de cont (0x400010) mirando una referencia de instrucción MIPS, vemos que está codificada como un inmediato con signo de 16 bits en relación con la siguiente instrucción (dividido por 4, ya que todas las instrucciones deben residir en una dirección alineada de 4 bytes de todos modos).

Es decir:

Current address of instruction + 4 = 0x400004 + 4 = 0x400008
Branch target = 0x400010
Difference = 0x400010 - 0x400008 = 0x8
To encode = Difference / 4 = 0x8 / 4 = 0x2 = 0b10

Codificación de beq $t0, $zero, cont

0001 00ss ssst tttt iiii iiii iiii iiii
---------------------------------------
0001 0001 0000 0000 0000 0000 0000 0010

Como puede ver, puede ramificarse hacia adentro -0x1fffc .. 0x20000 bytes. Si por alguna razón necesita saltar más, puede usar un trampolín (un salto incondicional al objetivo real colocado dentro del límite dado).

Saltar direcciones de destino están, a diferencia de las direcciones de destino de las sucursales, codificadas mediante la absoluto dirección (nuevamente dividida por 4). Dado que la codificación de instrucciones usa 6 bits para el código de operación, esto solo deja 26 bits para la dirección (efectivamente 28 dado que los 2 últimos bits serán 0), por lo tanto, los 4 bits más significativos del registro de PC se usan al formar la dirección ( no importará a menos que tenga la intención de cruzar los límites de 256 MB).

Volviendo al ejemplo anterior, la codificación para jal func es:

Destination address = absolute address of func = 0x400000
Divided by 4 = 0x400000 / 4 = 0x100000
Lower 26 bits = 0x100000 & 0x03ffffff = 0x100000 = 0b100000000000000000000

0000 11ii iiii iiii iiii iiii iiii iiii
---------------------------------------
0000 1100 0001 0000 0000 0000 0000 0000

Puede verificar esto rápidamente y jugar con diferentes instrucciones, utilizando este ensamblador MIPS en línea con el que me encontré (tenga en cuenta que no admite todos los códigos de operación, por ejemplo slti, así que lo cambié a slt aquí):

00400000:     ;  func:
00400000: 0000002a  ;  slt $t0, $a0, 2
00400004: 11000002  ;  beq $t0, $zero, cont
00400008: 34020001  ;  ori $v0, $zero, 1
0040000c: 03e00008  ;  jr $ra
00400010:     ;  cont:
00400010: 0c100000  ;  jal func

Si tienes alguna sospecha y capacidad de reaccionar nuestro reseña te sugerimos dejar una glosa y con placer lo estudiaremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *