HLA Floating Point opcodes

  • Follow


In browsing, I found this post from about 20 months ago:

"Here's what you get with HLA v1.102:
1) The behavior of the FADD();  FSUB();  FSUBR();  FMUL();  FDIV();
and FDIVR(); instructions (with no operands) has changed. Previously,
these instructions, without operands, generated opcodes for faddp,
fsubp, fsubrp, fmulp, fdivp, and fdivrp, respectively.  This behavior
is inconsistent with Intel documentation (and most other assemblers).
This has been changed in HLA v1.102 so that these instructions,
without operands, are equivalent to fadd( st1, st0 );  fsub( st1,
st0 ); fsubr( st1, st0 );  fmul( st1, st0 ); fdiv( st1, st0 ); and
fdivr( st1, st0 ); (i.e., no pop after the arithmetic operation)."

As this is completely back-to-front - the no-operand instructions
listed *should* pop the stack, in other words FADD should encode as
FADDP ST(1),ST(0) - I expected to find a followup containing a
correction, but I didn't!  The reference to being "inconsistent with
Intel documentation (and most other assemblers)" is strange, as the
Intel docs - and every other assembler I've tried - confirm that the
instructions pop the stack (despite the absence of a P suffix).

What does the current version of HLA actually do?

Richard.
http://www.rtrussell.co.uk/
To reply by email change 'news' to my forename.
0
Reply Richard 12/18/2009 8:07:20 PM

"Richard Russell" <news@MUNGED.microcosmotalk.com> wrote in message 
news:4b2be0f8$0$5100$9a6e19ea@unlimited.newshosting.com...
>
> In browsing, I found this post from about 20 months ago:
>
> "Here's what you get with HLA v1.102:
> 1) The behavior of the FADD();  FSUB();  FSUBR();  FMUL();  FDIV();
> and FDIVR(); instructions (with no operands) has changed. Previously,
> these instructions, without operands, generated opcodes for faddp,
> fsubp, fsubrp, fmulp, fdivp, and fdivrp, respectively.  This behavior
> is inconsistent with Intel documentation (and most other assemblers).
> This has been changed in HLA v1.102 so that these instructions,
> without operands, are equivalent to fadd( st1, st0 );  fsub( st1,
> st0 ); fsubr( st1, st0 );  fmul( st1, st0 ); fdiv( st1, st0 ); and
> fdivr( st1, st0 ); (i.e., no pop after the arithmetic operation)."
>
> As this is completely back-to-front - the no-operand instructions
> listed *should* pop the stack, in other words FADD should encode as
> FADDP ST(1),ST(0) - I expected to find a followup containing a
> correction, but I didn't!  The reference to being "inconsistent with
> Intel documentation (and most other assemblers)" is strange, as the
> Intel docs - and every other assembler I've tried - confirm that the
> instructions pop the stack (despite the absence of a P suffix).
>
> What does the current version of HLA actually do?
>

Well, we happen to have a laboratory under our fingertips.  Shall we conduct 
a scientific experiment to discover the answer?

A typical FPU-using program that contains the 'p' suffix for the 
instructions under question:

program GenerateSines;
#include( "stdlib.hhf" );

var
    outFile: dword;
    angle:   int32;
    r:       int32;

readonly
    RoundMode: uns16 := $23f;



begin GenerateSines;

    // Open the file:

    mov( fileio.openNew( "sines.hla" ), outFile );

    // Emit the initial part of the declaration to the output file:

    fileio.put
    (
        outFile,
        stdio.tab,
        "sines: int32[360] := " nl,
        stdio.tab, stdio.tab, stdio.tab, "[" nl );

    // Enable rounding control (round to the nearest integer).

    fldcw( RoundMode );

    // Emit the sines table:

    for( mov( 0, angle); angle < 359; inc( angle )) do

        // Convert angle in degrees to an angle in radians
        // using "radians := angle * 2.0 * pi / 360.0;"

        fild( angle );
        fld( 2.0 );
        fmulp();
        fldpi();
        fmulp();
        fld( 360.0 );
        fdivp();

        // Okay, compute the sine of ST0

        fsin();

        // Multiply by 1000 and store the rounded result into
        // the integer variable r.

        fld( 1000.0 );
        fmulp();
        fistp( r );

        // Write out the integers eight per line to the source file:
        // Note: if (angle AND %111) is zero, then angle is evenly
        // divisible by eight and we should output a newline first.

        test( %111, angle );
        if( @z ) then

            fileio.put
            (
                outFile,
                nl,
                stdio.tab,
                stdio.tab,
                stdio.tab,
                stdio.tab,
                r:5,
                ','
            );

        else

            fileio.put( outFile, r:5, ',' );

        endif;

    endfor;

    // Output sine(359) as a special case (no comma following it).
    // Note: this value was computed manually with a calculator.

    fileio.put
    (
        outFile,
        "  -17",
        nl,
        stdio.tab,
        stdio.tab,
        stdio.tab,
        "];",
        nl
    );
    fileio.close( outFile );

end GenerateSines;

The output of said program:

 sines: int32[360] :=
   [

        0,   17,   35,   52,   70,   87,  105,  122,
      139,  156,  174,  191,  208,  225,  242,  259,
      276,  292,  309,  326,  342,  358,  375,  391,
      407,  423,  438,  454,  469,  485,  500,  515,
      530,  545,  559,  574,  588,  602,  616,  629,
      643,  656,  669,  682,  695,  707,  719,  731,
      743,  755,  766,  777,  788,  799,  809,  819,
      829,  839,  848,  857,  866,  875,  883,  891,
      899,  906,  914,  921,  927,  934,  940,  946,
      951,  956,  961,  966,  970,  974,  978,  982,
      985,  988,  990,  993,  995,  996,  998,  999,
      999, 1000, 1000, 1000,  999,  999,  998,  996,
      995,  993,  990,  988,  985,  982,  978,  974,
      970,  966,  961,  956,  951,  946,  940,  934,
      927,  921,  914,  906,  899,  891,  883,  875,
      866,  857,  848,  839,  829,  819,  809,  799,
      788,  777,  766,  755,  743,  731,  719,  707,
      695,  682,  669,  656,  643,  629,  616,  602,
      588,  574,  559,  545,  530,  515,  500,  485,
      469,  454,  438,  423,  407,  391,  375,  358,
      342,  326,  309,  292,  276,  259,  242,  225,
      208,  191,  174,  156,  139,  122,  105,   87,
       70,   52,   35,   17,    0,  -17,  -35,  -52,
      -70,  -87, -105, -122, -139, -156, -174, -191,
     -208, -225, -242, -259, -276, -292, -309, -326,
     -342, -358, -375, -391, -407, -423, -438, -454,
     -469, -485, -500, -515, -530, -545, -559, -574,
     -588, -602, -616, -629, -643, -656, -669, -682,
     -695, -707, -719, -731, -743, -755, -766, -777,
     -788, -799, -809, -819, -829, -839, -848, -857,
     -866, -875, -883, -891, -899, -906, -914, -921,
     -927, -934, -940, -946, -951, -956, -961, -966,
     -970, -974, -978, -982, -985, -988, -990, -993,
     -995, -996, -998, -999, -999,-1000,-1000,-1000,
     -999, -999, -998, -996, -995, -993, -990, -988,
     -985, -982, -978, -974, -970, -966, -961, -956,
     -951, -946, -940, -934, -927, -921, -914, -906,
     -899, -891, -883, -875, -866, -857, -848, -839,
     -829, -819, -809, -799, -788, -777, -766, -755,
     -743, -731, -719, -707, -695, -682, -669, -656,
     -643, -629, -616, -602, -588, -574, -559, -545,
     -530, -515, -500, -485, -469, -454, -438, -423,
     -407, -391, -375, -358, -342, -326, -309, -292,
     -276, -259, -242, -225, -208, -191, -174, -156,
     -139, -122, -105,  -87,  -70,  -52,  -35,  -17
   ];


Here is a version of the above program with the 'p' suffix removed:

program GenerateSinesSansPee;
#include( "stdlib.hhf" );

var
    outFile: dword;
    angle:   int32;
    r:       int32;

readonly
    RoundMode: uns16 := $23f;



begin GenerateSinesSansPee;

    // Open the file:

    mov( fileio.openNew( "sinesSansPee.hla" ), outFile );

    // Emit the initial part of the declaration to the output file:

    fileio.put
    (
        outFile,
        stdio.tab,
        "sines: int32[360] := " nl,
        stdio.tab, stdio.tab, stdio.tab, "[" nl );

    // Enable rounding control (round to the nearest integer).

    fldcw( RoundMode );

    // Emit the sines table:

    for( mov( 0, angle); angle < 359; inc( angle )) do

        // Convert angle in degrees to an angle in radians
        // using "radians := angle * 2.0 * pi / 360.0;"

        fild( angle );
        fld( 2.0 );
        fmul();
        fldpi();
        fmul();
        fld( 360.0 );
        fdiv();

        // Okay, compute the sine of ST0

        fsin();

        // Multiply by 1000 and store the rounded result into
        // the integer variable r.

        fld( 1000.0 );
        fmul();
        fist( r );

        // Write out the integers eight per line to the source file:
        // Note: if (angle AND %111) is zero, then angle is evenly
        // divisible by eight and we should output a newline first.

        test( %111, angle );
        if( @z ) then

            fileio.put
            (
                outFile,
                nl,
                stdio.tab,
                stdio.tab,
                stdio.tab,
                stdio.tab,
                r:5,
                ','
            );

        else

            fileio.put( outFile, r:5, ',' );

        endif;

    endfor;

    // Output sine(359) as a special case (no comma following it).
    // Note: this value was computed manually with a calculator.

    fileio.put
    (
        outFile,
        "  -17",
        nl,
        stdio.tab,
        stdio.tab,
        stdio.tab,
        "];",
        nl
    );
    fileio.close( outFile );

end GenerateSinesSansPee;

Here is the output of this second version of the program:

 sines: int32[360] :=
   [

    
1000,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,
   
-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,-2147483648,

  -17
   ];

Does this answer your question?

Nathan.


0
Reply Nathan 12/18/2009 8:46:17 PM


"Richard Russell" <news@MUNGED.microcosmotalk.com> wrote in message 
news:4b2be0f8$0$5100$9a6e19ea@unlimited.newshosting.com...
>
> In browsing, I found this post from about 20 months ago:
>
> "Here's what you get with HLA v1.102:
> 1) The behavior of the FADD();  FSUB();  FSUBR();  FMUL();  FDIV();
> and FDIVR(); instructions (with no operands) has changed. Previously,
> these instructions, without operands, generated opcodes for faddp,
> fsubp, fsubrp, fmulp, fdivp, and fdivrp, respectively.  This behavior
> is inconsistent with Intel documentation (and most other assemblers).
> This has been changed in HLA v1.102 so that these instructions,
> without operands, are equivalent to fadd( st1, st0 );  fsub( st1,
> st0 ); fsubr( st1, st0 );  fmul( st1, st0 ); fdiv( st1, st0 ); and
> fdivr( st1, st0 ); (i.e., no pop after the arithmetic operation)."
>

New documentation reflecting the new behavior *should* be available at this 
site:
http://homepage.mac.com/randyhyde/webster.cs.ucr.edu/index.html

However, if you want to keep using the old "Art of Assembly Programming" 
book (and various associated documents, examples), then here is an include 
file I wrote to allow you to continue writing your code the old way:

,---
|  fpumacs.hhf
,---
//  Macros to be used with HLA versions 1.102 and later
//  so these FPU instructions match the behavior
//  described in existing AoA and HLA Ref. material.
//  March 27, 2008

#id( fadd )
#macro fadd( _args_[] );

  #if( @elements( _args_ ) = 0 )

    faddp()

  #elseif( @elements( _args_ ) = 1 )

    ~fadd( @text( _args_[0] ) )

  #elseif( @elements( _args_ ) = 2 )

    ~fadd( @text( _args_[0]), @text( _args_[1] ))

  #else

    #error( "Illegal # of arguments to fadd" )

  #endif

#endmacro

#id( fsub )
#macro fsub( _args_[] );

  #if( @elements( _args_ ) = 0 )

    fsubp()

  #elseif( @elements( _args_ ) = 1 )

    ~fsub( @text( _args_[0] ) )

  #elseif( @elements( _args_ ) = 2 )

    ~fsub( @text( _args_[0]), @text( _args_[1] ))

  #else

    #error( "Illegal # of arguments to fsub" )

  #endif

#endmacro

#id( fsubr )
#macro fsubr( _args_[] );

  #if( @elements( _args_ ) = 0 )

    fsubrp()

  #elseif( @elements( _args_ ) = 1 )

    ~fsubr( @text( _args_[0] ) )

  #elseif( @elements( _args_ ) = 2 )

    ~fsubr( @text( _args_[0]), @text( _args_[1] ))

  #else

    #error( "Illegal # of arguments to fsubr" )

  #endif

#endmacro

#id( fmul )
#macro fmul( _args_[] );

  #if( @elements( _args_ ) = 0 )

    fmulp()

  #elseif( @elements( _args_ ) = 1 )

    ~fmul( @text( _args_[0] ) )

  #elseif( @elements( _args_ ) = 2 )

    ~fmul( @text( _args_[0]), @text( _args_[1] ))

  #else

    #error( "Illegal # of arguments to fmul" )

  #endif

#endmacro

#id( fdiv )
#macro fdiv( _args_[] );

  #if( @elements( _args_ ) = 0 )

    fdivp()

  #elseif( @elements( _args_ ) = 1 )

    ~fdiv( @text( _args_[0] ) )

  #elseif( @elements( _args_ ) = 2 )

    ~fdiv( @text( _args_[0]), @text( _args_[1] ))

  #else

    #error( "Illegal # of arguments to fdiv" )

  #endif

#endmacro

#id( fdivr )
#macro fdivr( _args_[] );

  #if( @elements( _args_ ) = 0 )

    fdivrp()

  #elseif( @elements( _args_ ) = 1 )

    ~fdivr( @text( _args_[0] ) )

  #elseif( @elements( _args_ ) = 2 )

    ~fdivr( @text( _args_[0]), @text( _args_[1] ))

  #else

    #error( "Illegal # of arguments to fdivr" )

  #endif

#endmacro

`---

Hope this helps.

Nathan.


0
Reply Nathan 12/18/2009 9:05:21 PM

On 18 Dec, 21:05, "Nathan Baker" wrote:
> Hope this helps.

I'm not sure to what extent it "helps".  It seems to confirm that,
sometime in 2008, HLA was changed from assembling the no-operand forms
of 'fadd, 'fmul' etc *correctly* (popping the stack) to assembling
them *incorrectly* (not popping the stack).

I'm not really interested in workarounds for this, but in why such a
decision was taken in the first place and why it wasn't immediately
spotted and corrected when the beta version was released.

Here is one of many places where the correct functionality is
described (and a particularly trustworthy one!):

http://software.intel.com/en-us/forums/watercooler-catchall/topic/48290/

Richard.
http://www.rtrussell.co.uk/
To reply by email change 'news' to my forename.
0
Reply Richard 12/18/2009 11:52:46 PM

"Richard Russell" <news@MUNGED.microcosmotalk.com> wrote in message 
news:4b2c15ce$0$5099$9a6e19ea@unlimited.newshosting.com...
>
> Here is one of many places where the correct functionality is
> described (and a particularly trustworthy one!):
>
> http://software.intel.com/en-us/forums/watercooler-catchall/topic/48290/
>

The way I see it, Intel is only responsible for the machine language that 
its CPUs will execute.  The author of an assembly language has complete 
freedom to match chosen mnemonics to those machine opcodes per his/her own 
design goals.  Microsoft certainly deviated from Intel's suggestions with 
several of the mnemonic/opcode mappings supported by MASM.  Herbert 
Kleebauer {sometimes found lurking in A.L.A which I've added to this 
thread }chose an entirely different mnemonic syntax { heavily enfluenced by 
Motorola 68000 and the like }for the entire instruction list supported by 
his Daniela/Windela/Lindela assembler.  I could easily keep going, but I'm 
sure you get the point.  If a programmer wants to whine about those 
choices -- that is the programmer's problem.

If you are truly interested in Randy's design decisions regarding HLA, then 
I suggest that you take the time to ask him.

Nathan.


0
Reply Nathan 12/19/2009 1:48:56 AM

On 18 Dec, 23:52, Richard Russell <n...@MUNGED.microcosmotalk.com>
wrote:
> On 18 Dec, 21:05, "Nathan Baker" wrote:
>
> > Hope this helps.
>
> I'm not sure to what extent it "helps". =A0It seems to confirm that,
> sometime in 2008, HLA was changed from assembling the no-operand forms
> of 'fadd, 'fmul' etc *correctly* (popping the stack) to assembling
> them *incorrectly* (not popping the stack).

I don't use it but perhaps HLA is a *language* which is based on
assembler rather than an assembler per se. For example, the manual
states, "Note that HLA does not support the entire FPU instruction
set.  If you absolutely need the few remaining instructions, use the
#ASM..#ENDASM or #EMIT directives to generate them." So there must be
something like a real assembler back end.

>
> I'm not really interested in workarounds for this, but in why such a
> decision was taken in the first place and why it wasn't immediately
> spotted and corrected when the beta version was released.

Why don't you ask Randall? It was his choice after all.

> Here is one of many places where the correct functionality is
> described (and a particularly trustworthy one!):
>
> http://software.intel.com/en-us/forums/watercooler-catchall/topic/48290/

Here's some notes from a bit of digging.

In the 80387 manual the mnemonic fadd with no operands was explicitly
listed in an example but the manual was somewhat vague in the
instruction definition.

By the time of the Pentium 1 the instruction was listed as faddp. No
zero-operand version on fadd was listed in the instruction
documentation. Instead it lists only faddp as operand-less. But the
manual does state (sect 6.3.1) that fadd "may be written without
operands...."

A later manual (Pentium Pro, I think) adds the comment, "In some
assemblers, the
mnemonic for this instruction is FADD rather than FADDP."

It seems Intel has been gradually moving itself away from fadd to
faddp. All of which is moot as you are asking about HLA but it is here
as some background in case I or anyone else refer back to this post.

James
0
Reply James 12/19/2009 2:49:42 AM

On 19 Dec, 01:48, "Nathan Baker" wrote:
> The way I see it, Intel is only responsible for the machine language
> that its CPUs will execute.  The author of an assembly language has
> complete freedom to match chosen mnemonics to those machine opcodes
> per his/her own design goals

On 19 Dec, 02:49, James Harris wrote:
> I don't use it but perhaps HLA is a *language* which is based on
> assembler rather than an assembler per se. For example, the manual
> states, "Note that HLA does not support the entire FPU instruction
> set.

I accept those points entirely, but if you reread the original post
you'll see that the justification given for the change was "This
[original] behavior is inconsistent with Intel documentation (and most
other assemblers)".

So Randy was quite explicitly stating that the change was to *improve*
compatibility with the Intel docs and other assemblers, when in fact
the effect was the exact opposite.

Maybe he'll pop up here to explain.

Richard.
http://www.rtrussell.co.uk/
To reply by email change 'news' to my forename.

0
Reply Richard 12/19/2009 12:49:09 PM

6 Replies
123 Views

(page loaded in 0.083 seconds)

Similiar Articles:






7/25/2012 12:18:32 AM


Reply: