Skip to content

New gcc, and newlib support #65

@GoogleCodeExporter

Description

@GoogleCodeExporter
I have been experimenting again with Dingoo programming, and figured I'd share 
my findings so far here. I tried building a fresh toolchain for the Dingoo, 
which uses Newlib rather than a custom libc. This has mostly been a success and 
I've built code that successfully runs natively with Newlib.

First, how to build the toolchain. I have done this on OS X 10.7, but the same 
method should also work on Linux, although I haven't tested it. I am not sure 
what the usual procedure would be to make it work on Windows. Perhaps building 
under mingw+msys would work.

I used the files binutils-2.21.1a.tar.bz2, gcc-4.6.2.tar.bz2, 
gmp-4.3.2.tar.bz2, mpfr-2.4.2.tar.bz2, mpc-0.8.1.tar.gz and 
newlib-1.19.0.tar.gz from their respective sites. This probably also works with 
other versions if you adjust the names in the commands listed below.

If you are building on OS X 10.7, you first need to disable the use of clang, 
as it does not build gcc correctly at the moment. Later versions may fix this 
so the follow steps become unnecessary. They are not necessary on any other 
platform:

---------------------

export CC=/usr/bin/gcc-4.2
export CPP=/usr/bin/cpp-4.2
export CXX=/usr/bin/g++-4.2
export LD=/usr/bin/gcc-4.2

---------------------

Next, here is the whole process for building the toolchain. A two-step build 
process was used for gcc, which takes longer but apparently works better. This 
will install the toolchain into /opt/mipsel-elf/. Adjust the paths as needed if 
you want it elsewhere.

---------------------

tar jxvf binutils-2.21.1a.tar.bz2
tar jxvf gcc-4.6.2.tar.bz2
tar jxvf gmp-4.3.2.tar.bz2
tar jxvf mpfr-2.4.2.tar.bz2
tar jxvf mpc-0.8.1.tar.gz
tar zxvf newlib-1.19.0.tar.gz

mkdir build-binutils
mkdir build-gcc
mkdir build-binutils

cd build-binutils
../binutils-2.21.1/configure --target=mipsel-elf --prefix=/opt/mipsel-elf
make all
sudo make install
cd ..

export PATH=$PATH:/opt/mipsel-elf/bin/

mv gmp-4.3.2 gcc-4.6.2/gmp
mv mpfr-2.4.2 gcc-4.6.2/mpfr
mv mpc-0.8.1 gcc-4.6.2/mpc
cd build-gcc
../gcc-4.6.2/configure --target=mipsel-elf --prefix=/opt/mipsel-elf 
--without-headers --with-newlib --with-gnu-as --with-gnu-ld 
--enable-languages=c,c++
make all-gcc

sudo make install-gcc
cd ..

cd build-newlib
../newlib-1.19.0/configure --target=mipsel-elf --prefix=/opt/mipsel-elf 
--disable-newlib-supplied-syscalls
make all
sudo make install
cd ..

cd build-gcc
../gcc-4.6.2/configure --target=mipsel-elf --prefix=/opt/mipsel-elf 
--with-newlib --with-gnu-as --with-gnu-ld --disable-shared --disable-libssp 
--enable-languages=c,c++
make all
sudo make install
cd ..

---------------------

This should get you a working toolchain which is named "mipsel-elf-" rather 
than "mipsel-linux-". This means you can use the linker from 
http://a320.forumfree.it/ without modifications. However, the dingoo.xn linker 
script supplied by that linker no longer works. A new one is needed. The one I 
ended up with is the following one:

---------------------

ENTRY(AppMain)
OUTPUT_FORMAT("elf32-littlemips", "elf32-littlemips", "elf32-littlemips")
OUTPUT_ARCH(mips)
SECTIONS { .dingoo 0x80A00000 : { Dummy.o (.text)
                                  *(.text*)
                                  *(.rodata*)
                                  *(.data*)
                                  *(.eh_frame*)
                                  *(.gcc_except_table*)
                                  _gp = ALIGN(16) + 0x7ff0;
                                  *(.sdata)
                                  *(.lit8) 
                                  *(.lit4)
                                }
                                  _fbss = .;
           .bss :               {
                                  *(.sbss) 
                                  *(.scommon)
                                  *(.bss)
                                  *(COMMON)
                                }
                                  _end = . ;
           /DISCARD/ : { *(*) }
         }


---------------------

The main changes are changing the OUTPUT_FORMAT, and adding the definition of 
_gp, and moving some sections around to match that. The _gp entry is a problem 
otherwise too. Newer gcc version uses a "small data" model for some global 
variables, keeping that data in a 64k region for fast access. The gp register 
is set to point to the middle of this region. The startup code in libdingoo.a 
as supplied by http://a320.forumfree.it/ does not set this correctly, and no 
source is supplied so I have been unable to fix this. There is a workaround for 
this, however: In your GameMain() function, as the first thing you do, add this 
line:

__asm volatile("move $gp,%0"::"r" (_gp));

And also import the definition of the _gp symbol in the global scope of that 
file:

extern char _gp[];

Another issue is that this version of gcc seems to not be able to find its 
library files by default. To get it to work right, the following flags should 
be used when linking:

-L/opt/mipsel-elf/mipsel-elf/lib/soft-float 
-L/opt/mipsel-elf/lib/gcc/mipsel-elf/4.6.2/soft-float libdingoo.a -lm -lc -lgcc

This should make the libdingoo.a entries override the ones in Newlib, so that 
you get malloc() from the Dingoo OS rather than from Newlib.

Finally, Newlib requires some stub functions to be defined for access to OS 
functions. If we do not use Newlib for OS access, we can get away with using 
dummy functions for all of these. I linked a file like this into my project to 
provide those:


---------------------

#include <reent.h>

int _close_r(struct _reent *r,int a) { return 0; }
int _execve_r(struct _reent *r,const char *a,char *const *b,char *const *c) { 
return 0; }
int _fcntl_r(struct _reent *r,int a,int b,int c) { return 0; }
int _fork_r(struct _reent *r) { return 0; }
int _fstat_r(struct _reent *r,int a,struct stat *b) { return 0; }
int _getpid_r(struct _reent *r) { return 0; }
int _isatty_r(struct _reent *r,int a) { return 0; }
int _kill_r(struct _reent *r,int a,int b) { return 0; }
int _link_r(struct _reent *r,const char *a, const char *b) { return 0; }
_off_t _lseek_r(struct _reent *r,int a,_off_t b,int c) { return 0; }
int _mkdir_r(struct _reent *r,const char *a,int b) { return 0; }
int _open_r(struct _reent *r,const char *a,int b,int c) { return 0; }
_ssize_t _read_r(struct _reent *r,int a,void *b,size_t c) { return 0; }
int _rename_r(struct _reent *r,const char *a, const char *b) { return 0; }
void *_sbrk_r(struct _reent *r,ptrdiff_t a) { return 0; }
int _stat_r(struct _reent *r,const char *a, struct stat *b) { return 0; }
_CLOCK_T_ _times_r(struct _reent *r,struct tms *a) { return 0; }
int _unlink_r(struct _reent *r,const char *a) { return 0; }
int _wait_r(struct _reent *r,int *a) { return 0; }
_ssize_t _write_r(struct _reent *r,int a,const void *b,size_t c) { return 0; }

void _exit()
{
        for(;;);
}

---------------------

If we wanted a more functional C library, the stub functions could be properly 
implemented to hook into the Dingoo OS. Especially the _exit() function should 
probably be better than an endless loop, this was just something I threw 
together to get the thing to build.

To get Newlib working properly would probably require changing libdingoo.a to 
rename the function to avoid namespace collisions, and then implementing the 
Newlib stubs. The Newlib stubs could also implement some kind of stdio console 
that would print to the screen. malloc() should probably be kept overridden, 
though. This would require re-writing libdingoo.a and the linker, though, which 
should be possible but more work than I have time for at the moment.

But basically, this could be used to write a new more comprehensive SDK, with a 
more up-to-date compiler on multiple platforms, if anyone wants to take it up. 
As usual, I don't have enough time to work on it myself beyond this.

Original issue reported on code.google.com by paracel...@gmail.com on 1 Nov 2011 at 9:19

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions