source: asp3_tinet_ecnl_rx/trunk/asp3_dcre/arch/rx630_gcc/prc_support.S@ 337

Last change on this file since 337 was 337, checked in by coas-nagasima, 6 years ago

ASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/plain;charset=UTF-8
File size: 30.9 KB
Line 
1;
2; TOPPERS/ASP Kernel
3; Toyohashi Open Platform for Embedded Real-Time Systems/
4; Advanced Standard Profile Kernel
5;
6; Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
7; Toyohashi Univ. of Technology, JAPAN
8; Copyright (C) 2007 by Embedded and Real-Time Systems Laboratory
9; Graduate School of Information Science, Nagoya Univ., JAPAN
10; Copyright (C) 2010 by Witz Corporation, JAPAN
11; Copyright (C) 2013 by Mitsuhiro Matsuura
12; Copyright (C) 2017 by Cores Co., Ltd. Japan
13;
14; 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
15; ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
16; 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
17; (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
18; 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
19; スコード中に含まれていること.
20; (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
21; 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
22; 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
23; の無保証規定を掲載すること.
24; (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
25; 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
26; と.
27; (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
28; 作権表示,この利用条件および下記の無保証規定を掲載すること.
29; (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
30; 報告すること.
31; (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
32; 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
33; また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
34; 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
35; 免責すること.
36;
37; 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
38; よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
39; に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
40; アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
41; の責任を負わない.
42;
43; @(#) $Id$
44;
45
46;
47; プロセッサ依存モジュール アセンブリ言語部(RX630用)
48;
49#define TOPPERS_MACRO_ONLY
50#define UINT_C(val) (val) /* uint_t型の定数を作るマクロ */
51#define ULONG_C(val) (val) /* ulong_t型の定数を作るマクロ */
52#define CAST(type, val) (val) /* 型キャストを行うマクロ */
53#include "kernel_impl.h"
54
55;
56; ディスパッチャおよび割込み(CPU例外)出入り口のルール:
57; 動作モードを以下のように定義する.
58; ディスパッチャモード:
59; CPUロック状態, 割込み優先度マスク全解除状態,
60; タスクコンテキスト(intnest = 0), タスクスタック
61; 割込み(CPU例外)処理モード
62; 全割込みロック状態(PSWレジスタIビット = 0),
63; 割込み優先度マスク全解除でない状態(IPL != 0)
64; 割込みコンテキスト(intnest != 0), 割込みスタック
65;
66; カーネル管理外割込みのサポート有無と, CPUロック状態, 割込み優先度
67; マスク全解除状態の関係は以下の通りである.
68; カーネル管理外割込み未サポート時:
69; CPUロック状態(PSWレジスタIビット = 0)
70; 割込み優先度マスク全解除状態(IPL = 0)
71; カーネル管理外割込みサポート時:
72; CPUロック状態
73; (PSWレジスタIビット = 0, IPL = IPL_LOCK, lock_flag = true)
74; 割込み優先度マスク全解除状態(saved_ipl = 0)
75;
76; 各構造体ポインタを以下のように各レジスタにアサインする.
77; r15 = p_runtsk ただしディスパッチャの各出口では無効
78; r14 = *p_runtsk dispatcher の中では p_runtsk 確定時に再取得する
79; 各入り口から最初に変数アクセスするときに上記レジスタに保存する.
80;
81; 構造体アライメントへの対応
82; 構造体アライメントが4Byte(アンパック)の場合:
83; 一般的なレジスタ相対アドレッシングが可能
84; 例: mov.l #__kernel_p_runtsk, r15
85; mov.l r0, TCB_sp[r15]
86; 構造体アライメントが4Byteではない(パック)の場合:
87; mov.lのようにロングサイズ指定の場合、相対値は4の倍数のみ有効
88; このため, 一度対象アドレスを求めてからアクセスする必要がある
89; 例: mov.l #__kernel_p_runtsk, r15
90; add #TCB_sp, r15, r5
91; mov.l r0, [r5]
92; 各オフセット値を判断し, 条件アセンブルによりコードを切り替える
93;
94
95;
96; 構造体アクセスのオフセット定義
97;
98#include "offset.h"
99
100;
101; 各種EQU定義(Hファイルの#define定義)
102;
103#include "target_kernel_impl.h"
104#include "prc_kernel_impl.h"
105
106 .global __kernel_istkpt
107
108 .global __kernel_p_runtsk
109 .global __kernel_p_schedtsk
110
111 .global __kernel_dispatch
112 .global __exit_and_dispatch
113 .global __kernel_start_r
114 .global __kernel_call_texrtn
115 .global _kernel_interrupt
116 .global _kernel_exception
117 .global __kernel_intnest
118 .global __kernel_call_exit_kernel
119 .global __kernel_start_dispatch
120
121 .global _ext_tsk
122 .global __kernel_exit_kernel
123
124#if TIPM_LOCK != -15
125 .global __kernel_lock_flag
126 .global __kernel_saved_ipl
127#endif
128
129 .global __kernel_break_wait
130 .global _sil_dly_nse
131
132#if LOG_INH_ENTER == 1
133 .global _kernel_log_inh_enter
134#endif /* LOG_INH_ENTER == 1 */
135#if LOG_INH_LEAVE == 1
136 .global _kernel_log_inh_leave
137#endif /* LOG_INH_LEAVE == 1 */
138#if LOG_EXC_ENTER == 1
139 .global _kernel_log_exc_enter
140#endif /* LOG_EXC_ENTER == 1 */
141#if LOG_EXC_LEAVE == 1
142 .global _kernel_log_exc_leave
143#endif /* LOG_EXC_LEAVE == 1 */
144#if LOG_DSP_ENTER == 1
145 .global _kernel_log_dsp_enter
146#endif /* LOG_DSP_ENTER == 1 */
147#if LOG_DSP_LEAVE == 1
148 .global _kernel_log_dsp_leave
149#endif /* LOG_DSP_LEAVE == 1 */
150
151#ifdef TOPPERS_SUPPORT_OVRHDR
152 .global __kernel_ovrtimer_start
153 .global __kernel_ovrtimer_stop
154#endif /* TOPPERS_SUPPORT_OVRHDR */
155
156;
157; TCB_sp への書込みマクロ
158;
159.macro st_TCB_sp src, tcb, tmp
160#if (TCB_sp % 4) == 0
161 mov.l \src, TCB_sp[\tcb]
162#else
163 add #TCB_sp, \tcb, \tmp
164 mov.l \src, [\tmp]
165#endif
166.endm
167
168;
169; TCB_sp からの読出しマクロ
170;
171.macro ld_TCB_sp dst, tcb, tmp
172#if (TCB_sp % 4) == 0
173 mov.l TCB_sp[\tcb], \dst
174#else
175 add #TCB_sp, \tcb, \tmp
176 mov.l [tmp], \dst
177#endif
178.endm
179
180;
181; TCB_pc への書込みマクロ
182;
183.macro st_TCB_pc src, tcb, tmp
184#if (TCB_pc % 4) == 0
185 mov.l \src, TCB_pc[\tcb]
186#else
187 add #TCB_pc, \tcb, \tmp
188 mov.l \src, [\tmp]
189#endif
190.endm
191
192;
193; TCB_pc からの読出しマクロ
194;
195.macro ld_TCB_pc dst, tcb, tmp
196#if (TCB_pc % 4) == 0
197 mov.l TCB_pc[\tcb], \dst
198#else
199 add #TCB_pc, \tcb, \tmp
200 mov.l [\tmp], \dst
201#endif
202.endm
203
204;
205; TCB_texptn からの読出しマクロ
206;
207.macro ld_TCB_texptn dst, tcb, tmp
208#if (TCB_texptn % 4) == 0
209 mov.l TCB_texptn[\tcb], \dst
210#else
211 add #TCB_texptn, \tcb, \tmp
212 mov.l [\tmp], \dst
213#endif
214.endm
215
216;
217; TCB_p_tinib からの読出しマクロ
218;
219.macro ld_TCB_p_tinib dst, tcb, tmp
220#if (TCB_p_tinib % 4) == 0
221 mov.l TCB_p_tinib[\tcb], \dst
222#else
223 add #TCB_p_tinib, \tcb, \tmp
224 mov.l [\tmp], \dst
225#endif
226.endm
227
228;
229; TINIB_exinf からの読出しマクロ
230;
231.macro ld_TINIB_exinf dst, tinib, tmp
232#if (TINIB_exinf % 4) == 0
233 mov.l TINIB_exinf[\tinib], \dst
234#else
235 add #TINIB_exinf, \tinib, \tmp
236 mov.l [\tmp], \dst
237#endif
238.endm
239
240;
241; TINIB_task からの読出しマクロ
242;
243.macro ld_TINIB_task dst, tinib, tmp
244#if (TINIB_task % 4) == 0
245 mov.l TINIB_task[\tinib], \dst
246#else
247 add #TINIB_task, \tinib, \tmp
248 mov.l [\tmp], \dst
249#endif
250.endm
251
252
253 .section P, CODE
254
255;
256; APIからのタスクディスパッチャ入口
257;
258; 呼び出し条件:
259; ・ディスパッチャモード(ファイルヘッダ参照)
260;
261; ここでは, コンテキストの退避と, 実行再開番地の設定をする.
262;
263__kernel_dispatch:
264#ifdef TOPPERS_SUPPORT_OVRHDR /* (6-5-3-1) */
265 mov.l #255, r1 ; r1にダミー割込み番号
266 bsr __kernel_ovrtimer_stop
267#endif /* TOPPERS_SUPPORT_OVRHDR */
268 pushm r6-r13 ; 非スクラッチレジスタ保存
269 mov.l #__kernel_p_runtsk, r15
270 mov.l [r15], r14
271 st_TCB_sp r0, r14, r5 ; スタックポインタをTCBに保存
272 st_TCB_pc #dispatch_r, r14, r5 ; 実行再開番地をTCBに保存
273 bra dispatcher
274
275;
276; APIへのタスクディスパッチャ出口
277;
278; 呼び出し条件:
279; ・ディスパッチャモード(ファイルヘッダ参照)
280;
281; ここでは, タスク例外ハンドラ呼出しと, コンテキストの復帰をする.
282;
283dispatch_r:
284dispatch_r_rts:
285 popm r6-r13 ; 非スクラッチレジスタ復帰
286#ifdef TOPPERS_SUPPORT_OVRHDR /* (6-5-3-2) */
287 bsr __kernel_ovrtimer_start
288#endif /* TOPPERS_SUPPORT_OVRHDR */
289 rts ; dispatch 呼び出し元へ戻る.
290
291;
292; タスク起動処理(タスク先頭へのタスクディスパッチャ出口)
293;
294; 呼び出し条件:
295; ・ディスパッチャモード(ファイルヘッダ参照)
296;
297; ここでは, CPUロック解除状態にし, タスクを起動する.
298;
299__kernel_start_r:
300#ifdef TOPPERS_SUPPORT_OVRHDR /* (6-5-6-1) */
301 push.l r14
302 bsr __kernel_ovrtimer_start
303 pop r14
304#endif /* TOPPERS_SUPPORT_OVRHDR */
305 mov.l #_ext_tsk, r5
306 push.l r5 ; 戻り番地をスタックに積む
307 ld_TCB_p_tinib r5, r14, r4
308 ld_TINIB_exinf r1, r5, r4 ; 拡張情報を第一引数に設定
309 ld_TINIB_task r5, r5, r4 ; タスクの起動番地を取得
310.if TIPM_LOCK == -15
311 setpsw i ; 割込み許可(CPUロック解除状態)
312.else
313 mov.l #__kernel_lock_flag, r4 ; CPUロック解除状態へ
314 mov.l #0, [r4] ; ここに来るときは必ず saved_ipl の
315 mvtc #00010000H, psw ; 値は 0 のため, 直値を設定する.
316 ; 全割込みロック解除状態( I = 1 )
317 ; 割込み優先度マスク全解除状態( IPL = 0 )
318.endif
319 jmp r5
320
321;
322; カーネル起動からのタスクディスパッチャ入口
323;
324; このルーチンは,カーネル起動時に,すべての割込みを禁止した状態
325; (割込みロック状態と同等)で呼び出される.また,割込みモード(非
326; タスクコンテキストと同等)で呼び出されることを想定している.
327;
328; 呼び出し条件:
329; ・割込み(CPU例外)処理モード(ファイルヘッダ参照)
330;
331; ここでは, ディスパッチャモードに変更する.
332;
333__kernel_start_dispatch:
334 mov.l #__kernel_intnest, r5
335 mov.w #0, [r5] ; タスクコンテキストに切換え
336#if TIPM_LOCK != -15
337 mvtc #(IPL_LOCK | 00010000H), psw ; 全割込みロック解除状態
338 ; 割込み優先度マスク全解除でない状態
339#endif
340
341;
342; タスク終了(現在のコンテキストを捨てる)からのタスクディスパッチャ入口
343;
344; 呼び出し条件:
345; ・ディスパッチャモード(ファイルヘッダ参照)
346;
347; ここでは, 何もすることはない.
348; なお, p_runtsk のアドレス取得だけは行なう.
349;
350__exit_and_dispatch:
351 mov.l #__kernel_p_runtsk, r15
352.if LOG_DSP_ENTER == 1
353 mov.l [r15], r14
354.endif
355;
356; ディスパッチャ本体
357;
358; 呼び出し条件:
359; ・すべてのタスクのコンテキストは保存されている.
360;
361; dispatcher 呼出時のスタック:
362; ・__kernel_dispatch からきた場合 : タスクスタック
363; ・exit_and_dispatch からきた場合:
364; exit_task からきた場合 : タスクスタック
365; カーネル起動時(__kernel_start_dispatch) : 割込みスタック
366; ・ret_int からきた場合 : タスクスタック
367; ・dispatcher_idle_loop からきた場合 : 割込みスタック
368;
369dispatcher:
370.if LOG_DSP_ENTER == 1
371 push.l r15
372 mov.l r14, r1 ; 引数(ディスパッチ元TCB)を設定
373 bsr __kernel_log_dsp_enter
374 pop r15
375.endif
376 mov.l #__kernel_p_schedtsk, r5
377 mov.l [r5], [r15] ; p_schedtsk を p_runtsk に
378 mov.l [r15], r14
379 cmp #0, r14
380 bz dispatcher_pre_idle ; schedtsk がなければアイドルループへ
381 ld_TCB_sp r0, r14, r5 ; タスクスタックポインタを復帰
382.if LOG_DSP_LEAVE == 1
383 push.l r14
384 mov.l r14, r1 ; 引数(ディスパッチ先TCB)を設定
385 bsr __kernel_log_dsp_leave
386 pop r14
387.endif
388 ld_TCB_pc r5, r14, r4
389 jmp r5 ; 実行再開番地へジャンプ
390
391;
392; schdedtskがNULLの場合はアイドルループに入る
393; アイドルループは割込み処理モードで動作させる
394;
395; ここで割込みモードに切り換えるのは,ここで発生する割込み処理に
396; どのスタックを使うかという問題の解決と,割込みハンドラ内でのタ
397; スクディスパッチの防止という2つの意味がある.
398;
399dispatcher_pre_idle:
400 mov.l #__kernel_istkpt,r5
401 mov.l [r5], r0 ; 割込み用のスタックへ切替え
402 mov.l #__kernel_intnest, r5
403 mov.w #1, [r5] ; 非タスクコンテキストに切換え
404#if TIPM_LOCK != -15
405 mov.l #__kernel_lock_flag, r5 ; CPUロック解除状態へ
406 mov.l #0, [r5]
407 mvtc #0, psw ; 優先度0の割込み処理中を偽装
408#endif
409
410dispatcher_idle_loop:
411 setpsw i ; 全割込み許可
412 clrpsw i ; 全割込み禁止
413
414 mov.l #__kernel_p_schedtsk, r4
415 mov.l [r4], r4 ; p_schedtsk -> r4
416 mov.l #__kernel_p_runtsk, r5
417 mov.l [r5], r5 ; p_runtsk -> r5
418 cmp r4, r5 ; p_schedtsk と p_runtsk が同じでディスパッチ要求無しなら
419 beq dispatcher_idle_loop ; アイドルループを繰り返す
420 mov.l #0, [r5] ; reqflgがtrueならfalseにする
421 mov.l #__kernel_intnest, r5
422 mov.w #0, [r5] ; タスクコンテキストに切換え
423#if TIPM_LOCK != -15
424 mov.l #__kernel_lock_flag, r5 ; CPUロック状態へ
425 mov.l #1, [r5]
426 mov.l #__kernel_saved_ipl, r5
427 mov.l #0, [r5]
428 mvtc #(IPL_LOCK | PSW_I_MASK), psw ; 全割込みロック解除状態
429 ; 割込み優先度マスク全解除でない状態
430#endif
431 bra dispatcher ; dispatcher へ戻る
432
433
434;
435; カーネルの終了処理の呼出し
436;
437; モードとスタックを非タスクコンテキスト用に切り替え.
438;
439 .global __kernel_call_exit_kernel
440__kernel_call_exit_kernel:
441#if TIPM_LOCK != -15
442 clrpsw i ; 全割込み禁止
443 mov.l #__kernel_lock_flag, r5 ; CPUロック解除状態へ
444 mov.l #0, [r5]
445#endif
446 mov.l #__kernel_istkpt, r5
447 mov.l [r5], r0 ; 割込み用のスタックへ切替え
448 mov.l #__kernel_intnest, r5
449 mov.w #1, [r5] ; 非タスクコンテキストに切換え
450 bsr __kernel_exit_kernel
451 bra __kernel_call_exit_kernel
452
453
454;
455; 割込み(CPU例外)からのタスクディスパッチャ入口
456;
457; 呼出し条件:
458; ・全割込みロック状態(PSWレジスタIビット = 0)
459; ・割込み優先度マスク全解除でない状態(IPL != 0)
460; ・タスクコンテキスト(intnest=0)
461; ・使用スタックはタスクスタック
462; ・reqflg = true
463;
464; ここでは, ディスパッチャモードに変更し, reqflgをOFFにしてから,
465; 遅延ディスパッチの有無を判断する.
466;
467
468;
469; ret_int先頭でスタックに積まれているPSWレジスタへのオフセット
470; ACC + FPSW + R14--R15 + R1--R5 + PC
471;
472 .equ RET_INT_GET_PSW_OFFSET, (8+4+28+4)
473
474ret_int:
475.if TIPM_LOCK == -15
476 mov.l RET_INT_GET_PSW_OFFSET[r0], r5 ; 割込み/CPU例外発生前のIPL値取得
477 and #PSW_IPL_MASK, r5
478 mvtc r5, psw ; 全割込みロック(CPUロック)状態
479 ; 割込み/CPU例外発生前の割込み優先度
480.else
481 mov.l #__kernel_lock_flag, r5 ; CPUロック状態へ
482 mov.l #1, [r5]
483 mov.l RET_INT_GET_PSW_OFFSET[r0], r5 ; 割込み/CPU例外発生前のIPL値取得
484 and #PSW_IPL_MASK, r5
485 mov.l #__kernel_saved_ipl, r4
486 mov.l r5, [r4]
487 mvtc #(IPL_LOCK | PSW_I_MASK), psw ; 全割込みロック解除状態
488 ; 割込み優先度マスク全解除でない状態
489.endif
490 mov.l #__kernel_p_runtsk, r15
491 mov.l [r15], r14
492 mov.l #__kernel_p_schedtsk, r5
493 mov.l [r5], r5
494 cmp r5, r14 ; p_schedtsk と p_runtsk が同じなら
495 beq ret_int_r_call_tex ; ret_int_r_call_tex へ
496 pushm r6-r13 ; 非スクラッチレジスタ保存
497 st_TCB_sp r0, r14, r5 ; スタックポインタをTCBに保存
498 st_TCB_pc #ret_int_r, r14, r5 ; 実行再開番地をTCBに保存
499 bra dispatcher
500
501;
502; 割込み(CPU例外)へのタスクディスパッチャ出口
503;
504; 呼び出し条件:
505; ・ディスパッチャモード(ファイルヘッダ参照)
506;
507; ここでは, タスク例外ハンドラ呼出しと, 割込み(CPU例外)処理モードへの
508; 変更と, コンテキストの復帰を行い, 割込み(CUP例外)発生元へ戻る.
509;
510__kernel_break_wait: ;タスクモニタ用ラベル
511ret_int_r:
512 popm r6-r13 ; 非スクラッチレジスタ復帰
513ret_int_r_call_tex:
514#ifdef TOPPERS_SUPPORT_OVRHDR /* 6.6.1 & 6.7.1 */
515 push.l r14
516 bsr __kernel_ovrtimer_start
517 pop r14
518#endif /* TOPPERS_SUPPORT_OVRHDR */
519ret_int_r_rte:
520#if TIPM_LOCK != -15
521 clrpsw i ; 全割込み禁止
522 mov.l #__kernel_lock_flag, r5 ; CPUロック解除状態へ
523 mov.l #0, [r5]
524#endif
525 popm r4-r5 ; アキュムレータ復帰
526 mvtaclo r5 ; ACC最下位16bitは0で復帰
527 mvtachi r4
528 popc fpsw ; FPUステータスレジスタ復帰
529 popm r14-r15 ; レジスタ復帰
530 popm r1-r5
531 rte ; 割込み前の処理に戻る
532
533
534;
535; 割込みの出入口処理(アセンブリ言語記述部分)
536;
537; 呼出し条件:
538; ・割込み発生時のH/W処理により, PSWレジスタのIビット=0, IPLは受付け
539; た割込みのIPL.
540; ・スタックは多重割り込みなら割込みスタック, そうでなければ
541; タスクスタック
542; ・割込み発生時のH/W処理により,スタックに割込みからの復帰PCとPSWが
543; 保存されている.
544; ・ベクタテーブルに登録された個別の入り口処理により, スタックに
545; スクラッチレジスタ(R1-R5)が保存されている.
546;
547; 引数:
548; ・r1:割込み要因番号
549; ・r2:割込みハンドラのアドレス
550;
551; レジスタがスタック上にどのように保存されているかを以下に示す.
552; この図では上が低位, 下が高位のアドレスで, スタックは下から
553; 上方向に向かって積み上げられるものとする.
554;
555; -------------------------
556; | ACC-HI(4byte) |
557; -------------------------(SP + 0)
558; | ACC-LO(4byte) |
559; -------------------------(SP + 4)
560; | FPSW(4byte) |
561; -------------------------(SP + 8)
562; | R14(4byte) |
563; -------------------------(SP + 12)
564; | R15(4byte) |
565; -------------------------(SP + 16)
566; | R1(4byte) |
567; -------------------------(SP + 20)
568; | R2(4byte) |
569; -------------------------(SP + 24)
570; | R3(4byte) |
571; -------------------------(SP + 28)
572; | R4(4byte) |
573; -------------------------(SP + 32)
574; | R5(4byte) |
575; -------------------------(SP + 36)
576; | PC(4byte) |
577; -------------------------(SP + 40)
578; | PSW(4byte) |
579; -------------------------(SP + 44)
580;
581; ここでは, 割込み処理モードに変更してハンドラを実行する.
582;
583; ハンドラからリターンした後は, 多重割込みでなく, かつ reqflg が
584; TRUE になった時に,ret_int へ分岐(遅延ディスパッチ)する.
585;
586; 多重割込みかどうかは割込みネストカウンタの値で判定する.
587; intnest != 0 ならば多重割込みであると判定する.
588;
589; reqflg はCPUロック状態でチェックする. そうでないと,
590; reqflg チェック後に起動された割込みハンドラ内で
591; ディスパッチが要求された場合に,ディスパッチされない.
592;
593_kernel_interrupt:
594 pushm r14-r15 ; スクラッチレジスタを退避
595 pushc fpsw ; FPUステータスレジスタ退避
596 mvfacmi r5
597 shll #16, r5 ; ACC最下位16bitは0とする
598 mvfachi r4
599 pushm r4-r5 ; アキュムレータ退避
600 mov.l #__kernel_intnest, r5
601 mov.w [r5], r4
602 add #1, r4 ; ネスト回数をインクリメント
603 mov.w r4, [r5]
604 cmp #1, r4 ; 多重割り込みかどうか
605 bnz interrupt_from_int ; 加算前が0でなければ多重割込み
606 ; 初段の割込み
607#ifdef TOPPERS_SUPPORT_OVRHDR /* 6.6.1 */
608 pushm r1-r5
609 bsr __kernel_ovrtimer_stop ; r1に割込み番号
610 popm r1-r5
611#endif /* TOPPERS_SUPPORT_OVRHDR */
612 mov.l r0, r3 ; スタックポインタを取り出し
613 mov.l #__kernel_istkpt, r5 ; 割込み用のスタックへ切替える
614 mov.l [r5], r0
615 push.l r3 ; タスクスタックを保持
616interrupt_from_int: ; 多重割込み
617 setpsw i ; 割込み許可(CPUロック解除状態)
618
619.if LOG_INH_LEAVE == 1
620 push.l r1 ; ログトレースの引数を保持
621.endif
622
623.if LOG_INH_ENTER == 1
624 push.l r2
625 bsr __kernel_log_inh_enter ; ログトレース関数の呼出し
626 ; 引数の割込み要因番号は既にr1に入っている
627 pop r2
628.endif
629
630 jsr r2 ; Cルーチン呼び出し
631
632.if LOG_INH_LEAVE == 1
633 pop r1 ; 引数に割込み要因番号を設定
634 bsr __kernel_log_inh_leave ; ログトレース関数の呼出し
635.endif
636
637 clrpsw i ; 割込み禁止(CPUロック状態)
638 mov.l #__kernel_intnest, r5
639 mov.w [r5], r4
640 sub #1, r4 ; ネスト回数をデクリメント
641 mov.w r4, [r5]
642 cmp #0, r4 ; 多重割り込みかどうか
643 bnz interrupt_return ; 多重割り込みならリターン
644 ; 初段の割込み
645 pop r0 ; タスクのスタックに戻す
646 mov.l #__kernel_p_schedtsk, r4
647 mov.l [r4], r4 ; p_schedtsk -> r4
648 mov.l #__kernel_p_runtsk, r5
649 mov.l [r5], r5 ; p_runtsk -> r5
650 cmp r4, r5 ; p_schedtsk と p_runtsk が異なりディスパッチ要求有りなら
651 bne ret_int ; ret_int へジャンプ
652#ifdef TOPPERS_SUPPORT_OVRHDR /* 6.6.1 */
653 mov.l #__kernel_p_runtsk, r5
654 mov.l [r5], r4
655 cmp #0, r4
656 beq interrupt_return
657 bsr __kernel_ovrtimer_start
658#endif /* TOPPERS_SUPPORT_OVRHDR */
659interrupt_return:
660 popm r4-r5 ; アキュムレータ復帰
661 mvtaclo r5 ; ACC最下位16bitは0で復帰
662 mvtachi r4
663 popc fpsw ; FPUステータスレジスタ復帰
664 popm r14-r15 ; レジスタ復帰
665 popm r1-r5
666 rte ; 割込み前の処理に戻る
667
668
669;
670; CPU例外の出入口処理(アセンブリ言語記述部分)
671;
672; 呼出し条件:
673; ・CPU例外発生時のH/W処理により, PSWレジスタのIビット=0, IPL=0.
674; ・スタックは多重割り込みなら割込みスタック, そうでなければ
675; タスクスタック
676; ・CPU例外発生時のH/W処理により,スタックにCPU例外からの復帰PCと
677; PSWが保存されている.
678; ・ベクタテーブルに登録された個別の入り口処理により, スタックに
679; スクラッチレジスタ(R1-R5)が保存されている.
680;
681; 引数:
682; ・r1:CPU例外要因番号
683; ・r2:CPU例外ハンドラのアドレス
684;
685; レジスタがスタック上にどのように保存されているかを以下に示す.
686; この図では上が低位, 下が高位のアドレスで, スタックは下から
687; 上方向に向かって積み上げられるものとする.
688; なお, CPU例外要因番号とR6-R13はCPU例外ハンドラ内で情報を取得
689; する目的で退避しており, 出口処理では保存内容を破棄すればよい.
690;
691; -------------------------
692; | CPU例外要因番号 | <----- p_excinf
693; ------------------------- (intptr_t)(p_excinf + 0)
694; | R6(4byte) |
695; ------------------------- (intptr_t)(p_excinf + 4)
696; | R7(4byte) |
697; ------------------------- (intptr_t)(p_excinf + 8)
698; | R8(4byte) |
699; ------------------------- (intptr_t)(p_excinf + 12)
700; | R9(4byte) |
701; ------------------------- (intptr_t)(p_excinf + 16)
702; | R10(4byte) |
703; ------------------------- (intptr_t)(p_excinf + 20)
704; | R11(4byte) |
705; ------------------------- (intptr_t)(p_excinf + 24)
706; | R12(4byte) |
707; ------------------------- (intptr_t)(p_excinf + 28)
708; | R13(4byte) |
709; ------------------------- (intptr_t)(p_excinf + 32)
710; | ACC-HI(4byte) |
711; ------------------------- (intptr_t)(p_excinf + 36)
712; | ACC-LO(4byte) |
713; ------------------------- (intptr_t)(p_excinf + 40)
714; | FPSW(4byte) |
715; ------------------------- (intptr_t)(p_excinf + 44)
716; | R14(4byte) |
717; ------------------------- (intptr_t)(p_excinf + 48)
718; | R15(4byte) |
719; ------------------------- (intptr_t)(p_excinf + 52)
720; | R1(4byte) |
721; ------------------------- (intptr_t)(p_excinf + 56)
722; | R2(4byte) |
723; ------------------------- (intptr_t)(p_excinf + 60)
724; | R3(4byte) |
725; ------------------------- (intptr_t)(p_excinf + 64)
726; | R4(4byte) |
727; ------------------------- (intptr_t)(p_excinf + 68)
728; | R5(4byte) |
729; ------------------------- (intptr_t)(p_excinf + 72)
730; | PC(4byte) |
731; ------------------------- (intptr_t)(p_excinf + 76)
732; | PSW(4byte) |
733; ------------------------- (intptr_t)(p_excinf + 80)
734;
735; ここでは, 割込み処理モードに変更してハンドラを実行する.
736; CPU例外ハンドラに渡すVP型の変数 p_excinf としてISPの値渡す.
737;
738; ハンドラからリターンした後は, 多重割込みでなく, かつ reqflg が
739; TRUE になった時に,ret_int へ分岐(遅延ディスパッチ)する.
740;
741; 多重割込みかどうかは割込みネストカウンタの値で判定する.
742; intnest != 0 ならば多重割込みであると判定する.
743;
744; reqflg はCPUロック状態でチェックする. そうでないと,
745; reqflg チェック後に起動された割込みハンドラ内で
746; ディスパッチが要求された場合に,ディスパッチされない.
747;
748;
749; CPU例外入口処理
750;
751; ここでは, 割込み処理モードに変更してハンドラを実行する.
752;
753
754;
755; CPU例外ハンドラ呼出し後に不要となるスタック情報のサイズ
756; EXCNO + R6--R13
757;
758 .equ EXCINF_REG_SIZE, (4+32)
759
760_kernel_exception:
761 pushm r14-r15 ; スクラッチレジスタを退避
762 pushc fpsw
763 mvfacmi r5
764 shll #16, r5 ; ACC最下位16bitは0とする
765 mvfachi r4
766 pushm r4-r5 ; アキュムレータ退避
767 pushm r6-r13 ; 非スクラッチレジスタ保存
768 push.l r1 ; CPU例外要因番号を保持
769 mov.l r0, r3 ; スタックポインタを取り出し
770 mov.l EXC_GET_PSW_OFFSET[r3], r5
771 and #PSW_I_MASK, r5
772 bz exception_nonkernel ; 全割込み禁止(CPUロック)状態なら管理外
773#if TIPM_LOCK != -15
774 mov.l EXC_GET_PSW_OFFSET[r3], r5
775 and #PSW_IPL_MASK, r5
776 cmp #IPL_LOCK, r5
777 bgt exception_nonkernel ; IPLがCPUロックレベル以上なら管理外
778#endif
779 mov.l #__kernel_intnest, r5
780 mov.w [r5], r4
781 add #1, r4 ; ネスト回数をインクリメント
782 mov.w r4, [r5]
783 cmp #1, r4 ; 多重割り込みかどうか
784 bnz exception_from_int ; 加算前が0でなければ多重割込み
785 ; 初段の割込み
786#ifdef TOPPERS_SUPPORT_OVRHDR /* 6.7.1 */
787 pushm r1-r5
788 mov.l #255, r1 ; r1にダミー割込み番号
789 bsr __kernel_ovrtimer_stop
790 popm r1-r5
791#endif /* TOPPERS_SUPPORT_OVRHDR */
792 mov.l #__kernel_istkpt, r5 ; 割込み用のスタックへ切替える
793 mov.l [r5], r0
794 push.l r3 ; タスクスタックを保持
795exception_from_int: ; 多重割込み
796 mov.l EXC_GET_PSW_OFFSET[r3], r5
797 mvtc r5, psw ; CPU例外発生前の状態に戻す
798#if LOG_EXC_LEAVE == 1
799 push.l r1 ; ログトレースの引数を保持
800#endif
801
802#if LOG_EXC_ENTER == 1
803 pushm r2-r3
804 bsr __kernel_log_exc_enter ; ログトレース関数の呼出し
805 ; 引数の割込み要因番号は既にr1に入っている
806 popm r2-r3
807#endif
808
809 mov.l r3, r1 ; 引数のp_excinfを設定
810 jsr r2 ; Cルーチン呼び出し
811
812.if LOG_EXC_LEAVE == 1
813 pop r1 ; 引数に割込み要因番号を設定
814 bsr __kernel_log_exc_leave ; ログトレース関数の呼出し
815.endif
816
817 clrpsw i ; ここからは必ず割込み禁止
818 mov.l #__kernel_intnest, r5
819 mov.w [r5], r4
820 sub #1, r4 ; ネスト回数をデクリメント
821 mov.w r4, [r5]
822 cmp #0, r4 ; 多重割り込みかどうか
823 bnz exception_return ; 多重割り込みならリターン
824 ; 初段の割込み
825 pop r0 ; タスクのスタックに戻す
826 mov.l #__kernel_p_schedtsk, r4
827 mov.l [r4], r4 ; p_schedtsk -> r4
828 mov.l #__kernel_p_runtsk, r5
829 mov.l [r5], r5 ; p_runtsk -> r5
830 cmp r4, r5 ; p_schedtsk と p_runtsk が同じでディスパッチ要求無しか
831#ifndef TOPPERS_SUPPORT_OVRHDR /* 6.7.1 */
832 beq exception_return ; なければリターン
833 add #EXCINF_REG_SIZE, r0 ; CPU例外情報の破棄
834 bra ret_int ; あれば ret_int へジャンプ
835#else /* TOPPERS_SUPPORT_OVRHDR */
836 beq exception_return_ovr ; なければリターン
837 add #EXCINF_REG_SIZE, r0 ; CPU例外情報の破棄
838 bra ret_int ; あれば ret_int へジャンプ
839exception_return_ovr:
840 mov.l #__kernel_p_runtsk, r5
841 mov.l [r5], r4
842 cmp #0, r4
843 beq exception_return
844 bsr __kernel_ovrtimer_start
845 bra exception_return
846#endif /* TOPPERS_SUPPORT_OVRHDR */
847
848exception_nonkernel:
849 mov.l #__kernel_intnest, r5
850 mov.w [r5], r4
851 add #1, r4 ; ネスト回数をインクリメント
852 mov.w r4, [r5]
853 cmp #1, r4 ; 多重割り込みかどうか
854 bnz exception_from_nonkernelint ; 加算前が0でなければ多重割込み
855 ; 初段の割込み
856 mov.l #__kernel_istkpt, r5 ; 割込み用のスタックへ切替える
857 mov.l [r5], r0
858 push.l r3 ; タスクスタックを保持
859exception_from_nonkernelint: ; 多重割込み
860 mov.l EXC_GET_PSW_OFFSET[r3], r5
861 mvtc r5, psw ; CPU例外発生前の状態に戻す
862
863 mov.l r3, r1 ; 引数のp_excinfを設定
864 jsr r2 ; Cルーチン呼び出し
865
866 clrpsw i ; ここからは必ず割込み禁止
867 mov.l #__kernel_intnest, r5
868 mov.w [r5], r4
869 sub #1, r4 ; ネスト回数をデクリメント
870 mov.w r4, [r5]
871 cmp #0, r4 ; 多重割り込みかどうか
872 bnz exception_return ; 多重割り込みならリターン
873 ; 初段の割込み
874 pop r0 ; タスクのスタックに戻す
875
876exception_return:
877 add #EXCINF_REG_SIZE, r0 ; CPU例外情報の破棄
878 popm r4-r5 ; アキュムレータ復帰
879 mvtaclo r5 ; ACC最下位16bitは0で復帰
880 mvtachi r4
881 popc fpsw ; FPUステータスレジスタ復帰
882 popm r14-r15 ; レジスタ復帰
883 popm r1-r5
884 rte ; 割込み前の処理に戻る
885
886
887;
888; 微少時間待ち
889;
890_sil_dly_nse:
891 mov.l #SIL_DLY_TIM1, r5
892 sub r5, r1
893 ble sil_dly_nse_ret
894sil_dly_nse_loop:
895 mov.l #SIL_DLY_TIM2, r5
896 sub r5, r1
897 bgt sil_dly_nse_loop
898sil_dly_nse_ret:
899 rts
900
901 .end
902
Note: See TracBrowser for help on using the repository browser.