パスワードを忘れた? アカウント作成
13970972 journal
日記

yasuokaの日記: Z80における定数10の除算は、商と余りのどちらを先に求めるべきか 5

日記 by yasuoka

ここ数日の日記(これこれこれ)で、Z80で100未満の数値を10で除算処理するというのに挑戦してみた。Bレジスタに0~99の整数が入っている時に、10で除算した商をHレジスタに、余りをAレジスタに返す、という問題なのだが、ここまでに私(安岡孝一)が検討した結果を、とりあえず、まとめておこうと思う。まずは、商を51/512で求めて、その後に余りを求める手法。

78      LD A,B
0F    RRCA
0F    RRCA
0F    RRCA
0F    RRCA
E6 0F  AND 0FH
3C     INC A
80     ADD B
4F      LD C,A
81     ADD C
81     ADD C
17     RLA
17     RLA
17     RLA
17     RLA
E6 0F  AND 0FH
67      LD H,A
87     ADD A
87     ADD A
84     ADD H
2F     CPL
07    RLCA
88     ADC B

25バイト98ステート、といったところだろうか。私個人としては、まずまずの速さだと思う。一方、余りをDAAで先に求めて、その後に商を求める方法。

78      LD A,B
0F    RRCA
0F    RRCA
0F    RRCA
27     DAA
87     ADD A
27     DAA
4F      LD C,A
78      LD A,B
E6 07  AND 07H
91     SUB C
27     DAA
E6 0F  AND 0FH
4F      LD C,A
78      LD A,B
91     SUB C
67      LD H,A
0F    RRCA
94     SUB H
94     SUB H
E6 0F  AND 0FH
67      LD H,A
79      LD A,C

26バイト101ステート、といったところだろうか。計算間違いでなければ、商を先に求める方が、ほんの少し早い気がする。ただ、この程度の差だと、ほんのひとチューニングで簡単にひっくり返る。何か、いいアイデア、ないかなぁ。

この議論は、yasuoka (21275)によって ログインユーザだけとして作成されたが、今となっては 新たにコメントを付けることはできません。
  • by uratan (26577) on 2019年07月31日 21時25分 (#3661456) ホームページ 日記

    >商を51/512で求めて

    7行目 INC A の分、3/32 が暗黙のうちに加算されていますね?

    # そして後半を読み解く元気はない…

  • 0~99の数値Aの10での余りは、Aを8での商と余りの
    二つにわけて、各々の10での余りを加算すればいい
     A   =(A/8)*8 + (A%8)
     A%10=((A/8)*8)%10 + (A%8)%10
          (この加算で10を越えたらもう一度余りを…)

    DAAでは(ざっくり)0~15の連続数が0~9、16~21に
    分断される、これを使って割る10をうまいこと振り分けて・・・?


    組み合わせて 余りを求めているのではないか? までわかった、つもり。

    で、

    (A/8)を足してはDAA、足してはDAAで8回足し、
    最後に(A%8)を足してDAAすれば、
    Aに二進化10進で商と余りがペアで入る、
    (56→0x56になる)ような気がする、
    けど極端に短くはなりませんでした。
     (商と余りの分割もクロック喰うし)

    というところで勘弁してください。

    p.s.
     INC A ... は二つ前の日記で触れてありましたね。

    • ちょっとだけ改良できてしまいました。よければ今日の私(安岡孝一)の日記 [srad.jp]をどうぞ。
      親コメント
    • p.s.
       足してはDAA足してはDAA…は一つ前の日記に書いてありましたね。
       (他の考察も)

       -*-*-

      DAA は鬼門なんですよ…。

      以下、私が今をさること25年ぐらい前に書いた
      Z80シミュレータの DAA の部分です。(たぶん間違っている)

      int ans, half_ans, dst;
      u_char data;

      case 0x27:
      #ifdef DEBUG
              fprintf(stdout, "DAA ");
      #endif /* DEBUG */
              data = 0x00;
              if(((reg.sing.A & 0xf) > 9) || (reg.flag.H==1)) {
                      data = 0x06;
              }
              if((reg.sing.A > 0x90) || (reg.flag.C==1)) {
                      data |= 0x60;
              }
              if(reg.flag.N==0) {
                      half_ans = (reg.sing.A & 0x0f) + (data & 0x0f);
                      reg.sing.A = ans = reg.sing.A + data;
              } else {
                      half_ans = (reg.sing.A & 0x0f) - (data & 0x0f);
                      reg.sing.A = ans = reg.sing.A - data;
              }
              reg.flag.H = half_ans >> 4;
              reg.flag.C |= ans >> 8; /* is it true ??? */
              reg.flag.S = reg.sing.A >> 7;
              reg.flag.Z = (reg.sing.A==0);
              reg.flag.P = parity(reg.sing.A);
              return(D_OK);

      本や解説書には「二進化10進の補正をします」ぐらいしか書いてなくて、
      想像と実機でちょろっと確認したぐらいで、書いたものです。
      加算を一度しかやっていないので、0x89 + 0x11 → DAA が
      0x00 にならないからたぶん間違っているんじゃないかなぁ…。

      親コメント
typodupeerror

ナニゲにアレゲなのは、ナニゲなアレゲ -- アレゲ研究家

読み込み中...