Yip, so the compiler spots these two lines:
         Ndiv = target / source;
         Nmod = target % source;

and turns them into
  Ndiv, Nmod = __aeabi_uldivmod(target, source)

Depending on the policy of the kernel developers, you should either
implement __aeabi_uldivmod in lib1funcs.asm or use another kernel
construct to prevent the optimisation from happening.

Googling around brought up this thread:
 http://comments.gmane.org/gmane.linux.kernel/965262

-- Michael

On Tue, Apr 26, 2011 at 1:42 PM, Barry Song <21cn...@gmail.com> wrote:
> Hi Michael,
>
> 2011/4/26 Michael Hope <michael.h...@linaro.org>:
>> Hi Barry.  I think the toolchain is operating correctly here.  The
>> current version recognises a divide followed by a modulo and optimises
>> this into a call to the standard EABI function __aeabi__uldivmod().
>> Note the code:
>>
>>        do_div(Kpart, source);
>>
>>        K = Kpart & 0xFFFFFFFF;
>>
>>        /* Check if we need to round */
>>        if ((K % 10) >= 5)
>>                K += 5;
>>
>> This function is provided by libgcc for normal applications. The
>> kernel provides it's own versions in arch/arm/lib/lib1funcs.s but is
>> missing __aeabi_uldivmod (note the 'l' for 64 bit).
> In fact the problem happen ealier:
>
>  if (Ndiv < 6) {
>               source /= 2;
>                pll_div->pre_div = 1;
>                Ndiv = target / source;
>        } else
>                pll_div->pre_div = 0;
>
>        if ((Ndiv < 6) || (Ndiv > 12))
>                printk(KERN_WARNING
>                        "WM8974 N value %u outwith recommended range!\n",
>                        Ndiv);
>
>        pll_div->n = Ndiv;
>        Nmod = target % source;
>        Kpart = FIXED_PLL_SIZE * (long long)Nmod;
>
>        do_div(Kpart, source);
>
> If commenting "source /= 2", the problem disappear.
>
>
>>
>> -- Michael
>>
>> On Tue, Apr 26, 2011 at 12:45 AM, Barry Song <21cn...@gmail.com> wrote:
>>> Hi All,
>>> I am using 2011.3 4.5 linaro GCC(armv7-a vfpv3d16) to compile kernel
>>> and modules. I select to compile all codecs as modules:
>>> "config SND_SOC_ALL_CODECS
>>>          tristate "Build all ASoC CODEC drivers"
>>> "
>>> as M and I2C/SPI too.
>>>
>>> Then in the kernel dir, run "make" to get both vmlinux and modules, I
>>> found snd-soc-wm8974.ko, snd-soc-wm8940.ko and snd-soc-wm8510.ko will
>>> fail due to "__aeabi_uldivmod undefined".
>>>
>>> If i comment do_div() in these codec drivers, this issue will
>>> disappear. But it is strange there are many codecs which use do_div()
>>> too, for example:
>>> sound/soc/codecs/max98088.c
>>> sound/soc/codecs/max9850.c
>>> sound/soc/codecs/wm8350.c
>>> sound/soc/codecs/wm8400.c
>>> sound/soc/codecs/wm8510.c
>>> sound/soc/codecs/wm8580.c
>>> sound/soc/codecs/wm8753.c
>>> sound/soc/codecs/wm8804.c
>>> sound/soc/codecs/wm8900.c
>>> sound/soc/codecs/wm8904.c
>>> sound/soc/codecs/wm8940.c
>>> sound/soc/codecs/wm8955.c
>>> sound/soc/codecs/wm8960.c
>>> sound/soc/codecs/wm8974.c
>>> sound/soc/codecs/wm8978.c
>>> sound/soc/codecs/wm8985.c
>>> sound/soc/codecs/wm8990.c
>>> sound/soc/codecs/wm8991.c
>>> sound/soc/codecs/wm8993.c
>>> sound/soc/codecs/wm8994.c
>>> sound/soc/codecs/wm8995.c
>>> sound/soc/codecs/wm9081.c
>>>
>>> but others can pass the compiling except those 3 modules. Is it due to
>>> a wrong optimization by gcc?
>>>
>>> Other information:
>>> 1. old tool-chains we are using can pass the compiling of the 3 modules.
>>> 2. If i built all codecs into kernel image, these 3 drivers don't
>>> report error while compiling.
>>>
>>> Thanks
>>> Barry
>>>
>>> _______________________________________________
>>> linaro-toolchain mailing list
>>> linaro-toolchain@lists.linaro.org
>>> http://lists.linaro.org/mailman/listinfo/linaro-toolchain
>>>
>>
>

_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to