source: azure_iot_hub/trunk/asp3_dcre/arch/rx630_gcc/prc_support.S@ 389

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

ビルドが通るよう更新

  • 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 wait
413 clrpsw i ; 全割込み禁止
414
415 mov.l #__kernel_p_schedtsk, r4
416 mov.l [r4], r4 ; p_schedtsk -> r4
417 mov.l #__kernel_p_runtsk, r5
418 mov.l [r5], r5 ; p_runtsk -> r5
419 cmp r4, r5 ; p_schedtsk と p_runtsk が同じでディスパッチ要求無しなら
420 beq dispatcher_idle_loop ; アイドルループを繰り返す
421 mov.l #0, [r5] ; reqflgがtrueならfalseにする
422 mov.l #__kernel_intnest, r5
423 mov.w #0, [r5] ; タスクコンテキストに切換え
424#if TIPM_LOCK != -15
425 mov.l #__kernel_lock_flag, r5 ; CPUロック状態へ
426 mov.l #1, [r5]
427 mov.l #__kernel_saved_ipl, r5
428 mov.l #0, [r5]
429 mvtc #(IPL_LOCK | PSW_I_MASK), psw ; 全割込みロック解除状態
430 ; 割込み優先度マスク全解除でない状態
431#endif
432 bra dispatcher ; dispatcher へ戻る
433
434
435;
436; カーネルの終了処理の呼出し
437;
438; モードとスタックを非タスクコンテキスト用に切り替え.
439;
440 .global __kernel_call_exit_kernel
441__kernel_call_exit_kernel:
442#if TIPM_LOCK != -15
443 clrpsw i ; 全割込み禁止
444 mov.l #__kernel_lock_flag, r5 ; CPUロック解除状態へ
445 mov.l #0, [r5]
446#endif
447 mov.l #__kernel_istkpt, r5
448 mov.l [r5], r0 ; 割込み用のスタックへ切替え
449 mov.l #__kernel_intnest, r5
450 mov.w #1, [r5] ; 非タスクコンテキストに切換え
451 bsr __kernel_exit_kernel
452 bra __kernel_call_exit_kernel
453
454
455;
456; 割込み(CPU例外)からのタスクディスパッチャ入口
457;
458; 呼出し条件:
459; ・全割込みロック状態(PSWレジスタIビット = 0)
460; ・割込み優先度マスク全解除でない状態(IPL != 0)
461; ・タスクコンテキスト(intnest=0)
462; ・使用スタックはタスクスタック
463; ・reqflg = true
464;
465; ここでは, ディスパッチャモードに変更し, reqflgをOFFにしてから,
466; 遅延ディスパッチの有無を判断する.
467;
468
469;
470; ret_int先頭でスタックに積まれているPSWレジスタへのオフセット
471; ACC + FPSW + R14--R15 + R1--R5 + PC
472;
473 .equ RET_INT_GET_PSW_OFFSET, (8+4+28+4)
474
475ret_int:
476.if TIPM_LOCK == -15
477 mov.l RET_INT_GET_PSW_OFFSET[r0], r5 ; 割込み/CPU例外発生前のIPL値取得
478 and #PSW_IPL_MASK, r5
479 mvtc r5, psw ; 全割込みロック(CPUロック)状態
480 ; 割込み/CPU例外発生前の割込み優先度
481.else
482 mov.l #__kernel_lock_flag, r5 ; CPUロック状態へ
483 mov.l #1, [r5]
484 mov.l RET_INT_GET_PSW_OFFSET[r0], r5 ; 割込み/CPU例外発生前のIPL値取得
485 and #PSW_IPL_MASK, r5
486 mov.l #__kernel_saved_ipl, r4
487 mov.l r5, [r4]
488 mvtc #(IPL_LOCK | PSW_I_MASK), psw ; 全割込みロック解除状態
489 ; 割込み優先度マスク全解除でない状態
490.endif
491 mov.l #__kernel_p_runtsk, r15
492 mov.l [r15], r14
493 mov.l #__kernel_p_schedtsk, r5
494 mov.l [r5], r5
495 cmp r5, r14 ; p_schedtsk と p_runtsk が同じなら
496 beq ret_int_r_call_tex ; ret_int_r_call_tex へ
497 pushm r6-r13 ; 非スクラッチレジスタ保存
498 st_TCB_sp r0, r14, r5 ; スタックポインタをTCBに保存
499 st_TCB_pc #ret_int_r, r14, r5 ; 実行再開番地をTCBに保存
500 bra dispatcher
501
502;
503; 割込み(CPU例外)へのタスクディスパッチャ出口
504;
505; 呼び出し条件:
506; ・ディスパッチャモード(ファイルヘッダ参照)
507;
508; ここでは, タスク例外ハンドラ呼出しと, 割込み(CPU例外)処理モードへの
509; 変更と, コンテキストの復帰を行い, 割込み(CUP例外)発生元へ戻る.
510;
511__kernel_break_wait: ;タスクモニタ用ラベル
512ret_int_r:
513 popm r6-r13 ; 非スクラッチレジスタ復帰
514ret_int_r_call_tex:
515#ifdef TOPPERS_SUPPORT_OVRHDR /* 6.6.1 & 6.7.1 */
516 push.l r14
517 bsr __kernel_ovrtimer_start
518 pop r14
519#endif /* TOPPERS_SUPPORT_OVRHDR */
520ret_int_r_rte:
521#if TIPM_LOCK != -15
522 clrpsw i ; 全割込み禁止
523 mov.l #__kernel_lock_flag, r5 ; CPUロック解除状態へ
524 mov.l #0, [r5]
525#endif
526 popm r4-r5 ; アキュムレータ復帰
527 mvtaclo r5 ; ACC最下位16bitは0で復帰
528 mvtachi r4
529 popc fpsw ; FPUステータスレジスタ復帰
530 popm r14-r15 ; レジスタ復帰
531 popm r1-r5
532 rte ; 割込み前の処理に戻る
533
534
535;
536; 割込みの出入口処理(アセンブリ言語記述部分)
537;
538; 呼出し条件:
539; ・割込み発生時のH/W処理により, PSWレジスタのIビット=0, IPLは受付け
540; た割込みのIPL.
541; ・スタックは多重割り込みなら割込みスタック, そうでなければ
542; タスクスタック
543; ・割込み発生時のH/W処理により,スタックに割込みからの復帰PCとPSWが
544; 保存されている.
545; ・ベクタテーブルに登録された個別の入り口処理により, スタックに
546; スクラッチレジスタ(R1-R5)が保存されている.
547;
548; 引数:
549; ・r1:割込み要因番号
550; ・r2:割込みハンドラのアドレス
551;
552; レジスタがスタック上にどのように保存されているかを以下に示す.
553; この図では上が低位, 下が高位のアドレスで, スタックは下から
554; 上方向に向かって積み上げられるものとする.
555;
556; -------------------------
557; | ACC-HI(4byte) |
558; -------------------------(SP + 0)
559; | ACC-LO(4byte) |
560; -------------------------(SP + 4)
561; | FPSW(4byte) |
562; -------------------------(SP + 8)
563; | R14(4byte) |
564; -------------------------(SP + 12)
565; | R15(4byte) |
566; -------------------------(SP + 16)
567; | R1(4byte) |
568; -------------------------(SP + 20)
569; | R2(4byte) |
570; -------------------------(SP + 24)
571; | R3(4byte) |
572; -------------------------(SP + 28)
573; | R4(4byte) |
574; -------------------------(SP + 32)
575; | R5(4byte) |
576; -------------------------(SP + 36)
577; | PC(4byte) |
578; -------------------------(SP + 40)
579; | PSW(4byte) |
580; -------------------------(SP + 44)
581;
582; ここでは, 割込み処理モードに変更してハンドラを実行する.
583;
584; ハンドラからリターンした後は, 多重割込みでなく, かつ reqflg が
585; TRUE になった時に,ret_int へ分岐(遅延ディスパッチ)する.
586;
587; 多重割込みかどうかは割込みネストカウンタの値で判定する.
588; intnest != 0 ならば多重割込みであると判定する.
589;
590; reqflg はCPUロック状態でチェックする. そうでないと,
591; reqflg チェック後に起動された割込みハンドラ内で
592; ディスパッチが要求された場合に,ディスパッチされない.
593;
594_kernel_interrupt:
595 pushm r14-r15 ; スクラッチレジスタを退避
596 pushc fpsw ; FPUステータスレジスタ退避
597 mvfacmi r5
598 shll #16, r5 ; ACC最下位16bitは0とする
599 mvfachi r4
600 pushm r4-r5 ; アキュムレータ退避
601 mov.l #__kernel_intnest, r5
602 mov.w [r5], r4
603 add #1, r4 ; ネスト回数をインクリメント
604 mov.w r4, [r5]
605 cmp #1, r4 ; 多重割り込みかどうか
606 bnz interrupt_from_int ; 加算前が0でなければ多重割込み
607 ; 初段の割込み
608#ifdef TOPPERS_SUPPORT_OVRHDR /* 6.6.1 */
609 pushm r1-r5
610 bsr __kernel_ovrtimer_stop ; r1に割込み番号
611 popm r1-r5
612#endif /* TOPPERS_SUPPORT_OVRHDR */
613 mov.l r0, r3 ; スタックポインタを取り出し
614 mov.l #__kernel_istkpt, r5 ; 割込み用のスタックへ切替える
615 mov.l [r5], r0
616 push.l r3 ; タスクスタックを保持
617interrupt_from_int: ; 多重割込み
618 setpsw i ; 割込み許可(CPUロック解除状態)
619
620.if LOG_INH_LEAVE == 1
621 push.l r1 ; ログトレースの引数を保持
622.endif
623
624.if LOG_INH_ENTER == 1
625 push.l r2
626 bsr __kernel_log_inh_enter ; ログトレース関数の呼出し
627 ; 引数の割込み要因番号は既にr1に入っている
628 pop r2
629.endif
630
631 jsr r2 ; Cルーチン呼び出し
632
633.if LOG_INH_LEAVE == 1
634 pop r1 ; 引数に割込み要因番号を設定
635 bsr __kernel_log_inh_leave ; ログトレース関数の呼出し
636.endif
637
638 clrpsw i ; 割込み禁止(CPUロック状態)
639 mov.l #__kernel_intnest, r5
640 mov.w [r5], r4
641 sub #1, r4 ; ネスト回数をデクリメント
642 mov.w r4, [r5]
643 cmp #0, r4 ; 多重割り込みかどうか
644 bnz interrupt_return ; 多重割り込みならリターン
645 ; 初段の割込み
646 pop r0 ; タスクのスタックに戻す
647 mov.l #__kernel_p_schedtsk, r4
648 mov.l [r4], r4 ; p_schedtsk -> r4
649 mov.l #__kernel_p_runtsk, r5
650 mov.l [r5], r5 ; p_runtsk -> r5
651 cmp r4, r5 ; p_schedtsk と p_runtsk が異なりディスパッチ要求有りなら
652 bne ret_int ; ret_int へジャンプ
653#ifdef TOPPERS_SUPPORT_OVRHDR /* 6.6.1 */
654 mov.l #__kernel_p_runtsk, r5
655 mov.l [r5], r4
656 cmp #0, r4
657 beq interrupt_return
658 bsr __kernel_ovrtimer_start
659#endif /* TOPPERS_SUPPORT_OVRHDR */
660interrupt_return:
661 popm r4-r5 ; アキュムレータ復帰
662 mvtaclo r5 ; ACC最下位16bitは0で復帰
663 mvtachi r4
664 popc fpsw ; FPUステータスレジスタ復帰
665 popm r14-r15 ; レジスタ復帰
666 popm r1-r5
667 rte ; 割込み前の処理に戻る
668
669
670;
671; CPU例外の出入口処理(アセンブリ言語記述部分)
672;
673; 呼出し条件:
674; ・CPU例外発生時のH/W処理により, PSWレジスタのIビット=0, IPL=0.
675; ・スタックは多重割り込みなら割込みスタック, そうでなければ
676; タスクスタック
677; ・CPU例外発生時のH/W処理により,スタックにCPU例外からの復帰PCと
678; PSWが保存されている.
679; ・ベクタテーブルに登録された個別の入り口処理により, スタックに
680; スクラッチレジスタ(R1-R5)が保存されている.
681;
682; 引数:
683; ・r1:CPU例外要因番号
684; ・r2:CPU例外ハンドラのアドレス
685;
686; レジスタがスタック上にどのように保存されているかを以下に示す.
687; この図では上が低位, 下が高位のアドレスで, スタックは下から
688; 上方向に向かって積み上げられるものとする.
689; なお, CPU例外要因番号とR6-R13はCPU例外ハンドラ内で情報を取得
690; する目的で退避しており, 出口処理では保存内容を破棄すればよい.
691;
692; -------------------------
693; | CPU例外要因番号 | <----- p_excinf
694; ------------------------- (intptr_t)(p_excinf + 0)
695; | R6(4byte) |
696; ------------------------- (intptr_t)(p_excinf + 4)
697; | R7(4byte) |
698; ------------------------- (intptr_t)(p_excinf + 8)
699; | R8(4byte) |
700; ------------------------- (intptr_t)(p_excinf + 12)
701; | R9(4byte) |
702; ------------------------- (intptr_t)(p_excinf + 16)
703; | R10(4byte) |
704; ------------------------- (intptr_t)(p_excinf + 20)
705; | R11(4byte) |
706; ------------------------- (intptr_t)(p_excinf + 24)
707; | R12(4byte) |
708; ------------------------- (intptr_t)(p_excinf + 28)
709; | R13(4byte) |
710; ------------------------- (intptr_t)(p_excinf + 32)
711; | ACC-HI(4byte) |
712; ------------------------- (intptr_t)(p_excinf + 36)
713; | ACC-LO(4byte) |
714; ------------------------- (intptr_t)(p_excinf + 40)
715; | FPSW(4byte) |
716; ------------------------- (intptr_t)(p_excinf + 44)
717; | R14(4byte) |
718; ------------------------- (intptr_t)(p_excinf + 48)
719; | R15(4byte) |
720; ------------------------- (intptr_t)(p_excinf + 52)
721; | R1(4byte) |
722; ------------------------- (intptr_t)(p_excinf + 56)
723; | R2(4byte) |
724; ------------------------- (intptr_t)(p_excinf + 60)
725; | R3(4byte) |
726; ------------------------- (intptr_t)(p_excinf + 64)
727; | R4(4byte) |
728; ------------------------- (intptr_t)(p_excinf + 68)
729; | R5(4byte) |
730; ------------------------- (intptr_t)(p_excinf + 72)
731; | PC(4byte) |
732; ------------------------- (intptr_t)(p_excinf + 76)
733; | PSW(4byte) |
734; ------------------------- (intptr_t)(p_excinf + 80)
735;
736; ここでは, 割込み処理モードに変更してハンドラを実行する.
737; CPU例外ハンドラに渡すVP型の変数 p_excinf としてISPの値渡す.
738;
739; ハンドラからリターンした後は, 多重割込みでなく, かつ reqflg が
740; TRUE になった時に,ret_int へ分岐(遅延ディスパッチ)する.
741;
742; 多重割込みかどうかは割込みネストカウンタの値で判定する.
743; intnest != 0 ならば多重割込みであると判定する.
744;
745; reqflg はCPUロック状態でチェックする. そうでないと,
746; reqflg チェック後に起動された割込みハンドラ内で
747; ディスパッチが要求された場合に,ディスパッチされない.
748;
749;
750; CPU例外入口処理
751;
752; ここでは, 割込み処理モードに変更してハンドラを実行する.
753;
754
755;
756; CPU例外ハンドラ呼出し後に不要となるスタック情報のサイズ
757; EXCNO + R6--R13
758;
759 .equ EXCINF_REG_SIZE, (4+32)
760
761_kernel_exception:
762 pushm r14-r15 ; スクラッチレジスタを退避
763 pushc fpsw
764 mvfacmi r5
765 shll #16, r5 ; ACC最下位16bitは0とする
766 mvfachi r4
767 pushm r4-r5 ; アキュムレータ退避
768 pushm r6-r13 ; 非スクラッチレジスタ保存
769 push.l r1 ; CPU例外要因番号を保持
770 mov.l r0, r3 ; スタックポインタを取り出し
771 mov.l EXC_GET_PSW_OFFSET[r3], r5
772 and #PSW_I_MASK, r5
773 bz exception_nonkernel ; 全割込み禁止(CPUロック)状態なら管理外
774#if TIPM_LOCK != -15
775 mov.l EXC_GET_PSW_OFFSET[r3], r5
776 and #PSW_IPL_MASK, r5
777 cmp #IPL_LOCK, r5
778 bgt exception_nonkernel ; IPLがCPUロックレベル以上なら管理外
779#endif
780 mov.l #__kernel_intnest, r5
781 mov.w [r5], r4
782 add #1, r4 ; ネスト回数をインクリメント
783 mov.w r4, [r5]
784 cmp #1, r4 ; 多重割り込みかどうか
785 bnz exception_from_int ; 加算前が0でなければ多重割込み
786 ; 初段の割込み
787#ifdef TOPPERS_SUPPORT_OVRHDR /* 6.7.1 */
788 pushm r1-r5
789 mov.l #255, r1 ; r1にダミー割込み番号
790 bsr __kernel_ovrtimer_stop
791 popm r1-r5
792#endif /* TOPPERS_SUPPORT_OVRHDR */
793 mov.l #__kernel_istkpt, r5 ; 割込み用のスタックへ切替える
794 mov.l [r5], r0
795 push.l r3 ; タスクスタックを保持
796exception_from_int: ; 多重割込み
797 mov.l EXC_GET_PSW_OFFSET[r3], r5
798 mvtc r5, psw ; CPU例外発生前の状態に戻す
799#if LOG_EXC_LEAVE == 1
800 push.l r1 ; ログトレースの引数を保持
801#endif
802
803#if LOG_EXC_ENTER == 1
804 pushm r2-r3
805 bsr __kernel_log_exc_enter ; ログトレース関数の呼出し
806 ; 引数の割込み要因番号は既にr1に入っている
807 popm r2-r3
808#endif
809
810 mov.l r3, r1 ; 引数のp_excinfを設定
811 jsr r2 ; Cルーチン呼び出し
812
813.if LOG_EXC_LEAVE == 1
814 pop r1 ; 引数に割込み要因番号を設定
815 bsr __kernel_log_exc_leave ; ログトレース関数の呼出し
816.endif
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 mov.l #__kernel_p_schedtsk, r4
828 mov.l [r4], r4 ; p_schedtsk -> r4
829 mov.l #__kernel_p_runtsk, r5
830 mov.l [r5], r5 ; p_runtsk -> r5
831 cmp r4, r5 ; p_schedtsk と p_runtsk が同じでディスパッチ要求無しか
832#ifndef TOPPERS_SUPPORT_OVRHDR /* 6.7.1 */
833 beq exception_return ; なければリターン
834 add #EXCINF_REG_SIZE, r0 ; CPU例外情報の破棄
835 bra ret_int ; あれば ret_int へジャンプ
836#else /* TOPPERS_SUPPORT_OVRHDR */
837 beq exception_return_ovr ; なければリターン
838 add #EXCINF_REG_SIZE, r0 ; CPU例外情報の破棄
839 bra ret_int ; あれば ret_int へジャンプ
840exception_return_ovr:
841 mov.l #__kernel_p_runtsk, r5
842 mov.l [r5], r4
843 cmp #0, r4
844 beq exception_return
845 bsr __kernel_ovrtimer_start
846 bra exception_return
847#endif /* TOPPERS_SUPPORT_OVRHDR */
848
849exception_nonkernel:
850 mov.l #__kernel_intnest, r5
851 mov.w [r5], r4
852 add #1, r4 ; ネスト回数をインクリメント
853 mov.w r4, [r5]
854 cmp #1, r4 ; 多重割り込みかどうか
855 bnz exception_from_nonkernelint ; 加算前が0でなければ多重割込み
856 ; 初段の割込み
857 mov.l #__kernel_istkpt, r5 ; 割込み用のスタックへ切替える
858 mov.l [r5], r0
859 push.l r3 ; タスクスタックを保持
860exception_from_nonkernelint: ; 多重割込み
861 mov.l EXC_GET_PSW_OFFSET[r3], r5
862 mvtc r5, psw ; CPU例外発生前の状態に戻す
863
864 mov.l r3, r1 ; 引数のp_excinfを設定
865 jsr r2 ; Cルーチン呼び出し
866
867 clrpsw i ; ここからは必ず割込み禁止
868 mov.l #__kernel_intnest, r5
869 mov.w [r5], r4
870 sub #1, r4 ; ネスト回数をデクリメント
871 mov.w r4, [r5]
872 cmp #0, r4 ; 多重割り込みかどうか
873 bnz exception_return ; 多重割り込みならリターン
874 ; 初段の割込み
875 pop r0 ; タスクのスタックに戻す
876
877exception_return:
878 add #EXCINF_REG_SIZE, r0 ; CPU例外情報の破棄
879 popm r4-r5 ; アキュムレータ復帰
880 mvtaclo r5 ; ACC最下位16bitは0で復帰
881 mvtachi r4
882 popc fpsw ; FPUステータスレジスタ復帰
883 popm r14-r15 ; レジスタ復帰
884 popm r1-r5
885 rte ; 割込み前の処理に戻る
886
887
888;
889; 微少時間待ち
890;
891_sil_dly_nse:
892 mov.l #SIL_DLY_TIM1, r5
893 sub r5, r1
894 ble sil_dly_nse_ret
895sil_dly_nse_loop:
896 mov.l #SIL_DLY_TIM2, r5
897 sub r5, r1
898 bgt sil_dly_nse_loop
899sil_dly_nse_ret:
900 rts
901
902 .end
903
Note: See TracBrowser for help on using the repository browser.