1 #ifndef _ASM_M32R_ASSEMBLER_H
2 #define _ASM_M32R_ASSEMBLER_H
3 
4 /*
5  * linux/asm-m32r/assembler.h
6  *
7  * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
8  *
9  * This file contains M32R architecture specific macro definitions.
10  */
11 
12 #include <linux/stringify.h>
13 
14 #undef __STR
15 
16 #ifdef __ASSEMBLY__
17 #define __STR(x) x
18 #else
19 #define __STR(x) __stringify(x)
20 #endif
21 
22 #ifdef CONFIG_SMP
23 #define M32R_LOCK	__STR(lock)
24 #define M32R_UNLOCK	__STR(unlock)
25 #else
26 #define M32R_LOCK	__STR(ld)
27 #define M32R_UNLOCK	__STR(st)
28 #endif
29 
30 #ifdef __ASSEMBLY__
31 #undef ENTRY
32 #define ENTRY(name) ENTRY_M name
33 	.macro  ENTRY_M name
34 	.global \name
35 	ALIGN
36 \name:
37 	.endm
38 #endif
39 
40 
41 /**
42  * LDIMM - load immediate value
43  * STI - enable interruption
44  * CLI - disable interruption
45  */
46 
47 #ifdef __ASSEMBLY__
48 
49 #define LDIMM(reg,x) LDIMM reg x
50 	.macro LDIMM reg x
51 	seth	\reg, #high(\x)
52 	or3	\reg, \reg, #low(\x)
53 	.endm
54 
55 #if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
56 #define ENABLE_INTERRUPTS(reg) ENABLE_INTERRUPTS reg
57 	.macro ENABLE_INTERRUPTS reg
58 	setpsw  #0x40	    ->	nop
59 	; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
60 	.endm
61 
62 #define DISABLE_INTERRUPTS(reg) DISABLE_INTERRUPTS reg
63 	.macro DISABLE_INTERRUPTS reg
64 	clrpsw  #0x40	    ->	nop
65 	; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
66 	.endm
67 #else	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
68 #define ENABLE_INTERRUPTS(reg) ENABLE_INTERRUPTS reg
69 	.macro ENABLE_INTERRUPTS reg
70 	mvfc	\reg, psw
71 	or3	\reg, \reg, #0x0040
72 	mvtc	\reg, psw
73 	.endm
74 
75 #define DISABLE_INTERRUPTS(reg) DISABLE_INTERRUPTS reg
76 	.macro DISABLE_INTERRUPTS reg
77 	mvfc	\reg, psw
78 	and3	\reg, \reg, #0xffbf
79 	mvtc	\reg, psw
80 	.endm
81 #endif	/* CONFIG_CHIP_M32102 */
82 
83 	.macro	SAVE_ALL
84 	push	r0		; orig_r0
85 	push	sp		; spi (r15)
86 	push	lr		; r14
87 	push	r13
88 	mvfc	r13, cr3	; spu
89 	push	r13
90 	mvfc	r13, bbpc
91 	push	r13
92 	mvfc	r13, bbpsw
93 	push	r13
94 	mvfc	r13, bpc
95 	push	r13
96 	mvfc	r13, psw
97 	push	r13
98 #if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
99 	mvfaclo	r13, a1
100 	push	r13
101 	mvfachi r13, a1
102 	push	r13
103 	mvfaclo	r13, a0
104 	push	r13
105 	mvfachi	r13, a0
106 	push	r13
107 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
108 	mvfaclo	r13
109 	push	r13
110 	mvfachi	r13
111 	push	r13
112 	ldi	r13, #0
113 	push	r13		; dummy push acc1h
114 	push	r13		; dummy push acc1l
115 #else
116 #error unknown isa configuration
117 #endif
118 	ldi	r13, #-1
119 	push	r13		; syscall_nr (default: -1)
120 	push	r12
121 	push	r11
122 	push	r10
123 	push	r9
124 	push	r8
125 	push	r7
126 	push	r3
127 	push	r2
128 	push	r1
129 	push	r0
130 	addi	sp, #-4		; room for implicit pt_regs parameter
131 	push	r6
132 	push	r5
133 	push	r4
134 	.endm
135 
136 	.macro	RESTORE_ALL
137 	pop	r4
138 	pop	r5
139 	pop	r6
140 	addi	sp, #4
141 	pop	r0
142 	pop	r1
143 	pop	r2
144 	pop	r3
145 	pop	r7
146 	pop	r8
147 	pop	r9
148 	pop	r10
149 	pop	r11
150 	pop	r12
151 	addi	r15, #4		; Skip syscall number
152 #if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
153 	pop	r13
154 	mvtachi	r13, a0
155 	pop	r13
156 	mvtaclo	r13, a0
157 	pop	r13
158 	mvtachi	r13, a1
159 	pop	r13
160 	mvtaclo	r13, a1
161 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
162 	pop	r13		; dummy pop acc1h
163 	pop	r13		; dummy pop acc1l
164 	pop	r13
165 	mvtachi	r13
166 	pop	r13
167 	mvtaclo	r13
168 #else
169 #error unknown isa configuration
170 #endif
171 	pop	r14
172 	mvtc	r14, psw
173 	pop	r14
174 	mvtc	r14, bpc
175 	addi	sp, #8		; Skip bbpsw, bbpc
176 	pop	r14
177 	mvtc	r14, cr3	; spu
178 	pop	r13
179 	pop	lr		; r14
180 	pop	sp		; spi (r15)
181 	addi	sp, #4		; Skip orig_r0
182 	.fillinsn
183 1:	rte
184 	.section .fixup,"ax"
185 2:	bl	do_exit
186 	.previous
187 	.section __ex_table,"a"
188 	ALIGN
189 	.long	1b, 2b
190 	.previous
191 	.endm
192 
193 #define GET_CURRENT(reg)  get_current reg
194 	.macro get_current reg
195 	ldi  \reg, #-8192
196 	and  \reg, sp
197 	.endm
198 
199 #if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
200 	.macro	SWITCH_TO_KERNEL_STACK
201 	; switch to kernel stack (spi)
202 	clrpsw	#0x80	    ->	nop
203 	.endm
204 #else	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
205 	.macro	SWITCH_TO_KERNEL_STACK
206 	push	r0		; save r0 for working
207 	mvfc	r0, psw
208 	and3	r0, r0, #0x00ff7f
209 	mvtc	r0, psw
210 	slli	r0, #16
211 	bltz	r0, 1f		; check BSM-bit
212 ;
213 	;; called from kernel context: previous stack = spi
214 	pop	r0		; retrieve r0
215 	bra	2f
216 	.fillinsn
217 1:
218 	;; called from user context: previous stack = spu
219 	mvfc	r0, cr3		; spu
220 	addi	r0, #4
221 	mvtc	r0, cr3		; spu
222 	ld	r0, @(-4,r0)	; retrieve r0
223 	.fillinsn
224 2:
225 	.endm
226 #endif	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
227 
228 #endif	/* __ASSEMBLY__ */
229 
230 #endif	/* _ASM_M32R_ASSEMBLER_H */
231