avr-gcc tries to optimize bit sets and resets to IO register 0x20 (PCMSK1 in the ATtiny24) into sbi/cbi instructions. However, sbi/cbi are not suitable for registers >= 0x20. IO registers 0x1f and 0x21 are handled correctly, so it appears to be just register address 0x20. Here is an example that will fail (filtered out from avr-libc): ------------------ typedef unsigned char uint8_t; #define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) #define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + 0x20) #define PCMSK1 _SFR_IO8(0x20) main() { PCMSK1 |= 0x01; } ------------------ $ avr-gcc -Os fail.c /tmp/ccJwjyqk.s: Assembler messages: /tmp/ccJwjyqk.s:19: Error: number must be less than 32 No optimization will work fine as will other values for PCMSK1. Using gcc snapshot from 20061014. -mark
The test program works for me for AVR GCC 4.1.1. (WinAVR distro 20070122)
Subject: Re: avr-gcc wrongly optimizes bit sets/resets for IO register 0x20 Hi Eric, Indeed, the test program works for me too under GCC 4.1.2. However, I am developing on the ATtiny24 and 44, which isn't supported in GCC 4.1.x (-mmcu=attiny24 and friends). That's why I was using the 4.2 pre-release. The test program still generates bad code under a more recent pre-release (gcc-core-4.2.0-20070316) (I do check periodically). Although not a critical bug since there are plenty of ways to work around it, I was hoping to head it off now before 4.2.0 made it to release. It might be worth noting that the more generic -mmcu=avr2 also causes the pre-release to generate bad code for I/O register 0x20. Below is more detail on what's happening. Thanks, -mark On Fri, 2007-03-30 at 19:58 +0000, eweddington at cso dot atmel dot com wrote: > > ------- Comment #1 from eweddington at cso dot atmel dot com 2007-03-30 20:58 ------- > The test program works for me for AVR GCC 4.1.1. (WinAVR distro 20070122) > > ---------------------------------------------- File gcc-sbi-bug.c: typedef unsigned char uint8_t; #define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr)) #define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + 0x20) #define PCMSK1 _SFR_IO8(0x20) main() { PCMSK1 |= 0x01; } ---------------------------------------------- Code generated by gcc-core-4.2.0-20070316 (avr-gcc -Os -S gcc-sbi-bug.c -mmcu=attiny44): .file "gcc-sbi-bug.c" __SREG__ = 0x3f __SP_H__ = 0x3e __SP_L__ = 0x3d __tmp_reg__ = 0 __zero_reg__ = 1 .global __do_copy_data .global __do_clear_bss .text .global main .type main, @function main: /* prologue: frame size=0 */ ldi r28,lo8(__stack - 0) ldi r29,hi8(__stack - 0) out __SP_H__,r29 out __SP_L__,r28 /* prologue end (size=4) */ sbi 64-0x20,0 <----- WRONG! /* epilogue: frame size=0 */ rjmp exit /* epilogue end (size=1) */ /* function main size 6 (1) */ .size main, .-main /* File "gcc-sbi-bug.c": code 6 = 0x0006 ( 1), prologues 4, epilogues 1 */ ---------------------------------------------- Code generated by gcc-4.1.2: (avr-gcc -Os -S gcc-sbi-bug.c): .file "gcc-sbi-bug.c" .arch avr2 __SREG__ = 0x3f __SP_H__ = 0x3e __SP_L__ = 0x3d __tmp_reg__ = 0 __zero_reg__ = 1 .global __do_copy_data .global __do_clear_bss .text .global main .type main, @function main: /* prologue: frame size=0 */ ldi r28,lo8(__stack - 0) ldi r29,hi8(__stack - 0) out __SP_H__,r29 out __SP_L__,r28 /* prologue end (size=4) */ in r24,64-0x20 <----- OK ori r24,lo8(1) <----- out 64-0x20,r24 <----- /* epilogue: frame size=0 */ rjmp exit /* epilogue end (size=1) */ /* function main size 8 (3) */ .size main, .-main /* File "gcc-sbi-bug.c": code 8 = 0x0008 ( 3), prologues 4, epilogues 1 */ ----------------------------------------------
Created attachment 13327 [details] Patch by Anatoly Sokolov
Subject: Bug 29932 Author: aesok Date: Sun Apr 8 11:38:38 2007 New Revision: 123657 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=123657 Log: PR target/29932 * config/avr/predicates.md (io_address_operand): Delete predicate. (low_io_address_operand): Don't use 'mode' argument. (higth_io_address_operand): Rename ... (high_io_address_operand): ... to this. Don't use 'mode' argument. * config/avr/avr.md (*sbix_branch_tmp, *sbix_branch_tmp_bit7): Adjust for above change. Modified: trunk/gcc/ChangeLog trunk/gcc/config/avr/avr.md trunk/gcc/config/avr/predicates.md
Subject: Bug 29932 Author: aesok Date: Sun Apr 8 15:39:59 2007 New Revision: 123659 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=123659 Log: PR target/29932 * config/avr/predicates.md (io_address_operand): Delete predicate. (low_io_address_operand): Don't use 'mode' argument. (higth_io_address_operand): Rename ... (high_io_address_operand): ... to this. Don't use 'mode' argument. * config/avr/avr.md (*sbix_branch_tmp, *sbix_branch_tmp_bit7): Adjust for above change. Modified: branches/gcc-4_2-branch/gcc/ChangeLog branches/gcc-4_2-branch/gcc/config/avr/avr.md branches/gcc-4_2-branch/gcc/config/avr/predicates.md
Fixed in 4.2 branch and HEAD.