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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [sparc/] [kernel/] [entry.S] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1624 jcastillo
/* $Id: entry.S,v 1.1 2005-12-20 09:50:43 jcastillo Exp $
2
 * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
3
 *
4
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5
 */
6
 
7
#include 
8
#include 
9
 
10
#include 
11
#include 
12
#include 
13
#include 
14
#include 
15
#include 
16
#include 
17
#include 
18
#include 
19
#include 
20
#include 
21
#include 
22
#include 
23
 
24
#include 
25
 
26
#define NR_SYSCALLS 255      /* Each OS is different... */
27
 
28
/* First, KGDB low level things.  This is a rewrite
29
 * of the routines found in the sparc-stub.c asm() statement
30
 * from the gdb distribution.  This is also dual-purpose
31
 * as a software trap for userlevel programs.
32
 */
33
        .data
34
        .align  4
35
 
36
in_trap_handler:
37
        .word   0
38
 
39
        .text
40
        .align  4
41
 
42
! This function is called when any SPARC trap (except window overflow or
43
! underflow) occurs.  It makes sure that the invalid register window is still
44
! available before jumping into C code.  It will also restore the world if you
45
! return from handle_exception.
46
 
47
        .globl  C_LABEL(trap_low)
48
C_LABEL(trap_low):
49
        rd      %wim, %l3
50
        SAVE_ALL
51
        ENTER_SYSCALL
52
 
53
        sethi   %hi(in_trap_handler), %l4
54
        ld      [%lo(in_trap_handler) + %l4], %l5
55
        inc     %l5
56
        st      %l5, [%lo(in_trap_handler) + %l4]
57
 
58
        /* Make sure kgdb sees the same state we just saved. */
59
        LOAD_PT_GLOBALS(sp)
60
        LOAD_PT_INS(sp)
61
        ld      [%sp + REGWIN_SZ + PT_Y], %l4
62
        ld      [%sp + REGWIN_SZ + PT_WIM], %l3
63
        ld      [%sp + REGWIN_SZ + PT_PSR], %l0
64
        ld      [%sp + REGWIN_SZ + PT_PC], %l1
65
        ld      [%sp + REGWIN_SZ + PT_NPC], %l2
66
        rd      %tbr, %l5       /* Never changes... */
67
 
68
        /* Make kgdb exception frame. */
69
        sub     %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals
70
                                        ! + hidden arg + arg spill
71
                                        ! + doubleword alignment
72
                                        ! + registers[72] local var
73
        SAVE_KGDB_GLOBALS(sp)
74
        SAVE_KGDB_INS(sp)
75
        SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
76
 
77
        /* We are increasing PIL, so two writes. */
78
        or      %l0, PSR_PIL, %l0
79
        wr      %l0, 0, %psr
80
        wr      %l0, PSR_ET, %psr
81
        WRITE_PAUSE
82
 
83
        call    C_LABEL(handle_exception)
84
         add    %sp, REGWIN_SZ, %o0     ! Pass address of registers
85
 
86
        /* Load new kgdb register set. */
87
        LOAD_KGDB_GLOBALS(sp)
88
        LOAD_KGDB_INS(sp)
89
        LOAD_KGDB_SREGS(sp, l0, l2)
90
        wr      %l0, 0x0, %y
91
 
92
        sethi   %hi(in_trap_handler), %l4
93
        ld      [%lo(in_trap_handler) + %l4], %l5
94
        dec     %l5
95
        st      %l5, [%lo(in_trap_handler) + %l4]
96
 
97
        add     %sp,(16+1+6+1+72)*4,%sp ! Undo the kgdb trap frame.
98
 
99
        /* Now take what kgdb did and place it into the pt_regs
100
         * frame which SparcLinux RESTORE_ALL understands.,
101
         */
102
        STORE_PT_INS(sp)
103
        STORE_PT_GLOBALS(sp)
104
        STORE_PT_YREG(sp, g2)
105
        STORE_PT_PRIV(sp, l1, l2, l3)
106
 
107
        RESTORE_ALL
108
 
109
 
110
#ifdef CONFIG_BLK_DEV_FD
111
#ifdef TRACE_FLOPPY_HARDINT
112
/* Useful tracing */
113
        .data
114
        .align  4
115
        .globl  C_LABEL(floppy_hardint_trace)
116
C_LABEL(floppy_hardint_trace):
117
        .skip   32
118
        .globl  C_LABEL(floppy_hardint_index)
119
C_LABEL(floppy_hardint_index):
120
        .word   0
121
#endif
122
 
123
        .text
124
        .align  4
125
        .globl  C_LABEL(floppy_hardint)
126
C_LABEL(floppy_hardint):
127
        /* Can only use regs %l3->%l7:
128
         * %l3 -- base address of fdc registers
129
         * %l4 -- pdma_vaddr
130
         * %l5 -- scratch for ld/st address
131
         * %l6 -- pdma_size
132
         * %l7 -- floppy_softint
133
         */
134
 
135
#ifdef TRACE_FLOPPY_HARDINT
136
        sethi   %hi(C_LABEL(floppy_hardint_trace)), %l5
137
        or      %l5, %lo(C_LABEL(floppy_hardint_trace)), %l5
138
        ld      [%l5 + 32], %l7
139
        add     %l7, 1, %l7
140
        and     %l7, 31, %l7
141
        st      %l7, [%l5 + 32]
142
        sub     %l7, 1, %l7
143
        and     %l7, 31, %l7
144
        add     %l7, %l5, %l5
145
        or      %g0, 0xf, %l7
146
        stb     %l7, [%l5]
147
#endif
148
 
149
        /* Do we have work to do? */
150
        sethi   %hi(C_LABEL(doing_pdma)), %l4
151
        ld      [%l4 + %lo(C_LABEL(doing_pdma))], %l4
152
        cmp     %l4, 0
153
        be      floppy_dosoftint
154
         nop
155
 
156
        /* Load fdc register base */
157
        sethi   %hi(C_LABEL(fdc_status)), %l3
158
        ld      [%l3 + %lo(C_LABEL(fdc_status))], %l3
159
 
160
        /* Setup register addresses */
161
        sethi   %hi(C_LABEL(pdma_vaddr)), %l5   ! transfer buffer
162
        ld      [%l5 + %lo(C_LABEL(pdma_vaddr))], %l4
163
        sethi   %hi(C_LABEL(pdma_size)), %l5    ! bytes to go
164
        ld      [%l5 + %lo(C_LABEL(pdma_size))], %l6
165
next_byte:
166
#ifdef TRACE_FLOPPY_HARDINT
167
        sethi   %hi(C_LABEL(floppy_hardint_trace)), %l5
168
        or      %l5, %lo(C_LABEL(floppy_hardint_trace)), %l5
169
        ld      [%l5 + 32], %l7
170
        add     %l7, 1, %l7
171
        and     %l7, 31, %l7
172
        st      %l7, [%l5 + 32]
173
        sub     %l7, 1, %l7
174
        and     %l7, 31, %l7
175
        add     %l7, %l5, %l5
176
        ldub    [%l3], %l7
177
        stb     %l7, [%l5]
178
#else
179
        ldub    [%l3], %l7
180
#endif
181
 
182
        andcc   %l7, 0x80, %g0          ! Does fifo still have data
183
        bz      floppy_fifo_emptied     ! fifo has been emptied...
184
         andcc  %l7, 0x20, %g0          ! in non-dma mode still?
185
        bz      floppy_overrun          ! nope, overrun
186
         andcc  %l7, 0x40, %g0          ! 0=write 1=read
187
        bz      floppy_write
188
         sub    %l6, 0x1, %l6
189
 
190
        /* Ok, actually read this byte */
191
        ldub    [%l3 + 1], %l7
192
        orcc    %g0, %l6, %g0
193
        stb     %l7, [%l4]
194
        bne     next_byte
195
         add    %l4, 0x1, %l4
196
 
197
        b       floppy_tdone
198
         nop
199
 
200
floppy_write:
201
        /* Ok, actually write this byte */
202
        ldub    [%l4], %l7
203
        orcc    %g0, %l6, %g0
204
        stb     %l7, [%l3 + 1]
205
        bne     next_byte
206
         add    %l4, 0x1, %l4
207
 
208
        /* fall through... */
209
floppy_tdone:
210
        sethi   %hi(C_LABEL(pdma_vaddr)), %l5
211
        st      %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
212
        sethi   %hi(C_LABEL(pdma_size)), %l5
213
        st      %l6, [%l5 + %lo(C_LABEL(pdma_size))]
214
        /* Flip terminal count pin */
215
        set     C_LABEL(auxio_register), %l4
216
        ld      [%l4], %l4
217
 
218
        set     C_LABEL(sparc_cpu_model), %l5
219
        ld      [%l5], %l5
220
        subcc   %l5, 1, %g0             /* enum { sun4c = 1 }; */
221
        be      1f
222
         ldub   [%l4], %l5
223
 
224
        or      %l5, 0xc2, %l5
225
        stb     %l5, [%l4]
226
        andn    %l5, 0x02, %l5
227
        b       2f
228
         nop
229
 
230
1:
231
        or      %l5, 0xf4, %l5
232
        stb     %l5, [%l4]
233
        andn    %l5, 0x04, %l5
234
 
235
2:
236
        /* Kill some time so the bits set */
237
        WRITE_PAUSE
238
        WRITE_PAUSE
239
 
240
        stb     %l5, [%l4]
241
 
242
        /* Prevent recursion */
243
        sethi   %hi(C_LABEL(doing_pdma)), %l4
244
        b       floppy_dosoftint
245
         st     %g0, [%l4 + %lo(C_LABEL(doing_pdma))]
246
 
247
        /* We emptied the FIFO, but we haven't read everything
248
         * as of yet.  Store the current transfer address and
249
         * bytes left to read so we can continue when the next
250
         * fast IRQ comes in.
251
         */
252
floppy_fifo_emptied:
253
        sethi   %hi(C_LABEL(pdma_vaddr)), %l5
254
        st      %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
255
        sethi   %hi(C_LABEL(pdma_size)), %l7
256
        st      %l6, [%l7 + %lo(C_LABEL(pdma_size))]
257
 
258
        /* Restore condition codes */
259
        wr      %l0, 0x0, %psr
260
        WRITE_PAUSE
261
 
262
        jmp     %l1
263
        rett    %l2
264
 
265
floppy_overrun:
266
        sethi   %hi(C_LABEL(pdma_vaddr)), %l5
267
        st      %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
268
        sethi   %hi(C_LABEL(pdma_size)), %l5
269
        st      %l6, [%l5 + %lo(C_LABEL(pdma_size))]
270
        /* Prevent recursion */
271
        sethi   %hi(C_LABEL(doing_pdma)), %l4
272
        st      %g0, [%l4 + %lo(C_LABEL(doing_pdma))]
273
 
274
        /* fall through... */
275
floppy_dosoftint:
276
        rd      %wim, %l3
277
        SAVE_ALL
278
        ENTER_IRQ
279
 
280
        /* Set all IRQs off. */
281
        or      %l0, PSR_PIL, %l4
282
        wr      %l4, 0x0, %psr
283
        wr      %l4, PSR_ET, %psr
284
        WRITE_PAUSE
285
 
286
        mov     11, %o0                 ! floppy irq level
287
        call    C_LABEL(floppy_interrupt)
288
         add    %sp, REGWIN_SZ, %o1     ! struct pt_regs *regs
289
 
290
        LEAVE_IRQ
291
        RESTORE_ALL
292
 
293
#endif /* (CONFIG_BLK_DEV_FD) */
294
 
295
        /* Bad trap handler */
296
        .globl  bad_trap_handler
297
bad_trap_handler:
298
        SAVE_ALL
299
        ENTER_SYSCALL
300
 
301
        wr      %l0, PSR_ET, %psr
302
        WRITE_PAUSE
303
 
304
        mov     %l7, %o0                ! trap number
305
        mov     %l0, %o1                ! psr
306
        call    C_LABEL(do_hw_interrupt)
307
         mov    %l1, %o2                ! pc
308
 
309
        RESTORE_ALL
310
 
311
/* For now all IRQ's not registered get sent here. handler_irq() will
312
 * see if a routine is registered to handle this interrupt and if not
313
 * it will say so on the console.
314
 */
315
 
316
        .align  4
317
        .globl  real_irq_entry
318
real_irq_entry:
319
        SAVE_ALL
320
#ifdef __SMP__
321
        cmp     %l7, 9
322
        bne     1f
323
         nop
324
 
325
        GET_PROCESSOR_MID(l4, l5)
326
        set     C_LABEL(sun4m_interrupts), %l5
327
        ld      [%l5], %l5
328
        sethi   %hi(0x02000000), %l6
329
        sll     %l4, 12, %l4
330
        add     %l5, %l4, %l5
331
        ld      [%l5], %l4
332
        andcc   %l4, %l6, %g0
333
        be      1f
334
         nop
335
 
336
        b       linux_trap_ipi9_sun4m
337
         nop
338
 
339
1:
340
#endif
341
        ENTER_IRQ
342
 
343
#ifdef __SMP__
344
        cmp     %l7, 13
345
        bne     1f
346
         nop
347
 
348
        /* This is where we catch the level 13 reschedule soft-IRQ. */
349
        GET_PROCESSOR_MID(o3, o2)
350
        set     C_LABEL(sun4m_interrupts), %l5
351
        ld      [%l5], %o5
352
        sethi   %hi(0x20000000), %o4
353
        sll     %o3, 12, %o3
354
        add     %o5, %o3, %o5
355
        ld      [%o5], %o1              ! read processor irq pending reg
356
        andcc   %o1, %o4, %g0
357
        be      1f
358
         nop
359
 
360
        b       linux_trap_ipi13_sun4m
361
         nop
362
 
363
1:
364
 
365
#endif
366
 
367
        /* start atomic operation with respect to software interrupts */
368
        sethi   %hi(C_LABEL(intr_count)), %l4
369
        ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
370
        add     %l5, 0x1, %l5
371
        st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
372
 
373
        /* Enable traps w/IRQs off, so we can call c-code properly.
374
         * Note how we are increasing PIL so we need to do two writes
375
         * to work around a MicroSPARC bug of sorts.
376
         */
377
        or      %l0, PSR_PIL, %l4
378
 
379
        wr      %l4, 0x0, %psr
380
        WRITE_PAUSE
381
        wr      %l4, PSR_ET, %psr
382
        WRITE_PAUSE
383
 
384
        mov     %l7, %o0                ! irq level
385
        call    C_LABEL(handler_irq)
386
         add    %sp, REGWIN_SZ, %o1     ! pt_regs ptr
387
 
388
rie_checkbh:
389
        sethi   %hi(C_LABEL(intr_count)), %l4
390
        ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
391
        subcc   %l5, 0x1, %l5
392
        bne     2f      /* IRQ within IRQ, get out of here... */
393
         nop
394
 
395
        sethi   %hi(C_LABEL(bh_active)), %l3
396
        ld      [%l3 + %lo(C_LABEL(bh_active))], %g2
397
        sethi   %hi(C_LABEL(bh_mask)), %l3
398
        ld      [%l3 + %lo(C_LABEL(bh_mask))], %g3
399
        andcc   %g2, %g3, %g0
400
        be      2f
401
         nop
402
 
403
        call    C_LABEL(do_bottom_half)
404
         nop
405
 
406
        /* Try again... */
407
        b       rie_checkbh
408
         nop
409
 
410
2:
411
        st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
412
 
413
        LEAVE_IRQ
414
        RESTORE_ALL
415
 
416
        /* This routine handles illegal instructions and privileged
417
         * instruction attempts from user code.
418
         */
419
        .align  4
420
        .globl  bad_instruction
421
bad_instruction:
422
        SAVE_ALL
423
        ENTER_SYSCALL
424
 
425
        wr      %l0, PSR_ET, %psr               ! re-enable traps
426
        WRITE_PAUSE
427
 
428
        add     %sp, REGWIN_SZ, %o0
429
        mov     %l1, %o1
430
        mov     %l2, %o2
431
        call    C_LABEL(do_illegal_instruction)
432
         mov    %l0, %o3
433
 
434
        RESTORE_ALL
435
 
436
        .align  4
437
        .globl  priv_instruction
438
priv_instruction:
439
        SAVE_ALL
440
        ENTER_SYSCALL
441
 
442
        wr      %l0, PSR_ET, %psr
443
        WRITE_PAUSE
444
 
445
        add     %sp, REGWIN_SZ, %o0
446
        mov     %l1, %o1
447
        mov     %l2, %o2
448
        call    C_LABEL(do_priv_instruction)
449
         mov    %l0, %o3
450
 
451
        RESTORE_ALL
452
 
453
        /* This routine handles unaligned data accesses.
454
         */
455
        .align  4
456
        .globl  mna_handler
457
mna_handler:
458
        SAVE_ALL
459
        ENTER_SYSCALL
460
 
461
        wr      %l0, PSR_ET, %psr               ! re-enable traps
462
        WRITE_PAUSE
463
 
464
        add     %sp, REGWIN_SZ, %o0
465
        mov     %l1, %o1
466
        mov     %l2, %o2
467
        call    C_LABEL(do_memaccess_unaligned)
468
         mov    %l0, %o3
469
 
470
        RESTORE_ALL
471
 
472
        /* This routine handles floating point disabled traps. */
473
        .align  4
474
        .globl  fpd_trap_handler
475
fpd_trap_handler:
476
        SAVE_ALL
477
        ENTER_SYSCALL
478
 
479
        wr      %l0, PSR_ET, %psr               ! re-enable traps
480
        WRITE_PAUSE
481
 
482
        add     %sp, REGWIN_SZ, %o0
483
        mov     %l1, %o1
484
        mov     %l2, %o2
485
        call    C_LABEL(do_fpd_trap)
486
         mov    %l0, %o3
487
 
488
        RESTORE_ALL
489
 
490
        /* This routine handles Floating Point Exceptions. */
491
        .align  4
492
        .globl  fpe_trap_handler
493
fpe_trap_handler:
494
        set     fpsave_magic, %l5
495
        cmp     %l1, %l5
496
        be      1f
497
         sethi  %hi(C_LABEL(fpsave)), %l5
498
        or      %l5, %lo(C_LABEL(fpsave)), %l5
499
        cmp     %l1, %l5
500
        bne     2f
501
         sethi  %hi(fpsave_catch2), %l5
502
        or      %l5, %lo(fpsave_catch2), %l5
503
        wr      %l0, 0x0, %psr
504
        WRITE_PAUSE
505
        jmp     %l5
506
         rett   %l5 + 4
507
1:
508
        sethi   %hi(fpsave_catch), %l5
509
        or      %l5, %lo(fpsave_catch), %l5
510
        wr      %l0, 0x0, %psr
511
        WRITE_PAUSE
512
        jmp     %l5
513
         rett   %l5 + 4
514
 
515
2:
516
        SAVE_ALL
517
        ENTER_SYSCALL
518
 
519
        wr      %l0, PSR_ET, %psr               ! re-enable traps
520
        WRITE_PAUSE
521
 
522
        add     %sp, REGWIN_SZ, %o0
523
        mov     %l1, %o1
524
        mov     %l2, %o2
525
        call    C_LABEL(do_fpe_trap)
526
         mov    %l0, %o3
527
 
528
        RESTORE_ALL
529
 
530
        /* This routine handles Tag Overflow Exceptions. */
531
        .align  4
532
        .globl  do_tag_overflow
533
do_tag_overflow:
534
        SAVE_ALL
535
        ENTER_SYSCALL
536
 
537
        wr      %l0, PSR_ET, %psr               ! re-enable traps
538
        WRITE_PAUSE
539
 
540
        add     %sp, REGWIN_SZ, %o0
541
        mov     %l1, %o1
542
        mov     %l2, %o2
543
        call    C_LABEL(handle_tag_overflow)
544
         mov    %l0, %o3
545
 
546
        RESTORE_ALL
547
 
548
        /* This routine handles Watchpoint Exceptions. */
549
        .align  4
550
        .globl  do_watchpoint
551
do_watchpoint:
552
        SAVE_ALL
553
        ENTER_SYSCALL
554
 
555
        wr      %l0, PSR_ET, %psr               ! re-enable traps
556
        WRITE_PAUSE
557
 
558
        add     %sp, REGWIN_SZ, %o0
559
        mov     %l1, %o1
560
        mov     %l2, %o2
561
        call    C_LABEL(handle_watchpoint)
562
         mov    %l0, %o3
563
 
564
        RESTORE_ALL
565
 
566
        /* This routine handles Register Access Exceptions. */
567
        .align  4
568
        .globl  do_reg_access
569
do_reg_access:
570
        SAVE_ALL
571
        ENTER_SYSCALL
572
 
573
        wr      %l0, PSR_ET, %psr               ! re-enable traps
574
        WRITE_PAUSE
575
 
576
        add     %sp, REGWIN_SZ, %o0
577
        mov     %l1, %o1
578
        mov     %l2, %o2
579
        call    C_LABEL(handle_reg_access)
580
         mov    %l0, %o3
581
 
582
        RESTORE_ALL
583
 
584
        /* This routine handles Co-Processor Disabled Exceptions. */
585
        .align  4
586
        .globl  do_cp_disabled
587
do_cp_disabled:
588
        SAVE_ALL
589
        ENTER_SYSCALL
590
 
591
        wr      %l0, PSR_ET, %psr               ! re-enable traps
592
        WRITE_PAUSE
593
 
594
        add     %sp, REGWIN_SZ, %o0
595
        mov     %l1, %o1
596
        mov     %l2, %o2
597
        call    C_LABEL(handle_cp_disabled)
598
         mov    %l0, %o3
599
 
600
        RESTORE_ALL
601
 
602
        /* This routine handles Unimplemented FLUSH Exceptions. */
603
        .align  4
604
        .globl  do_bad_flush
605
do_bad_flush:
606
        SAVE_ALL
607
        ENTER_SYSCALL
608
 
609
        wr      %l0, PSR_ET, %psr               ! re-enable traps
610
        WRITE_PAUSE
611
 
612
        add     %sp, REGWIN_SZ, %o0
613
        mov     %l1, %o1
614
        mov     %l2, %o2
615
        call    C_LABEL(handle_bad_flush)
616
         mov    %l0, %o3
617
 
618
        RESTORE_ALL
619
 
620
        /* This routine handles Co-Processor Exceptions. */
621
        .align  4
622
        .globl  do_cp_exception
623
do_cp_exception:
624
        SAVE_ALL
625
        ENTER_SYSCALL
626
 
627
        wr      %l0, PSR_ET, %psr               ! re-enable traps
628
        WRITE_PAUSE
629
 
630
        add     %sp, REGWIN_SZ, %o0
631
        mov     %l1, %o1
632
        mov     %l2, %o2
633
        call    C_LABEL(handle_cp_exception)
634
         mov    %l0, %o3
635
 
636
        RESTORE_ALL
637
 
638
        /* This routine handles Hardware Divide By Zero Exceptions. */
639
        .align  4
640
        .globl  do_hw_divzero
641
do_hw_divzero:
642
        SAVE_ALL
643
        ENTER_SYSCALL
644
 
645
        wr      %l0, PSR_ET, %psr               ! re-enable traps
646
        WRITE_PAUSE
647
 
648
        add     %sp, REGWIN_SZ, %o0
649
        mov     %l1, %o1
650
        mov     %l2, %o2
651
        call    C_LABEL(handle_hw_divzero)
652
         mov    %l0, %o3
653
 
654
        RESTORE_ALL
655
 
656
        .align  4
657
        .globl  do_flush_windows
658
do_flush_windows:
659
        SAVE_ALL
660
        ENTER_SYSCALL
661
 
662
        wr      %l0, PSR_ET, %psr
663
        WRITE_PAUSE
664
 
665
        andcc   %l0, PSR_PS, %g0
666
        bne     dfw_kernel
667
         nop
668
 
669
        call    C_LABEL(flush_user_windows)
670
         nop
671
 
672
        /* Advance over the trap instruction. */
673
        ld      [%sp + REGWIN_SZ + PT_NPC], %l1
674
        add     %l1, 0x4, %l2
675
        st      %l1, [%sp + REGWIN_SZ + PT_PC]
676
        st      %l2, [%sp + REGWIN_SZ + PT_NPC]
677
 
678
        RESTORE_ALL
679
 
680
        /* We get these for debugging routines using __builtin_return_address() */
681
dfw_kernel:
682
        FLUSH_ALL_KERNEL_WINDOWS
683
 
684
        /* Advance over the trap instruction. */
685
        ld      [%sp + REGWIN_SZ + PT_NPC], %l1
686
        add     %l1, 0x4, %l2
687
        st      %l1, [%sp + REGWIN_SZ + PT_PC]
688
        st      %l2, [%sp + REGWIN_SZ + PT_NPC]
689
 
690
        RESTORE_ALL
691
 
692
        /* The getcc software trap.  The user wants the condition codes from
693
         * the %psr in register %g1.
694
         */
695
 
696
        .align  4
697
        .globl  getcc_trap_handler
698
getcc_trap_handler:
699
        srl     %l0, 20, %g1    ! give user
700
        and     %g1, 0xf, %g1   ! only ICC bits in %psr
701
        jmp     %l2             ! advance over trap instruction
702
        rett    %l2 + 0x4       ! like this...
703
 
704
        /* The setcc software trap.  The user has condition codes in %g1
705
         * that it would like placed in the %psr.  Be careful not to flip
706
         * any unintentional bits!
707
         */
708
 
709
        .align  4
710
        .globl  setcc_trap_handler
711
setcc_trap_handler:
712
        sll     %g1, 0x14, %l4
713
        set     PSR_ICC, %l5
714
        andn    %l0, %l5, %l0   ! clear ICC bits in current %psr
715
        and     %l4, %l5, %l4   ! clear non-ICC bits in user value
716
        or      %l4, %l0, %l4   ! or them in... mix mix mix
717
 
718
        wr      %l4, 0x0, %psr  ! set new %psr
719
        WRITE_PAUSE             ! TI scumbags...
720
 
721
        jmp     %l2             ! advance over trap instruction
722
        rett    %l2 + 0x4       ! like this...
723
 
724
        .align  4
725
        .globl  linux_trap_nmi_sun4c
726
linux_trap_nmi_sun4c:
727
        SAVE_ALL
728
        ENTER_SYSCALL
729
 
730
        /* Ugh, we need to clear the IRQ line.  This is now
731
         * a very sun4c specific trap handler...
732
         */
733
        sethi   %hi(C_LABEL(interrupt_enable)), %l5
734
        ld      [%l5 + %lo(C_LABEL(interrupt_enable))], %l5
735
        ldub    [%l5], %l6
736
        andn    %l6, INTS_ENAB, %l6
737
        stb     %l6, [%l5]
738
 
739
        /* Now it is safe to re-enable traps without recursion. */
740
        or      %l0, PSR_PIL, %l0
741
        wr      %l0, PSR_ET, %psr
742
        WRITE_PAUSE
743
 
744
        /* Now call the c-code with the pt_regs frame ptr and the
745
         * memory error registers as arguments.  The ordering chosen
746
         * here is due to unlatching semantics.
747
         */
748
        sethi   %hi(AC_SYNC_ERR), %o0
749
        add     %o0, 0x4, %o0
750
        lda     [%o0] ASI_CONTROL, %o2  ! sync vaddr
751
        sub     %o0, 0x4, %o0
752
        lda     [%o0] ASI_CONTROL, %o1  ! sync error
753
        add     %o0, 0xc, %o0
754
        lda     [%o0] ASI_CONTROL, %o4  ! async vaddr
755
        sub     %o0, 0x4, %o0
756
        lda     [%o0] ASI_CONTROL, %o3  ! async error
757
        call    C_LABEL(sparc_lvl15_nmi)
758
         add    %sp, REGWIN_SZ, %o0
759
 
760
        RESTORE_ALL
761
 
762
#ifdef __SMP__
763
 
764
        .align  4
765
        .globl  linux_trap_ipi9_sun4m
766
linux_trap_ipi9_sun4m:
767
        sethi   %hi(0x02000000), %o2
768
        GET_PROCESSOR_MID(o0, o1)
769
        set     C_LABEL(sun4m_interrupts), %l5
770
        ld      [%l5], %o5
771
        sll     %o0, 12, %o0
772
        add     %o5, %o0, %o5
773
        st      %o2, [%o5 + 4]
774
        WRITE_PAUSE
775
 
776
        ld      [%o5], %g0
777
        WRITE_PAUSE
778
 
779
        /* IRQ's off else we deadlock. */
780
        or      %l0, PSR_PIL, %l4
781
        wr      %l4, 0x0, %psr
782
        WRITE_PAUSE
783
 
784
        wr      %l4, PSR_ET, %psr
785
        WRITE_PAUSE
786
 
787
        call    C_LABEL(smp_message_irq)
788
         nop
789
 
790
        RESTORE_ALL_FASTIRQ
791
 
792
        .align  4
793
        .globl  linux_trap_ipi13_sun4m
794
linux_trap_ipi13_sun4m:
795
        /* NOTE: real_irq_entry saved state and grabbed klock already. */
796
 
797
        /* start atomic operation with respect to software interrupts */
798
        sethi   %hi(C_LABEL(intr_count)), %l4
799
        ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
800
        add     %l5, 0x1, %l5
801
        st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
802
 
803
        sethi   %hi(0x20000000), %o2
804
        GET_PROCESSOR_MID(o0, o1)
805
        set     C_LABEL(sun4m_interrupts), %l5
806
        ld      [%l5], %o5
807
        sll     %o0, 12, %o0
808
        add     %o5, %o0, %o5
809
        st      %o2, [%o5 + 4]
810
        WRITE_PAUSE
811
 
812
        ld      [%o5], %g0
813
        WRITE_PAUSE
814
 
815
        /* IRQ's off else we deadlock. */
816
        or      %l0, PSR_PIL, %l4
817
        wr      %l4, 0x0, %psr
818
        WRITE_PAUSE
819
 
820
        wr      %l4, PSR_ET, %psr
821
        WRITE_PAUSE
822
 
823
        call    C_LABEL(smp_reschedule_irq)
824
         nop
825
 
826
        sethi   %hi(C_LABEL(intr_count)), %l4
827
        ld      [%l4 + %lo(C_LABEL(intr_count))], %l5
828
        sub     %l5, 0x1, %l5
829
        st      %l5, [%l4 + %lo(C_LABEL(intr_count))]
830
 
831
        LEAVE_IRQ
832
        RESTORE_ALL
833
 
834
        .align  4
835
        .globl  linux_trap_ipi15_sun4m
836
linux_trap_ipi15_sun4m:
837
        SAVE_ALL
838
 
839
        /* First check for hard NMI memory error. */
840
        sethi   %hi(0xf0000000), %o2
841
        set     C_LABEL(sun4m_interrupts), %l5
842
        set     0x4000, %o3
843
        ld      [%l5], %l5
844
        add     %l5, %o3, %l5
845
        ld      [%l5], %l6
846
        andcc   %o2, %l6, %o2
847
        be      1f
848
         nop
849
 
850
        /* Asynchronous fault, why you little ?!#&%@... */
851
        sethi   %hi(0x80000000), %o2
852
        st      %o2, [%l5 + 0xc]
853
        WRITE_PAUSE
854
        ld      [%l5], %g0
855
        WRITE_PAUSE
856
 
857
        /* All interrupts are off... now safe to enable traps
858
         * and call C-code.
859
         */
860
        or      %l0, PSR_PIL, %l4       ! I am very paranoid...
861
        wr      %l4, 0x0, %psr
862
        WRITE_PAUSE
863
        wr      %l4, PSR_ET, %psr
864
        WRITE_PAUSE
865
        call    C_LABEL(sun4m_nmi)
866
         nop
867
 
868
        sethi   %hi(0x80000000), %o2
869
        st      %o2, [%l5 + 0x8]
870
        WRITE_PAUSE
871
        ld      [%l5], %g0
872
        WRITE_PAUSE
873
 
874
        RESTORE_ALL_FASTIRQ
875
 
876
1:
877
        sethi   %hi(0x80000000), %o2
878
        GET_PROCESSOR_MID(o0, o1)
879
        set     C_LABEL(sun4m_interrupts), %l5
880
        ld      [%l5], %o5
881
        sll     %o0, 12, %o0
882
        add     %o5, %o0, %o5
883
        st      %o2, [%o5 + 4]
884
        WRITE_PAUSE
885
 
886
        ld      [%o5], %g0
887
        WRITE_PAUSE
888
 
889
        /* IRQ's off else we deadlock. */
890
        or      %l0, PSR_PIL, %l4
891
        wr      %l4, 0x0, %psr
892
        WRITE_PAUSE
893
 
894
        wr      %l4, PSR_ET, %psr
895
        WRITE_PAUSE
896
 
897
        call    C_LABEL(smp_message_irq)
898
         nop
899
 
900
        RESTORE_ALL_FASTIRQ
901
 
902
#endif
903
 
904
        .align  4
905
        .globl  sun4c_fault
906
sun4c_fault:
907
        SAVE_ALL
908
        ENTER_SYSCALL
909
 
910
        /* XXX This needs to be scheduled better */
911
        sethi   %hi(AC_SYNC_ERR), %l4
912
        add     %l4, 0x4, %l5           ! AC_SYNC_VA in %l5
913
        lda     [%l5] ASI_CONTROL, %o3          /* Address */
914
        lda     [%l4] ASI_CONTROL, %l6
915
        srl     %l6, 15, %l6
916
        and     %l6, 1, %o2     /* Write? */
917
 
918
        wr      %l0, PSR_ET, %psr
919
        WRITE_PAUSE
920
 
921
        mov     %l7, %o1                        /* Text fault? */
922
        call    C_LABEL(do_sparc_fault)
923
         add    %sp, REGWIN_SZ, %o0             /* pt_regs */
924
 
925
        RESTORE_ALL
926
 
927
        .align  4
928
        .globl  C_LABEL(srmmu_fault)
929
C_LABEL(srmmu_fault):
930
        mov     0x400, %l5
931
        mov     0x300, %l4
932
 
933
        lda     [%l5] ASI_M_MMUREGS, %l6        ! read sfar first
934
        lda     [%l4] ASI_M_MMUREGS, %l5        ! read sfsr last
935
 
936
        andn    %l6, 0xfff, %l6
937
        srl     %l5, 6, %l5                     ! and encode all info into l7
938
 
939
        and     %l5, 2, %l5
940
        or      %l5, %l6, %l6
941
 
942
        or      %l6, %l7, %l7                   ! l7 = [addr,write,txtfault]
943
 
944
        SAVE_ALL
945
        ENTER_SYSCALL
946
 
947
        mov     %l7, %o1
948
        mov     %l7, %o2
949
        and     %o1, 1, %o1             ! arg2 = text_faultp
950
        mov     %l7, %o3
951
        and     %o2, 2, %o2             ! arg3 = writep
952
        andn    %o3, 0xfff, %o3         ! arg4 = faulting address
953
 
954
        wr      %l0, PSR_ET, %psr
955
        WRITE_PAUSE
956
 
957
        call    C_LABEL(do_sparc_fault)
958
         add    %sp, REGWIN_SZ, %o0     ! arg1 = pt_regs ptr
959
 
960
        RESTORE_ALL
961
 
962
        /* SunOS uses syscall zero as the 'indirect syscall' it looks
963
         * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
964
         * This is complete brain damage.
965
         */
966
        .globl  C_LABEL(sunos_indir)
967
C_LABEL(sunos_indir):
968
        ld      [%sp + REGWIN_SZ + PT_I0], %g1
969
        cmp     %g1, NR_SYSCALLS
970
        blu,a   1f
971
         sll    %g1, 0x2, %g1
972
 
973
        set     C_LABEL(sunos_nosys), %l6
974
        b       2f
975
         nop
976
 
977
1:
978
        set     C_LABEL(sunos_sys_table), %l7
979
        ld      [%l7 + %g1], %l6
980
 
981
2:
982
        ld      [%sp + REGWIN_SZ + PT_I1], %o0
983
        ld      [%sp + REGWIN_SZ + PT_I2], %o1
984
        ld      [%sp + REGWIN_SZ + PT_I3], %o2
985
        mov     %o7, %l5
986
        ld      [%sp + REGWIN_SZ + PT_I4], %o3
987
        call    %l6
988
         ld     [%sp + REGWIN_SZ + PT_I5], %o4
989
 
990
        jmp     %l5 + 0x8               /* so stupid... */
991
         nop
992
 
993
        /* Note how we really return to ret_syscall because we share the
994
         * register window with our caller.
995
         */
996
 
997
        .align 4
998
        .globl  C_LABEL(sys_ptrace)
999
C_LABEL(sys_ptrace):
1000
        call    C_LABEL(do_ptrace)
1001
         add    %sp, REGWIN_SZ, %o0
1002
 
1003
        LOAD_CURRENT(l4, l5)
1004
        ld      [%l4 + 0x14], %l5
1005
        andcc   %l5, 0x20, %g0
1006
        be      1f
1007
         nop
1008
 
1009
        call    C_LABEL(syscall_trace)
1010
         nop
1011
 
1012
1:
1013
        RESTORE_ALL
1014
 
1015
        .align  4
1016
        .globl  C_LABEL(sys_execve)
1017
C_LABEL(sys_execve):
1018
        mov     %o7, %l5
1019
        call    C_LABEL(sparc_execve)
1020
         add    %sp, REGWIN_SZ, %o0             ! pt_regs *regs arg
1021
 
1022
        jmp     %l5 + 0x8
1023
         nop
1024
 
1025
        .align  4
1026
        .globl  C_LABEL(sys_pipe)
1027
C_LABEL(sys_pipe):
1028
        mov     %o7, %l5
1029
 
1030
        call    C_LABEL(sparc_pipe)
1031
         add    %sp, REGWIN_SZ, %o0             ! pt_regs *regs arg
1032
 
1033
        jmp     %l5 + 0x8
1034
         nop
1035
 
1036
        .align  4
1037
        .globl  C_LABEL(sys_sigpause)
1038
C_LABEL(sys_sigpause):
1039
        ld      [%sp + REGWIN_SZ + PT_I0], %o0
1040
        call    C_LABEL(do_sigpause)
1041
         add    %sp, REGWIN_SZ, %o1
1042
 
1043
        LOAD_CURRENT(l4, l5)
1044
        ld      [%l4 + 0x14], %l5
1045
        andcc   %l5, 0x20, %g0
1046
        be      1f
1047
         nop
1048
 
1049
        call    C_LABEL(syscall_trace)
1050
         nop
1051
 
1052
1:
1053
        /* We are returning to a signal handler. */
1054
        RESTORE_ALL
1055
 
1056
        .align  4
1057
        .globl  C_LABEL(sys_sigsuspend)
1058
C_LABEL(sys_sigsuspend):
1059
        call    C_LABEL(do_sigsuspend)
1060
         add    %sp, REGWIN_SZ, %o0
1061
 
1062
        LOAD_CURRENT(l4, l5)
1063
        ld      [%l4 + 0x14], %l5
1064
        andcc   %l5, 0x20, %g0
1065
        be      1f
1066
         nop
1067
 
1068
        call    C_LABEL(syscall_trace)
1069
         nop
1070
 
1071
1:
1072
        /* We are returning to a signal handler. */
1073
        RESTORE_ALL
1074
 
1075
        .align  4
1076
        .globl  C_LABEL(sys_sigreturn)
1077
C_LABEL(sys_sigreturn):
1078
        call    C_LABEL(do_sigreturn)
1079
         add    %sp, REGWIN_SZ, %o0
1080
 
1081
        LOAD_CURRENT(l4, l5)
1082
        ld      [%l4 + 0x14], %l5
1083
        andcc   %l5, 0x20, %g0
1084
        be      1f
1085
         nop
1086
 
1087
        call    C_LABEL(syscall_trace)
1088
         nop
1089
 
1090
1:
1091
        /* We don't want to muck with user registers like a
1092
         * normal syscall, just return.
1093
         */
1094
        RESTORE_ALL
1095
 
1096
        /* Now that we have a real sys_clone, sys_fork() is
1097
         * implemented in terms of it.  Our _real_ implementation
1098
         * of SunOS vfork() will use sys_clone() instead.
1099
         */
1100
        .align  4
1101
        .globl  C_LABEL(sys_fork), C_LABEL(sys_vfork)
1102
C_LABEL(sys_vfork):
1103
C_LABEL(sys_fork):
1104
        mov     %o7, %l5
1105
 
1106
        /* Save the kernel state as of now. */
1107
        FLUSH_ALL_KERNEL_WINDOWS;
1108
        STORE_WINDOW(sp)
1109
        LOAD_CURRENT(g6, g5)
1110
        rd      %psr, %g4
1111
        rd      %wim, %g5
1112
        std     %g4, [%g6 + THREAD_FORK_KPSR]
1113
 
1114
        mov     SIGCHLD, %o0                    ! arg0: clone flags
1115
        ld      [%sp + REGWIN_SZ + PT_FP], %o1  ! arg1: usp
1116
        call    C_LABEL(do_fork)
1117
         add    %sp, REGWIN_SZ, %o2             ! arg2: pt_regs ptr
1118
 
1119
        jmp     %l5 + 0x8
1120
         nop
1121
 
1122
        /* Whee, kernel threads! */
1123
        .globl  C_LABEL(sys_clone)
1124
C_LABEL(sys_clone):
1125
        mov     %o7, %l5
1126
 
1127
        /* Save the kernel state as of now. */
1128
        FLUSH_ALL_KERNEL_WINDOWS;
1129
        STORE_WINDOW(sp)
1130
        LOAD_CURRENT(g6, g5)
1131
        rd      %psr, %g4
1132
        rd      %wim, %g5
1133
        std     %g4, [%g6 + THREAD_FORK_KPSR]
1134
 
1135
        ldd     [%sp + REGWIN_SZ + PT_I0], %o0  ! arg0,1: flags,usp
1136
        cmp     %o1, 0x0                        ! Is new_usp NULL?
1137
        be,a    1f
1138
         ld     [%sp + REGWIN_SZ + PT_FP], %o1  ! yes, use current usp
1139
1:
1140
        call    C_LABEL(do_fork)
1141
         add    %sp, REGWIN_SZ, %o2             ! arg2: pt_regs ptr
1142
 
1143
        jmp     %l5 + 0x8
1144
         nop
1145
 
1146
        /* Linux native and SunOS system calls enter here... */
1147
        .align  4
1148
        .globl  linux_sparc_syscall
1149
linux_sparc_syscall:
1150
        /* While we are here trying to optimize our lives
1151
         * away, handle the easy bogus cases like a
1152
         * ni_syscall or sysnum > NR_SYSCALLS etc.
1153
         * In the cases where we cannot optimize the
1154
         * call inline we don't really lose anything
1155
         * performance wise because we are doing here
1156
         * things which we did anyway in the original
1157
         * routine.  The only added complexity is a
1158
         * bit test, compare, and branch to decide
1159
         * if we need to save process state or not.
1160
         */
1161
 
1162
        /* XXX TODO: When we have ptrace working test
1163
         * XXX       test for PF_TRACESYS in task flags.
1164
         */
1165
 
1166
        /* Direct access to user regs, must faster. */
1167
        cmp     %g1, NR_SYSCALLS
1168
        blu,a   1f
1169
         sll    %g1, 2, %l4
1170
 
1171
        set     C_LABEL(sys_ni_syscall), %l7
1172
        b       syscall_is_too_hard
1173
         nop
1174
 
1175
1:
1176
        ld      [%l7 + %l4], %l7
1177
 
1178
        /* If bit-1 is set, this is a "fast" syscall.
1179
         * This is the _complete_ overhead of this optimization,
1180
         * and we save ourselves a load, so it evens out to nothing.
1181
         */
1182
        andcc   %l7, 0x1, %g0
1183
        be      syscall_is_too_hard
1184
         andn   %l7, 0x1, %l7
1185
 
1186
        jmpl    %l7, %g0
1187
         nop
1188
 
1189
        .globl  syscall_is_too_hard
1190
syscall_is_too_hard:
1191
        rd      %wim, %l3
1192
        SAVE_ALL
1193
        ENTER_SYSCALL
1194
 
1195
        wr      %l0, PSR_ET, %psr
1196
        WRITE_PAUSE
1197
 
1198
        LOAD_CURRENT(l4, l5)
1199
        ld      [%l4 + 0x14], %l5
1200
        andcc   %l5, 0x20, %g0
1201
        be      2f
1202
         nop
1203
 
1204
        call    C_LABEL(syscall_trace)
1205
         nop
1206
 
1207
2:
1208
        ldd     [%sp + REGWIN_SZ + PT_I0], %o0
1209
        st      %o0, [%sp + REGWIN_SZ + PT_G0]  ! for restarting syscalls
1210
        ldd     [%sp + REGWIN_SZ + PT_I2], %o2
1211
        call    %l7
1212
         ldd    [%sp + REGWIN_SZ + PT_I4], %o4
1213
 
1214
        st      %o0, [%sp + REGWIN_SZ + PT_I0]
1215
 
1216
        .globl  C_LABEL(ret_sys_call)
1217
C_LABEL(ret_sys_call):
1218
        ld      [%sp + REGWIN_SZ + PT_I0], %o0
1219
        set     PSR_C, %l6
1220
        cmp     %o0, -ENOIOCTLCMD
1221
        bgeu    1f
1222
         ld     [%sp + REGWIN_SZ + PT_PSR], %l5
1223
 
1224
        /* System call success, clear Carry condition code. */
1225
        andn    %l5, %l6, %l5
1226
        b       2f
1227
         st     %l5, [%sp + REGWIN_SZ + PT_PSR]
1228
 
1229
1:
1230
        /* System call failure, set Carry condition code.
1231
         * Also, get abs(errno) to return to the process.
1232
         */
1233
        sub     %g0, %o0, %o0
1234
        st      %o0, [%sp + REGWIN_SZ + PT_I0]
1235
        or      %l5, %l6, %l5
1236
        st      %l5, [%sp + REGWIN_SZ + PT_PSR]
1237
 
1238
2:
1239
        LOAD_CURRENT(l4, l5)
1240
        ld      [%l4 + 0x14], %l5
1241
        andcc   %l5, 0x20, %g0
1242
        be      3f
1243
         nop
1244
 
1245
        call    C_LABEL(syscall_trace)
1246
         nop
1247
 
1248
        /* Advance the pc and npc over the trap instruction. */
1249
3:
1250
        ld      [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc  = npc   */
1251
        add     %l1, 0x4, %l2                   /* npc = npc+4 */
1252
        st      %l1, [%sp + REGWIN_SZ + PT_PC]
1253
        st      %l2, [%sp + REGWIN_SZ + PT_NPC]
1254
 
1255
        RESTORE_ALL
1256
 
1257
        /* Solaris system calls enter here... */
1258
        .align  4
1259
        .globl  solaris_syscall
1260
solaris_syscall:
1261
        /* While we are here trying to optimize our lives
1262
         * away, handle the easy bogus cases like a
1263
         * ni_syscall or sysnum > NR_SYSCALLS etc.
1264
         * In the cases where we cannot optimize the
1265
         * call inline we don't really lose anything
1266
         * performance wise because we are doing here
1267
         * things which we did anyway in the original
1268
         * routine.  The only added complexity is a
1269
         * bit test, compare, and branch to decide
1270
         * if we need to save process state or not.
1271
         */
1272
 
1273
        /* XXX TODO: When we have ptrace working test
1274
         * XXX       test for PF_TRACESYS in task flags.
1275
         */
1276
 
1277
        /* Direct access to user regs, must faster. */
1278
        cmp     %g1, NR_SYSCALLS
1279
        blu,a   1f
1280
         sll    %g1, 2, %l4
1281
 
1282
        set     C_LABEL(sys_ni_syscall), %l7
1283
        b       solaris_is_too_hard
1284
         nop
1285
 
1286
1:
1287
        ld      [%l7 + %l4], %l7
1288
 
1289
        /* If bit-1 is set, this is a "fast" syscall.
1290
         * This is the _complete_ overhead of this optimization,
1291
         * and we save ourselves a load, so it evens out to nothing.
1292
         */
1293
        andcc   %l7, 0x1, %g0
1294
        be      solaris_is_too_hard
1295
         andn   %l7, 0x1, %l7
1296
 
1297
        jmpl    %l7, %g0
1298
         nop
1299
 
1300
        .globl  solaris_is_too_hard
1301
solaris_is_too_hard:
1302
        rd      %wim, %l3
1303
        SAVE_ALL
1304
        ENTER_SYSCALL
1305
 
1306
        wr      %l0, PSR_ET, %psr
1307
        WRITE_PAUSE
1308
 
1309
2:
1310
        ldd     [%sp + REGWIN_SZ + PT_I0], %o0
1311
        st      %o0, [%sp + REGWIN_SZ + PT_G0]  ! for restarting syscalls
1312
        ldd     [%sp + REGWIN_SZ + PT_I2], %o2
1313
        call    %l7
1314
         ldd    [%sp + REGWIN_SZ + PT_I4], %o4
1315
 
1316
        st      %o0, [%sp + REGWIN_SZ + PT_I0]
1317
        set     PSR_C, %l6
1318
        cmp     %o0, -ENOIOCTLCMD
1319
        bgeu    1f
1320
         ld     [%sp + REGWIN_SZ + PT_PSR], %l5
1321
 
1322
        /* System call success, clear Carry condition code. */
1323
        andn    %l5, %l6, %l5
1324
        b       2f
1325
         st     %l5, [%sp + REGWIN_SZ + PT_PSR]
1326
 
1327
1:
1328
        /* System call failure, set Carry condition code.
1329
         * Also, get abs(errno) to return to the process.
1330
         */
1331
        sub     %g0, %o0, %o0
1332
        sethi   %hi(C_LABEL(solaris_xlatb_rorl)), %o3
1333
        or      %o3, %lo(C_LABEL(solaris_xlatb_rorl)), %o3
1334
        sll     %o0, 2, %o0
1335
        ld      [%o3 + %o0], %o0
1336
        st      %o0, [%sp + REGWIN_SZ + PT_I0]
1337
        or      %l5, %l6, %l5
1338
        st      %l5, [%sp + REGWIN_SZ + PT_PSR]
1339
 
1340
        /* Advance the pc and npc over the trap instruction. */
1341
2:
1342
        ld      [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc  = npc   */
1343
        add     %l1, 0x4, %l2                   /* npc = npc+4 */
1344
        st      %l1, [%sp + REGWIN_SZ + PT_PC]
1345
        st      %l2, [%sp + REGWIN_SZ + PT_NPC]
1346
 
1347
        RESTORE_ALL
1348
 
1349
        /* {net, open}bsd system calls enter here... */
1350
        .align  4
1351
        .globl  bsd_syscall
1352
bsd_syscall:
1353
        /* While we are here trying to optimize our lives
1354
         * away, handle the easy bogus cases like a
1355
         * ni_syscall or sysnum > NR_SYSCALLS etc.
1356
         * In the cases where we cannot optimize the
1357
         * call inline we don't really lose anything
1358
         * performance wise because we are doing here
1359
         * things which we did anyway in the original
1360
         * routine.  The only added complexity is a
1361
         * bit test, compare, and branch to decide
1362
         * if we need to save process state or not.
1363
         */
1364
 
1365
        /* XXX TODO: When we have ptrace working test
1366
         * XXX       test for PF_TRACESYS in task flags.
1367
         */
1368
 
1369
        /* Direct access to user regs, must faster. */
1370
        cmp     %g1, NR_SYSCALLS
1371
        blu,a   1f
1372
         sll    %g1, 2, %l4
1373
 
1374
        set     C_LABEL(sys_ni_syscall), %l7
1375
        b       bsd_is_too_hard
1376
         nop
1377
 
1378
1:
1379
        ld      [%l7 + %l4], %l7
1380
 
1381
        /* If bit-1 is set, this is a "fast" syscall.
1382
         * This is the _complete_ overhead of this optimization,
1383
         * and we save ourselves a load, so it evens out to nothing.
1384
         */
1385
        andcc   %l7, 0x1, %g0
1386
        be      bsd_is_too_hard
1387
         andn   %l7, 0x1, %l7
1388
 
1389
        jmpl    %l7, %g0
1390
         nop
1391
 
1392
        .globl  bsd_is_too_hard
1393
bsd_is_too_hard:
1394
        rd      %wim, %l3
1395
        SAVE_ALL
1396
        ENTER_SYSCALL
1397
 
1398
        wr      %l0, PSR_ET, %psr
1399
        WRITE_PAUSE
1400
 
1401
2:
1402
        ldd     [%sp + REGWIN_SZ + PT_I0], %o0
1403
        st      %o0, [%sp + REGWIN_SZ + PT_G0]  ! for restarting syscalls
1404
        ldd     [%sp + REGWIN_SZ + PT_I2], %o2
1405
        call    %l7
1406
         ldd    [%sp + REGWIN_SZ + PT_I4], %o4
1407
 
1408
        st      %o0, [%sp + REGWIN_SZ + PT_I0]
1409
        set     PSR_C, %l6
1410
        cmp     %o0, -ENOIOCTLCMD
1411
        bgeu    1f
1412
         ld     [%sp + REGWIN_SZ + PT_PSR], %l5
1413
 
1414
        /* System call success, clear Carry condition code. */
1415
        andn    %l5, %l6, %l5
1416
        b       2f
1417
         st     %l5, [%sp + REGWIN_SZ + PT_PSR]
1418
 
1419
1:
1420
        /* System call failure, set Carry condition code.
1421
         * Also, get abs(errno) to return to the process.
1422
         */
1423
        sub     %g0, %o0, %o0
1424
#if 0 /* XXX todo XXX */
1425
        sethi   %hi(C_LABEL(bsd_xlatb_rorl), %o3
1426
        or      %o3, %lo(C_LABEL(bsd_xlatb_rorl)), %o3
1427
        sll     %o0, 2, %o0
1428
        ld      [%o3 + %o0], %o0
1429
#endif
1430
        st      %o0, [%sp + REGWIN_SZ + PT_I0]
1431
        or      %l5, %l6, %l5
1432
        st      %l5, [%sp + REGWIN_SZ + PT_PSR]
1433
 
1434
        /* Advance the pc and npc over the trap instruction. */
1435
2:
1436
        ld      [%sp + REGWIN_SZ + PT_NPC], %l1 /* pc  = npc   */
1437
        add     %l1, 0x4, %l2                   /* npc = npc+4 */
1438
        st      %l1, [%sp + REGWIN_SZ + PT_PC]
1439
        st      %l2, [%sp + REGWIN_SZ + PT_NPC]
1440
 
1441
        RESTORE_ALL
1442
 
1443
/* Saving and restoring the FPU state is best done from lowlevel code.
1444
 *
1445
 * void fpsave(unsigned long *fpregs, unsigned long *fsr,
1446
 *             void *fpqueue, unsigned long *fpqdepth)
1447
 */
1448
 
1449
        .globl  C_LABEL(fpsave)
1450
C_LABEL(fpsave):
1451
        st      %fsr, [%o1]     ! this can trap on us if fpu is in bogon state
1452
        ld      [%o1], %g1
1453
        set     0x2000, %g4
1454
        andcc   %g1, %g4, %g0
1455
        be      2f
1456
         mov    0, %g2
1457
 
1458
        /* We have an fpqueue to save. */
1459
1:
1460
        std     %fq, [%o2]
1461
fpsave_magic:
1462
        st      %fsr, [%o1]
1463
        ld      [%o1], %g3
1464
        andcc   %g3, %g4, %g0
1465
        add     %g2, 1, %g2
1466
        bne     1b
1467
         add    %o2, 8, %o2
1468
 
1469
2:
1470
        st      %g2, [%o3]
1471
 
1472
        std     %f0, [%o0 + 0x00]
1473
        std     %f2, [%o0 + 0x08]
1474
        std     %f4, [%o0 + 0x10]
1475
        std     %f6, [%o0 + 0x18]
1476
        std     %f8, [%o0 + 0x20]
1477
        std     %f10, [%o0 + 0x28]
1478
        std     %f12, [%o0 + 0x30]
1479
        std     %f14, [%o0 + 0x38]
1480
        std     %f16, [%o0 + 0x40]
1481
        std     %f18, [%o0 + 0x48]
1482
        std     %f20, [%o0 + 0x50]
1483
        std     %f22, [%o0 + 0x58]
1484
        std     %f24, [%o0 + 0x60]
1485
        std     %f26, [%o0 + 0x68]
1486
        std     %f28, [%o0 + 0x70]
1487
        retl
1488
         std    %f30, [%o0 + 0x78]
1489
 
1490
        /* Thanks for Theo Deraadt and the authors of the Sprite/netbsd/openbsd
1491
         * code for pointing out this possible deadlock, while we save state
1492
         * above we could trap on the fsr store so our low level fpu trap
1493
         * code has to know how to deal with this.
1494
         */
1495
fpsave_catch:
1496
        b       fpsave_magic + 4
1497
         st     %fsr, [%o1]
1498
 
1499
fpsave_catch2:
1500
        b       C_LABEL(fpsave) + 4
1501
         st     %fsr, [%o1]
1502
 
1503
        /* void fpload(unsigned long *fpregs, unsigned long *fsr); */
1504
 
1505
        .globl  C_LABEL(fpload)
1506
C_LABEL(fpload):
1507
        ldd     [%o0 + 0x00], %f0
1508
        ldd     [%o0 + 0x08], %f2
1509
        ldd     [%o0 + 0x10], %f4
1510
        ldd     [%o0 + 0x18], %f6
1511
        ldd     [%o0 + 0x20], %f8
1512
        ldd     [%o0 + 0x28], %f10
1513
        ldd     [%o0 + 0x30], %f12
1514
        ldd     [%o0 + 0x38], %f14
1515
        ldd     [%o0 + 0x40], %f16
1516
        ldd     [%o0 + 0x48], %f18
1517
        ldd     [%o0 + 0x50], %f20
1518
        ldd     [%o0 + 0x58], %f22
1519
        ldd     [%o0 + 0x60], %f24
1520
        ldd     [%o0 + 0x68], %f26
1521
        ldd     [%o0 + 0x70], %f28
1522
        ldd     [%o0 + 0x78], %f30
1523
        ld      [%o1], %fsr
1524
        retl
1525
         nop
1526
 
1527
        .globl  C_LABEL(udelay)
1528
C_LABEL(udelay):
1529
        save    %sp, -REGWIN_SZ, %sp
1530
        mov     %i0, %o0
1531
        sethi   %hi(0x10c6), %o1
1532
        call    .umul
1533
         or     %o1, %lo(0x10c6), %o1
1534
#ifndef __SMP__
1535
        sethi   %hi(C_LABEL(loops_per_sec)), %o3
1536
        call    .umul
1537
         ld     [%o3 + %lo(C_LABEL(loops_per_sec))], %o1
1538
#else
1539
        GET_PROCESSOR_OFFSET(o4)
1540
        set     C_LABEL(cpu_data), %o3
1541
        call    .umul
1542
         ld     [%o3 + %o4], %o1
1543
#endif
1544
 
1545
        cmp     %o1, 0x0
1546
1:
1547
        bne     1b
1548
         subcc  %o1, 1, %o1
1549
 
1550
        ret
1551
        restore
1552
 
1553
/* End of entry.S */

powered by: WebSVN 2.1.0

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