简体   繁体   中英

Why RISC-V don't have conditional branch equal with immediate value?

Following is most common conditional branch code in my RISC-V assembly project.

li a0, UART1_BASE;
lw t0, UART_INTR_PEND_OFFSET(a0); // Read UART interrupt pending status

andi t0, t0, 1;
li t1, 1; // IMM LOAD
beq t0, t1, LB_process_tx; // UART Tx interrupt 
// else UART rx interrupt 

The IMM LOAD instruction li t1, 1 could be avoided if branch equal instruction has a immediate variant (like beqi t0, 1, LB_process_tx . I don't find immediate variant for conditional branch. Correct me if I'm wrong.

I am well aware that lot of thoughts have gone in the RISC-V instruction set and hence more interested in knowing is there any other way of doing this conditional branch with lesser instructions . if not, what might be the reasoning behind not having the immediate variant for conditional branch?

Instruction format-wise, the field for register can be used for imm5 value.

There's not so much room in the instruction encoding!

There already is an immediate — the branch target.

Conditional branching generally requires many operands: two sources, a condition and a branch target. Many instruction sets split them into two instructions, compare and branch linked together by condition codes.

But RISC V chooses to avoid condition codes, so offers those two register source branches instead.

If that code is in a tight loop, you can place the immediate into a register before the loop, and save that instruction inside the loop.

Even better, you can switch to a bne using the zero register instead of comparing against 1 in that code sequence to eliminate the li .

Original:

andi t0, t0, 1;
li t1, 1; // IMM LOAD
beq t0, t1, LB_process_tx; // UART Tx interrupt 

Since the andi operation in the above constrains the result to 0 or 1, we can use bne to check for zero instead, without needing the li :

andi t0 t0 1
bne t0, zero, LB_process_tx  # compare for != 0

or, here where the andi result constrains to 0 or 2, we can still use bne :

andi t0, t0, 2
bne t0, zero, LB_process_rx

Instruction format-wise, the field for register can be used for imm5 value.

Yes, that could work. This would might require an additional opcode (or if restricted to just bne and beq leaving out the other relations, could be squeezed into the func3 of the existing SB format main opcode), and then would also require an additional instruction format.

The value in code space and other performance improvement is unknown to me, given that the immediate value of 0 (probably the most important immediate) is already accounted for with the zero register, and given that the li instruction can be moved out of tight loops. However, those other factors (new opcode/instruction format) would complicate especially the low end / embedded processor implementation (known to be very important to the designers) in return for that (small?) improvement. The RISC V design allows for extensibility though, so this could still be conceivably implemented.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM