prc_config.h

説明を見る。
00001 /*
00002  *  TOPPERS/ASP Kernel
00003  *      Toyohashi Open Platform for Embedded Real-Time Systems/
00004  *      Advanced Standard Profile Kernel
00005  * 
00006  *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
00007  *                              Toyohashi Univ. of Technology, JAPAN
00008  *  Copyright (C) 2005-2008 by Embedded and Real-Time Systems Laboratory
00009  *              Graduate School of Information Science, Nagoya Univ., JAPAN
00010  * 
00011  *  上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
00012  *  ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
00013  *  変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
00014  *  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
00015  *      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
00016  *      スコード中に含まれていること.
00017  *  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
00018  *      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
00019  *      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
00020  *      の無保証規定を掲載すること.
00021  *  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
00022  *      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
00023  *      と.
00024  *    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
00025  *        作権表示,この利用条件および下記の無保証規定を掲載すること.
00026  *    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
00027  *        報告すること.
00028  *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
00029  *      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
00030  *      また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
00031  *      由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
00032  *      免責すること.
00033  * 
00034  *  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
00035  *  よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
00036  *  に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
00037  *  アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
00038  *  の責任を負わない.
00039  * 
00040  *  @(#) $Id: prc_config.h 759 2008-03-07 23:01:20Z hiro $
00041  */
00042 
00043 /*
00044  *      プロセッサ依存モジュール(M68040用)
00045  *
00046  *  このインクルードファイルは,target_config.h(または,そこからインク
00047  *  ルードされるファイル)のみからインクルードされる.他のファイルから
00048  *  直接インクルードしてはならない.
00049  */
00050 
00051 #ifndef TOPPERS_PRC_CONFIG_H
00052 #define TOPPERS_PRC_CONFIG_H
00053 
00054 #ifndef TOPPERS_MACRO_ONLY
00055 
00056 /*
00057  *  プロセッサの特殊命令のインライン関数定義
00058  */
00059 #include "prc_insn.h"
00060 
00061 /*
00062  *  タスクコンテキストブロックの定義
00063  */
00064 typedef struct task_context_block {
00065     void    *msp;       /* スタックポインタ */
00066     FP      pc;         /* プログラムカウンタ */
00067 } CTXB;
00068 
00069 #endif /* TOPPERS_MACRO_ONLY */
00070 
00071 /*
00072  *  割込み優先度マスク操作ライブラリ
00073  *
00074  *  M68040では,ステータスレジスタ(SR)の下から8〜10ビットめの3ビット
00075  *  に割込み優先度マスク(ハードウェアの割込み優先度マスク,IPM)が置か
00076  *  れている.IPMを保存しておくために,割込み優先度の外部表現(-1から連
00077  *  続した負の値)を使うことも可能であるが,余計な左右ビットシフトと符
00078  *  号反転が必要になる.これを避けるために,IPMを保存する場合には,SRの
00079  *  8〜10ビットめを取り出した値を使うことにする.この値を割込み優先度マ
00080  *  スクの内部表現と呼び,IIPMと書くことにする.
00081  */
00082 
00083 /*
00084  *  割込み優先度マスクの外部表現と内部表現の変換
00085  */
00086 #define EXT_IPM(iipm)   (-CAST(PRI, (iipm) >> 8))       /* 外部表現に変換 */
00087 #define INT_IPM(ipm)    (CAST(uint16_t, -(ipm)) << 8)   /* 内部表現に変換 */
00088 
00089 #ifndef TOPPERS_MACRO_ONLY
00090 
00091 /*
00092  *  IPM(ハードウェアの割込み優先度マスク,内部表現)の現在値の読出し
00093  */
00094 Inline uint16_t
00095 current_iipm(void)
00096 {
00097     return(current_sr() & 0x0700U);
00098 }
00099 
00100 /*
00101  *  IPM(ハードウェアの割込み優先度マスク,内部表現)の現在値の設定
00102  */
00103 Inline void
00104 set_iipm(uint16_t iipm)
00105 {
00106     set_sr((current_sr() & ~0x0700U) | iipm);
00107 }
00108 
00109 /*
00110  *  TOPPERS標準割込み処理モデルの実現
00111  *
00112  *  M68040は,ステータスレジスタ(SR)中に割込み優先度マスク(ハードウェ
00113  *  アの割込み優先度マスク,IPM)を持っているが,CPUロックフラグに相当
00114  *  する機能を持たない.そのため,CPUロックフラグの機能を,IPMによって
00115  *  実現する.
00116  *
00117  *  まずCPUロックフラグの値(すなわち,CPUロック状態かCPUロック解除状態
00118  *  か)は,そのための変数(lock_flag)を用意して保持する.
00119  *
00120  *  CPUロックフラグがクリアされている間(すなわち,CPUロック解除状態の
00121  *  間)は,IPM(ハードウェアの割込み優先度マスク)を,モデル上の割込み
00122  *  優先度マスクの値に設定する.この間は,モデル上の割込み優先度マスク
00123  *  は,IPMを用いて保持する.
00124  *
00125  *  それに対してCPUロックフラグがセットされている間(すなわち,CPUロッ
00126  *  ク状態の間)は,IPM(ハードウェアの割込み優先度マスク)を,カーネル
00127  *  管理の割込みをすべてマスクする値(TIPM_LOCK)と,モデル上の割込み優
00128  *  先度マスクとの高い方に設定する.この間のモデル上の割込み優先度マス
00129  *  クは,そのための変数(saved_iipm,内部表現で保持)を用意して保持す
00130  *  る.
00131  */
00132 
00133 /*
00134  *  コンテキストの参照
00135  *
00136  *  M68040では,タスクコンテキストをマスタモードで,非タスクコンテキス
00137  *  トを割込みモードで実行する.マスタモードか割込みモードかは,ステー
00138  *  タスレジスタ(SR)中の割込みモードビットにより判別できる.
00139  */
00140 Inline bool_t
00141 sense_context(void)
00142 {
00143     return((current_sr() & 0x1000U) == 0U);
00144 }
00145 
00146 #endif /* TOPPERS_MACRO_ONLY */
00147 
00148 /*
00149  *  CPUロック状態での割込み優先度マスク
00150  *
00151  *  TIPM_LOCKは,カーネル管理の割込みをすべてマスクする値に定義する.具
00152  *  体的には,TMIN_INTPRIが-6の時はTIPM_LOCKを-7に,そうでない場合には
00153  *  TIPM_LOCKをTMIN_INTPRIに一致させる.
00154  */
00155 #if TMIN_INTPRI == -6       /* NMI以外にカーネル管理外の割込みを設けない */
00156 #define TIPM_LOCK       (-7)
00157 #else /* TMIN_INTPRI == -6 */
00158 #if (-1 >= TMIN_INTPRI) && (TMIN_INTPRI > -6)
00159 #define TIPM_LOCK       TMIN_INTPRI
00160 #else /*  (-1 >= TMIN_INTPRI) && (TMIN_INTPRI > -6) */
00161 #error TMIN_INTPRI out of range.
00162 #endif /*  (-1 >= TMIN_INTPRI) && (TMIN_INTPRI > -6) */
00163 #endif /* TMIN_INTPRI == -6 */
00164 
00165 /*
00166  *  CPUロック状態での割込み優先度マスクの内部表現
00167  */
00168 #define IIPM_LOCK       INT_IPM(TIPM_LOCK)
00169 
00170 /*
00171  *  TIPM_ENAALL(割込み優先度マスク全解除)の内部表現
00172  */
00173 #define IIPM_ENAALL     INT_IPM(TIPM_ENAALL)
00174 
00175 #ifndef TOPPERS_MACRO_ONLY
00176 
00177 /*
00178  *  CPUロックフラグ実現のための変数
00179  *
00180  *  これらの変数は,CPUロック状態の時のみ書き換えてよいものとする.
00181  */
00182 extern volatile bool_t      lock_flag;  /* CPUロックフラグの値を保持する変数 */
00183 extern volatile uint16_t    saved_iipm; /* 割込み優先度マスクを保存する変数 */
00184 
00185 /*
00186  *  CPUロック状態への移行
00187  *
00188  *  IPM(ハードウェアの割込み優先度マスク)を,saved_iipmに保存し,カー
00189  *  ネル管理の割込みをすべてマスクする値(TIPM_LOCK)に設定する.また,
00190  *  lock_flagをtrueにする.
00191  *
00192  *  IPMが,最初からTIPM_LOCKと同じかそれより高い場合には,それを
00193  *  saved_iipmに保存するのみで,TIPM_LOCKには設定しない.これは,モデル
00194  *  上の割込み優先度マスクが,TIPM_LOCKと同じかそれより高いレベルに設定
00195  *  されている状態にあたる.
00196  *
00197  *  この関数は,CPUロック状態(lock_flagがtrueの状態)で呼ばれることは
00198  *  ないものと想定している.
00199  */
00200 Inline void
00201 x_lock_cpu(void)
00202 {
00203     uint16_t    iipm;
00204 
00205     /*
00206      *  current_iipm()の返り値を直接saved_iipmに保存せず,一時変数iipm
00207      *  を用いているのは,current_iipm()を呼んだ直後に割込みが発生し,
00208      *  起動された割込み処理でsaved_iipmが変更される可能性があるためで
00209      *  ある.
00210      */
00211     iipm = current_iipm();
00212 #if TIPM_LOCK == -7
00213     disint();
00214 #else /* TIPM_LOCK == -7 */
00215     if (IIPM_LOCK > iipm) {
00216         set_iipm(IIPM_LOCK);
00217     }
00218 #endif /* TIPM_LOCK == -7 */
00219     saved_iipm = iipm;
00220     lock_flag = true;
00221     Asm("":::"memory");
00222 }
00223 
00224 #define t_lock_cpu()    x_lock_cpu()
00225 #define i_lock_cpu()    x_lock_cpu()
00226 
00227 /*
00228  *  CPUロック状態の解除
00229  *
00230  *  lock_flagをfalseにし,IPM(ハードウェアの割込み優先度マスク)を,
00231  *  saved_iipmに保存した値に戻す.
00232  *
00233  *  この関数は,CPUロック状態(lock_flagがtrueの状態)でのみ呼ばれるも
00234  *  のと想定している.
00235  */
00236 Inline void
00237 x_unlock_cpu(void)
00238 {
00239     Asm("":::"memory");
00240     lock_flag = false;
00241     set_iipm(saved_iipm);
00242 }
00243 
00244 #define t_unlock_cpu()  x_unlock_cpu()
00245 #define i_unlock_cpu()  x_unlock_cpu()
00246 
00247 /*
00248  *  CPUロック状態の参照
00249  */
00250 Inline bool_t
00251 x_sense_lock(void)
00252 {
00253     return(lock_flag);
00254 }
00255 
00256 #define t_sense_lock()  x_sense_lock()
00257 #define i_sense_lock()  x_sense_lock()
00258 
00259 /*
00260  *  chg_ipmで有効な割込み優先度の範囲の判定
00261  *
00262  *  TMIN_INTPRIの値によらず,chg_ipmでは,-6〜TIPM_ENAALL(=0)の範囲
00263  *  に設定できることとする(ターゲット定義の拡張).
00264  */
00265 #define VALID_INTPRI_CHGIPM(intpri) \
00266                 ((-6 <= (intpri) && (intpri) <= TIPM_ENAALL))
00267 
00268 /*
00269  * (モデル上の)割込み優先度マスクの設定
00270  *
00271  *  CPUロックフラグがクリアされている時は,ハードウェアの割込み優先度マ
00272  *  スクを設定する.CPUロックフラグがセットされている時は,saved_iipm
00273  *  を設定し,さらに,ハードウェアの割込み優先度マスクを,設定しようと
00274  *  した(モデル上の)割込み優先度マスクとTIPM_LOCKの高い方に設定する.
00275  */
00276 Inline void
00277 x_set_ipm(PRI intpri)
00278 {
00279     uint16_t    iipm = INT_IPM(intpri);
00280 
00281     if (!lock_flag) {
00282         set_iipm(iipm);
00283     }
00284     else {
00285         saved_iipm = iipm;
00286 #if TIPM_LOCK == -7
00287         /*
00288          *  TIPM_LOCKが-7の場合には,この時点でハードウェアの割込み優先
00289          *  度マスクが必ず7に設定されているため,設定しなおす必要がない.
00290          */
00291 #else /* TIPM_LOCK == -7 */
00292         set_iipm(iipm > IIPM_LOCK ? iipm : IIPM_LOCK);
00293 #endif /* TIPM_LOCK == -7 */
00294     }
00295 }
00296 
00297 #define t_set_ipm(intpri)   x_set_ipm(intpri)
00298 #define i_set_ipm(intpri)   x_set_ipm(intpri)
00299 
00300 /*
00301  * (モデル上の)割込み優先度マスクの参照
00302  *
00303  *  CPUロックフラグがクリアされている時はハードウェアの割込み優先度マ
00304  *  スクを,セットされている時はsaved_iipmを参照する.
00305  */
00306 Inline PRI
00307 x_get_ipm(void)
00308 {
00309     uint16_t    iipm;
00310 
00311     if (!lock_flag) {
00312         iipm = current_iipm();
00313     }
00314     else {
00315         iipm = saved_iipm;
00316     }
00317     return(EXT_IPM(iipm));
00318 }
00319 
00320 #define t_get_ipm()     x_get_ipm()
00321 #define i_get_ipm()     x_get_ipm()
00322 
00323 /*
00324  *  最高優先順位タスクへのディスパッチ(prc_support.S)
00325  *
00326  *  dispatchは,タスクコンテキストから呼び出されたサービスコール処理か
00327  *  ら呼び出すべきもので,タスクコンテキスト・CPUロック状態・ディスパッ
00328  *  チ許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さな
00329  *  ければならない.
00330  */
00331 extern void dispatch(void);
00332 
00333 /*
00334  *  ディスパッチャの動作開始(prc_support.S)
00335  *
00336  *  start_dispatchは,カーネル起動時に呼び出すべきもので,すべての割込
00337  *  みを禁止した状態(割込みロック状態と同等の状態)で呼び出さなければ
00338  *  ならない.
00339  */
00340 extern void start_dispatch(void) NoReturn;
00341 
00342 /*
00343  *  現在のコンテキストを捨ててディスパッチ(prc_support.S)
00344  *
00345  *  exit_and_dispatchは,ext_tskから呼び出すべきもので,タスクコンテキ
00346  *  スト・CPUロック状態・ディスパッチ許可状態・(モデル上の)割込み優先
00347  *  度マスク全解除状態で呼び出さなければならない.
00348  */
00349 extern void exit_and_dispatch(void) NoReturn;
00350 
00351 /*
00352  *  カーネルの終了処理の呼出し(prc_support.S)
00353  *
00354  *  call_exit_kernelは,カーネルの終了時に呼び出すべきもので,非タスク
00355  *  コンテキストに切り換えて,カーネルの終了処理(exit_kernel)を呼び出
00356  *  す.
00357  */
00358 extern void call_exit_kernel(void) NoReturn;
00359 
00360 /*
00361  *  タスクコンテキストの初期化
00362  *
00363  *  タスクが休止状態から実行できる状態に移行する時に呼ばれる.この時点
00364  *  でスタック領域を使ってはならない.
00365  *
00366  *  activate_contextを,インライン関数ではなくマクロ定義としているのは,
00367  *  この時点ではTCBが定義されていないためである.
00368  */
00369 extern void start_r(void);
00370 
00371 #define activate_context(p_tcb)                                         \
00372 {                                                                       \
00373     (p_tcb)->tskctxb.msp = (void *)((char *)((p_tcb)->p_tinib->stk)     \
00374                                         + (p_tcb)->p_tinib->stksz);     \
00375     (p_tcb)->tskctxb.pc = (void *) start_r;                             \
00376 }
00377 
00378 /*
00379  *  calltexは使用しない
00380  */
00381 #define OMIT_CALLTEX
00382 
00383 /*
00384  *  例外ベクタテーブルの構造の定義
00385  */
00386 typedef struct exc_vector_entry {
00387     FP      exc_handler;        /* 例外ハンドラの起動番地 */
00388 } EXCVE;
00389 
00390 /*
00391  *  割込みハンドラ番号とCPU例外ハンドラ番号の範囲の判定
00392  */
00393 #define VALID_INHNO_DEFINH(inhno)   ((0x10U <= (inhno) && (inhno) <= 0x1fU) \
00394                                     || (0x40U <= (inhno) && (inhno) <= 0xffU))
00395 #define VALID_EXCNO_DEFEXC(excno)   ((0x02U <= (excno) && (excno) <= 0x0fU) \
00396                                     || (0x20U <= (excno) && (excno) <= 0x3fU))
00397 
00398 /*
00399  *  割込みハンドラの設定
00400  *
00401  *  ベクトル番号inhnoの割込みハンドラの出入口処理の番地をint_entryに設
00402  *  定する.
00403  */
00404 Inline void
00405 x_define_inh(INHNO inhno, FP int_entry)
00406 {
00407     EXCVE   *excvt;
00408 
00409     assert(VALID_INHNO_DEFINH(inhno));
00410 
00411 #ifdef EXCVT_KERNEL
00412     /*
00413      *  EXCVT_KERNELが定義されている時は,初期化処理の中でVBRを
00414      *  EXCVT_KERNELに設定するので,EXCVT_KERNELを使う.
00415      */
00416     excvt = (EXCVE *) EXCVT_KERNEL;
00417 #else /* EXCVT_KERNEL */
00418     excvt = (EXCVE *) current_vbr();
00419 #endif /* EXCVT_KERNEL */
00420     excvt[inhno].exc_handler = int_entry;
00421 }
00422 
00423 /*
00424  *  CPU例外ハンドラの設定
00425  *
00426  *  ベクトル番号excnoのCPU例外ハンドラの出入口処理の番地をexc_entryに設
00427  *  定する.
00428  */
00429 Inline void
00430 x_define_exc(EXCNO excno, FP exc_entry)
00431 {
00432     EXCVE   *excvt;
00433 
00434     assert(VALID_EXCNO_DEFEXC(excno));
00435 
00436 #ifdef EXCVT_KERNEL
00437     /*
00438      *  EXCVT_KERNELが定義されている時は,初期化処理の中でVBRを
00439      *  EXCVT_KERNELに設定するので,EXCVT_KERNELを使う.
00440      */
00441     excvt = (EXCVE *) EXCVT_KERNEL;
00442 #else /* EXCVT_KERNEL */
00443     excvt = (EXCVE *) current_vbr();
00444 #endif /* EXCVT_KERNEL */
00445     excvt[excno].exc_handler = exc_entry;
00446 }
00447 
00448 /*
00449  *  割込みハンドラの出入口処理の生成
00450  */
00451 
00452 /*
00453  *  割込みハンドラの出入口処理のラベルを作るマクロ
00454  */
00455 #define INT_ENTRY(inhno, inthdr)    _kernel_##inthdr##_##inhno
00456 
00457 /*
00458  *  LOG_INH_ENTERがマクロ定義されている場合に,CALL_LOG_INH_ENTERを,
00459  *  inhno_numをパラメータとしてlog_inh_enterを呼び出すアセンブリ言語コー
00460  *  ドにマクロ定義する.
00461  */
00462 #ifdef LOG_INH_ENTER
00463 
00464 #define CALL_LOG_INH_ENTER(inhno_num) \
00465 "   move.l #" #inhno_num ", -(%sp)  \n"  /* inhno_numをパラメータに */ \
00466 "   jsr _kernel_log_inh_enter       \n"  /* log_inh_enterを呼び出す */ \
00467 "   addq.l #4, %sp                  \n"
00468 
00469 #else /* LOG_INH_ENTER */
00470 #define CALL_LOG_INH_ENTER(inhno_num)
00471 #endif /* LOG_INH_ENTER */
00472 
00473 #ifdef LOG_INH_LEAVE
00474 
00475 /*
00476  *  CALL_LOG_INH_LEAVEを,inhno_numをパラメータとしてlog_inh_leaveを呼
00477  *  び出すアセンブリ言語コードにマクロ定義する.
00478  */
00479 #define CALL_LOG_INH_LEAVE(inhno_num) \
00480 "   move.l #" #inhno_num ", -(%sp)  \n"  /* inhno_numをパラメータに */ \
00481 "   jsr _kernel_log_inh_leave       \n"  /* log_inh_leaveを呼び出す */ \
00482 "   addq.l #4, %sp                  \n"
00483 
00484 /*
00485  *  LOG_INH_LEAVEがマクロ定義されている場合の割込みハンドラの出入口処理.
00486  *  割込みハンドラをサブルーチンコールし,戻ってきたら,トレースログの
00487  *  取得後,ret_intに分岐する.
00488  */
00489 #define INTHDR_ENTRY(inhno, inhno_num, inthdr) \
00490 extern void _kernel_##inthdr##_##inhno(void); \
00491 asm(".text                          \n" \
00492 "_kernel_" #inthdr "_" #inhno ":    \n" \
00493 "   movem.l %d0-%d1/%a0-%a1, -(%sp) \n"  /* スクラッチレジスタを保存 */ \
00494     CALL_LOG_INH_ENTER(inhno_num) \
00495 "   jsr " #inthdr "                 \n"  /* 割込みハンドラを呼び出す */ \
00496     CALL_LOG_INH_LEAVE(inhno_num) \
00497 "   jmp _kernel_ret_int             \n");/* ret_intへ分岐 */
00498 
00499 #else /* LOG_INH_LEAVE */
00500 
00501 /*
00502  *  LOG_INH_LEAVEがマクロ定義されていない場合の割込みハンドラの出入口処
00503  *  理.戻り番地としてret_intをスタックに積んだ後,割込みハンドラの起動
00504  *  番地に分岐する.割込みハンドラからのリターンにより,ret_intへ分岐す
00505  *  る.
00506  */
00507 #define INTHDR_ENTRY(inhno, inhno_num, inthdr) \
00508 extern void _kernel_##inthdr##_##inhno(void); \
00509 asm(".text                          \n" \
00510 "_kernel_" #inthdr "_" #inhno ":    \n" \
00511 "   movem.l %d0-%d1/%a0-%a1, -(%sp) \n"  /* スクラッチレジスタを保存 */ \
00512     CALL_LOG_INH_ENTER(inhno_num) \
00513 "   move.l #_kernel_ret_int, -(%sp) \n"  /* 戻り番地をスタックに積む */ \
00514 "   jmp " #inthdr "                 \n");/* 割込みハンドラへ分岐 */
00515 
00516 #endif /* LOG_INH_LEAVE */
00517 
00518 /*
00519  *  CPU例外ハンドラの出入口処理の生成
00520  *
00521  *  CPU例外ハンドラは,非タスクコンテキストで実行する.そのため,CPU例
00522  *  外ハンドラを呼び出す前に割込みモードに移行し,リターンしてきた後に
00523  *  元のモードに戻す.元のモードに戻すために,割込みモードに移行する前
00524  *  のSRを割込みスタック上に保存する(リターン先のSRを参照する手もある
00525  *  が,タスクスタック上に保存される場合があり,参照するのが面倒).
00526  */
00527 
00528 /*
00529  *  CPU例外ハンドラの出入口処理のラベルを作るマクロ
00530  */
00531 #define EXC_ENTRY(excno, exchdr)    _kernel_##exchdr##_##excno
00532 
00533 /*
00534  *  LOG_EXC_ENTERがマクロ定義されている場合に,CALL_LOG_EXC_ENTERを,
00535  *  excno_numをパラメータとしてlog_exc_enterを呼び出すアセンブリ言語コー
00536  *  ドにマクロ定義する.
00537  */
00538 #ifdef LOG_EXC_ENTER
00539 
00540 #define CALL_LOG_EXC_ENTER(excno_num) \
00541 "   move.l #" #excno_num ", -(%sp)  \n"  /* excno_numをパラメータに */ \
00542 "   jsr _kernel_log_exc_enter       \n"  /* log_exc_enterを呼び出す */ \
00543 "   addq.l #4, %sp                  \n"
00544 
00545 #else /* LOG_EXC_ENTER */
00546 #define CALL_LOG_EXC_ENTER(excno_num)
00547 #endif /* LOG_EXC_ENTER */
00548 
00549 #ifdef LOG_EXC_LEAVE
00550 
00551 /*
00552  *  CALL_LOG_EXC_LEAVEを,excno_numをパラメータとしてlog_exc_leaveを呼
00553  *  び出すアセンブリ言語コードにマクロ定義する.
00554  */
00555 #define CALL_LOG_EXC_LEAVE(excno_num) \
00556 "   move.l #" #excno_num ", -(%sp)  \n"  /* excno_numをパラメータに */ \
00557 "   jsr _kernel_log_exc_leave       \n"  /* log_exc_leaveを呼び出す */ \
00558 "   addq.l #4, %sp                  \n"
00559 
00560 /*
00561  *  LOG_EXC_LEAVEがマクロ定義されている場合のCPU例外ハンドラの出入口処
00562  *  理.CPU例外ハンドラをサブルーチンコールし,戻ってきたら,トレースロ
00563  *  グの取得後,ret_excに分岐する.
00564  */
00565 #define EXCHDR_ENTRY(excno, excno_num, exchdr) \
00566 extern void _kernel_##exchdr##_##excno(void *sp); \
00567 asm(".text                          \n" \
00568 "_kernel_" #exchdr "_" #excno ":    \n" \
00569 "   movem.l %d0-%d1/%a0-%a1, -(%sp) \n"  /* スクラッチレジスタを保存 */ \
00570 "   lea.l 16(%sp), %a0              \n"  /* 例外フレームの先頭をA0に */ \
00571 "   move.w %sr, %d0                 \n"  /* SRをD0に */ \
00572 "   and.w #~0x1000, %sr             \n"  /* 割込みモード(スタック切換え)*/ \
00573 "   move.l %d0, -(%sp)              \n"  /* 元のSRをスタックに保存 */ \
00574 "   move.l _kernel_lock_flag, %d0   \n"  /* 元のlock_flagをスタックに保存 */ \
00575 "   move.l %d0, -(%sp)              \n" \
00576 "   move.l %a0, -(%sp)              \n"  /* A0をパラメータとして渡す */ \
00577     CALL_LOG_EXC_ENTER(excno_num) \
00578 "   jsr " #exchdr "                 \n"  /* CPU例外ハンドラへ分岐 */ \
00579     CALL_LOG_EXC_LEAVE(excno_num) \
00580 "   jmp _kernel_ret_exc             \n");/* 戻り番地をスタックに積む */
00581 
00582 #else /* LOG_EXC_LEAVE */
00583 
00584 /*
00585  *  LOG_EXC_LEAVEがマクロ定義されていない場合のCPU例外ハンドラの出入口
00586  *  処理.戻り番地としてret_excをスタックに積んだ後,CPU例外ハンドラの
00587  *  起動番地に分岐する.CPU例外ハンドラからのリターンにより,ret_excへ
00588  *  分岐する.
00589  */
00590 #define EXCHDR_ENTRY(excno, excno_num, exchdr) \
00591 extern void _kernel_##exchdr##_##excno(void *sp); \
00592 asm(".text                          \n" \
00593 "_kernel_" #exchdr "_" #excno ":    \n" \
00594 "   movem.l %d0-%d1/%a0-%a1, -(%sp) \n"  /* スクラッチレジスタを保存 */ \
00595 "   lea.l 16(%sp), %a0              \n"  /* 例外フレームの先頭をA0に */ \
00596 "   move.w %sr, %d0                 \n"  /* SRをD0に */ \
00597 "   and.w #~0x1000, %sr             \n"  /* 割込みモード(スタック切換え)*/ \
00598 "   move.l %d0, -(%sp)              \n"  /* 元のSRをスタックに保存 */ \
00599 "   move.l _kernel_lock_flag, %d0   \n"  /* 元のlock_flagをスタックに保存 */ \
00600 "   move.l %d0, -(%sp)              \n" \
00601 "   move.l %a0, -(%sp)              \n"  /* A0をパラメータとして渡す */ \
00602     CALL_LOG_EXC_ENTER(excno_num) \
00603 "   move.l #_kernel_ret_exc, -(%sp) \n"  /* 戻り番地をスタックに積む */ \
00604 "   jmp " #exchdr "                 \n");/* CPU例外ハンドラへ分岐 */
00605 
00606 #endif /* LOG_EXC_LEAVE */
00607 
00608 /*
00609  *  CPU例外の発生した時のコンテキストの参照
00610  *
00611  *  CPU例外の発生した時のコンテキストが,タスクコンテキストの時にfalse,
00612  *  そうでない時にtrueを返す.
00613  */
00614 Inline bool_t
00615 exc_sense_context(void *p_excinf)
00616 {
00617     return((*((uint16_t *) p_excinf) & 0x1000U) == 0U);
00618 }
00619 
00620 /*
00621  *  CPU例外の発生した時のIPM(ハードウェアの割込み優先度マスク,内部表
00622  *  現)の参照
00623  */
00624 Inline uint16_t
00625 exc_get_iipm(void *p_excinf)
00626 {
00627     return(*((uint16_t *) p_excinf) & 0x0700U);
00628 }
00629 
00630 /*
00631  *  CPU例外の発生した時のコンテキストと割込みのマスク状態の参照
00632  *
00633  *  CPU例外の発生した時のシステム状態が,カーネル実行中でなく,タスクコ
00634  *  ンテキストであり,割込みロック状態でなく,CPUロック状態でなく,(モ
00635  *  デル上の)割込み優先度マスク全解除状態である時にtrue,そうでない時
00636  *  にfalseを返す(CPU例外がカーネル管理外の割込み処理中で発生した場合
00637  *  にもfalseを返す).
00638  *
00639  *  M68040では,CPU例外の発生した時のIPM(ハードウェアの割込み優先度マ
00640  *  スク)がすべての割込みを許可する状態であることをチェックすることで,
00641  *  カーネル実行中でないこと,割込みロック状態でないこと,CPUロック状態
00642  *  でないこと,(モデル上の)割込み優先度マスク全解除状態であることの
00643  *  4つの条件をチェックすることができる(CPU例外が発生した時の
00644  *  lock_flagを参照する必要はない).
00645  */
00646 Inline bool_t
00647 exc_sense_intmask(void *p_excinf)
00648 {
00649     return(!exc_sense_context(p_excinf)
00650                     && exc_get_iipm(p_excinf) == IIPM_ENAALL);
00651 }
00652 
00653 /*
00654  *  CPU例外の発生した時のコンテキストと割込み/CPUロック状態の参照
00655  *
00656  *  CPU例外の発生した時のシステム状態が,カーネル実行中でなく,タスクコ
00657  *  ンテキストであり,割込みロック状態でなく,CPUロック状態でない時に
00658  *  true,そうでない時にfalseを返す(CPU例外がカーネル管理外の割込み処
00659  *  理中で発生した場合にもfalseを返す).
00660  *
00661  *  M68040では,CPU例外の発生した時のIPM(ハードウェアの割込み優先度マ
00662  *  スク)がTIPM_LOCKより低いことをチェックすることで,カーネル実行中で
00663  *  ないこと,割込みロック状態でないこと,CPUロック状態でないことの3つ
00664  *  の条件をチェックしている(CPU例外が発生した時のlock_flagは参照して
00665  *  いない).これにより,(モデル上の)割込み優先度マスクをTIPM_LOCKま
00666  *  たはそれより高い値に設定してタスクを実行している時にもfalse が返っ
00667  *  てしまうが,判断を正確にするためのオーバヘッドが大きいことから,許
00668  *  容することにする.
00669  */
00670 Inline bool_t
00671 exc_sense_unlock(void *p_excinf)
00672 {
00673     return(!exc_sense_context(p_excinf)
00674                     && exc_get_iipm(p_excinf) < IIPM_LOCK);
00675 }
00676 
00677 /*
00678  *  プロセッサ依存の初期化
00679  */
00680 extern void prc_initialize(void);
00681 
00682 /*
00683  *  プロセッサ依存の終了時処理
00684  */
00685 extern void prc_terminate(void);
00686 
00687 /*
00688  *  atexitの処理とデストラクタの実行
00689  */
00690 Inline void
00691 call_atexit(void)
00692 {
00693     extern void software_term_hook(void);
00694     void (*volatile fp)(void) = software_term_hook;
00695 
00696     /*
00697      *  software_term_hookへのポインタを,一旦volatile指定のあるfpに代
00698      *  入してから使うのは,0との比較が最適化で削除されないようにするた
00699      *  めである.
00700      */
00701     if (fp != 0) {
00702         (*fp)();
00703     }
00704 }
00705 
00706 #endif /* TOPPERS_MACRO_ONLY */
00707 #endif /* TOPPERS_PRC_CONFIG_H */

Copyright © 2008 by Kijineko Inc.

ホームページ制作