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 drop unuse code?

I wrote a program compress time to long. But some output give to much ( outout asm ). How can I reduce unuse code. see output below.

my source.

extern unsigned char convBcd2Hex(unsigned char c);

void convert( void )
{
  unsigned long dwTmp;

                      dwTmp =         convBcd2Hex( sClock[YEAR]  ); // 4 year
  _lrol_( dwTmp, 4 ); dwTmp = dwTmp | convBcd2Hex( sClock[MONTH] ); // 4 month
  _lrol_( dwTmp, 5 ); dwTmp = dwTmp | convBcd2Hex( sClock[DAY]   ); // 5 day
  _lrol_( dwTmp, 5 ); dwTmp = dwTmp | convBcd2Hex( sClock[HOUR]  ); // 5 hour
  _lrol_( dwTmp, 6 ); dwTmp = dwTmp | convBcd2Hex( sClock[MINUTE]); // 6 minute
  _lrol_( dwTmp, 6 ); dwTmp = dwTmp | convBcd2Hex( sClock[SECOND]); // 6 second

}
my output list.

                                           ; SOURCE LINE # 140
001F AF00        E     MOV     R7,sClock+06H
0021 120000      R     LCALL   _convBcd2Hex
0024 E4                CLR     A
0025 8F00        R     MOV     dwTmp+03H,R7
0027 F500        R     MOV     dwTmp+02H,A
0029 F500        R     MOV     dwTmp+01H,A
002B F500        R     MOV     dwTmp,A
                                           ; SOURCE LINE # 141
002D AE00        R     MOV     R6,dwTmp+02H
002F AD00        R     MOV     R5,dwTmp+01H
0031 AC00        R     MOV     R4,dwTmp
0033 7804              MOV     R0,#04H
0035 120000      E     LCALL   ?C?LROL
0038 AF00        E     MOV     R7,sClock+05H
003A 120000      R     LCALL   _convBcd2Hex
003D E4                CLR     A
003E EF                MOV     A,R7
003F 4500        R     ORL     A,dwTmp+03H
0041 F500        R     MOV     dwTmp+03H,A
0043 E500        R     MOV     A,dwTmp+02H  +
0045 F500        R     MOV     dwTmp+02H,A  |
0047 E500        R     MOV     A,dwTmp+01H  |-- How can I reduct this code?
0049 F500        R     MOV     dwTmp+01H,A  |
004B E500        R     MOV     A,dwTmp      |
004D F500        R     MOV     dwTmp,A      +
                                           ; SOURCE LINE # 142
004F AF00        R     MOV     R7,dwTmp+03H
0051 AE00        R     MOV     R6,dwTmp+02H
0053 AD00        R     MOV     R5,dwTmp+01H
0055 FC                MOV     R4,A
0056 7805              MOV     R0,#05H
0058 120000      E     LCALL   ?C?LROL
005B AF00        E     MOV     R7,sClock+04H
005D 120000      R     LCALL   _convBcd2Hex
0060 E4                CLR     A
0061 EF                MOV     A,R7
0062 4500        R     ORL     A,dwTmp+03H
0064 F500        R     MOV     dwTmp+03H,A
0066 E500        R     MOV     A,dwTmp+02H  +
0068 F500        R     MOV     dwTmp+02H,A  |
006A E500        R     MOV     A,dwTmp+01H  |-- How can I reduct this code? 
006C F500        R     MOV     dwTmp+01H,A  |
006E E500        R     MOV     A,dwTmp      |
0070 F500        R     MOV     dwTmp,A      +

  • void convert( void )
    {
        unsigned long dwTmp;
    
                                           dwTmp  = convBcd2Hex( sClock[YEAR]  ); // 4 year
        _lrol_( dwTmp, 4 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[MONTH] ); // 4 month
        _lrol_( dwTmp, 5 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[DAY]   ); // 5 day
        _lrol_( dwTmp, 5 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[HOUR]  ); // 5 hour
        _lrol_( dwTmp, 6 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[MINUTE]); // 6 minute
        _lrol_( dwTmp, 6 ); (unsigned char)dwTmp |= convBcd2Hex( sClock[SECOND]); // 6 second
    }
    
    

  • Shorter code that does the wrong thing is no good at all. Sorry, my previous reply OR's into the MSB not the LSB like I was expecting. I should have checked the resulting code a bit closer.

  • I could not give you a correct reply to your question, but I can give you a correction to a problem.

    I don't think your usage of _lrol_() is going to do what you want as it stands right now. The manual does not indicate that _lrol_() rotates its long argument "in place". The manual says that _lrol_() returns the rotated value, so you would want to assign the return value back to dwTmp or use the return value as part of the OR expression.

  • What optimiser setting are you using?

    Note that _lrol_ is not compiled inline - contrary to what it says in the manual!
    See http://www.keil.com/forum/msgpage.asp?Offset=-1&MsgID=3914

    I think the Keil _lrol_ is be rather inefficient - try a search for previous discussions?

  • Even the best compilers will generate some unnecessary code - it can be very frustrating especially if you come from an assembly language background.

    You are not using _lrol_ in quite the right way, although that is not the root of your question. It looks like the compiler is casting the return value of convBcd2Hex() an insists on "going through the motions" when performing an OR.

    Have you tried using a union between a long and a structure with bit fields defined for each of the components year, month day... etc. It would look something like this:

    typedef struct
    {
        unsigned char   year   :5
        unsigned char   month  :4
        unsigned char   day    :5
        unsigned char   hour   :6
        unsigned char   minute :6;
        unsigned char   second :6;
    
    } date_time_record_type;
    
    typedef union
    {
        unsigned long          l;
        date_time_record_type  t;
    } date_time_type;
    
    ....
    date_time_type dwTmp;
    ....
    dwTmp.t.month = convBcd2Hex( sClock[MONTH] );
    .... 
    
    This way, C will do all the necessary rolling etc. with the programmer having to worry about it. With any luck, Keil will generate more efficient code this way.

    For a faster version of _lrol_ see:

    http://www.keil.com/forum/msgpage.asp?MsgID=4857

  • Have you tried using optimizer level 9?

    Jon

  • I think we go wrong way. The problem is not in _lrol_(). It is in OR operation unsigned long and unsigned char. I use optimizer level 8. but i will try level 9. Thank for Graham Cole about c structure. But i already try it. It take more memory space than i think see below. I want to keep time in memory for time log. So I want optimize space. thank you.

    typedef struct
    {
        unsigned char   year   :4;
        unsigned char   month  :4;
        unsigned char   day    :5;
        unsigned char   hour   :5;
        unsigned char   minute :6;
        unsigned char   second :6;
    
    } date_time_record_type;
    
    typedef union
    {
        unsigned long          l;
        date_time_record_type  t;
    } date_time_type;
    
    date_time_type dwTmp;
    
    

    
    dwTmp. . . . . . . . . . . . . . . . .  PUBLIC   DATA   UNION    0000H  5
    
    date_time_record_type. . . . . . . . .  TYPEDEF  -----  STRUCT   -----  5     <-- use 5 byte not 4 byte
      year . . . . . . . . . . . . . . . .  MEMBER   -----  FIELD    0000H  4.0
      month. . . . . . . . . . . . . . . .  MEMBER   -----  FIELD    0000H  4.4
      day. . . . . . . . . . . . . . . . .  MEMBER   -----  FIELD    0001H  5.0
      hour . . . . . . . . . . . . . . . .  MEMBER   -----  FIELD    0002H  5.0
      minute . . . . . . . . . . . . . . .  MEMBER   -----  FIELD    0003H  6.0
      second . . . . . . . . . . . . . . .  MEMBER   -----  FIELD    0004H  6.0
    
    

  • As ever, if you really must squeeze the last drop of effecieny, you need to write very carefully in Assembler.

    When you use 'C' (or any other high-level languae) you trade absolute control of the generated code for ease of writing & maintaining the source code.