source: rubycfg_asp/trunk/asp_dcre/arch/rx630_ccrx/prc_support.src@ 315

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

SVNプロパティを設定

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