Reputation: 157
I have assembly code in which I am using RVC instructions such as:
c.j 24
and when I try to assemble it I get 32-bit machine code, but I expect to get 16-bit because it's a compressed instruction. In the binary file the instruction is represented with 32 bits, and the opcode of the assembled instruction corresponds to the normal RV32I instruction JAL, instead to opcode of C.JAL, which is 16bit wide. I compile it like this:
riscv64-unknown-linux-gnu-gcc -c -mabi=ilp32 -march=rv32imac input.s -o output
Does anyone know how to solve this?
Upvotes: 2
Views: 1435
Reputation: 19
I had the same issue in a slightly different circumstance. I was compiling with -march=rv64gc i.e. to include compressed instructions. However the issue lies with objdump not gcc. If I did the following:
$ riscv64-unknown-elf-objdump -d myexecutable > myassembly.txt
I got 32 and 64bit instructions and some pseudo instructions but no compressed instructions. The thread Understanding RiscV objdump gave the answer. If I did:
$ riscv64-unknown-elf-objdump -d -M no-aliases myexecutable > myassembly.txt
I got 32, 64 and 16 bit (i.e. compressed) instructions but no pseudo instructions.
IMHO this is very misleading. An alias or pseudo instruction has the same object code as the underlying real instruction e.g. blez
and bge
. But replacing a 16 bit instruction with, say, the 32 bit equivalent is very different. Sure internally the chip may expand a 16 bit instruction to it's 32 bit equivalent, but the bit pattern retrieved from memory will be different and half the length. I don't think this behaviour should be the default.
Upvotes: 1
Reputation: 1746
If you are using the riscv toolchain from https://github.com/riscv/riscv-gnu-toolchain.
It is normal you are getting 32 bits version. In the binutils, you can see in the assembler porting tc-riscv.c
that the assembler Expand the RVC branch into a RISC-V one.
If it cant validate that the range will be respected.
When you use c.j 24
the assembler have no idea where the code will be placed and convert it to j
. This is a safe approach, otherwise if a compressed instruction is emitted, the linker will have to handle this case with relax or it will issue an error if it cannot handle this case or in the worst case the generated code will be incorrect.
Upvotes: 1