更新日: 2023 年 7 月 10 日
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