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

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

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

File size: 24.3 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-2011 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#define USE_EXTRA_EXCEPTION
61
62/*
63 * スタック操作 : プッシュ
64 */
65 .macro Push source
66 addi sp, sp, -4
67 stw \source, 0(sp)
68 .endm
69
70/*
71 * スタック操作 : ポップ
72 */
73 .macro Pop source
74 ldw \source, 0(sp)
75 addi sp, sp, 4
76 .endm
77
78/*
79 * 例外/割込みエントリ
80 */
81 .set noat
82 .section .exceptions, "xa"
83 .align 2
84 .global exception_entry
85exception_entry:
86 /*
87 * 例外要因の判定
88 */
89 rdctl et, estatus
90 andi et, et, 1
91 beq et, zero, _check_trap
92 rdctl et, ipending
93 beq et, zero, _check_trap
94
95/*
96 * 例外要因が割込みの場合
97 */
98interrupt:
99 addi ea, ea, -4 /* 戻り番地をデクリメント */
100
101 /*
102 * コンテキストの保存
103 */
104 addi sp, sp, -76
105 rdctl et, estatus
106 stw et, 0(sp)
107 stw at, 4(sp)
108 stw r2, 8(sp)
109 stw r3, 12(sp)
110 stw r4, 16(sp)
111 stw r5, 20(sp)
112 stw r6, 24(sp)
113 stw r7, 28(sp)
114 stw r8, 32(sp)
115 stw r9, 36(sp)
116 stw r10, 40(sp)
117 stw r11, 44(sp)
118 stw r12, 48(sp)
119 stw r13, 52(sp)
120 stw r14, 56(sp)
121 stw r15, 60(sp)
122 stw fp, 64(sp)
123 stw ra, 68(sp)
124 stw ea, 72(sp)
125
126 /*
127 * 割り込み要因の取得
128 */
129#ifdef NIOS2_USE_INT_VEC_INST
130 /*
131 * Interrupt Vector Instruction 命令を持つ場合
132 */
133 custom NIOS2_INT_VEC_INST_NO, r4, r0, r0 /* 割込み番号の読み込み(8倍したものが読み込める) */
134 srli r4, r4, 3 /* 8分の1にする */
135#else
136 /*
137 * ipending 中の1のビットの内,最も下位(右)のものをサーチ
138 */
139int_bitmap_search:
140 rdctl r4, ipending
141 andi r2, r4, 65535
142 mov r5, zero
143 bne r2, zero, int_bitmap_search1
144 srli r4, r4, 16
145 movi r5, 16
146int_bitmap_search1:
147 andi r2, r4, 255
148 bne r2, zero, int_bitmap_search2
149 srli r4, r4, 8
150 addi r5, r5, 8
151int_bitmap_search2:
152 andi r2, r4, 15
153 srli r4, r4, 4
154 bne r2, zero, int_bitmap_search3
155 addi r5, r5, 4
156 andi r2, r4, 15
157int_bitmap_search3:
158 movhi r3, %hiadj(int_bitmap_search_table-1)
159 addi r3, r3, %lo(int_bitmap_search_table-1)
160 add r3, r2, r3
161 ldbu r2, 0(r3)
162 add r4, r2, r5
163#endif
164
165 /*
166 * 多重割込みか判定
167 */
168 ldw r3, %gprel(except_nest_count)(gp) /* ネスト回数のチェック */
169 bltu zero, r3, nest_int
170
171 /*
172 * スタックポインタの入れ替え
173 */
174 ldw r2, %gprel(_kernel_istkpt)(gp)
175 addi r2, r2, -4
176 stw sp, 0(r2) /* スタックポインタの保存 */
177 mov sp, r2 /* スタックポインタの入れ替え */
178
179nest_int:
180 /*
181 * 割込み・例外のネスト回数のインクリメント
182 */
183 addi r3, r3, 1
184 stw r3, %gprel(except_nest_count)(gp)
185
186 /*
187 * 割込み要因の割込み優先度を求め(モデル上の)割込み優先度マスクをセット
188 * する.またその際,ハンドラ実行前の(モデル上の)割込み優先度マスクを
189 * 保存する.
190 */
191 movhi r2, %hiadj(inh_iipm_tbl) /* 受け付けた割込みの割込み優先度マスク */
192 addi r2, r2, %lo(inh_iipm_tbl) /* を取得 */
193 add r3, r4, r2
194 ldbu r5, 0(r3)
195 ldbu r2, %gprel(iipm)(gp) /* 割込み発生前の割込み優先度マスクを */
196 Push r2 /* スタックに保存 */
197 stb r5, %gprel(iipm)(gp) /* (モデル上の)割込み優先度マスクをセット */
198
199 /*
200 * ienableを受け付けた割込みの割込み優先度に対応するマスクビットの
201 * 否定値にセットする.
202 */
203 slli r3, r5, 2 /* 割込み優先度マスクを4倍してオフセットを生成 */
204 movhi r2, %hiadj(iipm_mask_tbl) /* 割込み優先度マスクに対応した割込み禁止パターンを取得 */
205 addi r2, r2, %lo(iipm_mask_tbl)
206 add r2, r2, r3
207 ldw r5, 0(r2)
208 ldw r8, %gprel(idf)(gp) /* 各割込みの割込み要求禁止フラグの状態を取得 */
209 nor r8, r8, r5 /* 両者のORの否定を生成 */
210 wrctl ienable, r8 /* 指定した割り込みのみ許可 */
211
212 /*
213 * 割込みハンドラのアドレスを読み込む
214 */
215 slli r3, r4, 2 /* 割込み番号を4倍してオフセットを生成 */
216 movhi r2, %hiadj(inh_tbl)
217 addi r2, r2, %lo(inh_tbl)
218 add r2, r2, r3
219 ldw r5, 0(r2)
220
221 /*
222 * 割込み許可
223 */
224 rdctl r3, status
225 ori r3, r3, STATUS_PIE
226 wrctl status, r3
227
228#ifdef LOG_INH_ENTER
229 Push r4 /* 割込み番号を保存 */
230 Push r5 /* ハンドラアドレスを保存 */
231 call log_inh_enter
232 Pop r5 /* ハンドラアドレスを復帰 */
233 ldw r4, 0(sp) /* 割込み番号を復帰 */
234#endif /* LOG_INH_ENTER */
235
236 /*
237 * 割込みハンドラ呼び出し
238 */
239 callr r5
240
241#ifdef LOG_INH_LEAVE
242 Pop r4 /* 割込み番号を復帰 */
243 call log_inh_leave
244#endif /* LOG_INH_LEAVE */
245
246 /*
247 * 割込み禁止
248 */
249 rdctl r3, status
250 movi r4, ~STATUS_PIE
251 and r3, r3, r4
252 wrctl status, r3
253
254/*
255 * 割込みハンドラ/CPU例外ハンドラ出口処理
256 *
257 * ret_intは,割込みハンドラから戻った直後に実行するルーチンで,
258 * 割込みハンドラ終了後,ターゲット依存の処理を実行した後,
259 * カーネル管理の割込みを禁止,スタックを割込み前のスタックにした
260 * 状態で呼び出される.
261 */
262 .global ret_int
263 .global ret_exc
264rer_int:
265ret_exc:
266 /*
267 * (モデル上の)割込み優先度マスクを元に戻す
268 */
269 Pop r3 /* 割込み前の(モデル上の)割込み優先度マスクを取得 */
270 stb r3, %gprel(iipm)(gp) /* (モデル上の)割込み優先度マスクをセット */
271 slli r3, r3, 2 /* 割込み優先度マスクを4倍してオフセットを生成 */
272 movhi r2, %hiadj(iipm_mask_tbl) /* 割込み優先度マスクに対応した割込み禁止パターンを取得 */
273 addi r2, r2, %lo(iipm_mask_tbl)
274 add r2, r2, r3
275 ldw r5, 0(r2)
276 ldw r8, %gprel(idf)(gp) /* 各割込みの割込み要求禁止フラグの状態を取得 */
277 nor r8, r8, r5 /* 両者のORの否定を生成 */
278 wrctl ienable, r8 /* 指定した割り込みのみ許可 */
279
280 /*
281 * 割込み・例外のネスト回数のデクリメント
282 */
283 ldw r3, %gprel(except_nest_count)(gp)
284 addi r3, r3, -1
285 stw r3, %gprel(except_nest_count)(gp)
286
287 bltu zero, r3, ret_int_1 /* ネスト回数が1以上なら戻る */
288
289 ldw r2, 0(sp) /* スタックポインタを戻す */
290 mov sp, r2
291 ldw r3, %gprel(reqflg)(gp) /* reqflgのチェック */
292 beq r3, zero, ret_int_1 /* false なら タスクに戻る */
293 br ret_int_2 /* true なら ret_int_2 に */
294
295ret_int_1:
296 ldw et, 0(sp) /* レジスタの復帰 */
297 wrctl estatus, et
298 ldw at, 4(sp)
299 ldw r2, 8(sp)
300 ldw r3, 12(sp)
301 ldw r4, 16(sp)
302 ldw r5, 20(sp)
303 ldw r6, 24(sp)
304 ldw r7, 28(sp)
305 ldw r8, 32(sp)
306 ldw r9, 36(sp)
307 ldw r10, 40(sp)
308 ldw r11, 44(sp)
309 ldw r12, 48(sp)
310 ldw r13, 52(sp)
311 ldw r14, 56(sp)
312 ldw r15, 60(sp)
313 ldw fp, 64(sp)
314 ldw ra, 68(sp)
315 ldw ea, 72(sp)
316 addi sp, sp, 76
317 eret
318
319 /*
320 * 例外かトラップかを判断
321 */
322_check_trap:
323 /*
324 * Trapか判定
325 */
326 ldw et, -4(ea) /* 例外を出した命令を取得 */
327 xorhi et, et, 0x003b /* 上位16bit */
328 xori et, et, 0x683a /* 下位16bit */
329 beq et, zero, trap_handler
330
331 /*
332 * 例外エントリ
333 */
334exception:
335 /*
336 * コンテキストの保存
337 */
338 addi sp, sp, -76
339 rdctl et, estatus
340 stw et, 0(sp)
341 stw at, 4(sp)
342 stw r2, 8(sp)
343 stw r3, 12(sp)
344 stw r4, 16(sp)
345 stw r5, 20(sp)
346 stw r6, 24(sp)
347 stw r7, 28(sp)
348 stw r8, 32(sp)
349 stw r9, 36(sp)
350 stw r10, 40(sp)
351 stw r11, 44(sp)
352 stw r12, 48(sp)
353 stw r13, 52(sp)
354 stw r14, 56(sp)
355 stw r15, 60(sp)
356 stw fp, 64(sp)
357 stw ra, 68(sp)
358 stw ea, 72(sp)
359 mov r4, sp /* ハンドラの引数 */
360
361 /*
362 * カーネル管理外のCPU例外か判定する
363 *
364 * カーネル管理外のCPU例外は,カーネル実行中,全割込みロック状態,
365 * CPUロック状態,カーネル管理外の割込みハンドラ実行中に発生した
366 * CPU例外である.
367 * Nios2の場合は,PIEが'0'の場合が相当する.
368 */
369 rdctl r3, estatus
370 andi r3, r3, STATUS_PIE
371 beq r3, zero, kernel_unc_exception
372
373 /*
374 * 例外発生元のコンテキストを判定
375 */
376 ldw r3, %gprel(except_nest_count)(gp) /* ネスト回数のチェック */
377 bltu zero, r3, nest_int_exc
378
379 /*
380 * 発生元がタスクの場合はスタックポインタの入れ替え
381 */
382 ldw r2, %gprel(_kernel_istkpt)(gp)
383 addi r2, r2, -4
384 stw sp, 0(r2) /* スタックポインタの保存 */
385 mov sp, r2 /* スタックポインタの入れ替え */
386
387nest_int_exc:
388 /*
389 * 割込み・例外のネスト回数のインクリメント
390 */
391 addi r4, r3, 1
392 stw r4, %gprel(except_nest_count)(gp)
393
394 /*
395 * CPU例外ハンドラ番号の取得(4倍されている)
396 */
397#ifdef USE_EXTRA_EXCEPTION
398 rdctl r5, exception
399#else
400 mov r5, zero
401#endif /* USE_EXTRA_EXCEPTION */
402 srli r6, r5, 2
403
404 /*
405 * 割込み発生前の割込み優先度マスクをスタックに保存
406 */
407 ldbu r2, %gprel(iipm)(gp)
408 Push r2
409
410 /*
411 * 例外フレームの作成 オフセット
412 * 例外番号 0
413 * ESTATUS(et) 4
414 * 割込み・例外ネストカウント(r3) 8
415 * 戻りアドレス 12
416 * 割込み優先度マスク(iipm) 16
417 */
418 addi sp, sp, -20
419 stw r6, 0(sp)
420 stw et, 4(sp)
421 stw r3, 8(sp)
422 stw ea, 12(sp)
423 stw r2, 16(sp)
424
425 /*
426 * 例外フレームの先頭番地をCPU例外ハンドラの引数に設定(r4)
427 */
428 mov r4, sp
429
430 /*
431 * 例外ハンドラアドレスの取得
432 */
433 movhi r2, %hiadj(exch_tbl)
434 addi r2, r2, %lo(exch_tbl)
435 add r2, r2, r5
436 ldw r5, 0(r2)
437
438 /*
439 * CPUロック解除状態とする
440 */
441 rdctl r3, status
442 ori r3, r3, STATUS_PIE
443 wrctl status, r3
444
445call_exc_handler:
446#ifdef LOG_EXC_ENTER
447 Push r6 /* CPU例外ハンドラ番号保存 */
448 Push r5 /* CPU例外ハンドラアドレス保存 */
449 Push r4 /* CPU例外フレームの先頭番地保存 */
450 mov r4, r6 /* CPU例外ハンドラ番号を引数に */
451 call log_exc_enter
452 Pop r4 /* CPU例外フレームの先頭番地復帰 */
453 Pop r5 /* CPU例外ハンドラアドレス復帰 */
454#endif /* LOG_EXC_ENTER */
455
456 /*
457 * CPU例外ハンドラ呼び出し
458 */
459 callr r5
460
461#ifdef LOG_EXC_LEAVE
462 Pop r4 /* CPU例外ハンドラ番号復帰 */
463 call log_exc_leave
464#endif /* LOG_EXC_LEAVE */
465
466 /*
467 * 割込み禁止
468 */
469 rdctl r3, status
470 movi r4, ~STATUS_PIE
471 and r3, r3, r4
472 wrctl status, r3
473
474 /*
475 * 例外フレームを捨てる
476 */
477 addi sp, sp, 20
478
479 /*
480 * 例外からのリターン処理
481 */
482 br ret_exc
483
484 /*
485 * Trapハンドラ
486 */
487trap_handler:
488 eret
489
490 /*
491 * 割込みハンドラ/CPU例外ハンドラ出口処理1
492 *
493 * ここでは,戻り先がタスクであり,スタックは,タスクスタックの上
494 * にスクラッチレジスタのみが保存された状態になっている.また,
495 * プロセッサは,スーパーバイザーモード・カーネル管理の割込みを禁止
496 * した状態となっている.
497 */
498ret_int_2:
499 stw zero, %gprel(reqflg)(gp) /* reqflg を false に */
500
501 /*
502 * CPUロック状態に移行する.
503 *
504 * この時点でCPUロック状態とするのは,dispatcherへ分岐する時と,
505 * call_texrtnを呼び出す時に,CPUロック状態になっている必要がある
506 * ためである.
507 *
508 * Nios2では,カーネル管理外の割込みを設けないため,ここでは,
509 * 特に何も行わない.
510 */
511
512 /*
513 * dspflgがfalseである場合と,p_runtskとp_schedtskが同じ場合には,
514 * ディスパッチを行わない.このチェックが必要なのは,タスク例外処
515 * 理ルーチンの呼出しが必要な場合に,ディスパッチが必要なくても,
516 * reqflgをtrueにするためである.
517 */
518 ldw r5, %gprel(p_runtsk)(gp) /* r5 <- runtsk */
519 ldw r6, %gprel(dspflg)(gp) /* r6 <- dspflg */
520 beq r6, zero, ret_int_3 /* dspflg が false なら ret_int_3 へ */
521 ldw r4, %gprel(p_schedtsk)(gp) /* r4 <- p_schedtsk */
522 beq r4, r5, ret_int_3 /* runtsk と schedtskが同じならret_int_3へ */
523 addi sp, sp, -32 /* 残りのレジスタを保存 */
524 stw r16, 0(sp)
525 stw r17, 4(sp)
526 stw r18, 8(sp)
527 stw r19, 12(sp)
528 stw r20, 16(sp)
529 stw r21, 20(sp)
530 stw r22, 24(sp)
531 stw r23, 28(sp)
532 stw sp, TCB_sp(r5) /* タスクスタックをTCBに保存 */
533 movhi r2, %hiadj(ret_int_r) /* 実行開始番地を保存 */
534 addi r2, r2, %lo(ret_int_r)
535 stw r2, TCB_pc(r5) /* 実行再開番地をTCBに保存 */
536 br dispatcher
537
538 /*
539 * 割込み・例外でコンテキスト保存した場合の復帰ルーチン
540 */
541ret_int_r:
542 ldw r16, 0(sp) /* レジスタを復帰 */
543 ldw r17, 4(sp)
544 ldw r18, 8(sp)
545 ldw r19, 12(sp)
546 ldw r20, 16(sp)
547 ldw r21, 20(sp)
548 ldw r22, 24(sp)
549 ldw r23, 28(sp)
550 addi sp, sp, 32
551
552ret_int_3:
553 /*
554 * タスク例外ルーチンの起動
555 * ret_int_r は dispatcher から呼び出されるため,
556 * tcb のアドレスは r4 に入っている
557 */
558 ldb r5, TCB_enatex(r4) /* r5 <- enatex */
559#if TCB_enatex_mask > 0xffff
560 andhi r6, r5, %hi(TCB_enatex_mask)
561#else
562 andi r6, r5, %lo(TCB_enatex_mask)
563#endif /* TCB_enatex_mask > 0xffff */
564 beq r6, zero, ret_int_4 /* enatex が false ならリターン */
565 ldw r7, TCB_texptn(r4) /* r7 <- texptn, texptnが0でなければ */
566 beq zero, r7, ret_int_4
567 ldw r7, %gprel(ipmflg)(gp) /* r7 <- ipmflg */
568 beq zero, r7, ret_int_4 /* ipmflgがfalseであればリターン */
569 call call_texrtn /* タスク例外ルーチンの呼び出し */
570
571ret_int_4:
572 ldw et, 0(sp) /* レジスタを復帰 */
573 wrctl estatus, et
574 ldw at, 4(sp)
575 ldw r2, 8(sp)
576 ldw r3, 12(sp)
577 ldw r4, 16(sp)
578 ldw r5, 20(sp)
579 ldw r6, 24(sp)
580 ldw r7, 28(sp)
581 ldw r8, 32(sp)
582 ldw r9, 36(sp)
583 ldw r10, 40(sp)
584 ldw r11, 44(sp)
585 ldw r12, 48(sp)
586 ldw r13, 52(sp)
587 ldw r14, 56(sp)
588 ldw r15, 60(sp)
589 ldw fp, 64(sp)
590 ldw ra, 68(sp)
591 ldw ea, 72(sp)
592 addi sp, sp, 76
593 eret
594
595/*
596 * カーネル管理外のCPU例外の出入口処理
597 */
598kernel_unc_exception:
599 /*
600 * 例外発生元のコンテキストを判定
601 */
602 ldw r3, %gprel(except_nest_count)(gp) /* ネスト回数のチェック */
603 bltu zero, r3, nest_int_exc
604
605 /*
606 * 発生元がタスクの場合はスタックポインタの入れ替え
607 */
608 ldw r2, %gprel(_kernel_istkpt)(gp)
609 addi r2, r2, -4
610 stw sp, 0(r2) /* スタックポインタの保存 */
611 mov sp, r2 /* スタックポインタの入れ替え */
612
613nest_int_kernel_unc_exc:
614 /*
615 * 割込み・例外のネスト回数のインクリメント
616 */
617 addi r4, r3, 1
618 stw r4, %gprel(except_nest_count)(gp)
619
620 /*
621 * CPU例外ハンドラ番号の取得(4倍されている)
622 */
623#ifdef USE_EXTRA_EXCEPTION
624 rdctl r5, exception
625#else
626 mov r5, zero
627#endif /* USE_EXTRA_EXCEPTION */
628 srli r6, r5, 2
629
630 /*
631 * 割込み発生前の割込み優先度マスクをスタックに保存
632 */
633 ldbu r2, %gprel(iipm)(gp)
634 Push r2
635
636 /*
637 * 例外フレームの作成 オフセット
638 * 例外番号 0
639 * ESTATUS(et) 4
640 * 割込み・例外ネストカウント(r3) 8
641 * 戻りアドレス 12
642 * 割込み優先度マスク(iipm) 16
643 */
644 addi sp, sp, -20
645 stw r6, 0(sp)
646 stw et, 4(sp)
647 stw r3, 8(sp)
648 stw ea, 12(sp)
649 stw r2, 16(sp)
650
651 /*
652 * 例外フレームの先頭番地をCPU例外ハンドラの引数に設定(r4)
653 */
654 mov r4, sp
655
656 /*
657 * 例外ハンドラアドレスの取得
658 */
659 movhi r2, %hiadj(exch_tbl)
660 addi r2, r2, %lo(exch_tbl)
661 add r2, r2, r5
662 ldw r5, 0(r2)
663
664 /*
665 * CPU例外ハンドラ呼び出し
666 */
667 callr r5
668
669 /*
670 * 割込み禁止
671 */
672 rdctl r3, status
673 movi r4, ~STATUS_PIE
674 and r3, r3, r4
675 wrctl status, r3
676
677 /*
678 * 例外フレームを捨てる
679 */
680 addi sp, sp, 20
681
682 /*
683 * (モデル上の)割込み優先度マスクを元に戻す
684 */
685 Pop r3 /* 割込み前の(モデル上の)割込み優先度マスクを取得 */
686 stb r3, %gprel(iipm)(gp) /* (モデル上の)割込み優先度マスクをセット */
687 slli r3, r3, 2 /* 割込み優先度マスクを4倍してオフセットを生成 */
688 movhi r2, %hiadj(iipm_mask_tbl) /* 割込み優先度マスクに対応した割込み禁止パターンを取得 */
689 addi r2, r2, %lo(iipm_mask_tbl)
690 add r2, r2, r3
691 ldw r5, 0(r2)
692 ldw r8, %gprel(idf)(gp) /* 各割込みの割込み要求禁止フラグの状態を取得 */
693 nor r8, r8, r5 /* 両者のORの否定を生成 */
694 wrctl ienable, r8 /* 指定した割り込みのみ許可 */
695
696 /*
697 * 割込み・例外のネスト回数のデクリメント
698 */
699 ldw r3, %gprel(except_nest_count)(gp)
700 addi r3, r3, -1
701 stw r3, %gprel(except_nest_count)(gp)
702
703 bltu zero, r3, ret_int_1_kernel_unc_exc /* ネスト回数が1以上ならスタックポインタを変更しない */
704
705 ldw r2, 0(sp) /* スタックポインタを戻す */
706 mov sp, r2
707
708ret_int_1_kernel_unc_exc:
709 ldw et, 0(sp) /* レジスタの復帰 */
710 wrctl estatus, et
711 ldw at, 4(sp)
712 ldw r2, 8(sp)
713 ldw r3, 12(sp)
714 ldw r4, 16(sp)
715 ldw r5, 20(sp)
716 ldw r6, 24(sp)
717 ldw r7, 28(sp)
718 ldw r8, 32(sp)
719 ldw r9, 36(sp)
720 ldw r10, 40(sp)
721 ldw r11, 44(sp)
722 ldw r12, 48(sp)
723 ldw r13, 52(sp)
724 ldw r14, 56(sp)
725 ldw r15, 60(sp)
726 ldw fp, 64(sp)
727 ldw ra, 68(sp)
728 ldw ea, 72(sp)
729 addi sp, sp, 76
730 eret
731
732/*
733 * タスクディスパッチャ
734 */
735 .global dispatch
736 .align 2
737dispatch:
738 /*
739 * このルーチンは,タスクコンテキスト・CPUロック状態・ディスパッチ
740 * 許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さ
741 * れる.
742 */
743 addi sp, sp, -40 /* レジスタを保存 */
744 stw r16, 0(sp)
745 stw r17, 4(sp)
746 stw r18, 8(sp)
747 stw r19, 12(sp)
748 stw r20, 16(sp)
749 stw r21, 20(sp)
750 stw r22, 24(sp)
751 stw r23, 28(sp)
752 stw fp, 32(sp)
753 stw ra, 36(sp)
754 ldw r4, %gprel(p_runtsk)(gp) /* r4 <- runtsk */
755 stw sp, TCB_sp(r4) /* タスクスタックをTCBに保存 */
756 movhi r5, %hiadj(dispatch_r) /* 実行開始番地を保存 */
757 addi r5, r5, %lo(dispatch_r)
758 stw r5, TCB_pc(r4) /* 実行再開番地をTCBに保存 */
759 br dispatcher
760
761dispatch_r:
762 ldw r16, 0(sp) /* レジスタを復帰 */
763 ldw r17, 4(sp)
764 ldw r18, 8(sp)
765 ldw r19, 12(sp)
766 ldw r20, 16(sp)
767 ldw r21, 20(sp)
768 ldw r22, 24(sp)
769 ldw r23, 28(sp)
770 ldw fp, 32(sp)
771
772 /*
773 * タスク例外処理ルーチンの起動
774 * dispatch_r は dispatcher から呼び出されるため,
775 * tcb のアドレスは r4 に入っている
776 */
777 ldb r5, TCB_enatex(r4) /* r5 <- enatex */
778#if TCB_enatex_mask > 0xffff
779 andhi r6, r5, %hi(TCB_enatex_mask)
780#else
781 andi r6, r5, %lo(TCB_enatex_mask)
782#endif /* TCB_enatex_mask > 0xffff */
783 beq r6, zero, dispatch_r_1 /* enatex が false ならリターン */
784 ldw r7, TCB_texptn(r4) /* r7 <- texptn, texptnが0でなければ */
785 beq r7, zero, dispatch_r_1
786 ldw r7, %gprel(ipmflg)(gp) /* r7 <- ipmflg */
787 beq zero, r7, dispatch_r_1 /* ipmflgがfalseであればリターン */
788 call call_texrtn /* タスク例外ルーチンの呼び出し */
789
790dispatch_r_1:
791 ldw ra, 36(sp) /* 残りのレジスタを復帰 */
792 addi sp, sp, 40
793 ret
794
795/*
796 * ディスパッチャの動作開始
797 */
798 .globl start_dispatch
799start_dispatch:
800 /*
801 * このルーチンは,カーネル起動時に,すべての割込みを禁止した状態
802 * (割込みロック状態と同等)で呼び出される.また,割込みモード(非
803 * タスクコンテキストと同等)で呼び出されることを想定している.
804 *
805 * dispatcherは,CPUロック状態,(モデル上の)割込み優先度マスク全
806 * 解除状態,例外(割込み/CPU例外)のネスト回数0で呼び出す.
807 * target_initializeでは,(モデル上の)割込み優先度マスク全解除
808 * とし,カーネル管理外の割込みであるFIQを許可することで,
809 * CPUロック状態・(モデル上の)割込み優先度マスク全解除状態になる.
810 * また,task_initializeでdisdspをfalseに初期化しているため,ディ
811 * スパッチ許可状態になっている.
812 */
813 /* 例外(割込み/CPU例外)のネスト回数をクリア */
814 stw zero, %gprel(except_nest_count)(gp)
815
816/*
817 * 現在のコンテキストを捨ててディスパッチ
818 */
819 .globl exit_and_dispatch
820exit_and_dispatch:
821 /* ディスパッチャ本体(dispatcher)へ */
822
823/*
824 * ディスパッチャ本体
825 */
826dispatcher:
827 /*
828 * このルーチンは,タスクコンテキスト・CPUロック状態・ディスパッチ
829 * 許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さ
830 * れる.実行再開番地へもこの状態のまま分岐する.
831 */
832#ifdef LOG_DSP_ENTER
833 ldw r4, %gprel(p_runtsk)(gp)
834 call log_dsp_enter
835#endif /* LOG_DSP_ENTER */
836
837dispatcher_0:
838 ldw r4, %gprel(p_schedtsk)(gp) /* r4 <- schedtsk */
839 stw r4, %gprel(p_runtsk)(gp) /* schedtsk を runtskに */
840 beq r4, zero, dispatcher_1 /* schedtskがあるか */
841 ldw sp, TCB_sp(r4) /* TCBからタスクスタックを復帰 */
842
843#ifdef LOG_DSP_LEAVE
844 Push r4
845 call log_dsp_leave
846 Pop r4
847#endif /* LOG_DSP_LEAVE */
848
849 ldw r5, TCB_pc(r4) /* TCBから実行再開番地を復帰 */
850 jmp r5
851
852dispatcher_1:
853 /*
854 * CPUロック状態の解除と,非タスクコンテキスト実行状態への
855 * 準備をする
856 */
857 ldw r2, %gprel(_kernel_istkpt)(gp) /* 非タスクコンテキスト用のスタックの読み込み */
858 mov sp, r2 /* スタックポインタの入れ替え */
859 movi r5, 1
860 stw r5, %gprel(except_nest_count)(gp) /* except_nest_count を1に */
861dispatcher_2:
862 /*
863 * 割込みを許可し,非タスクコンテキスト実行状態とし割込みを待つ.
864 *
865 * ここで非タスクコンテキスト実行状態に切り換えるのは,ここで発生
866 * する割込み処理にどのスタックを使うかという問題の解決と,割込み
867 * ハンドラ内でのタスクディスパッチの防止という2つの意味がある.
868 *
869 * プロセッサを割込み待ちに移行させる処理と,割込み許可とは,不可
870 * 分に行なう必要がある.
871 * これを不可分に行なわない場合,割込みを許可した直後に割込
872 * みが入り,その中でタスクが実行可能状態になると,実行すべきタス
873 * クがあるにもかかわらずプロセッサが割込み待ちになってしまう.
874 *
875 * 割込み待ちの間は,p_runtskをNULL(=0)に設定しなければならな
876 * い.このように設定しないと,割込みハンドラからiget_tidを呼び出
877 * した際の動作が仕様に合致しなくなる.
878 *
879 */
880 rdctl r3, status /* 割込み許可 */
881 ori r3, r3, STATUS_PIE
882 wrctl status, r3
883 nop
884 nop
885 nop
886 nop
887 rdctl r3, status /* 割込み禁止 */
888 movi r4, ~STATUS_PIE
889 and r3, r3, r4
890 wrctl status, r3
891 ldw r6, %gprel(reqflg)(gp) /* r6 <- reqflg */
892 beq r6, zero, dispatcher_2 /* reqflg が FALSE なら */
893 stw zero, %gprel(except_nest_count)(gp) /* interrupt_count をクリア */
894 stw zero, %gprel(reqflg)(gp) /* reqflg を FALSE に */
895 br dispatcher_0
896
897/*
898 * カーネルの終了処理の呼出し
899 *
900 * モードとスタックを非タスクコンテキスト用に切り替え.
901 */
902 .globl call_exit_kernel
903call_exit_kernel:
904 ldw r2, %gprel(_kernel_istkpt)(gp) /* 非タスクコンテキスト用のスタックの読み込み */
905 mov sp, r2 /* スタックポインタの入れ替え */
906 call exit_kernel
907
908/*
909 * タスク開始時処理
910 *
911 * dispatcherから呼び出されるため,TCBのアドレスは r4 に入っている
912 */
913 .text
914 .global start_r
915 .align 2
916start_r:
917 rdctl r3, status /* 割込み許可 */
918 ori r3, r3, STATUS_PIE
919 wrctl status, r3
920 ldw r3, TCB_p_tinib(r4) /* r3 <- p_runtsk->p_tinib */
921 ldw r4, TINIB_exinf(r3) /* r4 <- 引数(exinf) */
922 ldw r2, TINIB_task(r3) /* r2 <- タスクの実行番地 */
923 movhi ra, %hiadj(ext_tsk)
924 addi ra, ra, %lo(ext_tsk)
925 jmp r2 /* タスクの実行開始 */
926
927
928/*
929 * 微少時間待ち
930 */
931 .global sil_dly_nse
932sil_dly_nse:
933 addi r4, r4, -SIL_DLY_TIM1
934 bgt r4, zero, sil_dly_nse_1
935 ret
936sil_dly_nse_1:
937 addi r4, r4, -SIL_DLY_TIM2
938 bgt r4, zero, sil_dly_nse_1
939 ret
Note: See TracBrowser for help on using the repository browser.