非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

X68000(26)

線を描画する関数をコンパイルした結果をインラインアセンブラに取り込んだものを作成しました。「関数電卓コマンド版(3) - 非専門的シンギュラリティー研究所」の乗算・除算のコードを使っています。そのままでは動かなかったので変数をスタックで渡さず変数の領域を確保してそこに値を設定する方法に変更しました。正しいやり方とは思えませんがいったんこれで良いものとします。

2025年にやることではないとは思うのですが、サンプルが探しても見つからないので自分で作っていきます。IOCS ではできないこともあるのでやっておくと後で役に立つ予定です。

コンパイルした結果を修正した関数

// 変数をスタックで渡さず変数の領域を確保してそこに値を設定する方法に変更
asm(
        "dlx36: dc.l 0\n\t"
        "dlx40: dc.l 0\n\t"
    "drawlinex_a:\n\t"
        "move.l  dlxx1, %d4\n\t" // d4 = x1
        "move.l  dlxy1, %d3\n\t" // d3 = y1
        "move.l  dlxx2, %d1\n\t" // d1 = x2
        "move.l  dlxy2, %d0\n\t" // d0 = y2
        "move.w  dlxcolor, %a4\n\t" // a4 = color
        "move.l  %d1, %d5\n\t" // d5 = x2
        "sub.l   %d4, %d5\n\t" // d5 = x2 - x1
        "move.l  %d0, %a3\n\t" // a3 = y2
        "sub.l   %d3, %a3\n\t" // a3 = y2 - y1  
        "move.l  %a3, %d6\n\t" // d6 = y2 - y1
        "jpl     dlxL4\n\t" // y2 - y1 >= 0
        "neg.l   %d6\n\t" // d6 = -(y2 - y1)
    "dlxL4:\n\t"
        "move.l  %d5, %d2\n\t" // d2 = x2 - x1
        "jpl     dlxL5\n\t" // x2 - x1 >= 0
        "neg.l   %d2\n\t" // d2 = -(x2 - x1)
    "dlxL5:\n\t"
        "lea     shift_multiply_a, %a5\n\t" // shift_multiply_aのアドレスをa5に設定
        "cmp.l   %d6, %d2\n\t" // y2 - y1 と x2 - x1 を比較
        "jle     dlxL3\n\t" // y2 - y1 <= x2 - x1 の場合
        "tst.l   %d5\n\t" // x2 - x1 が0かどうかをチェック
        "jlt     dlxL13\n\t" // x2 - x1 < 0 の場合
        "moveq   #1, %d7\n\t" // d7 = 1
    "dlxL6:\n\t"
        "move.l  %d1, -(%sp)\n\t" // スタックにx2を保存
        "move.l  %d7, -(%sp)\n\t" // スタックにd7を保存
        "jsr     (%a5)\n\t" // shift_multiply_aを呼び出す
        "addq.l  #8, %sp\n\t" // スタックを8バイト戻す
        "move.l  %d0, dlx36\n\t" // スタックにy2を保存
        "move.l  %d4, -(%sp)\n\t" // スタックにx1を保存
        "move.l  %d7, -(%sp)\n\t" // スタックにd7を保存
        "jsr     (%a5)\n\t" // shift_multiply_aを呼び出す
        "addq.l  #8, %sp\n\t" // スタックを8バイト戻す
        "move.l  %d0, %d6\n\t" // d6 = y2 - y1 の結果を保存
        "move.l  %a3, -(%sp)\n\t" // スタックにy2 - y1を保存
        "move.l  %d7, -(%sp)\n\t" // スタックにd7を保存
        "jsr     (%a5)\n\t" // shift_multiply_aを呼び出す
        "addq.l  #8, %sp\n\t" // スタックを8バイト戻す
        "move.l  %d0, dlx40\n\t" // スタックにx2 - x1の結果を保存
        "sub.l   %a3, %a3\n\t" // a3 = y2 - y1 の結果を0にする
        "move.l  #0xc00000, %a5\n\t" // GraMemのアドレスをa5に設定
        "lea     shift_divide_a, %a6\n\t" // shift_divide_aのアドレスをa6に設定
    "dlxL7:\n\t"
        "cmp.l   dlx36, %d6\n\t" // スタックのy2とd6を比較
        "jlt     dlxL8\n\t" // y2 < d6 の場合
    "dlxL2:\n\t"
        "rts\n\t" // 戻り値を返す
    "dlxL13:\n\t"
        "moveq   #-1, %d7\n\t" // d7 = -1
        "jra     dlxL6\n\t" // dlxL6にジャンプ
    "dlxL8:\n\t"
        "move.l  %d5, -(%sp)\n\t" // スタックにx2 - x1を保存
        "move.l  %a3, -(%sp)\n\t" // スタックにy2 - y1を保存
        "jsr     (%a6)\n\t" // shift_divide_aを呼び出す
        "addq.l  #8, %sp\n\t" // スタックを8バイト戻す
        "add.l   %d3, %d0\n\t" // d0 = y2 - y1 + y1
        "moveq   #9, %d1\n\t" // d1 = 9
        "lsl.l   %d1, %d0\n\t" // d0 = (y2 - y1 + y1) * 512
        "add.l   %d4, %d0\n\t" // d0 = x1 + (y2 - y1 + y1) * 512
        "add.l   %d0, %d0\n\t" // d0 = x1 + (y2 - y1 + y1) * 512 * 2
        "move.w  %a4, (%a5, %d0.l)\n\t" // GraMemに色を設定
        "add.l   %d7, %d4\n\t" // x1 = x1 + d7
        "addq.l  #1, %d6\n\t" // d6 = y2 - y1 + 1
        "add.l   dlx40, %a3\n\t" // y2 - y1 = y2 - y1 + x2 - x1
        "jra     dlxL7\n\t" // dlxL7にジャンプ
    "dlxL3:\n\t"
        "cmp.w   #0, %a3\n\t" // y2 - y1 が0かどうかをチェック
        "jlt     dlxL14\n\t" // y2 - y1 < 0 の場合
        "moveq   #1, %d6\n\t" // d6 = 1
    "dlxL9:\n\t"
        "move.l  %d0, -(%sp)\n\t" // スタックにy2を保存
        "move.l  %d6, -(%sp)\n\t" // スタックにd6を保存
        "jsr     (%a5)\n\t" // shift_multiply_aを呼び出す
        "addq.l  #8, %sp\n\t" // スタックを8バイト戻す
        "move.l  %d0, dlx36\n\t" // スタックにy2を保存
        "move.l  %d3, -(%sp)\n\t" // スタックにy2 - y1を保存
        "move.l  %d6, -(%sp)\n\t" // スタックにd6を保存
        "jsr     (%a5)\n\t" // shift_multiply_aを呼び出す
        "addq.l  #8, %sp\n\t" // スタックを8バイト戻す
        "move.l  %d0, %d7\n\t" // d7 = y2 - y1 の結果を保存
        "move.l  %d5, -(%sp)\n\t" // スタックにx2 - x1を保存
        "move.l  %d6, -(%sp)\n\t" // スタックにd6を保存
        "jsr     (%a5)\n\t" // shift_multiply_aを呼び出す
        "addq.l  #8, %sp\n\t" // スタックを8バイト戻す
        "move.l  %d0, dlx40\n\t" // スタックにx2 - x1の結果を保存
        "moveq   #9, %d0\n\t" // d0 = 9
        "lsl.l   %d0, %d6\n\t" // d6 = (y2 - y1 + y1) * 512
        "move.l  %d3, %d5\n\t" // d5 = y2 - y1
        "lsl.l   %d0, %d5\n\t" // d5 = (y2 - y1 + y1) * 512
        "moveq   #0,  %d3\n\t" // d3 = 0
        "move.l  #0xc00000, %a5\n\t" // GraMemのアドレスをa5に設定
        "lea     shift_divide_a, %a6\n\t" // shift_divide_aのアドレスをa6に設定
    "dlxL10:\n\t"
        "cmp.l   dlx36, %d7\n\t" // スタックのy2とd7を比較
        "jge     dlxL2\n\t" // y2 >= d7 の場合
        "move.l  %a3, -(%sp)\n\t" // スタックにy2 - y1を保存
        "move.l  %d3, -(%sp)\n\t" // スタックにd3を保存
        "jsr     (%a6)\n\t" // shift_divide_aを呼び出す
        "addq.l  #8, %sp\n\t" // スタックを8バイト戻す
        "move.l  %d5, %d1\n\t" // d1 = x2 - x1 の結果を保存
        "add.l   %d4, %d1\n\t" // d1 = x1 + (y2 - y1 + y1) * 512
        "add.l   %d1, %d0\n\t" // d0 = x1 + (y2 - y1 + y1) * 512 * 2
        "add.l   %d0, %d0\n\t" // d0 = x1 + (y2 - y1 + y1) * 512 * 2 * 2
        "move.w  %a4, (%a5, %d0.l)\n\t" // GraMemに色を設定
        "addq.l  #1, %d7\n\t" // d7 = y2 - y1 + 1
        "add.l   dlx40, %d3\n\t" // y2 - y1 = y2 - y1 + x2 - x1
        "add.l   %d6, %d5\n\t" // d5 = y2 - y1 + (y2 - y1 + y1) * 512
        "jra     dlxL10\n\t" // dlxL10にジャンプ
    "dlxL14:\n\t"
        "moveq   #-1, %d6\n\t" // d6 = -1
        "jra     dlxL9\n\t" // dlxL9にジャンプ
);

上記の関数を呼び出すための関数

// 変数をスタックで渡さず変数の領域を確保してそこに値を設定する方法に変更
void drawlinex(int x1, int y1, int x2, int y2, COLORREF color)
{
    asm(
        "move.l   %0, dlxx1\n\t"
        "move.l   %1, dlxy1\n\t"
        "move.l   %2, dlxx2\n\t"
        "move.l   %3, dlxy2\n\t"
        "move.w   %4, dlxcolor\n\t"
        "clr.l	  -(%%sp)\n\t"
        "dc.w	  0xff20\n\t"      // _SUPER (スーパーバイザーモードへ)
        "move.l   %%d0, (%%sp)\n\t"

        "movem.l  %%d0-%%d7/%%a0-%%a6, -(%%sp)\n\t" // レジスタを保存
        "jsr     drawlinex_a\n\t"
        "movem.l  (%%sp)+, %%d0-%%d7/%%a0-%%a6\n\t" // レジスタを復元

        "dc.w	  0xff20\n\t"      // _SUPER (スーパーバイザーモードから戻る)
        "addq.l   #4,%%sp\n\t"
        "jmp      dlxexit\n\t"
        "dlxx1: dc.l 0\n\t"
        "dlxy1: dc.l 0\n\t"
        "dlxx2: dc.l 0\n\t"
        "dlxy2: dc.l 0\n\t"
        "dlxcolor: dc.w 0\n\t"
        "dlxexit:\n\t"
        :
        : "r"(x1), "r"(y1), "r"(x2), "r"(y2), "r"(color) // 入力
        : "d0"                                           // 使用するレジスタ
    );
}