Menu

#49 8x8 multiply uses 16bit intermediate

closed
None
5
2004-01-25
2003-12-14
No

the other operators are fine, but multiply
uses a 16bit intermediate:

volatile unsigned char s,t;
void main()
{
s=t*5; // this uses an 16 bit intermediate
s=t/5; // whereas the other operators are fine
without
s=t%5;
s=t+5;
s=t-5;
}

Discussion

  • Maarten Brock

    Maarten Brock - 2004-01-20

    Logged In: YES
    user_id=888171

    This also applies to indexing an array of elements with size
    <256.

    long int x[];
    long y;
    unsigned char i;

    y = x[i];

    Both i and sizeof(x[0]) get cast up to int and _mulint is called.

     
  • Bernhard Held

    Bernhard Held - 2004-01-20

    Logged In: YES
    user_id=203539

    The array access has been fixed at least in SDCCicode.c 1.183

     
  • Mathias Neuhaus

    Mathias Neuhaus - 2004-01-21

    Logged In: YES
    user_id=850360

    According to the ANSI type conversion rules the code
    generated by SDCC is correct for the multiplication example
    and the array-access.
    The code generated for /%+- is incorrect!

    5 is an integer constant (there ain't no such thing as a char
    constant!!), so both operands have to be converted to int;
    the result of the operation is then cast back to char.

    Similar for the array access:
    sizeof (something) returns size_t, which - in most cases - is
    "typedef int size_t;" or "#define size_t int".
    Again we start with one int and one char (the index i) which
    has to be promoted to int.

    To keep ANSI compatibility, please DON'T change the
    behaviour for the multiplication, but correct the behaviour for
    operators /%+-.

    The user can force use of 8-bit operation by an explicit cast
    (well, should be, didn't try!).

    Taking into account the memory- and runtime-constraints of
    embedded systems, you might implement some #pragma to
    force 8bit operations, or something a "char-suffix" (similar to
    the long-suffix L).

     
  • Erik Petrich

    Erik Petrich - 2004-01-22

    Logged In: YES
    user_id=635249

    It is acceptable to skip integer promotion as long as the
    same result is obtained as if the promotion occurred (often
    referred to as the "as-if semantics"). A quote from ISO/IEC
    9899-1999 (the C-99 standard), section 5.1.2.3 Example 2:

    "In executing the fragment

    char c1, c2;
    /* ... */
    c1 = c1 + c2;

    the "integer promotions" require that the abstract machine
    promote the value of each variable to int size and then add
    the two ints and truncate the sum. Provided the addition of
    two chars can be done without overflow, or with overflow
    wrapping silently to produce the correct result, the actual
    execution need only produce the same result, possibly
    omitting the promotions."

    The user can't force the use of 8-bit operation by an
    explicit cast since the integer promotion rules make no
    exception for dealing with the result of a cast. You can
    explicitly cast to char all you want, but the rules will
    still cause a final cast to int before the operator is
    applied. 8-bit operations are only possible using the as-if
    semantics.

     
  • Mathias Neuhaus

    Mathias Neuhaus - 2004-01-22

    Logged In: YES
    user_id=850360

    Eric, as far as I understand the ISO documents, that rule
    comes into effect only, when the operands are of the same
    type...

    ISO/IEC 9899/1999 - 6.3.1.8:
    "... (conversion rules for float and double) ...
    Otherwise, the integer promotions are performed on both
    operands. Then the following rules are applied to the
    promoted operands:
    -- If both operands have the same type, then no
    further conversion is needed.
    -- Otherwise, if both operands have signed integer
    types or both have unsigned integer types, the
    operand with the type of lesser integer conversion
    rank is converted to the type of the operand with
    greater rank.
    ..."
    (ranks are defined in 6.3.1.1, and rank (int) > rank (char))

    According to 5.1.2.3 ex. 2 the promotion can be skipped, but
    the type conversions have to be done in any case.
    Because 5 is of type int (there is no char constant (6.4.4.1)),
    the other operand (t) has to be converted (not promoted!) to
    int as well (2nd rule), even though promotion was skipped.
    On the other hand, when you cast the int constant to a char
    constant ((char) 5), no conversion has to be done (1st rule).

    I mixed up "promotion" and "conversion" in my first post, sorry.
    And 5 is an int constant, not an integer constant (sorry once
    again).

     
  • Bernhard Held

    Bernhard Held - 2004-01-22

    Logged In: YES
    user_id=203539

    5 is an 'unsigned char' in SDCC, and it would be very unwise
    to choose anything else. If it would be an int, the code size
    would explode.
    In this special case I don't care about a violation of the
    standard. But I take much care about the correctness of the
    results. The correct result is of course defined by the
    standard.

     
  • Bernhard Held

    Bernhard Held - 2004-01-25

    Logged In: YES
    user_id=203539

    Fixed, see ChangeLog 1.605
    The new type flow is enabled with the environment variable
    SDCC_NEWTYPEFLOW
    Discussion in sdcc-user

     
  • Bernhard Held

    Bernhard Held - 2004-01-25
    • assigned_to: nobody --> bernhardheld
    • status: open --> closed
     

Log in to post a comment.

MongoDB Logo MongoDB