Closed gxflying closed 4 years ago
"bltu x2, x1, 4" means "branch to absolute address 4", which is something you probably don't want to do. You should try branching to a label, rather than branching to an absolute address.
On Tue, Apr 28, 2020 at 4:11 AM Felix notifications@github.com wrote:
hi, i find it's weird when I compile only one instruction : bltu, I encounter the error : relocation truncated to fit : R_RISCV_JAL against `UND' and from the .o file, I find it actually generated 2 instructions for the bltu:
- bgeu
- j : this is where the R_RISCV_JAL needed, but not defined
my program is simple: .S : .global _start _start: addi x1, x0 , 0 addi x2, x0, 0 bltu x2, x1, 4 addi x3, x0, 4 lds: OUTPUT_ARCH("riscv") ENTRY(_start) SECTIONS { . = 0X800000000 .text : { *(.text) } _end = . ;
}
command line: see the attachment [image: dddd] https://user-images.githubusercontent.com/16956976/80480836-f0afde00-8983-11ea-9a3b-a9c60f32ed9b.png
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/riscv/riscv-gnu-toolchain/issues/626, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAH3XQX5N5455MXHQVNWTN3RO22VPANCNFSM4MSXORAQ .
@aswaterman thank you for your reply.and i want to go further, sine more questions below:
1) To jump to an absolute address, you can load it into a register then jr to it--e.g., li t0, 4; jr t0.
2) The assembler emits a conservative sequence if it thinks the branch will go far away.
3) mcmodel primarily affects the C compiler, not the assembler.
On Tue, Apr 28, 2020 at 8:02 AM Felix notifications@github.com wrote:
@aswaterman https://github.com/aswaterman thank you for your reply.and i want to go further, sine more questions below:
- if I really want to jump from a address above 0x80000000 to the very start of the address , e.g the 0x04, what should I do by using conditional branch instructions?
- from the .o file we can see that the bltu acctually was translated into a "bgeu" and a "J" why it behavors like this? 3.how does the complie option "mcmodel" effect the jump or branch instructions when the offset value is in conserned, for example jump over 2G?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/riscv/riscv-gnu-toolchain/issues/626#issuecomment-620662575, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAH3XQX2PVC7NEGZQEAPVSLRO3VXJANCNFSM4MSXORAQ .
@aswaterman thanks, about the second question , why does it fail when it enits a far away jump, and it already generats a "J" instruction , besides, the absolute address is also here in the origin instruction. i think it may emits and generates instructions like this: bgeu, x,x,x li x6, 0x04 jr x6 and why not? is the reason that it does not kown which register is avilable to use? or something else?
then in what conditiion the "bgeu & J" series works?
I think the truncated is caused by two cases,
Like @aswaterman said, the immediate of branch should be a Label in assembler. This may be confusing since RISC-V ISA spec said that the immediate is an offset, and you can also use the immediate as an offset in assembler for many targets. However, the immediate is really an offset when it is relocated and executed. But it is better to be a label when we write the assembly.
The linker script put the text far away from the start of the address. In assembler, we can not know the detailed about the linker script. And it is hard to find an extra register to do what you mentioned (convert bltu to the pattern with jr) in the assemble-time, since we don't preserve an register for temporarily usage in RISC-V ABI. So in the assemble-time, we can only know that you may want to jump to an absolute address by branch, and the range may be not enough. We try our best to convert the branch to a long branch (branch + j), but it may still not far enough.
Maybe you can write your code by C and use compiler with -mcmodel setting, and you probably can resolve the problem. But I remember that there is a long branch issue for compiler, not sure if it is resolved and related to your case.
Thanks
@Nelson1225 thanks for your answer, I think the same way as you do. and it really is confused for the branch immediate treated as a absolute address while the spec says it's a offset. about the behavior of the assembler, source code may help to understand the machanism. I think it's time to close this issue and thank you again @aswaterman @Nelson1225
Hi @gxflying,
This document may be helpful, https://github.com/riscv/riscv-asm-manual/blob/master/riscv-asm.md. You can see the details in "Labels".
But I can not find where to describe the above behavior, that is, "bltu x2, x1, 4" means "branch to absolute address 4". Maybe we should add the related description to the document or spec :)
Thanks
@Nelson1225 Hi, I want to see how the compiler emits the "bltu x2, x1, 4" into two instructions "bgeu & j", and I have got the source code of the gcc with riscv sopported. but it is so hurge that i don't know where to start, could you help me? where the "instruction emits" actions happens? thanks
@aswaterman thank you very much.
I have just found emit_insn() called in the gcc source code in riscv.c.
https://github.com/riscv/riscv-gcc/blob/riscv-gcc-9.2.0/gcc/config/riscv/riscv.c
what i saw is just gcc compiler. and the "emit" happens in gcc assembler you linked above. am I right ?
Yes, the assembler expands the out-of-range branch into two instructions.
hi, i find it's weird when I compile only one instruction : bltu, I encounter the error : relocation truncated to fit : R_RISCV_JAL against `UND' and from the .o file, I find it actually generated 2 instructions for the bltu:
my program is simple: .S : .global _start _start: addi x1, x0 , 0 addi x2, x0, 0 bltu x2, x1, 4 addi x3, x0, 4 lds: OUTPUT_ARCH("riscv") ENTRY(_start) SECTIONS { . = 0X800000000 .text : { *(.text) } _end = . ;
}
command line: see the attachment