This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to get the C-compiler to use RLC and ACC.x

Hello,

I would like to know if there's any way I can write C code that will use the assembly instructions RLC and ACC.x efficiently. I would like to some C code that will result in:

MOV A,byBuffer
MOV c,bInput
RLC A
MOV byBuffer,A

The closest I could get was this:

byBuffer=(byBuffer<<1)&bInput;

Which results in:

MOV A,byBuffer
ADD A,ACC
MOV R7,A
MOV C,bInput
CLR A
RLC A
ANL A,R7
MOV byBuffer,A

The same thing happens when I want to use a specific bit from a byte. I have never seen the C-compiler use the ACC.x instruction. It uses solutions like this:

MOV A,R6
MOV R0,AR5
INC R0
SJMP ?C0078
?C0077:
CLR C
RLC A
?C0078:
DJNZ R0,?C0077

Any ideas ????

Parents
  • Sorry, forgot to use the pre and /pre....

    //--------------------------------------//

    Hello,

    I would like to know if there's any way I can write C code that will use the assembly instructions RLC and ACC.x efficiently. I would like to some C code that will result in:

    MOV A,byBuffer
    MOV c,bInput
    RLC A
    MOV byBuffer,A
    
    The closest I could get was this:
    byBuffer=(byBuffer<<1)&bInput;
    
    Which results in:
    MOV A,byBuffer
    ADD A,ACC
    MOV R7,A
    MOV C,bInput
    CLR A
    RLC A
    ANL A,R7
    MOV byBuffer,A
    
    The same thing happens when I want to use a specific bit from a byte. I have never seen the C-compiler use the ACC.x instruction. It uses solutions like this:
    MOV A,R6
    MOV R0,AR5
    INC R0
    SJMP ?C0078
    ?C0077:
    CLR C
    RLC A
    ?C0078:
    DJNZ R0,?C0077
    
    Any ideas ????

Reply
  • Sorry, forgot to use the pre and /pre....

    //--------------------------------------//

    Hello,

    I would like to know if there's any way I can write C code that will use the assembly instructions RLC and ACC.x efficiently. I would like to some C code that will result in:

    MOV A,byBuffer
    MOV c,bInput
    RLC A
    MOV byBuffer,A
    
    The closest I could get was this:
    byBuffer=(byBuffer<<1)&bInput;
    
    Which results in:
    MOV A,byBuffer
    ADD A,ACC
    MOV R7,A
    MOV C,bInput
    CLR A
    RLC A
    ANL A,R7
    MOV byBuffer,A
    
    The same thing happens when I want to use a specific bit from a byte. I have never seen the C-compiler use the ACC.x instruction. It uses solutions like this:
    MOV A,R6
    MOV R0,AR5
    INC R0
    SJMP ?C0078
    ?C0077:
    CLR C
    RLC A
    ?C0078:
    DJNZ R0,?C0077
    
    Any ideas ????

Children
  • I don't think that it is quite what you are looking for, but there are a number of intrinsic functions provided by Keil and detailed in the C51 Compiler Manual. Most of these intrinsic functions roll a 1, 2 or 4-byte variable n places left or right. Although not perfect, the code for 1 and 2 byte variables is put in-line (rather than a function call) and they make use of RLC type instructions so that they are reasonably fast when shifting by a small number of bits.

    In spite of the claims of the manual, the rolls for 4-byte variables are actually implemented by library calls. Also, if I recall correctly from the last time that I looked, the compiler always codes a loop even when the roll is know to be just one bit.

    For a faster way to roll long variables, see: http://www.keil.com/forum/docs/thread1252.asp

    C can access any bit of a variable by various means. See http://www.keil.com/forum/docs/thread554.asp for some examples The most portable method it to use masks, but I don't think that that will generate an ACC.x type reference. The most obvious method is to use a structure containing fields with a width of just one bit, this will cause ACC.x type instructions to be generated, but Keil does not seem to make very efficient use of them (see http://www.keil.com/forum/docs/thread1291.asp ).

    In the end, if there are just a few very specific functions that you want to perform then your best bet is going to be to write an assembly language sub-routine that you can call from a C function.

  • First of all, your C code fragment doesn't do what the ASM did. The truly equivalent C fragment would have been:

      byBuffer=(byBuffer<<1) | bInput;
    

    Note the '|' instead of '&' before bInput.

    Anyway: your original assembly isn't picture-perfect, either, so there's not much reason that the C compiler should generate that for any given piece of C code.

      MOV	A, byBuffer
      RL	A
      MOV	ACC.7, bInput
      MOV	byBuffer, A
    

    would have been better, because it doesn't pollute whatever
    was in the carry bit before.