__aeabi_uldivmod undefined for sound/soc/codecs/snd-soc-wm8974.ko, snd-soc-wm8940.ko and snd-soc-wm8510.ko
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
Re: __aeabi_uldivmod undefined for sound/soc/codecs/snd-soc-wm8974.ko, snd-soc-wm8940.ko and snd-soc-wm8510.ko
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 & 0x; /* 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). -- 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
Re: __aeabi_uldivmod undefined for sound/soc/codecs/snd-soc-wm8974.ko, snd-soc-wm8940.ko and snd-soc-wm8510.ko
Hi Michael, 2011/4/26 Michael Hope : > 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 & 0x; > > /* 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
Re: __aeabi_uldivmod undefined for sound/soc/codecs/snd-soc-wm8974.ko, snd-soc-wm8940.ko and snd-soc-wm8510.ko
2011/4/26 Barry Song <21cn...@gmail.com>: > Hi Michael, > > 2011/4/26 Michael Hope : >> 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 & 0x; >> >> /* 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. > > Or if adding one line before do_div, all will be ok. asm("" : "+r"(source)); do_div(Kpart, source); >> >> -- 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
Re: __aeabi_uldivmod undefined for sound/soc/codecs/snd-soc-wm8974.ko, snd-soc-wm8940.ko and snd-soc-wm8510.ko
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 : >> 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 & 0x; >> >> /* 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
Re: __aeabi_uldivmod undefined for sound/soc/codecs/snd-soc-wm8974.ko, snd-soc-wm8940.ko and snd-soc-wm8510.ko
On Tue, 26 Apr 2011, Michael Hope wrote: > 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 & 0x; > > /* 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). The kernel is omitting this function on purpose. The idea is to prevent people from ever using 64-bit by 64-bit divisions since they are always costly and avoidable. This is why the kernel provides a do_div() macro: to allow for 64-bit dividend by only 32-bit divisors. And this stems from the fact that gcc has no (or used not to have) patterns to match a division with a 64-bit dividend and a 32-bit divisor, hence it promotes the divisor to a 64-bit value and perform the costly division that the kernel wants to avoid. Worse, gcc isn't smart enough to optimize the operation even when the divisor is constant, which is quite a common operation in the kernel. This is why many years ago I wrote the code for the do_div() version you can find in arch/arm/include/asm/div64.h where the division is turned into a reciprocal multiplication. For example, despite the amount of added C code, do_div(x, 1) now produces the following assembly code (where x is assigned to r0-r1): adr r4, .L0 ldmia r4, {r4-r5} umull r2, r3, r4, r0 mov r2, #0 umlal r3, r2, r5, r0 umlal r3, r2, r4, r1 mov r3, #0 umlal r2, r3, r5, r1 mov r0, r2, lsr #11 orr r0, r0, r3, lsl #21 mov r1, r3, lsr #11 ... .L0: .word 948328779 .word 879609302 But I digress. This is just to say that gcc shouldn't pull __aeabi_uldivmod in this case because: 1) the division and the modulus are not performed on the same operands; 2) the modulus is performed on a 32-bit variable; 3) the do_div() implementation looks like nothing that gcc could recognize as being a division. Therefore I don't see how the right pattern could have been matched. Nicolas ___ linaro-toolchain mailing list linaro-toolchain@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-toolchain
Re: __aeabi_uldivmod undefined for sound/soc/codecs/snd-soc-wm8974.ko, snd-soc-wm8940.ko and snd-soc-wm8510.ko
On Tue, 26 Apr 2011, Michael Hope wrote: > Yip, so the compiler spots these two lines: > Ndiv = target / source; > Nmod = target % source; > > and turns them into > Ndiv, Nmod = __aeabi_uldivmod(target, source) Why would gcc do that? All four variables involved here are of type unsigned int, no unsigned long long. Seems to me that __aeabi_uidivmod should have been used here instead. Nicolas ___ linaro-toolchain mailing list linaro-toolchain@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-toolchain