扩展或避免 MIPS 中的 addiu

Expanding or avoiding addiu in MIPS

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

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

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

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

注意:output_layer 是一个 32 位整数数组。

  1. 当我在 C 中编译 "mod" 函数时发生的 Addiu 指令(扩展 mod 函数以获得余数 "the hard way" 没有帮助)例如fracPart = currentInput % 256; 在 C 中 编译为
lw      ,40($fp)
        li      ,-2147483648                  # 0xffffffff80000000
        ori     ,,0xff
        and     ,,
        bgez    ,$L17
        nop

        addiu   ,,-1
        li      ,-256           # 0xffffffffffffff00
        or      ,,
        addiu   ,,1
$L17:
        sw      ,48($fp)

目标是运行 MIPS 代码,该代码仅包含此特定微处理器指令集中的指令,不包括 ADDIU。

I work in a lab which develops new microprocessors, so this micro is not commercially available.

据我根据你的说法了解,编译器也在开发中。您应该与开发编译器的团队讨论这个问题,以便他们考虑您的需求。

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

因此,您可以将所有 addiu 替换为 addi。

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     ,%hi(output_layer.3511)
ori     ,,%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      ,40($fp)
   li      ,-2147483648                  # 0xffffffff80000000
   ori     ,,0xff
   and     ,,
   bgez    ,$L17
   nop

   addiu   ,,-1
   li      ,-256           # 0xffffffffffffff00
   or      ,,
   addiu   ,,1
$L17:
   sw      ,48($fp)

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

    li      , 0xffffffff800000ff

最后一部分(在 bgez 之后)仅由严格的负数执行,对它们来说,它相当于一个带有 0xffffffffffffff00 的 or,而且这对 addiu 似乎没用...
无论如何,它们也可以用 addi 代替。

编辑:

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

addiu的系统翻译可以

    addiu $d, $s, imm
## ->
    ori   , [=13=], imm
    add   $d, $s, 

ori和add都是真实指令,$1可以放心使用。在某些汇编程序中,您必须使用 $at(临时汇编程序)而不是 $1。