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.

CCS/MSP430FG4618: How safe is the -mhwmult=auto option?

Part Number: MSP430FG4618

Tool/software: Code Composer Studio

I've been looking at migrating my build definitions from an explicit HW multiplier option (-mhwmult=16bit etc), to the more generic -mhwmult=auto option. This leaves one less thing to remember when I change processors (or at least that's the theory!).

The specific code I've been playing with generates a static library, with the final executables linking against this. Initially both the project that builds the library, and the project that uses this and builds the executable, were using the auto option for the hardware multiplier. This immediately generates issues with undefined __mulhi2 symbols during the link (interestingly nothing in the code is explicitly using the hardware multiplier, but maybe one of the libraries is - the error refers back to a timer interrupt ISR within the static library code). The only way I've found round this is to explicitly set the hardware multiplier to 16bit in the project that builds the executable (this is for a 4618). Leaving the hardware multiplier at auto in the project that builds the library doesn't seem to cause any problems.

I'd like something like nm to have a poke around inside my static library, as the __mulhi2 reference is coming from some logic inside that, but haven't found one that works on Windows yet. However, it appears that the compiler stage is generating the reference to __mulhi2 correctly, but the linker stage is failing to include the correct library to resolve this, unless the multiplier is explicitly set to 16bit. 

Are there any issues using the auto option, or am I missing something? 

Thanks and regards

Andrew

  • I can shed some light, though I cannot answer everything.

    The option -mhwmult=auto is automatic in only a limited sense.  It means, during the current build, the compiler looks to the setting of the -mmcu option to know what kind of HW multiply to use.  A library built with -mhwmult=auto cannot change after that build.  It always uses the HW multiply variant specified by the -mmcu option during the build of the library.

    For a library that must work on a wide range of MSP430 devices, it probably has to be built with -mhwmult=none.  That gives up the possibility of library code using whatever HW multiply feature is available.  But it avoids having a different library for each HW multiply variant.  I'm not certain on this point.  So I'll ask an expert to comment.

    Thanks and regards,

    -George

  • Hi George,

    I can understand your comments about the multiplier option being effectively hard-coded into the library, and also the advisability of using the "none" option unless you explicitly need hardware multiplier support (and are cognizant of the device selection complexities that result).

    In my case, I'm not using the hardware multiplier at all (it was a bit of a surprise that this reference ended up in my library from what appears to be an ISR declaration). So in reality, I have no reason not to use the "none" option, and that's probably sensible.

    But the question remains. I would assume that if I use the "auto" option, CCS would determine that (in my case) "16bit" was the valid hardware multiplier setting, and would continue on as if I had explicitly selected "16bit". That is, I would expect that "auto" and "16bit" would behave exactly the same. But they don't! In the "16bit" case CCS appears to be including the libmul_16.a library (where __mulhi2 is defined) in the link, in the "auto" case it isn't.

    So, I'll just take your advice, revert to the "none" option where I have no need for multiplier support, and assign this to the curio department.

    Regards

    Andrew

  • Hi,

    George covered -mhwmult=auto so I'm going to just give some other background on how you should go about configuring your project.

    The code generated by the GCC compiler itself is not influenced too much by the -mhwmult= option. The only things this option changes in the compiler are:

    • The decision about inlining some hardware multiply operations (instead of using the library function) at -O3
    • Transformation of generic libgcc library function names to mspabi function names.

    I think the behaviour of the latter is actually a little confusing. When there is no hardware multiply support (-mhwmult=none) we always emit "__mspabi_mpy*" function names. If there is hardware multiply support we keep the generic libgcc function names (__mul{hi,si}*), and append a suffix, depending on whether the hardware multiply support is:

    • 16-bit (no suffix is added)
    • 32-bit ("_hw32" suffix is added for 32-bit operations, otherwise no suffix is added)
    • f5series ("_f5" suffix added)

    But when pulling this all together at the link stage, overall the names of the library calls are somewhat insignificant. Each library function has a couple of aliases, so if you use any of these it will link the same function. For example:

    • libmul_16.a
      • Aliases for 16-bit multiplication: "__mulhi2", "__mspabi_mpyi" and "__mspabi_mpyi_hw"
      • Aliases for 32-bit multiplication: "__mulsi2",  "__mspabi_mpyl"  and "__mspabi_mpyl_hw"
    • libmul_32.a
      • Aliases for 16-bit multiplication: "__mulhi2", "__mspabi_mpyi" and "__mspabi_mpyi_hw"
      • Aliases for 32-bit multiplication: "__mulsi2_hw32",  "__mspabi_mpyl"  and "__mspabi_mpyl_hw32"
    • libmul_f5.a
      • Aliases for 16-bit multiplication: "__mulhi2_f5", "__mspabi_mpyi" and "__mspabi_mpyi_f5hw"
      • Aliases for 32-bit multiplication: "__mulsi2_f5",  "__mspabi_mpyl"  and "__mspabi_mpyl_f5hw"

    So in conclusion, I would recommend building your library with -mhwmult=none, so the __mspabi_mpy names are generated. Then when you link a program with your library use the -mmcu= option as normal. Or the explicit -mhwmult= option for your device, if that is how you are building (it is recommended to use -mmcu).

    I tried an example, using the same object file in a program for an FG4618 and an F5529.

    msp430-elf-gcc none.c -mhwmult=none -c -o none.o
    msp430-elf-gcc none.o -mmcu=msp430f5529 -I msp430-gcc-support-files/include -L msp430-gcc-support-files/include main.c -Wl,-Map=f5.map
    msp430-elf-gcc none.o -mmcu=msp430fg4618 -I msp430-gcc-support-files/include -L msp430-gcc-support-files/include main.c -Wl,-Map=fg4.map

    We can see from the f5.map file, that the use of __mspabi_mpyl pulls in the function from the f5 library:

    /home/jozef/msp430-gcc-8.3.0.16_linux64/bin/../lib/gcc/msp430-elf/8.3.0/libmul_f5.a(lib2hw_mul_f5.o)
                                  none.o (__mspabi_mpyl)
    

    And these 3 symbols have the same address i.e. they are aliases:

     .text.__mulsi2_f5                                                                                                                                
                    0x000000000000447e       0x20 /home/jozef/msp430-gcc-8.3.0.16_linux64/bin/../lib/gcc/msp430-elf/8.3.0/libmul_f5.a(lib2hw_mul_f5.o)
                    0x000000000000447e                __mspabi_mpyl                                                                                   
                    0x000000000000447e                __mspabi_mpyl_f5hw                                                                              
                    0x000000000000447e                __mulsi2_f5                                                                                     

    And the same for fg4.map, but the references are resolved from the 16-bit hardware multiply library:

    Archive member included to satisfy reference by file (symbol)
    
    /home/jozef/msp430-gcc-8.3.0.16_linux64/bin/../lib/gcc/msp430-elf/8.3.0/libmul_16.a(lib2hw_mul_16.o)
                                  none.o (__mspabi_mpyl)
    ................
     .text.__mulsi2                                                                                                                                      
                    0x000000000000317e       0x2e /home/jozef/msp430-gcc-8.3.0.16_linux64/bin/../lib/gcc/msp430-elf/8.3.0/libmul_16.a(lib2hw_mul_16.o)   
                    0x000000000000317e                __mspabi_mpyl                                                                                      
                    0x000000000000317e                __mulsi2                                                                                           
                    0x000000000000317e                __mspabi_mpyl_hw                                                                                   

    I hope this helps, let me know if you have any further questions.