fxSDK:BinaryFormat

FrontPage | Categories | PageIndex | RecentChanges | RecentlyCommented | Login/Register
To produce add-in executables using GCC, you need some initialization code, and some section magic. This information has been extracted by analyzing object code produced by the official SDK.

Toolchain installation

Gentoo

Confirmed to work with GCC version 4.1.2 and Binutils version 2.17, compiled and installed using Gentoo Linux's crossdev software. The target string for my installation is sh3eb-unknown-linux-gnu.

Ubuntu

GCC 4.3.2 and binutils 2.19. Follow http://wiki.osdev.org/GCC_Cross-Compiler#Step_1_-_Bootstrap but set the TARGET variable to "sh3eb-elf". I have only compiled the toolchain with C support (only --enable-languages=c when configuring GCC).

Required files

Firstly, you need a linker script that says where each portion of the code is located;
addin.ld (line 1)
  1. OUTPUT_ARCH(sh3)
  2. ENTRY(initialize)
  3. MEMORY
  4. {
  5.         rom  : o = 0x00300200, l = 512k
  6.         ram  : o = 0x08100000, l = 64k  /* pretty safe guess */
  7. }
  8. SECTIONS
  9. {
  10.         .text : {
  11.                 *(.pretext)     /* init stuff */
  12.                 *(.text)
  13.         } > rom
  14.         .rodata : {
  15.                 *(.rodata)
  16.                 *(.rodata.str1.4)
  17.                 _romdata = . ;  /* symbol for initialization data */
  18.         } > rom
  19.         .bss : {
  20.                 _bbss = . ;
  21.                 _bssdatasize = . ;
  22.                 LONG(0);        /* bssdatasize */
  23.                 *(.bss) *(COMMON);
  24.                 _ebss = . ;
  25.         } > ram
  26.         .data : AT(_romdata) {
  27.                 _bdata = . ;
  28.                 *(.data);
  29.                 _edata = . ;
  30.         } > ram
  31. }

The script specifies two areas, named ram and rom. The executable code and constant data are located in rom (they don't change), while stuff like variables and initialized variables have to stay in ram. Our initialize() function is specified to stay in .pretext, the first section in the executable, and will therefore be the first code executed when the file is written in binary.

crt0.s (line 1)
  1.         .section .pretext
  2.         .global initialize
  3. initialize:
  4.         sts.l   pr, @-r15
  5.  
  6.         ! set up TLB
  7.         mov.l   Hmem_SetMMU, r3
  8.         mov.l   address_one, r4 ! 0x8102000
  9.         mov.l   address_two, r5 ! 0x8801E000
  10.         jsr     @r3    ! _Hmem_SetMMU
  11.         mov     #108, r6
  12.  
  13.         ! clear the BSS
  14.         mov.l   bbss, r4   ! start
  15.         mov.l   ebss, r5   ! end
  16.         bra     L_check_bss
  17.         mov     #0, r6
  18. L_zero_bss:
  19.         mov.l   r6, @r4        ! zero and advance
  20.         add     #4, r4
  21. L_check_bss:
  22.         cmp/hs  r5, r4
  23.         bf      L_zero_bss
  24.  
  25.         ! Copy the .data
  26.         mov.l   bdata, r4  ! dest
  27.         mov.l   edata, r5  ! dest limit
  28.         mov.l   romdata, r6        ! source
  29.         bra     L_check_data
  30.         nop
  31. L_copy_data:
  32.         mov.l   @r6+, r3
  33.         mov.l   r3, @r4
  34.         add     #4, r4
  35. L_check_data:
  36.         cmp/hs  r5, r4
  37.         bf      L_copy_data
  38.  
  39.         mov.l   bbss, r4
  40.         mov.l   edata, r5
  41.         sub     r4, r5              ! size of .bss and .data sections
  42.         add     #4, r5
  43.         mov.l   bssdatasize, r4
  44.         mov.l   r5, @r4
  45.  
  46.         mov.l   GLibAddinAplExecutionCheck, r2
  47.         mov     #0, r4
  48.         mov     #1, r5
  49.         jsr     @r2    ! _GLibAddinAplExecutionCheck(0,1,1);
  50.         mov     r5, r6
  51.  
  52.         mov.l   CallbackAtQuitMainFunction, r3
  53.         mov.l   exit_handler, r4
  54.         jsr     @r3    ! _CallbackAtQuitMainFunction(&exit_handler)
  55.         nop
  56.         mov.l   main, r3
  57.         jmp     @r3    ! _main()
  58.         lds.l   @r15+, pr
  59.  
  60. _exit_handler:
  61.         mov.l   r14, @-r15
  62.         mov.l   r13, @-r15
  63.         mov.l   r12, @-r15
  64.         sts.l   pr, @-r15
  65.  
  66.         mov.l   Bdel_cychdr, r14
  67.         jsr     @r14 ! _Bdel_cychdr
  68.         mov     #6, r4
  69.         jsr     @r14 ! _Bdel_cychdr
  70.         mov     #7, r4
  71.         jsr     @r14 ! _Bdel_cychdr
  72.         mov     #8, r4
  73.         jsr     @r14 ! _Bdel_cychdr
  74.         mov     #9, r4
  75.         jsr     @r14 ! _Bdel_cychdr
  76.         mov     #10, r4
  77.        
  78.         mov.l   BfileFLS_CloseFile, r12
  79.         mov     #4, r14
  80.         mov     #0, r13
  81. L_close_files:
  82.         jsr     @r12 ! _BfileFLS_CloseFile
  83.         mov     r13, r4
  84.         add     #1, r13
  85.         cmp/ge  r14, r13
  86.         bf      L_close_files
  87.  
  88.         mov.l   flsFindClose, r12
  89.         mov     #0, r13
  90. L_close_finds:
  91.         jsr     @r12 ! _flsFindClose
  92.         mov     r13, r4
  93.         add     #1, r13
  94.         cmp/ge  r14, r13
  95.         bf      L_close_finds
  96.  
  97.         lds.l   @r15+, pr
  98.         mov.l   @r15+, r12
  99.         mov.l   @r15+, r13
  100.         mov.l   Bkey_Set_RepeatTime_Default, r2
  101.         jmp     @r2    ! _Bkey_Set_RepeatTime_Default
  102.         mov.l   @r15+, r14
  103.  
  104. .align 4
  105. address_two:    .long 0x8801E000
  106. address_one:    .long 0x8102000
  107. Hmem_SetMMU:    .long _Hmem_SetMMU
  108. GLibAddinAplExecutionCheck:     .long _GLibAddinAplExecutionCheck
  109. CallbackAtQuitMainFunction:     .long _CallbackAtQuitMainFunction
  110. Bdel_cychdr:    .long _Bdel_cychdr
  111. BfileFLS_CloseFile:     .long _BfileFLS_CloseFile
  112. flsFindClose:   .long _flsFindClose
  113. Bkey_Set_RepeatTime_Default:    .long _Bkey_Set_RepeatTime_Default
  114. bbss:      .long _bbss
  115. ebss:      .long _ebss
  116. edata:    .long _edata
  117. bdata:    .long _bdata
  118. romdata:        .long _romdata
  119. bssdatasize:    .long _bssdatasize
  120.  
  121. exit_handler:   .long _exit_handler
  122. main:      .long _main
  123.  
  124. _Hmem_SetMMU:
  125.         mov.l   sc_addr, r2
  126.         mov.l   1f, r0
  127.         jmp     @r2
  128.         nop
  129. 1:      .long 0x3FA
  130.  
  131. _Bdel_cychdr:
  132.         mov.l   sc_addr, r2
  133.         mov.l   1f, r0
  134.         jmp     @r2
  135.         nop
  136. 1:      .long 0x119
  137.  
  138. _BfileFLS_CloseFile:
  139.         mov.l   sc_addr, r2
  140.         mov.l   1f, r0
  141.         jmp     @r2
  142.         nop
  143. 1:      .long 0x1E7
  144.  
  145. _Bkey_Set_RepeatTime_Default:
  146.         mov.l   sc_addr, r2
  147.         mov.l   1f, r0
  148.         jmp     @r2
  149.         nop
  150. 1:      .long 0x244
  151.  
  152. _CallbackAtQuitMainFunction:
  153.         mov.l   sc_addr, r2
  154.         mov.l   1f, r0
  155.         jmp     @r2
  156.         nop
  157. 1:      .long 0x494
  158.  
  159. _flsFindClose:
  160.         mov.l   sc_addr, r2
  161.         mov.l   1f, r0
  162.         jmp     @r2
  163.         nop
  164. 1:      .long 0x218
  165.  
  166. _GLibAddinAplExecutionCheck:
  167.         mov.l   sc_addr, r2
  168.         mov     #0x13, r0
  169.         jmp     @r2
  170.         nop
  171. sc_addr:        .long 0x80010070
  172. .end

This code is similar to the code that is used by the official SDK. It basically clears out the RAM for the uninitialized variables, initializes the appropriate variables and registers a function to be run on program exit. The last thing it does, is to call _main() where the user has written his code. Note the underscore in _main()

The names of these functions are identical to the ones referenced by the SDK. There is no need to keep the exact names, but in some cases the function name is all that hints about what the function does (when I don't know for sure).

Compiling

That file should be all you need to compile a basic C program, and to run most, if not all OS-calls. You will also need a C-library if you want to use stuff like math functions. That is however another task.
I am assuming you are in a directory with crt0.s, addin.ld and your programs main() function in main.c. To compile your program with your SH3-capable GCC, run:

sh3eb-gcc -m3 -mb -O9 -nostdlib -T addin.ld" crt0.s main.c -o myaddin.elf -lgcc

To avoid unnecessary compilation of crt0.s, compile it to an object and specify that object instead when compiling your files.
Note: If you get complaints from GCC about the unsupported emulation mode shelf, your GCC support libraries (libgcc.a) are not compiled in big-endian mode. Your GCC must support shelf to create big endian code.
If you are referencing other source files (you use code from multiple files), you can just list them right by the others. The option -O9 enables full optimization, but is optional. If your compiler supports both little and big endian targets, add -mb to make sure it is in the right format. GCC has now produced an ELF file called myaddin.elf, The calculator does not handle ELF files, only binary files with a specific HeaderFormat. Therefore, we need to copy the wanted sections into a binary file, using objcopy:

sh3eb-objcopy -R .comment -R .bss -O binary myaddin.elf myaddin.bin

This strips out the .comment and .bss sections and stores the other ones in binary format. This binary needs a header before it is a ready add-in. You can do this with g1awrapper.
There are no comments on this page. [Add comment]
SourceForge.net Logo
Valid XHTML 1.0 Transitional | Valid CSS | Powered by Wikka Wakka Wiki 1.1.6.3
Page was generated in 0.1829 seconds