Search code examples
cassemblymipsmips64

Crosscompiling C to MIPS64 and simulating


I needed to translate the follwing C code to MIPS64:

#include <stdio.h>

int main() {
    int x;
    for (x=0;x<10;x++) {
    }
    return 0;
}

I used codebench to crosscompile this code to MIPS64. The following code was created:

    .file   1 "loop.c"
    .section .mdebug.abi32
    .previous
    .gnu_attribute 4, 1
    .abicalls
    .option pic0
    .text
    .align  2
    .globl  main
    .set    nomips16
    .set    nomicromips
    .ent    main
    .type   main, @function
main:
    .frame  $fp,24,$31      # vars= 8, regs= 1/0, args= 0, gp= 8
    .mask   0x40000000,-4
    .fmask  0x00000000,0
    .set    noreorder
    .set    nomacro
    addiu   $sp,$sp,-24
    sw  $fp,20($sp)
    move    $fp,$sp
    sw  $0,8($fp)
    j   $L2
    nop

$L3:
    lw  $2,8($fp)
    addiu   $2,$2,1
    sw  $2,8($fp)
$L2:
    lw  $2,8($fp)
    slt $2,$2,10
    bne $2,$0,$L3
    nop

    move    $2,$0
    move    $sp,$fp
    lw  $fp,20($sp)
    addiu   $sp,$sp,24
    j   $31
    nop

    .set    macro
    .set    reorder
    .end    main
    .size   main, .-main
    .ident  "GCC: (Sourcery CodeBench 2012.03-81) 4.6.3"

To check if the code works as expected, I usually use the WINMIPS64 simulator. For one or other reason this simulator does not want to accept this code. It appears that every line of code is wrong. I have been looking at this issue for over a day. I hope someone can help me out with this. What is wrong with this assembly code for the mips64 architecture?


Solution

  • From page 7 of the WINMIPS64 documentation:

    The following assembler directives are supported
    
    .data                 - start of data segment
    .text                 - start of code segment
    .code                 - start of code segment (same as .text)  
    .org    <n>           - start address
    .space  <n>           - leave n empty bytes
    .asciiz <s>           - enters zero terminated ascii string
    .ascii  <s>           - enter ascii string
    .align  <n>           - align to n-byte boundary
    .word   <n1>,<n2>..   - enters word(s) of data (64-bits)
    .byte   <n1>,<n2>..   - enter bytes
    .word32 <n1>,<n2>..   - enters 32 bit number(s)
    .word16 <n1>,<n2>..   - enters 16 bit number(s)
    .double <n1>,<n2>..   - enters floating-point number(s)
    

    Get rid of everything that's not in the above list, as it won't run in the simulator.

    You'll need to move the .align to before .text

    WINMIPS64 expects daddi/daddui instead of addi/addiu, again as per the documentation.

    As per the documentation, move $a, $b is not a supported mnemonic. Replace them with daddui $a, $b, 0 instead.

    slt needs to be slti.

    Finally, the simulator expects an absolute address for j, but you've given it a register. Use jr instead.

    At this point I get an infinite loop. This is because the stack pointer doesn't get initialized. The simulator only gives you 0x400 bytes of memory, so go ahead and initialize the stack to 0x400:

    .text
        daddui  $sp,$0,0x400
    

    Now it runs. Since you're running the code by itself, nothing will be in the return register and the final jr $31 will just bring it back to the beginning.

    Here's my version:

        .align   2
        .text
        daddui   $sp,$0,0x400
    main:
        daddui   $sp,$sp,-24
        sw       $fp,20($sp)
        daddui   $fp,$sp,0
        sw       $0,8($fp)
        j        $L2
        nop
    
    $L3:
        lw       $2,8($fp)
        daddui   $2,$2,1
        sw       $2,8($fp)
    $L2:
        lw       $2,8($fp)
        slti     $2,$2,10
        bne      $2,$0,$L3
        nop
    
        daddui   $2,$0,0
        daddui   $sp,$fp,0
        lw       $fp,20($sp)
        daddui   $sp,$sp,24
        jr       $31
        nop
    

    Consider getting either another compiler or another simulator, because these two clearly hate each other.