Cコンパイラ部のportingの本質的な部分はgcc/config/配下にzumi32用のディレクトリを作成し、そこにMachine Descriptionファイル(以下mdファイルと略す)を作成することである。 (他にconfigure関係やMakefile関係の編集も必要)
例えばCソース側で、
a = b;
のようなプログラムがある場合に、これをcpuのどういう命令で実現するかをmdファイルに記述する。 a, b はレジスタの場合も有るし、メモリの場合も有り、其々の場合で割り当てるcpuの命令は違ってくる。 char / short / int や signed / unsigned 等の型によっても命令を使い分けなければならない場合もある。 上記のようなデータの移動は以下のような記述になる。
(define_insn "movsi_insn"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,m,r,r,r,r")
(match_operand:SI 1 "movsi_rhs_operand" "m,r,r,J,K,L,U,Y"))]
""
"@
ld32 %0,%1
mov %0,%1
st32 %0,%1
st32 %0,r0
ldsi %0,%1
ldui %0,%1
ldhi %0,hi(%1)\n\tshli\t%0,%0,16
ldhi %0,hi(%1)\n\tshli\t%0,%0,16"
[(set_attr "type" "load,arith,store,store,arith,arith,arith,arith")]
)
Machine DescriptionはRTL(Register Transfer Language)という言語というか記法で記述する。RTLの言語仕様はLispから影響を受けているらしい。 portingをする場合は、既存のcpu用のmdファイルを参考にするのが良いのは言うまでもなく資料にもそう書かれているのだが、RTLの言語仕様に関する知識がまったくない状態で、それらを見よう見まねしようとしてもほぼ無理だと思う。 各cpu固有のアーキテクチャがあり、また、書き方や構成も異なるため、定形の型が中々読み取れない。 そこで、ドキュメントを読んで学習する必要がある。ドキュメントはgccのソースツリーのgcc/doc配下にあるgccint.infoだ。 build時にmake pdfとするとgccint.pdfが作られるので、それを読むと良い。 ただ、このドキュメントが640ページもある上、ちょーーーーーー難解だ。 以前から挑戦しては挫折の繰り返しで、何回よんでも難解だ。難解だけに、・・・ぷぷっ でも、今回はじっくり読んだこともあり、少しだけ理解が深まった気がする。また、mdファイルはLattice Mico32用のmdファイルをお手本にさせて貰った。 また、今回の作業でzumi32の命令も一部変更と追加をすることにした。 具体的には算術命令をsignedとunsigned用に分けるということと、条件分岐命令でbczとbcnzを追加等である。bcz, bnczは比較命令 ≧ や ≦ の実装の容易化の為に追加した。
悪戦苦闘の末、cc1でアセンブラソースの出力は出きるようにはなってきた。
以下ではポインタとfor ループの確認
→ 少なくとも整数の乗除算、剰余算は自分で作る必要があるようだ。
以下はchar,short,int混在の演算の確認
以下はVRAMを単一色で塗りつぶす処理モデルをコンパイルしてみた。
zumi32(lm32等もそうだが)は32bit即値をそのままレジスタにロードすることが出来ない。これは命令を32bit固定としていることによる。そのため、32bitの即値をロードさせる場合は即値を上位と下位に分けて、ロード・合成する必要がある。上記のアセンブリ言語側のhi(...)やlo(...)はそれを表している。 上記では上位値をldsi命令でロードした後シフト命令でシフトしているが、Lattice Micoやmipsでは直接上位にロードする命令がある。 zumi32もその命令を追加すべきか思案中だ。
上記のような上位/下位に分けてロードする場合は即値は16bitの方が扱いやすいが、zumi32の即値ロード命令は20bitの即値になっており、この点も今一な仕様になってしまっている。
変えようかな。。。
portingに必要なGCCの情報を完全に理解しない状態で行っているのでゴールが近いのか遠いのかさえ見えていない状態だが、何とか完成させたい、それまでモチベーションが維持できればいいが。。。Cが使えればプログラムの作成効率は格段に上がるからなぁー。