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