jalr

jalr

RISC-V Ассемблер Ссылка

lyszt.net охватывает jalr и другие инструкции RISC-V более подробно.

Формат кодирования

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

Описание

jalr принадлежит к тому же семейству, что и jal, где r означает регистр. Обе инструкции выполняют переход и сохраняют адрес возврата, как описано на странице jal. Различие заключается в цели перехода. jal выполняет переход на метку, фиксированную при написании программы, тогда как jalr выполняет переход на адрес, хранящийся в регистре, что позволяет вычислять назначение во время выполнения.

Именно это позволяет функции возвращаться. Вызывающий помещает адрес возврата в регистр ra, а функция возвращается, используя jalr для достижения адреса в ra. Инструкция ret — это jalr на ra.

Та же возможность применима всякий раз, когда назначение заранее неизвестно. Она охватывает вызовы функции, адрес которой был передан, и выбор среди процедур, перечисленных в таблице адресов, — именно так реализуется большой оператор switch или диспетчеризация интерпретатора.

Согласно руководству RISC-V, jalr добавляет знаково-расширенный 12-битный immediate к регистру rs1, затем очищает младший значащий бит результата. Он сохраняет адрес следующей инструкции, pc плюс 4, в rd, и x0 может служить назначением, когда адрес возврата не нужен. lui, за которым следует jalr, достигает любого 32-битного абсолютного адреса, а auipc, за которым следует jalr, достигает любого 32-битного адреса относительно pc. Обе инструкции перехода вызывают исключение, если целевой адрес не выровнен по границе четырёх байтов.

Формат jalr приведён ниже. Он выполняет переход на адрес в регистре rs плюс необязательное небольшое смещение и сохраняет адрес возврата в rd.

jalr rd, rs, offset

Как и в случае с jal, записываемый регистр перезаписывается, поэтому требуется та же осторожность в отношении сохранения ra.

Пример

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