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