diff --git a/riscv/src/compiler.rs b/riscv/src/compiler.rs index 5881bd200..0155906fa 100644 --- a/riscv/src/compiler.rs +++ b/riscv/src/compiler.rs @@ -1264,8 +1264,20 @@ fn process_instruction(instr: &str, args: &[Argument], coprocessors: &CoProcesso vec![format!("tmp1 <== jump_dyn({rs});")] } "jal" => { - let (_rd, _label) = rl(args); - todo!(); + if let [label] = args { + vec![format!( + "x1 <== jump({});", + argument_to_escaped_symbol(label) + )] + } else { + let (rd, label) = rl(args); + let statement = if rd.is_zero() { + format!("tmp1 <== jump({label})") + } else { + format!("{rd} <== jump({label})") + }; + vec![statement] + } } "jalr" => { // TODO there is also a form that takes more arguments diff --git a/riscv/tests/instruction_tests/README.md b/riscv/tests/instruction_tests/README.md index 7fc179f12..ddd14915c 100644 --- a/riscv/tests/instruction_tests/README.md +++ b/riscv/tests/instruction_tests/README.md @@ -1,10 +1,13 @@ Tests from https://github.com/riscv/riscv-tests/tree/master/isa/ Powdr partially implements riscv32imac userspace ISA. One major difference is -that our zkVM "text" section doesn't have a 1-to-1 correspondence to the RISC-V -instructions section, so we don't support any kind of arithmetic over `.text` -label and addresses, nor alignment or spacing directives in `.text` sections. -Most unsupported instructions are related to this limitation. +that the code in our zkVM is interpreted at a higher abstraction level than the +binary representation of a RISC-V "text" section, and we use code labels as +absolute references, not relative to the PC like in binary format RISC-V. Thus +labels in code sections are treated as opaque values, and we don't support any +kind of arithmetic over `.text` label and addresses, nor alignment or spacing +directives in `.text` sections. Most unsupported instructions are related to +this limitation. Following there is a list of tests from the test suite that we do not support: @@ -13,18 +16,13 @@ Following there is a list of tests from the test suite that we do not support: - auipc This test is not supported because we don't support any kind of arithmetic over -`.text` label and addresses. - -Also, `lla` and `jal` (pseudo-)instructions are not yet implemented. +`.text` label and addresses, nor the `lla` pseudoinstruction. - fence_i -Our zkVM "text" is static. We don't support dynamic binary code, so it makes no -sense to implement `fence_i` instruction. - -- jal - -Not yet implemented. +This test is not supported because our zkVM "text" is static: we don't support +dynamic binary code or self modifying programs. Thus, our `fence.i` instruction +is just a nop. - jalr diff --git a/riscv/tests/instruction_tests/generated/jal.S b/riscv/tests/instruction_tests/generated/jal.S new file mode 100644 index 000000000..b689b7398 --- /dev/null +++ b/riscv/tests/instruction_tests/generated/jal.S @@ -0,0 +1,118 @@ +# 0 "sources/jal.S" +# 0 "" +# 0 "" +# 1 "/usr/include/stdc-predef.h" 1 3 4 +# 0 "" 2 +# 1 "sources/jal.S" +# See LICENSE for license details. + +#***************************************************************************** +# jal.S +#----------------------------------------------------------------------------- + +# Test jal instruction. + + +# 1 "sources/riscv_test.h" 1 +# 11 "sources/jal.S" 2 +# 1 "sources/test_macros.h" 1 + + + + + + +#----------------------------------------------------------------------- +# Helper macros +#----------------------------------------------------------------------- +# 20 "sources/test_macros.h" +# We use a macro hack to simpify code generation for various numbers +# of bubble cycles. +# 36 "sources/test_macros.h" +#----------------------------------------------------------------------- +# RV64UI MACROS +#----------------------------------------------------------------------- + +#----------------------------------------------------------------------- +# Tests for instructions with immediate operand +#----------------------------------------------------------------------- +# 92 "sources/test_macros.h" +#----------------------------------------------------------------------- +# Tests for vector config instructions +#----------------------------------------------------------------------- +# 120 "sources/test_macros.h" +#----------------------------------------------------------------------- +# Tests for an instruction with register operands +#----------------------------------------------------------------------- +# 148 "sources/test_macros.h" +#----------------------------------------------------------------------- +# Tests for an instruction with register-register operands +#----------------------------------------------------------------------- +# 242 "sources/test_macros.h" +#----------------------------------------------------------------------- +# Test memory instructions +#----------------------------------------------------------------------- +# 319 "sources/test_macros.h" +#----------------------------------------------------------------------- +# Test branch instructions +#----------------------------------------------------------------------- +# 404 "sources/test_macros.h" +#----------------------------------------------------------------------- +# Test jump instructions +#----------------------------------------------------------------------- +# 433 "sources/test_macros.h" +#----------------------------------------------------------------------- +# RV64UF MACROS +#----------------------------------------------------------------------- + +#----------------------------------------------------------------------- +# Tests floating-point instructions +#----------------------------------------------------------------------- +# 569 "sources/test_macros.h" +#----------------------------------------------------------------------- +# Pass and fail code (assumes test num is in x28) +#----------------------------------------------------------------------- +# 581 "sources/test_macros.h" +#----------------------------------------------------------------------- +# Test data section +#----------------------------------------------------------------------- +# 12 "sources/jal.S" 2 + + +.globl __runtime_start; __runtime_start: la x10,__return_pointer; sw x1,0(x10); li x10,0 + + #------------------------------------------------------------- + # Test 2: Basic test + #------------------------------------------------------------- + +test_2: + li x28, 2 + li ra, 0 + + jal x4, target_2 +linkaddr_2: + nop + nop + + j fail + +target_2: + la x2, linkaddr_2 + bne x2, x4, fail + + #------------------------------------------------------------- + # Test delay slot instructions not executed nor bypassed + #------------------------------------------------------------- + + test_3: li x10, 3; ebreak; li ra, 1; jal x0, test_jal_1; addi ra, ra, 1; addi ra, ra, 1; addi ra, ra, 1; addi ra, ra, 1; test_jal_1: addi ra, ra, 1; addi ra, ra, 1;; li x29, 3; li x28, 3; bne ra, x29, fail; +# 50 "sources/jal.S" + bne x0, x28, pass; fail: unimp;; pass: la x10,__return_pointer; lw x1,0(x10); ret; + + + + .data +.balign 4; __return_pointer: .word 0; + + + + diff --git a/riscv/tests/instruction_tests/sources/jal.S b/riscv/tests/instruction_tests/sources/jal.S new file mode 100644 index 000000000..154d31ad0 --- /dev/null +++ b/riscv/tests/instruction_tests/sources/jal.S @@ -0,0 +1,59 @@ +# See LICENSE for license details. + +#***************************************************************************** +# jal.S +#----------------------------------------------------------------------------- +# +# Test jal instruction. +# + +#include "riscv_test.h" +#include "test_macros.h" + +RVTEST_RV32U +RVTEST_CODE_BEGIN + + #------------------------------------------------------------- + # Test 2: Basic test + #------------------------------------------------------------- + +test_2: + li TESTNUM, 2 + li ra, 0 + + jal x4, target_2 +linkaddr_2: + nop + nop + + j fail + +target_2: + la x2, linkaddr_2 + bne x2, x4, fail + + #------------------------------------------------------------- + # Test delay slot instructions not executed nor bypassed + #------------------------------------------------------------- + + TEST_CASE( 3, ra, 3, \ + li ra, 1; \ + jal x0, test_jal_1; \ + addi ra, ra, 1; \ + addi ra, ra, 1; \ + addi ra, ra, 1; \ + addi ra, ra, 1; \ +test_jal_1: addi ra, ra, 1; \ + addi ra, ra, 1; \ + ) + + TEST_PASSFAIL + +RVTEST_CODE_END + + .data +RVTEST_DATA_BEGIN + + TEST_DATA + +RVTEST_DATA_END