1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <linux/linkage.h>
20 #include <asm/current.h>
21 #include <asm/asm-offsets.h>
22 #include <asm/asmmacro.h>
23 #include <asm/processor.h>
24
25 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
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 #define UNALIGNED_USER_EXCEPTION
62
63 #if XCHAL_HAVE_BE
64
65 #define HWORD_START 16
66 #define INSN_OP0 28
67 #define INSN_T 24
68 #define INSN_OP1 16
69
70 .macro __ssa8r r; ssa8l \r; .endm
71 .macro __sh r, s; srl \r, \s; .endm
72 .macro __sl r, s; sll \r, \s; .endm
73 .macro __exth r, s; extui \r, \s, 0, 16; .endm
74 .macro __extl r, s; slli \r, \s, 16; .endm
75
76 #else
77
78 #define HWORD_START 0
79 #define INSN_OP0 0
80 #define INSN_T 4
81 #define INSN_OP1 12
82
83 .macro __ssa8r r; ssa8b \r; .endm
84 .macro __sh r, s; sll \r, \s; .endm
85 .macro __sl r, s; srl \r, \s; .endm
86 .macro __exth r, s; slli \r, \s, 16; .endm
87 .macro __extl r, s; extui \r, \s, 0, 16; .endm
88
89 #endif
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 #define OP0_L32I_N 0x8
128 #define OP0_S32I_N 0x9
129 #define OP1_SI_MASK 0x4
130 #define OP1_SI_BIT 2
131
132 #define OP1_L32I 0x2
133 #define OP1_L16UI 0x1
134 #define OP1_L16SI 0x9
135 #define OP1_L32AI 0xb
136
137 #define OP1_S32I 0x6
138 #define OP1_S16I 0x5
139 #define OP1_S32RI 0xf
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 .literal_position
156 ENTRY(fast_unaligned)
157
158
159
160
161
162
163
164
165 s32i a4, a2, PT_AREG4
166 s32i a5, a2, PT_AREG5
167 s32i a6, a2, PT_AREG6
168 s32i a7, a2, PT_AREG7
169 s32i a8, a2, PT_AREG8
170
171 rsr a0, depc
172 s32i a0, a2, PT_AREG2
173 s32i a3, a2, PT_AREG3
174
175 rsr a3, excsave1
176 movi a4, fast_unaligned_fixup
177 s32i a4, a3, EXC_TABLE_FIXUP
178
179
180
181 rsr a0, sar
182 rsr a8, excvaddr # load unaligned memory address
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201 rsr a7, epc1 # load exception address
202 movi a3, ~3
203 and a3, a3, a7 # mask lower bits
204
205 l32i a4, a3, 0 # load 2 words
206 l32i a5, a3, 4
207
208 __ssa8 a7
209 __src_b a4, a4, a5 # a4 has the instruction
210
211
212
213 extui a5, a4, INSN_OP0, 4 # get insn.op0 nibble
214
215 #if XCHAL_HAVE_DENSITY
216 _beqi a5, OP0_L32I_N, .Lload # L32I.N, jump
217 addi a6, a5, -OP0_S32I_N
218 _beqz a6, .Lstore # S32I.N, do a store
219 #endif
220
221 _bbci.l a4, OP1_SI_BIT + INSN_OP1, .Lload
222
223
224
225 .Lstore:movi a5, .Lstore_table # table
226 extui a6, a4, INSN_T, 4 # get source register
227 addx8 a5, a6, a5
228 jx a5 # jump into table
229
230
231
232 .Lload: movi a3, ~3
233 and a3, a3, a8 # align memory address
234
235 __ssa8 a8
236 #ifdef UNALIGNED_USER_EXCEPTION
237 addi a3, a3, 8
238 l32e a5, a3, -8
239 l32e a6, a3, -4
240 #else
241 l32i a5, a3, 0
242 l32i a6, a3, 4
243 #endif
244 __src_b a3, a5, a6 # a3 has the data word
245
246 #if XCHAL_HAVE_DENSITY
247 addi a7, a7, 2 # increment PC (assume 16-bit insn)
248
249 extui a5, a4, INSN_OP0, 4
250 _beqi a5, OP0_L32I_N, 1f # l32i.n: jump
251
252 addi a7, a7, 1
253 #else
254 addi a7, a7, 3
255 #endif
256
257 extui a5, a4, INSN_OP1, 4
258 _beqi a5, OP1_L32I, 1f # l32i: jump
259
260 extui a3, a3, 0, 16 # extract lower 16 bits
261 _beqi a5, OP1_L16UI, 1f
262 addi a5, a5, -OP1_L16SI
263 _bnez a5, .Linvalid_instruction_load
264
265
266
267 slli a3, a3, 16
268 srai a3, a3, 16
269
270
271
272 1:
273 extui a4, a4, INSN_T, 4 # extract target register
274 movi a5, .Lload_table
275 addx8 a4, a4, a5
276 jx a4 # jump to entry for target register
277
278 .align 8
279 .Lload_table:
280 s32i a3, a2, PT_AREG0; _j .Lexit; .align 8
281 mov a1, a3; _j .Lexit; .align 8 # fishy??
282 s32i a3, a2, PT_AREG2; _j .Lexit; .align 8
283 s32i a3, a2, PT_AREG3; _j .Lexit; .align 8
284 s32i a3, a2, PT_AREG4; _j .Lexit; .align 8
285 s32i a3, a2, PT_AREG5; _j .Lexit; .align 8
286 s32i a3, a2, PT_AREG6; _j .Lexit; .align 8
287 s32i a3, a2, PT_AREG7; _j .Lexit; .align 8
288 s32i a3, a2, PT_AREG8; _j .Lexit; .align 8
289 mov a9, a3 ; _j .Lexit; .align 8
290 mov a10, a3 ; _j .Lexit; .align 8
291 mov a11, a3 ; _j .Lexit; .align 8
292 mov a12, a3 ; _j .Lexit; .align 8
293 mov a13, a3 ; _j .Lexit; .align 8
294 mov a14, a3 ; _j .Lexit; .align 8
295 mov a15, a3 ; _j .Lexit; .align 8
296
297 .Lstore_table:
298 l32i a3, a2, PT_AREG0; _j 1f; .align 8
299 mov a3, a1; _j 1f; .align 8 # fishy??
300 l32i a3, a2, PT_AREG2; _j 1f; .align 8
301 l32i a3, a2, PT_AREG3; _j 1f; .align 8
302 l32i a3, a2, PT_AREG4; _j 1f; .align 8
303 l32i a3, a2, PT_AREG5; _j 1f; .align 8
304 l32i a3, a2, PT_AREG6; _j 1f; .align 8
305 l32i a3, a2, PT_AREG7; _j 1f; .align 8
306 l32i a3, a2, PT_AREG8; _j 1f; .align 8
307 mov a3, a9 ; _j 1f; .align 8
308 mov a3, a10 ; _j 1f; .align 8
309 mov a3, a11 ; _j 1f; .align 8
310 mov a3, a12 ; _j 1f; .align 8
311 mov a3, a13 ; _j 1f; .align 8
312 mov a3, a14 ; _j 1f; .align 8
313 mov a3, a15 ; _j 1f; .align 8
314
315
316
317 .extern _kernel_exception
318 .Linvalid_instruction_load:
319 .Linvalid_instruction_store:
320
321 movi a4, 0
322 rsr a3, excsave1
323 s32i a4, a3, EXC_TABLE_FIXUP
324
325
326
327 l32i a8, a2, PT_AREG8
328 l32i a7, a2, PT_AREG7
329 l32i a6, a2, PT_AREG6
330 l32i a5, a2, PT_AREG5
331 l32i a4, a2, PT_AREG4
332 wsr a0, sar
333 mov a1, a2
334
335 rsr a0, ps
336 bbsi.l a0, PS_UM_BIT, 2f # jump if user mode
337
338 movi a0, _kernel_exception
339 jx a0
340
341 2: movi a0, _user_exception
342 jx a0
343
344 1: # a7: instruction pointer, a4: instruction, a3: value
345
346 movi a6, 0 # mask: ffffffff:00000000
347
348 #if XCHAL_HAVE_DENSITY
349 addi a7, a7, 2 # incr. PC,assume 16-bit instruction
350
351 extui a5, a4, INSN_OP0, 4 # extract OP0
352 addi a5, a5, -OP0_S32I_N
353 _beqz a5, 1f # s32i.n: jump
354
355 addi a7, a7, 1 # increment PC, 32-bit instruction
356 #else
357 addi a7, a7, 3 # increment PC, 32-bit instruction
358 #endif
359
360 extui a5, a4, INSN_OP1, 4 # extract OP1
361 _beqi a5, OP1_S32I, 1f # jump if 32 bit store
362 _bnei a5, OP1_S16I, .Linvalid_instruction_store
363
364 movi a5, -1
365 __extl a3, a3 # get 16-bit value
366 __exth a6, a5 # get 16-bit mask ffffffff:ffff0000
367
368
369
370 1:
371 movi a4, ~3
372 and a4, a4, a8 # align memory address
373
374
375
376 movi a5, -1 # mask: ffffffff:XXXX0000
377 #ifdef UNALIGNED_USER_EXCEPTION
378 addi a4, a4, 8
379 #endif
380
381 __ssa8r a8
382 __src_b a8, a5, a6 # lo-mask F..F0..0 (BE) 0..0F..F (LE)
383 __src_b a6, a6, a5 # hi-mask 0..0F..F (BE) F..F0..0 (LE)
384 #ifdef UNALIGNED_USER_EXCEPTION
385 l32e a5, a4, -8
386 #else
387 l32i a5, a4, 0 # load lower address word
388 #endif
389 and a5, a5, a8 # mask
390 __sh a8, a3 # shift value
391 or a5, a5, a8 # or with original value
392 #ifdef UNALIGNED_USER_EXCEPTION
393 s32e a5, a4, -8
394 l32e a8, a4, -4
395 #else
396 s32i a5, a4, 0 # store
397 l32i a8, a4, 4 # same for upper address word
398 #endif
399 __sl a5, a3
400 and a6, a8, a6
401 or a6, a6, a5
402 #ifdef UNALIGNED_USER_EXCEPTION
403 s32e a6, a4, -4
404 #else
405 s32i a6, a4, 4
406 #endif
407
408 .Lexit:
409 #if XCHAL_HAVE_LOOPS
410 rsr a4, lend # check if we reached LEND
411 bne a7, a4, 1f
412 rsr a4, lcount # and LCOUNT != 0
413 beqz a4, 1f
414 addi a4, a4, -1 # decrement LCOUNT and set
415 rsr a7, lbeg # set PC to LBEGIN
416 wsr a4, lcount
417 #endif
418
419 1: wsr a7, epc1 # skip emulated instruction
420
421
422 rsr a4, icountlevel
423 beqz a4, 1f
424 bgeui a4, LOCKLEVEL + 1, 1f
425 rsr a4, icount
426 addi a4, a4, 1
427 wsr a4, icount
428 1:
429 movi a4, 0
430 rsr a3, excsave1
431 s32i a4, a3, EXC_TABLE_FIXUP
432
433
434
435 l32i a8, a2, PT_AREG8
436 l32i a7, a2, PT_AREG7
437 l32i a6, a2, PT_AREG6
438 l32i a5, a2, PT_AREG5
439 l32i a4, a2, PT_AREG4
440 l32i a3, a2, PT_AREG3
441
442
443
444 wsr a0, sar
445 l32i a0, a2, PT_AREG0
446 l32i a2, a2, PT_AREG2
447 rfe
448
449 ENDPROC(fast_unaligned)
450
451 ENTRY(fast_unaligned_fixup)
452
453 l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
454 wsr a3, excsave1
455
456 l32i a8, a2, PT_AREG8
457 l32i a7, a2, PT_AREG7
458 l32i a6, a2, PT_AREG6
459 l32i a5, a2, PT_AREG5
460 l32i a4, a2, PT_AREG4
461 l32i a0, a2, PT_AREG2
462 xsr a0, depc # restore depc and a0
463 wsr a0, sar
464
465 rsr a0, exccause
466 s32i a0, a2, PT_DEPC # mark as a regular exception
467
468 rsr a0, ps
469 bbsi.l a0, PS_UM_BIT, 1f # jump if user mode
470
471 rsr a0, exccause
472 addx4 a0, a0, a3 # find entry in table
473 l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler
474 l32i a3, a2, PT_AREG3
475 jx a0
476 1:
477 rsr a0, exccause
478 addx4 a0, a0, a3 # find entry in table
479 l32i a0, a0, EXC_TABLE_FAST_USER # load handler
480 l32i a3, a2, PT_AREG3
481 jx a0
482
483 ENDPROC(fast_unaligned_fixup)
484
485 #endif