6809 Simulator V09,
By L.C. Benschop, Eidnhoven The Netherlands.
/usr/open/lectures/kono/compiler/util09/v09.c
は、非常に簡単な構造をしている。
/* 6809 registers */ Byte ccreg,dpreg; Word xreg,yreg,ureg,sreg,ureg,pcreg; Byte d_reg[2]; Word *dreg=(Word *)d_reg; /* 6809 memory space */ static Byte mem[65536];という形で、MC6809のレジスタをCのプログラムとして持っている。
main()では、以下のようにMC6809の命令を実行(execute)する。
for(;;){ ireg=mem[pcreg++]; /* Fetech 1 instruction */ (*instrtable[ireg])(); /* call a procedure for the instruction */ }(実際のプログラムではtraceなどが入っているので、もっと複雑) instrtable には、Cのfunctionが一覧表になっている。
int (*instrtable[])() = { neg , ill , ill , com , lsr , ill , ror , asr , asl , rol , dec , ill , inc , tst , jmp , clr , flag0 , flag1 , nop , sync , ill , ill , lbra , lbsr , ill , daa , orcc , ill , andcc , sex , exg , tfr , bra , brn , bhi , bls , bcc , bcs , bne , beq , bvc , bvs , bpl , bmi , bge , blt , bgt , ble , leax , leay , leas , leau , pshs , puls , pshu , pulu , ill , rts , abx , rti , cwai , mul , ill , swi , neg , ill , ill , com , lsr , ill , ror , asr ,これは表の一部である。同じ命令(instruction)があるのは、たま たま同じcodeが同じ命令だったり、その関数の中でさらに細かく処理が 分かれたりする。
例えば、neg は、2の補数(2's complement)として 符号を変える演算だが、(nega だったら a = -a )
neg() { Byte *ea; Word a,r; a=0; ea=eaddr0(); a=*ea; r=-a; SETSTATUS(0,a,r) *ea=r; }となっている。ここで、eaddr0() は、オペランド(operand)を計算する 関数(function)である。これは、
Byte * eaddr0() /* effective address for NEG..JMP as byte poitner */ { switch( (ireg & 0x70) >> 4) { case 0: return mem+zeropage(); case 1:case 2:case 3: return 0; /*canthappen*/ case 4: return areg; case 5: return breg; case 6: return mem+postbyte(); case 7: return mem+direct(); } }などとなっている。MC6809には豊富なアドレッシングモード(addressing mode) があり、zeropage, postbye, direct などがそれを示している。例えば、
NEGA レジスタAのnegativeを取る (inherent/areg,breg) NEG <$80 Direct page $80のnegative を取る (zeropage) NEG $8000 Meomry $8000 のnegative を取る (direct) NEG ,X Index register X の指すmemoryのnegativeを取る (index/postbyte)Indexにはpostbyteで指定されるのだが、さらにいろいろなものを使うことが できる。
NEG 5,X X + 5 が指すmemoryのnegativeを取る NEG ,X+ X が指すmemoryのnegativeを取る、そして X を一つ進める NEG ,-X Xを一つ減らしてkら、X が指すmemoryのnegativeを取る NEG A,X X + A が指すmemoryのnegativeを取る NEG D,X X + D が指すmemoryのnegativeを取る NEG [5,X] X + 5 が指すmemoryの中身が指すmemory のnegativeを取るpostbyteの処理は少し複雑なので、ここでははぶこう。良く使う ,X や、5,X などは短くcodingされ、1000,Xなどは長くcodingされるように工夫されている。
0100: 23 0101: 45 0102: 56 0103: 78 5678: 01 5679: 02 567a: 03 567b: 04 7856: 05 7857: 06 7858: 07 7859: 08
int a,b; main() { a = a+1-(b-123); return a; }これを /usr/open/lectures/kono/compiler/mc/mc でコンパイルしてみると、
a EQU 0 b EQU 2 main PSHS U # function call LEAU ,S # local variable の場所を取る LDD 2,Y # b を D に入れる SUBD #123 # それから 123 を引く(sub) PSHS D # D をstackに積む LDD 0,Y # a を D に入れる ADDD #1 # それに 1 を足す(add) SUBD ,S++ # それからstackにつんだものを引く STD 0,Y # それをaに入れる LDD 0,Y # a の値を main() の値として返す。 PULS U,PC _1 RTS _INITIALIZE EQU _1 _GLOBALS EQU 4 ENDとなる。Sがstackであり、Yが大域変数を指し示している。