jalr

jalr

Ensamblador RISC-V Referencia

lyszt.net cubre jalr y otras instrucciones RISC-V con más detalle.

Formato de codificación

R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

Descripción

jalr pertenece a la misma familia que jal, donde la r significa registro. Ambas instrucciones saltan y almacenan una dirección de retorno, como se describe en la página de jal. La diferencia es el destino del salto. jal salta a una etiqueta fijada cuando se escribe el programa, mientras que jalr salta a una dirección contenida en un registro, lo que permite que el destino se calcule en tiempo de ejecución.

Esto es lo que permite que una función retorne. El llamador coloca una dirección de retorno en el registro ra, y la función vuelve usando jalr para alcanzar la dirección en ra. La instrucción ret es un jalr a ra.

La misma capacidad se aplica siempre que el destino sea desconocido de antemano. Cubre llamadas a una función cuya dirección se pasó como argumento, y la selección entre rutinas listadas en una tabla de direcciones, que es como se despacha una gran sentencia switch o un intérprete.

Según el manual de RISC-V, jalr suma el inmediato de 12 bits con extensión de signo al registro rs1, luego borra el bit menos significativo del resultado. Almacena la dirección de la siguiente instrucción, pc más 4, en rd, y x0 puede servir como destino cuando no se necesita una dirección de retorno. Un lui seguido de jalr alcanza cualquier dirección absoluta de 32 bits, y un auipc seguido de jalr alcanza cualquier dirección relativa al pc de 32 bits. Ambas instrucciones de salto generan una excepción si la dirección de destino no está alineada a un límite de cuatro bytes.

El formato de jalr aparece a continuación. Salta a la dirección en el registro rs más un pequeño desplazamiento opcional, y almacena la dirección de retorno en rd.

jalr rd, rs, offset

Al igual que con jal, el registro que escribe se sobrescribe, por lo que se aplica el mismo cuidado respecto a preservar ra.

Ejemplo

la t0, target
jalr ra, t0, 0   # jump to target; ra holds the return address