source: UsbWattMeter/trunk/asp_dcre/arch/rx630_ccrx/prc_support.src

Last change on this file was 167, checked in by coas-nagasima, 8 years ago

MIMEにSJISを設定

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