diff options
author | Yoshinori Sato <ysato@users.sourceforge.jp> | 2006-11-05 02:15:19 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2006-12-05 20:45:36 -0500 |
commit | de39840646a223ae13a346048c280b7c871bf56e (patch) | |
tree | aa2449880c12310ccb92540bfd63e43e8a568745 /arch/sh/kernel/cpu/sh3 | |
parent | 0983b31849bbe1fe82520947acc1bec97c457d4b (diff) |
sh: Exception vector rework and SH-2/SH-2A support.
This splits out common bits from the existing exception handler for
use between SH-2/SH-2A and SH-3/4, and adds support for the SH-2/2A
exceptions.
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/cpu/sh3')
-rw-r--r-- | arch/sh/kernel/cpu/sh3/Makefile | 2 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh3/entry.S | 526 |
2 files changed, 527 insertions, 1 deletions
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index 58d3815695ff..83905e4e4387 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the Linux/SuperH SH-3 backends. | 2 | # Makefile for the Linux/SuperH SH-3 backends. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := ex.o probe.o | 5 | obj-y := ex.o probe.o entry.o |
6 | 6 | ||
7 | # CPU subtype setup | 7 | # CPU subtype setup |
8 | obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o | 8 | obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o |
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S new file mode 100644 index 000000000000..8bcd63f9f351 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
@@ -0,0 +1,526 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/entry.S | ||
3 | * | ||
4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | ||
5 | * Copyright (C) 2003 - 2006 Paul Mundt | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | */ | ||
11 | #include <linux/sys.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/linkage.h> | ||
14 | #include <asm/asm-offsets.h> | ||
15 | #include <asm/thread_info.h> | ||
16 | #include <asm/cpu/mmu_context.h> | ||
17 | #include <asm/unistd.h> | ||
18 | |||
19 | ! NOTE: | ||
20 | ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address | ||
21 | ! to be jumped is too far, but it causes illegal slot exception. | ||
22 | |||
23 | /* | ||
24 | * entry.S contains the system-call and fault low-level handling routines. | ||
25 | * This also contains the timer-interrupt handler, as well as all interrupts | ||
26 | * and faults that can result in a task-switch. | ||
27 | * | ||
28 | * NOTE: This code handles signal-recognition, which happens every time | ||
29 | * after a timer-interrupt and after each system call. | ||
30 | * | ||
31 | * NOTE: This code uses a convention that instructions in the delay slot | ||
32 | * of a transfer-control instruction are indented by an extra space, thus: | ||
33 | * | ||
34 | * jmp @k0 ! control-transfer instruction | ||
35 | * ldc k1, ssr ! delay slot | ||
36 | * | ||
37 | * Stack layout in 'ret_from_syscall': | ||
38 | * ptrace needs to have all regs on the stack. | ||
39 | * if the order here is changed, it needs to be | ||
40 | * updated in ptrace.c and ptrace.h | ||
41 | * | ||
42 | * r0 | ||
43 | * ... | ||
44 | * r15 = stack pointer | ||
45 | * spc | ||
46 | * pr | ||
47 | * ssr | ||
48 | * gbr | ||
49 | * mach | ||
50 | * macl | ||
51 | * syscall # | ||
52 | * | ||
53 | */ | ||
54 | #if defined(CONFIG_KGDB_NMI) | ||
55 | NMI_VEC = 0x1c0 ! Must catch early for debounce | ||
56 | #endif | ||
57 | |||
58 | /* Offsets to the stack */ | ||
59 | OFF_R0 = 0 /* Return value. New ABI also arg4 */ | ||
60 | OFF_R1 = 4 /* New ABI: arg5 */ | ||
61 | OFF_R2 = 8 /* New ABI: arg6 */ | ||
62 | OFF_R3 = 12 /* New ABI: syscall_nr */ | ||
63 | OFF_R4 = 16 /* New ABI: arg0 */ | ||
64 | OFF_R5 = 20 /* New ABI: arg1 */ | ||
65 | OFF_R6 = 24 /* New ABI: arg2 */ | ||
66 | OFF_R7 = 28 /* New ABI: arg3 */ | ||
67 | OFF_SP = (15*4) | ||
68 | OFF_PC = (16*4) | ||
69 | OFF_SR = (16*4+8) | ||
70 | OFF_TRA = (16*4+6*4) | ||
71 | |||
72 | |||
73 | #define k0 r0 | ||
74 | #define k1 r1 | ||
75 | #define k2 r2 | ||
76 | #define k3 r3 | ||
77 | #define k4 r4 | ||
78 | |||
79 | #define g_imask r6 /* r6_bank1 */ | ||
80 | #define k_g_imask r6_bank /* r6_bank1 */ | ||
81 | #define current r7 /* r7_bank1 */ | ||
82 | |||
83 | #include <asm/entry-macros.S> | ||
84 | |||
85 | /* | ||
86 | * Kernel mode register usage: | ||
87 | * k0 scratch | ||
88 | * k1 scratch | ||
89 | * k2 scratch (Exception code) | ||
90 | * k3 scratch (Return address) | ||
91 | * k4 scratch | ||
92 | * k5 reserved | ||
93 | * k6 Global Interrupt Mask (0--15 << 4) | ||
94 | * k7 CURRENT_THREAD_INFO (pointer to current thread info) | ||
95 | */ | ||
96 | |||
97 | ! | ||
98 | ! TLB Miss / Initial Page write exception handling | ||
99 | ! _and_ | ||
100 | ! TLB hits, but the access violate the protection. | ||
101 | ! It can be valid access, such as stack grow and/or C-O-W. | ||
102 | ! | ||
103 | ! | ||
104 | ! Find the pmd/pte entry and loadtlb | ||
105 | ! If it's not found, cause address error (SEGV) | ||
106 | ! | ||
107 | ! Although this could be written in assembly language (and it'd be faster), | ||
108 | ! this first version depends *much* on C implementation. | ||
109 | ! | ||
110 | |||
111 | #if defined(CONFIG_MMU) | ||
112 | .align 2 | ||
113 | ENTRY(tlb_miss_load) | ||
114 | bra call_dpf | ||
115 | mov #0, r5 | ||
116 | |||
117 | .align 2 | ||
118 | ENTRY(tlb_miss_store) | ||
119 | bra call_dpf | ||
120 | mov #1, r5 | ||
121 | |||
122 | .align 2 | ||
123 | ENTRY(initial_page_write) | ||
124 | bra call_dpf | ||
125 | mov #1, r5 | ||
126 | |||
127 | .align 2 | ||
128 | ENTRY(tlb_protection_violation_load) | ||
129 | bra call_dpf | ||
130 | mov #0, r5 | ||
131 | |||
132 | .align 2 | ||
133 | ENTRY(tlb_protection_violation_store) | ||
134 | bra call_dpf | ||
135 | mov #1, r5 | ||
136 | |||
137 | call_dpf: | ||
138 | mov.l 1f, r0 | ||
139 | mov r5, r8 | ||
140 | mov.l @r0, r6 | ||
141 | mov r6, r9 | ||
142 | mov.l 2f, r0 | ||
143 | sts pr, r10 | ||
144 | jsr @r0 | ||
145 | mov r15, r4 | ||
146 | ! | ||
147 | tst r0, r0 | ||
148 | bf/s 0f | ||
149 | lds r10, pr | ||
150 | rts | ||
151 | nop | ||
152 | 0: sti | ||
153 | mov.l 3f, r0 | ||
154 | mov r9, r6 | ||
155 | mov r8, r5 | ||
156 | jmp @r0 | ||
157 | mov r15, r4 | ||
158 | |||
159 | .align 2 | ||
160 | 1: .long MMU_TEA | ||
161 | 2: .long __do_page_fault | ||
162 | 3: .long do_page_fault | ||
163 | |||
164 | .align 2 | ||
165 | ENTRY(address_error_load) | ||
166 | bra call_dae | ||
167 | mov #0,r5 ! writeaccess = 0 | ||
168 | |||
169 | .align 2 | ||
170 | ENTRY(address_error_store) | ||
171 | bra call_dae | ||
172 | mov #1,r5 ! writeaccess = 1 | ||
173 | |||
174 | .align 2 | ||
175 | call_dae: | ||
176 | mov.l 1f, r0 | ||
177 | mov.l @r0, r6 ! address | ||
178 | mov.l 2f, r0 | ||
179 | jmp @r0 | ||
180 | mov r15, r4 ! regs | ||
181 | |||
182 | .align 2 | ||
183 | 1: .long MMU_TEA | ||
184 | 2: .long do_address_error | ||
185 | #endif /* CONFIG_MMU */ | ||
186 | |||
187 | #if defined(CONFIG_SH_STANDARD_BIOS) | ||
188 | /* Unwind the stack and jmp to the debug entry */ | ||
189 | debug_kernel_fw: | ||
190 | mov.l @r15+, r0 | ||
191 | mov.l @r15+, r1 | ||
192 | mov.l @r15+, r2 | ||
193 | mov.l @r15+, r3 | ||
194 | mov.l @r15+, r4 | ||
195 | mov.l @r15+, r5 | ||
196 | mov.l @r15+, r6 | ||
197 | mov.l @r15+, r7 | ||
198 | stc sr, r8 | ||
199 | mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F | ||
200 | or r9, r8 | ||
201 | ldc r8, sr ! here, change the register bank | ||
202 | mov.l @r15+, r8 | ||
203 | mov.l @r15+, r9 | ||
204 | mov.l @r15+, r10 | ||
205 | mov.l @r15+, r11 | ||
206 | mov.l @r15+, r12 | ||
207 | mov.l @r15+, r13 | ||
208 | mov.l @r15+, r14 | ||
209 | mov.l @r15+, k0 | ||
210 | ldc.l @r15+, spc | ||
211 | lds.l @r15+, pr | ||
212 | mov.l @r15+, k1 | ||
213 | ldc.l @r15+, gbr | ||
214 | lds.l @r15+, mach | ||
215 | lds.l @r15+, macl | ||
216 | mov k0, r15 | ||
217 | ! | ||
218 | mov.l 2f, k0 | ||
219 | mov.l @k0, k0 | ||
220 | jmp @k0 | ||
221 | ldc k1, ssr | ||
222 | .align 2 | ||
223 | 1: .long 0x300000f0 | ||
224 | 2: .long gdb_vbr_vector | ||
225 | #endif /* CONFIG_SH_STANDARD_BIOS */ | ||
226 | |||
227 | restore_all: | ||
228 | mov.l @r15+, r0 | ||
229 | mov.l @r15+, r1 | ||
230 | mov.l @r15+, r2 | ||
231 | mov.l @r15+, r3 | ||
232 | mov.l @r15+, r4 | ||
233 | mov.l @r15+, r5 | ||
234 | mov.l @r15+, r6 | ||
235 | mov.l @r15+, r7 | ||
236 | ! | ||
237 | stc sr, r8 | ||
238 | mov.l 7f, r9 | ||
239 | or r9, r8 ! BL =1, RB=1 | ||
240 | ldc r8, sr ! here, change the register bank | ||
241 | ! | ||
242 | mov.l @r15+, r8 | ||
243 | mov.l @r15+, r9 | ||
244 | mov.l @r15+, r10 | ||
245 | mov.l @r15+, r11 | ||
246 | mov.l @r15+, r12 | ||
247 | mov.l @r15+, r13 | ||
248 | mov.l @r15+, r14 | ||
249 | mov.l @r15+, k4 ! original stack pointer | ||
250 | ldc.l @r15+, spc | ||
251 | lds.l @r15+, pr | ||
252 | mov.l @r15+, k3 ! original SR | ||
253 | ldc.l @r15+, gbr | ||
254 | lds.l @r15+, mach | ||
255 | lds.l @r15+, macl | ||
256 | add #4, r15 ! Skip syscall number | ||
257 | ! | ||
258 | #ifdef CONFIG_SH_DSP | ||
259 | mov.l @r15+, k0 ! DSP mode marker | ||
260 | mov.l 5f, k1 | ||
261 | cmp/eq k0, k1 ! Do we have a DSP stack frame? | ||
262 | bf skip_restore | ||
263 | |||
264 | stc sr, k0 ! Enable CPU DSP mode | ||
265 | or k1, k0 ! (within kernel it may be disabled) | ||
266 | ldc k0, sr | ||
267 | mov r2, k0 ! Backup r2 | ||
268 | |||
269 | ! Restore DSP registers from stack | ||
270 | mov r15, r2 | ||
271 | movs.l @r2+, a1 | ||
272 | movs.l @r2+, a0g | ||
273 | movs.l @r2+, a1g | ||
274 | movs.l @r2+, m0 | ||
275 | movs.l @r2+, m1 | ||
276 | mov r2, r15 | ||
277 | |||
278 | lds.l @r15+, a0 | ||
279 | lds.l @r15+, x0 | ||
280 | lds.l @r15+, x1 | ||
281 | lds.l @r15+, y0 | ||
282 | lds.l @r15+, y1 | ||
283 | lds.l @r15+, dsr | ||
284 | ldc.l @r15+, rs | ||
285 | ldc.l @r15+, re | ||
286 | ldc.l @r15+, mod | ||
287 | |||
288 | mov k0, r2 ! Restore r2 | ||
289 | skip_restore: | ||
290 | #endif | ||
291 | ! | ||
292 | ! Calculate new SR value | ||
293 | mov k3, k2 ! original SR value | ||
294 | mov #0xf0, k1 | ||
295 | extu.b k1, k1 | ||
296 | not k1, k1 | ||
297 | and k1, k2 ! Mask orignal SR value | ||
298 | ! | ||
299 | mov k3, k0 ! Calculate IMASK-bits | ||
300 | shlr2 k0 | ||
301 | and #0x3c, k0 | ||
302 | cmp/eq #0x3c, k0 | ||
303 | bt/s 6f | ||
304 | shll2 k0 | ||
305 | mov g_imask, k0 | ||
306 | ! | ||
307 | 6: or k0, k2 ! Set the IMASK-bits | ||
308 | ldc k2, ssr | ||
309 | ! | ||
310 | #if defined(CONFIG_KGDB_NMI) | ||
311 | ! Clear in_nmi | ||
312 | mov.l 6f, k0 | ||
313 | mov #0, k1 | ||
314 | mov.b k1, @k0 | ||
315 | #endif | ||
316 | mov.l @r15+, k2 ! restore EXPEVT | ||
317 | mov k4, r15 | ||
318 | rte | ||
319 | nop | ||
320 | |||
321 | .align 2 | ||
322 | 5: .long 0x00001000 ! DSP | ||
323 | 7: .long 0x30000000 | ||
324 | |||
325 | ! common exception handler | ||
326 | #include "../../entry.S" | ||
327 | |||
328 | ! Exception Vector Base | ||
329 | ! | ||
330 | ! Should be aligned page boundary. | ||
331 | ! | ||
332 | .balign 4096,0,4096 | ||
333 | ENTRY(vbr_base) | ||
334 | .long 0 | ||
335 | ! | ||
336 | .balign 256,0,256 | ||
337 | general_exception: | ||
338 | mov.l 1f, k2 | ||
339 | mov.l 2f, k3 | ||
340 | bra handle_exception | ||
341 | mov.l @k2, k2 | ||
342 | .align 2 | ||
343 | 1: .long EXPEVT | ||
344 | 2: .long ret_from_exception | ||
345 | ! | ||
346 | ! | ||
347 | .balign 1024,0,1024 | ||
348 | tlb_miss: | ||
349 | mov.l 1f, k2 | ||
350 | mov.l 4f, k3 | ||
351 | bra handle_exception | ||
352 | mov.l @k2, k2 | ||
353 | ! | ||
354 | .balign 512,0,512 | ||
355 | interrupt: | ||
356 | mov.l 2f, k2 | ||
357 | mov.l 3f, k3 | ||
358 | #if defined(CONFIG_KGDB_NMI) | ||
359 | ! Debounce (filter nested NMI) | ||
360 | mov.l @k2, k0 | ||
361 | mov.l 5f, k1 | ||
362 | cmp/eq k1, k0 | ||
363 | bf 0f | ||
364 | mov.l 6f, k1 | ||
365 | tas.b @k1 | ||
366 | bt 0f | ||
367 | rte | ||
368 | nop | ||
369 | .align 2 | ||
370 | 5: .long NMI_VEC | ||
371 | 6: .long in_nmi | ||
372 | 0: | ||
373 | #endif /* defined(CONFIG_KGDB_NMI) */ | ||
374 | bra handle_exception | ||
375 | mov #-1, k2 ! interrupt exception marker | ||
376 | |||
377 | .align 2 | ||
378 | 1: .long EXPEVT | ||
379 | 2: .long INTEVT | ||
380 | 3: .long ret_from_irq | ||
381 | 4: .long ret_from_exception | ||
382 | |||
383 | ! | ||
384 | ! | ||
385 | .align 2 | ||
386 | ENTRY(handle_exception) | ||
387 | ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), | ||
388 | ! save all registers onto stack. | ||
389 | ! | ||
390 | stc ssr, k0 ! Is it from kernel space? | ||
391 | shll k0 ! Check MD bit (bit30) by shifting it into... | ||
392 | shll k0 ! ...the T bit | ||
393 | bt/s 1f ! It's a kernel to kernel transition. | ||
394 | mov r15, k0 ! save original stack to k0 | ||
395 | /* User space to kernel */ | ||
396 | mov #(THREAD_SIZE >> 8), k1 | ||
397 | shll8 k1 ! k1 := THREAD_SIZE | ||
398 | add current, k1 | ||
399 | mov k1, r15 ! change to kernel stack | ||
400 | ! | ||
401 | 1: mov.l 2f, k1 | ||
402 | ! | ||
403 | #ifdef CONFIG_SH_DSP | ||
404 | mov.l r2, @-r15 ! Save r2, we need another reg | ||
405 | stc sr, k4 | ||
406 | mov.l 1f, r2 | ||
407 | tst r2, k4 ! Check if in DSP mode | ||
408 | mov.l @r15+, r2 ! Restore r2 now | ||
409 | bt/s skip_save | ||
410 | mov #0, k4 ! Set marker for no stack frame | ||
411 | |||
412 | mov r2, k4 ! Backup r2 (in k4) for later | ||
413 | |||
414 | ! Save DSP registers on stack | ||
415 | stc.l mod, @-r15 | ||
416 | stc.l re, @-r15 | ||
417 | stc.l rs, @-r15 | ||
418 | sts.l dsr, @-r15 | ||
419 | sts.l y1, @-r15 | ||
420 | sts.l y0, @-r15 | ||
421 | sts.l x1, @-r15 | ||
422 | sts.l x0, @-r15 | ||
423 | sts.l a0, @-r15 | ||
424 | |||
425 | ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr. | ||
426 | |||
427 | ! FIXME: Make sure that this is still the case with newer toolchains, | ||
428 | ! as we're not at all interested in supporting ancient toolchains at | ||
429 | ! this point. -- PFM. | ||
430 | |||
431 | mov r15, r2 | ||
432 | .word 0xf653 ! movs.l a1, @-r2 | ||
433 | .word 0xf6f3 ! movs.l a0g, @-r2 | ||
434 | .word 0xf6d3 ! movs.l a1g, @-r2 | ||
435 | .word 0xf6c3 ! movs.l m0, @-r2 | ||
436 | .word 0xf6e3 ! movs.l m1, @-r2 | ||
437 | mov r2, r15 | ||
438 | |||
439 | mov k4, r2 ! Restore r2 | ||
440 | mov.l 1f, k4 ! Force DSP stack frame | ||
441 | skip_save: | ||
442 | mov.l k4, @-r15 ! Push DSP mode marker onto stack | ||
443 | #endif | ||
444 | ! Save the user registers on the stack. | ||
445 | mov.l k2, @-r15 ! EXPEVT | ||
446 | |||
447 | mov #-1, k4 | ||
448 | mov.l k4, @-r15 ! set TRA (default: -1) | ||
449 | ! | ||
450 | sts.l macl, @-r15 | ||
451 | sts.l mach, @-r15 | ||
452 | stc.l gbr, @-r15 | ||
453 | stc.l ssr, @-r15 | ||
454 | sts.l pr, @-r15 | ||
455 | stc.l spc, @-r15 | ||
456 | ! | ||
457 | lds k3, pr ! Set the return address to pr | ||
458 | ! | ||
459 | mov.l k0, @-r15 ! save orignal stack | ||
460 | mov.l r14, @-r15 | ||
461 | mov.l r13, @-r15 | ||
462 | mov.l r12, @-r15 | ||
463 | mov.l r11, @-r15 | ||
464 | mov.l r10, @-r15 | ||
465 | mov.l r9, @-r15 | ||
466 | mov.l r8, @-r15 | ||
467 | ! | ||
468 | stc sr, r8 ! Back to normal register bank, and | ||
469 | or k1, r8 ! Block all interrupts | ||
470 | mov.l 3f, k1 | ||
471 | and k1, r8 ! ... | ||
472 | ldc r8, sr ! ...changed here. | ||
473 | ! | ||
474 | mov.l r7, @-r15 | ||
475 | mov.l r6, @-r15 | ||
476 | mov.l r5, @-r15 | ||
477 | mov.l r4, @-r15 | ||
478 | mov.l r3, @-r15 | ||
479 | mov.l r2, @-r15 | ||
480 | mov.l r1, @-r15 | ||
481 | mov.l r0, @-r15 | ||
482 | |||
483 | /* | ||
484 | * This gets a bit tricky.. in the INTEVT case we don't want to use | ||
485 | * the VBR offset as a destination in the jump call table, since all | ||
486 | * of the destinations are the same. In this case, (interrupt) sets | ||
487 | * a marker in r2 (now r2_bank since SR.RB changed), which we check | ||
488 | * to determine the exception type. For all other exceptions, we | ||
489 | * forcibly read EXPEVT from memory and fix up the jump address, in | ||
490 | * the interrupt exception case we jump to do_IRQ() and defer the | ||
491 | * INTEVT read until there. As a bonus, we can also clean up the SR.RB | ||
492 | * checks that do_IRQ() was doing.. | ||
493 | */ | ||
494 | stc r2_bank, r8 | ||
495 | cmp/pz r8 | ||
496 | bf interrupt_exception | ||
497 | shlr2 r8 | ||
498 | shlr r8 | ||
499 | mov.l 4f, r9 | ||
500 | add r8, r9 | ||
501 | mov.l @r9, r9 | ||
502 | jmp @r9 | ||
503 | nop | ||
504 | rts | ||
505 | nop | ||
506 | |||
507 | .align 2 | ||
508 | 1: .long 0x00001000 ! DSP=1 | ||
509 | 2: .long 0x000080f0 ! FD=1, IMASK=15 | ||
510 | 3: .long 0xcfffffff ! RB=0, BL=0 | ||
511 | 4: .long exception_handling_table | ||
512 | |||
513 | interrupt_exception: | ||
514 | mov.l 1f, r9 | ||
515 | jmp @r9 | ||
516 | nop | ||
517 | rts | ||
518 | nop | ||
519 | |||
520 | .align 2 | ||
521 | 1: .long do_IRQ | ||
522 | |||
523 | .align 2 | ||
524 | ENTRY(exception_none) | ||
525 | rts | ||
526 | nop | ||