Preface


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.

Compiler Options


Renesas Compiler Options

Equivalent GCC compiler options
 

-include = <path name>[,…]
Include paths.

-I<path>
 

-preinclude = <file name>[,...]
Includes the specified files at the head of compiled files.

-include <file>
 

-define = <sub> [,…]
<sub>: <macro name> [ = <string literal>]

Defines <string literal> as <macro name>

-D<macro>
 

-nomessage [ = <error code> [- <error code>] [,…] ]
Specifies whether to output information-level messages.

-w
 

-preprocessor [= <file name>]
Preprocessor to named file.

-E -o filename
 

-object [= <object file name>]
Set object filename.

-o filename
 

-Code=Asmcode -object=<file name>]
Assembly output to named file.

-S filename
 

-debug
Generate debug information.

-g[level]
 

-string = { Const | Data }
Outputs string literal to constant or data sections.

-fwritable-strings
 

-template = { None | Static | Used | All | AUto }
Specifies the condition to generate template instances.

-fno-implicit-templates
 

-List [= <file name>]
Assembly output to prefixed List filename.

-Wa, -al=file
 

-show=<sub>[,...]
<sub>: {source | nosource |
object | noobject |
statistics | nostatistics |
allocation | noallocation |
expansion | noexpansion |
width = <numeric value> |
length = <numeric value> |
tab = { 4 | 8 } }

Specifies the contents and format of the list output by the compiler, and the cancellation of list output.

-a[sub-option...]

Sub-options [default hls]:
c omit false conditionals
d omit debugging directives
h include high-level source
l include assembly
m include macro expansions
n omit forms processing
s include symbols
=FILE list to FILE (must be last sub-option)

 

-speed = <sub> [,…]
<sub>:{register shiift |
loop [ = { 1 | 2 } ] | switch |
inline[=<numeric value>] |
struct | expression}

Speed optimization

-O[1-3]
 

-optimize = { 0 | 1 }
Optimize for size.

-Os
 

-comment
Enables nested comments to be written.

By default enabled. To generate warning for nested comments use option.
-Wcomment
 

-macsave
The contents of the MAC register always remain unchanged after an interrupt function is called.

-mnomacsave
 

-pack
Specifies the boundary alignment of structures, unions, and class members.

-fpack-struct
 

-volatile

When volatile is specified, the compiler does not optimize external variables.

-fvolatile
 

-cmncode
Common subexpression elimination

-fgcse
 

-align16
Align labels after unconditional branches are aligned to a 16 byte boundary.

-falign
 

-loop
Performs loop unrolling.

-funroll-all-loops
 

-cpu = {sh1|sh2|sh2e|sh3|sh4}

-m1 –m2 –m2e –m3 –m4
 

-endian = { big | little }
[SH-3 - SH-4]
specifies Endian type.

-mb or –ml
 

-fpu= {single | double}
[SH-4]
Processes floating-point operation in single or double precision.

-fsingle-precision-constant
 

-pic= { 0 | 1 }
Position independent code

-fpic
 

-double=float
Converting double-type values to Float-type values.

-fshort-double
 

-rtti = { ON |OFf }
Controlling runtime type information.

-fno-rtti
 

-exception
Enables the C++ exception processing (try, catch, throw).

-fexceptions
 

-lang = { C | CPp }
Specifies the language of the source program.

-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.

Compiler Directives


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  :{*(_cseg);} > memory region [ram/rom]
 
#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>”)))
For e.g:
extern void foobar (void) __attribute__ ((section ("bar")));

Alternatively, this can be achieved using the linker script. In section definition, the contents of an output section can be specified by listing particular input files, listing particular input-file sections, or combination of the two.
Please refer Q2 in FAQ.html for more on linker scripts.

#pragma inline_asm (<function name>
[(size=numeric value)][,...])

Asm(<assembly-language instruction string>);

For more information on the above compiler directives, please refer to the gcc manual.

Assembler Directives


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>
(for details on more options of aligning like filling specific values,etc, please see link below)

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.

Intrinsic Functions


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.

C/Math Library Functions


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.

C library Math Functions only in Renesas:

No. Function
General Utilities (stddef.h)
1 offsetof

C library Math Functions only in GNU:

No. Function Description

Character type handling routines (ctype.h)

Please refer the http://sources.redhat.com/newlib/libc.html#SEC35 for more information on these routines.

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)

Please refer the http://sources.redhat.com/newlib/libm.html#SEC1 for more information on these routines.

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)

Please refer the http://sources.redhat.com/newlib/libc.html#SEC1 for more information on these routines.

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)

Please refer the http://sources.redhat.com/newlib/libc.html#SEC109 for more information on these routines.

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)

Please refer the http://sources.redhat.com/newlib/libc.html#SEC67 for more information on these routines.

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

Inline Assembly


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-hex

d) 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&colon;disp(base, index, scale)”. When a constant is used for disp and sol; scale, ’#’ shouldn’t be prefixed