- Floating point numbers are represented as sign+magnitude rather than the two's complement used for integers.The details are a bit messy but basically, the 32 bits in a float are divided as S-EEEEEEEE-MMMMMMMMMMMMMMMMMMMMMMMwhere S is the sign, 0 for positive, 1 for negative, EE...EE is an 8 bit exponent, and MM...MM is a 23 bit magnitude(see note 1)One characteristic of this representation is that if one or both of the numbers is positive, you can do a standard 32 bit integer compare and trust the result. If BOTH of the numbers are negative, you can still do an integer compare but you have to reverse the operands.The assembly code for the 32 bit integer and float compares is below. A float compare is almost 70 bytes total because of repeating the integer compare with the operands reversed. The challenge is to reduce this. Execution time is less significant, you could use registers 14 or 15 if you needed them. Bonus points if the reduction improves the 32 bit integer compare. I already have special cases for equal/not equal and zero compares but if there any other special cases that would be good.Sample positive and negative floats are one=0x3f800000, minus one is 0xbf800000. You can see that the two are the same except for the sign bit and if you did a signed integer compare you'd get a correct result.(because outlook seems to mungle my email sometimes I've attached the code as well as including it in the email)To do a 32 bit integer compare for a jump-if-A-less-than-B, the code is about 28 bytes long(here A is in R8:R9 and B is in R10:R11;signed comparison(less than) of two long integers - subtract R10:R11 from R8:R9 and jump if borrowdec sp ;make a work areaglo 11 ;lowest order bytestr spglo 9smghi 11str spghi 9smb ;that's a standard signed subtraction of one regglo 10 ;lowest order byte of the top registerstr spglo 8smbghi 10str spghi 8smb ;that's a standard signed subtraction of a double registerghi 8 ;xor ;sets the top bit if the signs are differentinc sp ;release the work areashlc ;the original df is now in bit 0 and df=1 if signs were differentlsnf ;bypass the flip if signs were the samexri 01 ;invert original df if signs were differentshrc ;put it back in dfLBNF label ;executeTo do a float comparison, I have to check the signs before comparing and, if both are negative, reverse the operands.;jump if float reg R8:R9< float reg R10:R11ghi rR8 ;see if first arg is -vshllbnf $$comp ;if at least 1 reg positive, just compareghi R10 ;check 2nd regshllbdf $$rcomp$$comp: jltI4 R8:R9,R10:R11,label ;as long as one register is +vlbr $$done$$rcomp: jltI4 R10:R11,R8:R9,label ;reverse the order of the operands$$done:(note 1) floats are "normalized" by shifting the magnitude left until bit 23 is 1 and adjusting the exponent then, since bit 23 is always 1, it's stripped off and used to hold one of the exponent bits. The exponent is carried as excess 127 i.e. 2^0 is carried as 127 and 2^-1 is carried as 126. See https://en.wikipedia.org/wiki/Floating_point#Internal_representation
- Ok, here is my 1st entry in the inaugural assembly language challenge. I've attached the code rather than laying it out in the email.Both the float compare and the underlying 32 bit integer subtractions behave differently depending on the signs of the operands. It occurred to me that if the signs are different I don't have to actually do the compare because one is clearly less than the other! I moved the sign tests all to the front of the code which let me take them out of the subtractions.The new routine is 59 bytes instead of 69 and, for random input, it should be noticeably quicker since the signs are checked early. It has the effect of introducing some more branching around but there you go.I was thinking of some way of reversing the subtraction using the sd and sdb instructions but i haven't worked that through.To: cosmacelf@yahoogroups.com; bill.rowe.ottawa@...

From: bill_rowe_ottawa@...

Date: Thu, 9 May 2013 21:04:37 -0400

Subject: RE: [cosmacelf] Assembly language Challenge - Sign/Magnitude Compares - Clarification [2 Attachments]

[Attachment(s) from bill rowe included below]Charles pointed out a couple of issues: there's a typo where i wrote rR8 instead of R8 and i used the term jlti4 to mean the 32 bit compare without explaining what I was doing.I redid the code in the attachment actually duplicating the 32 bit compare so you can see the whole messy glory. The .lst file was assembled with the excellent AS assembler by Alfred Arnold:

To: cosmacelf@yahoogroups.com; bill_rowe_ottawa@...; bill.rowe.ottawa@...

From: bill_rowe_ottawa@...

Date: Thu, 9 May 2013 11:42:58 -0400

Subject: [cosmacelf] Assembly language Challenge - Sign/Magnitude Compares [1 Attachment]

[Attachment(s) from bill rowe included below]Floating point numbers are represented as sign+magnitude rather than the two's complement used for integers.The details are a bit messy but basically, the 32 bits in a float are divided as S-EEEEEEEE-MMMMMMMMMMMMMMMMMMMMMMMwhere S is the sign, 0 for positive, 1 for negative, EE...EE is an 8 bit exponent, and MM...MM is a 23 bit magnitude(see note 1)One characteristic of this representation is that if one or both of the numbers is positive, you can do a standard 32 bit integer compare and trust the result. If BOTH of the numbers are negative, you can still do an integer compare but you have to reverse the operands.The assembly code for the 32 bit integer and float compares is below. A float compare is almost 70 bytes total because of repeating the integer compare with the operands reversed. The challenge is to reduce this. Execution time is less significant, you could use registers 14 or 15 if you needed them. Bonus points if the reduction improves the 32 bit integer compare. I already have special cases for equal/not equal and zero compares but if there any other special cases that would be good.Sample positive and negative floats are one=0x3f800000, minus one is 0xbf800000. You can see that the two are the same except for the sign bit and if you did a signed integer compare you'd get a correct result.(because outlook seems to mungle my email sometimes I've attached the code as well as including it in the email)To do a 32 bit integer compare for a jump-if-A-less-than-B, the code is about 28 bytes long(here A is in R8:R9 and B is in R10:R11;signed comparison(less than) of two long integers - subtract R10:R11 from R8:R9 and jump if borrowdec sp ;make a work areaglo 11 ;lowest order bytestr spglo 9smghi 11str spghi 9smb ;that's a standard signed subtraction of one regglo 10 ;lowest order byte of the top registerstr spglo 8smbghi 10str spghi 8smb ;that's a standard signed subtraction of a double registerghi 8 ;xor ;sets the top bit if the signs are differentinc sp ;release the work areashlc ;the original df is now in bit 0 and df=1 if signs were differentlsnf ;bypass the flip if signs were the samexri 01 ;invert original df if signs were differentshrc ;put it back in dfLBNF label ;executeTo do a float comparison, I have to check the signs before comparing and, if both are negative, reverse the operands.;jump if float reg R8:R9< float reg R10:R11ghi rR8 ;see if first arg is -vshllbnf $$comp ;if at least 1 reg positive, just compareghi R10 ;check 2nd regshllbdf $$rcomp$$comp: jltI4 R8:R9,R10:R11,label ;as long as one register is +vlbr $$done$$rcomp: jltI4 R10:R11,R8:R9,label ;reverse the order of the operands$$done:(note 1) floats are "normalized" by shifting the magnitude left until bit 23 is 1 and adjusting the exponent then, since bit 23 is always 1, it's stripped off and used to hold one of the exponent bits. The exponent is carried as excess 127 i.e. 2^0 is carried as 127 and 2^-1 is carried as 126. See https://en.wikipedia.org/wiki/Floating_point#Internal_representation