This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

__fmax() __fmin() intrinsics in CGTools 5.2.10

Hi everyone,

I am having troubles with __fmax() and __fmin() intrinsics. I found while browsing the forum that they should be available since CGTools 5.2.2 so I expected I would have these with my CGTools 5.2.10. The source file is compiling well, so the declaration and definition are included in the cl2000 5.2.10 but when I inspect the generated assembly, I don't see any call to instruction MAXF32 that I was expecting to see.

I tested assembly code generation for __f32_max_idx() and it looks way better, but it costs some MOV for indexes and float => double conversions.

Could someone confirm that __fmax() __fmin() intrinsics have empty implementation on CGTools 5.2.10 ?

  • These intrinsics should work with 5.2.10. Are you sure you are compiling with --float_support=fpu32?
    I was able to generate the MINF32 instruction for the __fmin() intrinsic with a simple example. Can you attach an example that does not work for you including the compile options being used?

  • Sure, I made this quick example which has the same behavior as I have on my project.


    #include <math.h>
    int main(void)
    {
        float a = 0.0, b = 1.0;
        double c = 0.0, d = 1.0, idx_c = 10, idx_d = 11;

        __fmax(a, b);
        __f32_max_idx(c, d, idx_c, idx_d);
    }


    Which gives me the following assembly
            ZERO      R0H                   ; |4|
            MOV32     *-SP[2],R0H
            MOVIZ     R0H,#16256            ; |4|
            MOV32     *-SP[4],R0H
            ZERO      R0H                   ; |5|
            MOV32     *-SP[6],R0H
            MOVIZ     R0H,#16256            ; |5|
            MOV32     *-SP[8],R0H
            MOVIZ     R0H,#16672            ; |5|
            MOV32     *-SP[10],R0H
            MOVIZ     R0H,#16688            ; |5|
            MOV32     *-SP[12],R0H
            MOV32     R1H,*-SP[10]
            MOV32     R3H,*-SP[8]
            MOV32     R0H,*-SP[6]
            MOV32     R2H,*-SP[12]
            MAXF32    R0H,R3H
           || MOV32  R1H,R2H               ; |8|
            MOV32     *-SP[10],R1H
            MOV32     *-SP[6],R0H
            MOVB      AL,#0
            SUBB      SP,#12
            LRETR

    I only see the assembly code for the __f32_max_idx intrinsic. Line 7 is totally skipped.

    Build options : -g -k -pdsw225 -fr"$(Proj_dir)\Debug" -d"_DEBUG" -d"LARGE_MODEL" -ml -v28 --float_support=fpu32

  • You need to be careful in devising test code for such things, because the compiler may optimize the generated assembly code.  For example, if the statement __fmax(a,b); doesn't require the contents of a or b to be modified, then the compiler can choose not to emit any corresponding assembly code.

  • You got a point. I simplified a lot in my example, maybe too much. To avoid pre-processing optimisation, I added some "weird" randomization of a and b which should be resolved at link time only. I expect that the compiler preprocessor will not be able to optimize the assembly code based on static analysis.


    #include <math.h>
    int main(void)
    {
        float a = 0.0, b = 1.0;
        double c = 0.0, d = 1.0, idx_c = 10, idx_d = 11;

        a = (float) (unsigned long int) &a; // weird randomization of a
        b = (float) (unsigned long int) &b; // weird randomization of b
        __fmax(a, b);
        __f32_max_idx(c, d, idx_c, idx_d);
    }


    Still I only have the assembly code for __f32_max_idx() line 10, but nothing for __fmax() line 9.

            ZERO      R0H                   ; |4|
            MOV32     *-SP[2],R0H
            MOVIZ     R0H,#16256            ; |4|
            MOV32     *-SP[4],R0H
            ZERO      R0H                   ; |5|
            MOV32     *-SP[6],R0H
            MOVIZ     R0H,#16256            ; |5|
            MOV32     *-SP[8],R0H
            MOVIZ     R0H,#16672            ; |5|
            MOV32     *-SP[10],R0H
            MOVIZ     R0H,#16688            ; |5|
            MOV32     *-SP[12],R0H
            MOVZ      AR4,SP                ; |7|
            SUBB      XAR4,#2               ; |7|
            MOV32     R0H,XAR4
            NOP
            NOP
            NOP
            NOP
            UI32TOF32 R0H,R0H               ; |7|
            NOP
            MOV32     *-SP[2],R0H
            MOVZ      AR4,SP                ; |8|
            SUBB      XAR4,#4               ; |8|
            MOV32     R0H,XAR4
            NOP
            NOP
            NOP
            NOP
            UI32TOF32 R0H,R0H               ; |8|
            NOP
            MOV32     *-SP[4],R0H
            MOV32     R1H,*-SP[10]
            MOV32     R3H,*-SP[8]
            MOV32     R0H,*-SP[6]
            MOV32     R2H,*-SP[12]
            MAXF32    R0H,R3H
           || MOV32  R1H,R2H               ; |10|
            MOV32     *-SP[10],R1H
            MOV32     *-SP[6],R0H
            MOVB      AL,#0
            SUBB      SP,#12
            LRETR

  • I finally found the solution, thank you to those who tried to help me :)

    The __fmin(), __fmax() were not documented in my spru514c for v5.x.x Compiler. But as I knew that MAXF32 and MINF32 assembly instruction exist, I found the name of the intrinsic functions in the forum and assumed that the prototype were made in the same thought of __f32_max_idx() and __f32_min_idx)  with argument thrown by adress... which is not the case. The result is not passed through argument like the 2 documented function, it is returned by function return code.

    So my code was all biased and it should have been :

    a = __fmax(a, b); // prototype is float __fmax(float x, float y). It is not int __fmax(float &dst, float &src)