MC6800のプログラミングテクニック(18) BYTE SAVING PROGRAMMING TRICKS FOR THE 8080
Dr. Dobb’s Journal という、書名だけでは内容がわからないマイコン雑誌があった。一時期は日本語版も発売されていた。プログラミングテクニックが掲載されていて、私も参考にしたものだ。
さて、その DDJ誌に “BYTE SAVING PROGRAMMING TRICKS FOR THE 8080” というTom Pittman氏の記事があった(June/July 1976, P.9-10)。
題名の通り 8080でのプログラミングテクニックの記事だが、6800でも参考になるので紹介する。
Carry を1byteに拡張
1バイトのsigned charを、2バイトintに符号拡張したい場合、charのb7に応じて上位バイトを$00または$FFにする必要がある。そのときに使えるテクニック。
8080では、レジスタ-レジスタ間の演算ができるが、両方ともAレジスタを指定することができる。
SBBは Areg – reg – Carry という命令で、SBB Aとすることで、A-A-C、つまり $00-C が計算できる。Carryが立っていれば A=$FF, C=0 なら A=$00 である。便利。
For 2’s complement signed arithmetic, it is some¬ times necessary to add a signed 1-byte number to a larger format. There are also other reasons for spreadingasingle bit (in the Carry FF) to a whole byte (in A). I found this one in the Scelbi book:
SBB A Copy carry to all bits in A
“BYTE SAVING PROGRAMMING TRICKS FOR THE 8080”, Dr. Dobb’s Journal, June/July 1976, P.9
つい最近、6800でAccABの右15bitシフトを高速化できないか考えた。unsignedなら簡単。8cyc, 4bytes。 Carry経由でAccAのb7を AccBのb0に移動する。
clrb asla rolb clra
問題はsignedのときだ。素直に書くと asra / rolb を15回繰り返すのだが、そんなことはやってられない。最初をtabにする手もあるが、焼け石に水である。
8080のように、0-C の操作ができれば良いのだが、1命令では残念ながら不可能。clrb と sbcb #0 が必要になる。
clrb asla sbcb #0 tba
応用として、signedの右14bitシフト。Carryフラグを壊さないようにコードを並べる必要がある。右シフトなのに、左シフト命令しか出てこないのが面白い。
clrb asla sbcb #0 asla tba rolb
Carryをb7に移動する
Aregのb7をCarryで置き換える。8080のRLC/RRCはb7とb0を直接つないで回転(Rotate)できるので、こんなトリックが使える。
To insert a single bit (in the Carry) into the left or right end of the A without altering the other seven bits:
RAL Remove old left bit
RRC Insert new from Carry“BYTE SAVING PROGRAMMING TRICKS FOR THE 8080”, Dr. Dobb’s Journal, June/July 1976, P.9
6800のRotate/Shiftは 必ずCを経由するので、同等機能を考えるのは難しい。Bを壊して良いなら、こうだ。
長くてダサいなあ。Aの操作にasla/roraは絶対必要だし、Cをどこかに保存しないといけないので、これが最短だと思う。
rolb asla rorb rora
b7をcarryにコピー
符号拡張に使うために、b7をCにコピーしたい場合がある。8080には算術右シフトがないので、その準備に使う。
The right-end version is symmetrical. To divide a signed (2’s complement) number in half, it is necessary to keep the sign bit (bit 7) unchanged while shifting A right. The 8080 does not have an instruction for this, but the RAR may be used if the Carry can bet set up to match the sign bit:
RLC Copy bit 7 to Carry
RRC Restore A“BYTE SAVING PROGRAMMING TRICKS FOR THE 8080”, Dr. Dobb’s Journal, June/July 1976, P.9
6800だと、算術右シフトがあるので、簡単。これはDDJ記事でも紹介されている。
The 6800 has a single instruction for signed right shifts, but no circular rotate. To copy a sign into the Carry:
ASR A (6800) Duplicate bit 7
ROL A Restore A with bit 7 in Carry“BYTE SAVING PROGRAMMING TRICKS FOR THE 8080”, Dr. Dobb’s Journal, June/July 1976, P.9
Aが0でなければCを立てる/Aが0ならCを立てる
任意の条件でCを操作できると便利。A!=0 なら Cを立てる、あるいはその逆を行う。
A zero in A may be converted into either a one or a zero in the Carry (so that non-zero is the reverse) by one of the following instructions (this also works in the 6800 with appropriate opcode sub¬stitutions):
ADI 0FFH C=0 if and only if A=00
SUI 1 C=1 if and only if A=00“BYTE SAVING PROGRAMMING TRICKS FOR THE 8080”, Dr. Dobb’s Journal, June/July 1976, P.9
記事にあるように6800でも簡単。 adda #$FF または suba #1 である。前者はnegaが短いし、後者は cmpa #1 の方が Aが壊れなくて良いかもしれない。前者もAを壊したくなければ、nega 2回。
b7の反転をCに入れる
$80を引くだけ。$80以上ならC=0だし、$7F以下ならC=1になる。これは6800でもcmpa #$80で良い。
It is easy to get the sign of A into the Carry (any left shift will do); to get the complement of the sign is a little trickier. This instruction leaves the contents of A unchanged, and also works for the 8080:
CP! 8OH Complement bit 7 to Carry
“BYTE SAVING PROGRAMMING TRICKS FOR THE 8080”, Dr. Dobb’s Journal, June/July 1976, P.9
Bregの特定のbitを、Aregにコピーする
C言語のbit fieldを実装するときに欲しくなるやつ。単純にやると、コピー元を mask でandして、コピー先を ~mask でクリアして、両方を or する手順になる。面倒くさい。
以下の手順なら3命令だ。素晴らしい。
Assume that the data in A and B (or any other register or memory location) are already in the correct bit positions. The mask represents a byte with the ones where the data in A is to be substituted; the non-data bits of A and B may contain garbage, as they are ignored:
XRA B XOR B to A data bits
ANI Mask Delete A garbage
XRA B Insert B data“BYTE SAVING PROGRAMMING TRICKS FOR THE 8080”, Dr. Dobb’s Journal, June/July 1976, P.9
6800にはレジスタ間論理演算命令がないので、対象はメモリになる。こんな感じ。eora mem anda #mask eora mem
言葉だけだとわかにくいので表も付いていた。昔の雑誌は親切だ。
“BYTE SAVING PROGRAMMING TRICKS FOR THE 8080”, Dr. Dobb’s Journal, June/July 1976, P.10これは、実際にchibicc-6800-v1のbitfieldで使った。
; x1.a = 1; (中略) ; bitfieled node->ty->size=2, mem->bit_width=1, mem->bit_offset=0, codegen.c 3780 andb #<$01 clra eorb 1,x eora 0,x andb #<$01 clra eorb 1,x eora 0,x stab 1,x staa 0,x
ディスカッション
コメント一覧
まだ、コメントがありません