multiplication with signed/unsigned

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

ARM instruction manual referring Cortex-M0 says there is a single instruction possibility muls R0,R1,R0

   

I can't figure out if it's signed/unsigned operation.

   

I try to multiply signed char with constant , like (signed_char * 40000 and I got always wrong value.

   

I tried (int32)signed_char * 40000 and this also give wrong value

   

I found that regardless of the C formula (int32) or (uint32) the compiler translates it to thumb instruction mul R0,R1

   

Thanks

0 Likes
9 Replies
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

This may be a compiler problem, you could always do inline ASM and

   

handle the issue yourself.

   

 

   

Consider filing a CASE (and post back what you found out to bebefit the forum) -

   

 

   

    

   

                    

   

www.cypress.com

   

“Support”

   

“Technical Support”

   

“Create a MyCase”

   

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Do You know about the result of mul instruction? Signed or unsigned?

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

According to http://infocenter.arm.com/help/topic/com.arm.doc.dui0497a/BABCFBDJ.html , muls works with signed and unsigned operands.

   

According to http://infocenter.arm.com/help/topic/com.arm.doc.dui0204f/Cihihggj.html , this is true also for mul. (mul and muls differ only in how flags are updated).

   

I'm not sure whether the cast in '(int32)signed_char * 40000' is for the result or the first operand. If its the former, than the multiplication is done signed (because you have a signed char) and then casted. This might result in wrong values (depending on what you have in the char).

   

Can you post a small example where you get wrong results?

0 Likes
Anonymous
Not applicable

function in C:
void MoveValve(int8 percent){
    int32 tmp;
    tmp = pDataConfig->SerVoCurrentPWM - ((int32)(percent*(SERVO_MIN_OPEN*(1<<26)/100)) >> 26);

   

}
SERVO_MIN_OPEN - constant

   

SERVO_MIN_OPEN*(1<<26)/100 = 1006632960 = 0x3C000000 (6 zero's)
pDataConfig->SerVoCurrentPWM - uint16

   


why this function produce following code:
ldr    r1, .L65
 505 0004 084B             ldr    r3, .L65+4
 506 0006 4843             mul    r0, r1
 507                  .LVL49:
 508 0008 1B68             ldr    r3, [r3]
 509 000a 8016             asr    r0, r0, #26
 510 000c 9A8B             ldrh    r2, [r3, #28]
 511 000e 111A             sub    r1, r2, r0
 

   

I pass percent value of -100 . assembly multiplies (126 * constant) and returns positive output.

0 Likes
Anonymous
Not applicable

Another problem:

   

1500*(1<<26)/100= 15*(1<<26)=0x3C000000

   

compiler makes 0x011EB851

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Shifting 100 or -100 left by 26 positions will exceed the 31 bits (one is used for sign) you have got for the intermediate result, so you will ALWAYS get a wrong result. Use the windows calculator, set it to "Programmer's Mode", set the width to DWord and start calculating. Watch the bit patterns.

   

How to get out of this? First try could be to use float math. If you'd lije to optimize size and speed you will have to arrange your calculation into some statements and group them in a way that no overflow may occure.

   

As I suspect the value of shifting to improve the precision of the result must be reduced, too

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Thanks. My calculator calculated wrong value

0 Likes
Anonymous
Not applicable

One thing I  found awhile ago.  I had some code as following

   

uint32 value;

   

value = 1<< 24;

   

and the value is wrong.

   

needs to be

   

value = (uint32)1 << 24;

   

Not sure if that can be problem with GCC now.

0 Likes
Anonymous
Not applicable

Also note that the result of shifting of a signed variable is compiler dependent. So it may not return the value you expected.

0 Likes