This document contains useful information for embedded software developers who wish to migrate their code from Renesas tools to CyberTHOR Studios GNU tools (and vice versa) for SH targets. At present, this guide contains the following:
Compiler Options
Compiler Directives
Assembler Directives.
Intrinsic Functions.
C/Math Library Functions.
Inline Assembly
Revision History:
Version Number |
Date |
Overview of changes |
1.0 | 23-August-2004 | Created. |
2.0 | 31-August-2004 | GNU intrinsic functions set_imask(), get_imask() modified. |
3.0 | 05-January-2005 | Assembler directives added. |
4.0 | 07-March-2008 | 'Using inline assembly in GNU' added. |
5.0 | 30-September-2008 | Modified 'Using inline assembly in GNU' section to add ‘-h-tick-hex’ option. |
6.0 | 29-January-2009 | Modified the following GNU intrinsic functions: get_vbr(), get_gbr(), gbr_read_byte(), dmuls_l(), dmuls_h(), macl(), macll(), swapw(), end_cnvl(), get_fpscr(). Added following GNU intrinsic functions for SH2A target: tas(), prefetch(), set_fpscr(), get_fpscr() Added following GNU intrinsic functions for SH3E, SH4_SINGLE and SH4_SINGLE_ONLY targets: set_fpscr(), get_fpscr() Added 'extern' keyword for GNU intrinsic functions. |
7.0 | 20-October-2016 | Added new responsive template |
Please note that this is an intermediate guide, which will be improved and enhanced periodically.
Please do not hesitate to send any of your suggestions or
ideas. You may log in your suggestions on our web site https://gcc-renesas.com/.
You will need to register first, after which you can either add a new support query at the following link: https://gcc-renesas.com/my-support-requests/tickettrackingsystem/addticket, or ask a question here: https://gcc-renesas.com/forum/ask/.
Please note that in order to be able to add a new support query or ask a question you must be logged in.
Renesas Compiler Options |
Equivalent GCC compiler options |
-include = <path name>[,…] |
-I<path> |
-preinclude = <file name>[,...] |
-include <file> |
-define = <sub> [,…] |
-D<macro> |
-nomessage [ = <error code> [- <error code>] [,…] ]
|
-w |
-preprocessor [= <file name>] |
-E -o filename |
-object [= <object file name>] |
-o filename |
-Code=Asmcode -object=<file name>] |
-S filename |
-debug |
-g[level] |
-string = { Const | Data } |
-fwritable-strings |
-template = { None | Static | Used | All | AUto } |
-fno-implicit-templates |
-List [= <file name>] |
-Wa, -al=file |
-show=<sub>[,...] Specifies the contents and format of the list output by the compiler, and the cancellation of list output. |
-a[sub-option...] |
-speed = <sub> [,…] |
-O[1-3] |
-optimize = { 0 | 1 } |
-Os |
-comment |
By default enabled. To generate warning for nested
comments use option. |
-macsave |
-mnomacsave |
-pack |
-fpack-struct |
-volatile |
-fvolatile |
-cmncode |
-fgcse |
-align16 |
-falign |
-loop |
-funroll-all-loops |
-cpu = {sh1|sh2|sh2e|sh3|sh4} |
-m1 –m2 –m2e –m3 –m4 |
-endian = { big | little } |
-mb or –ml |
-fpu= {single | double} |
-fsingle-precision-constant |
-pic= { 0 | 1 } |
-fpic |
-double=float |
-fshort-double |
-rtti = { ON |OFf } |
-fno-rtti |
-exception |
-fexceptions |
-lang = { C | CPp } |
-x <language> |
Options only in GCC:
-fomit-frame-pointer |
Register r14 in case of GCC is used as frame pointer. To avoid it from being pushed and popped during a function call, -fomit-frame-pointer option is specified. |
For more information on the above compiler command line options, please refer to the gcc manual.
Renesas Directives | Equivalent GNU directive or method |
#pragma interrupt (ext_0(vect=8)) void ext_0(void) { p0=6; } |
#define VECT_SECT __attribute__((section (".vects"))) #define ISR __attribute__ ((interrupt_handler)) typedef void (*function_ptr) (void); extern volatile int P0; extern void start (void); void ext_0() ISR; function_ptr HardwareVectors[] VECT_SECT = { start,0,0,0,0,0,0,0,ext_0,0,0,0,0,0,0,0 }; void ext_0() { P0 = 6; } |
extern char STK[100]; #pragma interrupt ( f(sp=STK+100) ) or _ _interrupt(sp=STK+100) void f(void); |
extern char STK[100]; void f () __attribute__ ((interrupt_handler, sp_switch ("STK+100"))); |
extern char STK[100]; #pragma interrupt ( g(tn=2) ) or _ _interrupt(tn=2) void g(void); |
trap_exit void g() __attribute__ ((interrupt_handler, trap_exit(2))); |
#pragma abs8(c1) #pragma abs16(i1) char c1; /* c1 is assigned to $ABS8B */ int i1; /* i1 is assigned to $ABS16B */ |
const int i1 __attribute__ ((section(“_cseg”))); const char c1[] __attribute__((section(“_cseg”)))={"Hello World"}; Please note this requires an entry in the linker section for the memory location of “_cseg”. For ex. in the linker script _cseg |
#pragma entry <function name> [<entry specification>] e.g. #pragma entry INIT(sp=0x8000) void INIT(){:} |
Achieved through linker script. |
#pragma inline (<function name>[,…]) _ _inline <type specifier> <function name> |
inline void foo (const char) __attribute__((always_inline)); |
#pragma global_register(x=R4) or _ _ global_register(R4L) char x; /* External variable x is allocated to R4 */ |
You can define a global register variable in GNU C like this: register int *x asm ("r4"); |
#pragma stacksize <constant> e.g. #pragma stacksize 100 <Code expansion example> .SECTION S, STACK .RES.W 50 Creates a stack section |
char stack[100] __attribute__ ((section ("STACK"))) = { 0 }; main() { /* Initialize stack pointer */ init_sp (stack + sizeof (stack)); } |
#pragma section [{<name> | <numeric value>}] |
Pragma is not available but the functionality can be
achieved using __attribute__ ((section(“<section name>”))) |
#pragma inline_asm (<function name>
|
Asm(<assembly-language instruction string>); |
For more information on the above compiler directives, please refer to the gcc manual.
Renesas Assembler Directives | GNU Assembler Directives |
.AIF | #if or .if |
.AELSE | #else or .else |
.AENDI | #endif or .endif |
Sym_name: .ASSIGN value | set sym_name , value |
.ALIGN <boundary alignment value> |
.align <boundary alignment value> |
sym_name: .EQU value | .equ sym_name , value |
.EXPORT | .global |
.GLOBAL | .global |
.IMPORT sym_name | .extern sym_name |
Sym_name .RES.B 1 | .size sym_name , 1 .sym_name: .byte initial_value |
Sym_name .RES.L 1 | .size sym_name , 4 .sym_name: .long initial_value |
Sym_name .RES.W 1 | .size sym_name, 2 .sym_name: .word initial_value |
sym_name: .EQU B’ value (binary value) |
.equ sym_name , 0x value (equivalent hex value) |
.SECTION name, attribute | .section “ name” , “attributes”
(for details on the possible attributes, please refer the link given below) |
Sym_name: .SDATA “str” | Sym_name: .string “str” |
Sym_name: .DATA.W H’18D Sym_name: .DATA.L H’18D Sym_name: .DATA.B H’8D |
Sym_name: .word 0x18d Sym_name: .long 0x18d Sym_name: .byte 0x8d |
For more information on the above
assembler directives, please refer to the
as manual.
Renesas Intrinsic functions | Equivalent GCC inline code |
void set_cr(int cr) |
extern __inline__ void set_cr(int cr) { asm("mov %0, r0"::"r"(cr):"r0"); asm("ldc r0, sr"); } |
int get_cr(void) |
extern __inline__ int get_cr(void) { long val; asm("stc sr, r0":::"r0"); asm("mov.l r0, %0":"=m"(val)); return val; } |
void set_imask(int mask) |
extern __inline__ void set_imask(int mask) { asm ("mov.l r0,@-r15"); mask <<= 4; mask &= 0xf0; asm("stc sr,r0"); asm("mov #0xff,r3"); asm("shll8 r3"); asm("add #0x0f,r3"); asm("and r3,r0"); asm("mov %0,r3"::"r"(mask)); asm("or r3,r0"); asm("ldc r0,sr"); asm("mov.l @r15+,r0"); } |
int get_imask(void) |
extern __inline__ int get_imask() { int val; asm("mov.l r0,@-r15"); asm("stc sr,r0"); asm("shlr2 r0"); asm("shlr2 r0"); asm("and #15,r0"); asm("mov.l r0,%0":"=m"(val)); asm("mov.l @r15+,r0"); return val; } |
void set_vbr(void *base) |
extern __inline__ void set_vbr(void *vbr) { asm("mov %0, r2"::"r"(vbr):"r2"); asm("ldc r2,vbr"); } |
void *get_vbr(void) |
extern __inline__ void* get_vbr(void) { void *ptr; asm("stc vbr,r2":::"r2"); asm("mov.l r2, %0":"=m"(ptr)); return ptr; } |
void set_gbr(void *base) |
extern __inline__ void set_gbr(void *gbr) { asm("mov %0, r2"::"r"(gbr):"r2"); asm("ldc r2, gbr"); } |
void *get_gbr(void) |
extern __inline__ void* get_gbr(void) { void *ptr; asm("stc gbr,r2":::"r2"); asm("mov.l r2, %0":"=m"(ptr)); return ptr; } |
unsigned char gbr_read_byte(int offset) unsigned short gbr_read_word(int offset) Unsigned long gbr_read_long(int offset) |
extern __inline__ unsigned char gbr_read_byte(int offset) { unsigned char val; asm("mov %0, r1"::"r"(offset):"r1"); asm("stc gbr, r2":::"r2"); asm("add r1, r2"); asm("mov.b @r2, r0"); asm("extu.b r0, r2"); asm("mov.l r2, %0":"=m"(val)); return val; } Similarly gbr_read_word(int offset) and gbr_read_long(int offset) |
void gbr_write_byte(int offset, unsigned char data) void gbr_write_word(int offset, unsigned short data) void gbr_write_long(int offset, unsigned long data) |
extern __inline__ void gbr_write_word(int offset, unsigned short data) { asm("mov %0, r1"::"r"(offset):"r1"); asm("stc gbr, r2":::"r2"); asm("add r1, r2"); asm("mov %0,r1"::"r"(data)); asm("mov r1,r0"); asm("mov.w r0,@r2"); } Similarly gbr_write_byte and gbr_write_long |
void gbr_and_byte(int offset, unsigned char mask) void gbr_or_byte(int offset, unsigned char mask) void gbr_xor_byte(int offset, unsigned char mask) void gbr_tst_byte(int offset, unsigned char mask) |
extern __inline__ void gbr_and_byte(int offset, unsigned char mask) { asm("mov %0, r0"::"r"(offset):"r0"); asm("and.b %0, @(r0,gbr)"::"g"(mask)); } Please replace occurrence of gbr_and_byte(offset,mask) with above. Similarly gbr_or_byte, gbr_xor_byte and gbr_tst_byte. |
void sleep(void) |
extern __inline__ void sleep(void) { asm("sleep"); } |
void tas(char *addr) |
extern __inline__ void tas(char *addr) { asm("mov %0, r1"::"r"(addr):"r1"); asm("tas.b @r1"); } |
void trapa(unsigned int trap_no) |
asm ("trapa %0"::"g"(trap_no)) Please replace occurance of trapa(trap_no) with above. |
int trapa_svc(int trap_no, type1 para1, type2 para2, type3 para3, type4 para4) |
Under Process |
void prefetch (void *p) |
extern __inline__ void prefetch (void *p) { asm("mov %0, r2"::"r"(p):"r2"); asm("pref @r2"); } Available only for sh3 and sh4 |
void trace(long v) |
Under process. Available only for sh3 and sh4 |
void ldtlb(void) |
extern __inline__ void ldtlb(void) { asm("ldtlb"); } Available only for sh3 and sh4 |
void nop(void) |
extern __inline__ void nop(void) { asm("nop"); } |
unsigned long dmuls_l(long data1, long data2) unsigned long dmulu_l(unsigned long data1, unsigned long data2) |
extern __inline__ unsigned long dmuls_l(long data1, long data2) { unsigned long val; asm("mov %0, r4"::"r"(data1):"r4"); asm("mov %0, r5"::"r"(data2):"r5"); asm("dmuls.l r4,r5"); asm("sts macl,r6":::"r6"); asm("sts mach,r2":::"r2"); asm("lds r6,macl"); asm("sts macl,r2"); asm("mov.l r2, %0":"=m"(val)); return val; } Similarly dmulu_l(). dmuls _l() is not available for sh1. dmulu _l() available only for sh1. |
long dmuls_h(long data1, long data2) dmulu_h(unsigned long data1, unsigned long data2) |
extern __inline__ long dmuls_h(long data1,long data2) { unsigned long val; asm("mov %0, r4"::"r"(data1):"r4"); asm("mov %0, r5"::"r"(data2):"r5"); asm("dmuls.l r4,r5"); asm("sts macl,r6":::"r6"); asm("sts mach,r2":::"r2"); asm("lds r2,mach"); asm("sts mach,r6"); asm("mov.l r6, %0":"=m"(val)); return val; } Similarly dmulu_h(). Not available for sh1. |
unsigned short swapb(unsigned short data) unsigned long swapw(unsigned long data) |
extern __inline__ unsigned long swapw(unsigned long data) { unsigned long val; asm("mov %0, r2"::"r"(data):"r2"); asm("swap.w r2,r6":::"r6"); asm("mov.l r6, %0":"=m"(val)); return val; } Similarly swapb() |
unsigned long end_cnvl(unsigned long data) |
extern __inline__ unsigned long end_cnvl(unsigned long data) { unsigned long val; asm("mov %0, r6"::"r"(data):"r6"); asm("mov r6,r2":::"r2"); asm("swap.b r2,r6"); asm("swap.w r6,r2"); asm("swap.b r2,r6"); asm("mov.l r6, %0":"=m"(val)); return val; } |
int macw(short *ptr1, short *ptr2, unsigned int count) int macl(int *ptr1, int *ptr2, unsigned int count) |
extern __inline__ int macl(int *ptr1,int*ptr2,unsigned int count) { int val; asm("mov %0,r4"::"r"(count):"r4"); asm("clrmac"); asm("sts macl,r2":::"r2"); asm("sts mach,r6":::"r6"); asm("tst r4,r4"); asm("bt l11"); asm("mov %0, r6"::"r"(ptr1):"r6"); asm("mov %0, r5"::"r"(ptr2):"r5"); asm("shll2 r4"); asm("add r6,r4"); asm("l13:"); asm("lds r2,macl"); asm("mac.l @r6+,@r5+"); asm("sts macl,r2"); asm("cmp/hi r6,r4"); asm("bt l13"); asm("l11:"); asm("lds r2,macl"); asm("sts macl,r6"); asm("mov.l r6, %0":"=m"(val)); return val; } Similarly int macw(short *ptr1, short *ptr2, unsigned int count) macl() is not available for sh1. |
int macwl(short *ptr1, short *ptr2, unsigned int count, unsigned int mask) int macll(int *ptr1, int*ptr2, unsigned int count, unsigned int mask) |
extern __inline__ int macll(int *ptr1,int*ptr2, unsigned int count,unsigned int mask) { int val; asm("mov %0,r4"::"r"(count):"r4"); asm("clrmac"); asm("sts macl,r2":::"r2"); asm("sts mach,r6":::"r6"); asm("tst r4,r4"); asm("bt l14"); asm("mov %0, r6"::"r"(ptr1):"r6"); asm("mov %0, r5"::"r"(ptr2):"r5"); asm("mov %0, r7"::"r"(mask):"r7"); asm("shll2 r4"); asm("add r6,r4"); asm("l16:"); asm("lds r2,macl"); asm("mac.l @r6+,@r5+"); asm("sts macl,r2"); asm("and r7,r5"); asm("cmp/hi r6,r4"); asm("bt l16"); asm("l14:"); asm("lds r2,macl"); asm("sts macl,r6"); asm("mov.l r6, %0":"=m"(val)); return val; } Similarly int macwl(short *ptr1, short *ptr2, unsigned int count, unsigned int mask) macll() is not available for sh1. |
void set_fpscr(int cr) |
extern __inline__ void set_fpscr(int cr) { asm("mov %0, r2"::"r"(cr):"r2"); asm("lds r2,fpscr"); } Available only for sh2e, sh3e and sh4. |
int get_fpscr() |
extern __inline__ int get_fpscr() { int val; asm("sts fpscr, r2":::"r2"); asm("mov.l r2, %0":"=m"(val)); return val; } Available only for sh2e, sh3e and sh4. |
float fipr(float vect1[4], float vect2[4]) |
extern __inline__ float fipr(float vect1[4], float vect2[4]) { float val; asm("mov %0,r2"::"r"(vect1):"r2"); asm("fmov.s @r2+,fr0":::"fr0"); asm("fmov.s @r2+,fr1":::"fr1"); asm("fmov.s @r2+,fr2":::"fr2"); asm("fmov.s @r2+,fr3":::"fr3"); asm("add #-16,r2"); asm("fmov fr3,fr8":::"fr8"); asm("fmov fr2,fr9":::"fr9"); asm("mov %0, r2"::"r"(vect2):"r2"); asm("fmov.s @r2+,fr4":::"fr4"); asm("fmov.s @r2+,fr5":::"fr5"); asm("fmov.s @r2+,fr6":::"fr6"); asm("fmov.s @r2+,fr7":::"fr7"); asm("add #-16,r2"); asm("fmov fr9,fr2"); asm("fmov fr8,fr3"); asm("fipr fv4,fv0"); asm("fmov fr3,fr8"); // asm("fmov fr8, %0":"=f"(val)); // return val; } Available only for sh4. |
void ftrv(float vec1[4],float vec2[4]) |
extern __inline__ void ftrv(float vec1[4],float vec2[4]) { asm("mov %0,r6"::"r"(vec1):"r6"); asm("fmov.s @r6+,fr0"); asm("fmov.s @r6+,fr1"); asm("fmov.s @r6+,fr2"); asm("fmov.s @r6+,fr3"); asm("add #-16,r6"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("mov %0,r6"::"r"(vec2)); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("add #16,r6"); asm("fmov.s fr3,@-r6"); asm("fmov.s fr2,@-r6"); asm("fmov.s fr1,@-r6"); asm("fmov.s fr0,@-r6"); } Available only for sh4. |
void ftrvadd(float vec1[4], float vec2[4],float vec3[4]) void ftrvsub(float vec1[4], float vec2[4],float vec3[4]) |
extern __inline__ void ftrvsub(float vec1[4], float vec2[4],float vec3[4]) { asm("mov %0,r2"::"r"(vec1):"r2"); asm("fmov.s @r2+,fr0"); asm("fmov.s @r2+,fr1"); asm("fmov.s @r2+,fr2"); asm("fmov.s @r2+,fr3"); asm("add #-16,r2"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("mov %0,r2"::"r"(vec2)); asm("fmov.s @r2+,fr4"); asm("fmov.s @r2+,fr5"); asm("fmov.s @r2+,fr6"); asm("fmov.s @r2+,fr7"); asm("add #-16,r2"); asm("fsub fr4,fr0"); asm("fsub fr5,fr1"); asm("fmov fr8,fr2"); asm("fsub fr6,fr2"); asm("fmov fr2,fr8"); asm("fmov fr9,fr3"); asm("fsub fr7,fr3"); asm("fmov fr3,fr9"); asm("mov %0,r2"::"r"(vec3)); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("add #16,r2"); asm("fmov.s fr3,@-r2"); asm("fmov.s fr2,@-r2"); asm("fmov.s fr1,@-r2"); asm("fmov.s fr0,@-r2"); } Similarly ftrvadd(). Available only for sh4 . |
void add4(float vec1[4], float vec2[4],float vec3[4]) void sub4(float vec1[4], float vec2[4],float vec3[4]) |
extern __inline__ void add4(float vec1[4], float vec2[4],float vec3[4]) { asm("mov %0,r2"::"r"(vec1):"r2"); asm("fmov.s @r2+,fr0"); asm("fmov.s @r2+,fr1"); asm("fmov.s @r2+,fr2"); asm("fmov.s @r2+,fr3"); asm("add #-16,r2"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("mov %0,r2"::"r"(vec2)); asm("fmov.s @r2+,fr4"); asm("fmov.s @r2+,fr5"); asm("fmov.s @r2+,fr6"); asm("fmov.s @r2+,fr7"); asm("add #-16,r2"); asm("fadd fr4,fr0"); asm("fadd fr5,fr1"); asm("fmov fr8,fr2"); asm("fadd fr6,fr2"); asm("fmov fr2,fr8"); asm("fmov fr9,fr3"); asm("fadd fr7,fr3"); asm("fmov fr3,fr9"); asm("mov %0,r2"::"r"(vec3)); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("add #16,r2"); asm("fmov.s fr3,@-r2"); asm("fmov.s fr2,@-r2"); asm("fmov.s fr1,@-r2"); asm("fmov.s fr0,@-r2"); } Similarly sub4() Available only for sh4. |
void mtrx4mul(float mat1[4][4], float mat2[4][4]) |
extern __inline__ void mtrx4mul(float mat1[4][4], float mat2[4][4]) { asm("mov %0,r2"::"r"(mat1):"r2"); asm("mov %0,r6"::"r"(mat2):"r6"); asm("fmov.s @r2+,fr0"); asm("fmov.s @r2+,fr1"); asm("fmov.s @r2+,fr2"); asm("fmov.s @r2+,fr3"); asm("fmov fr3,fr8"); asm("fmov fr2,fr9"); asm("fmov fr9,fr2"); asm("fmov fr8,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr8"); asm("fmov fr2,fr9"); asm("fmov fr9,fr2"); asm("fmov fr8,fr3"); asm("add #16,r6"); asm("fmov.s fr3,@-r6"); asm("fmov.s fr2,@-r6"); asm("fmov.s fr1,@-r6"); asm("fmov.s fr0,@-r6"); asm("fmov.s @r2+,fr0"); asm("fmov.s @r2+,fr1"); asm("fmov.s @r2+,fr2"); asm("fmov.s @r2+,fr3"); asm("fmov fr3,fr8"); asm("fmov fr2,fr9"); asm("fmov fr9,fr2"); asm("fmov fr8,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr8"); asm("fmov fr2,fr9"); asm("add #32,r6"); asm("fmov fr9,fr2"); asm("fmov fr8,fr3"); asm("fmov.s fr3,@-r6"); asm("fmov.s fr2,@-r6"); asm("fmov.s fr1,@-r6"); asm("fmov.s fr0,@-r6"); asm("fmov.s @r2+,fr0"); asm("fmov.s @r2+,fr1"); asm("fmov.s @r2+,fr2"); asm("fmov.s @r2+,fr3"); asm("fmov fr3,fr8"); asm("fmov fr2,fr9"); asm("fmov fr9,fr2"); asm("fmov fr8,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr8"); asm("fmov fr2,fr9"); asm("add #32,r6"); asm("fmov fr9,fr2"); asm("fmov fr8,fr3"); asm("fmov.s fr3,@-r6"); asm("fmov.s fr2,@-r6"); asm("fmov.s fr1,@-r6"); asm("fmov.s fr0,@-r6"); asm("fmov.s @r2+,fr0"); asm("fmov.s @r2+,fr1"); asm("fmov.s @r2+,fr2"); asm("fmov.s @r2+,fr3"); asm("fmov fr3,fr8"); asm("fmov fr2,fr9"); asm("fmov fr9,fr2"); asm("fmov fr8,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr8"); asm("fmov fr2,fr9"); asm("add #32,r6"); asm("fmov fr9,fr2"); asm("fmov fr8,fr3"); asm("fmov.s fr3,@-r6"); asm("fmov.s fr2,@-r6"); asm("fmov.s fr1,@-r6"); asm("fmov.s fr0,@-r6"); } Available only for sh4. |
void mtrx4muladd( float mat1[4][4], float mat2[4][4], float mat3[4][4]) void mtrx4mulsub( float mat1[4][4], float mat2[4][4], float mat3[4][4]) |
extern __inline__ void mtrx4mulsub(float mat1[4][4], float mat2[4][4],float mat3[4][4]) { asm("mov %0,r6"::"r"(mat1):"r6"); asm("mov %0,r2"::"r"(mat2):"r2"); asm("mov %0,r5"::"r"(mat3):"r5"); asm("fmov.s @r6+,fr0"); asm("fmov.s @r6+,fr1"); asm("fmov.s @r6+,fr2"); asm("fmov.s @r6+,fr3"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov.s @r2+,fr4"); asm("fmov.s @r2+,fr5"); asm("fmov.s @r2+,fr6"); asm("fmov.s @r2+,fr7"); asm("fsub fr4,fr0"); asm("fsub fr5,fr1"); asm("fmov fr8,fr2"); asm("fsub fr6,fr2"); asm("fmov fr2,fr8"); asm("fmov fr9,fr3"); asm("fsub fr7,fr3"); asm("fmov fr3,fr9"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("add #16,r5"); asm("fmov.s fr3,@-r5"); asm("fmov.s fr2,@-r5"); asm("fmov.s fr1,@-r5"); asm("fmov.s fr0,@-r5"); asm("fmov.s @r6+,fr0"); asm("fmov.s @r6+,fr1"); asm("fmov.s @r6+,fr2"); asm("fmov.s @r6+,fr3"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov.s @r2+,fr4"); asm("fmov.s @r2+,fr5"); asm("fmov.s @r2+,fr6"); asm("fmov.s @r2+,fr7"); asm("fsub fr4,fr0"); asm("fsub fr5,fr1"); asm("fmov fr8,fr2"); asm("fsub fr6,fr2"); asm("fmov fr2,fr8"); asm("fmov fr9,fr3"); asm("fsub fr7,fr3"); asm("fmov fr3,fr9"); asm("add #32,r5"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("fmov.s fr3,@-r5"); asm("fmov.s fr2,@-r5"); asm("fmov.s fr1,@-r5"); asm("fmov.s fr0,@-r5"); asm("fmov.s @r6+,fr0"); asm("fmov.s @r6+,fr1"); asm("fmov.s @r6+,fr2"); asm("fmov.s @r6+,fr3"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov.s @r2+,fr4"); asm("fmov.s @r2+,fr5"); asm("fmov.s @r2+,fr6"); asm("fmov.s @r2+,fr7"); asm("fsub fr4,fr0"); asm("fsub fr5,fr1"); asm("fmov fr8,fr2"); asm("fsub fr6,fr2"); asm("fmov fr2,fr8"); asm("fmov fr9,fr3"); asm("fsub fr7,fr3"); asm("fmov fr3,fr9"); asm("add #32,r5"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("fmov.s fr3,@-r5"); asm("fmov.s fr2,@-r5"); asm("fmov.s fr1,@-r5"); asm("fmov.s fr0,@-r5"); asm("fmov.s @r6+,fr0"); asm("fmov.s @r6+,fr1"); asm("fmov.s @r6+,fr2"); asm("fmov.s @r6+,fr3"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("ftrv xmtrx,fv0"); asm("fmov fr3,fr9"); asm("fmov fr2,fr8"); asm("fmov.s @r2+,fr4"); asm("fmov.s @r2+,fr5"); asm("fmov.s @r2+,fr6"); asm("fmov.s @r2+,fr7"); asm("fsub fr4,fr0"); asm("fsub fr5,fr1"); asm("fmov fr8,fr2"); asm("fsub fr6,fr2"); asm("fmov fr2,fr8"); asm("fmov fr9,fr3"); asm("fsub fr7,fr3"); asm("fmov fr3,fr9"); asm("add #32,r5"); asm("fmov fr8,fr2"); asm("fmov fr9,fr3"); asm("fmov.s fr3,@-r5"); asm("fmov.s fr2,@-r5"); asm("fmov.s fr1,@-r5"); asm("fmov.s fr0,@-r5"); } Similarly mtrx4muladd(). Available only for sh4. |
void ld_ext( float mat[4][4] ) |
extern __inline__ void ld_ext( float mat[4][4]) { asm("mov %0, r2"::"r"(mat):"r2"); asm("frchg"); asm("fmov.s @r2+,fr0":::"fr0"); asm("fmov.s @r2+,fr1":::"fr1"); asm("fmov.s @r2+,fr2":::"fr2"); asm("fmov.s @r2+,fr3":::"fr3"); asm("fmov.s @r2+,fr4":::"fr4"); asm("fmov.s @r2+,fr5":::"fr5"); asm("fmov.s @r2+,fr6":::"fr6"); asm("fmov.s @r2+,fr7":::"fr7"); asm("fmov.s @r2+,fr8":::"fr8"); asm("fmov.s @r2+,fr9":::"fr9"); asm("fmov.s @r2+,fr10":::"fr10"); asm("fmov.s @r2+,fr11":::"fr11"); asm("fmov.s @r2+,fr12":::"fr12"); asm("fmov.s @r2+,fr13":::"fr13"); asm("fmov.s @r2+,fr14":::"fr14"); asm("fmov.s @r2+,fr15":::"fr15"); asm("frchg"); asm("add #-64,r2"); } Available only for sh4. |
void st_ext(float mat[4][4]) |
extern __inline__ void st_ext(float mat[4][4]) { asm("mov %0,r2"::"r"(mat):"r2"); asm("add #64,r2"); asm("frchg"); asm("fmov.s fr15,@-r2"); asm("fmov.s fr14,@-r2"); asm("fmov.s fr13,@-r2"); asm("fmov.s fr12,@-r2"); asm("fmov.s fr11,@-r2"); asm("fmov.s fr10,@-r2"); asm("fmov.s fr9,@-r2"); asm("fmov.s fr8,@-r2"); asm("fmov.s fr7,@-r2"); asm("fmov.s fr6,@-r2"); asm("fmov.s fr5,@-r2"); asm("fmov.s fr4,@-r2"); asm("fmov.s fr3,@-r2"); asm("fmov.s fr2,@-r2"); asm("fmov.s fr1,@-r2"); asm("fmov.s fr0,@-r2"); asm("frchg"); } Available only for sh4. |
GNU C library namely Newlib is under free software license. The Newlib supports various processors and architectures.
1. Complete set of
Standard input/output functions.
2. Float parameters support
for Math library.
3. The library can be built with integer only
support. This in turn reduces the load.
4. Option is available
to build the libraries with floating point support.
5. A
customizable math error handler matherr() is available.
6. All
the functions are reentrant.
Drawbacks Involved:
1. malloc() is used in every stdio
routine.
2. There is no support for low-level routines to
connect to the target.
No. | Function |
General Utilities (stddef.h) | |
1 | offsetof |
C library Math Functions only in GNU:
No. | Function | Description |
Character type handling routines (ctype.h) | ||
1 | Isascii | ASCII character predicate |
2 | Toascii | Control character predicate |
3 | Iswalnum | Alphanumeric wide character test |
4 | Iswalpha | Alphabetic wide character test |
5 | Iswcntrla | Wide character cntrl test |
6 | Iswdigit | Decimal digit wide character test |
7 | Iswgraph | Graphic wide character test |
8 | Iswlower | Lowercase wide character test |
9 | Iswprint | Printable wide character test |
10 | Iswpunct | Punctuation wide character test |
11 | Iswspace | Wide character space test |
12 | Iswupper | Uppercase wide character test |
13 | Iswxdigit | Hexadecimal digit wide character test |
14 | Iswctype | Extensible wide character test |
15 | Wctype | Get wide character classification type |
16 | *Towlower | Translate wide characters to lower case |
17 | *Towupper | Translate wide characters to upper case |
18 | Towctrans | Extensible wide character case mapping |
19 | Wctrans | Get wide character translation type |
No. | Function | Description |
Mathematics Functions (math.h) | ||
1 | acosh, acoshf | Inverse hyperbolic cosine |
2 | asinh, asinhf | Inverse hyperbolic sine |
3 | atanh, atanhf | Inverse hyperbolic tangent |
4 | jN,jNf,yN,yNf | Bessel functions |
5 | erf, erff, erfc, erfcf | Error function |
6 | gamma, gammaf, lgamma, lgammaf, gamma_r, hypot, hypotf | Distance from origin |
7 | isnan, isnanf, isinf, isinff, finite, finitef | Test for exceptional numbers |
8 | remainder, remainderf | Round and remainder |
9 | cbrt, cbrtf | Cube root |
10 | copysign, copysignf | Sign of y, magnitude of x |
11 | expm, expmf | Exponential minus 1 |
12 | ilogb, ilogbf | Get exponent of floating point number |
13 | infinity, infinityf | Representation of infinity |
14 | logp, logpf | Log of 1 + x |
15 | Matherr | Modifiable math error handler |
16 | nan, nanf | Representation of infinity |
17 | nextafter, nextafterf | Get next number |
18 | scalbn, scalbnf | Scale by integer |
No. | Function | Description |
General Utilities (stdlib.h) | ||
1 | Atexit | Request execution of functions at program exit |
2 | Atoff | String to double or float |
3 | Ecvt, ecvtf, fcvt, fcvtf | Double or float to string |
4 | Gvcvt, gcvtf | Format double or float as string |
5 | Ecvtbuf, fcvtbuf | Double or float to string |
6 | __env_lock, __env_unlock | Lock environ variable |
7 | Getenv | Look up environment variable |
8 | Mallinfo, malloc_stats, mallopt | Malloc support |
9 | __malloc_lock, __malloc_unlock | Lock malloc pool |
10 | Mblen | Minimal multibyte length function |
11 | Mbstowcs | Minimal multibyte string to wide char converter |
12 | Mbtowc | Minimal multibyte to wide char converter |
13 | Rand48, drand48, erand48, lrand48, nrand48, mrand48, jrand48, srand48, seed48, lcong48 | Pseudo random number generators and initialization routines |
14 | Strtof | String to double or float |
15 | System | Execute command string |
16 | Wcstombs | Minimal wide char string to multibyte string converter |
17 | Wctomb | Minimal wide char to multibyte converter |
No. | Function | Description |
String and Memory routines (string.h) | ||
1 | Bcmp | Compare two memory areas |
2 | Bcopy | Copy memory regions |
3 | Bzero | Initialize memory to zero |
4 | Index | Search for character in string |
5 | Memccpy | Copy memory regions with end token check |
6 | Mempcpy | Copy memory regions and return end pointer |
7 | Rindex | Reverse search for character in string |
8 | Strcasecmp | Case insensitive character string compare |
9 | Strlwr | Force string to lower case |
10 | Strncasecmp | Case insensitive character string compare |
11 | strtok_r,strsep | Get next token from a string |
12 | Strupr | Force string to uppercase |
13 | Swab | Swap adjacent bytes |
No. | Function | Description |
Input/output routines (stdio.h) | ||
1 | Fgetpos | Record position in a stream or file |
2 | Fiprintf | Format output to file (integer only) |
3 | Fdopen | Turn open file into a stream |
4 | Freopen | Open a file using an existing file descriptor |
5 | fseeko | Set file position |
6 | Fsetpos | Restore position of a stream or file |
7 | ftello | Return position in a stream or file |
8 | Getw | Read a word (int) |
9 | Iprintf | Write formatted output (integer only) |
10 | mktemp, mkstemp | Generate unused file name |
11 | Putw | Write a word (int) |
12 | Remove | Delete a file's name |
13 | Rename | Rename a file |
14 | Setbuf | Specify full buffering for a file or stream |
15 | Siprintf | Write formatted output (integer only) |
16 | asprintf, snprintf | Format output |
17 | Tmpfile | Create a temporary file |
18 | Tmpnam, | Name for a temporary file |
Large file input / output: | ||
19 | Fopen64 | Open a large file |
20 | Freopen64 | Open a large file using an existing file descriptor |
21 | Ftello64 | Return position in a stream or file |
22 | Fseeko64 | Set file position for large file |
23 | Fgetpos64 | Record position in a large stream or file |
24 | Fsetpos64 | Restore position of a large stream or file |
25 | Tmpfile64 | Create a large temporary file |
Along with all the above, following set of routines are provided in the newlib library:
1. Wide character strings (wchar.h):
Please refer http://sources.redhat.com/newlib/libc.html#SEC144
2. Signal handling (signal.h):
Please refer http://sources.redhat.com/newlib/libc.html#SEC169
3. Time functions (time.h):
Please refer http://sources.redhat.com/newlib/libc.html#SEC172
4. Locale specific routines (locale.h):
Please refer http://sources.redhat.com/newlib/libc.html#SEC183
Useful Links:
http://sources.redhat.com/newlib/libc.html
http://sources.redhat.com/newlib/libm.html
We can instruct the compiler to insert the code of a function into the code of its callers, to the point where actually the call is to be made. Such functions are inline functions. This method of inlining reduces the function-call overhead. And if any of the actual argument values are constant, their known values may permit simplifications at compile time so that not all of the inline function’s code needs to be included. The effect on code size is less predictable, it depends on the particular case. To declare an inline function, we’ve to use the keyword inline in its declaration. Inline assembly is important primarily because of its ability to operate and make its output visible on C variables. Because of this capability, "asm" works as an interface between the assembly instructions and the "C" program that contains it.
Syntax
GCC, the GNU C Compiler for Linux, uses AT&T UNIX assembly syntax.
a) Source-Destination Ordering
The first operand is the source and the second operand is the destination. ie, "Op-code src dst".
This is similar to the syntax followed in Renesas.
b) Register Naming
Register names are prefixed by % i.e., if r0 is to be used, write %r0.
c) Immediate Operand
Immediate operands are preceded by ’#’. For hexadecimal constants a ’0x’ is suffixed to the constant.
However, in order to support hexadecimal constants suffixed with a 'H', please pass ‘-h-tick-hex’ option to the assembler.
e.g., Use the following command to build the “asm("mov #H'03,R0");” code statement, $ sh-elf-gcc test.c -Wa,-h-tick-hexd) Operand Size
Size of memory operands is determined from the last character of the op-code name.
Op-code suffixes of ’b’, ’w’, and ’l’ specify byte(8-bit), word(16-bit), and long (32-bit) memory references.
e) Memory Operands
Base register is enclosed in ‘(’ and ’)’ and indirect memory reference is like
“section:disp(base, index, scale)”. When a constant is used for disp and sol; scale, ’#’ shouldn’t be prefixed