• Using Log_Float in inline assembler for ARM

    From Ahlan Marriott@21:1/5 to All on Sun Nov 19 04:22:20 2023
    Hi,
    The following procedure Unbiased_Rounding for Float works as expected.

    function Unbiased_Rounding (X : Float) return Float is
    Y : Float;
    begin
    Asm ("vrintn.f32 %0,%1",
    Outputs => Float'asm_output ("=t", Y),
    Inputs => Float'asm_input ("t", X));
    return Y;
    end Unbiased_Rounding;

    according to https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
    the constraint t means "VFP floating-point registers s0-s31. Used for 32 bit values” and the constraint w means "VFP floating-point registers d0-d31 and the appropriate subset d0-d15 based on command line options. Used for 64 bit values only”

    therefore we wrote our long_float version as

    function Unbiased_Rounding (X : Long_Float) return Long_Float is
    Y : Long_Float;
    begin
    Asm ("vrintn.f64 %0,%1",
    Outputs => Long_Float'asm_output ("=w", Y),
    Inputs => Long_Float'asm_input ("w", X));
    return Y;
    end Unbiased_Rounding;

    however this fails to compile.
    GNAT 11.2/0-4 (Alire) complains
    Error: invalid instruction shape -- `vrintn.f64 s14,s14’

    presumably because the operands are S registers rather than double precisions D registers.
    Is this a bug or have we misunderstood something?

    Best wishes,
    Ahlan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ahlan Marriott@21:1/5 to Ahlan Marriott on Fri Nov 24 01:09:38 2023
    On Sunday, November 19, 2023 at 1:22:22 PM UTC+1, Ahlan Marriott wrote:
    Hi,
    The following procedure Unbiased_Rounding for Float works as expected.

    function Unbiased_Rounding (X : Float) return Float is
    Y : Float;
    begin
    Asm ("vrintn.f32 %0,%1",
    Outputs => Float'asm_output ("=t", Y),
    Inputs => Float'asm_input ("t", X));
    return Y;
    end Unbiased_Rounding;

    according to https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
    the constraint t means "VFP floating-point registers s0-s31. Used for 32 bit values” and the constraint w means "VFP floating-point registers d0-d31 and the appropriate subset d0-d15 based on command line options. Used for 64 bit values only”

    therefore we wrote our long_float version as

    function Unbiased_Rounding (X : Long_Float) return Long_Float is
    Y : Long_Float;
    begin
    Asm ("vrintn.f64 %0,%1",
    Outputs => Long_Float'asm_output ("=w", Y),
    Inputs => Long_Float'asm_input ("w", X));
    return Y;
    end Unbiased_Rounding;

    however this fails to compile.
    GNAT 11.2/0-4 (Alire) complains
    Error: invalid instruction shape -- `vrintn.f64 s14,s14’

    presumably because the operands are S registers rather than double precisions D registers.
    Is this a bug or have we misunderstood something?

    Best wishes,
    Ahlan

    The solution is to use %P to access the parameters constrained using “w” Try as I might I can’t find this wonderful secret documented anywhere.
    I stumbled on the solution in the NXP forum where jingpan replied to a question on how to use the ARM VSQRT instruction for double.
    When using the inline assembler from C and using named parameters you need to access parameters constrained by “w”, ie D registers using %P[name] rather than %[name] as everywhere else.
    Using positional parameters one needs to use %Pn rather than %n
    And yes it must be a capital P
    I fail to understand why one needs to do this because surely the assembler already knows that the parameter has been constrained to a D register - but I guess this is just an additional quirk to an already very quirky assembler.
    My GNAT Ada code to implement the Unbiased_Rounding attribute efficiently using the VFLOATN instruction is therefore

    subtype T is Long_Float;

    function Unbiased_Rounding (X : T) return T is
    Y : T;
    begin
    Asm (“vrintn.f64 %P0,%P1”,
    Outputs => T’asm_output (“=w”, Y),
    Inputs => T’asm_input (“w”, X));
    return Y;
    end Unbiased_Rounding;

    Of course we wouldn’t have to resort to assembler at all had there been a built-in intrinsic for VFLOATN as there is for all the other VFLOAT instructions. But I guess that is hoping for too much.

    Best wishes and happy programming,
    Ahlan

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Ahlan Marriott on Fri Nov 24 11:43:28 2023
    On 2023-11-24 10:09, Ahlan Marriott wrote:

    subtype T is Long_Float;

    function Unbiased_Rounding (X : T) return T is
    Y : T;
    begin
    Asm (“vrintn.f64 %P0,%P1”,
    Outputs => T’asm_output (“=w”, Y),
    Inputs => T’asm_input (“w”, X));
    return Y;
    end Unbiased_Rounding;

    What do you get from T'Unbiased_Rounding?

    --
    Jeff Carter
    "In the frozen land of Nador they were forced to
    eat Robin's minstrels, and there was much rejoicing."
    Monty Python & the Holy Grail
    70

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)