MC6800のプログラミングテクニック(19) AccABと0の比較
Amsterdam Compiler Kit の生成する中間言語(EM code)では、Top of Stack と0を比較し、ToSに0,1を入れる命令がある。
tlt,tle,teq,tne,tge,tgt がそれだ。6800では ToSはAccABに持つので、要するにAccABと0を比較して、AccABに0か1を入れれば良い。
どうするのが良いか考えてみよう。
tne命令 (AccAB!=0なら、AccAB=1)
AccABが0かどうかは、aba / adca #0 で わかる。AccAB=0 なら、AccA=0, Z=1 になり、AccAB!=0 なら AccA!=0, Z=0 になる。
negaはAccA=0ならC=0, AccA!=0ならC=1である。
組み合わせて下記のコードになる。12cycle, 7bytes。
aba adca #0 clrb nega rolb clra
素直に分岐で書くとこうなる。AccAB=0のときは何もしない。10 or 12cycle, 10bytes。
tstb bne true tsta beq false true: ldab #1 clra false:
teq命令 (AccAB==0なら、AccAB=1)
tneと逆の命令である。teqと同じ発想で書いてみる。suba #1で、AccA==0のときだけC=1にする。negがsuba #1になった分だけ長くなる。
12cycle, 8bytes。
aba adca #0 clrb suba #1 rolb clra
素直に分岐で書くとこうなる。バイト数を数える気が起こらないほど長い。bra nextの代わりに、fcb $85 (bita #)を書いて1バイト縮める技もあるが、現代風じゃないよな。
10 or 16 or 18cycles, 11bytes。
tstb bne false tsta bne false true: incb bra next: false: clrb clra next:
tlt命令 (AccAB<0なら、AccAB=1)
AccAB<0 かどうかは、AccAのbit7でわかる。bit7==1ならAccB=1, bit7==0ならAccB=0にすれば良い。 シフト・ローテート命令でAccAのbit7を、AccBのbit0に移動するだけである。 8cycle, 4bytes.
clrb asla rolb clra
tge命令 (AccAB>=0なら、AccAB=1)
tltとは逆にAccAのbit7の反転を AccBのbit0に移動する必要がある。Cの反転命令があると良いのだが(8080にはあるのに!)、無い袖は触れないのでeorで反転する。
eor命令の分だけ長くなった。10cycle, 6bytes.
clrb eora #$80 asla rolb clra
tgt命令 (AccAB>0なら、AccAB=1)
gt/le は、AccBの状態も見ないといけないので厄介である。素直に分岐で書くとこうなる。長いなあ。10 or 18 or or 24 cycle, 15bytes.
bne true / tstb / beq false2 は、 aba / adca #0 / beq false が良いか?
tsta bgt true blt false tstb beq false2 true: ldab #1 clra bra next false: clrb false2: clra next:
tle命令 (AccAB<=0なら、AccAB=1)
tgtとほぼ同じ。10 or 18 or or 24 cycle, 15bytes.
tsta blt true bgt false tstb bne false true: ldab #1 clra bra next false: clrb false2: clra next:
tgt、tle はなんとかならんかな。
符号を反転して(nega / negb / sbca #0)、tlt / tge に変換する方法を思いついたが、6cycle, 4bytes増えるので、14cyc, 8byte と 16cycle, 10bytesになる。
分岐よりはマシだが長いなあ。
ディスカッション
コメント一覧
まだ、コメントがありません