4

I've implemented a program (a fully-connected layer) in C, which needs to be compiled to MIPS to run on a specific microprocessor in order to test the microprocessor's function. Since the ADDIU instruction is not part of this processor's instruction set, I am editing the C program to produce fewer ADDIU instructions at compile time and trying to edit the remaining ones out of the MIPS code (ADD and ADDU are allowed). However, I am brand new to MIPS and want to make sure my edits don't change the function of the program. Is there an expansion for ADDIU using other instructions? If not, any ideas for how I can change the logic of my program to avoid using them?

I am developing a test for a specific microprocessor with a limited MIPS instruction set. Many of the problematic instructions in the compiled code can be expanded to use only instructions in the set, so I will edit the compiled code to include those expansions. However, ADDIU doesn't seem to have an expansion according to the expansion guides I've seen.

I've already gotten rid of some ADDIU instructions by storing commonly-used values as constants so I can refer to variables instead of literals in the rest of the C code, resulting in ADDU instructions (which are allowed). The ADDIU instructions which I'm having trouble editing out occur in the following places:

  1. 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.
    e.g. addiu   $sp,$sp,-3840
    e.g. addiu   $3,$fp,52
  1. Accessing the high/low parts of 32-bit integers separately using %hi and %lo and adding them together
e.g.    lui     $2,%hi(output_layer.3511)
        addiu   $2,$2,%lo(output_layer.3511)

Note: output_layer is an array of 32-bit ints.

  1. 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)

The goal is working MIPS code which contains only instructions in the instruction set of this particular microprocessor, which does not include ADDIU.

  • maybe it will be easier to tell the compiler what micro you use :) – 0___________ Jul 05 '19 at 09:39
  • I should have clarified. I work in a lab which develops new microprocessors, so this micro is not commercially available. Additionally, I am not sure how I would tell the compiler which processor I use, and I had no luck finding alternative compilers for limited instruction sets. – Margaret Schrayer Jul 05 '19 at 09:43
  • Does the processor implement traps? If not, then `addi` would make a good alternative for `addiu`. Source: https://stackoverflow.com/questions/36274590/why-would-we-use-addiu-instead-of-addi/36274750#36274750 – Ruud Helderman Jul 05 '19 at 10:36
  • ADDI is also not in the instruction set. ADDU and ADD are. – Margaret Schrayer Jul 05 '19 at 10:56

2 Answers2

2

addiu and addi are almost identical. The only difference is that addi generates an exception when there is an overflow in the addition, while addiu does not generate an overflow.

So, you can replace all addiu by 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.

No problem to replace addi by addi. No sane software can create addresses in sp/fp that can generate an overflow in this situation.

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

You can use addi, but people generally use an ori for this operation.

lui     $2,%hi(output_layer.3511)
ori     $2,$2,%lo(output_layer.3511)

In either case, there is no risk of overflow (as the 16 LSB are cleared by the lui) and addi, addiu and ori are strictly equivalent.

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)

This code seems very strange. Why not replace the two lines (li+ori) by

    li      $2, 0xffffffff800000ff

The last part (after bgez) is only executed by strictly negative numbers and for them, it is equivalent to an or with 0xffffffffffffff00, and the pair of addiu seems useless...
Anyway they can also be replaced by addi.

EDIT:

If addi is not available, you can copy the immediate in a free register and then perform an add/addu with this register. In most MIPS conventions, $1 is used to store temporaries by the asm and is never used by the compilers. So yo can freely use it (provided you do not use macros that may use this register).

A systematic translation of addiu can be

    addiu $d, $s, imm
## ->
    ori   $1, $0, imm
    add   $d, $s, $1

Both ori and add are real instructions and $1 can be used safely. In some assemblers, you must use $at (assembler temporary) instead of $1.

Alain Merigot
  • 10,667
  • 3
  • 18
  • 31
  • I know; however, ADDI is also not allowed. Only ADD and ADDU are. I'm sorry for not specifying that ADDI is not allowed. Thank you anyway for taking the time to write up such a thorough answer! – Margaret Schrayer Jul 05 '19 at 10:53
  • 1
    In that case, there is a systematic translation. See EDIT in the answer. – Alain Merigot Jul 05 '19 at 11:10
  • Thank you! That's exactly what I was looking for--knowing that $1 can be used safely solves my problems. I'll give it a try (I assume it's fine to use addu instead of add there, right?) – Margaret Schrayer Jul 05 '19 at 11:57
  • 2
    Of course, addu can be used. There is the same difference between add and addu than between addi and addiu. Addu do not generates traps and is probably better. – Alain Merigot Jul 05 '19 at 12:15
0

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

According to my understanding based on your statement, the compiler is also under development. You should discuss with the team developing the compiler about this issue, so they can take your needs into account.

virolino
  • 2,073
  • 5
  • 21
  • Under my team's instructions, am using a publicly available C-to-MIPS compiler. My team is not developing one. I have encountered the same issue using other publicly available C-to-MIPS compilers. – Margaret Schrayer Jul 05 '19 at 10:54