* 実レジスタ活用 -(by [[K]], 2013.04.20) ** もくてき -実レジスタをもっと使ったら速くなるんじゃないかという話。 -実レジスタを使ったらもっと速くなるんじゃないかという話。 ** こうさつ -(1) x86の32bitモードは、32bitレジスタが8本しかない。しかもそのうちの1つはスタックポインタで、自由には使えない。 --まずR00-R3F,P00-P1Fへのアクセスのためには、すくなくとも2つの作業用のレジスタが必要になる。LIMMとかADDとかだけならEAXだけで何とかなるけど、LMEMとかSMEMとかをやるときにはどうしてもEAXだけではうまくいかない。もう一つレジスタが必要になる。 ---それにシフト演算のときもCLを使う必要がある。 ---割り算をするときには、EDXを使う必要がある。 --実はosecpu027aでは、レジスタを結構雑に使っていて、他にもいろんなレジスタを汚してしまっている。反省。 -(2) いくつかのよく使う仮想レジスタを余った実レジスタに固定で割り振れるとしたら、なんかとっても速くなりそうな気はする。 --まあ実際のところは試してみないと分からないんだけど。 -ということで、思いっきりレジスタを節約する方向で考えてみる。 -まず、現在EBP上に展開しているレジスタイメージを、スタック上にコピーしてしまおう。そうすれば、EBPがあく。 --OSECPUは関数callなどをしても実CPUのスタックにリターンアドレスを積んだりはしないので、ESPが変化しない。だからこそできるテクニックだ。 -次にECX/EDXを必要とする命令は少数なので、これを特別扱いにして、それらの命令のときだけECX/EDXを仮想レジスタ域に退避して、そしてECX/EDXを使って目的を達して、その後にECX/EDXを復元する。 --こうすれば、ECX/EDXもあく。 -これで結局、EAXとESP以外のレジスタが使えて、ECX/EDXもまあまあ使えるということになる。5.5レジスタくらいというところかな。 --おお、これは結構いいんじゃないか? -(3) この5.5レジスタを、どのように割り振るべきかは意見の分かれるところだろうなあ。 --やっぱり使用頻度の高いレジスタに割り当てるべきなんだろうな。 --というかむしろ発想は逆で、実レジスタに割り当てることになったものを人間が積極的に使えばいいわけだ。OSECPUのアセンブラで。 --コンパイラとか使う人は、速度が大して重要じゃなくてとにかく楽して作ることを優先している人だから、その人のことを考える必要はない。 ---もし速度が出したくなったらそこだけアセンブラで書いてうまいレジスタの使い方をすればいいだけなんだから。 --ということで、こうしてみようかと検討中: R00 R01 R02 P01 P02 P03 EBX ECX EDX EBP ESI EDI --実レジスタと仮想レジスタが混ざるとJITコンパイラってどのくらいめんどくさくなるのかな。そんなに大変でもなさそうかな。適当に手抜きもできそうだ。 ---手抜き:EBX~EDIを一度スタック上に書き戻して従来の処理をして、またEBX~EDIに読み込む。 ---とりあえずこれをはさめば、少しずつ実レジスタ対応できる。 --やばいなー、なんだか超ワクワクしてきたぞ!(笑) -他のCPUのことも考えてコメントするとこんな感じ: --実レジスタに余裕のあるときは、以下の方針でレジスタを実レジスタ化します。 --P02,R00,P03,R01,P01,R02,P04,R03,P05,R04,P06,R05...の順に割り振ります。 --ポインタが若干優先されるのは、ポインタアクセスがボトルネックになりやすそうだという推測に基づきます。 --ポインタは、P02,P03,P01,P04,P05,P06,...の順に割り振ります。 ---P01よりもP02やP03が優先されるのは、P01がベースポインタであって用途が限定されるため、もっと汎用のものを優先した結果です。 ---ペースポインタ上にあるものを頻繁にアクセスする場合は、あえてP02=P01;としたあと、P02経由でアクセスすると、実レジスタ数の少ないCPUでも比較的高速に実行されるかもしれません。 --この方針は推奨されているだけであって義務ではありません。 ---実レジスタに余裕があっても、全部メモリ上に割り当ててもいいですし、JITCの実装の都合で他の割り当て方針でもかまいません。 ** こめんと欄 -このページにこめんと欄はありません。このページの内容にコメントしたいときは[[impressions]]にお願いします。