GCC Optimisation (Good or Bad)

Go To Last Post
36 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am about to start a project in which the proper choice of micro is the up-and-coming mega329 which will have LCD & 32K flash. As usual with Atmel products, it is late, so I must use the mega169.

My project will come close to overflowing the 16K flash of the mega169, so I must write my code with space efficiency in mind. To this end I have read Atmel's AppNote AVR035 (DOC1497.PDF) which describes procedures for efficient programming and gives Eighteen Hints to Reduce Code Size using IAR c compiler.

I've been coding some examples (using the standard WinAVR makefile) to see how these tips can be applied to GCC but have discovered the following anomolies:

Does anyone know how to make GCC behave itself and produce optimal code ?

1. INDIRECT ACCESS OF GLOBAL VARIABLES

In the following example a 32-Bit global variable is incremented, this is expensive in flash use because it involves 8 accesses.
I attempt to reduce the code size by using indirection

extern unsigned long RealTime;

void NewSecond (void)
{
unsigned long *s=&RealTime;

(*s)++;
}
GCC thinks it knows how to optimize code better than I do and has made a right pig's ear of it as follows:

	lds r24,RealTime
	lds r25,(RealTime)+1
	lds r26,(RealTime)+2
	lds r27,(RealTime)+3
	adiw r24,1
	adc r26,__zero_reg__
	adc r27,__zero_reg__
	sts RealTime,r24
	sts (RealTime)+1,r25
	sts (RealTime)+2,r26
	sts (RealTime)+3,r27


What I wanted was: (some 12-Bytes shorter)
	ldi r30,lo8(RealTime)
	ldi r31,hi8(RealTime)
	ld r24,Z
	ldd r25,Z+1
	ldd r26,Z+2
	ldd r27,Z+3
	adiw r24,1
	adc r26,__zero_reg__
	adc r27,__zero_reg__
	st Z,r24
	std Z+1,r25
	std Z+2,r26
	std Z+3,r27

2. BOOLEAN VARIABLES

GCC has a built-in type called _Bool , try it , it makes the compiler assign only the values 0 & 1 to variables of this type which is of size 1-Byte; unfortunately they do not pack.

I have written a command interpreter which contains many instances of the line:

if (bParseError) { CmdError() return; }

Where bParseError is of type _Bool. If this were coded optimally I would save hundreds of bytes of flash because it is used so many times.

I've read many recent posts concerning booleans, I could not find an optimal solution.

The newer mega AVRs have dedicated SFR registers to facilitate efficient packed booleans. In the mega169, located in the bit-addressable section, there is GPIOR0. To use this I could write lines like

#define PARSE_ERROR  0x80
#define ANOTHER_FLAG 0x40

if (GPIOR0 & PARSE_ERROR)  GPIOR0|=ANOTHER_FLAG;

This is not very readable but GCC does generate optimal code:

	sbic 62-0x20,7
	sbi 62-0x20,6

To improve readability I tried a bit-field like this:

typedef struct { 
 _Bool f0:1; 
 _Bool f1:1; 
 _Bool f2:1; 
 _Bool f3:1; 
 _Bool f4:1; 
 _Bool f5:1; 
 _Bool f6:1; 
 _Bool f7:1; 
} PackedBool;

#define bParseError ( (PackedBool*)(&GPIOR0) )->f7
#define bAnotherFlag ( (PackedBool*)(&GPIOR0) )->f6

void Command (void)
{
if (bParseError)
	bAnotherFlag=1;
}

GCC generates:
	in r24,62-0x20
	andi r24,lo8(-128)
	breq .L1

	ori r25,lo8(64)
	out 62-0x20,r25
  .L1

This is an improvement on my original but still not optimal.

Does anyone have any suggestions on this? Atmel in their AppNote AVR035 suggest using the not-so-readable Bit-Masks which are capable of generating optimal code.

3. GCC REUSES REGISTERS WHICH CONTAIN "USEFUL" VALUES INSTEAD OF RELOADING

In this example

extern char Status;

char Function (void)
{
if (!(Status & 4)) return 0;
return 2;
}

GCC produces this complete mess:

lds r24,Status
clr r25
movw r18,r24
andi r18,lo8(4)
andi r19,hi8(4)
sbrc r24,2
rjmp .L2
movw r24,r18
.LM3:
ret
.L2:
.LM4:
ldi r24,lo8(2)
ldi r25,hi8(2)
.LM5:
ret
ret

Here GCC has reused r18/r19 to movw into r24/r25 causing the function to return 0. It therefore cannot optimize out the 2 andi instructions or even the movw r18,r24.

I can prevent most this stupidity by making the function return 1.
The double return is a mystery it probably requires another different optimization pass to remove it.

char Function (void)
{
if (!(Status & 4)) return 1;
return 2;
}

lds r24,Status
sbrc r24,2
rjmp .L2
ldi r24,lo8(1)
ldi r25,hi8(1)
.LM3:
ret
.L2:
.LM4:
ldi r24,lo8(2)
ldi r25,hi8(2)
.LM5:
ret
ret

Does anyone know how to prevent this register resuse causing extra code ?

Nigel Winterbottom

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Two comments--

What optimization flags are you using? I usually use -Os which selects optimizations to reduce code size.

#define PARSE_ERROR  0x80
#define ANOTHER_FLAG 0x40

if (GPIOR0 & PARSE_ERROR)  GPIOR0|=ANOTHER_FLAG;

This is not very readable but GCC does generate optimal code:

   sbic 62-0x20,7
   sbi 62-0x20,6

There's no reason to put that all on one line.

if( GPIOR0 & PARSE_ERROR ) {
     GPIOR0 |= ANOTHER_FLAG;
}

should generate identical code.

I'd like to see a rerun of your examples with some optimization flags used during the compilation.

Bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My examples were all compiled using the standard WinAVR makefile which uses -Os. I've found that there really is no point in using any other setting it's almost a "one size fits all".

By "readable" I meant that I want to read something like

if (bParseError)  bAnotherFlag=TRUE;

PS
If any of you wish to mess about and experiment without tinkering with makefiles you can create a tool entry in programmers notepad under the C/C++ scheme, name it something sensible; "GCC" The commmand is "make.exe" and the Parameters are "%n.o". Ensure capture output is ticked and save

Now when editing a C file you will have an option under tools called GCC that will compile just that file being edited.

Most Useful...

Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, naturally, those tricks are highly tuned for IAR, since
obviously, each and any compiler has their own parser and optimizer
strategies. As you can see, GCC doesn't even care about your
additionally declared pointer -- it would encode the sequence
identical, regardless of whether you use a pointer variable or not.

I think this:

unsigned long RealTime;
unsigned long *rtp = &RealTime;

...

(*rtp)++;

does what you want. It works by forcing GCC into using the pointer
since the variable rtp has external linkage (as opposed to be local to
the function in your case), so the compiler must not make assumptions
about its contents (it could e.g. have been changed from another
source file), and has to use the pointer register.

Of course, it would be nice if AVR-GCC knew a bit better that the
above yields shorter code even in the standard case, so it could use
this sequence when optimizing for space.

For single-bit variables, I tend to use bitfields. In my case, I'm
frequently using it to flag a particular interrupt has been occured,
and process the event in the main loop.

struct {
unsigned char bit1: 1;
} flags;

...

if (flags.bit1)
...

This produces SBRS instructions, which looks quite optimal for me.

Summary: for GCC, a similar set of rules for efficient coding would
have to be written.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried the new atmel-gcc beta (13.7.2004) but it didn't compress the access to a long-variable in lTest++ like you suggested (ldi, ldi ld ldd,.. instead of lds,lds...). It's just a hint!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tried Jörg Wunsch's idea of:

unsigned long RealTime;
unsigned long *rtp = &RealTime;

This worked but of course requires 2-Bytes of SRAM and 2-Bytes flash of initialise it
plus 2 LDS instructions instead of LDI instructions.

As a matter of interrest changing:
unsigned long *rtp = &RealTime; to /unsigned long * const rtp = &RealTime;
resulted in exactly the assembly as my original attempt.

I''ll save this one for a rainy day & not use it as a matter of course.

I'll keep my fingers crossed that someone knows how to disable this optimmisation.

Hello neruem,

Can you tell me what optimisation level you chose in the Atmel GCC release ?

Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.Winterbottom wrote:

1. INDIRECT ACCESS OF GLOBAL VARIABLES

In the following example a 32-Bit global variable is incremented, this is expensive in flash use because it involves 8 accesses.
I attempt to reduce the code size by using indirection

extern unsigned long RealTime;

void NewSecond (void)
{
unsigned long *s=&RealTime;

(*s)++;
}
GCC thinks it knows how to optimize code better than I do and has made a right pig's ear of it as follows:

	lds r24,RealTime
	lds r25,(RealTime)+1
	lds r26,(RealTime)+2
	lds r27,(RealTime)+3
	adiw r24,1
	adc r26,__zero_reg__
	adc r27,__zero_reg__
	sts RealTime,r24
	sts (RealTime)+1,r25
	sts (RealTime)+2,r26
	sts (RealTime)+3,r27


What I wanted was: (some 12-Bytes shorter)
	ldi r30,lo8(RealTime)
	ldi r31,hi8(RealTime)
	ld r24,Z
	ldd r25,Z+1
	ldd r26,Z+2
	ldd r27,Z+3
	adiw r24,1
	adc r26,__zero_reg__
	adc r27,__zero_reg__
	st Z,r24
	std Z+1,r25
	std Z+2,r26
	std Z+3,r27

What are you talking about? In the second example above, IMHO you're wrong where you said it was 12 bytes shorter. Each of the opcodes in both examples are 16 bits. The first example has 11 opcodes (22 bytes) and the second example is 13 opcodes (26 bytes). So the second example is 4 bytes longer than the first.

N.Winterbottom wrote:

2. BOOLEAN VARIABLES

GCC has a built-in type called _Bool , try it , it makes the compiler assign only the values 0 & 1 to variables of this type which is of size 1-Byte; unfortunately they do not pack.

1. I would suggest staying away from any built-in types. GCC comes with stdbool.h (#include ) which gives you the type bool and you can assign true and false. This is IIRC a C99 standard header file.

2. Why would you assume that they would pack? It's not in the GCC documentation AFAIK, that bools pack into a byte. That's called a bitfield struct in C IIRC. :wink:

N.Winterbottom wrote:

Does anyone have any suggestions on this? Atmel in their AppNote AVR035 suggest using the not-so-readable Bit-Masks which are capable of generating optimal code.

Yes. Follow Atmel's suggestion. If you want bit masks that can be readable, then see this:
https://www.avrfreaks.net/phpBB2/viewtopic.php?t=8764&highlight=programming+101
Go down to the post that starts with "Programming 101"; it should be highlighted.

N.Winterbottom wrote:

3. GCC REUSES REGISTERS WHICH CONTAIN "USEFUL" VALUES INSTEAD OF RELOADING

In this example

extern char Status;

char Function (void)
{
if (!(Status & 4)) return 0;
return 2;
}

GCC produces this complete mess:

lds r24,Status
clr r25
movw r18,r24
andi r18,lo8(4)
andi r19,hi8(4)
sbrc r24,2
rjmp .L2
movw r24,r18
.LM3:
ret
.L2:
.LM4:
ldi r24,lo8(2)
ldi r25,hi8(2)
.LM5:
ret
ret

Here GCC has reused r18/r19 to movw into r24/r25 causing the function to return 0. It therefore cannot optimize out the 2 andi instructions or even the movw r18,r24.

I can prevent most this stupidity by making the function return 1.
The double return is a mystery it probably requires another different optimization pass to remove it.

char Function (void)
{
if (!(Status & 4)) return 1;
return 2;
}

lds r24,Status
sbrc r24,2
rjmp .L2
ldi r24,lo8(1)
ldi r25,hi8(1)
.LM3:
ret
.L2:
.LM4:
ldi r24,lo8(2)
ldi r25,hi8(2)
.LM5:
ret
ret

Does anyone know how to prevent this register resuse causing extra code ?

1. The double ret has been discussed here recently and could very well be a bug in the AVR GCC compiler that causes it to not clean up.

2. Using an inline if and an extra variable, this can get cleaned up:

extern char Status;

char Function (void)
{
    char val = (!(Status & 4) ? 0 : 2);
    return(val);
}

See what that gets you.

Eric

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

EW wrote:
What are you talking about? In the second example above, IMHO you're wrong where you said it was 12 bytes shorter. Each of the opcodes in both examples are 16 bits. The first example has 11 opcodes (22 bytes) and the second example is 13 opcodes (26 bytes). So the second example is 4 bytes longer than the first.

Not right!!!! LDS is 2words (4bytes) opcodes and LD/LDD is 1word(2bytes) opcodes so in the first routine you have 38 bytes and in the second 26bytes.

Regards,
FK

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nigel wrote:

Quote:

Can you tell me what optimisation level you chose in the Atmel GCC release ?

I tried level s,3,2 getting always the same result! Hope the compiler will soon support your suggestion! But I think the new gcc (3.4) supported currently through the atmel-release comes ahead with some better optimisations around loops (I think I saw a while-statement compiled with winavr04042004 with s-optimisation, that showed up the compare-code twice, once at the beginning and once at the end. The atmel gcc 3.4 release solved this with a jump at the beginning to the comparisation at the end. That saves one byte or more. I can't tell about this with a deep background-knowledge cause I haven't tried to track code compiled by both compilers, but nevertheless the gcc 3.4 could be better in optimisation than the 3.2.x is (even if it's no use with the long++-stuff)

so try it out and tell us whether it produces smaller code or not!

till then, sebastian...[/code]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

N.Winterbottom wrote:

I'll keep my fingers crossed that someone knows how to disable this optimmisation.l

static unsigned long RealTime;

#define FORCE_INDIRECT(ptr) __asm__ __volatile__ ("" : "=e" (ptr) : "0" (ptr))

void NewSecond (void)
{
	unsigned long* s = &RealTime;

	FORCE_INDIRECT(s);
	(*s)++;
}

Use this at your own risk. ;-)

Bye. Carlos.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hei Carlos,

this actually really work!!!!!!!!!! :)

Could you explain why??????

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

fkay wrote:
Quote:

EW wrote:
What are you talking about? In the second example above, IMHO you're wrong where you said it was 12 bytes shorter. Each of the opcodes in both examples are 16 bits. The first example has 11 opcodes (22 bytes) and the second example is 13 opcodes (26 bytes). So the second example is 4 bytes longer than the first.

Not right!!!! LDS is 2words (4bytes) opcodes and LD/LDD is 1word(2bytes) opcodes so in the first routine you have 38 bytes and in the second 26bytes.

Regards,
FK

I stand corrected (after looking at the instruction set carefully this time). :oops: My apologies.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

fkay wrote:
this actually really work!!!!!!!!!!

Could you explain why??????

It's a quick and dirty trick, just an empty inline assembler instruction with constraints to force the compiler to use the pointers (X, Y or Z) to store the value. Normally the compiler prefers direct addressing when the addresses are perfectly known to reserve the "precious" pointers (faster but bigger code), but once the pointer is loaded with the address it uses it to indirectly access the data.

But I've not tested that code in real world programs. Particularly I've not tested the case in that pointers are yet in use by the compiler.

Regards, Carlos.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There's one more flag that I use which is why I haven't seen code as bad as shown in the other examples posted

-mint8

I learned about it either from one of the demo programs that came with avr-gcc or the online documentation.

It is also documented at http://gcc.gnu.org/onlinedocs/gcc

Quote:
Assume int to be 8 bit integer. This affects the sizes of all types: A char will be 1 byte, an int will be 1 byte, an long will be 2 bytes and long long will be 4 bytes. Please note that this option does not comply to the C standards, but it will provide you with smaller code size.

Bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please also note that most if not all of avr-libc is incompatible with
-mint8, because it has not be compiled that way (and most of the
functions could not easily be compiled with that option because they
assume a standard int).

So as long as you don't use the library (or at most a few macros out
of the header files, but no functions), that might indeed work for
you.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is the source of avr-libc available so that it could be recompiled with -mint8 if it were still desired?

- Bill

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Of course, it's opensource. But if it were that easy, be assured we'd
have provided this as an option. ;-)

Most if not all of these routines silently assume `int' to be (at
least) 16 bits, and will probably yield just nonsense when compiled
with -mint8 (even if they compile without errors).

If someone volunteers, it's certainly possible to improve things here,
and provide an option to ship a cut-down version of the library
suitable for -mint8 compilations, as well as documenting all this. So
far, none of the (few) avr-libc developers is really interested in
-mint8, so there's no driving force behind that. (Many other things
need to be done which in our opinion have much higher priority.)

Let's face it, -mint8 is only useful for really small devices
(ATtiny). When it really comes to size on these chips (like in
industrial mass production), they can still be programmed in assembler
(< 1000 instructions is overlookable). For hobbyists, replacing an
ATtiny2313 by an ATmega8 is a nice option, it gives plenty of ROM
(useful for printf() debugging etc.) at neglicibly higher costs (EUR 1
or so).

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
(Many other things need to be done which in our opinion have much higher priority.)

Yes I agree,

I read in an earlier post that someone wanted to start a "GCC Wish List".

I think seamless handling of Flash based variables should go to the top, probably above my Optimisation requirements which would be No 2.

To the Moderator:
How is a "Wish-List" this to be achieved ?

Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

N.Winterbottom wrote:
Quote:
(Many other things need to be done which in our opinion have much higher priority.)

Yes I agree,

I read in an earlier post that someone wanted to start a "GCC Wish List".

I think seamless handling of Flash based variables should go to the top, probably above my Optimisation requirements which would be No 2.

To the Moderator:
How is a "Wish-List" this to be achieved ?

Nigel

The problem is that there are many open source projects that make up the toolchain. You have to figure out which project your wish is for. Most projects either reside on SourceForge or Savannah. Both have similar interfaces (Savannah was derived from SourceForge). Both places have way to add "Feature Request" trackers to the project. For the strictly GNU projects (GCC, Binutils, GDB, Insight) then you probably have to look at their bug databases (which are different from each other), they usually have a way to add an "enhancement request".

But Please, do not start a wish list here on AVR Freaks! The major developers of the toolchain (except for 1 and sometimes 2) usually don't come here and any ideas will be lost! It's important to put the ideas where the projects are so they don't get lost.

Also, as these are all volunteer projects, it helps if you can code up the idea yourself and provide a patch!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, such a wishlist would not be very useful. As already mentioned,
it mainly requires man power. It's opensource, which not only means
that you can get the source code, but it also means that you, yes
you are the one to get things done (together with anyone else
working on it). After all, how else do you believe has been achieved
what's already there?

There's a volunteer for making GCC aware of multiple memory spaces
(Svein Seldal, see the avr-gcc mailinglist archives). Alas, this is
no leightweight task, so it will certainly take its time to complete.

See above, so far, I don't see anyone volunteering for improving the
-mint8 behaviour of avr-libc. Unless someone steps up and
volunteers, it's certainly not going to happen, ever. Now upon
hearing "someone", you can always step down, and leave it to your
neighbour. But of course, your neighbour will also step down, and
leave it to his neighbour... So it just won't happen.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just out of idle curiousity, do any of the commercial compilers support "seamless handling of FLASH variables" (I suspect he didn't really mean variables)?
I have an IAR compiler for the AT90S, and that doesn't. It really bugged me at first, so I started writing my own printf function. Then I started to understand what the problems were. The whole pointer system has to be overhauled, and for the larger memory devices that would probably mean an extra byte per pointer. Maybe N.Winterbottom has some suggestions on how this seamless handling could be effected?

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Just out of idle curiousity, do any of the commercial compilers support "seamless handling of FLASH variables"

Could you elaborate? What do you mean by "seamless handling"?

Last Edited: Thu. Jul 15, 2004 - 05:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm only quoting from N.Winterbottom's postings, but what I took it to mean is that functions such as printf() would work for strings stored in RAM or strings stored in FLASH, as they do on CPUs like the 68000(or probably most non-Harvard chips) for example. Judging by the number of posts relating to strings in FLASH, I'm guessing that a lot of people find this hard to grasp if it's their first foray into the wonderful world of Harvard architecture. I know I did.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
I'm only quoting from N.Winterbottom's postings, but what I took it to mean is that functions such as printf() would work for strings stored in RAM or strings stored in FLASH, as they do on CPUs like the 68000(or probably most non-Harvard chips) for example. Judging by the number of posts relating to strings in FLASH, I'm guessing that a lot of people find this hard to grasp if it's their first foray into the wonderful world of Harvard architecture. I know I did.

Ah, now I understand. This would require GCC itself to be aware of multiple memory spaces, which currently it isn't. Perhaps then, a quote from further up the thread:

dl8dtl wrote:

There's a volunteer for making GCC aware of multiple memory spaces
(Svein Seldal, see the avr-gcc mailinglist archives). Alas, this is
no leightweight task, so it will certainly take its time to complete.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Offhand I'm not even sure whether the standard proposal for multiple
memory spaces will cover an automagic conversion/detection. I think
it will mainly implement what IAR & Co. are already doing, only
completely generalized. The discussion in the avr-gcc mailinglist
suggested to follow that standard proposal, which will of course make
sense (and increase the probability the large GCC developer crew that
has never had the problem of programming a microcontroller could be
convinced about its usefulness at all ;-).

John's idea is more what some MCS51 compilers implement as ``generic
pointers'', which is basically sort of an OO technique using `late
binding'. You could probably achieve this already by using C++, and
define a string class which is inherited into three subclasses (for
RAM, ROM, and EEPROM).

What I don't like with this approach is that the `late binding' will
cause some run-time overhead, and will always increase the memory
footprint to the maximum (since the library function need to be
prepared for all three memory spaces, regardless of whether the
application is really using all of them). Also, the object's size
will be increased (since the memory space attribute needs to be
carried along with each object instance).

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Just out of idle curiousity, do any of the commercial compilers support "seamless handling of FLASH variables" (I suspect he didn't really mean variables)?
I have an IAR compiler for the AT90S, and that doesn't. It really bugged me at first, so I started writing my own printf function. Then I started to understand what the problems were. The whole pointer system has to be overhauled, and for the larger memory devices that would probably mean an extra byte per pointer. Maybe N.Winterbottom has some suggestions on how this seamless handling could be effected?

Actually it can be done in IAR, but it reduces range and efficiency, as an additional bit is used to identify the memory space the pointer is pointing to, and code will need to check that bit to select which 'version' of the code to run. (in theis case the MSB is reassigned to select the memory space, thus reducing the pointers overall range) If you really want to do it, check out the __generic pointer type.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Actually it can be done in IAR, but it reduces range and efficiency, as an additional bit is used to identify the memory space the pointer is pointing to, and code will need to check that bit to select which 'version' of the code to run. (in theis case the MSB is reassigned to select the memory space, thus reducing the pointers overall range) If you really want to do it, check out the __generic pointer type.

That's what I was getting at, if you read my post. In fact that's the way I tried to do it with my old IAR compiler. The point I was making was that with FLASH memory hitting the 128K mark, the MSB is already spoken for, so an extra byte would be required.

John

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John_A_Brown wrote:
Quote:
Actually it can be done in IAR, but it reduces range and efficiency, as an additional bit is used to identify the memory space the pointer is pointing to, and code will need to check that bit to select which 'version' of the code to run. (in theis case the MSB is reassigned to select the memory space, thus reducing the pointers overall range) If you really want to do it, check out the __generic pointer type.

That's what I was getting at, if you read my post. In fact that's the way I tried to do it with my old IAR compiler. The point I was making was that with FLASH memory hitting the 128K mark, the MSB is already spoken for, so an extra byte would be required.

John

My appologies, in my haste, I stopped reading after the initial question and seeing IAR. (I really need to stop answering questions from work ;))

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
My appologies, in my haste, I stopped reading after the initial question and seeing IAR. (I really need to stop answering questions from work )

No big deal. Nobody ever reads all the previous posts.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
(Many other things need to be done which in our opinion have much higher priority.)

Yes I agree,

I read in an earlier post that someone wanted to start a "GCC Wish List".

I think seamless handling of Flash based variables should go to the top, probably above my Optimisation requirements which would be No 2.

To the Moderator:
How is a "Wish-List" this to be achieved ?

Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Read Eric Weddington's posting, for why this won't be done the way you
want.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi!
What are the advantages of using -mint8 instead of declaring variables as int8_t from stdint.h?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It guarantees that not hidden promotion to int will occur.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If it hasn't been already the -mint8 option is slated to be removed as it has all kinds of negative side-effects. Not least of which is the fact that library code is not going to have been built with -mint8 so any "int" boundary to the library could be FUBAR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
It guarantees that not hidden promotion to int will occur.

Hmm, I am not quite comfortable with type promotions. Is it true that

int8_t c,d;
sizeof(c+d) == sizeof(int);

in avr-gcc with avr-libc? in the standard?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The promotion rules are defined in the standard.
Type layout is defined by the standard or implementation defined.
sizeof(int) is defined by the implementation.

avrfreaks does not support Opera. Profile inactive.