Fuzix-Compiler-Kitの6800用コンパイラ(4)(ベーシックマスター開発 その36)
コンパイラが生成するオブジェクト(MC6800用)についてのメモです。
関数の引数
- 右から積む
- 引数のクリアは呼ばれた側が行う(可変長引数の関数の場合は呼ぶ側が行う)
- 引数の型がわかっている場合は、charは1バイトpush。わかっていない場合はintに昇格して2バイトpush
- 現状、long/floatの引数の積み方が非効率的。どうしたらいいか考える
スタックアクセス
- tsxしてインデックスアドレッシング
- 8bit offsetで届かない場合は、アドレス計算する
- ローカル変数は宣言順にアドレスの若い方から作られる。ただし配列は後回し
- 引数はローカル配列より後になるので、アクセスが多い場合は、最初に宣言した変数にコピーする
- 大きな配列アクセスは、配列へのポインタを作ると少し計算量が減る
整数演算
- charはintに昇格してから演算(これは改善されるかも)
- signed charが符号拡張されないのはバグなのか仕様なのか
実数演算
- floatのみ(IEEE754 32bit)。doubleはfloatとして扱う
- Cで書かれた最小限のライブラリはある。sin/cosなどの関数はない
- ハンドコンパイルすると2-10倍ぐらい速くなる
float演算の例
真理値、関係演算
- 関係演算を含まない場合。 if( 式 ) など
- 関係演算を含む式
- 関係演算子を値として使う場合は、そのままAccABを使う。条件分岐の場合はZを見る
- AccA,B(long,floatは@high,@high+1) に値を入れてbool/notを呼ぶ
- jsr __bool (__boolc,__booll,__boolf, __not, __notc, __notl, __notf)
- bool系は !=0 なら AccAB=1,Z=0 、==0 なら AccAB=0,Z=0 を返す。Z flagを立てるのに注意。Z壊れやすいのでCの方が良かったか?
- 左項をpsh、右項をAccA,B,@highに入れて、演算サブルーチンコール。スタックは呼ばれた側が捨てる
- jsr __ccxx (xxはeq,neなど。unsigned/char/long/floatなどは末尾に u,c,l,fなどが付く)
- 条件が成立したら AccAB=1,Z=0, 成立しなければ AccAB=0,Z=1 を返す。こちらもZ flagを立てるのに注意
- この両方を同一の関数で行っているので、optimizeがしづらい
- optimizeできそうなのは、if(関係演算式)と for, while ぐらいか。それだけでも効果は大きそうではあるが
条件判断
- 上記のboolかccを呼んだ後に、jeq/jneで判断。jxxは分岐の距離に応じてbxxかbyy+jmpに変換される。便利
- 関係演算を || && で繋ぐと、連鎖が起こるので、安易にoptimizeできない(jeq/jne以外が使えない)
- 結果が0,1であることを利用するパターンもあるので変更は無理っぽい
- (分岐のための判断と、計算のための判断を分ければなんとかなる。if(関係演算式)のような場合はoptimizeしたくなる
ディスカッション
コメント一覧
まだ、コメントがありません