stryd_one Posted April 5, 2007 Report Share Posted April 5, 2007 Hey you crazy coders. Great to see lots of buzz about user developed apps around here at the moment :)I hope someone might know a trick for me.... if I use a bitshift in C with the >> or << operators, then the ASM generated is a RRCF or RLCF. These both use the Carry bit (statusbits.C aka STATUS.0). The carry bit is cleared before the shift even if I don't specify it :(Is there a way to have C generate a RRNCF or RLNCF instead? There are certain cases where I'd be better off without it... Is there a way to NOT clear the carry bit before a bitshift?While I'm on the subject of bitfields, I wonder if anyone has tried this and might be able to save me a few hours experimenting...Which is faster in a FOR loop:Declare your bitfield in a union as normalTest bit 'n' in the loopor...Declare the bitfield as a normal char, bitshift, and test the carry bitOnce upon a time I remember TK saying that bitfields could slow things down, but looking at the generated code, I suspect that the newer versions of SDCC may have fixed that problem. For example, 'statusbits.C = 0' becomes 'BCF STATUS.0'... And I think I remember AC saying that bitfields are limited to 8 bit?Lootts of questions.... Quote Link to comment Share on other sites More sharing options...
audiocommander Posted April 5, 2007 Report Share Posted April 5, 2007 WTF is RRNCF and RLNCF?I know I should RTFMand yes: bitfields in SDCC are limited to 8 bits. Unfortunately.Unions and structs can be larger though, so you could theoretically add two or more bitfields to a struct. Haven't done this, though Quote Link to comment Share on other sites More sharing options...
stryd_one Posted April 5, 2007 Author Report Share Posted April 5, 2007 LOL :) Yeh RTFM isn't necessarily the best thing around for plain english about it either :P Ahh it's like this...I'll just do right shift as an example.The way it does a bitshift is really a bit rotation. Without the Carry bit, when you rotate right, the bottom bit doesn't just drop away, it gets pushed onto the top of the byte: v 0110 1001 >> 1 = 1011 0100 ^ That's an RRNCF - Rotate Right No Carry F However with the Carry Bit, there is one extra bit, and the bit that gets pushed off the end of the byte goes there: C v 0 0110 1001 >> 1 = 1 0011 0100 ^ If you continue to shift (OK rotate) after this without clearing the status bit, then it rolls back onto the byte: C v 1 0011 0100 >> 1 = 0 1001 1010 ^ That's an RRCF - Rotate Right through Carry F There are ways around it, but if you want one type of rotation, and are forced to use the other, it'll cost one instruction to get the same effect. Here's an example. scpbtemp is a long type (32b). I wrote this: STATUSbits.C = 0; //Clear Carry Bit scpbtemp = scpbtemp >> 1; And SDCC produced this: ; .line 40; vxscpb.c STATUSbits.C = 0; //Clear Carry Bit BCF _STATUSbits, 0 ; .line 41; vxscpb.c scpbtemp = scpbtemp >> 1; BCF STATUS, 0 RRCF r0x06, F RRCF r0x05, F RRCF r0x04, F RRCF r0x03, F Notice that it cleared the status bit twice - once when I told it to, and once all by itself. This is a good demonstration of use for the carry bit... It gets pushed onto the top of each successive lower byte of the 32 bits. This is why the Carry bit needs to be cleared, atherwise some random value from another function might be pushed onto our variable, and may be why SDCC chose to use RRCF rather than RRNCF... Or it might just always use it.. I can find out, but I was hoping someone might have come across it.But I don't like that it assumed I want that bit clear... Maybe I want the carry bit to be sent from another function? Then what? ??? Hmmmmmmm..... Quote Link to comment Share on other sites More sharing options...
audiocommander Posted April 5, 2007 Report Share Posted April 5, 2007 all right, you're definitely confusing me today...no... just kidding, you explained this perfectly clear!well, I think this would be a perfect case for an __asm / __endasm; statement, don't you think?I'm not exactly sure, but I cannot remeber having seen something about a carry bit in C. When you shift a bit, it's gone. Though IIRC, there are some libraries that contain similar functions; but as these are not available in our case, it'll be best to do this in __asm.Cheers ;DMichael Quote Link to comment Share on other sites More sharing options...
stryd_one Posted April 6, 2007 Author Report Share Posted April 6, 2007 hehehe yeh I went on a mission to figure out a problem, and found three more while I was there :PI could use naked ASM there but I'm trying to keep it portable where I can... I'll experiment today and see what it does with an unsigned char... Quote Link to comment Share on other sites More sharing options...
Wilba Posted April 6, 2007 Report Share Posted April 6, 2007 Basically the compiler is doing what it needs to do to support the C shift operators, which have no concept of carry bits, i.e. they always shift zeros into the byte. Which makes sense, because 99.99% of the time you're doing a shifting of bits in a bitmask, i.e. to generate a bitmask with just bit 2 set you write "1 << 2".So it's not just assuming you want that bit clear, it's meeting the specification of C, and there's nothing in C that does "rotate no carry", you have to code that explicitly.If you're shifting through one or more bytes in PIC ASM you would have to set the carry bit to the first (or last) bit prior to doing the "rotate through carry" ops.... this is generally achieved by doing an RRCF or RLCF putting result into W (i.e. just shift the bit into the carry but don't do the rotate on the register).A similar thing has to be done in C for every time you're bit shifting and want anything but zeros coming in... so for one byte you'd have to do something like this: /* rotate left no carry */ x = ( x & 0x80 ? 0x01 : 0x00 ) | ( x << 1 ); /* rotate right no carry */ x = ( x & 0x01 ? 0x80 : 0x00 ) | ( x >> 1 );[/code]I don't know how efficient that compiles with SDCC, but it's going to be less efficient than just doing two RLCF or RRCF. Quote Link to comment Share on other sites More sharing options...
stryd_one Posted April 6, 2007 Author Report Share Posted April 6, 2007 Ahh that explains it. Damn standards. If I were Bill Gates I could ignore this. ;DI had a look at it and was interested to find out that it always uses the carry bit when it rotates - but in a lot of cases for shifts of static magnitude it doesn't use R*CF at all - like for <<2, it does an ADDLW to double the number... Where the magnitude of the shift is variable, it will use that variable as a counter, and uses a rotate (with carry) . Where the variable being shifted is > 8bit then it uses rotate with carry always. Quote Link to comment Share on other sites More sharing options...
Wilba Posted April 6, 2007 Report Share Posted April 6, 2007 Yeah that makes sense... there's no C code that would translate to a rotate without carry. But I don't understand the ADDLW usage exactly, are you talking about a constant left-shifted? i.e. 4 << 2 becomes "movlw 4, addlw 4" ? Quote Link to comment Share on other sites More sharing options...
stryd_one Posted April 6, 2007 Author Report Share Posted April 6, 2007 are you talking about a constant left-shifted? i.e. 4 << 2 becomes "movlw 4, addlw 4" ?Yeh exactly. It just finds the method that uses the least instructions to get the correct answer. I guess it makes sense but it wasn't what I expected to find. ; .line 149; main.c bstest = bstest << 5; SWAPF _bstest, W, B ANDLW 0xf0 MOVWF _bstest, B ADDWF _bstest, F, B ; .line 149; main.c bstest = bstest << 7; RRCF _bstest, W, B CLRF _bstest, B RRCF _bstest, F, BWeird, but good :) Quote Link to comment Share on other sites More sharing options...
stryd_one Posted February 11, 2008 Author Report Share Posted February 11, 2008 bitfields in SDCC are limited to 8 bits. For the record:Good news, I have just tested a 15-bit bitfield (15, not 16, to test correct alignment of odd sizes across bytes), and all accesses are correct :)This was with a post 2.7.0 SDCC release. Quote Link to comment Share on other sites More sharing options...
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.