qsortのcallback関数

http://d.hatena.ne.jp/shinichiro_h/20070123#1169557406
に触発されてPPCで同じ事をやってみました。

int a[] = {1, 3, 7, 2, 6, 5, 4, 9, 8};
int main(){
  int i;
  qsort(a, sizeof(a)/4, 4, "}#@\x2e}D@\x2e|jHPN\x80\0 ");
  for(i = 0; i < sizeof(a)/4; ++i){
    printf("%d ", a[i]);
  }
  puts("");
  return 0;
}

これでちゃんと動いた。やっぱり文字列が長くなってしまうのはしょうがないのだけど、これでもちょっと工夫して短くしました。
まず、元のCのコードは

int cmp(int* a, int* b){
  return *a - *b;
}

でこれを素直にPPCアセンブリに直すと

lwz r5, 0(r3)
lwz r6, 0(r4)
sub r3, r5, r6
blr

軽く説明すると渡された引数は順番にr3, r4, r5, r6...とr3から順番にレジスタに入っていきます。戻り値はr3にいれて返します。
r3 〜 r10までが関数内で汎用的に使えるレジスタです。
PPCの場合メモリの中身を直接演算できないんで一旦読み出します。
雰囲気的には上のコードは

r5 = *(r3 + 0);
r6 = *(r4 + 0);
r3 = r5 - r6;
return

みたいな感じ。

それで上のコードをそのまま機械語に直すとlwz命令の箇所が\x80\xa3\x00\x00\x80\xc4\x00\x00みたいになっちゃうんで、

lwzx r9, r3, r8
lwzx r10, r4, r8
sub r3, r9, r10
blr

と変更したものの機械語を使いました。
lwzxはr9 = *(r3 + r8)みたいな意味で、r8が0に初期化されることを利用してます。

やっぱPPCアセンブリは暗号みたいで好きになれないな〜。