Hello!

There is something strange with multiplication of constant byte numbers.

----------------------------------------------------------------------------
------
Example 1.1:

unsigned int multiplikation (unsigned char wert)
{
   return (unsigned int)((unsigned int)wert*((unsigned int)180));
   0:   02 12           push    r2              ;
   2:   32 c2           dint                    
   4:   03 43           nop                     
   6:   c2 4f 30 01     mov.b   r15,    &0x0130 ;
   a:   c2 43 31 01     mov.b   #0,     &0x0131 ;r3 As==00
   e:   b2 40 b4 ff     mov     #-76,   &0x0138 ;#0xffb4           
  12:   38 01 
  14:   c2 43 39 01     mov.b   #0,     &0x0139 ;r3 As==00
  18:   1f 42 3a 01     mov     &0x013a,r15     ;0x013a
  1c:   32 41           pop     r2              ;
}
  1e:   30 41           ret                     
----------------------------------------------------------------------------
------

At line (e:) the high byte is set to 0xff. Because of the word access the
hardware multiplier will start and line (14:) has no effect.

With storing the 180 in uiTemp the code is ok (Example 1.2).

----------------------------------------------------------------------------
------
Example 1.2:

unsigned int multiplikation (unsigned char wert)
{
   unsigned int uiTemp = 180;
   return (unsigned int)((unsigned int)wert*(unsigned int)uiTemp);
   0:   7f f3           and.b   #-1,    r15     ;r3 As==11
   2:   02 12           push    r2              ;
   4:   32 c2           dint                    
   6:   03 43           nop                     
   8:   82 4f 32 01     mov     r15,    &0x0132 ;
   c:   b2 40 b4 00     mov     #180,   &0x0138 ;#0x00b4
  10:   38 01 
  12:   1f 42 3a 01     mov     &0x013a,r15     ;0x013a
  16:   32 41           pop     r2              ;
}
  18:   30 41           ret                     
----------------------------------------------------------------------------
------

The next example uses adding and shifting for multiplikation.
----------------------------------------------------------------------------
------
Example 2.1:

unsigned int multiplikation (unsigned char wert)
{
   return (unsigned int)((unsigned int)wert*((unsigned int)129));
   0:   4e 4f           mov.b   r15,    r14     ;
   2:   0e 5e           rla     r14             ;
   4:   0e 5e           rla     r14             ;
   6:   0e 5e           rla     r14             ;
   8:   0e 5e           rla     r14             ;
   a:   0e 5e           rla     r14             ;
   c:   0e 5e           rla     r14             ;
   e:   0e 5e           rla     r14             ;
  10:   7f f3           and.b   #-1,    r15     ;r3 As==11
  12:   0f 8e           sub     r14,    r15     ;
}
  14:   30 41           ret                     
----------------------------------------------------------------------------
------
The value to return ist wert - wert*128 and not wert + wert*128.

With storing the 129 in uiTemp the code is ok again (Example 2.2).
----------------------------------------------------------------------------
------
Example 2.2:

unsigned int multiplikation (unsigned char wert)
{
   unsigned int uiTemp = 129;
   return (unsigned int)((unsigned int)wert*(unsigned int)uiTemp);
   0:   7f f3           and.b   #-1,    r15     ;r3 As==11
   2:   02 12           push    r2              ;
   4:   32 c2           dint                    
   6:   03 43           nop                     
   8:   82 4f 32 01     mov     r15,    &0x0132 ;
   c:   b2 40 81 00     mov     #129,   &0x0138 ;#0x0081
  10:   38 01 
  12:   1f 42 3a 01     mov     &0x013a,r15     ;0x013a
  16:   32 41           pop     r2              ;
}
  18:   30 41           ret                     
----------------------------------------------------------------------------
------

Used options for mspgcc: -x c -c -g -O2 -Wall -mmcu=msp430x147 

Release: mspgcc-20040723.exe

Is the different behavior between examples 1.1 and 1.2 and between 2.1 and
2.2 a bug or a feature?
Or is it my mistake?

Marcus Else

Reply via email to