Index: asp_nios2/trunk/arch/nios2_gcc/prc_support.S
===================================================================
--- asp_nios2/trunk/arch/nios2_gcc/prc_support.S	(revision 1)
+++ asp_nios2/trunk/arch/nios2_gcc/prc_support.S	(revision 14)
@@ -4,5 +4,5 @@
  *      Advanced Standard Profile Kernel
  *
- *  Copyright (C) 2008 by Embedded and Real-Time Systems Laboratory
+ *  Copyright (C) 2008-2011 by Embedded and Real-Time Systems Laboratory
  *              Graduate School of Information Science, Nagoya Univ., JAPAN
  *
@@ -56,4 +56,9 @@
 
 /*
+ * 標準外の例外を用いる
+ */
+#define USE_EXTRA_EXCEPTION
+
+/*
  * スタック操作 : プッシュ
  */
@@ -93,4 +98,5 @@
 interrupt:
 	addi ea, ea, -4      /* 戻り番地をデクリメント */
+
 	/*
 	 *  コンテキストの保存
@@ -117,25 +123,4 @@
 	stw   ra,  68(sp)
 	stw   ea,  72(sp)
-
-	/*
-	 *  多重割込みか判定
-	 */
-	ldw   r3, %gprel(except_nest_count)(gp)  /* ネスト回数のチェック */
-	bltu  zero, r3,  nest_int
-
-	/*
-	 * スタックポインタの入れ替え
-	 */
-	ldw   r2, %gprel(_kernel_istkpt)(gp)
-	addi  r2, r2, -4
-	stw   sp, 0(r2)     /* スタックポインタの保存 */        
-	mov   sp, r2        /* スタックポインタの入れ替え */
-
-nest_int:
-	/* 
-	 *  割込み・例外のネスト回数のインクリメント
-	 */
-	addi  r3, r3, 1
-	stw   r3, %gprel(except_nest_count)(gp)
 
 	/*
@@ -179,4 +164,25 @@
 
 	/*
+	 *  多重割込みか判定
+	 */
+	ldw   r3, %gprel(except_nest_count)(gp)  /* ネスト回数のチェック */
+	bltu  zero, r3,  nest_int
+
+	/*
+	 * スタックポインタの入れ替え
+	 */
+	ldw   r2, %gprel(_kernel_istkpt)(gp)
+	addi  r2, r2, -4
+	stw   sp, 0(r2)     /* スタックポインタの保存 */        
+	mov   sp, r2        /* スタックポインタの入れ替え */
+
+nest_int:
+	/* 
+	 *  割込み・例外のネスト回数のインクリメント
+	 */
+	addi  r3, r3, 1
+	stw   r3, %gprel(except_nest_count)(gp)
+
+	/*
 	 *  割込み要因の割込み優先度を求め(モデル上の)割込み優先度マスクをセット
 	 *  する．またその際，ハンドラ実行前の(モデル上の)割込み優先度マスクを
@@ -245,5 +251,4 @@
 	and   r3, r3, r4
 	wrctl status, r3
-test1:
 
 /*
@@ -355,5 +360,17 @@
 
 	/*
-	 * 多重割込みか判定
+	 * カーネル管理外のCPU例外か判定する
+	 * 
+	 * カーネル管理外のCPU例外は，カーネル実行中，全割込みロック状態，
+	 * CPUロック状態，カーネル管理外の割込みハンドラ実行中に発生した
+	 * CPU例外である．
+	 * Nios2の場合は，PIEが'0'の場合が相当する．
+	 */
+	rdctl r3, estatus
+	andi  r3, r3, STATUS_PIE
+	beq   r3, zero, kernel_unc_exception
+
+	/*
+	 * 例外発生元のコンテキストを判定
 	 */
 	ldw   r3, %gprel(except_nest_count)(gp)  /* ネスト回数のチェック */
@@ -361,5 +378,5 @@
 
 	/*
-	 * スタックポインタの入れ替え
+	 * 発生元がタスクの場合はスタックポインタの入れ替え
 	 */
 	ldw   r2, %gprel(_kernel_istkpt)(gp)
@@ -376,5 +393,5 @@
 
 	/*
-	 *  CPU例外番号の取得(4倍されている)
+	 *  CPU例外ハンドラ番号の取得(4倍されている)
 	 */
 #ifdef USE_EXTRA_EXCEPTION
@@ -420,9 +437,6 @@
 
 	/*
-	 *  例外発生時CPUロック状態でなければCPUロック解除状態とする
-	 */
-	rdctl r3, estatus
-	andi  r3, r3, STATUS_PIE
-	beq   r3, zero, call_exc_handler
+	 *  CPUロック解除状態とする
+	 */
 	rdctl r3, status
 	ori   r3, r3, STATUS_PIE
@@ -431,8 +445,8 @@
 call_exc_handler:
 #ifdef LOG_EXC_ENTER
-	Push  r6         /* CPU例外番号保存               */
+	Push  r6         /* CPU例外ハンドラ番号保存       */
 	Push  r5         /* CPU例外ハンドラアドレス保存   */
 	Push  r4         /* CPU例外フレームの先頭番地保存 */
-	mov   r4, r6     /* CPU例外番号を引数に           */
+	mov   r4, r6     /* CPU例外ハンドラ番号を引数に   */
 	call  log_exc_enter
 	Pop   r4         /* CPU例外フレームの先頭番地復帰 */
@@ -446,5 +460,5 @@
 
 #ifdef LOG_EXC_LEAVE
-	Pop   r4         /* CPU例外番号復帰               */
+	Pop   r4         /* CPU例外ハンドラ番号復帰        */
 	call  log_exc_leave
 #endif /* LOG_EXC_LEAVE */
@@ -550,5 +564,7 @@
 	beq  r6, zero, ret_int_4      /* enatex が false ならリターン */
 	ldw  r7, TCB_texptn(r4)       /* r7 <- texptn, texptnが0でなければ */
-	beq  zero, r7, ret_int_4      
+	beq  zero, r7, ret_int_4
+	ldw  r7, %gprel(ipmflg)(gp)   /* r7 <- ipmflg      */
+	beq  zero, r7, ret_int_4      /* ipmflgがfalseであればリターン */
 	call call_texrtn              /* タスク例外ルーチンの呼び出し */
 
@@ -577,4 +593,140 @@
 	eret 
 
+/*
+ * カーネル管理外のCPU例外の出入口処理
+ */
+kernel_unc_exception:
+	/*
+	 * 例外発生元のコンテキストを判定
+	 */
+	ldw   r3, %gprel(except_nest_count)(gp)  /* ネスト回数のチェック */
+	bltu  zero, r3,  nest_int_exc
+
+	/*
+	 * 発生元がタスクの場合はスタックポインタの入れ替え
+	 */
+	ldw   r2, %gprel(_kernel_istkpt)(gp)
+	addi  r2, r2, -4
+	stw   sp, 0(r2)     /* スタックポインタの保存 */        
+	mov   sp, r2        /* スタックポインタの入れ替え */
+
+nest_int_kernel_unc_exc:
+	/* 
+	 *  割込み・例外のネスト回数のインクリメント
+	 */
+	addi  r4, r3, 1
+	stw   r4, %gprel(except_nest_count)(gp)
+
+	/*
+	 *  CPU例外ハンドラ番号の取得(4倍されている)
+	 */
+#ifdef USE_EXTRA_EXCEPTION
+	rdctl r5, exception
+#else 
+	mov   r5, zero
+#endif /* USE_EXTRA_EXCEPTION */
+	srli  r6, r5, 2
+
+	/*
+	 *  割込み発生前の割込み優先度マスクをスタックに保存
+	 */
+	ldbu  r2, %gprel(iipm)(gp)
+	Push  r2
+
+	/*
+	 *  例外フレームの作成            オフセット
+	 *    例外番号                        0
+	 *    ESTATUS(et)                     4
+	 *    割込み・例外ネストカウント(r3)  8
+	 *    戻りアドレス                   12  
+	 *    割込み優先度マスク(iipm)       16
+	 */
+	addi  sp,  sp, -20
+	stw   r6,  0(sp)
+	stw   et,  4(sp)
+	stw   r3,  8(sp)
+	stw   ea, 12(sp)
+	stw   r2, 16(sp)
+
+	/*
+	 *  例外フレームの先頭番地をCPU例外ハンドラの引数に設定（r4）
+	 */
+	mov   r4, sp
+
+	/*
+	 *  例外ハンドラアドレスの取得
+	 */
+	movhi r2, %hiadj(exch_tbl)  
+	addi  r2, r2, %lo(exch_tbl) 
+	add   r2, r2, r5
+	ldw   r5, 0(r2)
+
+	/* 
+	 *  CPU例外ハンドラ呼び出し 
+	 */
+	callr r5
+
+	/*
+	 *  割込み禁止
+	 */
+	rdctl r3, status
+	movi  r4, ~STATUS_PIE
+	and   r3, r3, r4
+	wrctl status, r3
+
+	/*
+	 *  例外フレームを捨てる
+	 */
+	addi  sp,  sp, 20
+
+	/*
+	 *  (モデル上の)割込み優先度マスクを元に戻す
+	 */
+	Pop   r3                   /* 割込み前の(モデル上の)割込み優先度マスクを取得 */
+	stb   r3, %gprel(iipm)(gp) /* (モデル上の)割込み優先度マスクをセット */
+	slli  r3, r3, 2            /* 割込み優先度マスクを4倍してオフセットを生成    */
+	movhi r2, %hiadj(iipm_mask_tbl) /* 割込み優先度マスクに対応した割込み禁止パターンを取得 */ 
+	addi  r2, r2, %lo(iipm_mask_tbl)
+	add   r2, r2, r3
+	ldw   r5, 0(r2)
+	ldw   r8, %gprel(idf)(gp)       /* 各割込みの割込み要求禁止フラグの状態を取得     */
+	nor   r8, r8, r5                /* 両者のORの否定を生成                           */
+	wrctl ienable, r8               /* 指定した割り込みのみ許可                       */
+
+	/* 
+	 *  割込み・例外のネスト回数のデクリメント
+	 */
+	ldw   r3, %gprel(except_nest_count)(gp)
+	addi  r3, r3, -1
+	stw   r3, %gprel(except_nest_count)(gp)
+
+	bltu  zero, r3, ret_int_1_kernel_unc_exc /* ネスト回数が1以上ならスタックポインタを変更しない */
+
+	ldw   r2, 0(sp)              /* スタックポインタを戻す    */
+	mov   sp, r2
+
+ret_int_1_kernel_unc_exc:
+	ldw   et,   0(sp)  /* レジスタの復帰 */
+	wrctl estatus, et
+	ldw   at,   4(sp)
+	ldw   r2,   8(sp)
+	ldw   r3,  12(sp)
+	ldw   r4,  16(sp)
+	ldw   r5,  20(sp)
+	ldw   r6,  24(sp)
+	ldw   r7,  28(sp)
+	ldw   r8,  32(sp)
+	ldw   r9,  36(sp)
+	ldw   r10, 40(sp)
+	ldw   r11, 44(sp)
+	ldw   r12, 48(sp)
+	ldw   r13, 52(sp)
+	ldw   r14, 56(sp)
+	ldw   r15, 60(sp)
+	ldw   fp,  64(sp)
+	ldw   ra,  68(sp)
+	ldw   ea,  72(sp)
+	addi  sp, sp, 76        
+	eret    
 
 /*
@@ -631,5 +783,7 @@
 	beq  r6, zero, dispatch_r_1   /* enatex が false ならリターン */
 	ldw  r7, TCB_texptn(r4)       /* r7 <- texptn, texptnが0でなければ */
-	beq  r7, zero, dispatch_r_1    
+	beq  r7, zero, dispatch_r_1
+	ldw  r7, %gprel(ipmflg)(gp)   /* r7 <- ipmflg      */
+	beq  zero, r7, dispatch_r_1   /* ipmflgがfalseであればリターン */
 	call call_texrtn              /* タスク例外ルーチンの呼び出し */
 
@@ -767,5 +921,4 @@
 	ldw   r4, TINIB_exinf(r3)     /* r4  <- 引数（exinf）         */
 	ldw   r2, TINIB_task(r3)      /* r2 <- タスクの実行番地       */
-	addi  sp, sp, 8
 	movhi ra, %hiadj(ext_tsk)
 	addi  ra, ra, %lo(ext_tsk)
