__builtin_ffsはどこへ行くのか?

__builtin_ffsとはなにか?

Other Builtins - Using the GNU Compiler Collection (GCC) http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Other-Builtins.html によると

Returns one plus the index of the least significant 1-bit of x, or if x is zero, returns zero.

ということで、ビットマップ何かを操作するときに使えるGCC拡張のようだ。

これ、何やってるかちょっと気になったのでアセンブラ見てみよー!

ということで、x86アセンブラはしばらくやる気ないので、ARMのアセンブラをやってみる。

gcc version 4.7.3 20130102 (prerelease) (Linaro GCC 4.7-2013.01) 
decque@ubuntu:~$ arm-none-eabi-gcc -print-multi-lib 
.;
thumb/arm7tdmi-s;@mthumb@mcpu=arm7tdmi-s
thumb/cortex-m0;@mthumb@mcpu=cortex-m0
thumb/cortex-m3;@mthumb@mcpu=cortex-m3
thumb/cortex-m4;@mthumb@mcpu=cortex-m4
thumb/cortex-m4/float-abi-hard/fpuv4-sp-d16;@mthumb@mcpu=cortex-m4@mfloat-abi=hard@mfpu=fpv4-sp-d16

この人、thumbしか吐けません。

__builtin_ffsを含むコードをアセンブラ化してみると:

ffsl:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 1, uses_anonymous_args = 0
        stmfd   sp!, {fp, lr}
        add     fp, sp, #4
        sub     sp, sp, #8
        str     r0, [fp, #-8]
        ldr     r0, [fp, #-8]
        bl      __ffssi2
        mov     r3, r0
        mov     r0, r3
        sub     sp, fp, #4
        ldmfd   sp!, {fp, lr}
        bx      lr

__ffssi2へ飛んでいる。


主よ、どこへ行かれるのですか?

探してみた。

バイナリファイル /lib/gcc/arm-none-eabi/4.7.3/thumb/cortex-m0/libgcc.a に一致しました

ほう。

_ffssi2.o:
00000010 N $d
00000000 t $t
         U __ctzsi2
00000001 T __ffssi2

_ffssi2.oを逆アセンブルしてみると

ar x gcc.a _ffssi2.o
objdump -D _ffssi2.o
00000000 <__ffssi2>:
   0:   b508            push    {r3, lr}
   2:   2300            movs    r3, #0
   4:   2800            cmp     r0, #0
   6:   d002            beq.n   e <__ffssi2+0xe>
   8:   f7ff fffe       bl      0 <__ctzsi2>
   c:   1c43            adds    r3, r0, #1
   e:   1c18            adds    r0, r3, #0
  10:   bc08            pop     {r3}
  12:   bc02            pop     {r1}
  14:   4708            bx      r1

だからどこへいくねん。。。

さらに追いかけてみると。。。

00000000 <__ctzsi2>:
   0:   e2601000        rsb     r1, r0, #0
   4:   e0000001        and     r0, r0, r1
   8:   e3a0101c        mov     r1, #28
   c:   e3500801        cmp     r0, #65536      ; 0x10000
  10:   21a00820        lsrcs   r0, r0, #16
  14:   22411010        subcs   r1, r1, #16
  18:   e3500c01        cmp     r0, #256        ; 0x100
  1c:   21a00420        lsrcs   r0, r0, #8
  20:   22411008        subcs   r1, r1, #8
  24:   e3500010        cmp     r0, #16
  28:   21a00220        lsrcs   r0, r0, #4
  2c:   22411004        subcs   r1, r1, #4
  30:   e28f2008        add     r2, pc, #8
  34:   e7d20000        ldrb    r0, [r2, r0]
  38:   e0400001        sub     r0, r0, r1
  3c:   e12fff1e        bx      lr

あー、なんか追い詰めきれないです。。。

  • 知らないインストラクションばっかになってる。。。単語帳引きながら英語読んでるレベル。。。
  • 32bit長になっちゃってるけどなんかARM modeになっているのでは
  • objdumpにもうちょっと頑張ってもらわないといけないのではないだろうか。。。

明日以降もうちょっと追ってみます。。。でも、対象をもうちょっとモダンなアーキテクチャに変えちゃうかも。。。