ARMアセンブラ勉強中(2)

前の、RGB565→RGB565の転送を透過転送用functorで組んだルーチンをアセンブラで出力してみると、8ループ展開の内部は次のようになってました。

 1    LDRH     r5,[r1,#-2]
 2    LDRH     r12,[r13,#0x38]
 3    CMP      r5,r12
 4    STRNEH   r5,[r9,#0]
 5    SUB      r9,r9,#2
 6    LDRH     r5,[r1,#-4]
 7    LDRH     r12,[r13,#0x38]
 8    CMP      r5,r12
 9    STRNEH   r5,[r9,#0]
10    SUB      r9,r9,#2
11    LDRH     r5,[r1,#-0xc]
      ....
41    SUB      r1,r1,#16
42    SUB      r0,r0,#8
43    CMP      r0,#8
44    BGE      0xe2b0    ;1行目へ

1行目でsrcのデータをロード。
2行目で透過色をロード。
3行目でその2つを比較して、両方が同じ値ではないときだけ
4行目の、転送先へのストアを実行し、
5行目で転送先のオフセットをずらす、と。
んで後はその繰り返しを8回やってるわけですね。


このループ内のクロック数を数えてみると、一回の転送が実際に転送する場合は10クロックで、転送しない場合は9クロック。とりあえず平均を取って9.5クロックとして、それを8回。最後にSUB,SUB,CMP,BGEで6クロックなので、合計82クロックですね。
これを出来る限り最適化したいと思います。


まずめちゃめちゃもったいないのが透過色を毎回ロードしてるところですね。
ロード命令は3クロックも消費するので、これは事前にロードしておいて、常にそれを使うようにします。
そうすれば3×8=24クロックも減ります。うひょーヽ(´ー`)ノ

      LDRH     r12,[r13,#0x38]    ;事前にロードしておく
      ;↑ループの外側
 1    LDRH     r5,[r1,#-2]
 3    CMP      r5,r12
 4    STRNEH   r5,[r9,#0]
 5    SUB      r9,r9,#2
 6    LDRH     r5,[r1,#-4]
 8    CMP      r5,r12
 9    STRNEH   r5,[r9,#0]
10    SUB      r9,r9,#2
11    LDRH     r5,[r1,#-0xc]
      ....
41    SUB      r1,r1,#16
42    SUB      r0,r0,#8
43    CMP      r0,#8
44    BGE      0xe2b0    ;1行目へ


次に、毎回転送先のアドレスを減算しているのがもったいないです。こいつは最後にまとめて引いてやることにしましょう。7クロック減ります。

      LDRH     r12,[r13,#0x38]    ;事前にロードしておく
      ;↑ループの外側
 1    LDRH     r5,[r1,#-2]
 3    CMP      r5,r12
 4    STRNEH   r5,[r9,#-2]
 6    LDRH     r5,[r1,#-4]
 8    CMP      r5,r12
 9    STRNEH   r5,[r9,#-4]     ;オフセットを指定して転送
11    LDRH     r5,[r1,#-0xc]
      ....
      SUB      r9,r9,#16 ;ここでまとめて引く
41    SUB      r1,r1,#16
42    SUB      r0,r0,#8
43    CMP      r0,#8
44    BGE      0xe2b0    ;1行目へ


ピクセルの転送を平均5.5クロックとすれば、合計51クロックになり、約40%ぐらい速くなる……はずです。
実測はしてないからわかんない(;´Д`)