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

Useless Moves

Is there a way to change the DEFINE statement to get rid of the two useless mov(s)?

C51 COMPILER V6.02, COMPILATION OF MODULE MAIN
OBJECT MODULE PLACED IN .\MAIN.OBJ
COMPILER INVOKED BY: C:\PROGRAM FILES\KEIL\C51\BIN\C51.EXE .\MAIN.C OPTIMIZE(7,SPEED) NOINTPROMOTE MODDP2 DEBUG OBJECTEX
                    -TEND CODE SYMBOLS NOCOND

stmt level    source

   1          typedef unsigned char BYTE;
   2          typedef unsigned int  WORD;
   3          
   4          typedef pdata struct 
   5          {
   6            BYTE PC0           :1;
   7            BYTE PC1           :1;
   8            BYTE nFifoPend     :1; //PC2
   9            BYTE PC3           :1;
  10            BYTE FpgaReset     :1; //PC4
  11            BYTE PC5           :1;
  12            BYTE PC6           :1;
  13            BYTE PC7           :1; 
  14          } CType;
  15          
  16          extern volatile BYTE pdata xOUTC;
  17          
  18          #define IoPins_FpgaReset ( ((CType pdata*)(&xOUTC))->FpgaReset )
  19          
  20          void main(void)
  21          {
  22   1        IoPins_FpgaReset = 1;
  23   1      }
  24          
  25          


             ; FUNCTION main (BEGIN)
                                           ; SOURCE LINE # 20
                                           ; SOURCE LINE # 21
                                           ; SOURCE LINE # 22
0000 7A00        E     MOV     R2,#HIGH xOUTC
0002 7900        E     MOV     R1,#LOW xOUTC
0004 7800        E     MOV     R0,#LOW xOUTC
0006 E2                MOVX    A,@R0
0007 4410              ORL     A,#010H
0009 F2                MOVX    @R0,A
                                           ; SOURCE LINE # 23
000A 22                RET     
             ; FUNCTION main (END)

Parents
  • 1. bit-fields in Keil C (8051's fault) are horribly inefficient.

    2. Pdata still requires two bytes for a pointer when we cannot guarantee that the page (a 256 byte block of xdata) is not currently loaded.

    How does this work for you?

    typedef enum
    {
        PC0        = 1 << 0,
        PC1        = 1 << 1,
        FIFO_PEND  = 1 << 2,
        PC3        = 1 << 3,
        FPGA_RESET = 1 << 4,
        PC5        = 1 << 5,
        PC6        = 1 << 6,
        PC7        = 1 << 7
    } FpgaPortC;
    
    
    typedef unsigned char U8;
    
    // I use 'r_' to indicate some sore of register variable.
    static volatile U8 pdata r_portC _at_ 0x8000; // 0x8000 is a guess.
    
    #ifdef MUST_INLINE
    #define  resetFpga()  do { r_portC |= FPGA_RESET; } while (0)
    #else
        void resetFpga(void) { r_portC |= FPGA_RESET; }
    #endif
    
    void main(void)
    {
        resetFpga();
    
        for (;;);
    }
    
    ;; *** No inlining ***
                 ; FUNCTION resetFpga (BEGIN)
                                               ; SOURCE LINE # 273
                                               ; SOURCE LINE # 274
                                               ; SOURCE LINE # 275
    0000 7800              MOV     R0,#LOW r_portC
    0002 E2                MOVX    A,@R0
    0003 4410              ORL     A,#010H
    0005 F2                MOVX    @R0,A
                                               ; SOURCE LINE # 276
    0006 22                RET     
                 ; FUNCTION resetFpga (END)
    
                 ; FUNCTION main (BEGIN)
                                               ; SOURCE LINE # 279
                                               ; SOURCE LINE # 280
                                               ; SOURCE LINE # 281
    0000 120000      R     LCALL   resetFpga
                                               ; SOURCE LINE # 283
    0003         ?C0002:
    0003 80FE              SJMP    ?C0002
                 ; FUNCTION main (END)
    
    ;; *** Inlining ***
                 ; FUNCTION main (BEGIN)
                                               ; SOURCE LINE # 279
                                               ; SOURCE LINE # 280
                                               ; SOURCE LINE # 281
    0000 7800              MOV     R0,#LOW r_portC
    0002 E2                MOVX    A,@R0
    0003 4410              ORL     A,#010H
    0005 F2                MOVX    @R0,A
                                               ; SOURCE LINE # 283
    0006         ?C0004:
    0006 80FE              SJMP    ?C0004
                 ; FUNCTION main (END)
    
    In both cases:
    C51 COMPILER V6.10, COMPILATION OF MODULE UART
    OBJECT MODULE PLACED IN .\a.OBJ
    COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE .\a.c BROWSE NOINTPROMOTE DEBUG OBJECTEXTEND CODE PAGEWIDTH(132) PAGELENGTH(6600) 
    
    - Mark

Reply
  • 1. bit-fields in Keil C (8051's fault) are horribly inefficient.

    2. Pdata still requires two bytes for a pointer when we cannot guarantee that the page (a 256 byte block of xdata) is not currently loaded.

    How does this work for you?

    typedef enum
    {
        PC0        = 1 << 0,
        PC1        = 1 << 1,
        FIFO_PEND  = 1 << 2,
        PC3        = 1 << 3,
        FPGA_RESET = 1 << 4,
        PC5        = 1 << 5,
        PC6        = 1 << 6,
        PC7        = 1 << 7
    } FpgaPortC;
    
    
    typedef unsigned char U8;
    
    // I use 'r_' to indicate some sore of register variable.
    static volatile U8 pdata r_portC _at_ 0x8000; // 0x8000 is a guess.
    
    #ifdef MUST_INLINE
    #define  resetFpga()  do { r_portC |= FPGA_RESET; } while (0)
    #else
        void resetFpga(void) { r_portC |= FPGA_RESET; }
    #endif
    
    void main(void)
    {
        resetFpga();
    
        for (;;);
    }
    
    ;; *** No inlining ***
                 ; FUNCTION resetFpga (BEGIN)
                                               ; SOURCE LINE # 273
                                               ; SOURCE LINE # 274
                                               ; SOURCE LINE # 275
    0000 7800              MOV     R0,#LOW r_portC
    0002 E2                MOVX    A,@R0
    0003 4410              ORL     A,#010H
    0005 F2                MOVX    @R0,A
                                               ; SOURCE LINE # 276
    0006 22                RET     
                 ; FUNCTION resetFpga (END)
    
                 ; FUNCTION main (BEGIN)
                                               ; SOURCE LINE # 279
                                               ; SOURCE LINE # 280
                                               ; SOURCE LINE # 281
    0000 120000      R     LCALL   resetFpga
                                               ; SOURCE LINE # 283
    0003         ?C0002:
    0003 80FE              SJMP    ?C0002
                 ; FUNCTION main (END)
    
    ;; *** Inlining ***
                 ; FUNCTION main (BEGIN)
                                               ; SOURCE LINE # 279
                                               ; SOURCE LINE # 280
                                               ; SOURCE LINE # 281
    0000 7800              MOV     R0,#LOW r_portC
    0002 E2                MOVX    A,@R0
    0003 4410              ORL     A,#010H
    0005 F2                MOVX    @R0,A
                                               ; SOURCE LINE # 283
    0006         ?C0004:
    0006 80FE              SJMP    ?C0004
                 ; FUNCTION main (END)
    
    In both cases:
    C51 COMPILER V6.10, COMPILATION OF MODULE UART
    OBJECT MODULE PLACED IN .\a.OBJ
    COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE .\a.c BROWSE NOINTPROMOTE DEBUG OBJECTEXTEND CODE PAGEWIDTH(132) PAGELENGTH(6600) 
    
    - Mark

Children
  • Thanks for the suggestion.

    However
    1. I have never found that the bit-fields in Keil C inefficient.

    2. When there is only one page of XDATA (which is common in small designs), it is fairly easy guarantee the correct page is loaded. If fact the 'upper address byte' is irrelevent.

    In particular, this design is using an Anchor chip that has all of it's control registers on one page. I just load the MPAGE register with the page address once and never have to use the DPTR for control access again.