I would like to access external memory hidden by internal SRAM. To be able to do that I masked AD15 address line, read a byte, and switch AD15 back to normal address line:
char Read_4kB(size_t adres) { DDRC=0xFF; PORTC=0x00; XMCRB|=_BV(XMM0); char byte=*((char*)(adres | 0x8000)); XMCRB&=~_BV(XMM0); return byte; }
But let's see generated assembly code:
char Read_4kB(size_t adres) { DDRC=0xFF; e0: 2f ef ldi r18, 0xFF ; 255 e2: 24 bb out 0x14, r18 ; 20 PORTC=0x00; e4: 15 ba out 0x15, r1 ; 21 XMCRB|=_BV(XMM0); e6: ec e6 ldi r30, 0x6C ; 108 e8: f0 e0 ldi r31, 0x00 ; 0 ea: 20 81 ld r18, Z ec: 21 60 ori r18, 0x01 ; 1 ee: 20 83 st Z, r18 char byte=*((char*)(adres | 0x8000)); XMCRB&=~_BV(XMM0); f0: 20 81 ld r18, Z f2: 2e 7f andi r18, 0xFE ; 254 f4: 20 83 st Z, r18 f6: fc 01 movw r30, r24 f8: f0 68 ori r31, 0x80 ; 128 return byte; } fa: 80 81 ld r24, Z fc: 08 95 ret
We can clearly see the misoptimization "“ acces to XMCRB register is done via Z register, LDS R18,0x006C would be faster and better. But it is only minor problem. The serious problem is with char byte=*((char*)(adres | 0x8000)); - it is moved after XMCRB&=~_BV(XMM0); so the read obviously is done from wrong location "“ AD15 line while read is not switched to normal IO pin. How to prevent gcc from reordering? To me it seems to be a serious bug in the compiler.
What is interesting, very similar function:
void Write_4kB(size_t adres, char byte) { DDRC=0xFF; PORTC=0x00; XMCRB|=_BV(XMM0); *((char*)(adres |0x8000))=byte; XMCRB&=~_BV(XMM0); }
Is compiled ok (without reordering):
void Write_4kB(size_t adres, char byte) { DDRC=0xFF; fe: 2f ef ldi r18, 0xFF ; 255 100: 24 bb out 0x14, r18 ; 20 PORTC=0x00; 102: 15 ba out 0x15, r1 ; 21 XMCRB|=_BV(XMM0); 104: ac e6 ldi r26, 0x6C ; 108 106: b0 e0 ldi r27, 0x00 ; 0 108: 2c 91 ld r18, X 10a: 21 60 ori r18, 0x01 ; 1 10c: 2c 93 st X, r18 *((char*)(adres |0x8000))=byte; 10e: fc 01 movw r30, r24 110: f0 68 ori r31, 0x80 ; 128 112: 60 83 st Z, r22 XMCRB&=~_BV(XMM0); 114: 8c 91 ld r24, X 116: 8e 7f andi r24, 0xFE ; 254 118: 8c 93 st X, r24 } 11a: 08 95 ret
Above program is compiled on ATMega128, with WinAVR 20100110.