blob: 9e3455a09f8fa36c1cfd27ba42ef83dec8e71fe9 [file] [log] [blame]
Arve Hjønnevåg73a0ce92010-09-27 17:50:00 -07001/*
2 * Copyright (C) 2008 Google, Inc.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/linkage.h>
16#include <asm/assembler.h>
17
18 .text
19
20 .global fiq_glue_end
21
22 /* fiq stack: r0-r15,cpsr,spsr of interrupted mode */
23
24ENTRY(fiq_glue)
25 /* store pc, cpsr from previous mode */
26 mrs r12, spsr
27 sub r11, lr, #4
28 subs r10, #1
29 bne nested_fiq
30
31 stmfd sp!, {r11-r12, lr}
32
33 /* store r8-r14 from previous mode */
34 sub sp, sp, #(7 * 4)
35 stmia sp, {r8-r14}^
36 nop
37
38 /* store r0-r7 from previous mode */
39 stmfd sp!, {r0-r7}
40
41 /* setup func(data,regs) arguments */
42 mov r0, r9
43 mov r1, sp
44 mov r3, r8
45
46 mov r7, sp
47
48 /* Get sp and lr from non-user modes */
49 and r4, r12, #MODE_MASK
50 cmp r4, #USR_MODE
51 beq fiq_from_usr_mode
52
53 mov r7, sp
54 orr r4, r4, #(PSR_I_BIT | PSR_F_BIT)
55 msr cpsr_c, r4
56 str sp, [r7, #(4 * 13)]
57 str lr, [r7, #(4 * 14)]
58 mrs r5, spsr
59 str r5, [r7, #(4 * 17)]
60
61 cmp r4, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT)
62 /* use fiq stack if we reenter this mode */
63 subne sp, r7, #(4 * 3)
64
65fiq_from_usr_mode:
66 msr cpsr_c, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT)
67 mov r2, sp
68 sub sp, r7, #12
69 stmfd sp!, {r2, ip, lr}
70 /* call func(data,regs) */
71 blx r3
72 ldmfd sp, {r2, ip, lr}
73 mov sp, r2
74
75 /* restore/discard saved state */
76 cmp r4, #USR_MODE
77 beq fiq_from_usr_mode_exit
78
79 msr cpsr_c, r4
80 ldr sp, [r7, #(4 * 13)]
81 ldr lr, [r7, #(4 * 14)]
82 msr spsr_cxsf, r5
83
84fiq_from_usr_mode_exit:
85 msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
86
87 ldmfd sp!, {r0-r7}
88 add sp, sp, #(7 * 4)
89 ldmfd sp!, {r11-r12, lr}
90exit_fiq:
91 msr spsr_cxsf, r12
92 add r10, #1
93 movs pc, r11
94
95nested_fiq:
96 orr r12, r12, #(PSR_F_BIT)
97 b exit_fiq
98
99fiq_glue_end:
100
101ENTRY(fiq_glue_setup) /* func, data, sp */
102 mrs r3, cpsr
103 msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
104 movs r8, r0
105 mov r9, r1
106 mov sp, r2
107 moveq r10, #0
108 movne r10, #1
109 msr cpsr_c, r3
110 bx lr
111