Error in gcc 5.4.0

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

I use openSUSE 13.2, 32 bit. As AVR environment I use packages from CrossToolchain:avr.

After last update of the avr-gcc I found an error in the c compiler.

Compiler info:

> avr-gcc -v
Using built-in specs.
Reading specs from /opt/cross/lib/gcc/avr/5.4.0/device-specs/specs-avr2
COLLECT_GCC=/opt/cross/bin/avr-gcc
COLLECT_LTO_WRAPPER=/opt/cross/libexec/gcc/avr/5.4.0/lto-wrapper
Target: avr
Configured with: ../gcc-5.4.0/configure -v --target=avr --disable-nls --mandir=/opt/cross/share/man --infodir=/opt/cross/share/info --program-prefix=avr- --prefix=/opt/cross --with-gnu-ld --with-gnu-as --enable-languages=c,c++ --disable-libssp --with-dwarf2
Thread model: single
gcc version 5.4.0 (GCC)

Test program (minimal example):

#include <avr/io.h>

void test(void)
{
    SFIOR |= _BV(PSR0);
}

Compilation:

> avr-gcc -c -mmcu=atmega128 -Os -save-temps test.c
test.s: Assembler messages:
test.s:16: Error: operand out of range: 32

Saved assembler file test.s:

        .file   "test.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__RAMPZ__ = 0x3b
__tmp_reg__ = 0
__zero_reg__ = 1
        .text
.global test
        .type   test, @function
test:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
        sbi 0x20,1
        ret
        .size   test, .-test
        .ident  "GCC: (GNU) 5.4.0"

This error occurs in any optimization level except O0, where the sbi instruction isn't used.

Could someone confirm this error? I don't know if it is in this version of the compiler or only in this package.

This topic has a solution.
Last Edited: Thu. Feb 9, 2017 - 02:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You haven't actually said what you believe the error to be? According to mega128 datasheet:

 

 

So:

    SFIOR |= _BV(PSR0);

converted to:

        sbi 0x20,1
        ret

is exactly the right code is it not? (PSR0 is, indeed bit 1 in IO location 0x20). Where is the error in this?

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

in and out cover 64 IO's but the bit operations only cover 256 bits so that is only 32 (0x00-0x1F) so 0x20 is outside

 

Add

So it's correct that it's wrong!

 

To make it clear :)

 

You can't do this, it's a program error, not a compiler error.

 

add again

yes I see that it's a compiler error it should not even try to make the bit code. 

Last Edited: Thu. Feb 9, 2017 - 02:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, I see. The very curious thing is I remember reading about this years ago. There was a "boundary condition" issue where 0x20 was included instead of just 0x00..0x1F so either that never actually got fixed or there's been a regression.

 

I'm not sure what the search terms would be but I do remember a thread about this - either find that or check the Bugzilla for avr-gcc and see if there's an issue raised there (and whether it's closed/open).

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

OK, rather remarkably I found it....

 

https://gcc.gnu.org/bugzilla/sho...

 

So that was back in 2007 and it was fixed in 4.2.

 

What could be useful here is to note that the changed files mainly seem to involve avr.md and predicates.md.

 

So look at what changed/fixed back then. Then go to the source tree for the 5.4 you are using and look at those same files and see if the fix has regressed.

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

clawson wrote:
I'm not sure what the search terms would be but I do remember a thread about this

 

It's like deja-vu, all over again.

--Yogi Berra
 

https://www.avrfreaks.net/forum/a...

 

Does the compiler still resolve to the SBI if you "force" it to do the volatile read? [possible workaround?]

 

SFIOR = SFIOR | stuff;

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Thu. Feb 9, 2017 - 02:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, so back in 2007 this was the fix...

https://gcc.gnu.org/viewcvs/gcc/...

 

and here's that same file in the (main tree) 5.4. build:

 

https://gcc.gnu.org/viewcvs/gcc/...

 

EDIT: And, yes, on the surface it looks like the code reverted...

 

The old fix was:

-;; Return true if OP is a valid address for an I/O register.
-(define_predicate "io_address_operand"
-  (and (match_code "const_int")
-       (match_test "INTVAL (op) >= 0x20 
-                    && INTVAL (op) <= 0x60 - GET_MODE_SIZE (mode)")))
-
 ;; Return true if OP is a valid address for lower half of I/O space.
 (define_predicate "low_io_address_operand"
   (and (match_code "const_int")
-       (match_test "INTVAL (op) >= 0x20 
-                    && INTVAL (op) <= 0x40 - GET_MODE_SIZE (mode)")))
-       
-;; Return true if OP is a valid address for higth half of I/O space.
-(define_predicate "higth_io_address_operand"
+       (match_test "IN_RANGE((INTVAL (op)), 0x20, 0x3F)")))
+
+;; Return true if OP is a valid address for high half of I/O space.
+(define_predicate "high_io_address_operand"
   (and (match_code "const_int")
-       (match_test "INTVAL (op) >= 0x40 
-                    && INTVAL (op) <= 0x60 - GET_MODE_SIZE (mode)")))
+       (match_test "IN_RANGE((INTVAL (op)), 0x40, 0x5F)")))

so that switched:

-       (match_test "INTVAL (op) >= 0x20 
-                    && INTVAL (op) <= 0x40 - GET_MODE_SIZE (mode)")))

style tests to be:

+       (match_test "IN_RANGE((INTVAL (op)), 0x20, 0x3F)")))

but now the 5.4 code looks to have:

           (match_test "IN_RANGE (INTVAL (op) - avr_arch->sfr_offset,
49 	                                   0, 0x20 - GET_MODE_SIZE (mode))"))

once again. So there's something wrong in the calculation of the 3F as the upper limit.

Last Edited: Thu. Feb 9, 2017 - 02:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Already fixed?  From a Studio7 vanilla build:

#include <avr/io.h>
int main(void){

	while (1){
		SFIOR |= 2;
  9e:	80 b5       	in	r24, 0x20	; 32
  a0:	82 60       	ori	r24, 0x02	; 2
  a2:	80 bd       	out	0x20, r24	; 32
		SFIOR = SFIOR | 2;
  a4:	80 b5       	in	r24, 0x20	; 32
  a6:	82 60       	ori	r24, 0x02	; 2
  a8:	80 bd       	out	0x20, r24	; 32
	}
  aa:	f9 cf       	rjmp	.-14     	; 0x9e <main>
Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\Studio\7.0\Vs\Compiler.targets" from project "C:\Users\ltheusch\Documents\Atmel Studio\7.0\GccApplication1\GccApplication1\GccApplication1.cproj" (target "Build" depends on it):
	Task "RunCompilerTask"
		Shell Utils Path C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils
		C:\Program Files (x86)\Atmel\Studio\7.0\shellUtils\make.exe all --jobs 4 --output-sync 
		Building file: .././main.c
		Invoking: AVR/GNU C Compiler : 4.9.2
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.1.130\include"  -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mrelax -g2 -Wall -mmcu=atmega128 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.1.130\gcc\dev\atmega128" -c -std=gnu99 -MD -MP -MF "main.d" -MT"main.d" -MT"main.o"   -o "main.o" ".././main.c" 
		Finished building: .././main.c
		Building target: GccApplication1.elf
		Invoking: AVR/GNU Linker : 4.9.2
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe" -o GccApplication1.elf  main.o   -Wl,-Map="GccApplication1.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mrelax -mmcu=atmega128 -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.1.130\gcc\dev\atmega128"  
		Finished building target: GccApplication1.elf
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures  "GccApplication1.elf" "GccApplication1.hex"
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -j .eeprom  --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex "GccApplication1.elf" "GccApplication1.eep" || exit 0
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objdump.exe" -h -S "GccApplication1.elf" > "GccApplication1.lss"
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-objcopy.exe" -O srec -R .eeprom -R .fuse -R .lock -R .signature -R .user_signatures "GccApplication1.elf" "GccApplication1.srec"
		"C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-size.exe" "GccApplication1.elf"
		   text	   data	    bss	    dec	    hex	filename
		    176	      0	      0	    176	     b0	GccApplication1.elf
	Done executing task "RunCompilerTask".
	Task "RunOutputFileVerifyTask"
				Program Memory Usage 	:	176 bytes   0.1 % Full
				Data Memory Usage 		:	0 bytes   0.0 % Full
	Done executing task "RunOutputFileVerifyTask".
Done building target "CoreBuild" in project "GccApplication1.cproj".

How does my 4.9.2 relate to OP's 5.4.0? 

 

And note that the poster in the thread I linked to was using "Studio7"...

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Looks like PR67839

 

https://gcc.gnu.org/PR67839

 

For some reasons, the fix was not back-ported to the v5 branch.

 

As a (bad) work around, -fdisable-rtl-combine does not come up with that instruction, but most likely you won't use that switch for other reasons.

 

IIUC, the problem only affects accesses of 0x20 + SFR_OFFSET, e.g. *((volatile unsigned char*) 0x40) |= 1; for ATmega128.  Hence I'd propose to use inline asm for that special address.
 

avrfreaks does not support Opera. Profile inactive.

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

The c compiler should not report any errors from the assembler, I think. In my opinion if there is any error in source code, it should be found and reported by the compiler itself. If the source file has no errors, the assembly file produced by the compiler can compile without any problems.

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

Georg-Johan,

 

It's looks specifically like:

IN_RANGE((INTVAL (op)), 0x20, 0x3F)")

changed to:

IN_RANGE (INTVAL (op) - avr_arch->sfr_offset,
49 	                                   0, 0x20 - GET_MODE_SIZE (mode))"

Presumably that GET_MODE_SIZE was supposed to return 1 but is returning 0 perhaps?

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A work around forcing indirect access could also read like

 

void test (void)
{
#if __GNUC__ == 5
    // PR67839
    volatile unsigned char *psfior = &SFIOR;
    __asm ("" : "+r" (psfior));

    *psfior |= _BV(PSR0);
#else
    SFIOR |= _BV(PSR0);
#endif // PR67839
}

 

avrfreaks does not support Opera. Profile inactive.

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

theusch wrote:
Does the compiler still resolve to the SBI if you "force" it to do the volatile read?

SFIOR = SFIOR | stuff;

This does not change anything. The result assembler code is the same.

 

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

Thank You SprinterSB!

My code compiles again. smiley

From my point of view theme is closed.

Thanks for all who want to help.

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

@clawson:  The misconception was that "mode" is not the mode of the access (in bytes, which would be one for the example) but the mode of the address, which is a constant integer (which has no mode and hence no size :-))
 

avrfreaks does not support Opera. Profile inactive.

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

SprinterSB, what exactly construction

__asm ("" : "+r" (psfior));

mean? An empty asm construction should not produce any code, but it is needed in this case.

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

Outcome is "Forget about the content of psfior," i.e. about knowledge that it contains 0x40.  Making psfior volatile would have a similar effect, but that would trigger a frame. Just try

volatile uint8_t *volatile psfior = &PSFIOR;</p>
<p>*psfior |= ...

 

avrfreaks does not support Opera. Profile inactive.

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

Ignore the p-tags, it's a bug in the forum software.

 

Hence with a volatile psfior you'll want to have it static, then the work-around is vanilla C.

 

avrfreaks does not support Opera. Profile inactive.

Last Edited: Thu. Feb 9, 2017 - 03:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks