EmbeddedRelated.com
Forums

Re: How to force the C-compiler to use registers?

Started by Preston Gurd May 26, 2004
Hi Dirk,

> I could think in asm, and I absolutely have to at
least when I design
> the HAL.
> But in all layers above that I don't want to care at all, if this
> algorithm is run on an MSP, a PC, my coffee-machine or fed into "The
> Matrix".

I've been following part of this thread with interest, and I agree here
100%,
regardless of any other moot issues.
I work a lot with single chip RF transceivers.
Now, I've written a Hardware Abstraction Library for many different RF
parts.

One client has moved on to 3 different RF parts : in each case it took me <
20 mins.
to bolt on the existing complete C coded DLL + network application to the new
HAL.
He's moved from IAR EW90 (on 8535 AVR) to ICC-AVR : it took me < 5 mins
to
recompile the project, no bugs, no side effects, no HW problems.
At one stage I've actually even debugged a new HAL on MSP430 RF Hardware
with
RAL CW430, and then ported it back to ICC-AVR and recompiled it, effortlessly.
The API only has a few simple user calls for the APP, and - admittedly - it is a

relatively simple application.
But the point is that porting the whole application code from MSP430 -> AVR
and 
AVR-> MSP430 took < 5 mins. I'd HATE to do this in ASM !!!!
(of course you'd only have to do this once !)
This client id considering going to ARM. When he does it will again take me
little effort to rebuild the machine code on ARM.

This is of course a specific example, but I'm from the other
"school" :
I wrote solely in ASM for quite a few years, and since about 6 years I
couldn't
imagine running a business efficiently without the use of C and respective
compilers.

The rest is indeed moot. Just like the issue of C++ and OOP is.
OOP is a programming concept, not a language. I'm actually trying to write
more
and more in what I guess is called "C+" rather than C if it's
worth it.
Eventually I'd like to learn more about EC++.

B rgds
Kris





Beginning Microcontrollers with the MSP430

Dirk Reymann <d.reymann@d.re...> writes:

> inline int IsVoltageAboveTheshold(void)
> {
>     CACTL = SOME_PATTERN;   // set up the comparator
>     _NOP();                 // wait for settling
>     return (!(CACTL & CAOUT));
> }
>
>
> inline int Signal(int state)
> {
>     if ( state == -1 )
>        P1OUT &= ~ BIT2;
>
>     if ( state == 1 )
>        P1OUT |= BIT2;
>
>     return ( P1OUT & BIT2 );
> }
>
> void main(void)
> {
>     if ( IsVoltageAboveTheshold() )
>       Signal( 1 );
> }

> --------------------------------
> I'm looking forward to any suggestions how to "improve" the
inlined
> functions above.
> Do NOT change main().
> --------------------------------

In the example above the Signal function returns a value.  This value
contains a read from a volatile.  Since volatile accesses musn't be
changed all compiler must generate code to perform this access, even
if your code ignores the return value from Signal.

You can see this in the generated code:

     29                Signal( 1 );
         \\ This performs the side-effects.
   \   000010   E2D22100             BIS.B   #0x4, &0x21

         \\ This is the remainder of the return statement of Signal.
   \   000014   C2932100             CMP.B   #0x0, &0x21

What you could do is to redefine Signal so that it doesn't return a
value at all, and implement a second function that does, for example
(using a ridiculously long name for the new function):


inline void Signal(int state)
{
    if ( state == -1 )
       P1OUT &= ~ BIT2;

    if ( state == 1 )
       P1OUT |= BIT2;
}

inline int SignalAndReturnStatus(int state)
{
   Signal(state)
   return ( P1OUT & BIT2 );
}


The effect is a four byte reduction for each call site where the
return value of Signal is discarded.

I would guess that you would get an improvment for this on all
compilers on the market, not just when using our tools.

    -- Anders Lindgren, IAR Systems
-- 
Disclaimer: Opinions expressed in this posting are strictly my own and
not necessarily those of my employer.

Dirk Reymann wrote:
> So my wish would be:
> 
> IAR - please add a register feature like QA430 does.
> 
> Quadravox - please improve your optimizer  (inlining, dead-code).
> 
> If both of you did so, we had two extremely effective compilers for
> our MSP430.

Did you try MSPGCC? In my experience it generates much better code than 
IAR in some cases. Just post a piece of code and let's see what the 
different compilers make out of it.


Hi Kris.

As we've discussed often before it's very much horses for courses. I 
NEVER expect to have to port anything I design to another micro. Even if 
I do the time taken is trivial. Not as fast as porting using compilers 
from the same vendor perhaps, but almost certainly faster than porting 
using a new compiler. My own course through programming was rather odd. 
Not counting the valve circuit that added two unitary numbers and gave 
the result on nixie tubes which I built around 1965. Staring around 
1970, and in the following approximate order:-

custom binary with LOGIC GATE BASED computers of my own design.
hexa decimal with early micros (4004/8008)
Custom medium level language for military digital radar
6800 asm
128bit mainframe binary
128 bit micro-code (Eureka! moment when I discovered this)
COBOL
6502 asm
8048 hex
6809 asm
8080 asm
8085 asm
BASIC
8051 asm
LISP
Modula (can't remember I or II)
PROLOG
C
80x86 asm & C
8087 asm
ADA
Relay ladder
Pascal (yeuk)
PIC asm (pre-microchip)
C++ (a JOKE)
68k asm & C
ADSP21XX	(THE BEST LANGUAGE OF THEM ALL)
68HC various & C
ADSP SHARC asm & C
TMS 320C3x asm
FAIRCHILD ASM
AVR ASM
OTHER TMS320FXXXX ASMS
MSP430
56F800 ASM
ARM ASM

As you know, I'm the opposite, even though we work in similar areas. I 
too do a lot of designs with a wide variety of sibngle chip 
transceivers. I can't imagine doing my designs without asm. It's okay 
writing a HAL that is all singing all dancing, but its very abstraction 
will usually, in my experience, force compromise on the  actaul hardware 
interface level which I'm not prepared to accept. Rather I have 
configuration libraries for various different parts, and a common 
protocol library, thus I'm implicitly NOT abstracting the hardware,
I'm 
getting very close up and personal to it, but I am, to some degree 
abstracting the higher level functions, again almost the opposite to 
yourself and Dirk.

Perhaps this is because my original interest was hardware, and my 
preference for many years was hardware. Software was merely something 
the hardware used to give itself adaptive functionality. Once hardware 
became, to some extent, boring, or less challenging, software in and of 
itself became more interesting., however, since I still believe that 
better designs are created when both areas are well understood, I have 
never been attracted to the idea of hardware abstraction, in fact it is 
anathema to me.

cheers

Al




microbit wrote:
> Hi Dirk,
> 
> 
>>I could think in asm, and I absolutely have to at least when I design
>>the HAL.
>>But in all layers above that I don't want to care at all, if this
>>algorithm is run on an MSP, a PC, my coffee-machine or fed into
"The
>>Matrix".
> 
> 
> I've been following part of this thread with interest, and I agree
here 100%,
> regardless of any other moot issues.
> I work a lot with single chip RF transceivers.
> Now, I've written a Hardware Abstraction Library for many different RF
parts.
> 
> One client has moved on to 3 different RF parts : in each case it took me
< 20 mins.
> to bolt on the existing complete C coded DLL + network application to the
new HAL.
> He's moved from IAR EW90 (on 8535 AVR) to ICC-AVR : it took me < 5
mins to
> recompile the project, no bugs, no side effects, no HW problems.
> At one stage I've actually even debugged a new HAL on MSP430 RF
Hardware with
> RAL CW430, and then ported it back to ICC-AVR and recompiled it,
effortlessly.
> The API only has a few simple user calls for the APP, and - admittedly - it
is a 
> relatively simple application.
> But the point is that porting the whole application code from MSP430 ->
AVR and 
> AVR-> MSP430 took < 5 mins. I'd HATE to do this in ASM !!!!
> (of course you'd only have to do this once !)
> This client id considering going to ARM. When he does it will again take me
> little effort to rebuild the machine code on ARM.
> 
> This is of course a specific example, but I'm from the other
"school" :
> I wrote solely in ASM for quite a few years, and since about 6 years I
couldn't
> imagine running a business efficiently without the use of C and respective
compilers.
> 
> The rest is indeed moot. Just like the issue of C++ and OOP is.
> OOP is a programming concept, not a language. I'm actually trying to
write more
> and more in what I guess is called "C+" rather than C if
it's worth it.
> Eventually I'd like to learn more about EC++.
> 
> B rgds
> Kris
> 
> 
> 
> 
> 
> 
> 
> .
> 
>  
> Yahoo! Groups Links
> 
> 
> 
>  
> 
> 


Hello Dirk,

I have just finished reading, with great interest, your comments about
your experience with using the AQ430 C compiler for your application.
I have also looked at Wolfgang Reich's practical suggestions and your
response to them, and at Anders Lindgren's comments, as well.

I gather that you try to inline just about every function call in your
application and that the AQ430 C compiler is not as good at handling your
code as the IAR compiler, although you can get pretty close.

First of all, I should point out that, in AQ430 C, any inline function
which is only ever called to be expanded inline (as opposed to calling
it externally or indirectly) should be declared as static. If you do not
declare it as static, then the compiler emits a function body, taking up
more space. So you should use

	static __inline__ 

Since the "embedded C" standard appears to say that you should only
get a function body if you say "extern inline", the default behavuour
of the compiler may change sometime soon, but "static __inline__" will
always do what is reasonable to expect.

You noted that the compiler does not appear to do dead code elimination.
This is not quite true! The compiler does in fact do dead code elimination
*most* of the time!
However, If a function is expanded inline and one of the variables
in the expansion is replaced by a constant argument, then the compiler
does not by default look to eliminate any dead code introduced as
a result of the substitution of the variable by the constant. 

However, if you turn on the global optimizer (by using "+O" C
compiler
command line option), then you will get a much higher level of optimization
(but you will lose the ability to symbolically debug the code thus optimized).
For the following code sample, based on the one which you posted:

#define __AQCOMPILER__
#define inline __inline__
#include "msp430x14x.h"

static inline int IsVoltageAboveTheshold(void)
{
    CACTL1 = 2;   // set up the comparator
    _NOP();                 // wait for settling
    return (!(CACTL1 & CAOUT));
}


static inline int Signal(int state)
{
    if ( state == -1 )
       P1OUT &= ~ BIT2;
       
    if ( state == 1 )
       P1OUT |= BIT2;
       
    return ( P1OUT & BIT2 );
}

void main(void)
{
    if ( IsVoltageAboveTheshold() )
      Signal( 1 );
}


The code size with default optimization was 56 bytes. With +O, it is
30 bytes. Among other things, it eliminates the redundant compares
of 1 ("state") to 1 and -1 in the inline expansion of Signal().

You also mentioned a problem with starting by double clicking the project
file. This is now fixed and will be in the next release. If you would
like to obtain a fixed version earlier, please send email to
aq430support@aq43... .
 
I appreciate your taking the time to study this issue and for sharing
what you found with the msp430 community. It had not occurred to me that
people might want to use inline functions in the way you have done. As a
result of your comments, I will be looking into ways to improve AQ430 C's
handling of inline functions.

If you have any other suggestions for improvement of the AQ430 C code generator,
please do not hesitate to get in touch with me directly. 

All the best,

Preston Gurd
(the AQ430 C compiler guy)