source: azure_iot_hub_riscv/trunk/asp_baseplatform/arch/riscv_gcc/prc_support.S@ 453

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

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/plain;charset=UTF-8
File size: 24.4 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) 2005-2010 by Embedded and Real-Time Systems Laboratory
9 * Graduate School of Information Science, Nagoya Univ., JAPAN
10 * Copyright (C) 2017-2019 by TOPPERS PROJECT Educational Working Group.
11 *
12 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
13 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
14 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
15 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * スコード中に含まれていること.
18 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
20 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
21 * の無保証規定を掲載すること.
22 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
23 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
24 * と.
25 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
26 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
27 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
28 * 報告すること.
29 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
30 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
31 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
32 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
33 * 免責すること.
34 *
35 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
36 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
37 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
38 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
39 * の責任を負わない.
40 *
41 * $Id$
42 */
43
44/*
45 * プロセッサ依存モジュール アセンブリ言語部(RISC-V用)
46 */
47
48#define TOPPERS_MACRO_ONLY
49#include "encoding.h"
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#include "offset.h"
55
56#if defined(__riscv64)
57#define LREG ld
58#define SREG sd
59#define LFREG fld
60#define SFREG fsd
61#define REGSIZE 8
62#else
63#define LREG lw
64#define SREG sw
65#define LFREG flw
66#define SFREG fsw
67#define REGSIZE 4
68#endif
69
70#if defined(USE_FPU) && !defined(__riscv_float_abi_soft)
71#define SAVEREG1 27
72#define SAVEREG2 42
73#define SAVEREG3 26
74#else
75#define SAVEREG1 15
76#define SAVEREG2 22
77#define SAVEREG3 14
78#endif
79
80/*
81 * タスクディスパッチャ
82 */
83 .text
84 .globl dispatch
85dispatch:
86 /*
87 * このルーチンは,タスクコンテキスト・CPUロック状態・ディスパッチ
88 * 許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さ
89 * れる.
90 */
91 addi sp, sp, -SAVEREG1*REGSIZE /* レジスタ保存領域を確保 */
92 SREG ra, 0*REGSIZE(sp) /* returnアドレスを保存 */
93 SREG gp, 1*REGSIZE(sp) /* call先セーブのレジスタを保存 */
94 SREG tp, 2*REGSIZE(sp)
95 SREG s0, 3*REGSIZE(sp)
96 SREG s1, 4*REGSIZE(sp)
97 SREG s2, 5*REGSIZE(sp)
98 SREG s3, 6*REGSIZE(sp)
99 SREG s4, 7*REGSIZE(sp)
100 SREG s5, 8*REGSIZE(sp)
101 SREG s6, 9*REGSIZE(sp)
102 SREG s7, 10*REGSIZE(sp)
103 SREG s8, 11*REGSIZE(sp)
104 SREG s9, 12*REGSIZE(sp)
105 SREG s10, 13*REGSIZE(sp)
106 SREG s11, 14*REGSIZE(sp)
107#if SAVEREG1 == 27
108 SFREG fs0, 15*REGSIZE(sp)
109 SFREG fs1, 16*REGSIZE(sp)
110 SFREG fs2, 17*REGSIZE(sp)
111 SFREG fs3, 18*REGSIZE(sp)
112 SFREG fs4, 19*REGSIZE(sp)
113 SFREG fs5, 20*REGSIZE(sp)
114 SFREG fs6, 21*REGSIZE(sp)
115 SFREG fs7, 22*REGSIZE(sp)
116 SFREG fs8, 23*REGSIZE(sp)
117 SFREG fs9, 24*REGSIZE(sp)
118 SFREG fs10, 25*REGSIZE(sp)
119 SFREG fs11, 26*REGSIZE(sp)
120#endif
121 la a1, p_runtsk /* p_runtskをA0に */
122 LREG a0, 0(a1)
123 SREG sp, TCB_sp(a0) /* タスクスタックを保存 */
124 la a1, dispatch_r
125 SREG a1, TCB_pc(a0) /* 実行再開番地を保存 */
126 j dispatcher
127
128 .globl dispatch_r
129dispatch_r:
130 LREG ra, 0*REGSIZE(sp) /* returnアドレスを復帰 */
131 LREG gp, 1*REGSIZE(sp) /* call先セーブのレジスタを復帰 */
132 LREG tp, 2*REGSIZE(sp)
133 LREG s0, 3*REGSIZE(sp)
134 LREG s1, 4*REGSIZE(sp)
135 LREG s2, 5*REGSIZE(sp)
136 LREG s3, 6*REGSIZE(sp)
137 LREG s4, 7*REGSIZE(sp)
138 LREG s5, 8*REGSIZE(sp)
139 LREG s6, 9*REGSIZE(sp)
140 LREG s7, 10*REGSIZE(sp)
141 LREG s8, 11*REGSIZE(sp)
142 LREG s9, 12*REGSIZE(sp)
143 LREG s10, 13*REGSIZE(sp)
144 LREG s11, 14*REGSIZE(sp)
145#if SAVEREG1 == 27
146 LFREG fs0, 15*REGSIZE(sp)
147 LFREG fs1, 16*REGSIZE(sp)
148 LFREG fs2, 17*REGSIZE(sp)
149 LFREG fs3, 18*REGSIZE(sp)
150 LFREG fs4, 19*REGSIZE(sp)
151 LFREG fs5, 20*REGSIZE(sp)
152 LFREG fs6, 21*REGSIZE(sp)
153 LFREG fs7, 22*REGSIZE(sp)
154 LFREG fs8, 23*REGSIZE(sp)
155 LFREG fs9, 24*REGSIZE(sp)
156 LFREG fs10, 25*REGSIZE(sp)
157 LFREG fs11, 26*REGSIZE(sp)
158#endif
159 addi sp, sp, SAVEREG1*REGSIZE /* レジスタ保存領域を解放 */
160 li a2, TCB_enatex_bit /* enatexがfalseならリターン */
161 lbu a1, TCB_enatex(a0)
162 sra a1, a1, a2
163 andi a1, a1, 1
164 beqz a1, dispatch_r_1
165 LREG a1, TCB_texptn(a0) /* texptnが0ならリターン */
166 beqz a1, dispatch_r_1
167 la a2, ipmflg /* ipmflgがtrueであれば */
168 lw a1, 0(a2)
169 bnez a1, call_texrtn /* タスク例外処理ルーチンの呼出し */
170dispatch_r_1:
171 ret
172
173/*
174 * ディスパッチャの動作開始(prc_support.S)
175 */
176 .globl start_dispatch
177start_dispatch:
178 /*
179 * このルーチンは,カーネル起動時に,すべての割込みを禁止した状態
180 * (割込みロック状態と同等)で呼び出される.また,割込みモード(非
181 * タスクコンテキストと同等)で呼び出されることを想定している.
182 *
183 * prc_initializeで,lock_flagをtrueに,mieはinit_mieに
184 * カーネル管理外の割込みを許可済みで,CPUロック状態・(モデル上の)
185 * 割込み優先度マスク全解除状態になっている.
186 * (カーネル管理外の割込みを許可しておかないとmtipがうまく起動しない)
187 * また,initialize_taskでdisdspをfalseに初期化しているため,ディ
188 * スパッチ許可状態になっている.
189 */
190 la a0, _kernel_istk /* STACKをカーネルISTKに */
191 LREG sp, 0(a0)
192 la a0, _kernel_istksz
193 LREG a1, 0(a0)
194 add sp, sp, a1
195 j dispatcher_0
196
197/*
198 * 現在のコンテキストを捨ててディスパッチ
199 */
200 .globl exit_and_dispatch
201exit_and_dispatch:
202 /* ディスパッチャ本体(dispatcher)へ */
203
204/*
205 * ディスパッチャ本体
206 */
207dispatcher:
208 /*
209 * このルーチンは,タスクコンテキスト・CPUロック状態・ディスパッチ
210 * 許可状態・(モデル上の)割込み優先度マスク全解除状態で呼び出さ
211 * れる.
212 *
213 * すなわち,マスタモード・lock_flagがtrue・disdspがfalse・dspflg
214 * がtrue・saved_iipmがIIPM_ENAALLとなっている.実行再開番地へもこ
215 * の状態のまま分岐する.
216 */
217#ifdef LOG_DSP_ENTER
218 la a2, p_runtsk /* p_runtskをパラメータに */
219 LREG a0, 0(a2)
220 jal log_dsp_enter
221#endif /* LOG_DSP_ENTER */
222dispatcher_0:
223 la a1, p_schedtsk /* p_schedtskをp_runtskに */
224 LREG a0, 0(a1)
225 la a2, p_runtsk
226 SREG a0, 0(a2)
227 beqz a0, dispatcher_1 /* p_runtskがNULLならdispatcher_1へ */
228 LREG sp, TCB_sp(a0) /* タスクスタックを復帰 */
229#ifdef LOG_DSP_LEAVE
230 jal log_dsp_leave
231 la a2, p_runtsk /* p_runtskを復帰 */
232 LREG a0, 0(a2)
233#endif /* LOG_DSP_LEAVE */
234 LREG a1, TCB_pc(a0) /* 実行再開番地へ分岐 */
235 jr a1
236dispatcher_1:
237 /*
238 * CPUロック状態を解除する準備をする.
239 */
240 csrr a5, mie /* mieをa5に保存 */
241 la a3, lock_flag /* CPUロック解除状態に */
242 sw zero, 0(a3)
243dispatcher_2:
244 /*
245 * 割込みを許可し,割込みモードに切り換えて,割込みを待つ.
246 *
247 * ここで割込みモードに切り換えるのは,ここで発生する割込み処理に
248 * どのスタックを使うかという問題の解決と,割込みハンドラ内でのタ
249 * スクディスパッチの防止という2つの意味がある.
250 *
251 * プロセッサを割込み待ちに移行させる処理と,割込み許可とは,不可
252 * 分に行なう必要がある(M68040ではstop命令で両方行なうので問題な
253 * い).これを不可分に行なわない場合,割込みを許可した直後に割込
254 * みが入り,その中でタスクが実行可能状態になると,実行すべきタス
255 * クがあるにもかかわらずプロセッサが割込み待ちになってしまう.
256 *
257 * 割込み待ちの間は,p_runtskをNULL(=0)に設定しなければならな
258 * い.このように設定しないと,割込みハンドラからiget_tidを呼び出
259 * した際の動作が仕様に合致しなくなる.
260 */
261 la a1, kernel_mie /* 割込み待ち */
262 LREG a2, 0(a1)
263 csrs mie, a2
264 wfi
265 csrw mie, a5 /* 元の状態に戻す */
266 la a2, reqflg /* reqflgがfalseならdispatcher_2へ */
267 lw a1, 0(a2)
268 beqz a1, dispatcher_2
269 sw zero, 0(a2) /* reqflgをfalseに */
270
271 /*
272 * CPUロック状態に戻す.割込み待ちの間に実行した割込みハンドラによ
273 * り,saved_iipmが書き換えられる可能性があるため,元の値に戻す必
274 * 要がある.dispatcherが実行される時は,saved_iipmがIIPM_ENAALL
275 * となっているため,ここではsaved_iipmをIIPM_ENAALL(=0)に戻せ
276 * ばよい.
277 */
278 la a3, lock_flag /* CPUロック状態に */
279 li a1, true
280 sw a1, 0(a3)
281 j dispatcher_0
282
283/*
284 * カーネルの終了処理の呼出し
285 *
286 * RISCVでは,モード切換えによりスタックも切り換わらないため,明示的な
287 * スタック切換えを行う.最初から割込みモードであった場合も,同じ処理
288 * でよい.
289 */
290 .globl call_exit_kernel
291call_exit_kernel:
292 la a0, _kernel_istk /* STACKをカーネルISTKに */
293 LREG sp, 0(a0)
294 la a0, _kernel_istksz
295 LREG a1, 0(a0)
296 add sp, sp, a1
297 j exit_kernel /* カーネルの終了処理を呼ぶ */
298
299/*
300 * タスク開始時処理
301 */
302 .text
303 .globl start_r
304start_r:
305 la a1, lock_flag /* CPUロック解除状態に */
306 sw zero, 0(a1)
307 la ra, ext_tsk /* ext_tskを戻り番地に設定 */
308 li a2, KERNEL_MIE
309 csrrs a2, mie, a2 /* 割込み許可 */
310 LREG a1, TCB_p_tinib(a0) /* p_runtsk->p_tinibをa1に */
311 LREG a0, TINIB_exinf(a1) /* exinfを引数レジスタa0に */
312 LREG a2, TINIB_task(a1) /* タスクの起動番地をa2に */
313 jr a2
314
315
316/*
317 * MACHINE割込み出口処理
318 *
319 * 第一レベルのMACHIE割込みを行う.スタックするレジスタはネスト割込みとほぼ
320 * 同じ,ユーザースタック上に,t3-t6までのレジスタはユーザースタックに
321 * 保存する.(ネスト割込みではシステムスタックに保存)そのため、
322 * 4*RGSIZEバイト分、割込みのためにユーザースタックを消費する.
323 * 例外/割込みが発生すると,システムスタック上に以下の情報とスクラッチ
324 * レジスタを保存する.
325 *
326 * ------------
327 * | mstatus |
328 * ------------
329 * | mpc |
330 * ------------
331 * | mcause |
332 * ------------
333 * | mip |
334 * ------------
335 * | sp(x2) |
336 * ------------
337 * | reserved |
338 * ------------
339 * | a0(x10) |
340 * ------------
341 * | a1(x11) |
342 * ------------
343 * | ra(x1) |
344 * ------------
345 * | a2(x12) |
346 * ------------
347 */
348 .text
349 .align 4
350 .global trap_entry
351trap_entry:
352 addi sp, sp, -SAVEREG2*REGSIZE /* ユーザースタックにワークレジスタの保存領域を作成 */
353 SREG t3, 18*REGSIZE(sp) /* t3-t6をワークレジスタとして使用する */
354 SREG t4, 19*REGSIZE(sp)
355 SREG t5, 20*REGSIZE(sp)
356 SREG t6, 21*REGSIZE(sp)
357 la t4, _kernel_istk /* STACKをカーネルISTKに */
358 LREG t5, 0(t4)
359 la t4, _kernel_istksz
360 LREG t6, 0(t4)
361 mv t4, sp /* ユーザースタックをt4にコピー */
362 add sp, t5, t6 /* システムスタックを設定 */
363
364 addi sp, sp, -SAVEREG2*REGSIZE /* システムスタック保存領域を作成 */
365 SREG a0, 6*REGSIZE(sp) /* スクラッチレジスタを保存 */
366 SREG a1, 7*REGSIZE(sp)
367 SREG a2, 8*REGSIZE(sp)
368 SREG ra, 9*REGSIZE(sp)
369 SREG a3, 10*REGSIZE(sp)
370 SREG a4, 11*REGSIZE(sp)
371 SREG a5, 12*REGSIZE(sp)
372 SREG a6, 13*REGSIZE(sp)
373 SREG a7, 14*REGSIZE(sp)
374 SREG t0, 15*REGSIZE(sp)
375 SREG t1, 16*REGSIZE(sp)
376 SREG t2, 17*REGSIZE(sp)
377#if SAVEREG2 == 42
378 SFREG ft0, 22*REGSIZE(sp)
379 SFREG ft1, 23*REGSIZE(sp)
380 SFREG ft2, 24*REGSIZE(sp)
381 SFREG ft3, 25*REGSIZE(sp)
382 SFREG ft4, 26*REGSIZE(sp)
383 SFREG ft5, 27*REGSIZE(sp)
384 SFREG ft6, 28*REGSIZE(sp)
385 SFREG ft7, 29*REGSIZE(sp)
386 SFREG fa0, 30*REGSIZE(sp)
387 SFREG fa1, 31*REGSIZE(sp)
388 SFREG fa2, 32*REGSIZE(sp)
389 SFREG fa3, 33*REGSIZE(sp)
390 SFREG fa4, 34*REGSIZE(sp)
391 SFREG fa5, 35*REGSIZE(sp)
392 SFREG fa6, 36*REGSIZE(sp)
393 SFREG fa7, 37*REGSIZE(sp)
394 SFREG ft8, 38*REGSIZE(sp)
395 SFREG ft9, 39*REGSIZE(sp)
396 SFREG ft10, 40*REGSIZE(sp)
397 SFREG ft11, 41*REGSIZE(sp)
398#endif
399
400 csrr a0, mcause /* mcauseを2に保存 */
401 SREG a0, 2*REGSIZE(sp)
402 csrr t5, mepc /* mpcを1に保存 */
403 SREG t5, 1*REGSIZE(sp)
404 csrr t6, mstatus /* mstatusを0に保存 */
405 SREG t6, 0*REGSIZE(sp)
406 csrr t3, mie /* mieを3に保存 */
407 SREG t3, 3*REGSIZE(sp)
408 SREG t4, 4*REGSIZE(sp) /* ユーザースタックを4に保存 */
409 li a2, KERNEL_MIE
410 csrc mie, a2 /* カーネル内割込み禁止 */
411 li a3, (MSTATUS_MPP | MSTATUS_MIE)
412 csrs mstatus, a3 /* カーネル外割込み許可 */
413 mv a1, sp /* スタックをa1に設定 */
414 call handle_trap /* MACHINEハンドラを呼び出す */
415
416 LREG a0, 6*REGSIZE(sp) /* スクラッチレジスタを復帰 */
417 LREG a1, 7*REGSIZE(sp)
418 LREG a2, 8*REGSIZE(sp)
419 LREG ra, 9*REGSIZE(sp)
420 LREG a3, 10*REGSIZE(sp)
421 LREG a4, 11*REGSIZE(sp)
422 LREG a5, 12*REGSIZE(sp)
423 LREG a6, 13*REGSIZE(sp)
424 LREG a7, 14*REGSIZE(sp)
425 LREG t0, 15*REGSIZE(sp)
426 LREG t1, 16*REGSIZE(sp)
427 LREG t2, 17*REGSIZE(sp)
428#if SAVEREG2 == 42
429 LFREG ft0, 22*REGSIZE(sp)
430 LFREG ft1, 23*REGSIZE(sp)
431 LFREG ft2, 24*REGSIZE(sp)
432 LFREG ft3, 25*REGSIZE(sp)
433 LFREG ft4, 26*REGSIZE(sp)
434 LFREG ft5, 27*REGSIZE(sp)
435 LFREG ft6, 28*REGSIZE(sp)
436 LFREG ft7, 29*REGSIZE(sp)
437 LFREG fa0, 30*REGSIZE(sp)
438 LFREG fa1, 31*REGSIZE(sp)
439 LFREG fa2, 32*REGSIZE(sp)
440 LFREG fa3, 33*REGSIZE(sp)
441 LFREG fa4, 34*REGSIZE(sp)
442 LFREG fa5, 35*REGSIZE(sp)
443 LFREG fa6, 36*REGSIZE(sp)
444 LFREG fa7, 37*REGSIZE(sp)
445 LFREG ft8, 38*REGSIZE(sp)
446 LFREG ft9, 39*REGSIZE(sp)
447 LFREG ft10, 40*REGSIZE(sp)
448 LFREG ft11, 41*REGSIZE(sp)
449#endif
450
451 la t5, reqflg /* reqflgがtrueであればtrap_entery_2へ */
452 lw t6, 0(t5)
453 bnez t6, trap_entry_2
454 la t5, lock_flag /* CPUロック解除の準備 */
455 sw zero, 0(t5)
456 LREG t5, 1*REGSIZE(sp) /* mepcの取り出し */
457 LREG t6, 0*REGSIZE(sp) /* mstatusの取り出し */
458 LREG t4, 3*REGSIZE(sp) /* mieの取り出し */
459 csrw mepc, t5 /* mepcを復帰 */
460 csrw mstatus, t6 /* mstatusを復帰 */
461 csrw mie, t4 /* mieを復帰 */
462 LREG sp, 4*REGSIZE(sp) /* ユーザースタックを復帰 */
463
464 LREG t3, 18*REGSIZE(sp) /* ワーク用スクラッチレジスタを復帰 */
465 LREG t4, 19*REGSIZE(sp)
466 LREG t5, 20*REGSIZE(sp)
467 LREG t6, 21*REGSIZE(sp)
468 addi sp, sp, SAVEREG2*REGSIZE /* スタックを開放 */
469 mret
470
471trap_entry_2:
472 LREG t5, 1*REGSIZE(sp) /* mepcの取り出し */
473 LREG t4, 2*REGSIZE(sp) /* mcauseの取り出し */
474 LREG t3, 3*REGSIZE(sp) /* mieの取り出し */
475 LREG t6, 0*REGSIZE(sp) /* mstatusの取り出し */
476 LREG sp, 4*REGSIZE(sp) /* ユーザースタックを復帰 */
477
478 SREG t6, 0*REGSIZE(sp) /* mstatusの保存 */
479 SREG t3, 3*REGSIZE(sp) /* mieの保存 */
480 SREG t4, 2*REGSIZE(sp) /* mcauseの保存 */
481 SREG t5, 1*REGSIZE(sp) /* mepcの保存 */
482 SREG a0, 6*REGSIZE(sp) /* スクラッチレジスタを保存 */
483 SREG a1, 7*REGSIZE(sp)
484 SREG a2, 8*REGSIZE(sp)
485 SREG ra, 9*REGSIZE(sp)
486 SREG a3, 10*REGSIZE(sp)
487 SREG a4, 11*REGSIZE(sp)
488 SREG a5, 12*REGSIZE(sp)
489 SREG a6, 13*REGSIZE(sp)
490 SREG a7, 14*REGSIZE(sp)
491 SREG t0, 15*REGSIZE(sp)
492 SREG t1, 16*REGSIZE(sp)
493 SREG t2, 17*REGSIZE(sp)
494#if SAVEREG2 == 42
495 SFREG ft0, 22*REGSIZE(sp)
496 SFREG ft1, 23*REGSIZE(sp)
497 SFREG ft2, 24*REGSIZE(sp)
498 SFREG ft3, 25*REGSIZE(sp)
499 SFREG ft4, 26*REGSIZE(sp)
500 SFREG ft5, 27*REGSIZE(sp)
501 SFREG ft6, 28*REGSIZE(sp)
502 SFREG ft7, 29*REGSIZE(sp)
503 SFREG fa0, 30*REGSIZE(sp)
504 SFREG fa1, 31*REGSIZE(sp)
505 SFREG fa2, 32*REGSIZE(sp)
506 SFREG fa3, 33*REGSIZE(sp)
507 SFREG fa4, 34*REGSIZE(sp)
508 SFREG fa5, 35*REGSIZE(sp)
509 SFREG fa6, 36*REGSIZE(sp)
510 SFREG fa7, 37*REGSIZE(sp)
511 SFREG ft8, 38*REGSIZE(sp)
512 SFREG ft9, 39*REGSIZE(sp)
513 SFREG ft10, 40*REGSIZE(sp)
514 SFREG ft11, 41*REGSIZE(sp)
515#endif
516
517 la a0, reqflg /* reqflgをfalseに */
518 sw zero, 0(a0)
519 la a1, lock_flag /* loc_flagをtrueに */
520 li a2, true
521 sw a2, 0(a1)
522
523 la a1, p_runtsk /* p_runtskをa0に */
524 LREG a0, 0(a1)
525 la a2, dspflg /* dspflgがfalseならret_int_1へ */
526 lw a3, 0(a2)
527 beqz a3, ret_int_1
528 la a2, p_schedtsk /* p_runtskとp_schedtskが同じなら */
529 LREG a3, 0(a2)
530 beq a0, a3, ret_int_1 /* ret_int_1へ */
531
532 addi sp, sp, -SAVEREG3*REGSIZE /* call先セーブのレジスタを保存 */
533 SREG gp, 0*REGSIZE(sp)
534 SREG tp, 1*REGSIZE(sp)
535 SREG s0, 2*REGSIZE(sp)
536 SREG s1, 3*REGSIZE(sp)
537 SREG s2, 4*REGSIZE(sp)
538 SREG s3, 5*REGSIZE(sp)
539 SREG s4, 6*REGSIZE(sp)
540 SREG s5, 7*REGSIZE(sp)
541 SREG s6, 8*REGSIZE(sp)
542 SREG s7, 9*REGSIZE(sp)
543 SREG s8, 10*REGSIZE(sp)
544 SREG s9, 11*REGSIZE(sp)
545 SREG s10, 12*REGSIZE(sp)
546 SREG s11, 13*REGSIZE(sp)
547#if SAVEREG3 == 26
548 SFREG fs0, 14*REGSIZE(sp)
549 SFREG fs1, 15*REGSIZE(sp)
550 SFREG fs2, 16*REGSIZE(sp)
551 SFREG fs3, 17*REGSIZE(sp)
552 SFREG fs4, 18*REGSIZE(sp)
553 SFREG fs5, 19*REGSIZE(sp)
554 SFREG fs6, 20*REGSIZE(sp)
555 SFREG fs7, 21*REGSIZE(sp)
556 SFREG fs8, 22*REGSIZE(sp)
557 SFREG fs9, 23*REGSIZE(sp)
558 SFREG fs10, 24*REGSIZE(sp)
559 SFREG fs11, 25*REGSIZE(sp)
560#endif
561 SREG sp, TCB_sp(a0) /* タスクスタックを保存 */
562 la a1, ret_int_r /* 実行再開番地を保存 */
563 SREG a1, TCB_pc(a0)
564 j dispatcher
565
566ret_int_r:
567 LREG gp, 0*REGSIZE(sp) /* call先セーブのレジスタを復帰 */
568 LREG tp, 1*REGSIZE(sp)
569 LREG s0, 2*REGSIZE(sp)
570 LREG s1, 3*REGSIZE(sp)
571 LREG s2, 4*REGSIZE(sp)
572 LREG s3, 5*REGSIZE(sp)
573 LREG s4, 6*REGSIZE(sp)
574 LREG s5, 7*REGSIZE(sp)
575 LREG s6, 8*REGSIZE(sp)
576 LREG s7, 9*REGSIZE(sp)
577 LREG s8, 10*REGSIZE(sp)
578 LREG s9, 11*REGSIZE(sp)
579 LREG s10, 12*REGSIZE(sp)
580 LREG s11, 13*REGSIZE(sp)
581#if SAVEREG3 == 26
582 LFREG fs0, 14*REGSIZE(sp)
583 LFREG fs1, 15*REGSIZE(sp)
584 LFREG fs2, 16*REGSIZE(sp)
585 LFREG fs3, 17*REGSIZE(sp)
586 LFREG fs4, 18*REGSIZE(sp)
587 LFREG fs5, 19*REGSIZE(sp)
588 LFREG fs6, 20*REGSIZE(sp)
589 LFREG fs7, 21*REGSIZE(sp)
590 LFREG fs8, 22*REGSIZE(sp)
591 LFREG fs9, 23*REGSIZE(sp)
592 LFREG fs10, 24*REGSIZE(sp)
593 LFREG fs11, 25*REGSIZE(sp)
594#endif
595 addi sp, sp, SAVEREG3*REGSIZE
596ret_int_1:
597 /*
598 * enatexがtrueで,texptnが0でなく,ipmflgがtrueであれば,タスク
599 * 例外処理ルーチンを呼び出す.
600 */
601 li a2, TCB_enatex_bit /* enatexがfalseならret_int_2へ */
602 lbu a1, TCB_enatex(a0)
603 sra a1, a1, a2
604 andi a1, a1, 1
605 beqz a1, ret_int_2
606 lw a1, TCB_texptn(a0) /* texptnが0ならばret_int_2へ */
607 beqz a1, ret_int_2
608 la a2, ipmflg /* ipmflgがfalseならret_int_2へ */
609 lw a1, 0(a2)
610 beqz a1, ret_int_2
611 jal call_texrtn
612ret_int_2:
613 /*
614 * 割込み処理からのリターンにより,CPUロック解除状態に移行するよ
615 * う準備する.割込み優先度マスクは,MRET命令により元の値に戻るた
616 * め,lock_flagをfalseにしておけばよい.
617 */
618 la a0, lock_flag /* CPUロック解除の準備 */
619 sw zero, 0(a0)
620
621ret_int_3:
622 LREG a1, 3*REGSIZE(sp) /* mieの取り出し */
623 LREG a2, 1*REGSIZE(sp) /* mpcの取り出し */
624 LREG a3, 0*REGSIZE(sp) /* mstatusの取り出し */
625 csrw mepc, a2 /* mpcの復帰 */
626 csrw mstatus, a3 /* mstatusの復帰 */
627 csrw mie, a1 /* mieの復帰 */
628
629 LREG a0, 6*REGSIZE(sp) /* スクラッチレジスタの復帰 */
630 LREG a1, 7*REGSIZE(sp)
631 LREG a2, 8*REGSIZE(sp)
632 LREG ra, 9*REGSIZE(sp)
633 LREG a3, 10*REGSIZE(sp)
634 LREG a4, 11*REGSIZE(sp)
635 LREG a5, 12*REGSIZE(sp)
636 LREG a6, 13*REGSIZE(sp)
637 LREG a7, 14*REGSIZE(sp)
638 LREG t0, 15*REGSIZE(sp)
639 LREG t1, 16*REGSIZE(sp)
640 LREG t2, 17*REGSIZE(sp)
641 LREG t3, 18*REGSIZE(sp)
642 LREG t4, 19*REGSIZE(sp)
643 LREG t5, 20*REGSIZE(sp)
644 LREG t6, 21*REGSIZE(sp)
645#if SAVEREG2 == 42
646 LFREG ft0, 22*REGSIZE(sp)
647 LFREG ft1, 23*REGSIZE(sp)
648 LFREG ft2, 24*REGSIZE(sp)
649 LFREG ft3, 25*REGSIZE(sp)
650 LFREG ft4, 26*REGSIZE(sp)
651 LFREG ft5, 27*REGSIZE(sp)
652 LFREG ft6, 28*REGSIZE(sp)
653 LFREG ft7, 29*REGSIZE(sp)
654 LFREG fa0, 30*REGSIZE(sp)
655 LFREG fa1, 31*REGSIZE(sp)
656 LFREG fa2, 32*REGSIZE(sp)
657 LFREG fa3, 33*REGSIZE(sp)
658 LFREG fa4, 34*REGSIZE(sp)
659 LFREG fa5, 35*REGSIZE(sp)
660 LFREG fa6, 36*REGSIZE(sp)
661 LFREG fa7, 37*REGSIZE(sp)
662 LFREG ft8, 38*REGSIZE(sp)
663 LFREG ft9, 39*REGSIZE(sp)
664 LFREG ft10, 40*REGSIZE(sp)
665 LFREG ft11, 41*REGSIZE(sp)
666#endif
667 addi sp, sp, SAVEREG2*REGSIZE
668 mret
669
670/*
671 * MACHINEネスト割込み出入口処理
672 *
673 * trap_nestは,ネストしたMACHINE割込みの出入口処理を行う.
674 * mtvecの設定は呼び出したhandle_trapで行う.
675 * handle_trapからのリターンはネスト状態に限定されるため
676 * この出入り口では、スタックの変更も行わない.
677 */
678 .text
679 .align 4
680 .global trap_nest
681trap_nest:
682 addi sp, sp, -SAVEREG2*REGSIZE /* システムスタック保存領域を作成 */
683 SREG a0, 6*REGSIZE(sp) /* スクラッチレジスタを保存 */
684 SREG a1, 7*REGSIZE(sp)
685 SREG a2, 8*REGSIZE(sp)
686 SREG ra, 9*REGSIZE(sp)
687 SREG a3, 10*REGSIZE(sp)
688 SREG a4, 11*REGSIZE(sp)
689 SREG a5, 12*REGSIZE(sp)
690 SREG a6, 13*REGSIZE(sp)
691 SREG a7, 14*REGSIZE(sp)
692 SREG t0, 15*REGSIZE(sp)
693 SREG t1, 16*REGSIZE(sp)
694 SREG t2, 17*REGSIZE(sp)
695 SREG t3, 18*REGSIZE(sp)
696 SREG t4, 19*REGSIZE(sp)
697 SREG t5, 20*REGSIZE(sp)
698 SREG t6, 21*REGSIZE(sp)
699#if SAVEREG2 == 42
700 SFREG ft0, 22*REGSIZE(sp)
701 SFREG ft1, 23*REGSIZE(sp)
702 SFREG ft2, 24*REGSIZE(sp)
703 SFREG ft3, 25*REGSIZE(sp)
704 SFREG ft4, 26*REGSIZE(sp)
705 SFREG ft5, 27*REGSIZE(sp)
706 SFREG ft6, 28*REGSIZE(sp)
707 SFREG ft7, 29*REGSIZE(sp)
708 SFREG fa0, 30*REGSIZE(sp)
709 SFREG fa1, 31*REGSIZE(sp)
710 SFREG fa2, 32*REGSIZE(sp)
711 SFREG fa3, 33*REGSIZE(sp)
712 SFREG fa4, 34*REGSIZE(sp)
713 SFREG fa5, 35*REGSIZE(sp)
714 SFREG fa6, 36*REGSIZE(sp)
715 SFREG fa7, 37*REGSIZE(sp)
716 SFREG ft8, 38*REGSIZE(sp)
717 SFREG ft9, 39*REGSIZE(sp)
718 SFREG ft10, 40*REGSIZE(sp)
719 SFREG ft11, 41*REGSIZE(sp)
720#endif
721
722 csrr a3, mstatus /* mstatusを0に保存 */
723 SREG a3, 0*REGSIZE(sp)
724 csrr a1, mie /* mieを3に保存 */
725 SREG a1, 3*REGSIZE(sp)
726 addi a2, sp, 22*REGSIZE /* システムスタックを4に保存 */
727 SREG a2, 4*REGSIZE(sp)
728 csrr a0, mcause /* mcauseをa0に取り出し */
729 SREG a0, 2*REGSIZE(sp) /* mcauseを2に保存 */
730 csrr a3, mepc /* mpcを1に保存 */
731 SREG a3, 1*REGSIZE(sp)
732 li a2, KERNEL_MIE
733 csrc mie, a2 /* カーネル内割込み禁止 */
734 li a3, (MSTATUS_MPP | MSTATUS_MIE)
735 csrs mstatus, a3 /* カーネル外割込み許可 */
736 mv a1, sp /* スタックをa1に設定 */
737 la ra, ret_int_3 /* リターンアドレスをセット */
738 j handle_trap /* MACHINEハンドラを呼び出す */
739
740/*
741 * 微少時間待ち(本来はSILのターゲット依存部)
742 */
743 .globl sil_dly_nse
744 .align 4
745sil_dly_nse:
746 addi a0, a0, (-SIL_DLY_TIM1) /* a0からSIL_DLY_TIM1を引く */
747 blez a0, _sil_dly_nse_2 /* 結果が0以下ならリターン */
748_sil_dly_nse_1:
749 addi a0, a0, (-SIL_DLY_TIM2) /* a0からSIL_DLY_TIM2を引く */
750 bgtz a0, _sil_dly_nse_1 /* 結果が0より大きければループ */
751_sil_dly_nse_2:
752 ret
753
Note: See TracBrowser for help on using the repository browser.