【问题标题】:How to write "||" condition in Risc-V?如何写“||” Risc-V 中的情况?
【发布时间】:2023-04-01 05:28:01
【问题描述】:

例如,在 C 中

if (a == 0 || a == b) return 0;

我不知道如何在 Risc-v 中编写多个条件。各位大神能帮我解答一下吗?

【问题讨论】:

  • 你想带还是不带short-circuit evaluation?你试过什么?您是否尝试过查看 C 编译器生成的代码?
  • 如果您可以为我演示这两种解决方案,那就太棒了,我还没有尝试过一种,您也可以向我推荐一种。我是 Risc-v 的新手,顺便感谢您提供的链接。
  • 要跳过短路评估(强制评估两个表达式),您可以使用if ((a == 0) + (a == b)) return 0;,也可以查看godbolt.org,您可以看到几种架构上的程序集输出
  • 画一个流程图,然后用 asm 编码。或者用简单的ifgoto 用C 编写它(没有||)。
  • @Jester 谢谢老兄,我想我明白了

标签: c assembly riscv


【解决方案1】:

它比 RISC V 更广泛——所有汇编语言都使用 if-goto 作为它们唯一的条件。

If-goto 用于if-then-else 语句、forwhiledorepeat 循环,以及用于&&|| 评估.

|| 的操作数可以分开并单独工作。

if ( a == 0 || a == b ) return 0;

可以翻译成if-goto形式如下:

    if ( a == 0 ) goto L1;      // fall thru only if a!=0
    if ( a != b ) goto L2;      // fall thru only if a==b, branch if a!=b
L1:
    return 0;                   // reaches here if either a==0 or else a==b
L2:                             // comes here if either a!=0 or else a!=b

对于连词,

if ( a == 0 && b == 0 ) return 0;

可以翻译成if-goto形式如下:

    if ( a != 0 ) goto L1;     // fall thru only if a==0, branch if a!=0
    if ( b != 0 ) goto L1;     // fall thru only if b==0, branch if b!=0
    return 0;                  // reaches here when both a==0 and b==0
L1:                            // comes here if either a!=0 or else b!=0

(当然,还有其他可能的转换。)


这些 if-goto 的翻译可以直接用各种汇编语言编写,使用比较和分支。

在 RISC V 中,上述 if-goto 转换可以使用带有两个操作数和一个标签的分支相等 (beq) 或分支不相等 (bne) 指令。

对于使用条件代码的指令集,我们编写了两条指令,比较两个操作数,然后是一个条件分支,以适当地标记相等或不相等。

【讨论】:

  • 值得一提的是,有时最好将条件转换为寄存器中的布尔值 0/1,这样您就可以将多个条件组合在一起并分支一次。例如,仅当 r1 == 0 时,sltu r0, r1, 1 才会为 1。(零是唯一小于 1 的无符号数。)
  • @PeterCordes,是的,好点。为了在更高级别的术语中强调,我们可以分别用|&(逻辑或、和)替换||&&(短路或、和),例如,用于不需要短路评估,并且对于现代处理器上的某些结构会更有效。
  • 仅供参考,ARM 并不总是使用 if-goto,它的所有指令都有条件执行,以避免在许多情况下分支。
【解决方案2】:

明确一点:RISC-V 已经有几个可用的 C 编译器(示例包括 GCC、LLVM 和 IAR),因此您可以使用现有的 C 代码并为 RISC-V 编译它,就像为 ARM 等其他目标一样.

如果您的问题更多的是关于如何在 RISC-V 程序集中编写类似的东西,那么这样的东西可能会起作用(假设 a 在 reg a0 中,b 在 a1 中):

  beqz a0, is_true;    # Jump to the is_true label if a == 0
  beq a0, a1, is_true; # Jump to the is_true label if a == b
  j is_false;          # Jump to the is_false label to continue the function
is_true:
  mv a0, x0;           # Load 0 into the return value register (x0 is hard-wired 0)
  ret;
is_false:
  # Continue the function...

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 2023-04-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多