David Bender 28 Posted July 14, 2014 Share Posted July 14, 2014 I'm puzzled as to why gcc is producing code for rrc as follows: f97e: 1f 42 02 02 mov &0x0202,r15 f982: 12 c3 clrc f984: 0f 10 rrc r15 f986: 82 4f 02 02 mov r15, &0x0202 whereas bit set is: f96c: b2 d0 80 00 bis #128, &0x0164 ;#0x0080 f970: 64 01 slau144 seems to indicate that rrc supports absolute mode; am I missing something here (besides possible lost clock cycles). Why the extra mov instructions? (note: for the variable at 0x202, I have tried with and without the volatile keyword and get the same result) Quote Link to post Share on other sites
spirilis 1,265 Posted July 14, 2014 Share Posted July 14, 2014 What optimization level? (Cue the "GCC was never really meant to be run without some level of optimization turned on" comment I recall from @@pabigot ) Quote Link to post Share on other sites
Rickta59 589 Posted July 14, 2014 Share Posted July 14, 2014 Depends on which version of gcc, and which compiler options. Quote Link to post Share on other sites
David Bender 28 Posted July 14, 2014 Author Share Posted July 14, 2014 Here are the CFLAGS I used CFLAGS = -mmcu=$(MCU) -std=c99 -g -Os -Wall -Wunused -mnoint-hwmul -DF_CPU=16000000 I also tried adding -O2 -O1 with no effect. -O0 produces horrendous code. My gcc version: gcc version 4.6.3 20120301 (mspgcc LTS 20120406 unpatched) (Gentoo 4.6.3_p20120406 p1.0) Quote Link to post Share on other sites
Rickta59 589 Posted July 14, 2014 Share Posted July 14, 2014 Is this in an ISR? Quote Link to post Share on other sites
David Bender 28 Posted July 14, 2014 Author Share Posted July 14, 2014 Yes it is an ISR. However, I copied the code to my main and I still got the same assembly generation. Quote Link to post Share on other sites
Rickta59 589 Posted July 14, 2014 Share Posted July 14, 2014 what does the C code actually look like? Quote Link to post Share on other sites
David Bender 28 Posted July 14, 2014 Author Share Posted July 14, 2014 static uint16_t tx_char; .... static void Test2(void){ TA0CCR1 += rx_ticks_per_bit; // setup next time to send a bit, OUT will be set then TA0CCTL1 |= OUTMOD2; // reset OUT (set to 0) OUTMOD2|OUTMOD0 (0b101) if ( tx_char & 0x01 ) { // look at LSB if 1 then set OUT high TA0CCTL1 &= ~OUTMOD2; // set OUT (set to 1) OUTMOD0 (0b001) } /* The bit shift is producing extra movs? */ if (!(tx_char >>= 1)) { // All bits transmitted ? TA0CCTL1 &= ~CCIE; // disable interrupt, indicates we are done } } It's adapted from the TimerSerial code from Energia (which I think was yours actually). Context (you can skip if you want): Didn't like TA0CCTL1 being written twice; was looking to optimize and noticed the bit shift.... Quote Link to post Share on other sites
Rickta59 589 Posted July 14, 2014 Share Posted July 14, 2014 What I've noticed is that if you use global variables in ISR routines, you often end up with it using a register as a temporary. The best way to get it to do exactly what you want in 4.6.3 is to use inline asm. FWIW, the new msp430-elf-gcc seems to do a good job with using memory to memory move instructions. However, you have to replace the startup routine if you want to make it work on the smaller g series chips. Quote Link to post Share on other sites
pabigot 355 Posted July 14, 2014 Share Posted July 14, 2014 (edited) Dunno why it'd do that. Same behavior in my internal 4.7.2 version. I no longer maintain mspgcc unless contracted to do so, and am transitioning to msp430-elf for my own work. msp430-elf-gcc (4.9.0-based and TI msp430-130423-371) generates a call to a rotate subroutine. Somebody should probably document the msp430-elf issue and submit it to RH/TI to be fixed; I don't expect to be doing anything with msp430 in the next month or two or I'd do it myself. [FWIW, with mspgcc the fact a function is an ISR should have no impact on code generation except in the function prolog and epilog.] Edited July 14, 2014 by pabigot Quote Link to post Share on other sites
David Bender 28 Posted July 14, 2014 Author Share Posted July 14, 2014 The latest Gentoo package is 4.8.3; would this do the rotate directly? Quote Link to post Share on other sites
Rickta59 589 Posted July 14, 2014 Share Posted July 14, 2014 No harm in trying. Just remember the current msp430-elf-gcc isn't finished. Quote Link to post Share on other sites
David Bender 28 Posted July 14, 2014 Author Share Posted July 14, 2014 Thanks for all the info. I think I will spend my time bettering my understanding of inline asm before I play around with changing compiler versions. 43oh rocks! Quote Link to post Share on other sites
David Bender 28 Posted July 14, 2014 Author Share Posted July 14, 2014 OK parting thought: 1) The movs cost 3 cycles each. The register RRC costs 1. 2) RRC costs 4 cycles. (edit: with an absolute destination) For 3 bit shifts, method 1 costs 9 cycles while method 2 costs 12. So gcc is doing the correct thing for shifts >= 3 bits. For 2 bit shifts, it is break even at 8 cycles. It is 1 bit shifts that are getting shafted (unfortunately I tend to use 1 bit shifts precisely because shifts are expensive...) Quote Link to post Share on other sites
Rickta59 589 Posted July 14, 2014 Share Posted July 14, 2014 (edited) __attribute__ ((interrupt(TIMER0_A0_VECTOR))) void putch_bit_isr(void) { #if 0 TA0CCR0 += TICKS_PER_BIT; /* setup next time to send next bit, OUT is set then */ TA0CCTL0 |= OUTMOD2; /* reset OUT (set to 0) OUTMOD2|OUTMOD0 (0b101) */ if (TX_BUF & 0x01) { /* look at LSB, if 1 */ TA0CCTL0 &= ~OUTMOD2; /* then set OUT (set to 1) OUTMOD0 (0b001) */ } if (!(TX_BUF >>= 1)) { /* if all bits transmitted ? */ TA0CCTL0 &= ~CCIE; /* then disable interrupt, send no more bits */ /* NOTE: this indicates byte transmit complete */ } #else __asm__ ( " add %[TICKS],%[ccr0]\n" " bis %2,%[cctl0]\n" " bit #1, %[tx_buf]\n" " jz 1f\n" " and %5,%[cctl0]\n" "1:\n" " clrc\n" " rrc %[tx_buf], %[tx_buf]\n" " jnz 2f\n" " and %6,%[cctl0]\n" "2:\n" : : [TICKS] "i" (TICKS_PER_BIT), /* 0 */ [ccr0] "m" (TA0CCR0), /* 1 */ [mod2] "i" (OUTMOD2), /* 2 */ [cctl0] "m" (TA0CCTL0), /* 3 */ [tx_buf] "m" (TX_BUF), /* 4 */ "i" (~OUTMOD2), /* 5 */ "i" (~CCIE) /* 6 */ : "cc" ); #endif } Edited July 14, 2014 by Rickta59 add "cc" flag clobber and whitespace fixes Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.