undefined reference to `__divdi3'
Himanshu Jha
himanshujha199640 at gmail.com
Sun Jul 22 08:18:21 EDT 2018
Hi,
I am currently working on my GSoC project and while testing through
0-day test service, I hit the following error:
drivers/iio/chemical/bme680_core.o: In function `bme680_compensate_gas':
drivers/iio/chemical/bme680_core.c:450: undefined reference to `__divdi3'
vim +450 drivers/iio/chemical/bme680_core.c
417
418 /*
419 * Taken from Bosch BME680 API:
420 * https://github.com/BoschSensortec/BME680_driver/blob/63bb5336/bme680.c#L973
421 *
422 * Returns gas measurement in Ohm. Output value of "82986" represent 82986 ohms.
423 */
424 static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc,
425 u8 gas_range)
426 {
427 struct bme680_calib *calib = &data->bme680;
428 s64 var1;
429 u64 var2;
430 s64 var3;
431 u32 calc_gas_res;
432
433 /* Look up table 1 for the possible gas range values */
434 u32 lookupTable1[16] = {2147483647u, 2147483647u, 2147483647u,
435 2147483647u, 2147483647u, 2126008810u,
436 2147483647u, 2130303777u, 2147483647u,
437 2147483647u, 2143188679u, 2136746228u,
438 2147483647u, 2126008810u, 2147483647u,
439 2147483647u};
440 /* Look up table 2 for the possible gas range values */
441 u32 lookupTable2[16] = {4096000000u, 2048000000u, 1024000000u,
442 512000000u, 255744255u, 127110228u, 64000000u,
443 32258064u, 16016016u, 8000000u, 4000000u,
444 2000000u, 1000000u, 500000u, 250000u, 125000u};
445
446 var1 = ((1340 + (5 * (s64) calib->range_sw_err)) *
447 ((s64) lookupTable1[gas_range])) >> 16;
448 var2 = (((s64) ((s64) gas_res_adc << 15) - 16777216) + var1);
449 var3 = (((s64) lookupTable2[gas_range] * (s64) var1) >> 9);
> 450 calc_gas_res = (u32) ((var3 + ((s64) var2 >> 1)) / (s64) var2);
451
452 return calc_gas_res;
453 }
Now, I understood the problem of 64bit divison and how gcc places
'__divdi3()'
https://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html
to support the "freestanding" environment and support architectures
which don't have such datatypes. And I need to use div64_s64()
or hack around do_div() to solve the issue.
Just out of curiosity, I decided to disassemble this particular function
to see __divdi3 and couldn't find it!
(gdb) disassemble bme680_compensate_gas
Dump of assembler code for function bme680_compensate_gas:
0x0000000000000000 <+0>: call 0x5 <bme680_compensate_gas+5>
0x0000000000000005 <+5>: sub rsp,0x88
0x000000000000000c <+12>: movabs rcx,0x7eb851ea7fffffff
0x0000000000000016 <+22>: movzx edx,dl
0x0000000000000019 <+25>: mov rax,QWORD PTR gs:0x28
0x0000000000000022 <+34>: mov QWORD PTR [rsp+0x80],rax
0x000000000000002a <+42>: xor eax,eax
0x000000000000002c <+44>: movabs rax,0x7fffffff7fffffff
0x0000000000000036 <+54>: movabs r8,0x7ef9db217fffffff
0x0000000000000040 <+64>: movabs r9,0x7f5c28f47fbe76c7
0x000000000000004a <+74>: mov QWORD PTR [rsp],rax
0x000000000000004e <+78>: mov QWORD PTR [rsp+0x8],rax
0x0000000000000053 <+83>: movzx esi,si
0x0000000000000056 <+86>: mov QWORD PTR [rsp+0x20],rax
0x000000000000005b <+91>: mov QWORD PTR [rsp+0x38],rax
0x0000000000000060 <+96>: movabs rax,0x7a120000f4240000
0x000000000000006a <+106>: mov QWORD PTR [rsp+0x40],rax
0x000000000000006f <+111>: movabs rax,0x1e8480003d090000
0x0000000000000079 <+121>: mov QWORD PTR [rsp+0x10],rcx
0x000000000000007e <+126>: mov QWORD PTR [rsp+0x48],rax
0x0000000000000083 <+131>: movabs rax,0x7938c540f3e58ff
0x000000000000008d <+141>: mov QWORD PTR [rsp+0x18],r8
0x0000000000000092 <+146>: mov QWORD PTR [rsp+0x50],rax
0x0000000000000097 <+151>: movabs rax,0x1ec381003d09000
0x00000000000000a1 <+161>: mov QWORD PTR [rsp+0x28],r9
0x00000000000000a6 <+166>: mov QWORD PTR [rsp+0x58],rax
0x00000000000000ab <+171>: movabs rax,0x7a120000f46290
0x00000000000000b5 <+181>: mov QWORD PTR [rsp+0x30],rcx
0x00000000000000ba <+186>: mov QWORD PTR [rsp+0x60],rax
0x00000000000000bf <+191>: movabs rax,0x1e8480003d0900
0x00000000000000c9 <+201>: mov ecx,DWORD PTR [rsp+rdx*4]
0x00000000000000cc <+204>: mov QWORD PTR [rsp+0x68],rax
0x00000000000000d1 <+209>: movabs rax,0x7a120000f4240
0x00000000000000db <+219>: shl rsi,0xf
0x00000000000000df <+223>: mov QWORD PTR [rsp+0x70],rax
0x00000000000000e4 <+228>: movabs rax,0x1e8480003d090
0x00000000000000ee <+238>: mov QWORD PTR [rsp+0x78],rax
0x00000000000000f3 <+243>: movsx rax,BYTE PTR [rdi+0x2f]
0x00000000000000f8 <+248>: lea rax,[rax+rax*4+0x53c]
0x0000000000000100 <+256>: imul rax,rcx
0x0000000000000104 <+260>: sar rax,0x10
0x0000000000000108 <+264>: lea rsi,[rax+rsi*1-0x1000000]
0x0000000000000110 <+272>: mov rcx,rax
0x0000000000000113 <+275>: mov eax,DWORD PTR [rsp+rdx*4+0x40]
0x0000000000000117 <+279>: mov rdx,rsi
0x000000000000011a <+282>: sar rdx,1
0x000000000000011d <+285>: imul rax,rcx
0x0000000000000121 <+289>: sar rax,0x9
0x0000000000000125 <+293>: add rax,rdx
0x0000000000000128 <+296>: cqo
0x000000000000012a <+298>: idiv rsi
0x000000000000012d <+301>: mov rdi,QWORD PTR [rsp+0x80]
0x0000000000000135 <+309>: xor rdi,QWORD PTR gs:0x28
0x000000000000013e <+318>: jne 0x148 <bme680_compensate_gas+328>
0x0000000000000140 <+320>: add rsp,0x88
0x0000000000000147 <+327>: ret
0x0000000000000148 <+328>: call 0x14d
End of assembler dump.
So, we have here:
0x000000000000012a <+298>: idiv rsi
Now, my question is, will __divdi3() be generated when I compile using
-m32 gcc flag or make ARCH=i386 ?
My machine is x86_64 and therefore idiv instruction is used instead of referencing
__divdi3(). Isn't it ?
Thanks.
--
Himanshu Jha
Undergraduate Student
Department of Electronics & Communication
Guru Tegh Bahadur Institute of Technology
More information about the Kernelnewbies
mailing list