Bug for prologue_saves and local vars ? [Solved]

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

I posted some code here, using #1 and #2 from my sign, m644 and -Os :
https://www.avrfreaks.net/index.p...

unsigned long  huge = 0x12345678, swapped;

uint8_t    *ptr = (uint8_t * )&huge, yea[4];
		
int main(void)
{
	
	for ( uint8_t i = 4; i > 0; i-- ){

		yea[i-1] = *ptr++ ;
	}
	
	swapped = *( uint32_t * )yea;

	while(1);

*.LSS

int main(void)
{
  d0:	ad e0       	ldi	r26, 0x0D	; 13
  d2:	b1 e0       	ldi	r27, 0x01	; 1

	for ( uint8_t i = 4; i > 0; i-- ){

		yea[i-1] = *ptr++ ;
  d4:	e0 91 04 01 	lds	r30, 0x0104
  d8:	f0 91 05 01 	lds	r31, 0x0105
  dc:	81 91       	ld	r24, Z+
  de:	8c 93       	st	X, r24
  e0:	f0 93 05 01 	sts	0x0105, r31
  e4:	e0 93 04 01 	sts	0x0104, r30
  e8:	11 97       	sbiw	r26, 0x01	; 1
uint8_t    *ptr = (uint8_t * )&huge	;		

int main(void)
{

	for ( uint8_t i = 4; i > 0; i-- ){
  ea:	81 e0       	ldi	r24, 0x01	; 1
  ec:	a9 30       	cpi	r26, 0x09	; 9
  ee:	b8 07       	cpc	r27, r24
  f0:	89 f7       	brne	.-30     	; 0xd4 

		yea[i-1] = *ptr++ ;
	}
	
	swapped = *( uint32_t * )yea;
  f2:	11 96       	adiw	r26, 0x01	; 1
  f4:	8d 91       	ld	r24, X+
  f6:	9d 91       	ld	r25, X+
  f8:	0d 90       	ld	r0, X+
  fa:	bc 91       	ld	r27, X
  fc:	a0 2d       	mov	r26, r0
  fe:	80 93 06 01 	sts	0x0106, r24
 102:	90 93 07 01 	sts	0x0107, r25
 106:	a0 93 08 01 	sts	0x0108, r26
 10a:	b0 93 09 01 	sts	0x0109, r27

This version just makes yea[] local to main() and prologue_saves() blows up the code by 60 bytes ! It doesn't do any good, though and shouldn't even be called, right ?!! If I put ptr as local instead code size doesn't change. This has to be a bug.

version2.LSS

int main(void)
{
  d0:	a4 e0       	ldi	r26, 0x04	; 4
  d2:	b0 e0       	ldi	r27, 0x00	; 0
  d4:	ed e6       	ldi	r30, 0x6D	; 109
  d6:	f0 e0       	ldi	r31, 0x00	; 0
  d8:	30 c0       	rjmp	.+96     	; 0x13a <__prologue_saves__+0x20>
  da:	de 01       	movw	r26, r28
  dc:	14 96       	adiw	r26, 0x04	; 4
uint8_t yea[4];
	for ( uint8_t i = 4; i > 0; i-- ){

		yea[i-1] = *ptr++ ;
  de:	e0 91 04 01 	lds	r30, 0x0104
  e2:	f0 91 05 01 	lds	r31, 0x0105
  e6:	81 91       	ld	r24, Z+
  e8:	8c 93       	st	X, r24
  ea:	f0 93 05 01 	sts	0x0105, r31
  ee:	e0 93 04 01 	sts	0x0104, r30
  f2:	11 97       	sbiw	r26, 0x01	; 1
uint8_t    *ptr = (uint8_t * )&huge	;		

int main(void)
{
uint8_t yea[4];
	for ( uint8_t i = 4; i > 0; i-- ){
  f4:	ac 17       	cp	r26, r28
  f6:	bd 07       	cpc	r27, r29
  f8:	91 f7       	brne	.-28     	; 0xde 

		yea[i-1] = *ptr++ ;
	}
	
	swapped = *( uint32_t * )yea;
  fa:	89 81       	ldd	r24, Y+1	; 0x01
  fc:	9a 81       	ldd	r25, Y+2	; 0x02
  fe:	ab 81       	ldd	r26, Y+3	; 0x03
 100:	bc 81       	ldd	r27, Y+4	; 0x04
 102:	80 93 06 01 	sts	0x0106, r24
 106:	90 93 07 01 	sts	0x0107, r25
 10a:	a0 93 08 01 	sts	0x0108, r26
 10e:	b0 93 09 01 	sts	0x0109, r27

	asm volatile( "nop":: );
 112:	00 00       	nop
 114:	ff cf       	rjmp	.-2      	; 0x114 

00000116 :
 116:	f8 94       	cli
 118:	1c c0       	rjmp	.+56     	; 0x152 <_exit>

0000011a <__prologue_saves__>:
 11a:	2f 92       	push	r2
 11c:	3f 92       	push	r3
 11e:	4f 92       	push	r4
 120:	5f 92       	push	r5
 122:	6f 92       	push	r6
 124:	7f 92       	push	r7
 126:	8f 92       	push	r8
 128:	9f 92       	push	r9
 12a:	af 92       	push	r10
 12c:	bf 92       	push	r11
 12e:	cf 92       	push	r12
 130:	df 92       	push	r13
 132:	ef 92       	push	r14
 134:	ff 92       	push	r15
 136:	0f 93       	push	r16
 138:	1f 93       	push	r17
 13a:	cf 93       	push	r28
 13c:	df 93       	push	r29
 13e:	cd b7       	in	r28, 0x3d	; 61
 140:	de b7       	in	r29, 0x3e	; 62
 142:	ca 1b       	sub	r28, r26
 144:	db 0b       	sbc	r29, r27
 146:	0f b6       	in	r0, 0x3f	; 63
 148:	f8 94       	cli
 14a:	de bf       	out	0x3e, r29	; 62
 14c:	0f be       	out	0x3f, r0	; 63
 14e:	cd bf       	out	0x3d, r28	; 61
 150:	09 94       	ijmp

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

Last Edited: Sun. Aug 21, 2011 - 10:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I cannot reproduce that.

#include 

extern unsigned long huge;
extern unsigned long swapped;

uint8_t *ptr = (uint8_t*) &huge;
       
void foo (void) 
{ 
    uint8_t yea[4]; 

    for (uint8_t i = 4; i > 0; i--) 
        yea[i-1] = *ptr++; 

    swapped = *((uint32_t*) yea);
}

WinAVR-20100110 compiles with -Os -mmcu=atmega128 -std=c99 -dp to

foo:
	push r29	 ;  73	*pushhi/1	[length = 2]
	push r28
	rcall .	 ;  79	*addhi3_sp_R_pc2	[length = 2]
	rcall .
	in r28,__SP_L__	 ;  80	*movhi_sp/2	[length = 2]
	in r29,__SP_H__
/* prologue: function */
/* frame size = 4 */
	movw r26,r28	 ;  72	*movhi/1	[length = 1]
	adiw r26,4	 ;  43	*addhi3/2	[length = 1]
.L2:
	lds r30,ptr	 ;  70	*movhi/2	[length = 4]
	lds r31,(ptr)+1
	ld r24,Z+	 ;  46	*movqi/4	[length = 1]
	st X,r24	 ;  47	*movqi/3	[length = 1]
	sts (ptr)+1,r31	 ;  49	*movhi/3	[length = 4]
	sts ptr,r30
	sbiw r26,1	 ;  50	*addhi3/3	[length = 1]
	cp r26,r28	 ;  53	cmphi/1	[length = 2]
	cpc r27,r29
	brne .L2	 ;  54	branch	[length = 1]
	ldd r24,Y+1	 ;  56	*movsi/3	[length = 4]
	ldd r25,Y+2
	ldd r26,Y+3
	ldd r27,Y+4
	sts swapped,r24	 ;  57	*movsi/4	[length = 8]
	sts (swapped)+1,r25
	sts (swapped)+2,r26
	sts (swapped)+3,r27
/* epilogue start */
	pop __tmp_reg__	 ;  86	*addhi3_sp_R_pc2	[length = 4]
	pop __tmp_reg__
	pop __tmp_reg__
	pop __tmp_reg__
	pop r28	 ;  87	pophi	[length = 2]
	pop r29
	ret	 ;  88	return_from_epilogue	[length = 1]

Notice that your type-punning breaks strict aliasing rules. Your code it not robust and might break with better optimization.

avrfreaks does not support Opera. Profile inactive.

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

A clean solution to this using gcc is

extern unsigned long huge;
extern unsigned long swapped;

void bar (void)
{
    swapped = __builtin_bswap32 (huge);
}

The built-in maps to a library call which is open coded in C for avr-gcc < 4.7 so that you may want to do that by hand to get an optimized version:

#if defined (__GNUC__) && defined (__AVR__)

__asm (".global __bswapsi2            \n"
    ".type __bswapsi2,@function       \n"
    "__bswapsi2:                      \n"
    "eor 24,23 $ eor 23,24 $eor 24,23 \n"
    "eor 25,22 $ eor 22,25 $eor 25,22 \n"
    "ret"
);

#endif /* avr-gcc */

Notice that the built-in knows how to fold constants and that bswap32°bswap32 = identity.

avrfreaks does not support Opera. Profile inactive.

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

FYI, the following C solution performs nicely with avr-gcc 4.3, 4.5 and 4.6:

static inline long bswap32 (long lb)
{
    union { long lb; char b[4]; } u, v;
    
    u.lb = lb;
    
    v.b[3] = u.b[0];
    v.b[2] = u.b[1];
    v.b[1] = u.b[2];
    v.b[0] = u.b[3];
    
    return v.lb;
}

Note that this is not a general solution because, e.g. v.lb is read but never written. GCC supports this and with GCC it works as expected, i.e. writing to v.b changes v.lb.

avrfreaks does not support Opera. Profile inactive.

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

Quote:
Notice that your type-punning breaks strict aliasing rules. Your code it not robust and might break with better optimization.
Sprinter thanks for the other posts' info, but in your 1st post how can what I posted be fixed ( if possible at all ) ?

From my *.LSS how can my compiler give this results but not yours and it's the same version ? I may have gotten my Winavr from a university site ( it also had all the studio and SP exes, so that's why I went there. IF it's where I got Winavr at all ). I'll install from sourceforge and hopefully it won't do this. :cry:

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

Quote:

but in your 1st post how can what I posted be fixed ( if possible at all ) ?

Have a read of this to understand the issue:

http://labs.qt.nokia.com/2011/06...

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

Quote:
how can my compiler give this results but not yours

Post a minimum *compilable* example exhibiting the problem together with the command line you are using to compile it.

JW

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

Clawson, thanks for the link. It's something to get used to, I've never heard of all that. I thought it was all proper casting. :shock: OK, live and learn.

Wek, all that info is in my OP .

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

indianajones11 wrote:
Wek, all that info is in my OP .
I said, *compilable*.

And the command line, by which I mean the *complete* command line (alternatively, the makefile generated and actually used by AS4).

c:\tmp>type f.c
unsigned long  huge = 0x12345678, swapped;

uint8_t    *ptr = (uint8_t * )&huge, yea[4];

int main(void)
{

   for ( uint8_t i = 4; i > 0; i-- ){

      yea[i-1] = *ptr++ ;
   }

   swapped = *( uint32_t * )yea;

   while(1);

c:\tmp>"c:\Program Files\Atmel\AVRTools\WinAVR20100110\bin\avr-gcc" -Os -mmcu=atmega644 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wl,-Map=tmp.map f.c -o f.elf
f.c:3: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token
f.c: In function 'main':
f.c:8: error: 'uint8_t' undeclared (first use in this function)
f.c:8: error: (Each undeclared identifier is reported only once
f.c:8: error: for each function it appears in.)
f.c:8: error: expected ';' before 'i'
f.c:8: error: 'i' undeclared (first use in this function)
f.c:10: error: 'yea' undeclared (first use in this function)
f.c:10: error: 'ptr' undeclared (first use in this function)
f.c:13: error: 'uint32_t' undeclared (first use in this function)
f.c:13: error: expected expression before ')' token
f.c:15: error: expected declaration or statement at end of input

c:\tmp>

Jan

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

Close the main() with a " } " .

###############################################################################
# Makefile for the project PWM
###############################################################################

## General Flags
PROJECT = PWM
MCU = atmega644
TARGET = PWM.elf
CC = avr-gcc

CPP = avr-g++

## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall -gdwarf-2 -std=gnu99 -fno-inline-small-functions -ffunction-sections -fdata-sections   -mcall-prologues                    -DF_CPU=1000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d 

## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2

## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS += -Wl,--relax  -Wl,--gc-sections -Wl,-Map=PWM.map


## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature

HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings


## Include Directories
INCLUDES = -I"C:\Program Files\Atmel\Avr Projects 2\Megas\mega 644\PWM\..\..\..\MY_Includes" 

## Library Directories
LIBDIRS = -L"C:\Program Files\Atmel\Avr Projects 2\MY_LIBS" 

## Libraries
LIBS = -lc -lm 

## Objects that must be built in order to link
OBJECTS = PWM.o asm.o lcd.o 

## Objects explicitly added by the user
LINKONLYOBJECTS = 

## Build
all: $(TARGET) PWM.hex PWM.eep PWM.lss size

## Compile
PWM.o: ../PWM.c
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

asm.o: ../asm.S
	$(CC) $(INCLUDES) $(ASMFLAGS) -c  $<

lcd.o: ../../../../MY_LIBS/lcd.c
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

##Link
$(TARGET): $(OBJECTS)
	 $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)

%.hex: $(TARGET)
	avr-objcopy -O ihex $(HEX_FLASH_FLAGS)  $< $@

%.eep: $(TARGET)
	-avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0

%.lss: $(TARGET)
	avr-objdump -h -S $< > $@

size: ${TARGET}
	@echo
	@avr-size -C --mcu=${MCU} ${TARGET}

## Clean target
.PHONY: clean
clean:
	-rm -rf $(OBJECTS) PWM.elf dep/* PWM.hex PWM.eep PWM.lss PWM.map


## Other dependencies
-include $(shell mkdir dep 2>NUL) $(wildcard dep/*)

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

indianajones11 wrote:
Close the main() with a " } " .
I did, here it comes:

c:\tmp>type f.c
unsigned long  huge = 0x12345678, swapped;

uint8_t    *ptr = (uint8_t * )&huge, yea[4];

int main(void)
{

   for ( uint8_t i = 4; i > 0; i-- ){

      yea[i-1] = *ptr++ ;
   }

   swapped = *( uint32_t * )yea;

   while(1);
}

c:\tmp>"c:\Program Files\Atmel\AVRTools\WinAVR20100110\bin\avr-gcc" -Os -mmcu=atmega644 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wl,-Map=tmp.map f.c -o f.elf
f.c:3: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token
f.c: In function 'main':
f.c:8: error: 'uint8_t' undeclared (first use in this function)
f.c:8: error: (Each undeclared identifier is reported only once
f.c:8: error: for each function it appears in.)
f.c:8: error: expected ';' before 'i'
f.c:8: error: 'i' undeclared (first use in this function)
f.c:10: error: 'yea' undeclared (first use in this function)
f.c:10: error: 'ptr' undeclared (first use in this function)
f.c:13: error: 'uint32_t' undeclared (first use in this function)
f.c:13: error: expected expression before ')' token

c:\tmp>

Now please stop wasting your and my time and post the *whole compilable* code exhibiting the problem together with the *complete* command line or makefile. Or, if this is an AS4 project, zip it up and post.

Jan

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

Okay, so as I suspected, there's much more than in your initial post, isn't it.

Quote:

## Include Directories
INCLUDES = -I"C:\Program Files\Atmel\Avr Projects 2\Megas\mega 644\PWM\..\..\..\MY_Includes"

## Library Directories
LIBDIRS = -L"C:\Program Files\Atmel\Avr Projects 2\MY_LIBS"

## Libraries
LIBS = -lc -lm

## Objects that must be built in order to link
OBJECTS = PWM.o asm.o lcd.o 

Jan

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

How can you look at the code and think ANYTHING'S missing ? It's YOUR setup that's not recognizing uint8_t and uint32_t . I don't have a clue what to tell you about how to fix that, except use unsigned char and unsigned long instead.

Quote:
Okay, so as I suspected, there's much more than in your initial post, isn't it.
Yes, but none of those files are being used in the posted code due to the while(1) .

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

Okay, so why can't YOU start a new project in AS4, NOT including those files which you say are NOT being used, compile it and have a look at the output, whether it still includes the prologue_saves; and if it does, simply pack that new project up and post it so that we can chew on it further.

Jan

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

With a new pjt. with just the posted code with yea[] local to main(), it compiles correctly ! It's strange to me that the placement of that 1 var as a local or global would have that behaviour ( to me ), since NOTHING appears in the *.LSS file after the while(1) in my OP problem post ( there wasn't much code past the while(1); ). I only did it that way as a quick test of my code idea for the thread I mentioned in my OP, w/o starting a new pjt. Oh well, thanks anyway.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

indianajones11 wrote:
How can you look at the code and think ANYTHING'S missing ? It's YOUR setup that's not recognizing uint8_t and uint32_t.
No, it's in your source. If you use uint8_t et al. you need something like
#include 

which is not present in your Snip or

-include stdint.h

or

-Duint8_t='unsigned char'

in your command line.

avrfreaks does not support Opera. Profile inactive.

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

Quote:

which is not present in your Snip

I'll bet the "snip" missed a:

#include 

at the very top (which indirectly includes )

I find the irony of this thread to be beyond belief given how often IJ has told others to post complete code :lol: :lol:

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

indianajones11 wrote:
Quote:
Notice that your type-punning breaks strict aliasing rules. Your code it not robust and might break with better optimization.
Sprinter thanks for the other posts' info, but in your 1st post how can what I posted be fixed?
There is plenty many much information out in the web on strict aliasing and type-punning, e.g.
http://dbp-consulting.com/tutori...

avrfreaks does not support Opera. Profile inactive.

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

Clawson wrote:
I find the irony of this thread to be beyond belief given how often IJ has told others to post complete code
LOL, true enough Clawson, but I felt I could afford to leave such a line out ( Ma bad ).

Sorry about that Wek, I forgot how much you HATE C and so it may have slipped your mind to have to include the line I left out.

I appreciate the link, Sprinter since this is something I'll have to get used to.

Can anybody tell me why this behaviour happens ( from the info I gave esp. in my last post ) ? It may be obvious to y'all with many years of experience with compilers, but it's a big fat surprise to me.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1