Tree Generation Part 式と型を表す2種類の中間木 list2, list3, list4 などで作られる 型 INT CHAR UNSIGNED POINTER ARRAY STRUCT UNION FUNCTION EMPTY 式 変数を表すノード (変数のoffset付き) GVAR RGVAR CRGVAR LVAR RLVAR CRLVAR 定数を表す (値付き) CONST 関数名 (名前付き) FNAME 式の間接参照(indirect = *) INDIRECT RINDIRECT CRINDIRECT 式のアドレス( = &) ADDRESS Unary operator (単項演算子) MINUS LNOT BNOT INC POSTINC PREINC CPOSTINC CPREINC DEC CPOSTDEC CPREDEC Binary operator (2項演算子) MUL UMUL DIV UDIV MOD UMOD ADD SUB RSHIFT URSHIFT LSHIFT ULSHIFT BAND EOR BOR LAND LOR Relational operator (比較演算子) GT UGT GE UGE LT ULT LE ULE EQ NEQ 3項演算子 (?:) COND COLON Assignment (代入) ASS CASS ASSOP CASSOP Comma (逐次演算) COMMA 条件文のコード生成 do_if() など bexpr() リターン文のコード生成 doreturn() return2() ret() unlink() goto文 dogoto() jmp() 左辺値への木の変更 rvalue() 左辺値かどうかのチェック lcheck() indrect の木の変更 expr13() indop(e) 構造体の木の生成 expr16() strop() rvalue() 2項演算子の木の生成 (定数の計算などを含む) binop() アドレスの足し算等もここで木を生成する bexpr() 条件分岐のコード生成 rexpr() jcond() rexpr() 引き算して条件分岐するのコード生成 jcond() EQ/NE での条件分岐 jmp() 分岐 fwdlabel() 新しい forward label の参照 fwddef(l) forward labelの定義 backdef() 直前に定義したラベルの定義 gexpr() 式のコード生成 GVAR: leaxy(e2); RGVAR: lddy(e2); CRGVAR: ldby(e2); sex(); LVAR: leaxu(e2); RLVAR: lddu(e2); CRLVAR: ldbu(e2); sex(); FNAME: leaxpcr() tfrxd(); CONST: lddim() (0 だったら clrd()) STRING: string(e1); FUNCTION: function(e1); INDIRECT: indirect(e1); RINDIRECT: CRINDIRECT: rindirect(e1); ADDRESS: gexpr(e2); tfrxd(); MINUS: NEGA NEGB SBCA BNOT: COMA COMB PREINC: GVAR: LVAR: ldd(e2); adddim(caddr(e1)); std(e2); default: gexpr(e2); lddx(); adddim()); stdx(); POSTINC: GVAR: LVAR: ldd(e2); adddim() std(e2); subdim(e3); default: gexpr(e2); lddx(); adddim() stdx(); subdim(e3); CPOSTINC: gexpr(e2); ldbx(); incx(); sex(); CPREINC: gexpr(e2); incx(); ldbx(); sex(); CPOSTDEC: gexpr(e2); ldbx(); decx(); sex(); CPREDEC: gexpr(e2); decx(); ldbx(); sex(); MUL: UMUL: 定数の場合はいろいろ工夫する (asld() など) DIV: UDIV: MOD: UMOD: LSHIFT: ULSHIFT: RSHIFT: URSHIFT: binexpr(e1); ADD: SUB: BAND: EOR: BOR: machinop(e1); COND: ?: のコード生成 bexpr() ASS: case CASS: assign(e1); ASSOP: CASSOP: assop(e1); COMMA: default: 式の値によって 1,0 を返す string() 文字定数 "abc" などのコード生成 function(e1) 関数呼び出しのコード生成 最初に引き数を積む FNAME: leaxpcr(n); pushx(); ADDRESS: gexpr(e5); pushx(); default: gexpr(e4); pushd(); FNAME ならば LBSR する そうでなければ JSR ,X する 最後にスタックをたたむ printf("\tLEAS\t%d,S\n",2*nargs); indirect(e1) 間接参照のコード生成 RGVAR: RLVAR: ldx(e2); ADD: ADDRESS opdx("LEAX"); RGVAR: RLVAR: gexpr(e3); ldx(e4); opdx("LEAX"); default: gexpr(e2); tfrdx(); machinop(e1) RGVAR: RLVAR: CONST: gexpr(e2); oprt(car(e1),e3); default: gexpr(e3); pushd(); gexpr(e2); tosop(car(e1)); rindirect(e1) 間接参照の右辺値 最後にLDB or LDD を生成する RGVAR: RLVAR: indir(op,e2); sextend(byte); ADD: ADDRESS opdx(op); sextend(byte); RGVAR: RLVAR: gexpr(e3); ldx(e4); opdx(op); sextend(byte); CONST: RGVAR: RLVAR: ldx(e3); indexx(op,cadr(e4)); sextend(byte); default: gexpr(e3); pushd(); gexpr(e4); pulx(); opdx(op); sextend(byte); PREINC: 1,2の場合は特別扱い GVAR: LVAR: ldx(e3); predecx(op,l); stx(e3); sextend(byte); POSTINC: 1,2の場合は特別扱い {GVAR: LVAR: ldx(e3); postincx(op,l); stx(e3); sextend(byte); default: gexpr(e2); tfrdx(); indexx(op,0); sextend(byte); assign(e1) 代入文 STB STD を生成する {GVAR: LVAR: gexpr(e4); index(op,e2); INDIRECT: RGVAR: RLVAR: gexpr(e4); indir(op,e3); ADD: 定数の場合は gexpr(e4); ldx(e5); indexx(op,cadr(caddr(e3))); PREINC: 1,2の場合は特別扱い GVAR: LVAR: gexpr(e4); ldx(e5); predecx(op,l); stx(e5); POSTINC: 1,2の場合は特別扱い GVAR: LVAR: gexpr(e4); ldx(e5); postincx(op,l); stx(e5); RGVAR: CRGVAR: RLVAR: CRLVAR: CONST: この場合はスタックを使わずに左辺値を計算出来る gexpr(e2); gexpr(e4); default: 普通はできないのでDをスタックに積んでから左辺値を計算する gexpr(e4); pushd(); gexpr(e2); pulld(); 最後に STD, STB を生成する indexx(op,0); assop(e1) 演算代入文 += など LDB,LDD して計算そしてSTB,STD GVAR: LVAR: 右辺が変数 RGVAR: RLVAR: CONST: 左辺も右辺も変数か定数で簡単な演算 index(ldop,e2); sextend(byte); oprt(op,e3); index(stop,e2); default: gexpr(e3); pushd(); index(ldop,e2); sextend(byte); tosop(op); index(stop,e2); default: 右辺はもっと複雑 RGVAR: RLVAR: CONST: 右辺は変数か定数で簡単な演算 gexpr(e2); indexx(ldop,0); sextend(byte); oprt(op,e3); indexx(stop,0); default: gexpr(e3); pushd(); gexpr(e2); indexx(ldop,0); sextend(byte); tosop(op); indexx(stop,0); simpop(op) 6809で一命令で計算出来る ADD SUB BAND EOR BOR oprt(op,e1) oprt1() oprtc() oprt1(op,index,n) index mode での計算 dualop(op,index,n) byte 毎に計算する index mode での計算 oprtc(op,n) 定数演算 dualc(op,n) byte 毎に計算する 定数演算 tosop(op) stackとの演算 (一つスタックを片づける) ADD: addds(); SUB: subds(); BAND: EOR: BOR: dualtosop(op); default: pulx(); library(op); dualtosop(op) byte 毎に計算する stackとの演算 (一つスタックを片づける) ldd(e) D register へのload GVAR: lddy(cadr(e)); LVAR: lddu(cadr(e)); std(e) D register のstore GVAR: stdy(cadr(e)); LVAR: stdu(cadr(e)); ldx(e) X register への load GVAR: RGVAR: ldxy(cadr(e)); LVAR: RLVAR: ldxu(cadr(e)); stx(e) X register の store GVAR: stxy(cadr(e)); LVAR: stxu(cadr(e)); index(op,e) Index register へのload/store GVAR: indexy(op,cadr(e)); LVAR: indexu(op,cadr(e)); indir(op,e) 間接 RGVAR: indiry(op,cadr(e)); RLVAR: indiru(op,cadr(e)); sextend(byte) 符号拡張(byteのみ) binexpr(e1) ライブラリを使う演算 gexpr(caddr(e1)); pushd(); gexpr(cadr(e1)); pulx(); library(car(e1)); library(op) ライブラリの呼び出し MUL UMUL DIV UDIV MOD UMOD LSHIFT ULSHIFT RSHIFT URSHIFT