jalr

jalr

Assembly RISC-V Referência

lyszt.net aborda jalr e outras instruções RISC-V com mais detalhes.

Formato de codificação

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

Descrição

jalr pertence à mesma família que jal, com o r significando registrador. Ambas as instruções saltam e armazenam um endereço de retorno, como descrito na página jal. A diferença é o alvo do salto. jal salta para um rótulo fixado quando o programa é escrito, enquanto jalr salta para um endereço mantido em um registrador, o que permite que o destino seja calculado em tempo de execução.

É isso que permite que uma função retorne. O chamador coloca um endereço de retorno no registrador ra, e a função retorna usando jalr para alcançar o endereço em ra. A instrução ret é um jalr para ra.

A mesma capacidade se aplica sempre que o destino é desconhecido antecipadamente. Ela cobre chamadas a uma função cujo endereço foi passado, e a seleção entre rotinas listadas em uma tabela de endereços, que é como um grande comando switch ou um interpretador despacha.

De acordo com o manual RISC-V, jalr adiciona o imediato de 12 bits com extensão de sinal ao registrador rs1, e então limpa o bit menos significativo do resultado. Ele armazena o endereço da próxima instrução, pc mais 4, em rd, e x0 pode servir como destino quando nenhum endereço de retorno é necessário. Um lui seguido de jalr alcança qualquer endereço absoluto de 32 bits, e um auipc seguido de jalr alcança qualquer endereço relativo ao pc de 32 bits. Ambas as instruções de salto geram uma exceção se o endereço de destino não estiver alinhado a um limite de quatro bytes.

O formato de jalr aparece abaixo. Ele salta para o endereço no registrador rs mais um pequeno deslocamento opcional, e armazena o endereço de retorno em rd.

jalr rd, rs, offset

Assim como jal, o registrador que ele escreve é sobrescrito, então o mesmo cuidado com a preservação de ra se aplica.

Exemplo

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