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

ARM7TDMI: SUBS vs SUB + CMP

Note: This was originally posted on 2nd April 2009 at http://forums.arm.com

Hi,

I have a question regarding the SUBS instruction and how it compares to SUB and CMP (due to unexpected behavior in a C-program).

The original C-code goes like this (all variables are 32 bit signed integers):

    t = a*b - c*c;
    if (t > 0) d = t;

In a particular case (a = 0x80, b = 0x106DCD9, c = 0x4E352501) I get an overflow in a*b as well as in the subtraction. What is puzzling to me is that there's a difference between the the following two assembler versions in a certain simulated environment - and I'm trying to figure out if this is expected or a bug in the simulator:

MUL temp1, c, c
MUL temp2, a, b
SUBS t, temp2, temp1
MOVGT d, t

and

MUL temp1, c, c
MUL temp2, a, b
SUB t, temp2, temp1
CMP t, #0
MOVGT d, t

(These are genereated depending on different compiler settings.)

Any help is greatly appreciated!

Greger
Parents
  • Note: This was originally posted on 3rd April 2009 at http://forums.arm.com

    Thank you for your answers!

    I realize I gave the wrong numbers. The calculation in question (indeed, the root cause is poor algorithm design) is

    t = 0x80 * 0x106DCD9 - 0x8D7F * 0x8D7F

    => t = 0x836E6C80 - 0x4E352501 (=0x3539477F)

    (a = 0x80, b = 0x106DCD9, c = 0x8DF, a*b = 0x836E6C80, c*c = 0x4E352501)

    So, if I understand you right we should have

    MUL temp1, c, c => no overflow flag, no negative flag (this is in bounds)
    MUL temp2, a, b => negative flag, no overflow flag (but shouldn't overflow be set since it's a signed multiply?)
    SUBS t, temp2, temp1 => no negative flag, overflow flag (underflow)
    MOVGT d, t => MOV is not executed

    and

    MUL temp1, c, c => no overflow flag, no negative flag (this is in bounds)
    MUL temp2, a, b => negative flag, no overflow flag (but shouldn't overflow be set since it's a signed multiply?)
    SUB t, temp2, temp1
    CMP t, #0  => 0x3539477F  - 0 => no negative flag, no overflow overflow flag
    MOVGT d, t => MOV is executed

    OK. Then it is really not a problem with the simulator but that the optimizer takes a legal short cut due to a poorly designed algorithm (which overflows). "Good."

    Just a follow-up question here, shouldn't the negative flag be set in the SUBS? I mean we do subtract a positive number from a negative number.

    Thanks again!

    Greger
Reply
  • Note: This was originally posted on 3rd April 2009 at http://forums.arm.com

    Thank you for your answers!

    I realize I gave the wrong numbers. The calculation in question (indeed, the root cause is poor algorithm design) is

    t = 0x80 * 0x106DCD9 - 0x8D7F * 0x8D7F

    => t = 0x836E6C80 - 0x4E352501 (=0x3539477F)

    (a = 0x80, b = 0x106DCD9, c = 0x8DF, a*b = 0x836E6C80, c*c = 0x4E352501)

    So, if I understand you right we should have

    MUL temp1, c, c => no overflow flag, no negative flag (this is in bounds)
    MUL temp2, a, b => negative flag, no overflow flag (but shouldn't overflow be set since it's a signed multiply?)
    SUBS t, temp2, temp1 => no negative flag, overflow flag (underflow)
    MOVGT d, t => MOV is not executed

    and

    MUL temp1, c, c => no overflow flag, no negative flag (this is in bounds)
    MUL temp2, a, b => negative flag, no overflow flag (but shouldn't overflow be set since it's a signed multiply?)
    SUB t, temp2, temp1
    CMP t, #0  => 0x3539477F  - 0 => no negative flag, no overflow overflow flag
    MOVGT d, t => MOV is executed

    OK. Then it is really not a problem with the simulator but that the optimizer takes a legal short cut due to a poorly designed algorithm (which overflows). "Good."

    Just a follow-up question here, shouldn't the negative flag be set in the SUBS? I mean we do subtract a positive number from a negative number.

    Thanks again!

    Greger
Children
No data