assemblyldavravr-gcclibgcc

Math symbols missing from AVR libgcc


I have some AVR assembly which was generated for an unknown version of GCC. I can assemble this source into object code, but if I try to link it I am told that it contains undefined symbols.

Specifically, I am missing the following symbols:

__lshrsi3, __ashlsi3, 
__divsi3, __divhi3, __divqi3, __modsi3, __modhi3, __modqi3, 
__udivsi3, __udivhi3, __udivqi3, __umodsi3, __umodhi3, __umodqi3

These seem to be libgcc symbols, but they are not present in libgcc.a for my version of AVR-GCC (4.8.3). I verified this running nm on those files and there were no symbols with these names defined.

I have been unable to determine in which versions of AVR-GCC these symbols were present, if at all, or if they were provided by another library. Other searches have proved fruitless so now I'm hoping the wisdom of SO will be able to solve my mystery.

For clarity, here is a trivial example of an assembly file which will assemble without issue but fails linking:

    .text
    .globl  main
    .align  2
    .type   main,@function
main:                                   ; @main
; BB#0:
    ldi r24, 31
    ldi r22, 31
    call    __udivqi3
    ret
.Ltmp1:
    .size   main, .Ltmp1-main

Trying to link this fails with the following error:

/tmp/ccxYMfat.o:udiv.s:9: undefined reference to `__udivqi3'
collect2: error: ld returned 1 exit status

Here's the libgcc I'm using:

$ avr-gcc -print-libgcc-file-name
/usr/lib/gcc/avr/4.8.3/libgcc.a

Which does not contain the symbol __udivqi3

$ avr-nm /usr/lib/gcc/avr/4.8.3/avr6/libgcc.a |grep udivq
$ 

Alternatively, if there isn't a version of GCC that ever contained these symbols, are there drop-in replacements for them that would follow the same calling convention and perform the same tasks?


Solution

  • The library function __udivqi3 was removed from libgcc way back on 2001-01-20. You'll need to find a version of GCC released before that date, like GCC 2.95.2. Most of the functions you're using were replaced by a function that combined division and modulus into the same operation so an alternative would be to rewrite the functions to call those routines instead. For example instead of calling __udivqi3 call __udivmodqi4. Note that these new functions aren't drop in replacements.

    I'm not sure when, if ever, __lshrsi3 and __ashlsi3 were part of libgcc. It shouldn't be too hard to roll your own replacements for these functions if necessary.