[Mono-list] Concerns regarding interpreter implementation of Compare and Branching instructions w/ Floating Point values
Tom Guinther
tomguinther@hotmail.com
Sun, 20 Oct 2002 17:37:40 -0400
This is a multi-part message in MIME format.
------=_NextPart_000_008C_01C2785F.63377400
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
The other day while reading the CLI specification I became a bit =
confused regarding the exact implementation of the compare and branching =
instructions when floating point values are being evaluated. Being =
aware of, but completely uninvolved with, this project I thought it =
would be interesting to review the "mono" interpretation of the =
specification. Surprisingly I found an implementation that seems =
relatively inconsistent and somewhat bizarre in relation to my (naive?) =
interpretation of the specification. This simply leads me to wonder =
whether the spec is grossly inaccurate, my interpretation is =
off-the-wall, or the Mono implementation is lacking in =
detail/correctness in this area.
Their two fundamental issues that I wanted to bring up for discussion:
1) The proper interpretation of CGT.UN(.S) and CLT.UN(.S)
2) The overall implementation of compare and branching instructions =
w/ floating point values
Note: The answer to question #1 has little or no bearing on my =
questions related to the existing implementation of the compare and =
branching instructions w/
floating point values
Just to be explicit, my entire discussion is only related to floating =
point values and therefore I only talk about implementation of the =
instructions with regard to floating-point values and I am extracting =
implementation information from the mono/interpreter/interp.c (which I =
am assuming is not a DEAD file.)
Part 1 - The proper interpretation of CGT.UN(.S) and CLT.UN(.S):
The original question I was pondering was related to implementations of =
CGT.UN(.S) and CLT.UN(.S) where the spec uses the following type of =
wording:
"for floating-point numbers, either value1 is strictly greater than =
value2, or value1 is not ordered with respect to value2"
contrasted with the wording for the non UN version(s) which explicitly =
state the following:
"... If value1 is strictly greater than value2, ... for =
floating-point numbers, CGT returns 0 [false] if the numbers are =
unordered (that is, if one or both of the arguments are NaN)"
The explicit wording of the CGT instruction leads to me to the following =
pseudo implementation (CLT is the same, just change the > operator to < =
operator):
CGT
..., F1, F2 =3D> Int32(true=3D1 or false=3D0)
if isunordered(F1) or isunordered(F2)
result =3D false ;
else
result =3D F1 > F2 ;
Given the different "wordage" for CGT.UN I concluded that the =
following pseudo implementation was correct. If it is not correct I =
would be extremely happy to receive the correct interpretation. Also, =
the implementation of CLT.UN would be the same except for replacing the =
> operator with the < operator.
CGT.UN
..., F1, F2 =3D> Int32(true=3D1, false=3D0)
if (isunordered(F1))
result =3D false ;
else
result =3D isunordered(F2) or (F1 > F2)
Part 2: The overall implementation of compare and branching =
instructions w/ floating point values
The correct interpretation and implementation of the compare =
instructions is critical to successfully implementing the branch =
instructions. This is because the branch instructions are defined in =
terms of the compare instructions. For completeness sake I want to =
explicitly define pseudo implementation for the remaining compare =
instruction CEQ.
CEQ
..., F1, F2 =3D> Int32(true=3D1, false=3D0)
if isunordered(F1) or isunordered(F2)
result =3D false ;
else
result =3D F1 =3D=3D F2 ;
As you might expect, the Mono implementation of CEQ is as follows (and =
seems correct to me):
CEQ:
if (isnan(F1) || isnan(F2))
result =3D 0 ;
else
result =3D F1 =3D=3D F2
The Mono implementation for CGT(.S), CLT(.S), CGT.UN(.S), CLT.UN(.S) =
follows:
CGT:
CGT.S:
if (isnan(F1) || isnan(F2))
result =3D 0 ;
else
result =3D F1 > F2
CLT:
CLT.S:
if (isnan(F1) || isnan(F2))
result =3D 0 ;
else
result =3D F1 < F2
CGT.UN:
result =3D isnan(F1) || isnan(F2)
CLT.UN:
result =3D isnan(F1) || isnan(F2)
You may notice that the implementations of CGT.UN and CLT.UN are exactly =
the same and involve NO comparisons. This may be intentional, and if so, =
the CLI specification for these instructions is written very poorly. I =
don't see how the Mono implementation can be correct assuming that the =
designers would not define two opcodes that do the exact same thing and =
imply that some type of comparison is involved when it isn't. Hmmm...
Now to the branching instructions:
BEQ(.S) is defined as equivalent to:
CEQ
BRTRUE
Which is the equivalent of:
if isunordered(F1) or isunordered(F2)
branch =3D false
else
branch =3D F1 =3D=3D F2
The Mono implementation of BEQ(.S) is:
result =3D F1 =3D=3D F2
Clearly, unordered values are not taken into consideration as the =
specification requires.
BGE(.S) is defined as equivalent to:
CLT.UN
BRTRUE
Which is the equivalent of (according to my possibly errant =
interpretation):
if isunordered(F1)
branch =3D true ;
else
branch =3D !isunordered(F2) and (F1 >=3D F2)
The Mono implementation of BGE(.S) is:
result =3D F1 >=3D F2 ;
Regardless of interpretation of CLT.UN, Mono is not accounting for =
unordered values.
And so the list goes on for the branch instructions that are not of =
the .UN form. Unordered values are not properly taken into account =
(based on my understanding).
The implementation of the B??.UN(.S) instructions are generally of =
the form:
!isunordered(F1) && !isunordered(F2) and (F1 op F2)
This may not be the correct implementation (depending on correct =
interpretation of CGT.UN(.S) and CLT.UN(.S)) for:
BGT.UN(.S) and BLT.UN(.S) since there equivalency is defined in =
terms of CGT.UN(.S) and CLT.UN(.S) respectively while
BGE.UN(.S) and BLE.UN(.S) are defined in terms of CLT and CGT =
(respectively)
Apologies in advance for the long, incoherent e-mail, but any =
thoughts/answers would be much appreciated.
Tom Guinther
=20
------=_NextPart_000_008C_01C2785F.63377400
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2600.0" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>The other day while reading the CLI =
specification I=20
became a bit confused regarding the exact implementation of the compare =
and=20
branching instructions when floating point values are being =
evaluated. =20
Being aware of, but completely uninvolved with, this project I thought =
it would=20
be interesting to review the "mono" interpretation of the specification. =
Surprisingly I found an implementation that seems relatively =
inconsistent and=20
somewhat bizarre in relation to my (naive?) interpretation of the =
specification.=20
This simply leads me to wonder whether the spec is grossly inaccurate, =
my=20
interpretation is off-the-wall, or the Mono implementation is lacking in =
detail/correctness in this area.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Their two fundamental issues that =
I wanted to=20
bring up for discussion:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> 1) The proper =
interpretation of=20
CGT.UN(.S) and CLT.UN(.S)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> 2) The overall =
implementation of=20
compare and branching instructions w/ floating point values</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2> Note: The answer to =
question #1=20
has little or no bearing on my questions related to the existing =
implementation=20
of the compare and branching instructions w/</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
floating=20
point values</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Just to be explicit, my entire =
discussion is only=20
related to floating point values and therefore I only talk about =
implementation=20
of the instructions with regard to floating-point values and I am =
extracting=20
implementation information from the mono/interpreter/interp.c (which I =
am=20
assuming is not a DEAD file.)</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Part 1 - The proper interpretation of =
CGT.UN(.S)=20
and CLT.UN(.S):</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>The original question I was pondering =
was related=20
to implementations of CGT.UN(.S) and CLT.UN(.S) where the spec uses the=20
following type of wording:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> "for floating-point =
numbers,=20
either value1 is strictly greater than value2, or value1 is not ordered =
with=20
respect to value2"</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>contrasted with the wording for the non =
UN=20
version(s) which explicitly state the following:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> "... If value1 is =
strictly=20
greater than value2, ... for floating-point numbers, CGT returns 0 =
[false] if=20
the numbers are unordered (that is, if one or both of the arguments are=20
NaN)"</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>The explicit wording of the CGT =
instruction leads=20
to me to the following pseudo implementation (CLT is the same, just =
change the=20
> operator to < operator):</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2> CGT</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> ..., F1, F2 =3D>=20
Int32(true=3D1 or false=3D0)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2> if isunordered(F1) =
or=20
isunordered(F2)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D=20
false ;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> else</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D F1=20
> F2 ;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2> Given the different =
"wordage"=20
for CGT.UN I concluded that the following pseudo implementation was =
correct. If=20
it is not correct I would be extremely happy to receive the correct=20
interpretation. Also, the implementation of CLT.UN would be the same =
except for=20
replacing the > operator with the < operator.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2> CGT.UN</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> ..., F1, F2 =3D> =
Int32(true=3D1,=20
false=3D0)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2> if=20
(isunordered(F1))</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D=20
false ;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> else</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D=20
isunordered(F2) or (F1 > F2)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2> Part 2: The overall=20
implementation of compare and branching instructions w/ floating point=20
values</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2> The correct =
interpretation and=20
implementation of the compare instructions is critical to successfully=20
implementing the branch instructions. This is because the branch =
instructions=20
are defined in terms of the compare instructions. For completeness sake =
I want=20
to explicitly define pseudo implementation for the remaining compare =
instruction=20
CEQ.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>CEQ</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>..., F1, F2 =3D> Int32(true=3D1,=20
false=3D0)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>if isunordered(F1) or =
isunordered(F2)</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> result =3D false =
;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>else</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> result =3D F1 =3D=3D =
F2 ;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>As you might expect, the Mono =
implementation of CEQ=20
is as follows (<FONT face=3DArial size=3D2>and seems correct to=20
me)</FONT>:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>CEQ:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> if (isnan(F1) ||=20
isnan(F2))</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D 0=20
;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> else</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D F1=20
=3D=3D F2</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>The Mono implementation for CGT(.S), =
CLT(.S),=20
CGT.UN(.S), CLT.UN(.S) follows:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>CGT:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>CGT.S:</FONT></DIV><FONT face=3DArial =
size=3D2>
<DIV><FONT face=3DArial size=3D2> if (isnan(F1) ||=20
isnan(F2))</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D 0=20
;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> else</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D=20
F1 > F2</FONT></DIV>
<DIV> </DIV>
<DIV>CLT:</DIV>
<DIV>CLT.S:</DIV>
<DIV>
<DIV><FONT face=3DArial size=3D2> if (isnan(F1) ||=20
isnan(F2))</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D 0=20
;</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> else</FONT></DIV>
<DIV><FONT face=3DArial size=3D2> =
result =3D=20
F1 < F2</FONT></DIV></DIV>
<DIV> </DIV>
<DIV>CGT.UN:</DIV>
<DIV> result =3D isnan(F1) || isnan(F2)</DIV>
<DIV> </DIV>
<DIV>CLT.UN:</DIV>
<DIV> result =3D isnan(F1) || isnan(F2)</DIV>
<DIV> </DIV>
<DIV>You may notice that the implementations of CGT.UN and CLT.UN are =
exactly=20
the same and involve NO comparisons. This may be intentional, and if so, =
the CLI=20
specification for these instructions is written very poorly. I don't see =
how the=20
Mono implementation can be correct assuming that the designers would not =
define=20
two opcodes that do the exact same thing and imply that some type of =
comparison=20
is involved when it isn't. Hmmm...</DIV>
<DIV> </DIV>
<DIV>Now to the branching instructions:</DIV>
<DIV> BEQ(.S) is defined as equivalent to:</DIV>
<DIV> CEQ</DIV>
<DIV> BRTRUE</DIV>
<DIV> </DIV>
<DIV> Which is the equivalent of:</DIV>
<DIV> if isunordered(F1) or=20
isunordered(F2)</DIV>
<DIV> =
branch =3D=20
false</DIV>
<DIV> else</DIV>
<DIV> branch =3D =
F1 =3D=3D=20
F2</DIV>
<DIV> </DIV>
<DIV>The Mono implementation of BEQ(.S) is:</DIV>
<DIV> result =3D F1 =3D=3D F2</DIV>
<DIV> </DIV>
<DIV>Clearly, unordered values are not taken into consideration as the=20
specification requires.</DIV>
<DIV> BGE(.S) is defined as equivalent to:</DIV>
<DIV> CLT.UN</DIV>
<DIV> BRTRUE</DIV>
<DIV> </DIV>
<DIV> Which is the equivalent of (according to my =
possibly=20
errant interpretation):</DIV>
<DIV> if isunordered(F1)</DIV>
<DIV> branch =3D =
true=20
;</DIV>
<DIV> else</DIV>
<DIV> branch =3D =
!isunordered(F2) and (F1 >=3D F2)</DIV>
<DIV> </DIV>
<DIV> The Mono implementation of BGE(.S) is:</DIV>
<DIV> result =3D F1 >=3D F2 =
;</DIV>
<DIV> </DIV>
<DIV> Regardless of interpretation of CLT.UN, Mono is =
not=20
accounting for unordered values.</DIV>
<DIV> </DIV>
<DIV> And so the list goes on for the branch =
instructions that=20
are not of the .UN form. Unordered values are not properly taken into =
account=20
(based on my understanding).</DIV>
<DIV> </DIV>
<DIV> The implementation of the B??.UN(.S) =
instructions are=20
generally of the form:</DIV>
<DIV> !isunordered(F1) &&=20
!isunordered(F2) and (F1 op F2)</DIV>
<DIV> </DIV>
<DIV> This may not be the correct implementation =
(depending on=20
correct interpretation of CGT.UN(.S) and CLT.UN(.S)) for:</DIV>
<DIV> BGT.UN(.S) and =
BLT.UN(.S) since=20
there equivalency is defined in terms of CGT.UN(.S) and CLT.UN(.S) =
respectively=20
while</DIV>
<DIV> BGE.UN(.S) and BLE.UN(.S) are =
defined=20
in terms of CLT and CGT (respectively)</DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV>Apologies in advance for the long, incoherent e-mail, but any=20
thoughts/answers would be much appreciated.</DIV>
<DIV> </DIV>
<DIV>Tom Guinther</DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV> </DIV>
<DIV> </FONT></DIV></BODY></HTML>
------=_NextPart_000_008C_01C2785F.63377400--