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が大域変数を指し示している。