misc/060tsys/t20dosmem.s
;----------------------------------------------------------------
;
; メモリ管理関連のDOSCALL
;
;----------------------------------------------------------------
.include t01dos.equ
.include t02const.equ
.include t08debug.equ
;__DEBUG__ equ 1
.cpu 68060
;----------------------------------------------------------------
;_MALLOC ブロックの確保(下位から)
;<(a6).l:確保するブロックのサイズ
;>d0.l:確保したブロックのユーザ領域の先頭
; $81xxxxxx=確保できる最大のサイズ,$82000000=まったく確保できない
;*d0,?d2/d4-d5/a0-a5
dosMalloc::
debug '|malloc in (size)=',1,(a6)
bsr dosAreaLockMalloc
bmi dosMallocNever
;<a2.l:(次候補)メモリ空間の先頭(先頭のブロックのヘッダ)
;<a3.l:(次候補)メモリ空間の末尾+1(16バイトアラインメント)
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
move.l (a6),d2 ;確保するサイズ
;<d2.l:確保するサイズ
cmp.l #$00FFFFF0,d2 ;$00FFFFF0よりも大きいときは最大サイズの取得と見なす
bhi dosMallocGetSize
;ブロックを確保する
bsr getProc
;<d4.l:実行中のプロセスのメモリ管理テーブル
bsr malloc20 ;ブロックの確保(下位から)
;<d0.l:0=成功,$8xxxxxxx=確保できる最大のサイズ
;<a1.l:0=失敗,0以外=確保したブロックのユーザ領域の先頭
bpl dosMallocDone
movea.l a2,a4
movea.l a3,a5
bsr malloc20
bmi dosMallocFailed
dosMallocDone:
move.l a1,d0
dosMallocEnd:
bsr dosAreaUnlock
debug '|malloc out (ptr)=',1,d0
tst.l d0
rts
;最大サイズの取得
dosMallocGetSize:
movea.l a2,a4 ;最大のサイズは優先範囲に制限せずに求める
movea.l a3,a5
bsr getSize
move.l d1,d0 ;一度に確保できる最大のサイズ
dosMallocFailed:
lsl.l #1,d0
beq dosMallocNever ;まったく確保できない
lsr.l #1,d0
cmp.l #$00FFFFF0,d0
bls @f
move.l #$00FFFFF0,d0 ;$00FFFFFFは不可(もう1度$00FFFFFFで呼ばれてしまうから)
@@: or.l #$81000000,d0
bra dosMallocEnd
dosMallocNever:
move.l #$82000000,d0 ;まったく確保できない
bra dosMallocEnd
;----------------------------------------------------------------
;_MALLOC3 ブロックの確保(下位から)
;<(a6).l:確保するブロックのサイズ
;>d0.l:確保したブロックのユーザ領域の先頭
; $8xxxxxxx=確保できる最大のサイズ
;*d0,?d2/d4-d5/a0-a5
dosMalloc3::
debug '|malloc3 in (size)=',1,(a6)
debugChar '!'
bsr dosAreaLockMalloc
bmi dosMalloc3Never
debugChar '@'
;<a2.l:(次候補)メモリ空間の先頭(先頭のブロックのヘッダ)
;<a3.l:(次候補)メモリ空間の末尾+1(16バイトアラインメント)
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
move.l (a6),d2 ;確保するサイズ
;<d2.l:確保するサイズ
;ブロックを確保する
bsr getProc
;<d4.l:実行中のプロセスのメモリ管理テーブル
bsr malloc20 ;ブロックの確保(下位から)
;<d0.l:0=成功,$8xxxxxxx=確保できる最大のサイズ
;<a1.l:0=失敗,0以外=確保したブロックのユーザ領域の先頭
bpl dosMalloc3Done
movea.l a2,a4
movea.l a3,a5
bsr malloc20
bmi dosMalloc3End
dosMalloc3Done:
move.l a1,d0
dosMalloc3End:
bsr dosAreaUnlock
debug '|malloc3 out (ptr)=',1,d0
tst.l d0
rts
dosMalloc3Never:
move.l #$80000000,d0
bra dosMalloc3End
;----------------------------------------------------------------
;_MFREE ブロックの開放
;(a6).l:開放するブロックのユーザ領域の先頭
; 0=実行中のプロセスが確保したブロックをすべて開放する
;>d0.l:エラーコード
; $FFFFFFF7=無効なブロックを指定した
;*d0,?d2/d4-d5/a0-a5
dosMfree::
debug '|mfree in (ptr)=',1,(a6)
moveq.l #8,d5 ;制限なし,優先なし
bsr dosAreaLock
bmi dosMfreeNotFound
;制限なし,優先なしなのでa2-a3はa4-a5と同じ
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
move.l (a6),d2 ;開放するブロックのユーザ領域の先頭
beq dosMfreeProc ;実行中のプロセスが確保したブロックをすべて開放
;<d2.l:開放するブロックのユーザ領域の先頭
dosMfreeSMfree::
bsr free
;<d0.l:0=成功,-1=ヘッダが見つからない
bmi dosMfreeNotFound ;開放できない
dosMfreeEnd:
bsr dosAreaUnlock
debug '|mfree out (error-code)=',1,d0
tst.l d0
rts
;実行中のプロセスが確保したブロックをすべて開放
dosMfreeProc:
bsr getProc
;<d4.l:実行中のプロセスのメモリ管理テーブル
bsr psfree
;<d0.l:0(常に成功する)
bra dosMfreeEnd
dosMfreeNotFound:
moveq.l #$FFFFFFF7,d0 ;無効なブロックを指定した
bra dosMfreeEnd
;----------------------------------------------------------------
;_SETBLOCK ブロックのサイズ変更
; ブロックは移動しない
;<(a6).l:サイズを変更するブロックのユーザ領域の先頭
;<(4,a6).l:新しいサイズ
;>d0.l:エラーコード
; $FFFFFFF7=無効なブロックを指定した
; $81xxxxxx=確保できる最大のサイズ
;*d0,?d2-d3/d5/a0-a5
dosSetblock::
debug '|setblock in (ptr,size)=',2,(a6),(4,a6)
moveq.l #8,d5 ;制限なし,優先なし
bsr dosAreaLock
bmi dosSetblockNotFound
;制限なし,優先なしなのでa2-a3はa4-a5と同じ
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
move.l (a6),d2
move.l (4,a6),d3
;<d2.l:サイズを変更するブロックのユーザ領域の先頭
;<d3.l:新しいサイズ
cmp.l #$00FFFFF0,d3 ;$00FFFFF0よりも大きいときは最大サイズの取得と見なす
bhi dosSetblockGetSize
;サイズを変更する
bsr resize
;<d0.l:0=成功,-1=ヘッダが見つからない,$8xxxxxxx=確保できる最大のサイズ
bmi dosSetblockFailed
dosSetblockEnd:
bsr dosAreaUnlock
debug '|setblock out (error-code)=',1,d0
tst.l d0
rts
;最大サイズの取得
dosSetblockGetSize:
moveq.l #-1,d3 ;必ずエラーを出す
bsr resize
dosSetblockFailed:
;<d0.l:-1=ヘッダが見つからない,$8xxxxxxx=確保できる最大のサイズ
cmp.l #$FFFFFFFF,d0
beq dosSetblockNotFound
cmp.l #$80FFFFF0,d0
blo @f
move.l #$80FFFFF0,d0 ;$80FFFFFFは不可(もう1度$00FFFFFFで呼ばれてしまうから)
@@: or.l #$81000000,d0
bra dosSetblockEnd
dosSetblockNotFound:
moveq.l #$FFFFFFF7,d0 ;無効なブロックを指定した
bra dosSetblockEnd
;----------------------------------------------------------------
;_SETBLOCK2 ブロックのサイズ変更
; ブロックは移動しない
;<(a6).l:サイズを変更するブロックのユーザ領域の先頭
;<(4,a6).l:新しいサイズ
;>d0.l:エラーコード
; $FFFFFFF7=無効なブロックを指定した
; $8xxxxxxx=確保できる最大のサイズ
;*d0,?d2-d3/d5/a0-a5
dosSetblock2::
debug '|setblock2 in (ptr,size)=',2,(a6),(4,a6)
moveq.l #8,d5 ;制限なし,優先なし
bsr dosAreaLock
bmi dosSetblock2NotFound
;制限なし,優先なしなのでa2-a3はa4-a5と同じ
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
move.l (a6),d2
move.l (4,a6),d3
;<d2.l:サイズを変更するブロックのユーザ領域の先頭
;<d3.l:新しいサイズ
;サイズを変更する
bsr resize
;<d0.l:0=成功,-1=ヘッダが見つからない,$8xxxxxxx=確保できる最大のサイズ
cmp.l #$FFFFFFFF,d0
beq dosSetblock2NotFound
dosSetblock2End:
bsr dosAreaUnlock
debug '|setblock2 out (error-code)=',1,d0
tst.l d0
rts
dosSetblock2NotFound:
moveq.l #$FFFFFFF7,d0 ;無効なブロックを指定した
bra dosSetblock2End
;----------------------------------------------------------------
;_MALLOC2 ブロックの確保(モード指定あり)
;<(a6).w:bit15=プロセス指定フラグ(0=実行中のプロセス,1=(6,a6).lを親プロセスとして使用する)
; 下位8bit=モード(0=下位から,1=必要最小ブロックから,2=上位から,3=最大ブロックから)
;<(2,a6).l:確保するサイズ
;<(6,a6).l:((a6).wのbit15が1のとき)親プロセスのメモリ管理テーブル
;>d0.l:確保したブロックのユーザ領域の先頭
; $FFFFFFF2=パラメータが無効
; $81xxxxxx=確保できる最大のサイズ,$82000000=まったく確保できない
;*d0,?d2-d4/a0-a5
dosMalloc2::
debug '|malloc2 in (mode,size,proc)=',3,(-2,a6),(2,a6),(6,a6)
bsr dosAreaLockMalloc
bmi dosMalloc2Never
;<a2.l:(次候補)メモリ空間の先頭(先頭のブロックのヘッダ)
;<a3.l:(次候補)メモリ空間の末尾+1(16バイトアラインメント)
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
dosMalloc2SMalloc::
move.l (2,a6),d2 ;確保するサイズ
;<d2.l:確保するサイズ
cmp.l #$00FFFFF0,d2 ;00FFFFF0よりも大きいときは最大サイズの取得と見なす
bhi dosMalloc2GetSize
;親プロセスのメモリ管理テーブルを求める
bsr getProc
move.w (a6),d3 ;モード
bpl @f
move.l (6,a6),d4 ;親プロセスのメモリ管理テーブル
and.w #$7FFF,d3
@@: cmp.w #4,d3
bcc dosMalloc2ParamError
;ブロックを確保する
;<d4.l:実行中のプロセスのメモリ管理テーブル
jsr ([malloc2Table,d3.w*4]) ;ブロックの確保
;<d0.l:0=成功,$8xxxxxxx=確保できる最大のサイズ
;<a1.l:0=失敗,0以外=確保したブロックのユーザ領域の先頭
bpl dosMalloc2Done
movea.l a2,a4
movea.l a3,a5
jsr ([malloc2Table,d3.w*4]) ;ブロックの確保
bmi dosMalloc2Failed
dosMalloc2Done:
move.l a1,d0
dosMalloc2End:
bsr dosAreaUnlock
debug '|malloc2 out (ptr)=',1,d0
tst.l d0
rts
;最大サイズの取得
dosMalloc2GetSize:
movea.l a2,a4 ;最大のサイズは優先範囲に制限せずに求める
movea.l a3,a5
bsr getSize
move.l d1,d0 ;一度に確保できる最大のサイズ
dosMalloc2Failed:
lsl.l #1,d0
beq dosMalloc2Never ;まったく確保できない
lsr.l #1,d0
cmp.l #$00FFFFF0,d0
bls @f
move.l #$00FFFFF0,d0 ;$00FFFFFFは不可(もう1度$00FFFFFFで呼ばれてしまうから)
@@: or.l #$81000000,d0
bra dosMalloc2End
dosMalloc2Never:
move.l #$82000000,d0 ;まったく確保できない
bra dosMalloc2End
dosMalloc2ParamError:
moveq.l #$FFFFFFF2,d0 ;パラメータが無効
bra dosMalloc2End
;----------------------------------------------------------------
;_MALLOC4 ブロックの確保(モード指定あり)
;<(a6).w:bit15=プロセス指定フラグ(0=実行中のプロセス,1=d4.lを親プロセスとして使用する)
; 下位8bit=モード(0=下位から,1=必要最小ブロックから,2=上位から,3=最大ブロックから)
;<(2,a6).l:確保するサイズ
;<(6,a6).l:((a6).wのbit15が1のとき)親プロセスのメモリ管理テーブル
;>d0.l:確保したブロックのユーザ領域の先頭
; $FFFFFFF2=パラメータが無効
; $8xxxxxxx=確保できる最大のサイズ
;*d0,?d2-d5/a0-a5
dosMalloc4::
debug '|malloc4 in (mode,size,proc)=',3,(-2,a6),(2,a6),(6,a6)
bsr dosAreaLockMalloc
bmi dosMalloc4Never
;<a2.l:(次候補)メモリ空間の先頭(先頭のブロックのヘッダ)
;<a3.l:(次候補)メモリ空間の末尾+1(16バイトアラインメント)
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
dosMalloc4SMalloc::
move.l (2,a6),d2 ;確保するサイズ
;<d2.l:確保するサイズ
move.w (a6),d3 ;モード
bpl @f
move.l (6,a6),d4 ;親プロセスのメモリ管理テーブル
and.w #$7FFF,d3
@@: cmp.w #4,d3
bcc dosMalloc4ParamError
;ブロックを確保する
bsr getProc
;<d4.l:実行中のプロセスのメモリ管理テーブル
jsr ([malloc2Table,d3.w*4]) ;ブロックの確保
;<d0.l:0=成功,$8xxxxxxx=確保できる最大のサイズ
;<a1.l:0=失敗,0以外=確保したブロックのユーザ領域の先頭
bpl dosMalloc4Done
movea.l a2,a4
movea.l a3,a5
jsr ([malloc2Table,d3.w*4]) ;ブロックの確保
bmi dosMalloc4End
dosMalloc4Done:
move.l a1,d0
dosMalloc4End:
bsr dosAreaUnlock
debug '|malloc4 out (ptr)=',1,d0
tst.l d0
rts
dosMalloc4Never:
move.l #$80000000,d0 ;まったく確保できない
bra dosMalloc4End
dosMalloc4ParamError:
moveq.l #$FFFFFFF2,d0 ;パラメータが無効
bra dosMalloc4End
;----------------------------------------------------------------
;アクセスできないメモリ空間を制限する
; 自分以外の連続メモリ型サブスレッドのすべてのブロックをロックする
; _EXECの場合はプログラムのロード範囲の制限を受ける
; _EXEC以外ではアロケート範囲の制限を受ける
; 次候補は優先して確保する範囲に制限する前の範囲なので優先する範囲を含む
;<d5.b:モード
; 0 下位のみ
; 1 上位のみ
; 2 親と同じ側のみ
; 3 親と反対側のみ
; 4 制限なし,下位優先
; 5 制限なし,上位優先
; 6 制限なし,親と同じ側優先
; 7 制限なし,親と反対側優先
; 8 制限なし,優先なし
;>d0.l:0=成功,-1=失敗
;>a2.l:(次候補)メモリ空間の先頭(先頭のブロックのヘッダ)
;>a3.l:(次候補)メモリ空間の末尾+1(16バイトアラインメント)
;>a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;>a5.l:メモリ空間の末尾+1(16バイトアラインメント)
;*d0/a2-a5,?a0-a1
dosAreaLockMalloc::
cmpi.b #_EXEC-$FF00,$1C0A.w ;レベル0で入ったDOSコール番号
bne dosAreaLockNotExec
;_EXECのとき
moveq.l #1,d5 ;loadhighのときは上位のみ
tst.b execLoadHigh
bne dosAreaLock
move.b defaultLoadArea,d5
bra dosAreaLock
;_EXEC以外のとき
dosAreaLockNotExec:
movea.l ([$1C28.w]),a0 ;親プロセスのプロセス管理テーブル
move.b (pAllocArea,a0),d5
;<d5.b:モード
; 0 下位のみ
; 1 上位のみ
; 2 親と同じ側のみ
; 3 親と反対側のみ
; 4 制限なし,下位優先
; 5 制限なし,上位優先
; 6 制限なし,親と同じ側優先
; 7 制限なし,親と反対側優先
; 8 制限なし,優先なし
dosAreaLock::
debugByte '|dosAreaLock in (mode)=',1,d5
movea.l $1C54.w,a0 ;現在のスレッドのスレッド管理テーブル
bsr lockBlocks ;自分以外のサブスレッドのブロックをロックする
movea.l $1C04.w,a4 ;メモリ空間の先頭
movea.l $1C00.w,a5 ;メモリ空間の末尾+1
movea.l a4,a2 ;優先する範囲に制限する前のメモリ空間の先頭
movea.l a5,a3 ;優先する範囲に制限する前のメモリ空間の末尾+1
move.b d5,d0
beq dosAreaLockLowerOnly ;0=下位のみ
subq.b #2,d0
bcs dosAreaLockUpperOnly ;1=上位のみ
beq dosAreaLockProcOnly ;2=親と同じ側のみ
subq.b #2,d0
bcs dosAreaLockNotProcOnly ;3=親と反対側のみ
beq dosAreaLockLower ;4=制限なし,下位優先
subq.b #2,d0
bcs dosAreaLockUpper ;5=制限なし,上位優先
beq dosAreaLockProc ;6=制限なし,親と同じ側優先
subq.b #2,d0
bcs dosAreaLockNotProc ;7=制限なし,親と反対側優先
;8=制限なし,優先なし
dosAreaLockEnd:
moveq.l #0,d0
debug '|dosAreaLock out (d0,top,btm,top2,btm2)=',5,d0,a4,a5,a2,a3
rts
dosAreaLockFailed:
moveq.l #-1,d0
debug '|dosAreaLock out (d0,top,btm,top2,btm2)=',5,d0,a4,a5,a2,a3
rts
;親と反対側のみ
dosAreaLockNotProcOnly:
cmpi.l #$01000000,([$1C28.w])
blo dosAreaLockUpperOnly
;下位のみ
;<a0.l:親プロセスのプロセス管理テーブル
dosAreaLockLowerOnly:
;上位の部分を切り捨てる
move.l himemAreaStart,d0 ;下位メモリの上限
beq @f ;上位がない
cmpa.l d0,a5
bls @f ;既に下位だけに制限されている
cmpa.l d0,a4
bhs dosAreaLockFailed ;上位だけに制限されている
movea.l d0,a5 ;末尾+1を制限する
movea.l a5,a3 ;次候補も制限する
@@: moveq.l #0,d0
debug '|dosAreaLock out (d0,top,btm,top2,btm2)=',5,d0,a4,a5,a2,a3
rts
;親と同じ側のみ
;<a0.l:親プロセスのプロセス管理テーブル
dosAreaLockProcOnly:
cmpi.l #$01000000,([$1C28.w])
blo dosAreaLockLowerOnly
;上位のみ
;<a0.l:親プロセスのプロセス管理テーブル
dosAreaLockUpperOnly:
;下位の部分を切り捨てる,下位しかないときは条件を無視する
move.l himemAreaStart,d0 ;上位メモリの下限
beq @f ;下位しかないので条件を無視する
cmpa.l d0,a4
bhs @f ;既に上位だけに制限されている
cmpa.l d0,a5
bls dosAreaLockFailed ;下位だけに制限されている
movea.l d0,a4 ;先頭を制限する
movea.l a4,a2 ;次候補も制限する
@@: moveq.l #0,d0
debug '|dosAreaLock out (d0,top,btm,top2,btm2)=',5,d0,a4,a5,a2,a3
rts
;制限なし,親と反対側優先
;<a0.l:親プロセスのプロセス管理テーブル
dosAreaLockNotProc:
cmpi.l #$01000000,([$1C28.w])
blo dosAreaLockUpper
;制限なし,下位優先
;<a0.l:親プロセスのプロセス管理テーブル
dosAreaLockLower:
;上位と下位の境目を跨いでいるときだけ制限する
move.l himemAreaStart,d0 ;下位メモリの上限
beq @f ;下位しかない
cmpa.l d0,a5
bls @f ;既に下位だけに制限されている
cmpa.l d0,a4
bhs @f ;上位だけに制限されている
movea.l d0,a5 ;末尾+1を制限する
;次候補は制限しない
@@: moveq.l #0,d0
debug '|dosAreaLock out (d0,top,btm,top2,btm2)=',5,d0,a4,a5,a2,a3
rts
;制限なし,親と同じ側優先
;<a0.l:親プロセスのプロセス管理テーブル
dosAreaLockProc:
cmpi.l #$01000000,([$1C28.w])
blo dosAreaLockLower
;制限なし,上位優先
;<a0.l:親プロセスのプロセス管理テーブル
dosAreaLockUpper:
;上位と下位の境目を跨いでいるときだけ制限する
move.l himemAreaStart,d0 ;上位メモリの下限
beq @f ;下位しかないので制限できない
cmpa.l d0,a4
bhs @f ;既に上位だけに制限されている
cmpa.l d0,a5
bls @f ;下位しかないので制限できない
movea.l d0,a4 ;先頭を制限する
;次候補は制限しない
@@: moveq.l #0,d0
debug '|dosAreaLock out (d0,top,btm,top2,btm2)=',5,d0,a4,a5,a2,a3
rts
;----------------------------------------------------------------
;アクセスできるメモリ空間の制限を解除する
; ブロックのロックを解除する
;<a4.l:メモリ空間の先頭(先頭のブロックのヘッダ)
;<a5.l:メモリ空間の末尾+1(16バイトアラインメント)
dosAreaUnlock::
bsr unlockBlocks
rts