OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [armnommu/] [kernel/] [entry-armo.S] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 * linux/arch/arm/lib/traps.S
3
 *
4
 * Copyright (C) 1995, 1996 Russell King.
5
 *
6
 * Low-level vector interface routines
7
 *
8
 * Design issues:
9
 *  - We have several modes that each vector can be called from,
10
 *    each with its own set of registers.  On entry to any vector,
11
 *    we *must* save the registers used in *that* mode.
12
 *
13
 *  - This code must be as fast as possible.
14
 *
15
 * There are a few restrictions on the vectors:
16
 *  - the SWI vector cannot be called from *any* non-user mode
17
 *
18
 *  - the FP emulator is *never* called from *any* non-user mode undefined
19
 *    instruction.
20
 *
21
 * Ok, so this file may be a mess, but its as efficient as possible while
22
 * adhering to the above criteria.
23
 */
24
 
25
#include 
26
#include 
27
#include 
28
 
29
#if 0
30
/*
31
 * Uncomment these if you wish to get more debugging into about data aborts.
32
 */
33
#define FAULT_CODE_LDRSTRPOST   0x80
34
#define FAULT_CODE_LDRSTRPRE    0x40
35
#define FAULT_CODE_LDRSTRREG    0x20
36
#define FAULT_CODE_LDMSTM       0x10
37
#define FAULT_CODE_LDCSTC       0x08
38
#endif
39
#define FAULT_CODE_PREFETCH     0x04
40
#define FAULT_CODE_WRITE        0x02
41
#define FAULT_CODE_USER         0x01
42
 
43
                .text
44
 
45
/* Offsets into task structure
46
 * ---------------------------
47
 */
48
#define STATE           0
49
#define COUNTER         4
50
#define PRIORITY        8
51
#define SIGNAL          12
52
#define BLOCKED         16
53
#define FLAGS           20
54
#define ERRNO           24
55
 
56
#define PF_TRACESYS     0x20
57
 
58
/* Bad Abort numbers
59
 * -----------------
60
 */
61
#define BAD_PREFETCH    0
62
#define BAD_DATA        1
63
#define BAD_ADDREXCPTN  2
64
#define BAD_IRQ         3
65
 
66
/* OS version number used in SWIs
67
 *  RISC OS is 0
68
 *  RISC iX is 8
69
 */
70
#define OS_NUMBER       9
71
 
72
/* Stack format (ensured by USER_* and SVC_*)
73
 */
74
#define S_OLD_R0        64
75
#define S_PC            60
76
#define S_LR            56
77
#define S_SP            52
78
#define S_IP            48
79
#define S_FP            44
80
#define S_R10           40
81
#define S_R9            36
82
#define S_R8            32
83
#define S_R7            28
84
#define S_R6            24
85
#define S_R5            20
86
#define S_R4            16
87
#define S_R3            12
88
#define S_R2            8
89
#define S_R1            4
90
#define S_R0            0
91
 
92
#include "../lib/constants.h"
93
 
94
#define USER_SAVE_ALL                           \
95
                str     r0, [sp, #-4]!          ;\
96
                str     lr, [sp, #-4]!          ;\
97
                sub     sp, sp, #15*4           ;\
98
                stmia   sp, {r0 - lr}^          ;\
99
                mov     r0, r0                  ;\
100
                mov     fp, #0
101
 
102
#define SVC_SAVE_ALL                            \
103
                str     sp, [sp, #-16]!         ;\
104
                str     lr, [sp, #8]            ;\
105
                str     lr, [sp, #4]            ;\
106
                stmfd   sp!, {r0 - r12}         ;\
107
                mov     r0, #-1                 ;\
108
                str     r0, [sp, #S_OLD_R0]     ;\
109
                mov     fp, #0
110
 
111
#define SVC_IRQ_SAVE_ALL                        \
112
                str     sp, [sp, #-16]!         ;\
113
                str     lr, [sp, #4]            ;\
114
                ldr     lr, [pc, #LC4 - . - 8]  ;\
115
                ldr     lr, [lr]                ;\
116
                str     lr, [sp, #8]            ;\
117
                stmfd   sp!, {r0 - r12}         ;\
118
                mov     r0, #-1                 ;\
119
                str     r0, [sp, #S_OLD_R0]     ;\
120
                mov     fp, #0
121
 
122
#define USER_RESTORE_ALL                        \
123
                ldmia   sp, {r0 - lr}^          ;\
124
                mov     r0, r0                  ;\
125
                add     sp, sp, #15*4           ;\
126
                ldr     lr, [sp], #8            ;\
127
                movs    pc, lr
128
 
129
#define SVC_RESTORE_ALL                         \
130
                ldmfd   sp, {r0 - pc}^
131
 
132
                .global _ret_from_sys_call
133
 
134
/*
135
 * Interrupt table (incorporates priority).  First set is indexed using
136
 * IRQSTATB.
137
 */
138
 
139
Lirq_prio_h:    .byte    0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
140
                .byte   12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10
141
                .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
142
                .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
143
                .byte   14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
144
                .byte   14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10
145
                .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
146
                .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
147
                .byte   15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
148
                .byte   15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
149
                .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
150
                .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
151
                .byte   15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
152
                .byte   15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10
153
                .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
154
                .byte   13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10
155
 
156
Lirq_prio_l:    .byte    0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
157
                .byte    4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3
158
                .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
159
                .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
160
                .byte    6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
161
                .byte    6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3
162
                .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
163
                .byte    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
164
                .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
165
                .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
166
                .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
167
                .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
168
                .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
169
                .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
170
                .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
171
                .byte    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
172
 
173
/**************************************************************************
174
 * Interrupt (IRQ) handler (r13 points to irq temp save area)
175
 * Note: if in user mode, then *no* kernel routine is running, so dont have
176
 *       to save svc lr
177
 */
178
 
179
LC4:            .word   Lirq_temp
180
LC5:            .word   _irqjump
181
 
182
Lvector_IRQ:    ldr     r13, [pc, #LC4 - . - 8] @ Ill leave this one in just in case...
183
                sub     lr, lr, #4
184
                str     lr, [r13]
185
                tst     lr, #3
186
                bne     LIRQ_not_user
187
                teqp    pc, #0x08000003
188
                mov     r0, r0
189
                ldr     lr, [pc, #LC4 - . - 8]
190
                ldr     lr, [lr]
191
                USER_SAVE_ALL
192
                mov     r4, #IOC_BASE           @ point at IOC
193
                ldrb    r1, [r4, #0x24]         @ get high priority first
194
                adr     r2, Lirq_prio_h
195
                teq     r1, #0
196
                ldreqb  r1, [r4, #0x14]         @ get low priority
197
                adreq   r2, Lirq_prio_l
198
                teq     r1, #0
199
                beq     _ret_from_sys_call
200
                ldrb    r0, [r2, r1]            @ Get IRQ number
201
                ldr     r2, [pc, #LC5 - . - 8]
202
                mov     r1, sp
203
                mov     lr, pc
204
        /*
205
         * routine gets called with r0 = interrupt number, r1 = struct pt_regs *
206
         */
207
                ldr     pc, [r2, r0, lsl#2]
208
                mov     r2, #0
209
                teq     r0, #0                  @ Check to see if it is a fast IRQ
210
                beq     _ret_from_sys_call
211
                USER_RESTORE_ALL
212
 
213
LC65:
214
                .word   _intr_count             @ -8
215
                .word   _bh_mask                @ -4
216
                .word   _bh_active              @ -0
217
 
218
Lirq_illegal_mode:
219
                mov     r0, sp
220
                mov     r1, #BAD_IRQ
221
                b       _bad_mode
222
 
223
LIRQ_not_user:  teqp    pc, #0x08000003
224
                mov     r0, r0
225
                SVC_IRQ_SAVE_ALL
226
                and     r2, lr, #3
227
                teq     r2, #3
228
                bne     Lirq_illegal_mode
229
Lsrepeat:       mov     r4, #IOC_BASE           @ point at IOC
230
                ldrb    r1, [r4, #0x24]         @ get high priority first
231
                adr     r2, Lirq_prio_h
232
                teq     r1, #0
233
                ldreqb  r1, [r4, #0x14]         @ get low priority
234
                adreq   r2, Lirq_prio_l
235
                teq     r1, #0
236
                beq     Lno_irq2
237
                ldrb    r0, [r2, r1]            @ Get IRQ number
238
                ldr     r2, [pc, #LC5 - . - 8]
239
                mov     r1, sp
240
                mov     lr, pc
241
        /*
242
         * routine gets called with r0 = interrupt number, r1 = struct pt_regs *
243
         */
244
                ldr     pc, [r2, r0, lsl#2]
245
                mov     r2, #1
246
                teq     r0, #0                  @ Check to see if it is a fast IRQ
247
                bne     Lsrepeat
248
                ldr     r0, [pc, #LC65 - . - 8]
249
                ldr     r1, [r0]
250
                teq     r1, #0
251
                bne     Lsrepeat
252
                mov     r4, r0
253
                mov     r5, r1
254
                ldr     r6, [pc, #LC65 - . - 4]
255
                ldr     r7, [pc, #LC65 - . - 0]
256
Lrecheck_bh2:   ldr     r0, [r6]
257
                ldr     r1, [r7]
258
                tst     r0, r1
259
                beq     Lsrepeat
260
                add     r0, r5, #1
261
                str     r0, [r4]
262
                mov     r8, pc
263
                teqp    pc, #0x00000003
264
                bl      _do_bottom_half
265
                teqp    r8, #0
266
                str     r5, [r4]
267
                b       Lrecheck_bh2
268
Lno_irq2:       SVC_RESTORE_ALL
269
 
270
/**************************************************************************
271
 * Trap initialisation
272
 *
273
 * Note - FIQ code has changed.  The default is a couple of words in 0x1c,
274
 * 0x20 that call _unexp_fiq.  Nowever, we now copy the FIQ routine to
275
 * 0x1c (removes some excess cycles).
276
 */
277
 
278
Lswi_reset:     swi     SYS_ERROR0
279
                ldr     pc, . + 4
280
                .long   _unexp_fiq
281
 
282
Lfiqmsg:        .ascii  "*** Unexpeced FIQ\n\0"
283
                .align
284
 
285
_unexp_fiq:     mov     r12, #IOC_BASE
286
                strb    r12, [r12, #0x38]       @ Disable FIQ register
287
                teqp    pc, #0x0c000003
288
                mov     r0, r0
289
                stmfd   sp!, {r0 - r3, ip, lr}
290
                adr     r0, Lfiqmsg
291
                bl      _printk
292
                ldmfd   sp!, {r0 - r3, ip, lr}
293
                teqp    pc, #0x0c000001
294
                mov     r0, r0
295
                movs    pc, lr
296
 
297
Lvectors:       .long   Lvector_undefinstr - Lvectors - 12
298
                .long   Lvector_swi - Lvectors - 16
299
                .long   Lvector_prefetch - Lvectors - 20
300
                .long   Lvector_data - Lvectors - 24
301
                .long   Lvector_addrexcptn - Lvectors - 28
302
                .long   Lvector_IRQ - Lvectors - 32
303
                .long   0xea000000
304
 
305
                .global _trap_init
306
_trap_init:     stmfd   sp !,{r4 - r9,lr}       @ Save link register
307
                teqp    pc, #0x0c000003
308
                mov     r0, #IOC_BASE
309
                str     r0, [r0, #0x18]
310
                str     r0, [r0, #0x28]
311
                str     r0, [r0, #0x38]
312
                mov     r0, #0                  @ Lowest location
313
                adr     r1, Lvectors
314
                ldmia   r1, {r2, r3, r4, r5, r6, r7, ip}
315
                add     r1, ip, r1, asr #2
316
                add     r2, r1, r2, asr #2
317
                add     r3, r1, r3, asr #2
318
                add     r4, r1, r4, asr #2
319
                add     r5, r1, r5, asr #2
320
                add     r6, r1, r6, asr #2
321
                add     r7, r1, r7, asr #2
322
                adr     r1, Lswi_reset
323
                ldmia   r1, {r1, r8, r9}
324
                stmia   r0!, {r1 - r9}          @ Save all into page 0 ram
325
                ldmfd   sp!, {r4 - r9, pc}^
326
 
327
/**************************************************************************
328
 * Prefetch abort handler
329
 */
330
 
331
#ifdef DEBUG_UNDEF
332
t:              .ascii "*** undef ***\r\n\0"
333
                .align
334
#endif
335
 
336
Lvector_prefetch:
337
                sub     lr, lr, #4
338
                tst     lr, #3
339
                bne     Lprefetch_not_user
340
                USER_SAVE_ALL
341
                teqp    pc, #0x00000003         @ NOT a problem - doesnt change mode
342
                bic     r0, lr, #0xfc000003     @ Address of abort
343
                mov     r1, #FAULT_CODE_PREFETCH|FAULT_CODE_USER @ Error code
344
                mov     r2, sp                  @ Tasks registers
345
                bl      _do_PrefetchAbort
346
                teq     r0, #0                  @ If non-zero, we believe this abort..
347
                bne     _ret_from_sys_call
348
#ifdef DEBUG_UNDEF
349
                adr     r0,t                    @ Otherwise it was probably an undefined
350
                bl      _printk                 @ instruction.  (I do wish that I had a
351
#endif
352
                ldr     lr, [sp,#S_PC]          @ program to test this on.  I think its
353
                b       _undefinstr             @ broken at the moment though!)
354
 
355
Lprefetch_not_user:
356
                SVC_SAVE_ALL                    @ Prefetch aborts are definitely *not*
357
                mov     r0, sp                  @ allowed in non-user modes.  We cant
358
                mov     r1, #BAD_PREFETCH       @ recover from this problem.
359
                and     r2, lr, #3
360
                b       _bad_mode               @ Doesnt return
361
 
362
/**************************************************************************
363
 * Undefined instruction handler
364
 */
365
LC8:
366
                .word   _last_task_used_math
367
                .word   _current
368
LC9:
369
                .word   _fp_enter
370
                .word   _fp_save
371
                .word   _fp_restore
372
 
373
Lundef_not_user:
374
                SVC_SAVE_ALL                    @ Non-user mode
375
                bic     r0, lr, #0xfc000003
376
                and     r2, lr, #3
377
                sub     r0, r0, #4
378
                mov     r1, sp
379
                bl      _do_undefinstr
380
                SVC_RESTORE_ALL
381
 
382
                .global _fpreturn
383
                .global _fpundefinstr
384
Lvector_undefinstr:
385
                tst     lr,#3
386
                bne     Lundef_not_user
387
                USER_SAVE_ALL                   @ USER mode undefined instructions
388
                teqp    pc, #0x08000003         @ MUST disable interrupts.
389
_undefinstr:
390
@
391
@ before calling FP, must call math_state_restore!!!
392
@  something along the lines of:
393
@
394
                adr     r3, LC8
395
                ldmia   r3, {r1, r2, r3}
396
                ldr     r1, [r1]                @ last task used math
397
                ldr     r2, [r2]                @ current task
398
                teq     r1, r2
399
                stmnefd sp!, {ip, lr}
400
                blne    _math_state_restore
401
                ldmnefd sp!, {ip, lr}
402
 
403
                ldr     r3, [pc, #LC9 - . - 8]
404
                ldr     pc, [r3]                @ Call FP module (when loaded)
405
_fpundefinstr:  mov     r1,sp                   @ Called by FP module on undefined instr
406
                teqp    pc, #3                  @ Enable interrupts
407
                mov     r2,#0
408
                mov     lr, pc
409
@ Change!!
410
                add     lr, lr, #_ret_from_sys_call - . - 4
411
                b       _do_undefinstr
412
 
413
/**************************************************************************
414
 * Address exception handler
415
 *
416
 * These aren't too critical. (they're not supposed to happen).
417
 */
418
 
419
/*
420
 * In order to debug the reason for address exceptions in non-user modes,
421
 * we have to obtain all the registers so that we can see what's going on.
422
 */
423
Laddrexcptn_illegal_mode:
424
                mov     r0, sp
425
                str     lr, [sp, #-4]!
426
                orr     r1, r2, #0x0c000000
427
                teqp    r1, #0                  @ change into mode (wont be user mode)
428
                mov     r0, r0
429
                mov     r1, r8                  @ Any register from r8 - r14 can be banked
430
                mov     r2, r9
431
                mov     r3, r10
432
                mov     r4, r11
433
                mov     r5, r12
434
                mov     r6, r13
435
                mov     r7, r14
436
                teqp    pc, #0x04000003         @ back to svc
437
                mov     r0, r0
438
                stmfd   sp!, {r1-r7}
439
                ldmia   r0, {r0-r7}
440
                stmfd   sp!, {r0-r7}
441
                mov     r0, sp
442
                mov     r1, #BAD_ADDREXCPTN
443
                b       _bad_mode
444
 
445
Laddrexcptn_not_user:
446
                SVC_SAVE_ALL
447
                and     r2, lr, #3
448
                teq     r2, #3
449
                bne     Laddrexcptn_illegal_mode
450
                teqp    pc, #0x00000003         @ NOT a problem - doesnt change mode
451
                bic     r0, lr, #0xfc000003
452
                mov     r1, sp
453
                orr     r2, r2, #0x400
454
                bl      _do_excpt
455
                ldmia   sp, {r0 - lr}           @ I cant remember the reason I changed this...
456
                add     sp, sp, #15*4
457
                movs    pc, lr
458
 
459
Lvector_addrexcptn:
460
                sub     lr, lr, #8
461
                tst     lr, #3
462
                bne     Laddrexcptn_not_user
463
                USER_SAVE_ALL
464
                teq     pc, #0x00000003
465
                bic     r0, lr, #0xfc000003     @ Point to instruction
466
                mov     r1, sp                  @ Point to registers
467
                mov     r2, #0x400
468
                mov     lr, pc
469
@ Change!!
470
                add     lr, lr, #_ret_from_sys_call - . - 4
471
                b       _do_excpt
472
 
473
/**************************************************************************
474
 * Data abort handler code
475
 */
476
 
477
Lvector_data:   sub     lr, lr, #8              @ Correct lr
478
                tst     lr, #3
479
                bne     Ldata_not_user
480
                USER_SAVE_ALL
481
                teqp    pc, #0x00000003         @ NOT a problem - doesnt change mode
482
                bic     r0, lr, #0xfc000003
483
                mov     r2, #FAULT_CODE_USER
484
                mov     lr, pc
485
                add     lr, lr, #_ret_from_sys_call - . - 4
486
                b       Ldata_do
487
 
488
Ldata_not_user:
489
                SVC_SAVE_ALL
490
                and     r2, lr, #3
491
                teq     r2, #3
492
                bne     Ldata_illegal_mode
493
                tst     lr, #0x08000000
494
                teqeqp  pc, #0x00000003         @ NOT a problem - doesnt change mode
495
                bic     r0, lr, #0xfc000003
496
                mov     r2, #0
497
                bl      Ldata_do
498
                SVC_RESTORE_ALL
499
 
500
Ldata_illegal_mode:
501
                mov     r0, sp
502
                mov     r1, #BAD_DATA
503
                b       _bad_mode
504
 
505
/**************************************************************************
506
 *
507
 * All exits to user mode from the kernel go through this code.
508
 */
509
 
510
LC6:
511
                .word   _intr_count             @ -8
512
                .word   _bh_mask                @ -4
513
                .word   _bh_active              @ -0
514
                .word   _need_resched           @ +4
515
                .word   _current                @ +8
516
                .word   _init_task              @ +12
517
 
518
Lreschedule:    bl      _schedule
519
_fpreturn:
520
_ret_from_sys_call:
521
                adr     r4, LC6
522
                ldmia   r4, {r4, r6, r7, r9}
523
                ldr     r5, [r4]
524
                teq     r5, #0
525
                bne     Lret_no_check
526
Lrecheck_bh:    ldr     r0, [r6]
527
                ldr     r1, [r7]
528
                tst     r0, r1
529
                bne     Lhandle_bottom_half
530
                ldr     r0, [sp, #S_PC]         @ Get old PC
531
                tst     r0, #3
532
                bne     Lret_no_check
533
                ldr     r0, [r9]
534
                teq     r0, #0
535
                bne     Lreschedule
536
 
537
                ldr     r2, [pc, #LC6 - . + 8]
538
                ldr     r2, [r2]
539
                ldr     r1, [pc, #LC6 - . + 12]
540
                teq     r2, r1
541
                beq     Lret_no_check
542
 
543
                ldr     r1, [r2, #SIGNAL]
544
                ldr     r0, [r2, #BLOCKED]
545
                bics    r1, r1, r0
546
                movne   r1, sp
547
                blne    _do_signal
548
Lret_no_check:  USER_RESTORE_ALL
549
 
550
Lhandle_bottom_half:
551
                add     r0, r5, #1
552
                str     r0, [r4]
553
                mov     r8, pc
554
                teqp    pc, #0x00000003
555
                bl      _do_bottom_half
556
                teqp    r8, #0
557
                str     r5, [r4]
558
                b       Lrecheck_bh
559
 
560
/**************************************************************************
561
 * SWI handler
562
 *
563
 *
564
 * We now handle sys-call tracing, and the errno in the task structure.
565
 * Still have a problem with >4 arguments for functions.  Theres only
566
 * a couple of functions in the code that have 5 arguments, so Im not
567
 * too worried.
568
 */
569
 
570
#include "calls.S"
571
 
572
LC1:            .word   _current
573
 
574
Lvector_swi:    USER_SAVE_ALL
575
                bic     lr, lr, #0xfc000003     @ get pc value from link register
576
                ldr     r6, [lr, #-4]           @ get swi instruction
577
                teqp    pc, #0x00000003         @ enable irqs
578
                bic     r6, r6, #0xff000000     @ mask off swi op code
579
                eor     r6, r6, #OS_NUMBER << 20 @ check OS number
580
Lretry:         cmp     r6, #NR_SYSCALLS        @ check upper syscall limit
581
                bcs     Lswi_bad_call
582
                ldr     r5, [pc, #LC1 - . - 8]
583
                ldr     r5, [r5]
584
                mov     ip, #0                  @ zero errno
585
                str     ip, [r5, #ERRNO]
586
 
587
                ldr     ip, [r5, #FLAGS]        @ check for syscall tracing
588
                tst     ip, #PF_TRACESYS
589
                bne     Ltrace_this_syscall
590
 
591
                adr     ip, _sys_call_table
592
                mov     r9, sp                  @ hack for old routines needing '*regs'
593
                str     r4, [sp, #-4]!          @ new-style: (r0 = arg1, r4 = arg5)
594
                mov     lr, pc
595
                ldr     pc, [ip, r6, lsl #2]    @ call sys routine (r0, r1, r2, r3, r4)
596
                add     sp, sp, #4
597
 
598
                ldr     ip, [r5, #ERRNO]        @ check errno
599
                rsbs    ip, ip, #0
600
                movne   r0, ip
601
                str     r0, [sp, #0]            @ returned r0
602
                b       _ret_from_sys_call
603
 
604
Ltrace_this_syscall:
605
                ldr     r7, [sp, #S_IP]
606
                mov     r0, #0
607
                str     r0, [sp, #S_IP]
608
                bl      _syscall_trace          @ trace entry [IP must = 0]
609
                str     r7, [sp, #S_IP]
610
                ldmia   sp, {r0 - r3}           @ have to reload r0 - r3
611
 
612
                adr     ip, _sys_call_table
613
                mov     r9, sp                  @ hack for routines needing '*regs'
614
                str     r4, [sp, #-4]!
615
                mov     lr, pc
616
                ldr     pc, [ip, r6, lsl #2]    @ call sys routine (r0, r1, r2, r3, r4)
617
                add     sp, sp, #4
618
 
619
                ldr     ip, [r5, #ERRNO]
620
                rsbs    ip, ip, #0
621
                movne   r0, ip
622
                str     r0, [sp, #0]            @ returned r0
623
 
624
                mov     r0, #1
625
                str     r0, [sp, #S_IP]
626
                bl      _syscall_trace          @ trace exit [IP must != 0]
627
                str     r7, [sp, #S_IP]
628
                b       _ret_from_sys_call
629
 
630
 
631
Lswi_bad_call:  tst     r6, #0x00f00000
632
                bne     Lbad
633
                cmp     r6, #(KSWI_SYS_BASE - KSWI_BASE)@ check for arm private syscalls
634
                bcs     Larm_sys_call
635
                bl      _sys_ni_syscall
636
                str     r0, [sp, #0]            @ returned r0
637
                b       _ret_from_sys_call
638
 
639
Lbad:           eor     r0, r6, #OS_NUMBER << 20 @ check OS number
640
                bl      _deferred
641
                ldmfd   sp, {r0 - r3}
642
                b       Lretry
643
 
644
Larm_sys_call:  bic     r0, r6, #0x000f0000
645
                mov     r1, sp
646
                bl      _arm_syscall
647
                b       _ret_from_sys_call
648
 
649
@ r0 = syscall number
650
@ r1 = syscall r0
651
@ r5 = syscall r4
652
@ ip = syscall table
653
_sys_syscall:   mov     r6, r0
654
                eor     r6, r6, #OS_NUMBER << 20
655
                cmp     r6, #NR_SYSCALLS                @ check range
656
                movgt   r0, #-ENOSYS
657
                movgt   pc, lr
658
                add     sp, sp, #4                      @ take of the save of our r4
659
                ldmib   sp, {r0 - r4}                   @ get our args
660
                str     r4, [sp, #-4]!                  @ Put our arg on the stack
661
                ldr     pc, [ip, r6, lsl #2]
662
 
663
                .global _sys_call_table
664
_sys_call_table:
665
#include "calls.S"
666
 
667
/******************************************************************************
668
 *
669
 * Data abort handler code.  This handles both exceptions from user and SVC
670
 *   modes, computes the address range of the problem, and does any
671
 *   correction that is required.  It then calls the kernel data abort routine.
672
 *
673
 * This is where I wish that the ARM would tell you which address aborted.
674
 */
675
 
676
Ldata_do:       mov     r3, sp
677
                ldr     r4, [r0]                @ Get instruction
678
                tst     r4, #1 << 20            @ Check to see if it is a write instruction
679
                orreq   r2, r2, #FAULT_CODE_WRITE @ Indicate write instruction
680
                mov     r1, r4, lsr #22         @ Now branch to the relevent processing routine
681
                and     r1, r1, #15 << 2
682
                add     pc, pc, r1
683
                movs    pc, lr
684
                b       Ldata_unknown
685
                b       Ldata_unknown
686
                b       Ldata_unknown
687
                b       Ldata_unknown
688
                b       Ldata_ldrstr_post       @ ldr   rd, [rn], #m
689
                b       Ldata_ldrstr_numindex   @ ldr   rd, [rn, #m]    @ RegVal
690
                b       Ldata_ldrstr_post       @ ldr   rd, [rn], rm
691
                b       Ldata_ldrstr_regindex   @ ldr   rd, [rn, rm]
692
                b       Ldata_ldmstm            @ ldm*a rn, 
693
                b       Ldata_ldmstm            @ ldm*b rn, 
694
                b       Ldata_unknown
695
                b       Ldata_unknown
696
                b       Ldata_ldrstr_post       @ ldc   rd, [rn], #m    @ Same as ldr   rd, [rn], #m
697
                b       Ldata_ldcstc_pre        @ ldc   rd, [rn, #m]
698
                b       Ldata_unknown
699
Ldata_unknown:  @ Part of jumptable
700
                ldr     r3, [sp, #15 * 4]
701
                str     r3, [sp, #-4]!
702
                mov     r1, r1, lsr #2
703
                mov     r2, r0
704
                mov     r3, r4
705
                adr     r0, Ltt
706
                bl      _printk
707
Llpxx:          b       Llpxx
708
 
709
Ltt:            .ascii  "Unknown data abort code %d [pc=%p, *pc=%p]\nLR=%p\0"
710
                .align
711
 
712
Ldata_ldrstr_post:
713
                mov     r0, r4, lsr #14         @ Get Rn
714
                and     r0, r0, #15 << 2        @ Mask out reg.
715
                teq     r0, #15 << 2
716
                ldr     r0, [r3, r0]            @ Get register
717
                biceq   r0, r0, #0xfc000003
718
                mov     r1, r0
719
                tst     r4, #1 << 21
720
                orrne   r2, r2, #FAULT_CODE_USER
721
#ifdef FAULT_CODE_LDRSTRPOST
722
                orr     r2, r2, #FAULT_CODE_LDRSTRPOST
723
#endif
724
                b       _do_DataAbort
725
 
726
Ldata_ldrstr_numindex:
727
                mov     r0, r4, lsr #14         @ Get Rn
728
                and     r0, r0, #15 << 2        @ Mask out reg.
729
                teq     r0, #15 << 2
730
                ldr     r0, [r3, r0]            @ Get register
731
                biceq   r0, r0, #0xfc000003
732
                mov     r1, r4, lsl #20
733
                tst     r4, #1 << 23
734
                addne   r0, r0, r1, lsr #20
735
                subeq   r0, r0, r1, lsr #20
736
                mov     r1, r0
737
#ifdef FAULT_CODE_LDRSTRPRE
738
                orr     r2, r2, #FAULT_CODE_LDRSTRPRE
739
#endif
740
                b       _do_DataAbort
741
 
742
Ldata_ldrstr_regindex:
743
                mov     r0, r4, lsr #14         @ Get Rn
744
                and     r0, r0, #15 << 2        @ Mask out reg.
745
                teq     r0, #15 << 2
746
                ldr     r0, [r3, r0]            @ Get register
747
                biceq   r0, r0, #0xfc000003
748
                and     r7, r4, #15
749
                teq     r7, #15                 @ Check for PC
750
                ldr     r7, [r3, r7, lsl #2]    @ Get Rm
751
                biceq   r7, r7, #0xfc000003
752
                and     r8, r4, #0x60           @ Get shift types
753
                mov     r9, r4, lsr #7          @ Get shift amount
754
                and     r9, r9, #31
755
                teq     r8, #0
756
                moveq   r7, r7, lsl r9
757
                teq     r8, #0x20               @ LSR shift
758
                moveq   r7, r7, lsr r9
759
                teq     r8, #0x40               @ ASR shift
760
                moveq   r7, r7, asr r9
761
                teq     r8, #0x60               @ ROR shift
762
                moveq   r7, r7, ror r9
763
                tst     r4, #1 << 23
764
                addne   r0, r0, r7
765
                subeq   r0, r0, r7              @ Apply correction
766
                mov     r1, r0
767
#ifdef FAULT_CODE_LDRSTRREG
768
                orr     r2, r2, #FAULT_CODE_LDRSTRREG
769
#endif
770
                b       _do_DataAbort
771
 
772
Ldata_ldmstm:
773
                mov     r7, #0x11
774
                orr     r7, r7, r7, lsl #8
775
                and     r0, r4, r7
776
                and     r1, r4, r7, lsl #1
777
                add     r0, r0, r1, lsr #1
778
                and     r1, r4, r7, lsl #2
779
                add     r0, r0, r1, lsr #2
780
                and     r1, r4, r7, lsl #3
781
                add     r0, r0, r1, lsr #3
782
                add     r0, r0, r0, lsr #8
783
                add     r0, r0, r0, lsr #4
784
                and     r7, r0, #15             @ r7 = no. of registers to transfer.
785
                mov     r5, r4, lsr #14         @ Get Rn
786
                and     r5, r5, #15 << 2
787
                ldr     r0, [r3, r5]            @ Get reg
788
                eor     r6, r4, r4, lsl #2
789
                tst     r6, #1 << 23            @ Check inc/dec ^ writeback
790
                rsbeq   r7, r7, #0
791
                add     r7, r0, r7, lsl #2      @ Do correction (signed)
792
                subne   r1, r7, #1
793
                subeq   r1, r0, #1
794
                moveq   r0, r7
795
                tst     r4, #1 << 21            @ Check writeback
796
                strne   r7, [r3, r5]
797
                eor     r6, r4, r4, lsl #1
798
                tst     r6, #1 << 24            @ Check Pre/Post ^ inc/dec
799
                addeq   r0, r0, #4
800
                addeq   r1, r1, #4
801
                teq     r5, #15*4               @ CHECK FOR PC
802
                biceq   r1, r1, #0xfc000003
803
                biceq   r0, r0, #0xfc000003
804
#ifdef FAULT_CODE_LDMSTM
805
                orr     r2, r2, #FAULT_CODE_LDMSTM
806
#endif
807
                b       _do_DataAbort
808
 
809
Ldata_ldcstc_pre:
810
                mov     r0, r4, lsr #14         @ Get Rn
811
                and     r0, r0, #15 << 2        @ Mask out reg.
812
                teq     r0, #15 << 2
813
                ldr     r0, [r3, r0]            @ Get register
814
                biceq   r0, r0, #0xfc000003
815
                mov     r1, r4, lsl #24         @ Get offset
816
                tst     r4, #1 << 23
817
                addne   r0, r0, r1, lsr #24
818
                subeq   r0, r0, r1, lsr #24
819
                mov     r1, r0
820
#ifdef FAULT_CODE_LDCSTC
821
                orr     r2, r2, #FAULT_CODE_LDCSTC
822
#endif
823
                b       _do_DataAbort
824
 
825
                .global _fpe_save
826
_fpe_save:      ldr     r1, [pc, #LC9 - . - 4]
827
                ldr     pc, [r1]
828
 
829
                .global _fpe_restore
830
_fpe_restore:   ldr     r1, [pc, #LC9 - . - 0]
831
                ldr     pc, [r1]
832
 
833
_fpnull:        mov     pc, lr
834
 
835
                .data
836
 
837
                .global _fp_enter
838
                .global _fp_save
839
                .global _fp_restore
840
_fp_enter:      .word   _fpundefinstr
841
_fp_save:       .word   _fpnull
842
_fp_restore:    .word   _fpnull
843
 
844
Lirq_temp:      .word   0

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.