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

Optimizing code for one off variable

Hi,

Taking the code snippet below,

char* ptr  = (char*)0x0000;
short size = 0x100;
short sum  = 0x00;

do {
   sum += *ptr++;
} while (size--)

This will cause C51 to allocate "ptr" and "size" in RAM.

        MOV     R3,#00H
        MOV     R2,#00H
        MOV     R1,#00H
        MOV     DPTR,#pre?1251
        MOVX    @DPTR,PR0

        MOV     DPTR,#size?1252
        MOV     A,#01H
        MOVX    @DPTR,A
        INC     DPTR
        CLR     A
        MOVX    @DPTR,A

and everytime "size" is decremented, or "ptr" is incremented, the values are loaded back into the RAM.

Is there a way to force C51 to not use RAM but use the registers only as "ptr" and "size" will never be used anymore after that. What I mean is, is there a way to force C51 to compile to something like this,

mov dptr, #WORD0(00h)
mov r4, #01h ; r4:r5 = size
mov r5, #00h
mov r6, #00h ; r6:r7 = sum
mov r7, #00h

loop:
movx A, @dptr+#000h
addw 006h, A ; r6:r7 += A

inc  dptr
subw 004h, 001h ; r4:r5--
jnc  loop

; add code to store r6:r7 into RAM

Any advice would be greatly appreciated. Thanks in advance.

  • Hi,

    My mistake. I just simply write a simple code snippet as example to explain what I meant. Thank you for pointing out the mistake in the sample.

    However, I have no issue writing the code in ASM to optimize it. The reason for this thread is to find out whether there is a way to at least force C51 to compile to code to avoid using RAM for variable that is used within the scope/loop. If possible, forcing it to use the DPTR, EPTR, PR0, PR1 directly.

  • Maybe I need to clarify further,

    The compiler will eventually load the pointer into dptr, eptr, pr0 or pr1 before read the value it pointed to. When I increment it in C, it will produce a code to increment the variable which is kept in the RAM, then it will load it back to either dptr, eptr, pr0 or pr1 before reading the value again. What I want is for it to increment dptr, eptr, pr0 or pr1 directly and thus avoid re-loading it back from RAM to register in each loop.

    C51 produced code,

    1. Allocate RAM area for pointer
    2. Load pointer with address
    3. Loop
       3.1 Load pointer from RAM to register (dptr, eptr, pr0 or pr1)
       3.2 Load value from dptr, eptr, pr0 or pr1
       3.3 ...
       3.4 Increment pointer in RAM
    4. ...
    

    What I want is,

    1. Load address into register (dptr, eptr, pr0, or pr1)
    2. Loop
       2.1 Load value from dptr, eptr, pr0 or pr1
       2.2 ...
       2.3 Increment dptr, eptr, pr0 or pr1
    3. ...
    

  • Btw, it's not just pointer. If possible, I also want variable which is used as counter to be kept in register without saving it to RAM each time it is incremented or decremented.

  • What I want is for it to increment dptr, eptr, pr0 or pr1 directly and thus avoid re-loading it back from RAM to register in each loop.

    Sounds like you are more than happy to take on the compiler's job. Ignore the compiler then, write in assembly.
    It also sounds like you are not happy with the quality of the code generated by this compiler. By the way, I share your view. It would be reasonble to look for a different compiler. I hear IAR make good compilers, and they happen to have one for the 8051.

  • By manually writing in assembly using registers, I manage to speed up the task by 50%. However it would be tedious to do so as the reason to use C is to simplify coding.
    while wrinting small routines in asm for speed reasons is a very valid approach, it you have to write large amounts of code in asm to achieve your goal, this is the wrong approach unless your product is to ship in millions.
    Wrinting small routines in asm for speed reasons is hardly 'tedious' and, typically, for the very reason they are small it will be write, debug and forget, so the 'tedium' is just once.

    Erik