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