countersince January 6, 2001X68000 LIBRARYEnglish
更新日: 2023 年 7 月 10 日
X68000 LIBRARY > ソフトウェアライブラリ > プログラミング > アセンブラ > HAS060.X > K_MACRO.MAC

K_MACRO.MAC

説明

HAS060.X の添付サンプルです。

K_MACRO.MAC
        .nlist

        .ifndef __MACRO_MAC__
__MACRO_MAC__   equ     0

;----------------------------------------------------------------
;
;       構造化マクロ定義 for HAS060.X
;               1998.02.08 by M.Kamada
;
;       HAS060.X v3.09+59 以降で使用できます。
;
;       ifcc〜elseifcc(elifcc)〜else〜endif     条件ブロック
;
;       repeat〜untilcc                 後ろ判定ループ
;       do〜whilecc                     後ろ判定ループ
;       whilecc〜endwhile               前判定ループ
;
;       break                           ループ脱出
;       breakcc                         ループ脱出(条件付き)
;       continue                        ループ条件へジャンプ
;       continuecc                      ループ条件へジャンプ(条件付き)
;
;----------------------------------------------------------------

;----------------------------------------------------------------
;
;       変数(ユーザは参照禁止)
;
;               ~km_s_condN     条件用のスタック(2個ずつ使う)
;                               (+0=else,+1=endif)
;               ~km_s_loopN     ループ用のスタック(3個ずつ使う)
;                               (+0=ループの先頭,+1=continue,+2=break)
;               ~km_s_repeatN   repeat〜untilcc用のスタック(1個ずつ使う)
;                               (ループの先頭のラベルの番号)
;               ~km_s_doN       do〜whilecc用のスタック(1個ずつ使う)
;                               (ループの先頭のラベルの番号)
;               ~km_s_whileN    whilecc〜endwhile用のスタック(1個ずつ使う)
;                               (ループの先頭のラベルの番号)
;
;               ~km_l_cond      条件のネスティングレベル(0〜)
;               ~km_l_loop      ループのネスティングレベル(0〜)
;               ~km_l_repeat    repeat〜untilccのネスティングレベル(0〜)
;               ~km_l_do        do〜whileccのネスティングレベル(0〜)
;               ~km_l_while     whilecc〜endwhileのネスティングレベル(0〜)
;
;               ~km_n           次に使うラベルの番号(常にインクリメント)
;
;               ~km_i           汎用
;               ~km_j           汎用
;
;----------------------------------------------------------------
;
;       ラベル(ユーザは参照禁止)
;
;               ~km_aN          共通ラベル
;
;----------------------------------------------------------------
;
;       マクロ(ユーザは使用禁止)
;
;               ~km_push t,d,p0,p1,p2
;                               スタックの先頭にデータをプッシュする
;                                       t       タイプ(_cond,_loop,_repeat,_do,_while)
;                                       d       深さ
;                                       p0      スタックの先頭に置くデータ
;                                       p1      スタックの先頭+1に置くデータ
;                                       p2      スタックの先頭+2に置くデータ
;
;               ~km_pop t,d     スタックの先頭のデータを捨てる
;                                       t       タイプ(_cond,_loop,_repeat,_do,_while)
;                                       d       深さ
;
;----------------------------------------------------------------

;----------------------------------------------------------------
;
;       初期化
;
;----------------------------------------------------------------
;マクロの構造上,スタックの先頭を初期化しておく必要がある
        ~km_s_cond0:=0          ;条件用のスタック(2個ずつ使う)
        ~km_s_loop0:=0          ;ループ用のスタック(3個ずつ使う)
        ~km_s_repeat0:=0        ;repeat〜untilcc用のスタック(1個ずつ使う)
        ~km_s_do0:=0            ;do〜whilecc用のスタック(1個ずつ使う)
        ~km_s_while0:=0         ;whilecc〜endwhile用のスタック(1個ずつ使う)

;ネスティングレベルの初期化
        ~km_l_cond:=0           ;条件のネスティングレベル(0〜)
        ~km_l_loop:=0           ;ループのネスティングレベル(0〜)
        ~km_l_repeat:=0         ;repeat〜untilccのネスティングレベル(0〜)
        ~km_l_do:=0             ;do〜whileccのネスティングレベル(0〜)
        ~km_l_while:=0          ;whilecc〜endwhileのネスティングレベル(0〜)

;ラベルの番号の初期化
        ~km_n:=1                ;次に使うラベルの番号(常にインクリメント)

;----------------------------------------------------------------
;
;       スタック操作マクロ
;
;----------------------------------------------------------------
~km_push        .macro  t,d,p0,p1,p2
        ~km_i:=~km_l&t-1
        .rept   ~km_l&t
                ~km_j:=~km_i+d
                ~km_s&t%~km_j:=~km_s&t%~km_i
                ~km_i:=~km_i-1
        .endm
        ~km_l&t:=~km_l&t+d
        .if     d>=1
                ~km_j:=0
                ~km_s&t%~km_j:=p0
        .endif
        .if     d>=2
                ~km_j:=1
                ~km_s&t%~km_j:=p1
        .endif
        .if     d>=3
                ~km_j:=2
                ~km_s&t%~km_j:=p2
        .endif
.endm

~km_pop .macro  t,d
        ~km_l&t:=~km_l&t-d
        ~km_i:=d
        .rept   ~km_l&t
                ~km_j:=~km_i-d
                ~km_s&t%~km_j:=~km_s&t%~km_i
                ~km_i:=~km_i+1
        .endm
.endm

;----------------------------------------------------------------
;       ifcc〜elseifcc(elifcc)〜else〜endif     条件ブロック
;
;                       ifcc    <命令>,…
;                               :
;                       elseifcc        <命令>,…
;                               :
;                       else
;                               :
;                       endif
;
;       条件が満たされているブロックだけを実行するようなコードを生成します.
;       elseifccはelifccと省略できます.
;
;       生成される構造:
;                       <命令>,…
;                       JBNcc   else1
;                               :
;                       JBRA    endif
;               else1:  <命令>,…
;                       JBNcc   else2
;                               :
;                       JBRA    endif
;               else2:          :
;               endif:
;
;       条件になる命令は,
;               <〜>で囲って指定します.
;               複数の命令を記述できます(0個以上10個以下).
;               最後の命令を通過した直後の状態に従って分岐します.
;----------------------------------------------------------------
        .irp %cc,t,f,hi,ls,cc,hs,cs,lo,ne,nz,eq,ze,vc,vs,pl,mi,ge,lt,gt,le

if%cc   .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        ~km_push        _cond,2,~km_n,~km_n+1
        ~km_n:=~km_n+2
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
        .elseif '%cc'='f'
                jbra&&sz        ~km_a%~km_s_cond0
        .else
                jbn%cc&&sz      ~km_a%~km_s_cond0
        .endif
.endm

ifn%cc  .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        ~km_push        _cond,2,~km_n,~km_n+1
        ~km_n:=~km_n+2
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
                jbra&&sz        ~km_a%~km_s_cond0
        .elseif '%cc'='f'
        .else
                jb%cc&&sz       ~km_a%~km_s_cond0
        .endif
.endm

elseif%cc       .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     ~km_l_cond=0
                .fail   1               ;elseifに対応するifがない
                .exitm
        .endif
        jbra&&sz        ~km_a%~km_s_cond1
~km_a%~km_s_cond0:
        ~km_s_cond0:=~km_n
        ~km_n:=~km_n+1
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
        .elseif '%cc'='f'
                jbra&&sz        ~km_a%~km_s_cond0
        .else
                jbn%cc&&sz      ~km_a%~km_s_cond0
        .endif
.endm

elseifn%cc      .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     ~km_l_cond=0
                .fail   1               ;elseifに対応するifがない
                .exitm
        .endif
        jbra&&sz        ~km_a%~km_s_cond1
~km_a%~km_s_cond0:
        ~km_s_cond0:=~km_n
        ~km_n:=~km_n+1
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
                jbra&&sz        ~km_a%~km_s_cond0
        .elseif '%cc'='f'
        .else
                jb%cc&&sz       ~km_a%~km_s_cond0
        .endif
.endm

elif%cc .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     ~km_l_cond=0
                .fail   1               ;elseifに対応するifがない
                .exitm
        .endif
        jbra&&sz        ~km_a%~km_s_cond1
~km_a%~km_s_cond0:
        ~km_s_cond0:=~km_n
        ~km_n:=~km_n+1
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
        .elseif '%cc'='f'
                jbra&&sz        ~km_a%~km_s_cond0
        .else
                jbn%cc&&sz      ~km_a%~km_s_cond0
        .endif
.endm

elifn%cc        .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     ~km_l_cond=0
                .fail   1               ;elseifに対応するifがない
                .exitm
        .endif
        jbra&&sz        ~km_a%~km_s_cond1
~km_a%~km_s_cond0:
        ~km_s_cond0:=~km_n
        ~km_n:=~km_n+1
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
                jbra&&sz        ~km_a%~km_s_cond0
        .elseif '%cc'='f'
        .else
                jb%cc&&sz       ~km_a%~km_s_cond0
        .endif
.endm

        .endm

else    .macro
        .sizem  sz
        .if     ~km_l_cond=0
                .fail   1               ;elseに対応するifがない
                .exitm
        .endif
        .if     ~km_s_cond0=0
                .fail   1               ;elseが重複している
                .exitm
        .endif
        jbra&sz ~km_a%~km_s_cond1
~km_a%~km_s_cond0:
        ~km_s_cond0:=0
        .endm

endif   .macro
        .if     ~km_l_cond=0
                .fail   1               ;endifに対応するifがない
                .exitm
        .endif
        .if     ~km_s_cond0
~km_a%~km_s_cond0:
        .endif
~km_a%~km_s_cond1:
        ~km_pop _cond,2
        .endm

;----------------------------------------------------------------
;       repeat〜untilcc                 後ろ判定ループ
;
;                       repeat
;                               :
;                       untilcc <命令>,…
;
;       条件が満たされるまでループするようなコードを生成します.
;       do〜whileccとは条件が逆になります.
;
;       生成される構造:
;               loop:
;                               :
;               continue:
;                       <命令>,…
;                       JBNcc   loop
;               break:
;
;       条件になる命令は,
;               <〜>で囲って指定します.
;               複数の命令を記述できます(0個以上10個以下).
;               最後の命令を通過した直後の状態に従って分岐します.
;----------------------------------------------------------------
repeat  .macro
        ~km_push        _loop,3,~km_n,~km_n+1,~km_n+2
        ~km_n:=~km_n+3
~km_a%~km_s_loop0:
        ~km_push        _repeat,1,~km_s_loop0
        .endm

        .irp %cc,t,f,hi,ls,cc,hs,cs,lo,ne,nz,eq,ze,vc,vs,pl,mi,ge,lt,gt,le

until%cc        .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     ~km_l_repeat=0
                .fail   1               ;untilccに対応するrepeatがない
                .exitm
        .endif
        .if     ~km_s_repeat0<>~km_s_loop0
                .fail   1               ;repeat〜untilccの対応がおかしい
                .exitm
        .endif
        ~km_pop _repeat,1
~km_a%~km_s_loop1:
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
        .elseif '%cc'='f'
                jbra&&sz        ~km_a%~km_s_loop0
        .else
                jbn%cc&&sz      ~km_a%~km_s_loop0
        .endif
~km_a%~km_s_loop2:
        ~km_pop _loop,3
.endm

untiln%cc       .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     ~km_l_repeat=0
                .fail   1               ;untilccに対応するrepeatがない
                .exitm
        .endif
        .if     ~km_s_repeat0<>~km_s_loop0
                .fail   1               ;repeat〜untilccの対応がおかしい
                .exitm
        .endif
        ~km_pop _repeat,1
~km_a%~km_s_loop1:
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
                jbra&&sz        ~km_a%~km_s_loop0
        .elseif '%cc'='f'
        .else
                jb%cc&&sz       ~km_a%~km_s_loop0
        .endif
~km_a%~km_s_loop2:
        ~km_pop _loop,3
.endm

        .endm

;----------------------------------------------------------------
;       do〜whilecc                     後ろ判定ループ
;
;                       do
;                               :
;                       whilecc <命令>,…
;
;       条件が満たされている間だけループするようなコードを生成します.
;       repeat〜untilccとは条件が逆になります.
;
;       生成される構造:
;               loop:
;                               :
;               continue:
;                       <命令>,…
;                       JBcc    loop
;               break:
;
;       条件になる命令は,
;               <〜>で囲って指定します.
;               複数の命令を記述できます(0個以上10個以下).
;               最後の命令を通過した直後の状態に従って分岐します.
;----------------------------------------------------------------
;       whilecc〜endwhile               前判定ループ
;
;                       whilecc <命令>,…
;                               :
;                       endwhile
;
;       条件が満たされている間だけループするようなコードを生成します.
;
;       生成される構造:
;               loop:
;               continue:
;                       <命令>,…
;                       JBNcc   break
;                               :
;                       JBRA    loop
;               break:
;
;       マクロの構造の都合で,
;       条件判定をループの末尾に配置するような生成方法にはなっていません.
;
;       条件になる命令は,
;               <〜>で囲って指定します.
;               複数の命令を記述できます(0個以上10個以下).
;               最後の命令を通過した直後の状態に従って分岐します.
;----------------------------------------------------------------
do      .macro
        ~km_push        _loop,3,~km_n,~km_n+1,~km_n+2
        ~km_n:=~km_n+3
~km_a%~km_s_loop0:
        ~km_push        _do,1,~km_s_loop0
        .endm

        .irp %cc,t,f,hi,ls,cc,hs,cs,lo,ne,nz,eq,ze,vc,vs,pl,mi,ge,lt,gt,le

while%cc        .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     (~km_l_do=0).or.(~km_s_do0<>~km_s_loop0)
;whileccに対応するdoがない,または,do〜whileccの対応がおかしいとき,
;whilecc〜endwhileと認識する
                ~km_push        _loop,3,~km_n,~km_n+1,~km_n+2
                ~km_n:=~km_n+3
~km_a%~km_s_loop0:
~km_a%~km_s_loop1:
                op0
                op1
                op2
                op3
                op4
                op5
                op6
                op7
                op8
                op9
                .if     '%cc'='t'
                .elseif '%cc'='f'
                        jbra&&sz        ~km_a%~km_s_loop2
                .else
                        jbn%cc&&sz      ~km_a%~km_s_loop2
                .endif
                ~km_push        _while,1,~km_s_loop0
        .else
;do〜whileccのとき
                ~km_pop _do,1
~km_a%~km_s_loop1:
                op0
                op1
                op2
                op3
                op4
                op5
                op6
                op7
                op8
                op9
                .if     '%cc'='t'
                        jbra&&sz        ~km_a%~km_s_loop0
                .elseif '%cc'='f'
                .else
                        jb%cc&&sz       ~km_a%~km_s_loop0
                .endif
~km_a%~km_s_loop2:
                ~km_pop _loop,3
        .endif
.endm

whilen%cc       .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     (~km_l_do=0).or.(~km_s_do0<>~km_s_loop0)
;whileccに対応するdoがない,または,do〜whileccの対応がおかしいとき,
;whilecc〜endwhileと認識する
                ~km_push        _loop,3,~km_n,~km_n+1,~km_n+2
                ~km_n:=~km_n+3
~km_a%~km_s_loop0:
~km_a%~km_s_loop1:
                op0
                op1
                op2
                op3
                op4
                op5
                op6
                op7
                op8
                op9
                .if     '%cc'='t'
                .elseif '%cc'='f'
                        jbra&&sz        ~km_a%~km_s_loop2
                .else
                        jb%cc&&sz       ~km_a%~km_s_loop2
                .endif
                ~km_push        _while,1,~km_s_loop0
        .else
;do〜whileccのとき
                ~km_pop _do,1
~km_a%~km_s_loop1:
                op0
                op1
                op2
                op3
                op4
                op5
                op6
                op7
                op8
                op9
                .if     '%cc'='t'
                .elseif '%cc'='f'
                        jbra&&sz        ~km_a%~km_s_loop0
                .else
                        jbn%cc&&sz      ~km_a%~km_s_loop0
                .endif
~km_a%~km_s_loop2:
                ~km_pop _loop,3
        .endif
.endm

        .endm

endwhile        .macro
        .sizem  sz
        .if     ~km_l_while=0
                .fail   1               ;endwhileに対応するwhileがない
                .exitm
        .endif
        .if     ~km_s_while0<>~km_s_loop0
                .fail   1               ;while〜endwhileの対応がおかしい
                .exitm
        .endif
        ~km_pop _while,1
        jbra&sz ~km_a%~km_s_loop0
~km_a%~km_s_loop2:
        ~km_pop _loop,3
.endm

;----------------------------------------------------------------
;       break                           ループ脱出
;
;                       break
;
;       無条件に一番内側のループを脱出するようなコードを生成します.
;
;       生成される構造:
;                       jbra    break
;
;----------------------------------------------------------------
;       breakcc                         ループ脱出(条件付き)
;
;                       breakcc <命令>,…
;
;       条件が成立したら一番内側のループを脱出するようなコードを生成します.
;
;       生成される構造:
;                       <命令>,…
;                       JBcc    break
;
;       条件になる命令は,
;               <〜>で囲って指定します.
;               複数の命令を記述できます(0個以上10個以下).
;               最後の命令を通過した直後の状態に従って分岐します.
;----------------------------------------------------------------
break   .macro
        .sizem  sz
        .if     ~km_l_loop=0
                .fail   1               ;breakすべきループがない
                .exitm
        .endif
        jbra&sz ~km_a%~km_s_loop2
.endm

        .irp %cc,t,f,hi,ls,cc,hs,cs,lo,ne,nz,eq,ze,vc,vs,pl,mi,ge,lt,gt,le

break%cc        .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     ~km_l_loop=0
                .fail   1               ;breakすべきループがない
                .exitm
        .endif
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
                jbra&&sz        ~km_a%~km_s_loop2
        .elseif '%cc'='f'
        .else
                jb%cc&&sz       ~km_a%~km_s_loop2
        .endif
.endm

        .endm

;----------------------------------------------------------------
;       continue                        ループ条件へジャンプ
;
;                       continue
;
;       無条件に一番内側のループの条件判定にジャンプするようなコードを生成します.
;
;       生成される構造:
;                       JBRA    continue
;----------------------------------------------------------------
;       continuecc                      ループ条件へジャンプ(条件付き)
;
;                       continuecc      <命令>,…
;
;       条件が成立したら一番内側のループの条件判定にジャンプするようなコードを生成します.
;
;       生成される構造:
;                       <命令>,…
;                       JBcc    continue
;
;       条件になる命令は,
;               <〜>で囲って指定します.
;               複数の命令を記述できます(0個以上10個以下).
;               最後の命令を通過した直後の状態に従って分岐します.
;----------------------------------------------------------------
continue        .macro
        .sizem  sz
        .if     ~km_l_loop=0
                .fail   1               ;continueすべきループがない
                .exitm
        .endif
        jbra&sz ~km_a%~km_s_loop1
.endm

        .irp %cc,t,f,hi,ls,cc,hs,cs,lo,ne,nz,eq,ze,vc,vs,pl,mi,ge,lt,gt,le

continue%cc     .macro  op0,op1,op2,op3,op4,op5,op6,op7,op8,op9
        .sizem  sz
        .if     ~km_l_loop=0
                .fail   1               ;continueすべきループがない
                .exitm
        .endif
        op0
        op1
        op2
        op3
        op4
        op5
        op6
        op7
        op8
        op9
        .if     '%cc'='t'
                jbra&&sz        ~km_a%~km_s_loop1
        .elseif '%cc'='f'
        .else
                jb%cc&&sz       ~km_a%~km_s_loop1
        .endif
.endm

        .endm

;----------------------------------------------------------------
        .endif

        .list