Thread overview
How to fix this warning problem:
Jan 18, 2006
Alex Stevenson
Jan 19, 2006
Regan Heath
Jan 19, 2006
BCS
Jan 19, 2006
Alex Stevenson
Jan 19, 2006
BCS
Jan 19, 2006
BCS
Jan 20, 2006
anon
January 18, 2006
I have a quick-and-dirty inplace endianness conversion function for ushorts:

ushort ConvertEndian(inout ushort input)
{
    version(LittleEndian)
    {
        return (input = ((input & 0xff00) >>> 8) |
                        ((input & 0x00ff) <<  8));
    }
    else
    {
        return input;
    }
}

Compiling with -w on DMD always gives the warning:
warning - util.d(40): implicit conversion of expression ((cast(int)(input) & 65280) >> 8 | (cast(int)(input) & 255) << 8) of type int to ushort can cause loss of data

I've tried inserting cast(ushort) everywhere I could - but the warning stays... Even when I insert casts before every ( and constant:

warning - util.d(40): implicit conversion of expression (cast(int)cast(ushort)(cast(int)cast(ushort)(cast(int)(input) & 65280) >>> 8) | cast(int)cast(ushort)(cast(int)cast(ushort)(cast(int)(input) & 255) << 8)) of type int to ushort can cause loss of data

Is there something I'm overlooking here? I'd like to use -w as I've been caught out by 'no return' problems a couple of times.
January 19, 2006
On Wed, 18 Jan 2006 17:31:06 +0000, Alex Stevenson <ans104@cs.york.ac.uk> wrote:
> I have a quick-and-dirty inplace endianness conversion function for ushorts:
>
> ushort ConvertEndian(inout ushort input)
> {
>      version(LittleEndian)
>      {
>          return (input = ((input & 0xff00) >>> 8) |
>                          ((input & 0x00ff) <<  8));
>      }
>      else
>      {
>          return input;
>      }
> }
>
> Compiling with -w on DMD always gives the warning:
> warning - util.d(40): implicit conversion of expression ((cast(int)(input) & 65280) >> 8 | (cast(int)(input) & 255) << 8) of type int to ushort can cause loss of data
>
> I've tried inserting cast(ushort) everywhere I could - but the warning stays... Even when I insert casts before every ( and constant:
>
> warning - util.d(40): implicit conversion of expression (cast(int)cast(ushort)(cast(int)cast(ushort)(cast(int)(input) & 65280)  >>> 8) | cast(int)cast(ushort)(cast(int)cast(ushort)(cast(int)(input) & 255) << 8)) of type int to ushort can cause loss of data
>
> Is there something I'm overlooking here? I'd like to use -w as I've been caught out by 'no return' problems a couple of times.

I believe the problem occurs because the operations &, |, >>> and << promote the operands to 'int' and give an 'int' result, therefore passing or assigning the result to a ushort is and "implicit" conversion from int to ushort.

You have to cast the results of each operation to ushort to fix it, eg.

ushort ConvertEndian(inout ushort input)
{
    version(LittleEndian)
    {
        return (input = cast(ushort)(cast(ushort)(cast(ushort)(input & 0xff00) >>> 8) |
                                     cast(ushort)(cast(ushort)(input & 0x00ff) <<  8)));
    }
    else
    {
        return input;
    }
}

or, perhaps just use an int, eg.

ushort ConvertEndian(inout ushort input)
{
    version(LittleEndian)
    {
    	int i = input;
    	
    	i = (((i & 0xff00) >>> 8) |
           ((i & 0x00ff) <<  8));

        return cast(ushort)i;
    }
    else
    {
        return input;
    }
}

Why does "ushort & ushort" require both operands promoted to int?
Why do it?

Regan
January 19, 2006
Regan Heath wrote:
> On Wed, 18 Jan 2006 17:31:06 +0000, Alex Stevenson <ans104@cs.york.ac.uk>  wrote:
> 
>> I have a quick-and-dirty inplace endianness conversion function for  ushorts:
>>
>> ushort ConvertEndian(inout ushort input)
>> {
>>      version(LittleEndian)
>>      {
>>          return (input = ((input & 0xff00) >>> 8) |
>>                          ((input & 0x00ff) <<  8));
>>      }
>>      else
>>      {
>>          return input;
>>      }
>> }
>>
>> Compiling with -w on DMD always gives the warning:
>> warning - util.d(40): implicit conversion of expression  ((cast(int)(input) & 65280) >> 8 | (cast(int)(input) & 255) << 8) of  type int to ushort can cause loss of data
>>
>> I've tried inserting cast(ushort) everywhere I could - but the warning  stays... Even when I insert casts before every ( and constant:
>>
>> warning - util.d(40): implicit conversion of expression  (cast(int)cast(ushort)(cast(int)cast(ushort)(cast(int)(input) & 65280)   >>> 8) | cast(int)cast(ushort)(cast(int)cast(ushort)(cast(int)(input) &  255) << 8)) of type int to ushort can cause loss of data
>>
>> Is there something I'm overlooking here? I'd like to use -w as I've been  caught out by 'no return' problems a couple of times.
> 
> 
> I believe the problem occurs because the operations &, |, >>> and <<  promote the operands to 'int' and give an 'int' result, therefore passing  or assigning the result to a ushort is and "implicit" conversion from int  to ushort.
> 
> You have to cast the results of each operation to ushort to fix it, eg.
> 
> ushort ConvertEndian(inout ushort input)
> {
>     version(LittleEndian)
>     {
>         return (input = cast(ushort)(cast(ushort)(cast(ushort)(input &  0xff00) >>> 8) |
>                                      cast(ushort)(cast(ushort)(input &  0x00ff) <<  8)));
>     }
>     else
>     {
>         return input;
>     }
> }
> 
> or, perhaps just use an int, eg.
> 
> ushort ConvertEndian(inout ushort input)
> {
>     version(LittleEndian)
>     {
>         int i = input;
>                i = (((i & 0xff00) >>> 8) |
>            ((i & 0x00ff) <<  8));
> 
>         return cast(ushort)i;
>     }
>     else
>     {
>         return input;
>     }
> }
> 
> Why does "ushort & ushort" require both operands promoted to int?
> Why do it?
> 
> Regan

Isn't there a byte swap intrinsic function (IIRC it uses 32bit values but a x86 ASM has an XCHG op that does exactly what you are looking for, maybe this should be added to std.intrinsic)
January 19, 2006
BCS wrote:
> Regan Heath wrote:
> 
>> On Wed, 18 Jan 2006 17:31:06 +0000, Alex Stevenson <ans104@cs.york.ac.uk>  wrote:
>>
>>> I have a quick-and-dirty inplace endianness conversion function for  ushorts:
>>>
>>> ushort ConvertEndian(inout ushort input)
>>> {
>>>      version(LittleEndian)
>>>      {
>>>          return (input = ((input & 0xff00) >>> 8) |
>>>                          ((input & 0x00ff) <<  8));
>>>      }
>>>      else
>>>      {
>>>          return input;
>>>      }
>>> }
>>>
>>> Compiling with -w on DMD always gives the warning:
>>> warning - util.d(40): implicit conversion of expression  ((cast(int)(input) & 65280) >> 8 | (cast(int)(input) & 255) << 8) of  type int to ushort can cause loss of data
>>>
>>> I've tried inserting cast(ushort) everywhere I could - but the warning  stays... Even when I insert casts before every ( and constant:
>>>
>>> warning - util.d(40): implicit conversion of expression  (cast(int)cast(ushort)(cast(int)cast(ushort)(cast(int)(input) & 65280)   >>> 8) | cast(int)cast(ushort)(cast(int)cast(ushort)(cast(int)(input) &  255) << 8)) of type int to ushort can cause loss of data
>>>
>>> Is there something I'm overlooking here? I'd like to use -w as I've been  caught out by 'no return' problems a couple of times.
>>
>>
>>
>> I believe the problem occurs because the operations &, |, >>> and <<  promote the operands to 'int' and give an 'int' result, therefore passing  or assigning the result to a ushort is and "implicit" conversion from int  to ushort.
>>
>> You have to cast the results of each operation to ushort to fix it, eg.
>>
>> ushort ConvertEndian(inout ushort input)
>> {
>>     version(LittleEndian)
>>     {
>>         return (input = cast(ushort)(cast(ushort)(cast(ushort)(input &  0xff00) >>> 8) |
>>                                      cast(ushort)(cast(ushort)(input &  0x00ff) <<  8)));
>>     }
>>     else
>>     {
>>         return input;
>>     }
>> }
>>
>> or, perhaps just use an int, eg.
>>
>> ushort ConvertEndian(inout ushort input)
>> {
>>     version(LittleEndian)
>>     {
>>         int i = input;
>>                i = (((i & 0xff00) >>> 8) |
>>            ((i & 0x00ff) <<  8));
>>
>>         return cast(ushort)i;
>>     }
>>     else
>>     {
>>         return input;
>>     }
>> }
>>
>> Why does "ushort & ushort" require both operands promoted to int?
>> Why do it?
>>
>> Regan
> 
> 
> Isn't there a byte swap intrinsic function (IIRC it uses 32bit values but a x86 ASM has an XCHG op that does exactly what you are looking for, maybe this should be added to std.intrinsic)

I use bswap from std.intrinsic for 32-bit values, but there is no corresponding function for 16-bit values. Having done some low-level SCSI work, I find that 16-bit endianness conversions are pretty common and it doesn't make too much sense to be to have an intrinsic for 32-bit endianness swapping but not 16-bit.
January 19, 2006
Alex Stevenson wrote:
> BCS wrote:
[...]
>> Isn't there a byte swap intrinsic function (IIRC it uses 32bit values but a x86 ASM has an XCHG op that does exactly what you are looking for, maybe this should be added to std.intrinsic)
> 
> 
> I use bswap from std.intrinsic for 32-bit values, but there is no corresponding function for 16-bit values. Having done some low-level SCSI work, I find that 16-bit endianness conversions are pretty common and it doesn't make too much sense to be to have an intrinsic for 32-bit endianness swapping but not 16-bit.

Well maybe their should be one.

January 19, 2006
BCS wrote:

>>> Isn't there a byte swap intrinsic function (IIRC it uses 32bit values but a x86 ASM has an XCHG op that does exactly what you are looking for, maybe this should be added to std.intrinsic)
>>
>> I use bswap from std.intrinsic for 32-bit values, but there is no corresponding function for 16-bit values. Having done some low-level SCSI work, I find that 16-bit endianness conversions are pretty common and it doesn't make too much sense to be to have an intrinsic for 32-bit endianness swapping but not 16-bit.
> 
> Well maybe their should be one.

Don't hold your breath, though...

http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.bugs/2153

--anders
January 19, 2006
Anders F Björklund wrote:
> BCS wrote:
> 
>>
>>
>> Well maybe their should be one.
> 
> 
> Don't hold your breath, though...
> 
> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.bugs/2153
> 
> --anders

x86 has it.

http://download.intel.com/design/Pentium4/manuals/25366718.pdf

look at 4.1 XCHG at about the middle of the table

IIRC the high and low bytes in a 16 bit reg can be addressed as 8 bit regs.
January 20, 2006
In article <dqos5c$av8$2@digitaldaemon.com>, BCS says...
>
>Anders F Björklund wrote:
>> BCS wrote:
>> 
>>>
>>>
>>> Well maybe their should be one.
>> 
>> 
>> Don't hold your breath, though...
>> 
>> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.bugs/2153
>> 
>> --anders
>
>x86 has it.
>
>http://download.intel.com/design/Pentium4/manuals/25366718.pdf
>
>look at 4.1 XCHG at about the middle of the table
>
>IIRC the high and low bytes in a 16 bit reg can be addressed as 8 bit regs.


yes something like the following should work:

ushort bswap(ushort val)
{
asm
{
naked;
xchg AL,AH;
ret;
}
}