ぱたへね

はてなダイアリーはrustの色分けができないのでこっちに来た

自作コンパイラで基本的な演算子が動いた

自作コンパイラでRISC-VのC言語の基本的な演算子が動くようになりました。

これの続き

natsutan.hatenablog.com

こんなCソースで動作確認しています。

int main(void) {
  putd(2>=4);
  return 0;
}

低レイヤを知りたい人のためのCコンパイラ作成入門に書いてないところ中心にまとめました。

www.sigbus.info

動いた演算子

<< >>

右シフト、左シフトはそのまんまの命令があるので使う。 C言語で負の値の右シフトは処理系依存。符号が残る方が好きなので算術シフト sra を使いました。

            | BinOpKind.LShift -> fp.WriteLine " sll a0, a0, a1"            
            | BinOpKind.RShift -> fp.WriteLine " sra a0, a0, a1"

& | ^

これも対応する命令がある。

            | BinOpKind.BitAnd -> fp.WriteLine " and a0, a0, a1"
            | BinOpKind.BitOr -> fp.WriteLine " or a0, a0, a1"
            | BinOpKind.BitXor -> fp.WriteLine " xor a0, a0, a1"

&& ||

bit演算をした後、結果を0と比較する。 結果が0でなければ1、結果が0ならば0を返す。

            | BinOpKind.LogicalAnd ->
                fp.WriteLine " and a0, a0, a1"
                fp.WriteLine " snez a0, a0"
            | BinOpKind.LogicalOr ->
                fp.WriteLine " or a0, a0, a1"
                fp.WriteLine " snez a0, a0"

2023/03/15修正 &&は間違っていた。こっちが正解。 一旦両オペランドを0か1にしてからandを取る。

            | BinOpKind.LogicalAnd ->
                fp.WriteLine "  snez a0, a0"
                fp.WriteLine "  snez a1, a1"
                fp.WriteLine "  and a0, a0, a1"
                fp.WriteLine "  snez a0, a0"

>= <=

ちょっと頭を使った。 RISC-Vの比較命令は、slt (set lesser than)しかない。 greater thanを使いた時は、左右のオペランドを入れ替える。

問題は>=と<=。引き算して0以上とかで行けるかなと思ってパターソン先生の The RISC-V Readerを眺めていたら、<=は、>の否定なので専用の命令は要らないと書いてあって納得。

riscvbook.com

seqz a0, a0が、a0が0ならa0を1に、a0が0以外ならa0を0にしてくれる。

            | BinOpKind.LesserThan -> fp.WriteLine " slt a0, a0, a1"
            | BinOpKind.LesserEqual ->
                fp.WriteLine " slt a0, a1, a0"
                fp.WriteLine " seqz a0, a0"
            | BinOpKind.GreaterThan -> fp.WriteLine " slt a0, a1, a0"
            | BinOpKind.GreaterEqual ->
                fp.WriteLine " slt a0, a0, a1"
                fp.WriteLine " seqz a0, a0"

%

これもそのまんまの命令があるので使う。

            | BinOpKind.Modulo -> fp.WriteLine " rem a0, a0, a1"

この後

基本的な演算子が動くようになったが、優先順位が全然ついてないので次は優先順位をつけていく。

ソースはここ

github.com