summaryrefslogtreecommitdiff
path: root/arch/m32r/include/asm/assembler.h
blob: ed90d894f285913c7979d3095c34e40320f82018 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_M32R_ASSEMBLER_H
#define _ASM_M32R_ASSEMBLER_H

/*
 * linux/asm-m32r/assembler.h
 *
 * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
 *
 * This file contains M32R architecture specific macro definitions.
 */

#include <linux/stringify.h>

#undef __STR

#ifdef __ASSEMBLY__
#define __STR(x) x
#else
#define __STR(x) __stringify(x)
#endif

#ifdef CONFIG_SMP
#define M32R_LOCK	__STR(lock)
#define M32R_UNLOCK	__STR(unlock)
#else
#define M32R_LOCK	__STR(ld)
#define M32R_UNLOCK	__STR(st)
#endif

#ifdef __ASSEMBLY__
#undef ENTRY
#define ENTRY(name) ENTRY_M name
	.macro  ENTRY_M name
	.global \name
	ALIGN
\name:
	.endm
#endif


/**
 * LDIMM - load immediate value
 * STI - enable interruption
 * CLI - disable interruption
 */

#ifdef __ASSEMBLY__

#define LDIMM(reg,x) LDIMM reg x
	.macro LDIMM reg x
	seth	\reg, #high(\x)
	or3	\reg, \reg, #low(\x)
	.endm

#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
#define ENABLE_INTERRUPTS(reg) ENABLE_INTERRUPTS reg
	.macro ENABLE_INTERRUPTS reg
	setpsw  #0x40	    ->	nop
	; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
	.endm

#define DISABLE_INTERRUPTS(reg) DISABLE_INTERRUPTS reg
	.macro DISABLE_INTERRUPTS reg
	clrpsw  #0x40	    ->	nop
	; WORKAROUND: "-> nop" is a workaround for the M32700(TS1).
	.endm
#else	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
#define ENABLE_INTERRUPTS(reg) ENABLE_INTERRUPTS reg
	.macro ENABLE_INTERRUPTS reg
	mvfc	\reg, psw
	or3	\reg, \reg, #0x0040
	mvtc	\reg, psw
	.endm

#define DISABLE_INTERRUPTS(reg) DISABLE_INTERRUPTS reg
	.macro DISABLE_INTERRUPTS reg
	mvfc	\reg, psw
	and3	\reg, \reg, #0xffbf
	mvtc	\reg, psw
	.endm
#endif	/* CONFIG_CHIP_M32102 */

	.macro	SAVE_ALL
	push	r0		; orig_r0
	push	sp		; spi (r15)
	push	lr		; r14
	push	r13
	mvfc	r13, cr3	; spu
	push	r13
	mvfc	r13, bbpc
	push	r13
	mvfc	r13, bbpsw
	push	r13
	mvfc	r13, bpc
	push	r13
	mvfc	r13, psw
	push	r13
#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
	mvfaclo	r13, a1
	push	r13
	mvfachi r13, a1
	push	r13
	mvfaclo	r13, a0
	push	r13
	mvfachi	r13, a0
	push	r13
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
	mvfaclo	r13
	push	r13
	mvfachi	r13
	push	r13
	ldi	r13, #0
	push	r13		; dummy push acc1h
	push	r13		; dummy push acc1l
#else
#error unknown isa configuration
#endif
	ldi	r13, #-1
	push	r13		; syscall_nr (default: -1)
	push	r12
	push	r11
	push	r10
	push	r9
	push	r8
	push	r7
	push	r3
	push	r2
	push	r1
	push	r0
	addi	sp, #-4		; room for implicit pt_regs parameter
	push	r6
	push	r5
	push	r4
	.endm

	.macro	RESTORE_ALL
	pop	r4
	pop	r5
	pop	r6
	addi	sp, #4
	pop	r0
	pop	r1
	pop	r2
	pop	r3
	pop	r7
	pop	r8
	pop	r9
	pop	r10
	pop	r11
	pop	r12
	addi	r15, #4		; Skip syscall number
#if defined(CONFIG_ISA_M32R2) && defined(CONFIG_ISA_DSP_LEVEL2)
	pop	r13
	mvtachi	r13, a0
	pop	r13
	mvtaclo	r13, a0
	pop	r13
	mvtachi	r13, a1
	pop	r13
	mvtaclo	r13, a1
#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
	pop	r13		; dummy pop acc1h
	pop	r13		; dummy pop acc1l
	pop	r13
	mvtachi	r13
	pop	r13
	mvtaclo	r13
#else
#error unknown isa configuration
#endif
	pop	r14
	mvtc	r14, psw
	pop	r14
	mvtc	r14, bpc
	addi	sp, #8		; Skip bbpsw, bbpc
	pop	r14
	mvtc	r14, cr3	; spu
	pop	r13
	pop	lr		; r14
	pop	sp		; spi (r15)
	addi	sp, #4		; Skip orig_r0
	.fillinsn
1:	rte
	.section .fixup,"ax"
2:	bl	do_exit
	.previous
	.section __ex_table,"a"
	ALIGN
	.long	1b, 2b
	.previous
	.endm

#define GET_CURRENT(reg)  get_current reg
	.macro get_current reg
	ldi  \reg, #-8192
	and  \reg, sp
	.endm

#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104))
	.macro	SWITCH_TO_KERNEL_STACK
	; switch to kernel stack (spi)
	clrpsw	#0x80	    ->	nop
	.endm
#else	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */
	.macro	SWITCH_TO_KERNEL_STACK
	push	r0		; save r0 for working
	mvfc	r0, psw
	and3	r0, r0, #0x00ff7f
	mvtc	r0, psw
	slli	r0, #16
	bltz	r0, 1f		; check BSM-bit
;
	;; called from kernel context: previous stack = spi
	pop	r0		; retrieve r0
	bra	2f
	.fillinsn
1:
	;; called from user context: previous stack = spu
	mvfc	r0, cr3		; spu
	addi	r0, #4
	mvtc	r0, cr3		; spu
	ld	r0, @(-4,r0)	; retrieve r0
	.fillinsn
2:
	.endm
#endif	/* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */

#endif	/* __ASSEMBLY__ */

#endif	/* _ASM_M32R_ASSEMBLER_H */