c - 在 MIPS 中扩展或避免 addiu

标签 c mips

我已经用 C 语言实现了一个程序(一个全连接层),它需要编译成 MIPS 才能在特定的微处理器上运行,以便测试微处理器的功能。由于 ADDIU 指令不是该处理器指令集的一部分,我正在编辑 C 程序以在编译时生成更少的 ADDIU 指令,并尝试从 MIPS 代码中编辑剩余的指令(允许 ADD 和 ADDU)。但是,我是 MIPS 的新手,希望确保我的编辑不会改变程序的功能。是否有使用其他指令的 ADDIU 扩展?如果没有,关于如何更改程序逻辑以避免使用它们的任何想法?

我正在为具有有限 MIPS 指令集的特定微处理器开发测试。编译代码中的许多有问题的指令可以扩展为仅使用集合中的指令,因此我将编辑编译代码以包含这些扩展。但是,根据我看到的扩展指南,ADDIU 似乎没有扩展。

我已经通过将常用值存储为常量来摆脱一些 ADDIU 指令,因此我可以在其余 C 代码中引用变量而不是文字,从而产生 ADDU 指令(这是允许的)。我无法编辑的 ADDIU 指令出现在以下位置:

  • 操作或访问堆栈和帧指针的值。我曾考虑将加数硬编码为常量,但我不确定这是否可行,或者是否会改变相关值。
  •     e.g. addiu   $sp,$sp,-3840
        e.g. addiu   $3,$fp,52
    
  • 使用 %hi 和 %lo 分别访问 32 位整数的高/低部分并将它们加在一起 ​​
  • e.g.    lui     $2,%hi(output_layer.3511)
            addiu   $2,$2,%lo(output_layer.3511)
    

    注意:output_layer 是一个 32 位整数数组。
  • 当我在 C 中编译“mod”函数时出现的 Addiu 指令(扩展 mod 函数以“艰难的方式”获得剩余部分没有帮助)例如fracPart = currentInput % 256;在 C
    编译为
  • lw      $3,40($fp)
            li      $2,-2147483648                  # 0xffffffff80000000
            ori     $2,$2,0xff
            and     $2,$3,$2
            bgez    $2,$L17
            nop
    
            addiu   $2,$2,-1
            li      $3,-256           # 0xffffffffffffff00
            or      $2,$2,$3
            addiu   $2,$2,1
    $L17:
            sw      $2,48($fp)
    

    目标是工作 MIPS 代码,它只包含这个特定微处理器指令集中的指令,不包括 ADDIU。

    最佳答案

    addiu 和 addi 几乎相同。唯一的区别是addi在加法出现溢出时会产生异常,而addiu不会产生溢出。

    所以,你可以用addi替换所有addiu。

    Manipulating or accessing the values of the stack and frame pointers. I've thought about hard-coding the addends as constants, but I'm not sure if that's even possible or if it would change the values in question.



    用 addi 替换 addi 没问题。任何健全的软件都无法在 sp/fp 中创建在这种情况下会产生溢出的地址。

    Accessing the high/low parts of 32-bit integers separately using %hi and %lo and adding them together



    您可以使用 addi,但人们通常使用 ori 进行此操作。
    lui     $2,%hi(output_layer.3511)
    ori     $2,$2,%lo(output_layer.3511)
    

    在任何一种情况下,都不存在溢出的风险(因为 16 LSB 被 lui 清除)并且 addi、addiu 和 ori 是严格等效的。

    Addiu instructions that occur when I compile the "mod" function in C (expanding the mod function to get the remainder "the hard way" didn't help) e.g. fracPart = currentInput % 256; in C compiles to


       lw      $3,40($fp)
       li      $2,-2147483648                  # 0xffffffff80000000
       ori     $2,$2,0xff
       and     $2,$3,$2
       bgez    $2,$L17
       nop
    
       addiu   $2,$2,-1
       li      $3,-256           # 0xffffffffffffff00
       or      $2,$2,$3
       addiu   $2,$2,1
    $L17:
       sw      $2,48($fp)
    

    这段代码看起来很奇怪。为什么不将两行 (li+ori) 替换为
        li      $2, 0xffffffff800000ff
    

    最后一部分(在 bgez 之后)仅由严格的负数执行,对它们来说,它相当于 or用0xffffffffffffff00,这对addiu似乎没用……
    反正他们也可以用addi代替。

    编辑:

    如果 addi 不可用,您可以在空闲寄存器中复制立即数,然后使用该寄存器执行 add/addu。在大多数 MIPS 约定中,$1 用于存储 asm 的临时数据,并且从未被编译器使用。所以你可以自由使用它(前提是你不使用可能使用这个寄存器的宏)。

    addiu 的系统翻译可以是
        addiu $d, $s, imm
    ## ->
        ori   $1, $0, imm
        add   $d, $s, $1
    

    ori 和 add 都是真正的指令,$1 可以安全使用。在某些汇编器中,您必须使用 $at(汇编器临时)而不是 $1。

    关于c - 在 MIPS 中扩展或避免 addiu,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56900055/

    相关文章:

    c - 在进行浮点除法时加倍和返回时是否有任何精度增益?

    ubuntu - 编译Nachos源代码时出现 “gnu/stubs-32.h: No such file or directory”错误

    assembly - 二进制补码快速方法

    c - MIPS的堆栈让我脑洞大开

    assembly - $ 在 MIPS 程序集中是什么意思?

    更改链接哪个 libc.so ?

    objective-c - Mac OS X 上 Netscape 插件的打开/保存对话框?

    c - fgetc 函数无法正常工作

    c - 如何将命令行参数作为字符串参数的一部分传递

    检查子串是否在主串中,如果是,从找到的子串开始打印主串