Fuzix-Compiler-Kitの6800用コンパイラ(4)(ベーシックマスター開発 その36)

BASICMASTER, 昔のパソコン

コンパイラが生成するオブジェクト(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( 式 ) など
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を立てるのに注意
関係演算子を値として使う場合は、そのままAccABを使う。条件分岐の場合はZを見る
この両方を同一の関数で行っているので、optimizeがしづらい
optimizeできそうなのは、if(関係演算式)と for, while ぐらいか。それだけでも効果は大きそうではあるが

条件判断

  • 上記のboolかccを呼んだ後に、jeq/jneで判断。jxxは分岐の距離に応じてbxxかbyy+jmpに変換される。便利
  • 関係演算を || && で繋ぐと、連鎖が起こるので、安易にoptimizeできない(jeq/jne以外が使えない)
  • 結果が0,1であることを利用するパターンもあるので変更は無理っぽい
  • (分岐のための判断と、計算のための判断を分ければなんとかなる。if(関係演算式)のような場合はoptimizeしたくなる


リンク