5

Do there exist intrinsics for ARM C compilers to do add-with-carry operations, or is it necessary to use assembly language?

On x86, there is _addcarry_u64 for add-with-carry. (There's also the newer _addcarryx_u64 for special purposes.)

Myria
  • 3,040
  • 18
  • 37
  • Compilers typically implement `int64_t` on 32bit machines with `adc`, so you can cast to that. GNU C (gcc / clang) on 64bit platforms usually supports `__int128_t`. – Peter Cordes May 10 '16 at 01:59
  • Aarch64 has an adc instruction that gcc 5.2 uses. (`adds` / `adc` to add two `__int128_t` args), but Aarch64 gcc 4.8 uses the [cmov-and-increment `csinc` instruction](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0802a/CSINC.html). See [the output on godbolt](https://godbolt.org/g/OujSx4). IDK why aarch64 gcc 4.8 doesn't manage to just use `adc`. – Peter Cordes May 10 '16 at 02:39
  • I don't see a gcc `__builtin` function for add-with-carry :( – Peter Cordes May 10 '16 at 02:50
  • 1
    Note that for whatever it is you're trying to do which would need this, you'd equally need another intrinsic for setting the carry flag in the first place. I'm pretty certain neither exists. – Notlikethat May 10 '16 at 08:32
  • The situation with x86 is not any better at leas for GCC and Clang http://stackoverflow.com/questions/33690791/producing-good-add-with-carry-code-from-clang/33719144#33719144 – Z boson May 16 '16 at 07:43

1 Answers1

7

There is no intrinsic with current versions of gcc. An issue is that communication of the 'carry flag'. However, the ARM backend does know and define a set of ADC primitives such as addsi3_carryin.

For example,

unsigned long long big_inc(unsigned long long x)
{
  return ++x;
}

Is translated to,

big_inc(unsigned long long):
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        adds    r0, r0, #1
        adc     r1, r1, #0
        bx      lr

It is always instructive to look at open source multi-precision libraries when you have a question like this. There is OpenSSL bignum and GNU MP libraries without any research. As the intrinsic doesn't exist a more definitive answer (for your work) depends on exactly what it is you want to achieve; prime factors, multiply, add, etc. You can always use assembler or more powerfully use a script that generates assembler for your particular integer length.

artless noise
  • 18,969
  • 5
  • 57
  • 95
  • A lot of general purpose libraries will do something like [Duff's device](https://en.wikipedia.org/wiki/Duff's_device) and run through to 'int[]` arrays to do the `adds`/`adc`/`adcs` appropriately to do an operation. However, the inside of the loop can often be combined for efficiency gains as you don't need to keep loading memory; the comment above about it depends what you want to do... – artless noise May 10 '16 at 21:17