5

I need to generate MIPS specific code on my machine when I run my C program. When I simply run,

gcc -O2 -S -c hello.c

On my system, I get the hello.s which seems to generate some assembly code but it doesn't seem to be MIPS specific code. The contents of hello.s file is as below.

    .file   "hello.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "Hello world"
    .text
    .p2align 4,,15
.globl main
    .type   main, @function
main:
.LFB11:
    .cfi_startproc
    movl    $.LC0, %edi
    xorl    %eax, %eax
    jmp printf
    .cfi_endproc
.LFE11:
    .size   main, .-main
    .ident  "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-4)"
    .section    .note.GNU-stack,"",@progbits

How can I generate the MIPS specific code on my machine?

My machine details are as below.

arch
x86_64
11

Understanding the Basics


From the wiki entry of MIPS architecture, it is described as,

MIPS (originally an acronym for Microprocessor without Interlocked Pipeline Stages) is a reduced instruction set computer (RISC) instruction set (ISA) developed by MIPS Technologies (formerly MIPS Computer Systems, Inc.).

From the wiki entry of the x86-64, it is described as,

x86-64 (also known as x64, x86_64 and AMD64) is the 64-bit version of the x86 instruction set.

So as per the arch output in the question, it is evident that I have a x86_64 machine and I try to produce the MIPS architecture specific code after running gcc compiler.

This is similar to trying and running a diesel car on a petrol engine. No matter how hard we try, without tweaking the gas engine, we could not run the diesel car on a petrol engine.

To describe it in a technical manner, gcc can produce assembly code for a large number of architectures, include MIPS. But what architecture a given gcc instance targets is decided when gcc itself is compiled. The precompiled binary you will find in an Ubuntu system knows about x86 (possibly both 32-bit and 64-bit modes) but not MIPS.


How to compile a C program to MIPS assembly code


Again quoting from the same answer, compiling gcc with a target architecture distinct from the architecture on which gcc itself will be running is known as preparing a cross-compilation toolchain. Or in layman's terms, this cross compilation toolchain is similar to tweaking the petrol engine to run the diesel car.

However, setting up a cross-compilation toolchain is quite a bit of work, so rather than describe how to set that up, I will describe how to install a native MIPS compiler into a MIPS virtual machine. This involves the additional steps of setting up an emulator for the VM and installing an OS into that environment, but will allow you to use a pre-built native compiler rather than compiling a cross compiler.

We will be first installing qemu to make our system run some virtualized operating systems. Again there are several approaches like installing some cross compiled tool chain as discussed here and using a buildroot as suggested in the answer that I earlier linked.

  • Download the tar ball of qemu from here.
  • After downloading the tar ball, run the following commands.

     bzip2 -d qe*
     tar -xvf qe*
     ./configure
     make
     make install
    
  • Now, after installing qemu on the machine, I tried several methods of netboot for the debian OS as suggested over here and here. But unfortunately I was not able to perform the debian OS installation using the netboot because the correct mirrors were not available.

I got an image for debian which targets MIPS architecture from here and I downloaded the kernel and qemu image and from the above link and performed the below steps.

  • I started the qemu as below.

    qemu-system-mips -M malta -kernel vmlinux-2.6.32-5-4kc-malta -hda 
    debian_squeeze_mips_standard.qcow2 -append "root=/dev/sda1 console=tty0"
    
  • After the debian system came up, I installed the gcc compiler as below.

    apt-get update && apt-get upgrade
    apt-get install build-essential
    

Now, I have a perfectly working native gcc compiler inside the MIPS debian virtual machine on qemu, which compiles my C program to MIPS specific assembly code.


Testing


Inside my debian machine, I just put in a sample C hello world program and saved it as hello.c as below.

#include<stdio.h>
int main()
{
    printf("Hello World");
}

To generate MIPS architecture code for my hello.c program, I ran the C program using the gcc compiler as,

gcc -O2 -S -c hello.c

The above command generated a hello.s file which generated my MIPS architecture code.

    .file   1 "hello.c"
    .section .mdebug.abi32
    .previous
    .gnu_attribute 4, 1
    .abicalls
    .section    .rodata.str1.4,"aMS",@progbits,1
    .align  2
$LC0:
    .ascii  "Hello World\000"
    .text
    .align  2
    .globl  main
    .set    nomips16
    .ent    main
    .type   main, @function
main:
    .frame  $sp,0,$31       # vars= 0, regs= 0/0, args= 0, gp= 0
    .mask   0x00000000,0
    .fmask  0x00000000,0
    .set    noreorder
    .set    nomacro

    lui $28,%hi(__gnu_local_gp)
    addiu   $28,$28,%lo(__gnu_local_gp)
    lui $4,%hi($LC0)
    lw  $25,%call16(printf)($28)
    nop
    jr  $25
    addiu   $4,$4,%lo($LC0)

    .set    macro
    .set    reorder
    .end    main
    .size   main, .-main
    .ident  "GCC: (Debian 4.4.5-8) 4.4.5"

But how will I know if the above generated code is MIPS assembly code?

The arch command's output will tell the machine's architecture. In my debian machine, it produces the output as mips and I also do not have any binutils or cross-compiler tool chains installed in the machine.

So, the generated assembly code is MIPS specific.

  • This is good and working but is native inside a vm (slower), in newer Debians with multi-arch support theoretically should be easy to get a toolchain (but I've a feeling isn't still that easy.. never checked) – Alex Oct 22 '14 at 14:49
  • @Alex, I would say getting a tool chain is a tad easier compared to building our own tool chain. – Ramesh Oct 22 '14 at 15:01
  • sure, my understanding is that pre-built like codesourcery are also optmized to produce better code. I'm trying the Debian build process which seems to work fine, eventually I'll update the answer. – Alex Oct 22 '14 at 15:35
3

You need a cross toolchain, gcc (+binutils) which run on x86_64 but output mips binaries.

You can try to build it yourself from scratch (google for examples: build cross toolchain) or download a pre-built one (like from Codesourcery)

Or you may build your own with the help of some tool like crosstool-ng

Also systems like buildroot build (or download) their own cross toolchain (I guess also OpenWRT).

  • thanks. I had checked the codesourcery tool chain. But I guess it is not available for free. – Ramesh Oct 22 '14 at 14:13
  • @Ramesh the Lite version is for free, and it is good (my old company used it on production for years), I'm not sure it is available for x86_64 but maybe you can get the ia32(ix86) working. You didn't mention in your question but, what is the target hw/arch? – Alex Oct 22 '14 at 14:36
1

The emdebian project has done some work on cross toolchains.

As these packages suffer from bit rot quite heavily, I'd inquire about the current status with the emdebian project, either via mailing list or IRC.

  • Thanks. Could you please add the relevant information from the link to the answer so that it would be useful for future readers? – Ramesh Oct 21 '14 at 18:12
  • @Ramesh, I'm not sure that's a good idea. Toolchain compilation is a moving target, and any reference that is not actively maintained becomes unusable rather quickly. – Simon Richter Oct 22 '14 at 4:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.