------- Additional Comments From bjoern dot m dot haase at web dot de 2005-01-18 21:40 ------- Indeed the problem seems to be related to a problem during the reload pass. I now think, that I have found a solution for the original problem that needs a tiny change in the back-end. DJ Delorie wrote me: >avr bug - GENERAL_REGS allows $r24 to contain a DImode, but you cannot >access the 5th byte of it via a subreg, because HARD_REGNO_MODE_OK >doesn't permit QImodes in $r29.  This disqualifies GENERAL_REGS. Since anyway any useful function using long longs will require the frame pointer, there is (in my opinion) no use for DI objects in the upper register range. The following patch restricts DI objects to registers with smaller indices. When using this patch, I succeed in building the gcc-4.0.0 snapshot dating from the 12th of december 04 without problems. This snapshot previously did not compile with the symptoms mentioned above. For a later head revision, unfortunately something else and independent seems to be broken. I'll check today's head this evening and report on this, as soon as I have analyzed this more in detail. Patch that needs to be applied to /gcc/config/avr/avr.c Reported differences are differences against the 4.0.0-20041212 snapshot. --- avr.c.old 2005-01-18 22:24:44.942273520 +0100 +++ avr.c.new 2005-01-18 22:19:19.000000000 +0100 @@ -5116,40 +5116,47 @@ register number REGNO. On the enhanced core, anything larger than 1 byte must start in even numbered register for "movw" to work (this way we don't have to check for odd registers everywhere). */ int avr_hard_regno_mode_ok (int regno, enum machine_mode mode) { /* Bug workaround: recog.c (peep2_find_free_register) and probably a few other places assume that the frame pointer is a single hard register, so r29 may be allocated and overwrite the high byte of the frame pointer. Do not allow any value to start in r29. */ if (regno == REG_Y + 1) return 0; /* Reload can use r28:r29 for reload register and for frame pointer in one insn. It's wrong. We must disable it. */ if (mode != Pmode && reload_in_progress && frame_pointer_required_p () && regno <= REG_Y && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1)) return 0; + if (mode == DImode) + { if ( (regno < 20) && (!(regno & 1)) ) + return 1; + else + return 0; + } + if (mode == QImode) return 1; /* if (regno < 24 && !AVR_ENHANCED) return 1;*/ return !(regno & 1); } /* Returns 1 if X is a valid address for an I/O register of size SIZE (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */ int avr_io_address_p (rtx x, int size) { return (optimize > 0 && GET_CODE (x) == CONST_INT && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size); } /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */ -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18887