undefined reference to `__divdi3'
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
On Sun, 22 Jul 2018 17:48:21 +0530, Himanshu Jha said:
I am currently working on my GSoC project and while testing through 0-day test service, I hit the following error:
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};
As an aside, making this a 'static u32' will get rid of the mess of mov and movabs instructions each time. 'static const u32' would be even better, as then the compiler knows it can optimize assuming it never changes any of the values... (In addition, with all that initialization out of the picture, figuring out which assembler code does what should be easier...
participants (2)
-
Himanshu Jha -
valdis.kletnieks@vt.edu