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