www.pudn.com > norti2.0 > NOCIF.ASM


;****************************************************************************** 
;* NORTi/86 CPUインターフェースモジュール(MASM,TASM互換形式)     * 
;*                                                                            * 
;*  File name : nocif.asm                                                     * 
;*  Copyright (c) Miyazaki System Planning Office. 1991-1995                  * 
;*                                                                            * 
;*  Assemble : masm /MX nocif.asm;       (for MS-C 5.1/6.0)                   * 
;*             masm /MX /DC7 nocif.asm;  (for MS-C 7.0)                       * 
;*             tasm /MX /DTC nocif.asm   (for TC, TC++, BC++)                 * 
;*                                                                            * 
;*             /DCPU=286 で PUSHA/POPA 命令が使われます。                     * 
;*             /DROM で ROM 化用の sysini_rom のみがアセンブルされます。      * 
;*             /DPIC で 割込みコントローラ対応部分もアセンブルされます。      * 
;*             /DMON=xxH で モニタ信号出力部分もアセンブルされます。          * 
;*                                                                            * 
;* 91-10-25 TRCOM Version                                                     * 
;* 92-02-16 Ver1.00                                                           * 
;* 92-08-20 Ver1.10                                                           * 
;* 93-01-18 Ver1.11                                                           * 
;* 93-02-17 Ver1.12                                                           * 
;* 93-05-16 Ver1.13β                                                         * 
;* 94-01-05 Ver1.14                                                           * 
;* 95-06-15 Ver1.20                                                           * 
;* 95-09-12 Ver1.21                                                           * 
;****************************************************************************** 
 
; タスク/割込みモニタ信号とは 
; 
;   任意のポートへ下記の信号を出力します。 
;   タスク切り替えや割込み禁止許可のタイミングを、ロジアナ等で解析できます。 
; 
; 信号の構成 
; 
;   bit0 ホ「 実行タスクIDの下位4ビット(0〜F) 
;   bit1 ニ 
;   bit2 ニ 
;   bit3 コ 
;   bit4 ホ「 割込みネストレベルの下位2ビット(0〜3) 
;   bit5 コ 
;   bit6 「「 割込み禁止(1)/許可(0)状態 
;   bit7 「「 ユーザ解放(out_usrsig 関数) 
; 
; 信号の出力方法 
; 
;   信号を出力させるポートアドレスを MON に定義して nocif.asm をアセンブルし、 
;   nocif.obj を他のモジュールと共にリンクしてください。 
; 
;   (例) masm /MX /DMON=40H nocif.asm 
;        cl ・・・・ nocif.obj nolib.lib /link /NOE 
 
;* プロセッサの型 
 
ifdef CPU 
if (CPU GE 186) 
.186 
endif 
endif 
 
;* ライブラリ生成用分割アセンブルスイッチ 
 
ifdef ROM 
 
SSW		EQU	-1	; sysini_rom のみアセンブル 
else 
ifndef SW 
SSW		EQU	0	; 全てアセンブル 
else 
if (SW EQ 1) 
SSW		EQU	1	; 分割アセンブル 
endif 
if (SW EQ 2) 
SSW		EQU	2 
endif 
if (SW EQ 3) 
SSW		EQU	3 
endif 
if (SW EQ 4) 
SSW		EQU	4 
endif 
endif 
endif 
 
;* 構造体メンバーの位置 
 
TCB_SP		EQU	36	; TCB の退避スタックポインタの位置 (注) 
TCB_TID		EQU	12	; TCB のタスクIDの位置 
 
CTX_STKHQQ	EQU	0	; 退避コンテキスト内の STKHQQ の位置 
CTX_AX		EQU	20	; 退避コンテキスト内の AX の位置 
CTX_CS		EQU	28	; 退避コンテキスト内の CS の位置 
 
; (注) TCB の構造を変更した場合は、TCB_XX の値を必ず見直してください。 
 
;* 外部参照(NOKNL.C) 
 
	EXTRN	C_SYSINI:NEAR	; システム初期化 
	EXTRN	WUP_TSK:FAR 
	EXTRN	SCHEDULE:NEAR	; スケジューラ 
 
	EXTRN	_RDQ:WORD	; レディキューヘッダ 
	EXTRN	_IMASK:WORD	; 割込みマスクフラグ 
	EXTRN	_INEST:BYTE	; 割込みネストカウンタ(減カウント) 
	EXTRN	_DELAY:BYTE	; 遅延ディスパッチ要求フラグ 
	EXTRN	_ISP:WORD	; 割込みスタックポインタ初期値 
 
;* 外部参照(ユーザ定義) 
 
	EXTRN	_intini:FAR	; 割込み初期化 
ifdef PIC 
	EXTRN	VDIS_PIC:FAR	; 割込みコントローラ割込みマスク 
	EXTRN	VENA_PIC:FAR	; 割込みコントローラ割込みマスク解除 
endif 
 
;* TURBO-Cのスタック領域管理変数 
 
ifdef TC 
	EXTRN	__stklen:WORD	; スタック長 
if ((SSW NE 0) AND (SSW NE 1)) 
	EXTRN	STKHQQ:WORD	; MS-Cと合わせる 
endif 
else 
 
;* MS-Cのスタック領域管理変数 
 
ifdef C7 
	EXTRN	_STKHQQ:WORD	; スタック先頭ポインタ(MS-C 7.0) 
STKHQQ	EQU	_STKHQQ 
else 
	EXTRN	STKHQQ:WORD	; スタック先頭ポインタ(MS-C 5.1/6.0) 
endif 
endif 
 
;* デバッグ用 
 
ifdef MON 
if ((SSW NE 0) AND (SSW NE 1)) 
	EXTRN	_MONSIG:BYTE	; モニタ信号出力バッファ 
endif 
endif 
 
;* セグメントの定義と内部変数の定義 
 
_BSS	SEGMENT WORD PUBLIC 'BSS' 
DGROUP	GROUP _BSS 
	ASSUME DS:DGROUP 
 
if ((SSW EQ 0) OR (SSW EQ 1)) 
 
	PUBLIC	_TOPCS 
_TOPCS	DW	?		; ユーザコード先頭セグメント 
 
ifdef TC			; TURBO-C では 
	PUBLIC	STKHQQ 
STKHQQ	DW	?		; MS-Cと合わせるためSTKHQQをダミー定義 
endif 
ifdef MON 
	PUBLIC	_MONSIG 
_MONSIG	DB	?		; モニタ信号出力バッファ 
endif 
 
endif 
if (SSW EQ 3) 
	EXTRN	_TOPCS:WORD 
endif 
_BSS	ENDS 
 
_TEXT	SEGMENT WORD PUBLIC 'CODE' 
	ASSUME CS:_TEXT 
 
if ((SSW EQ 0) OR (SSW EQ 1)) 
;************************************************ 
;* バージョンの定義				* 
;************************************************ 
 
	DB 'NORTi/86 (c) MiSPO' 
	PUBLIC	_NORTI_VER 
_NORTI_VER:			; T_VER NORTI_VER; 
	DW	0108H		; メーカー番号(宮崎システム設計事務所) 
ifdef TC 
	DW	0002H		; 形式番号(NORTi/86 for TURBO-C) 
else 
	DW	0001H		; 形式番号(NORTi/86 for MS-C) 
endif 
	DW	5201H		; 仕様書バージョン(μITRON仕様書Ver2.01) 
	DW	0121H		; 製品バージョン(Ver1.21) 
	DW	0000H		; 製品管理情報0 
	DW	0000H		; 製品管理情報1 
	DW	0000H		; 製品管理情報2 
	DW	0000H		; 製品管理情報3 
if (@Cpu AND 2) 
	DW	0062H		; CPU情報(80286) 
else 
	DW	0060H		; CPU情報(8086) 
endif 
	DW	8000H		; バリエーション記述(レベルS) 
 
;****************************************************************************** 
;*                                                                            * 
;*                           システムコール関数                               * 
;*                                                                            * 
;****************************************************************************** 
ifdef TC 
;************************************************ 
;* システム初期化(TURBO-C)			* 
;************************************************ 
 
	PUBLIC	SYSINI 
SYSINI:					; void far pascal sysini(void) 
 
	CLI				; CPU割込み禁止 
	MOV	[_TOPCS],CS		; TOPCS = ここ(_TEXT)のCS; 
	MOV	AX,SS 
	CMP	AX,DGROUP		; SS == DGROUP (スモール/ミディアム) ? 
	MOV	AX,0			; No  : STKHQQ = 0; 
	JNZ	SYSINI_COM 
	SUB	AX,[__stklen]		; Yes : STKHQQ = 0 - _stklen; 
else 
;************************************************ 
;* システム初期化(MS-C)			* 
;************************************************ 
 
	PUBLIC	SYSINI 
SYSINI:					; void far pascal sysini(void) 
 
	CLI				; CPU 割込み禁止 
	MOV	CX,BP 
	MOV	BP,SP 
	MOV	AX,[BP+2] 
	MOV	BP,CX 
	MOV	[_TOPCS],AX		; TOPCS = 呼出し元(main関数)のCS; 
	JMP	sysini_4 
endif 
;************************************************ 
;* システム初期化(MS-C/TURBO-C/ROM化共通部分)	* 
;************************************************ 
 
	PUBLIC	SYSINI_COM 
SYSINI_COM: 
	MOV	[STKHQQ],AX 
sysini_4: 
	PUSH	[STKHQQ] 
	PUSHF 
	POP	AX 
	OR	AH,02H 
	PUSH	AX			; タスク起動時のFLAGS(IF=1) 
	SUB	SP,12*2			; (CS,IP,アキ,アキ,AX,CX,DX,BX,SP,BP,SI,DI) 
	PUSH	DS			; タスク起動時のDS 
	PUSH	DS			; (ES) 
	SUB	SP,2			; (STKHQQ) 
	CALL	C_SYSINI		; c_sysini(STKHQQ, ctx); 
	CALL	FAR PTR _intini		; intini(); 割込み初期化 
ifdef MON				; モニタ信号出力 
	MOV	AL,40H			; c = 0x40; 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	RETF 
 
endif ;((SSW EQ 0) OR (SSW EQ 1)) 
if ((SSW EQ 0) OR (SSW EQ 2)) 
;************************************************ 
;* 割込みハンドラの開始				* 
;************************************************ 
 
;				T_CTX 構造体 
;	!______!		     + 0!STKHQQ!<- TCBの退避SP 
;	!______!		     + 2!__ES__! 
;	!______!		     + 4!__DS__! 
;	!______!		     + 6!__DI__! 
;	!______!		     + 8!__SI__! 
;	!______!		     +10!__BP__! 
;	!______!		     +12!_(SP)_! 
;	!______!      コンテキスト退避     +14!__BX__! 
;	!______!        ----->       +16!__DX__! 
;	!______!		     +18!__CX__! 
;	!______!		     +20!__AX__! 
;	!__IP'_!<- 本関数入口でのSP  +22!__アキ__! 
;	!__CS'_!		     +24!__アキ__! 
;	!__IP__!-・ 		     +26!__IP__! 
;	!__CS__! | 割込みによる退避  +28!__CS__! 
;	!_FLAGS!-・		     +30!_FLAGS! 
 
	PUBLIC	ENT_INT 
ENT_INT:				; void far pascal ent_int(void) 
 
if (@Cpu AND 2) 
	PUSHA				; 80186 以上なら PUSHA 命令で 
else 
	PUSH	AX			; AX 退避 
	PUSH	CX			; CX 退避 
	PUSH	DX			; DX 退避 
	PUSH	BX			; BX 退避 
	SUB	SP,2 
	PUSH	BP			; BP 退避 
	PUSH	SI			; SI 退避 
	PUSH	DI			; DI 退避 
endif 
	PUSH	DS			; DS 退避 
	MOV	AX,DGROUP 
	MOV	DS,AX			; DS 設定 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	MOV	AH,AL			; c = (c & ~0x70) 
	ADD	AH,10H			;   | ((c + 0x10) & 0x30) | 0x40; 
	AND	AX,308FH		; bit5-4 = 割込みネストレベル 
	OR	AH,40H			; bit6   = 割込み禁止(1) 
	OR	AL,AH 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	CLD 
	PUSH	ES			; ES 退避 
	PUSH	[STKHQQ]		; STKHQQ 退避 
 
	MOV	BP,SP 
	MOV	SI,[BP+CTX_AX+2]	; リターンアドレス(IP')を得る 
	MOV	DI,[BP+CTX_AX+4]	; リターンアドレス(CS')を得る 
 
	SUB	[_INEST],1		; if (--INEST == -1) 
	JNC	ent_int_8		; { 
	MOV	BX,[_RDQ] 
	MOV	[BX+TCB_SP+2],SS	;   RDQ[0].head->sp = SS:SP; 
	MOV	[BX+TCB_SP],SP 
	MOV	SS,[_ISP+2]		;   SS:SP = ISP; 
	MOV	SP,[_ISP] 
ent_int_8:				; } 
	PUSH	DI			; リターンアドレス(CS')をPUSH 
	PUSH	SI			; リターンアドレス(IP')をPUSH 
	RETF				; return; 
 
endif ;((SSW EQ 0) OR (SSW EQ 2)) 
if ((SSW EQ 0) OR (SSW EQ 3)) 
;************************************************ 
;* 割込みハンドラの開始(CodeViewデバッグ用)	* 
;************************************************ 
 
	PUBLIC	ENT_INT2 
ENT_INT2:				; int far pascal ent_int2(void) 
 
if (@Cpu AND 2) 
	PUSHA				; 80186 以上なら PUSHA 命令で 
else 
	PUSH	AX			; AX 退避 
	PUSH	CX			; CX 退避 
	PUSH	DX			; DX 退避 
	PUSH	BX			; BX 退避 
	SUB	SP,2 
	PUSH	BP			; BP 退避 
	PUSH	SI			; SI 退避 
	PUSH	DI			; DI 退避 
endif 
	PUSH	DS			; DS 退避 
	MOV	AX,DGROUP 
	MOV	DS,AX			; DS 設定 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	MOV	AH,AL			; c = (c & ~0x70) 
	ADD	AH,10H			;   | ((c + 0x10) & 0x30) | 0x40; 
	AND	AX,308FH		; bit5-4 = 割込みネストレベル 
	OR	AH,40H			; bit6   = 割込み禁止(1) 
	OR	AL,AH 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	CLD 
	PUSH	ES			; ES 退避 
	PUSH	[STKHQQ]		; STKHQQ 退避 
 
	MOV	BP,SP 
	MOV	SI,[BP+CTX_AX+2]	; リターンアドレス(IP')を得る 
	MOV	DI,[BP+CTX_AX+4]	; リターンアドレス(CS')を得る 
	MOV	AX,[BP+CTX_CS]		; AX = 割込み時のCS 
 
	SUB	[_INEST],1		; if (--INEST == -1) 
	JNC	ent_int_6		; { 
	MOV	BX,[_RDQ] 
	MOV	[BX+TCB_SP+2],SS	;   RDQ[0].head->sp = SS:SP; 
	MOV	[BX+TCB_SP],SP 
	MOV	SS,[_ISP+2]		;   SS:SP = ISP; 
	MOV	SP,[_ISP] 
ent_int_6:				; } 
	CMP	AX,[_TOPCS]		; 割込み時のCS値判断 
	JB	ent_int_7 
	CMP	AX,DGROUP 
	JA	ent_int_7		; if (TOPCS <= AX && AX <= DGROUP) 
	XOR	AX,AX			;   AX = 0; ユーザコード内 
ent_int_7: 
	PUSH	DI			; リターンアドレス(CS')をPUSH 
	PUSH	SI			; リターンアドレス(IP')をPUSH 
	RETF				; return AX; 
 
endif ;((SSW EQ 0) OR (SSW EQ 3)) 
if ((SSW EQ 0) OR (SSW EQ 1)) 
;************************************************ 
;* 割込みハンドラから復帰する			* 
;************************************************ 
 
	PUBLIC	RET_INT 
RET_INT:				; void far pascal ret_int(void) 
 
	ADD	SP,2*2			; リターンアドレス破棄 
ret_int_2: 
 
	CLI				; CPU割込み禁止 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	OR	AL,40H			; c |= 0x40; 割込み禁止 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
 
ifdef PIC 
	CALL	FAR PTR VDIS_PIC	; PIC割込みマスク 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	AND	AL,0BFH			; c &= ~0x40; 割込み許可 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	STI				; CPU割込み許可 
endif 
 
	INC	[_INEST]		; if (++INEST == 0) 
	JNZ	ret_int_4		; { 
	SHR	[_DELAY],1		;    if (DELAY != 0) 
	JNC	ret_int_3		;    { 
	CALL	SCHEDULE		;       schedule(); 
ret_int_3:				;    } 
	MOV	BX,[_RDQ] 
ifdef MON				;    モニタ信号出力 
	MOV	AL,_MONSIG		;    c = MONSIG; 
	AND	AL,0F0H			;    c = (c & 0xf0) 
	MOV	AH,[BX+TCB_TID]		;      | (RDQ[0].tid & 0x0f); 
	AND	AH,0FH			;    bit3-0 = タスクID 
	OR	AL,AH 
	OUT	MON,AL			;    outp(MON, c); 
	MOV	_MONSIG,AL		;    MONSIG = c; 
endif 
	MOV	SS,[BX+TCB_SP+2]	;    SS:SP = RDQ[0].head->sp 
	MOV	SP,[BX+TCB_SP] 
ret_int_4:				; } 
	POP	[STKHQQ]		; STKHQQ 復元 
 
ifdef PIC 
	CLI				; CPU割込み禁止 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	OR	AL,40H			; c |= 0x40; 割込み禁止 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	CALL	FAR PTR VENA_PIC	; PIC割込みマスク解除 
endif 
 
	POP	ES			; ES 復元 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	MOV	AH,AL			; c = (c & ~0x70) 
	SUB	AH,10H			;   | ((c - 0x10) & 0x30); 
	AND	AX,308FH		; bit6   = 割込み許可(0) 
	OR	AL,AH			; bit4,5 = 割込みネストレベル 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	POP	DS			; DS 復元 
if (@Cpu AND 2) 
	POPA				; 80186 以上なら POPA 命令で 
else 
	POP	DI			; DI 復元 
	POP	SI			; SI 復元 
	POP	BP			; BP 復元 
	ADD	SP,2 
	POP	BX			; BX 復元 
	POP	DX			; DX 復元 
	POP	CX			; CX 復元 
	POP	AX			; AX 復元 
endif 
	ADD	SP,2*2			; アキ 
	IRET				; IP,CS,FLAGS 復元 
 
;************************************************ 
;* 割込み処理復帰とタスク起床を行う		* 
;************************************************ 
 
	PUBLIC	RET_WUP 
RET_WUP:				; void far pascal ret_wup(ID tskid) 
 
	ADD	SP,2*2			; リターンアドレス破棄 
	PUSH	CS 
	CALL	NEAR PTR WUP_TSK	; wup_tsk(tskid); 
	JMP	ret_int_2		; --> 以下 ret_int() と同じ 
 
endif ;((SSW EQ 0) OR (SSW EQ 1)) 
if ((SSW EQ 0) OR (SSW EQ 1)) 
;****************************************************************************** 
;*                                                                            * 
;*                            カーネル内部関数                                * 
;*                                                                            * 
;****************************************************************************** 
;************************************************ 
;* コンテキスト切替え    			* 
;************************************************ 
 
;				T_CTX 構造体 
;	!______!		     + 0!STKHQQ!<- TCBの退避SP 
;	!______!		     + 2!__ES__! 
;	!______!		     + 4!__DS__! 
;	!______!		     + 6!__DI__! 
;	!______!		     + 8!__SI__! 
;	!______!		     +10!__BP__! 
;	!______!		     +12!_(SP)_! 
;	!______!      コンテキスト退避     +14!_(BX)_! 
;	!______!        ----->       +16!_(DX)_! 
;	!______!		     +18!_(CX)_! 
;	!______!		     +20!__AX__! AX = E_OK 
;	!______!		     +22!__アキ__! 
;	!______!		     +24!__アキ__! 
;	!______!		     +26!__IP__! 
;	!______!		     +28!__CS__! 
;	!__IP__!<- 本関数入口でのSP  +30!_FLAGS! IF = 1 
 
; C言語から呼ばれるので BX,CX,DX は退避不要. 
; ES も退避不要だが、プロテクトモードで POP する際の一般保護例外回避のため退避 
; +12位置の SP は PUSHA/POPA 命令との互換用. 
 
	PUBLIC	CTXSWITCH 
CTXSWITCH:				; ER near pascal ctxswitch(void) 
 
; コンテキスト退避 
 
	POP	CX			; (POP IP) 
	PUSHF 
	POP	AX 
	OR	AH,02H 
	PUSH	AX			; 割込み許可(IF=1)の FLAGS 退避 
	PUSH	CS			; CS 退避 
	PUSH	CX			; IP 退避 
	SUB	SP,2*2			; アキ 
	XOR	AX,AX			; AX の退避値は E_OK(0); 
if (@Cpu AND 2) 
	PUSHA				; 80186 以上なら PUSHA 命令で 
else 
	PUSH	AX 
	SUB	SP,4*2			; CX,DX,BX,SP は退避不要 
	PUSH	BP			; BP 退避 
	PUSH	SI			; SI 退避 
	PUSH	DI			; DI 退避 
endif 
	PUSH	DS			; DS 退避 
	PUSH	ES			; ES 退避 
	PUSH	[STKHQQ]		; STKHQQ 退避 
 
	MOV	BX,[_RDQ] 
	MOV	[BX+TCB_SP+2],SS	; RDQ[0].head->sp = SS:SP; 
	MOV	[BX+TCB_SP],SP 
 
; 実行タスク選択 
 
	CALL	SCHEDULE		; schedule(); 
 
; コンテキスト復元 
 
	MOV	BX,[_RDQ] 
ifdef MON				; タスクモニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	AND	AL,0F0H			; c = (c & 0xf0) 
	MOV	AH,[BX+TCB_TID]		;   | (RDQ[0].tid & 0x0f); 
	AND	AH,0FH 
	OR	AL,AH 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	MOV	SS,[BX+TCB_SP+2]	; SS:SP = RDQ[0].head->sp 
	MOV	SP,[BX+TCB_SP] 
	POP	[STKHQQ]		; STKHQQ 復元 
 
ifdef PIC 
	CLI				; 割込み禁止 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	OR	AL,40H			; c |= 0x40; 割込み禁止 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	CALL	FAR PTR VENA_PIC	; PIC割込みマスク解除 
endif 
 
	POP	ES			; ES 復元 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	AND	AL,0BFH			; c &= ~0x40; 割込み許可 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	POP	DS			; DS 復元 
if (@Cpu AND 2) 
	POPA				; 80186 以上なら POPA 命令で 
else 
	POP	DI			; DI 復元 
	POP	SI			; SI 復元 
	POP	BP			; BP 復元 
	ADD	SP,2 
	POP	BX			; BX 復元 
	POP	DX			; DX 復元 
	POP	CX			; CX 復元 
	POP	AX			; AX 復元 
endif 
	ADD	SP,2*2			; アキ 
	IRET				; IP,CS,FLAGS 復元 
 
;************************************************ 
;* タスク起動時のコンテキスト初期化		* 
;************************************************ 
 
	PUBLIC	INIT_CTX 
INIT_CTX:			; void near pascal init_ctx(T_CTX far *ctx) 
	RET	4 
 
;************************************************ 
;* システムコール入口での割込みマスク		* 
;************************************************ 
 
	PUBLIC	SET_IMASK 
SET_IMASK:				; void near pascal set_imask(void) 
 
	PUSHF 
	POP	AX 
	NOT	AX 
	AND	AX,0200H 
	CLI				; CPU割込み禁止 
	MOV	[_IMASK],AX		; IMASK = ~(割込み禁止前のIF); 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	OR	AL,40H			; c |= 0x40; 割込み禁止 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
 
ifdef PIC 
	CALL	FAR PTR VDIS_PIC	; PIC割込みマスク 
	CMP	[_IMASK],0		; if (IMASK == 0) 
	JNZ	set_imask_4		; { 
ifdef MON				;    モニタ信号出力 
	MOV	AL,_MONSIG		;    c = MONSIG; 
	AND	AL,0BFH			;    c &= ~0x40; 割込み許可 
	OUT	MON,AL			;    outp(MON, c); 
	MOV	_MONSIG,AL		;    MONSIG = c; 
endif 
	STI				;    CPU割込み許可 
set_imask_4:				; } 
endif 
 
	RET 
 
;************************************************ 
;* システムコール出口での割込みマスク復元	* 
;************************************************ 
 
	PUBLIC	RET_IMASK 
RET_IMASK:				; ER near pascal ret_imask(void) 
 
ifdef PIC 
	CLI 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	OR	AL,40H			; c |= 0x40; 割込み禁止 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	CALL	FAR PTR VENA_PIC	; PIC割込みマスク解除 
endif 
 
	CMP	[_IMASK],0		; if (IMASK == 0) 
	JNZ	ret_imask_4		; { 
ifdef MON				;    モニタ信号出力 
	MOV	AL,_MONSIG		;    c = MONSIG; 
	AND	AL,0BFH			;    c &= ~0x40; 割込み許可 
	OUT	MON,AL			;    outp(MON, c); 
	MOV	_MONSIG,AL		;    MONSIG = c; 
endif 
	STI				;    CPU割込み許可 
ret_imask_4:				; } 
	XOR	AX,AX			; return E_OK; 
	RET 
 
;************************************************ 
;* タイマ処理中の割込みマスク一時解除		* 
;************************************************ 
 
	PUBLIC	OPE_IMASK 
OPE_IMASK:				; void near pascal ope_imask(void) 
 
	CMP	[_IMASK],0		; if (IMASK != 0) 
	JNZ	ope_imask_4		;    return; 
 
ifdef PIC 
	CLI				; CPU割込み禁止 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	OR	AL,40H			; c |= 0x40; 割込み禁止 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	CALL	FAR PTR VENA_PIC	; PIC割込みマスク解除 
endif 
 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	AND	AL,0BFH			; c &= ~0x40; 割込み許可 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	STI				; CPU割込み許可 
	NOP				; 他の割込みを入れる 
	CLI				; CPU割込み禁止 
	MOV	[_IMASK],0		; IMASK = 0; 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	OR	AL,40H			; c |= 0x40; 割込み禁止 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
 
ifdef PIC 
	CALL	FAR PTR VDIS_PIC	; PIC割込みマスク 
ifdef MON				; モニタ信号出力 
	MOV	AL,_MONSIG		; c = MONSIG; 
	AND	AL,0BFH			; c &= ~0x40; 割込み許可 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	STI				; CPU割込み許可 
endif 
 
ope_imask_4: 
	RET 
 
endif ;((SSW EQ 0) OR (SSW EQ 1)) 
;****************************************************************************** 
;*                                                                            * 
;*                         独自システムコール関数                             * 
;*                                                                            * 
;****************************************************************************** 
if ((SSW EQ 0) OR (SSW EQ 4)) 
;************************************************ 
;* CPUフラグレジスタのIFクリア(割込み禁止)	* 
;************************************************ 
 
	PUBLIC	VDIS_PSW 
VDIS_PSW:				; UINT far pascal vdis_psw(void) 
 
	PUSHF 
	POP	AX			; 戻値は割込み禁止前のFLAGS 
	CLI				; CPU割込み禁止 
ifdef MON				; モニタ信号出力 
	MOV	BX,AX 
	MOV	AL,_MONSIG		; c = MONSIG; 
	OR	AL,40H			; c |= 0x40; 割込み禁止 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
	MOV	AX,BX 
endif 
	RETF 
 
endif ;((SSW EQ 0) OR (SSW EQ 4)) 
if ((SSW EQ 0) OR (SSW EQ 4)) 
;************************************************ 
;* CPUフラグレジスタ設定			* 
;************************************************ 
 
	PUBLIC	VSET_PSW 
VSET_PSW:				; void far pascal vset_psw(UINT psw) 
 
	POP	CX 
	POP	BX 
ifdef MON				; モニタ信号出力 
	POP	AX 
	PUSH	AX 
	CLI 
	MOV	AL,_MONSIG		; c = MONSIG; 
	AND	AL,0BFH			; c &= ~0x40; 割込み許可 
	AND	AH,02H 
	JNZ	vset_psw_2		; if (!(psw & IF)) 
	OR	AL,40H			;   c |= 0x40; 割込み禁止 
vset_psw_2: 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
endif 
	POPF				; FLAGS = psw; 
	PUSH	BX 
	PUSH	CX 
	RETF 
 
endif ;((SSW EQ 0) OR (SSW EQ 4)) 
if ((SSW EQ 0) OR (SSW EQ 1)) 
;************************************************ 
;* ユーザ用モニタ信号出力			* 
;************************************************ 
 
	PUBLIC	OUT_USRSIG 
OUT_USRSIG:				; void far pascal out_usrsig(BOOL on) 
 
ifdef MON 
	MOV	CX,BP 
	MOV	BP,SP 
	PUSHF 
	CLI 
	MOV	AL,_MONSIG		; c = MONSIG; 
	AND	AL,7FH			; c &= ~0x80; 
	CMP	WORD PTR [BP+4],0 
	JZ	out_usrsig_2		; if (on) 
	OR	AL,80H			;   c |= 0x80; 
out_usrsig_2: 
	OUT	MON,AL			; outp(MON, c); 
	MOV	_MONSIG,AL		; MONSIG = c; 
	POPF 
	MOV	BP,CX 
endif 
	RETF	2 
 
endif ;((SSW EQ 0) OR (SSW EQ 1)) 
 
_TEXT	ENDS 
 
ifdef ROM 
;****************************************************************************** 
;*                                                                            * 
;*                               ROM化用                                   * 
;*                                                                            * 
;****************************************************************************** 
 
	EXTRN	SYSINI_COM:NEAR 
 
;* TURBO-C ROM化でのスタックセグメント 
 
ifdef TC 
_STACK	SEGMENT	PARA STACK 'STACK' 
_STACK	ENDS 
DGROUP	GROUP	_STACK 
else 
 
;* MS-C ROM化でのスタックセグメント 
 
STACK	SEGMENT	PARA STACK 'STACK' 
STACK	ENDS 
endif 
 
; ROM化では、sysini_rom() で現在の SP 値から上記スタックセグメントの先頭まで、 
; タスクのスタックを確保できると判断しています。 
; TURBO-C ラージ/コンパクトの ROM 化では、標準の sysini を使います。 
 
_TEXT	SEGMENT 
;************************************************ 
;* システム初期化(ROM化)			* 
;************************************************ 
 
	PUBLIC	SYSINI_ROM 
SYSINI_ROM:				; void far pascal sysini_rom(void) 
 
	CLI				; CPU 割込み禁止 
	MOV	AX,SS 
	CMP	AX,DGROUP		; SS == DGROUP ? 
	MOV	AX,0			; No  : STKHQQ = 0; 
	JNZ	sysini_3 
ifdef TC 
	MOV	AX,_STACK 
else 
	MOV	AX,STACK 
endif 
	SUB	AX,DGROUP		; (注) 
	MOV	CL,4			; 
	SHL	AX,CL			; Yes : STKHQQ = offset DGROUP:_STACK 
sysini_3: 
	JMP	SYSINI_COM 
 
; (注) TASM では、MOV AX,offset DGROUP:_STACK を行えないので実行時に計算 
 
_TEXT	ENDS 
 
endif ;ROM 
 
	END