summaryrefslogtreecommitdiff
path: root/arch/nios2/include/asm/asm-macros.h
blob: 522e50a176b2ff2c4b41d79b4715b08404b017f0 (plain)
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Macro used to simplify coding multi-line assembler.
 * Some of the bit test macro can simplify down to one line
 * depending on the mask value.
 *
 * Copyright (C) 2004 Microtronix Datacom Ltd.
 *
 * All rights reserved.
 */
#ifndef _ASM_NIOS2_ASMMACROS_H
#define _ASM_NIOS2_ASMMACROS_H
/*
 * ANDs reg2 with mask and places the result in reg1.
 *
 * You cannnot use the same register for reg1 & reg2.
 */

.macro ANDI32	reg1, reg2, mask
.if \mask & 0xffff
	.if \mask & 0xffff0000
		movhi	\reg1, %hi(\mask)
		movui	\reg1, %lo(\mask)
		and	\reg1, \reg1, \reg2
	.else
		andi	\reg1, \reg2, %lo(\mask)
	.endif
.else
	andhi	\reg1, \reg2, %hi(\mask)
.endif
.endm

/*
 * ORs reg2 with mask and places the result in reg1.
 *
 * It is safe to use the same register for reg1 & reg2.
 */

.macro ORI32	reg1, reg2, mask
.if \mask & 0xffff
	.if \mask & 0xffff0000
		orhi	\reg1, \reg2, %hi(\mask)
		ori	\reg1, \reg2, %lo(\mask)
	.else
		ori	\reg1, \reg2, %lo(\mask)
	.endif
.else
	orhi	\reg1, \reg2, %hi(\mask)
.endif
.endm

/*
 * XORs reg2 with mask and places the result in reg1.
 *
 * It is safe to use the same register for reg1 & reg2.
 */

.macro XORI32	reg1, reg2, mask
.if \mask & 0xffff
	.if \mask & 0xffff0000
		xorhi	\reg1, \reg2, %hi(\mask)
		xori	\reg1, \reg1, %lo(\mask)
	.else
		xori	\reg1, \reg2, %lo(\mask)
	.endif
.else
	xorhi	\reg1, \reg2, %hi(\mask)
.endif
.endm

/*
 * This is a support macro for BTBZ & BTBNZ.  It checks
 * the bit to make sure it is valid 32 value.
 *
 * It is safe to use the same register for reg1 & reg2.
 */

.macro BT	reg1, reg2, bit
.if \bit > 31
	.err
.else
	.if \bit < 16
		andi	\reg1, \reg2, (1 << \bit)
	.else
		andhi	\reg1, \reg2, (1 << (\bit - 16))
	.endif
.endif
.endm

/*
 * Tests the bit in reg2 and branches to label if the
 * bit is zero.  The result of the bit test is stored in reg1.
 *
 * It is safe to use the same register for reg1 & reg2.
 */

.macro BTBZ	reg1, reg2, bit, label
	BT	\reg1, \reg2, \bit
	beq	\reg1, r0, \label
.endm

/*
 * Tests the bit in reg2 and branches to label if the
 * bit is non-zero.  The result of the bit test is stored in reg1.
 *
 * It is safe to use the same register for reg1 & reg2.
 */

.macro BTBNZ	reg1, reg2, bit, label
	BT	\reg1, \reg2, \bit
	bne	\reg1, r0, \label
.endm

/*
 * Tests the bit in reg2 and then compliments the bit in reg2.
 * The result of the bit test is stored in reg1.
 *
 * It is NOT safe to use the same register for reg1 & reg2.
 */

.macro BTC	reg1, reg2, bit
.if \bit > 31
	.err
.else
	.if \bit < 16
		andi	\reg1, \reg2, (1 << \bit)
		xori	\reg2, \reg2, (1 << \bit)
	.else
		andhi	\reg1, \reg2, (1 << (\bit - 16))
		xorhi	\reg2, \reg2, (1 << (\bit - 16))
	.endif
.endif
.endm

/*
 * Tests the bit in reg2 and then sets the bit in reg2.
 * The result of the bit test is stored in reg1.
 *
 * It is NOT safe to use the same register for reg1 & reg2.
 */

.macro BTS	reg1, reg2, bit
.if \bit > 31
	.err
.else
	.if \bit < 16
		andi	\reg1, \reg2, (1 << \bit)
		ori	\reg2, \reg2, (1 << \bit)
	.else
		andhi	\reg1, \reg2, (1 << (\bit - 16))
		orhi	\reg2, \reg2, (1 << (\bit - 16))
	.endif
.endif
.endm

/*
 * Tests the bit in reg2 and then resets the bit in reg2.
 * The result of the bit test is stored in reg1.
 *
 * It is NOT safe to use the same register for reg1 & reg2.
 */

.macro BTR	reg1, reg2, bit
.if \bit > 31
	.err
.else
	.if \bit < 16
		andi	\reg1, \reg2, (1 << \bit)
		andi	\reg2, \reg2, %lo(~(1 << \bit))
	.else
		andhi	\reg1, \reg2, (1 << (\bit - 16))
		andhi	\reg2, \reg2, %lo(~(1 << (\bit - 16)))
	.endif
.endif
.endm

/*
 * Tests the bit in reg2 and then compliments the bit in reg2.
 * The result of the bit test is stored in reg1.  If the
 * original bit was zero it branches to label.
 *
 * It is NOT safe to use the same register for reg1 & reg2.
 */

.macro BTCBZ	reg1, reg2, bit, label
	BTC	\reg1, \reg2, \bit
	beq	\reg1, r0, \label
.endm

/*
 * Tests the bit in reg2 and then compliments the bit in reg2.
 * The result of the bit test is stored in reg1.  If the
 * original bit was non-zero it branches to label.
 *
 * It is NOT safe to use the same register for reg1 & reg2.
 */

.macro BTCBNZ	reg1, reg2, bit, label
	BTC	\reg1, \reg2, \bit
	bne	\reg1, r0, \label
.endm

/*
 * Tests the bit in reg2 and then sets the bit in reg2.
 * The result of the bit test is stored in reg1.  If the
 * original bit was zero it branches to label.
 *
 * It is NOT safe to use the same register for reg1 & reg2.
 */

.macro BTSBZ	reg1, reg2, bit, label
	BTS	\reg1, \reg2, \bit
	beq	\reg1, r0, \label
.endm

/*
 * Tests the bit in reg2 and then sets the bit in reg2.
 * The result of the bit test is stored in reg1.  If the
 * original bit was non-zero it branches to label.
 *
 * It is NOT safe to use the same register for reg1 & reg2.
 */

.macro BTSBNZ	reg1, reg2, bit, label
	BTS	\reg1, \reg2, \bit
	bne	\reg1, r0, \label
.endm

/*
 * Tests the bit in reg2 and then resets the bit in reg2.
 * The result of the bit test is stored in reg1.  If the
 * original bit was zero it branches to label.
 *
 * It is NOT safe to use the same register for reg1 & reg2.
 */

.macro BTRBZ	reg1, reg2, bit, label
	BTR	\reg1, \reg2, \bit
	bne	\reg1, r0, \label
.endm

/*
 * Tests the bit in reg2 and then resets the bit in reg2.
 * The result of the bit test is stored in reg1.  If the
 * original bit was non-zero it branches to label.
 *
 * It is NOT safe to use the same register for reg1 & reg2.
 */

.macro BTRBNZ	reg1, reg2, bit, label
	BTR	\reg1, \reg2, \bit
	bne	\reg1, r0, \label
.endm

/*
 * Tests the bits in mask against reg2 stores the result in reg1.
 * If the all the bits in the mask are zero it branches to label.
 *
 * It is safe to use the same register for reg1 & reg2.
 */

.macro TSTBZ	reg1, reg2, mask, label
	ANDI32	\reg1, \reg2, \mask
	beq	\reg1, r0, \label
.endm

/*
 * Tests the bits in mask against reg2 stores the result in reg1.
 * If the any of the bits in the mask are 1 it branches to label.
 *
 * It is safe to use the same register for reg1 & reg2.
 */

.macro TSTBNZ	reg1, reg2, mask, label
	ANDI32	\reg1, \reg2, \mask
	bne	\reg1, r0, \label
.endm

/*
 * Pushes reg onto the stack.
 */

.macro PUSH	reg
	addi	sp, sp, -4
	stw	\reg, 0(sp)
.endm

/*
 * Pops the top of the stack into reg.
 */

.macro POP	reg
	ldw	\reg, 0(sp)
	addi	sp, sp, 4
.endm


#endif /* _ASM_NIOS2_ASMMACROS_H */