[Vm-dev] how the h**l do I generate a signed shift?

Bert Freudenberg bert at freudenbergs.de
Tue Jul 1 12:29:54 UTC 2014

On 01.07.2014, at 01:27, David T. Lewis <lewis at mail.msen.com> wrote:

> On Mon, Jun 30, 2014 at 12:24:12PM -0700, Eliot Miranda wrote:
>> Hi All,
>>    I recently eliminated the optimization in Slang that replaces a
>> division by a power of two with a shift, because the code cast the argument
>> to signed, and hence broke unsigned division.  That's what used to be
>> controlled by the UseRightShiftForDivide class var of CCodeGenerator.
> <slightly OT>
> I'm just catching up with the conversation, and I see that the issue is now resolved,
> but it's worth noting that John Maloney's method comment from August 1998 is worthy
> of our appreciation :)
> CCodeGenerator class>>initialize
> 	"CCodeGenerator initialize"
> 	UseRightShiftForDivide := true.
> 		"If UseRightShiftForDivide is true, the translator will generate a right-shift when it encounters a division by a constant that is a small power of two. For example, 'x / 8' will generate '((int) x >> 3)'. The coercion to int is done to make it clear that the C compiler should generate a signed shift."
> 		"Note: The Kernighan and Ritchie 2nd Edition C manual, p. 49, leaves the semantics of right-shifting a negative number open to the discretion of the compiler implementor. However, it strongly suggests that most compilers should generate an arithmetic right shift (i.e., shifting in the sign bit), which is the same as dividing by a power of two. If your compiler does not generate or simulate an arithmetic shift, then make this class variable false and re-translate."
> </slightly OT>
> Dave

... except that even C's arithmetic right shift is NOT the same as dividing by a power of two for negative values:

-1 / 2 == 0

-1 >> 1 == -1

And C's '/' is not at all the same as Squeak's '//', as previously noted, which is why we have 'quo:'.

It's not just C, of course, and not just signed shifts. E.g. I'm having fun implementing BitBlt in JavaScript. Had this:

	mask = 0xFFFFFFFF;
	while (mask != 0) {
		mask = mask >>> bitdepth;

Here, '>>>' is a logical shift, meaning it shifts in zeroes. All values are positive. Bitdepth is 1, 2, 4, 8, 16, or 32. Still got into an endless loop. Nice, huh? And allegedly C might do the same, depending on the compiler.

- Bert -

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4142 bytes
Desc: not available
Url : http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20140701/2476b8c5/smime.bin

More information about the Vm-dev mailing list