Hi everyone, I'm smack in the middle of making some RISC-V tools in Squeak, which means I'm dealing with a lot of low-level bit manipulation. One question I have is how best to deal with two's complement representations of integers in Squeak, and how to translate between the different (positive v negative) values based on a given set of bits (or a byteArray or whatever). For example, doing the following: -1 printStringBase: 2 nDigits: 8. "11111111" Gives the expected binary value "11111111" However (and as we should expect), evaluating the following: 2r11111111. "255" Gives the (again, expected) value 255. My question is: what is the best way to convert between the complements in Squeak? How can I take 255, examine its bits, and get -1 as the response (or convert in the reverse)? I'm assuming there are already ways to deal with this, I just cannot find them. Thanks! -- Eric |
Integer readFrom: '11111111' readStream base: 2. ? Best, Karl On Tue, Jun 16, 2020 at 6:36 PM Eric Gade <[hidden email]> wrote:
|
Hi Karl,
When I evaluate this in Squeak, the Integer produced is 255 (I need to get from 255 to -1 -- and back again if possible). One hint that I've found in the image is that Integers respond to a message #highBitOfMagnitude, which gives me the value of the most significant bit in the integer. That is a starting point if I want to treat the bits in twos-complement: I can determine if the desired representation should be negative or positive. However, I'm not sure how to actually translate the bits into a matching Squeak integer with the correct sign and value. Here is a more concrete explanation of my issue: In the implementation / simulation, Register objects store their values as Squeak Integers, and they are truncated at evaluation to be 32-bit integers. Some instructions will treat a register as signed and others as unsigned. For unsigned treatment, there's no problem: Squeak always has the correct bit values for what I need. I just need to figure out what to "do" with the integer in the register when I want to treat it as signed. In the case of a value like -1 ('11111111') I can send that #highBitOfMagnitude to determine if it should be a negative or positive value, but then what? I can't just send #negative, because that gives me -255 PS - Perhaps at some point there was a #twosComplement method implemented on Integers. There is an EToys object that is currently sending the message (which has no implementors in 5.3 as far as I can see): SecurityManager >> #asn1Integer: On Tue, Jun 16, 2020 at 1:44 PM karl ramberg <[hidden email]> wrote:
-- Eric |
Try loading package TwosComplement from the SqueakMap loader, or
install it like this: Installer ss project: 'TwosComplement'; package: 'TwosComplement'; install. Then inspect these: TwosComplementRegister width: 8 value: -1. 255 asRegister: 8. "same as above but note the overflow bit is set" TwosComplementRegister width: 64 value: -1. Dave On Tue, Jun 16, 2020 at 02:09:15PM -0400, Eric Gade wrote: > Hi Karl, > > Integer readFrom: '11111111' readStream base: 2. ? > > > > When I evaluate this in Squeak, the Integer produced is 255 (I need to get > from 255 to -1 -- and back again if possible). > > One hint that I've found in the image is that Integers respond to a message > #highBitOfMagnitude, which gives me the value of the most significant bit > in the integer. That is a starting point if I want to treat the bits in > twos-complement: I can determine if the desired representation should be > negative or positive. However, I'm not sure how to actually translate the > bits into a matching Squeak integer with the correct sign and value. > > Here is a more concrete explanation of my issue: In the implementation / > simulation, Register objects store their values as Squeak Integers, and > they are truncated at evaluation to be 32-bit integers. Some instructions > will treat a register as signed and others as unsigned. For unsigned > treatment, there's no problem: Squeak always has the correct bit values for > what I need. I just need to figure out what to "do" with the integer in the > register when I want to treat it as signed. In the case of a value like -1 > ('11111111') I can send that #highBitOfMagnitude to determine if it should > be a negative or positive value, but then what? I can't just send > #negative, because that gives me -255 > > PS - Perhaps at some point there was a #twosComplement method implemented > on Integers. There is an EToys object that is currently sending the message > (which has no implementors in 5.3 as far as I can see): SecurityManager >> > #asn1Integer: > > On Tue, Jun 16, 2020 at 1:44 PM karl ramberg <[hidden email]> wrote: > > > Integer readFrom: '11111111' readStream base: 2. ? > > > > Best, > > Karl > > > > > > > > > > On Tue, Jun 16, 2020 at 6:36 PM Eric Gade <[hidden email]> wrote: > > > >> Hi everyone, > >> > >> I'm smack in the middle of making some RISC-V tools in Squeak, which > >> means I'm dealing with a lot of low-level bit manipulation. > >> > >> One question I have is how best to deal with two's complement > >> representations of integers in Squeak, and how to translate between the > >> different (positive v negative) values based on a given set of bits (or a > >> byteArray or whatever). > >> > >> For example, doing the following: > >> -1 printStringBase: 2 nDigits: 8. "11111111" > >> Gives the expected binary value "11111111" > >> > >> However (and as we should expect), evaluating the following: > >> 2r11111111. "255" > >> > >> Gives the (again, expected) value 255. > >> > >> My question is: what is the best way to convert between the complements > >> in Squeak? How can I take 255, examine its bits, and get -1 as the response > >> (or convert in the reverse)? I'm assuming there are already ways to deal > >> with this, I just cannot find them. > >> > >> Thanks! > >> > >> -- > >> Eric > >> > >> > > > > -- > Eric > |
Thanks Dave! The TwosComplementRegister is a good package and will be a helpful guide -- thanks for pointing me to it. For posterity I want to post the key functionality here (which was in #asSignedInteger). It more or less describes how to take bits (as an ordered collection of some kind) that are already in two's complement negative format and convert them to a Squeak negative Integer: asSignedInteger self negative ifTrue: [^ ((bits reversed collect: [:e | e value not]) inject: 0 into: [:val :bit | bit value ifTrue: [val << 1 + 1] ifFalse: [val << 1]]) negated - 1] ifFalse: [^ self asUnsignedInteger] Thanks again, On Tue, Jun 16, 2020 at 2:19 PM David T. Lewis <[hidden email]> wrote: Try loading package TwosComplement from the SqueakMap loader, or -- Eric |
Hi Eric, there are several simple snippets that might be useful. One simple thing to transform n bits unsigned into n bits signed value is ^self - ((self bitAt: n) bitShift: n). Transforming a signed value into an unsigned bit pattern can be obtained with a simple ^self bitAnd: AllOnesMask. where: AllOnesMask := (1 bitShift: n) - 1. Also note that #bitInvert definition assuming two complement is: ^ -1 - self Squeak assumes an infinite serie of bits. For limited register, that is: ^ -1 - self bitAnd: allOnesMask Inversely you can negate a 2 complement bit pattern thru ^1 + (self bitXor: AllOnesMask) bitAnd: AllOnesMask Of course, you cannot negate AllOneMask, case of overflow... Le mar. 16 juin 2020 à 21:40, Eric Gade <[hidden email]> a écrit :
|
Le mar. 16 juin 2020 à 23:20, Nicolas Cellier <[hidden email]> a écrit :
err, you can not negate (1 bitShift: n-1) of course...
|
Nicolas, Thanks so much for the examples. It's the (1 bitShift: n) - 1 trick that I had forgotten about (I did nand2tetris using Squeak/Pharo and I had to do some of this same stuff a a couple of years ago). These are all useful tidbits to have, both in my own work and especially for posterity here in the list. Thanks again! On Tue, Jun 16, 2020 at 5:52 PM Nicolas Cellier <[hidden email]> wrote:
-- Eric |
Free forum by Nabble | Edit this page |