source: asp_nios2/trunk/arch/nios2_gcc/prc_support.S@ 1

Last change on this file since 1 was 1, checked in by ertl-ichiba, 14 years ago

ASP 1.4.0対応のNios2依存部を追加

File size: 20.7 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) 2008 by Embedded and Real-Time Systems Laboratory
7 * Graduate School of Information Science, Nagoya Univ., JAPAN
8 *
9 * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
10 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14 * スコード中に含まれていること.
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18 * の無保証規定を掲載すること.
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
21 * と.
22 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
23 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
24 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
25 * 報告すること.
26 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
27 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
28 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
29 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
30 * 免責すること.
31 *
32 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
33 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
34 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
35 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
36 * の責任を負わない.
37 *
38 * @(#) $Id: chip_syssvc.h 698 2007-12-25 04:45:08Z honda $
39 */
40
41/*
42 * プロセッサ依存モジュール アセンブリ言語部(Nios2用)
43 */
44
45#define TOPPERS_MACRO_ONLY
46#define UINT_C(val) (val) /* uint_t型の定数を作るマクロ */
47#define ULONG_C(val) (val) /* ulong_t型の定数を作るマクロ */
48#define CAST(type, val) (val) /* 型キャストを行うマクロ */
49
50/*
51 * アセンブラ用のマクロを有効にする
52 */
53#define TOPPERS_ASM_MACRO
54#include "kernel_impl.h"
55#include "offset.h"
56
57/*
58 * スタック操作 : プッシュ
59 */
60 .macro Push source
61 addi sp, sp, -4
62 stw \source, 0(sp)
63 .endm
64
65/*
66 * スタック操作 : ポップ
67 */
68 .macro Pop source
69 ldw \source, 0(sp)
70 addi sp, sp, 4
71 .endm
72
73/*
74 * 例外/割込みエントリ
75 */
76 .set noat
77 .section .exceptions, "xa"
78 .align 2
79 .global exception_entry
80exception_entry:
81 /*
82 * 例外要因の判定
83 */
84 rdctl et, estatus
85 andi et, et, 1
86 beq et, zero, _check_trap
87 rdctl et, ipending
88 beq et, zero, _check_trap
89
90/*
91 * 例外要因が割込みの場合
92 */
93interrupt:
94 addi ea, ea, -4 /* 戻り番地をデクリメント */
95 /*
96 * コンテキストの保存
97 */
98 addi sp, sp, -76
99 rdctl et, estatus
100 stw et, 0(sp)
101 stw at, 4(sp)
102 stw r2, 8(sp)
103 stw r3, 12(sp)
104 stw r4, 16(sp)
105 stw r5, 20(sp)
106 stw r6, 24(sp)
107 stw r7, 28(sp)
108 stw r8, 32(sp)
109 stw r9, 36(sp)
110 stw r10, 40(sp)
111 stw r11, 44(sp)
112 stw r12, 48(sp)
113 stw r13, 52(sp)
114 stw r14, 56(sp)
115 stw r15, 60(sp)
116 stw fp, 64(sp)
117 stw ra, 68(sp)
118 stw ea, 72(sp)
119
120 /*
121 * 多重割込みか判定
122 */
123 ldw r3, %gprel(except_nest_count)(gp) /* ネスト回数のチェック */
124 bltu zero, r3, nest_int
125
126 /*
127 * スタックポインタの入れ替え
128 */
129 ldw r2, %gprel(_kernel_istkpt)(gp)
130 addi r2, r2, -4
131 stw sp, 0(r2) /* スタックポインタの保存 */
132 mov sp, r2 /* スタックポインタの入れ替え */
133
134nest_int:
135 /*
136 * 割込み・例外のネスト回数のインクリメント
137 */
138 addi r3, r3, 1
139 stw r3, %gprel(except_nest_count)(gp)
140
141 /*
142 * 割り込み要因の取得
143 */
144#ifdef NIOS2_USE_INT_VEC_INST
145 /*
146 * Interrupt Vector Instruction 命令を持つ場合
147 */
148 custom NIOS2_INT_VEC_INST_NO, r4, r0, r0 /* 割込み番号の読み込み(8倍したものが読み込める) */
149 srli r4, r4, 3 /* 8分の1にする */
150#else
151 /*
152 * ipending 中の1のビットの内,最も下位(右)のものをサーチ
153 */
154int_bitmap_search:
155 rdctl r4, ipending
156 andi r2, r4, 65535
157 mov r5, zero
158 bne r2, zero, int_bitmap_search1
159 srli r4, r4, 16
160 movi r5, 16
161int_bitmap_search1:
162 andi r2, r4, 255
163 bne r2, zero, int_bitmap_search2
164 srli r4, r4, 8
165 addi r5, r5, 8
166int_bitmap_search2:
167 andi r2, r4, 15
168 srli r4, r4, 4
169 bne r2, zero, int_bitmap_search3
170 addi r5, r5, 4
171 andi r2, r4, 15
172int_bitmap_search3:
173 movhi r3, %hiadj(int_bitmap_search_table-1)
174 addi r3, r3, %lo(int_bitmap_search_table-1)
175 add r3, r2, r3
176 ldbu r2, 0(r3)
177 add r4, r2, r5
178#endif
179
180 /*
181 * 割込み要因の割込み優先度を求め(モデル上の)割込み優先度マスクをセット
182 * する.またその際,ハンドラ実行前の(モデル上の)割込み優先度マスクを
183 * 保存する.
184 */
185 movhi r2, %hiadj(inh_iipm_tbl) /* 受け付けた割込みの割込み優先度マスク */
186 addi r2, r2, %lo(inh_iipm_tbl) /* を取得 */
187 add r3, r4, r2
188 ldbu r5, 0(r3)
189 ldbu r2, %gprel(iipm)(gp) /* 割込み発生前の割込み優先度マスクを */
190 Push r2 /* スタックに保存 */
191 stb r5, %gprel(iipm)(gp) /* (モデル上の)割込み優先度マスクをセット */
192
193 /*
194 * ienableを受け付けた割込みの割込み優先度に対応するマスクビットの
195 * 否定値にセットする.
196 */
197 slli r3, r5, 2 /* 割込み優先度マスクを4倍してオフセットを生成 */
198 movhi r2, %hiadj(iipm_mask_tbl) /* 割込み優先度マスクに対応した割込み禁止パターンを取得 */
199 addi r2, r2, %lo(iipm_mask_tbl)
200 add r2, r2, r3
201 ldw r5, 0(r2)
202 ldw r8, %gprel(idf)(gp) /* 各割込みの割込み要求禁止フラグの状態を取得 */
203 nor r8, r8, r5 /* 両者のORの否定を生成 */
204 wrctl ienable, r8 /* 指定した割り込みのみ許可 */
205
206 /*
207 * 割込みハンドラのアドレスを読み込む
208 */
209 slli r3, r4, 2 /* 割込み番号を4倍してオフセットを生成 */
210 movhi r2, %hiadj(inh_tbl)
211 addi r2, r2, %lo(inh_tbl)
212 add r2, r2, r3
213 ldw r5, 0(r2)
214
215 /*
216 * 割込み許可
217 */
218 rdctl r3, status
219 ori r3, r3, STATUS_PIE
220 wrctl status, r3
221
222#ifdef LOG_INH_ENTER
223 Push r4 /* 割込み番号を保存 */
224 Push r5 /* ハンドラアドレスを保存 */
225 call log_inh_enter
226 Pop r5 /* ハンドラアドレスを復帰 */
227 ldw r4, 0(sp) /* 割込み番号を復帰 */
228#endif /* LOG_INH_ENTER */
229
230 /*
231 * 割込みハンドラ呼び出し
232 */
233 callr r5
234
235#ifdef LOG_INH_LEAVE
236 Pop r4 /* 割込み番号を復帰 */
237 call log_inh_leave
238#endif /* LOG_INH_LEAVE */
239
240 /*
241 * 割込み禁止
242 */
243 rdctl r3, status
244 movi r4, ~STATUS_PIE
245 and r3, r3, r4
246 wrctl status, r3
247test1:
248
249/*
250 * 割込みハンドラ/CPU例外ハンドラ出口処理
251 *
252 * ret_intは,割込みハンドラから戻った直後に実行するルーチンで,
253 * 割込みハンドラ終了後,ターゲット依存の処理を実行した後,
254 * カーネル管理の割込みを禁止,スタックを割込み前のスタックにした
255 * 状態で呼び出される.
256 */
257 .global ret_int
258 .global ret_exc
259rer_int:
260ret_exc:
261 /*
262 * (モデル上の)割込み優先度マスクを元に戻す
263 */
264 Pop r3 /* 割込み前の(モデル上の)割込み優先度マスクを取得 */
265 stb r3, %gprel(iipm)(gp) /* (モデル上の)割込み優先度マスクをセット */
266 slli r3, r3, 2 /* 割込み優先度マスクを4倍してオフセットを生成 */
267 movhi r2, %hiadj(iipm_mask_tbl) /* 割込み優先度マスクに対応した割込み禁止パターンを取得 */
268 addi r2, r2, %lo(iipm_mask_tbl)
269 add r2, r2, r3
270 ldw r5, 0(r2)
271 ldw r8, %gprel(idf)(gp) /* 各割込みの割込み要求禁止フラグの状態を取得 */
272 nor r8, r8, r5 /* 両者のORの否定を生成 */
273 wrctl ienable, r8 /* 指定した割り込みのみ許可 */
274
275 /*
276 * 割込み・例外のネスト回数のデクリメント
277 */
278 ldw r3, %gprel(except_nest_count)(gp)
279 addi r3, r3, -1
280 stw r3, %gprel(except_nest_count)(gp)
281
282 bltu zero, r3, ret_int_1 /* ネスト回数が1以上なら戻る */
283
284 ldw r2, 0(sp) /* スタックポインタを戻す */
285 mov sp, r2
286 ldw r3, %gprel(reqflg)(gp) /* reqflgのチェック */
287 beq r3, zero, ret_int_1 /* false なら タスクに戻る */
288 br ret_int_2 /* true なら ret_int_2 に */
289
290ret_int_1:
291 ldw et, 0(sp) /* レジスタの復帰 */
292 wrctl estatus, et
293 ldw at, 4(sp)
294 ldw r2, 8(sp)
295 ldw r3, 12(sp)
296 ldw r4, 16(sp)
297 ldw r5, 20(sp)
298 ldw r6, 24(sp)
299 ldw r7, 28(sp)
300 ldw r8, 32(sp)
301 ldw r9, 36(sp)
302 ldw r10, 40(sp)
303 ldw r11, 44(sp)
304 ldw r12, 48(sp)
305 ldw r13, 52(sp)
306 ldw r14, 56(sp)
307 ldw r15, 60(sp)
308 ldw fp, 64(sp)
309 ldw ra, 68(sp)
310 ldw ea, 72(sp)
311 addi sp, sp, 76
312 eret
313
314 /*
315 * 例外かトラップかを判断
316 */
317_check_trap:
318 /*
319 * Trapか判定
320 */
321 ldw et, -4(ea) /* 例外を出した命令を取得 */
322 xorhi et, et, 0x003b /* 上位16bit */
323 xori et, et, 0x683a /* 下位16bit */
324 beq et, zero, trap_handler
325
326 /*
327 * 例外エントリ
328 */
329exception:
330 /*
331 * コンテキストの保存
332 */
333 addi sp, sp, -76
334 rdctl et, estatus
335 stw et, 0(sp)
336 stw at, 4(sp)
337 stw r2, 8(sp)
338 stw r3, 12(sp)
339 stw r4, 16(sp)
340 stw r5, 20(sp)
341 stw r6, 24(sp)
342 stw r7, 28(sp)
343 stw r8, 32(sp)
344 stw r9, 36(sp)
345 stw r10, 40(sp)
346 stw r11, 44(sp)
347 stw r12, 48(sp)
348 stw r13, 52(sp)
349 stw r14, 56(sp)
350 stw r15, 60(sp)
351 stw fp, 64(sp)
352 stw ra, 68(sp)
353 stw ea, 72(sp)
354 mov r4, sp /* ハンドラの引数 */
355
356 /*
357 * 多重割込みか判定
358 */
359 ldw r3, %gprel(except_nest_count)(gp) /* ネスト回数のチェック */
360 bltu zero, r3, nest_int_exc
361
362 /*
363 * スタックポインタの入れ替え
364 */
365 ldw r2, %gprel(_kernel_istkpt)(gp)
366 addi r2, r2, -4
367 stw sp, 0(r2) /* スタックポインタの保存 */
368 mov sp, r2 /* スタックポインタの入れ替え */
369
370nest_int_exc:
371 /*
372 * 割込み・例外のネスト回数のインクリメント
373 */
374 addi r4, r3, 1
375 stw r4, %gprel(except_nest_count)(gp)
376
377 /*
378 * CPU例外番号の取得(4倍されている)
379 */
380#ifdef USE_EXTRA_EXCEPTION
381 rdctl r5, exception
382#else
383 mov r5, zero
384#endif /* USE_EXTRA_EXCEPTION */
385 srli r6, r5, 2
386
387 /*
388 * 割込み発生前の割込み優先度マスクをスタックに保存
389 */
390 ldbu r2, %gprel(iipm)(gp)
391 Push r2
392
393 /*
394 * 例外フレームの作成 オフセット
395 * 例外番号 0
396 * ESTATUS(et) 4
397 * 割込み・例外ネストカウント(r3) 8
398 * 戻りアドレス 12
399 * 割込み優先度マスク(iipm) 16
400 */
401 addi sp, sp, -20
402 stw r6, 0(sp)
403 stw et, 4(sp)
404 stw r3, 8(sp)
405 stw ea, 12(sp)
406 stw r2, 16(sp)
407
408 /*
409 * 例外フレームの先頭番地をCPU例外ハンドラの引数に設定(r4)
410 */
411 mov r4, sp
412
413 /*
414 * 例外ハンドラアドレスの取得
415 */
416 movhi r2, %hiadj(exch_tbl)
417 addi r2, r2, %lo(exch_tbl)
418 add r2, r2, r5
419 ldw r5, 0(r2)
420
421 /*
422 * 例外発生時CPUロック状態でなければCPUロック解除状態とする
423 */
424 rdctl r3, estatus
425 andi r3, r3, STATUS_PIE
426 beq r3, zero, call_exc_handler
427 rdctl r3, status
428 ori r3, r3, STATUS_PIE
429 wrctl status, r3
430
431call_exc_handler:
432#ifdef LOG_EXC_ENTER
433 Push r6 /* CPU例外番号保存 */
434 Push r5 /* CPU例外ハンドラアドレス保存 */
435 Push r4 /* CPU例外フレームの先頭番地保存 */
436 mov r4, r6 /* CPU例外番号を引数に */
437 call log_exc_enter
438 Pop r4 /* CPU例外フレームの先頭番地復帰 */
439 Pop r5 /* CPU例外ハンドラアドレス復帰 */
440#endif /* LOG_EXC_ENTER */
441
442 /*
443 * CPU例外ハンドラ呼び出し
444 */
445 callr r5
446
447#ifdef LOG_EXC_LEAVE
448 Pop r4 /* CPU例外番号復帰 */
449 call log_exc_leave
450#endif /* LOG_EXC_LEAVE */
451
452 /*
453 * 割込み禁止
454 */
455 rdctl r3, status
456 movi r4, ~STATUS_PIE
457 and r3, r3, r4
458 wrctl status, r3
459
460 /*
461 * 例外フレームを捨てる
462 */
463 addi sp, sp, 20
464
465 /*
466 * 例外からのリターン処理
467 */
468 br ret_exc
469
470 /*
471 * Trapハンドラ
472 */
473trap_handler:
474 eret
475
476 /*
477 * 割込みハンドラ/CPU例外ハンドラ出口処理1
478 *
479 * ここでは,戻り先がタスクであり,スタックは,タスクスタックの上
480 * にスクラッチレジスタのみが保存された状態になっている.また,
481 * プロセッサは,スーパーバイザーモード・カーネル管理の割込みを禁止
482 * した状態となっている.
483 */
484ret_int_2:
485 stw zero, %gprel(reqflg)(gp) /* reqflg を false に */
486
487 /*
488 * CPUロック状態に移行する.
489 *
490 * この時点でCPUロック状態とするのは,dispatcherへ分岐する時と,
491 * call_texrtnを呼び出す時に,CPUロック状態になっている必要がある
492 * ためである.
493 *
494 * Nios2では,カーネル管理外の割込みを設けないため,ここでは,
495 * 特に何も行わない.
496 */
497
498 /*
499 * dspflgがfalseである場合と,p_runtskとp_schedtskが同じ場合には,
500 * ディスパッチを行わない.このチェックが必要なのは,タスク例外処
501 * 理ルーチンの呼出しが必要な場合に,ディスパッチが必要なくても,
502 * reqflgをtrueにするためである.
503 */
504 ldw r5, %gprel(p_runtsk)(gp) /* r5 <- runtsk */
505 ldw r6, %gprel(dspflg)(gp) /* r6 <- dspflg */
506 beq r6, zero, ret_int_3 /* dspflg が false なら ret_int_3 へ */
507 ldw r4, %gprel(p_schedtsk)(gp) /* r4 <- p_schedtsk */
508 beq r4, r5, ret_int_3 /* runtsk と schedtskが同じならret_int_3へ */
509 addi sp, sp, -32 /* 残りのレジスタを保存 */
510 stw r16, 0(sp)
511 stw r17, 4(sp)
512 stw r18, 8(sp)
513 stw r19, 12(sp)
514 stw r20, 16(sp)
515 stw r21, 20(sp)
516 stw r22, 24(sp)
517 stw r23, 28(sp)
518 stw sp, TCB_sp(r5) /* タスクスタックをTCBに保存 */
519 movhi r2, %hiadj(ret_int_r) /* 実行開始番地を保存 */
520 addi r2, r2, %lo(ret_int_r)
521 stw r2, TCB_pc(r5) /* 実行再開番地をTCBに保存 */
522 br dispatcher
523
524 /*
525 * 割込み・例外でコンテキスト保存した場合の復帰ルーチン
526 */
527ret_int_r:
528 ldw r16, 0(sp) /* レジスタを復帰 */
529 ldw r17, 4(sp)
530 ldw r18, 8(sp)
531 ldw r19, 12(sp)
532 ldw r20, 16(sp)
533 ldw r21, 20(sp)
534 ldw r22, 24(sp)
535 ldw r23, 28(sp)
536 addi sp, sp, 32
537
538ret_int_3:
539 /*
540 * タスク例外ルーチンの起動
541 * ret_int_r は dispatcher から呼び出されるため,
542 * tcb のアドレスは r4 に入っている
543 */
544 ldb r5, TCB_enatex(r4) /* r5 <- enatex */
545#if TCB_enatex_mask > 0xffff
546 andhi r6, r5, %hi(TCB_enatex_mask)
547#else
548 andi r6, r5, %lo(TCB_enatex_mask)
549#endif /* TCB_enatex_mask > 0xffff */
550 beq r6, zero, ret_int_4 /* enatex が false ならリターン */
551 ldw r7, TCB_texptn(r4) /* r7 <- texptn, texptnが0でなければ */
552 beq zero, r7, ret_int_4
553 call call_texrtn /* タスク例外ルーチンの呼び出し */
554
555ret_int_4:
556 ldw et, 0(sp) /* レジスタを復帰 */
557 wrctl estatus, et
558 ldw at, 4(sp)
559 ldw r2, 8(sp)
560 ldw r3, 12(sp)
561 ldw r4, 16(sp)
562 ldw r5, 20(sp)
563 ldw r6, 24(sp)
564 ldw r7, 28(sp)
565 ldw r8, 32(sp)
566 ldw r9, 36(sp)
567 ldw r10, 40(sp)
568 ldw r11, 44(sp)
569 ldw r12, 48(sp)
570 ldw r13, 52(sp)
571 ldw r14, 56(sp)
572 ldw r15, 60(sp)
573 ldw fp, 64(sp)
574 ldw ra, 68(sp)
575 ldw ea, 72(sp)
576 addi sp, sp, 76
577 eret
578
579
580/*
581 * タスクディスパッチャ
582 */
583 .global dispatch
584 .align 2
585dispatch:
586 /*
587 * このルーチンは,タスクコンテキスト・CPUロック状態・ディスパッチ
588 * 許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さ
589 * れる.
590 */
591 addi sp, sp, -40 /* レジスタを保存 */
592 stw r16, 0(sp)
593 stw r17, 4(sp)
594 stw r18, 8(sp)
595 stw r19, 12(sp)
596 stw r20, 16(sp)
597 stw r21, 20(sp)
598 stw r22, 24(sp)
599 stw r23, 28(sp)
600 stw fp, 32(sp)
601 stw ra, 36(sp)
602 ldw r4, %gprel(p_runtsk)(gp) /* r4 <- runtsk */
603 stw sp, TCB_sp(r4) /* タスクスタックをTCBに保存 */
604 movhi r5, %hiadj(dispatch_r) /* 実行開始番地を保存 */
605 addi r5, r5, %lo(dispatch_r)
606 stw r5, TCB_pc(r4) /* 実行再開番地をTCBに保存 */
607 br dispatcher
608
609dispatch_r:
610 ldw r16, 0(sp) /* レジスタを復帰 */
611 ldw r17, 4(sp)
612 ldw r18, 8(sp)
613 ldw r19, 12(sp)
614 ldw r20, 16(sp)
615 ldw r21, 20(sp)
616 ldw r22, 24(sp)
617 ldw r23, 28(sp)
618 ldw fp, 32(sp)
619
620 /*
621 * タスク例外処理ルーチンの起動
622 * dispatch_r は dispatcher から呼び出されるため,
623 * tcb のアドレスは r4 に入っている
624 */
625 ldb r5, TCB_enatex(r4) /* r5 <- enatex */
626#if TCB_enatex_mask > 0xffff
627 andhi r6, r5, %hi(TCB_enatex_mask)
628#else
629 andi r6, r5, %lo(TCB_enatex_mask)
630#endif /* TCB_enatex_mask > 0xffff */
631 beq r6, zero, dispatch_r_1 /* enatex が false ならリターン */
632 ldw r7, TCB_texptn(r4) /* r7 <- texptn, texptnが0でなければ */
633 beq r7, zero, dispatch_r_1
634 call call_texrtn /* タスク例外ルーチンの呼び出し */
635
636dispatch_r_1:
637 ldw ra, 36(sp) /* 残りのレジスタを復帰 */
638 addi sp, sp, 40
639 ret
640
641/*
642 * ディスパッチャの動作開始
643 */
644 .globl start_dispatch
645start_dispatch:
646 /*
647 * このルーチンは,カーネル起動時に,すべての割込みを禁止した状態
648 * (割込みロック状態と同等)で呼び出される.また,割込みモード(非
649 * タスクコンテキストと同等)で呼び出されることを想定している.
650 *
651 * dispatcherは,CPUロック状態,(モデル上の)割込み優先度マスク全
652 * 解除状態,例外(割込み/CPU例外)のネスト回数0で呼び出す.
653 * target_initializeでは,(モデル上の)割込み優先度マスク全解除
654 * とし,カーネル管理外の割込みであるFIQを許可することで,
655 * CPUロック状態・(モデル上の)割込み優先度マスク全解除状態になる.
656 * また,task_initializeでdisdspをfalseに初期化しているため,ディ
657 * スパッチ許可状態になっている.
658 */
659 /* 例外(割込み/CPU例外)のネスト回数をクリア */
660 stw zero, %gprel(except_nest_count)(gp)
661
662/*
663 * 現在のコンテキストを捨ててディスパッチ
664 */
665 .globl exit_and_dispatch
666exit_and_dispatch:
667 /* ディスパッチャ本体(dispatcher)へ */
668
669/*
670 * ディスパッチャ本体
671 */
672dispatcher:
673 /*
674 * このルーチンは,タスクコンテキスト・CPUロック状態・ディスパッチ
675 * 許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さ
676 * れる.実行再開番地へもこの状態のまま分岐する.
677 */
678#ifdef LOG_DSP_ENTER
679 ldw r4, %gprel(p_runtsk)(gp)
680 call log_dsp_enter
681#endif /* LOG_DSP_ENTER */
682
683dispatcher_0:
684 ldw r4, %gprel(p_schedtsk)(gp) /* r4 <- schedtsk */
685 stw r4, %gprel(p_runtsk)(gp) /* schedtsk を runtskに */
686 beq r4, zero, dispatcher_1 /* schedtskがあるか */
687 ldw sp, TCB_sp(r4) /* TCBからタスクスタックを復帰 */
688
689#ifdef LOG_DSP_LEAVE
690 Push r4
691 call log_dsp_leave
692 Pop r4
693#endif /* LOG_DSP_LEAVE */
694
695 ldw r5, TCB_pc(r4) /* TCBから実行再開番地を復帰 */
696 jmp r5
697
698dispatcher_1:
699 /*
700 * CPUロック状態の解除と,非タスクコンテキスト実行状態への
701 * 準備をする
702 */
703 ldw r2, %gprel(_kernel_istkpt)(gp) /* 非タスクコンテキスト用のスタックの読み込み */
704 mov sp, r2 /* スタックポインタの入れ替え */
705 movi r5, 1
706 stw r5, %gprel(except_nest_count)(gp) /* except_nest_count を1に */
707dispatcher_2:
708 /*
709 * 割込みを許可し,非タスクコンテキスト実行状態とし割込みを待つ.
710 *
711 * ここで非タスクコンテキスト実行状態に切り換えるのは,ここで発生
712 * する割込み処理にどのスタックを使うかという問題の解決と,割込み
713 * ハンドラ内でのタスクディスパッチの防止という2つの意味がある.
714 *
715 * プロセッサを割込み待ちに移行させる処理と,割込み許可とは,不可
716 * 分に行なう必要がある.
717 * これを不可分に行なわない場合,割込みを許可した直後に割込
718 * みが入り,その中でタスクが実行可能状態になると,実行すべきタス
719 * クがあるにもかかわらずプロセッサが割込み待ちになってしまう.
720 *
721 * 割込み待ちの間は,p_runtskをNULL(=0)に設定しなければならな
722 * い.このように設定しないと,割込みハンドラからiget_tidを呼び出
723 * した際の動作が仕様に合致しなくなる.
724 *
725 */
726 rdctl r3, status /* 割込み許可 */
727 ori r3, r3, STATUS_PIE
728 wrctl status, r3
729 nop
730 nop
731 nop
732 nop
733 rdctl r3, status /* 割込み禁止 */
734 movi r4, ~STATUS_PIE
735 and r3, r3, r4
736 wrctl status, r3
737 ldw r6, %gprel(reqflg)(gp) /* r6 <- reqflg */
738 beq r6, zero, dispatcher_2 /* reqflg が FALSE なら */
739 stw zero, %gprel(except_nest_count)(gp) /* interrupt_count をクリア */
740 stw zero, %gprel(reqflg)(gp) /* reqflg を FALSE に */
741 br dispatcher_0
742
743/*
744 * カーネルの終了処理の呼出し
745 *
746 * モードとスタックを非タスクコンテキスト用に切り替え.
747 */
748 .globl call_exit_kernel
749call_exit_kernel:
750 ldw r2, %gprel(_kernel_istkpt)(gp) /* 非タスクコンテキスト用のスタックの読み込み */
751 mov sp, r2 /* スタックポインタの入れ替え */
752 call exit_kernel
753
754/*
755 * タスク開始時処理
756 *
757 * dispatcherから呼び出されるため,TCBのアドレスは r4 に入っている
758 */
759 .text
760 .global start_r
761 .align 2
762start_r:
763 rdctl r3, status /* 割込み許可 */
764 ori r3, r3, STATUS_PIE
765 wrctl status, r3
766 ldw r3, TCB_p_tinib(r4) /* r3 <- p_runtsk->p_tinib */
767 ldw r4, TINIB_exinf(r3) /* r4 <- 引数(exinf) */
768 ldw r2, TINIB_task(r3) /* r2 <- タスクの実行番地 */
769 addi sp, sp, 8
770 movhi ra, %hiadj(ext_tsk)
771 addi ra, ra, %lo(ext_tsk)
772 jmp r2 /* タスクの実行開始 */
773
774
775/*
776 * 微少時間待ち
777 */
778 .global sil_dly_nse
779sil_dly_nse:
780 addi r4, r4, -SIL_DLY_TIM1
781 bgt r4, zero, sil_dly_nse_1
782 ret
783sil_dly_nse_1:
784 addi r4, r4, -SIL_DLY_TIM2
785 bgt r4, zero, sil_dly_nse_1
786 ret
Note: See TracBrowser for help on using the repository browser.