spirilis 1,265 Posted June 29, 2012 Share Posted June 29, 2012 I know about the BIS/BIC macros for manipulating the SR register, but I didn't see anything for general purpose use with memory variables/SFRs and such so I decided to create these: #ifdef __GNUC__ #define BIC(sfr, val) asm("bic %[src], %[dest]" : [dest] "=m" (sfr) : [src] "i" (val)) #define BIS(sfr, val) asm("bis %[src], %[dest]" : [dest] "=m" (sfr) : [src] "i" (val)) #define BIC_B(sfr, val) asm("bic.b %[src], %[dest]" : [dest] "=m" (sfr) : [src] "i" (val)) #define BIS_B(sfr, val) asm("bis.b %[src], %[dest]" : [dest] "=m" (sfr) : [src] "i" (val)) #else #define BIC(sfr, val) sfr &= ~val #define BIS(sfr, val) sfr |= val #define BIC_B(sfr, val) sfr &= ~val #define BIS_B(sfr, val) sfr |= val #endif Non-GCC compilers will simply use the conventional syntax for it. If someone could supply comparable inline-ASM code for IAR and CCS that would be cool! It seems to have shaved off a little size from my code, maybe 40-50 bytes or so for about 50 uses of that operation in my current project. (On a G2231 running close to 2K flash use, everything counts!) Quote Link to post Share on other sites
pabigot 355 Posted June 29, 2012 Share Posted June 29, 2012 If you ever see a situation where those actually make a difference, it's a bug or you're compiling with optimization disabled. The non-GNUC versions should suffice, along with -Os to optimize for size. Quote Link to post Share on other sites
spirilis 1,265 Posted June 29, 2012 Author Share Posted June 29, 2012 Weird, I always use -Os with my compiles. Looks like the code difference is 2 bytes saved in the BIC.B vs AND.B when clearing bits. Using my BIS/BIC macros, a P1_IRQ ISR: C: #pragma vector = PORT1_VECTOR __interrupt void P1_IRQ (void){ if(P1IFG & nrfIRQpin){ __bic_SR_register_on_exit(LPM4_bits); BIS_B(rf_irq, 0x80); //rf_irq |= 0x80; BIC_B(P1IFG, nrfIRQpin); //P1IFG &= ~nrfIRQpin; } } Disassembled machine code in mspdebug: P1_IRQ: 0fd5e: 0f 12 PUSH R15 0fd60: 5f 42 23 00 MOV.B &0x0023, R15 0fd64: 1f f3 AND #0x0001, R15 0fd66: 08 24 JZ P1_IRQ+0x1a 0fd68: b1 c0 f0 00 02 00 BIC #0x00f0, 0x0002(SP) 0fd6e: f2 d0 80 00 0a 02 BIS.B #0x0080, &rf_irq 0fd74: d2 c3 23 00 BIC.B #0x0001, &0x0023 <-- NOTE SIZE, 4 bytes 0fd78: 3f 41 POP R15 0fd7a: 00 13 RETI Using |= and &= instead: C: #pragma vector = PORT1_VECTOR __interrupt void P1_IRQ (void){ if(P1IFG & nrfIRQpin){ __bic_SR_register_on_exit(LPM4_bits); //BIS_B(rf_irq, 0x80); rf_irq |= 0x80; //BIC_B(P1IFG, nrfIRQpin); P1IFG &= ~nrfIRQpin; } } Disassembled machine code in mspdebug: P1_IRQ: 0fd5e: 0f 12 PUSH R15 0fd60: 5f 42 23 00 MOV.B &0x0023, R15 0fd64: 1f f3 AND #0x0001, R15 0fd66: 09 24 JZ P1_IRQ+0x1c 0fd68: b1 c0 f0 00 02 00 BIC #0x00f0, 0x0002(SP) 0fd6e: f2 d0 80 ff 0a 02 BIS.B #0x0080, &rf_irq 0fd74: f2 f0 fe ff 23 00 AND.B #0x00fe, &0x0023 <-- NOTE SIZE, 6 bytes 0fd7a: 3f 41 POP R15 0fd7c: 00 13 RETI Quote Link to post Share on other sites
spirilis 1,265 Posted June 29, 2012 Author Share Posted June 29, 2012 I had IAR Kickstarter installed at one point, but since removed it... maybe I'll break that back out (or see if CCS installs on my little win7 netbook...) Quote Link to post Share on other sites
spirilis 1,265 Posted June 29, 2012 Author Share Posted June 29, 2012 I'm thinking the BIC is using one of the constant generators, while the AND.B is not. Page 58 in the user's guide mentions how immediate mode can be 2 or 3 words depending on whether CG1/CG2 can be used. Another example with a more complex operand for the BIC yields 3 words: USI_TXRX: 0fd50: f2 c0 11 00 79 00 BIC.B #0x0011, &0x0079 0fd56: b1 c0 10 00 00 00 BIC #0x0010, 0x0000(SP) 0fd5c: 00 13 RETI Ok, so a very minor (nearly insignificant) optimization. Quote Link to post Share on other sites
pabigot 355 Posted June 29, 2012 Share Posted June 29, 2012 I'm thinking the BIC is using one of the constant generators, while the AND.B is not. Yes; gcc is not detecting that AND #-2 can be converted to BIC 1. It does detect and use BIC for AND of inverted constant in other cases. This qualifies as a missed optimization bug. If you report it on the mspgcc tracker I'll add it to the queue to look at for a future release. You may find that using inline assembly introduces other optimization problems because gcc can't tell what you're doing in those instructions. It will sometimes have to spill a register to memory to preserve it, where that would be avoided if the operation were left in a form where gcc understands the effect of the operation. Quote Link to post Share on other sites
spirilis 1,265 Posted June 29, 2012 Author Share Posted June 29, 2012 Thanks... Went ahead and added it- https://sourceforge.net/tracker/?func=d ... tid=432701 Quote Link to post Share on other sites
pabigot 355 Posted July 6, 2012 Share Posted July 6, 2012 I've added a peephole optimization for the case of AND #X, DST into BIC #-X, DST where -X can be expressed by the constant generator. The fix will be in mspgcc version following 20120627, and will be out sometime next week. (I won't add the fix to the LTS release series as it's not actually wrong, just sub-optimal.) Thanks for the report. If you encounter other cases where the obvious code in C doesn't do the right thing, please create new tracker tickets so those can be fixed too. Rickta59 and gordon 2 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.