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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [i386/] [arch/] [v2_0/] [src/] [vectors.S] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
##=============================================================================
2
##
3
##      vectors.S
4
##
5
##      x86 exception vectors
6
##
7
##=============================================================================
8
#####ECOSGPLCOPYRIGHTBEGIN####
9
## -------------------------------------------
10
## This file is part of eCos, the Embedded Configurable Operating System.
11
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
##
13
## eCos is free software; you can redistribute it and/or modify it under
14
## the terms of the GNU General Public License as published by the Free
15
## Software Foundation; either version 2 or (at your option) any later version.
16
##
17
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
## WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
## FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
## for more details.
21
##
22
## You should have received a copy of the GNU General Public License along
23
## with eCos; if not, write to the Free Software Foundation, Inc.,
24
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
##
26
## As a special exception, if other files instantiate templates or use macros
27
## or inline functions from this file, or you compile this file and link it
28
## with other works to produce a work based on this file, this file does not
29
## by itself cause the resulting work to be covered by the GNU General Public
30
## License. However the source code for this file must still be made available
31
## in accordance with section (3) of the GNU General Public License.
32
##
33
## This exception does not invalidate any other reasons why a work based on
34
## this file might be covered by the GNU General Public License.
35
##
36
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
## at http://sources.redhat.com/ecos/ecos-license/
38
## -------------------------------------------
39
#####ECOSGPLCOPYRIGHTEND####
40
##=============================================================================
41
#######DESCRIPTIONBEGIN####
42
##
43
## Author(s):   jskov
44
## Contributors:jskov
45
## Date:        1999-01-07
46
## Purpose:     x86 exception vectors
47
## Description: This file defines the code placed into the exception
48
##              vectors. It also contains the first level default VSRs
49
##              that save and restore state for both exceptions and
50
##              interrupts.
51
##
52
######DESCRIPTIONEND####
53
##
54
##=============================================================================
55
 
56
 
57
#include 
58
#include 
59
#include CYGBLD_HAL_PLATFORM_H
60
 
61
#ifdef CYGPKG_KERNEL
62
#include 
63
#endif /* CYGPKG_KERNEL */
64
 
65
#include 
66
 
67
#==============================================================================
68
 
69
//    .file   "vectors.S"
70
 
71
#==============================================================================
72
# Real startup code. We jump here from the various reset vectors to set up the
73
# world.
74
 
75
        .text
76
        .globl  _start
77
 
78
_start:
79
        hal_cpu_init
80
        hal_smp_init
81
        hal_diag_init
82
        hal_mmu_init
83
        hal_memc_init
84
        hal_intc_init
85
        hal_cache_init
86
        hal_timer_init
87
 
88
        # Loading the stack pointer seems appropriate now.
89
        # In SMP systems, this may not be the interrupt stack we
90
        # actually need to use for this CPU. We fix that up later.
91
 
92
        movl    $__interrupt_stack, %esp
93
 
94
#if defined(CYG_HAL_STARTUP_FLOPPY) \
95
    || defined(CYG_HAL_STARTUP_ROM) \
96
    || defined(CYG_HAL_STARTUP_GRUB)
97
        # If we are here first, initialize the IDT. RAM startup
98
        # configurations can assume that Redboot has already set
99
        # the IDT up.
100
        hal_idt_init
101
#endif
102
 
103
        hal_mon_init
104
 
105
        # Init FPU
106
        # Do this after the monitor init so that we can plant our
107
        # own FPU unavailable VSR.
108
 
109
        hal_fpu_init            # WARNING: may adjust stack pointer
110
 
111
        # Zero the BSS. If the BSS is not a whole number of words
112
        # long we will write up to 3 extra bytes at the end.
113
        # (This should not be a problem usually).
114
        movl    $__bss_end,%ecx         # ECX = end of BSS
115
        movl    $__bss_start,%edi       # EDI = base of BSS
116
        subl    %edi,%ecx               # ECX = size of BSS
117
        addl    $3,%ecx                 # ECX += sizeof(long)-1
118
        shrl    $2,%ecx                 # ECX >>= 2 = number of words to fill
119
        xorl    %eax,%eax               # EAX = 0 = fill value
120
        rep     stosl                   # Fill it in
121
 
122
#ifdef CYG_HAL_STARTUP_ROM
123
 
124
        # In a ROM booted system, we also need to copy the data section
125
        # out to the RAM.
126
        movl    $__rom_data_start,%esi  # ESI = base of ROM data area
127
        movl    $__ram_data_start,%edi  # EDI = base of RAM data area
128
        movl    $__ram_data_end,%ecx    # ECX = end of data
129
        subl    %edi,%ecx               # ECX = size of data in bytes
130
        shrl    $2,%ecx                 # ECX >>= 2 = number of words to copy
131
        rep     movsl                   # Copy it over
132
 
133
#endif
134
 
135
        .extern hal_variant_init
136
        call    hal_variant_init
137
 
138
        .extern hal_platform_init
139
        call    hal_platform_init
140
 
141
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
142
        // This is here so we can debug the constructors.
143
        .extern initialize_stub
144
        call    initialize_stub
145
#endif
146
 
147
        .extern cyg_hal_invoke_constructors
148
        call    cyg_hal_invoke_constructors
149
 
150
#ifdef CYGPKG_HAL_SMP_SUPPORT
151
 
152
        # Now move SP to actual interrupt stack we will use for this
153
        # processor.
154
        hal_init_istack %esp
155
 
156
#ifndef CYG_HAL_STARTUP_RAM
157
        # Only start other CPUs when we are the original boot executable.
158
        # RAM executables are loaded via RedBoot, so only FLOPPY, GRUB
159
        # and ROM startups count here.
160
 
161
        .extern cyg_hal_smp_cpu_start_all
162
        call cyg_hal_smp_cpu_start_all
163
#endif
164
 
165
#endif
166
 
167
#ifdef CYGDBG_HAL_DEBUG_GDB_INITIAL_BREAK
168
        .extern breakpoint
169
        call breakpoint
170
#endif
171
        .extern cyg_start
172
        call    cyg_start
173
 
174
        # Hmm.  Not expecting to return from cyg_start.
175
1:      hlt
176
        jmp     1b
177
 
178
##-----------------------------------------------------------------------------
179
## SMP entry point
180
 
181
#if defined(CYGPKG_HAL_SMP_SUPPORT)
182
        .extern cyg_hal_smp_startup
183
        .global cyg_hal_smp_start
184
cyg_hal_smp_start:
185
 
186
        # Finalize CPU init?
187
        # Interrupts?
188
 
189
#       hal_cpu_init
190
#       hal_intc_init
191
 
192
        hal_init_istack %esp
193
 
194
        # Init flags register
195
        pushl   $0
196
        popfl
197
 
198
        hal_fpu_cpu_init
199
 
200
        call    cyg_hal_smp_startup
201
1:
202
        jmp     1b
203
 
204
#ifdef CYG_HAL_STARTUP_RAM
205
        .align  4, 0xFF
206
gdtStart:
207
        /* Selector 0x00 == invalid. */
208
        .word   0x0000
209
        .word   0x0000
210
        .byte   0x00
211
        .byte   0x00
212
        .byte   0x00
213
        .byte   0x00
214
 
215
        /* Selector 0x08 == code. */
216
        .word   0xFFFF
217
        .word   0x0000
218
        .byte   0x00
219
        .byte   0x9B
220
        .byte   0xCF
221
        .byte   0x00
222
 
223
        /* Selector 0x10 == data. */
224
        .word   0xFFFF
225
        .word   0x0000
226
        .byte   0x00
227
        .byte   0x93
228
        .byte   0xCF
229
        .byte   0x00
230
 
231
        /* Selector 0x18 == shorter code: faults any code
232
         * access 0xF0000000-0xFFFFFFFF.
233
         */
234
        .word   0xFFFF
235
        .word   0x0000
236
        .byte   0x00
237
        .byte   0x9B
238
        .byte   0xC7
239
        .byte   0x00
240
 
241
        /* Selector 0x20 == data; faults any access 0xF0000000-0xFFFFFFFF. */
242
        .word   0xFFFF
243
        .word   0x0000
244
        .byte   0x00
245
        .byte   0x93
246
        .byte   0xC7
247
        .byte   0x00
248
 
249
        .align  4, 0xFF
250
gdtEnd:
251
#endif  // CYG_HAL_STARTUP_RAM
252
 
253
##-----------------------------------------------------------------------------
254
## Slave processor startup code
255
## This code is copied into low RAM, at 0x2000 and is the destination of the
256
## startup interrupt that is sent to get the slaves running.
257
 
258
        .data
259
        .code16
260
 
261
        .global cyg_hal_slave_trampoline
262
        .global cyg_hal_slave_trampoline_end
263
cyg_hal_slave_trampoline:
264
slave_base = .
265
        cld                             /* always count up. */
266
        cli                             /* disable interrupts */
267
 
268
        # Load up selector registers
269
        # Set DS == CS
270
        movw    %cs,%ax
271
        movw    %ax,%ds
272
 
273
        # load GDTR
274
        lgdt    slave_gdt - slave_base
275
        lidt    slave_idt - slave_base
276
 
277
        /* Switch to protected mode. */
278
        movl    %cr0,%eax
279
        orb     $1, %al
280
        movl    %eax,%cr0
281
        ljmp    $8, $3f-slave_base+0x2000
282
 
283
        hlt
284
 
285
        .align  4, 0xFF
286
slave_gdt:
287
        .word   gdtEnd - gdtStart
288
#       .word   39
289
        .long   gdtStart
290
 
291
        .align  4, 0xFF
292
slave_idt:
293
        .extern idtStart
294
        .word   0x07FF          # space for 256 entries
295
        .long   idtStart
296
 
297
        .code32
298
 
299
3:
300
 
301
        # Load up selector registers
302
        movw    $0x10, %ax
303
        movw    %ax, %ds
304
        movw    %ax, %ss
305
        movw    %ax, %es
306
        movw    %ax, %fs
307
        movw    %ax, %gs
308
 
309
        # Go to real HAL entry point
310
        movl    $cyg_hal_smp_start,%eax
311
        jmp     *%eax
312
 
313
cyg_hal_slave_trampoline_end:
314
 
315
        .text
316
 
317
#endif // defined(CYGPKG_HAL_SMP_SUPPORT)
318
 
319
#==============================================================================
320
# Default exception VSR
321
 
322
        .align  4, 0xCC
323
        .globl  __default_exception_vsr
324
__default_exception_vsr:
325
 
326
        ## We enter here with the CPU state still in the registers and:
327
        ## 12(%esp)     EFLAGS pushed by hardware
328
        ##  8(%esp)     CS pushed by hardware
329
        ##  4(%esp)     PC pushed by hardware
330
        ##  0(%esp)     vector number pushed by trampoline
331
 
332
        pusha                   # save all registers
333
 
334
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
335
        mov     %esp,%ebp                 # save SP
336
        cmpl    $__stub_stack_base,%esp   # compare SP with stub stack base
337
        jb      1f                        # if sp < istack base, switch
338
        cmpl    $__stub_stack,%esp        # compare SP with stub stack top
339
        jbe     2f                        # if sp < stack top, dont switch
340
1:
341
        movl    $__stub_stack,%esp        # move to stub stack
342
 
343
        ## We switched stacks with previous ESP in EBP
344
        ## 44(%ebp)     EFLAGS pushed by hardware
345
        ## 40(%ebp)     CS pushed by hardware
346
        ## 36(%ebp)     PC pushed by hardware
347
        ## 32(%ebp)     vector number pushed by trampoline
348
        ## 28(%ebp)     EAX
349
        ## 24(%ebp)     ECX
350
        ## 20(%ebp)     EDX
351
        ## 16(%ebp)     EBX
352
        ## 12(%ebp)     (ESP - 16)
353
        ##  8(%ebp)     EBP
354
        ##  4(%ebp)     ESI
355
        ##  0(%ebp)     EDI
356
 
357
        pushl   44(%ebp)                # copy EFLAGS from original stack
358
        pushl   40(%ebp)                # copy CS
359
        pushl   36(%ebp)                # copy PC
360
        pushl   32(%ebp)                # copy vector number
361
        pusha
362
        movl    8(%ebp),%eax            # copy EBP
363
        movl    %eax,8(%esp)
364
        movl    12(%ebp),%eax           # copy ESP
365
        movl    %eax,12(%esp)
366
2:
367
#endif
368
        hal_fpu_push_exc        # save FPU state
369
 
370
        mov     %esp,%edi       # save state pointer in EDI
371
 
372
        # adjust ESP by 16 for the state stored before the pusha
373
        add     $16,i386reg_esp(%edi)
374
 
375
#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) && defined(CYGPKG_HAL_SMP_SUPPORT)
376
 
377
        .extern cyg_hal_smp_cpu_sync
378
        .extern cyg_hal_smp_cpu_sync_flag
379
        .extern cyg_hal_smp_vsr_sync_flag
380
 
381
        # An SMP ROM monitor needs to suspend all other CPUs when
382
        # taking an exception.
383
 
384
1:
385
        lock btsl $0,cyg_hal_smp_vsr_sync_flag  # test serialization bit
386
        jnc     9f                              # if it was zero we are first here
387
 
388
        # Some other CPU is already handling an exception. We need to spin until
389
        # released.
390
 
391
        hal_smp_cpu %eax                # get CPU index
392
        movl    $cyg_hal_smp_cpu_sync,%ebx
393
        movl    $cyg_hal_smp_cpu_sync_flag,%ecx
394
        lock incl 0(%ecx,%eax,4)        # inc cpu sync flag
395
2:
396
        cmpl    $0,0(%ebx,%eax,4)       # test sync location
397
        je      2b                      # loop while value is zero
398
 
399
        lock decl 0(%ecx,%eax,4)        # dec cpu sync flag
400
 
401
        # Jump to return from this VSR. If the exception was genuine,
402
        # we will re-execute the cause and come back here. If it was
403
        # just a duplicate, or a halt NMI, we will continue as if
404
        # nothing had happened.
405
 
406
         jmp    __default_exception_vsr_return
407
 
408
9:
409
        # Stop all other CPUs
410
        .extern cyg_hal_smp_halt_other_cpus
411
        call    cyg_hal_smp_halt_other_cpus
412
 
413
#endif
414
 
415
        hal_fpu_push_exc_annex
416
 
417
        # Call exception handler
418
        .extern cyg_hal_exception_handler
419
        pushl   %edi                    # arg1 = saved state
420
        call    cyg_hal_exception_handler
421
        addl    $4,%esp                 # pop arg
422
 
423
        hal_fpu_pop_exc_annex
424
 
425
#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) && defined(CYGPKG_HAL_SMP_SUPPORT)
426
 
427
        .extern cyg_hal_smp_release_other_cpus
428
        call    cyg_hal_smp_release_other_cpus
429
 
430
        lock btrl $0,cyg_hal_smp_vsr_sync_flag  # clear serialization bit
431
 
432
__default_exception_vsr_return:
433
 
434
#endif
435
 
436
        hal_fpu_pop_exc         # restore FPU state
437
 
438
        ## At this point, the stack contains:
439
        ## 44(%esp)     EFLAGS pushed by hardware
440
        ## 40(%esp)     CS pushed by hardware
441
        ## 36(%esp)     PC pushed by hardware
442
        ## 32(%esp)     vector number pushed by trampoline
443
        ## 28(%esp)     EAX
444
        ## 24(%esp)     ECX
445
        ## 20(%esp)     EDX
446
        ## 16(%esp)     EBX
447
        ## 12(%esp)     ESP
448
        ##  8(%esp)     EBP
449
        ##  4(%esp)     ESI
450
        ##  0(%esp)     EDI
451
 
452
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
453
        movl    12(%esp),%ebp   # pre-exception ESP
454
        sub     $48,%ebp        # adjust for current stack frame
455
        cmpl    %esp,%ebp
456
        je      1f
457
 
458
        ## need to switch stacks
459
        xchg    %esp,%ebp
460
        add     $48,%esp
461
        pushl   44(%ebp)        # EFLAGS
462
        pushl   40(%ebp)        # CS
463
        pushl   36(%ebp)        # PC
464
        mov     %ebp,%esp
465
        popa
466
        movl    -20(%esp),%esp  # popa does not restore %esp
467
        sub     $12,%esp        # adjust for EFLAGS, CS, and PC
468
        iret
469
1:
470
#endif
471
        popa                    # restore all our registers.
472
        addl    $4, %esp        # skip the vector number
473
                                # Note: we do not need to re-adjust ESP
474
                                # back by 16 as popa does not pop ESP.
475
        iret                    # and return to the program.
476
 
477
#==============================================================================
478
# Default interrupt VSR
479
#
480
#
481
        .extern __interrupt_stack
482
 
483
        .align  4, 0xCC
484
        .globl  __default_interrupt_vsr
485
__default_interrupt_vsr:
486
 
487
        ## We enter here with the CPU state still in the registers and:
488
        ##  0(%esp)     vector number pushed by trampoline
489
        ##  4(%esp)     PC pushed by hardware
490
        ##  8(%esp)     CS pushed by hardware
491
        ## 12(%esp)     EFLAGS pushed by hardware
492
 
493
        pusha                   # save registers
494
        hal_fpu_push_int        # save FPU state
495
 
496
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) || \
497
    defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
498
        # Save the context just to be able to set a breakpoint
499
        # when we have a CTRL-C
500
        .extern hal_saved_interrupt_state
501
        movl %esp,hal_saved_interrupt_state
502
#endif
503
 
504
#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \
505
    !defined(CYGPKG_HAL_SMP_SUPPORT)
506
        # Increment scheduler lock
507
        .extern cyg_scheduler_sched_lock
508
        incl    cyg_scheduler_sched_lock
509
#endif
510
 
511
        movl    %esp,%ebp                       # EBP = copy of ESP
512
 
513
        # adjust ESP by 16 for the state stored before the pusha
514
        add     $16,i386reg_esp(%esp)
515
 
516
        hal_to_intstack
517
 
518
        hal_fpu_push_int_annex                  # save extra FPU state
519
 
520
#ifdef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
521
 
522
        # If we are allowing nested interrupts, restore the flags pushed
523
        # by the hardware when this interrupt was taken.
524
 
525
        movl    i386reg_eflags(%ebp), %eax
526
        btrl    $8,%eax                 # Clear TF bit
527
        pushl   %eax
528
        popfl
529
#endif
530
 
531
#if defined(CYGPKG_KERNEL_INSTRUMENT) && defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
532
 
533
        # Call cyg_instrument to record that this interrupt is being raised.
534
 
535
        movl    i386reg_vector(%ebp), %ecx # vector number from saved state
536
        movl    %ecx,%edi               # EDI = copy of vector
537
        subl    $0x20,%edi              # EDI = interrupt table offset
538
 
539
        pushl   %edi                    # arg3 = interrupt number
540
        pushl   %ecx                    # arg2 = vector number
541
        pushl   $0x0301                 # arg1 = type = INTR.RAISE
542
 
543
        call    cyg_instrument          # call instrument function
544
        add     $12,%esp                # skip arguments
545
#endif
546
 
547
        # Call hal_interrupt_handlers[vector](vector, cyg_hal_interrupt_data[vector])
548
 
549
        movl    i386reg_vector(%ebp), %ecx # vector number from saved state
550
        movl    %ecx,%edi               # EDI = copy of vector
551
        subl    $0x20,%edi              # EDI = interrupt table offset
552
        movl    $hal_interrupt_handlers, %ebx
553
        movl    (%ebx, %edi, 4), %edx   # EDX = interrupt routine
554
        movl    $hal_interrupt_data, %ebx
555
        movl    (%ebx, %edi, 4), %eax   # EAX = interrupt data
556
        pushl   %eax                    # arg2 = data
557
        pushl   %ecx                    # arg1 = vector
558
        call    *%edx                   # EAX = return value, needed for interrupt_end()
559
        addl    $8,%esp                 # pop args
560
 
561
        # At this point:
562
        # EAX = ISR return code (returned by call)
563
        # EDI = ISR table offset (saved across call)
564
        # EBP = State pointer (saved across call)
565
 
566
        hal_fpu_pop_int_annex           # Pop any saved interrupt state
567
 
568
        # If we are returning from the last nested interrupt, move back
569
        # to the thread stack. interrupt_end() must be called on the
570
        # thread stack since it potentially causes a context switch.
571
 
572
        hal_from_intstack
573
 
574
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
575
 
576
        # Call interrupt_end(r, cyg_hal_interrupt_objects[vector], regs)
577
        # - r is the return value from the ISR
578
        # - regs points to saved CPU context
579
 
580
        movl    $hal_interrupt_objects, %ebx
581
        movl    (%ebx, %edi, 4), %edx   # EDX = interrupt object ptr
582
        pushl   %ebp                    # arg3 = ptr to saved registers
583
        pushl   %edx                    # arg2 = object
584
        pushl   %eax                    # arg1 = ISR return code
585
        call    interrupt_end           # Call it
586
        addl    $12, %esp               # pop args
587
 
588
#endif
589
 
590
        # Now pull saved state from stack and return to
591
        # what thread was originally doing.
592
 
593
        hal_fpu_pop_int                 # restore FPU state
594
        popa                            # restore all our registers.
595
        addl    $4, %esp                # skip the vector number.
596
        iret                            # and return to the thread.
597
 
598
#==============================================================================
599
## Execute pending DSRs on the interrupt stack with interrupts enabled.
600
## Note: this can only be called from code running on a thread stack so we
601
## can always just jump to the interrupt stack without looking.
602
 
603
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
604
 
605
        .extern cyg_interrupt_call_pending_DSRs
606
        .global hal_interrupt_stack_call_pending_DSRs
607
 
608
hal_interrupt_stack_call_pending_DSRs:
609
 
610
        pushl   %ebp                    # save EBP
611
        pushfl                          # save flags
612
        movl    %esp,%ebp               # EBP = saved SP
613
 
614
        hal_load_istack %edx            # load new SP into EDX
615
        movl    %edx,%esp               # move it to ESP
616
 
617
        sti                             # Enable interrupts
618
 
619
        # Call back to kernel to run DSRs
620
        call    cyg_interrupt_call_pending_DSRs
621
 
622
        # On return EBP will still contain the old ESP since
623
        # it is a callee saved register.
624
 
625
        movl    %ebp,%esp               # restore saved SP
626
 
627
        # Now merge the original IF bit into the current
628
        # EFLAGS.
629
 
630
        popl    %eax                    # EAX = saved flags
631
        pushfl                          # 0(%esp) = current flags
632
        btrl    $9,0(%esp)              # clear IF bit in current flags
633
        andl    $0x00000200,%eax        # isolate saved IF bit
634
        orl     %eax,0(%esp)            # OR it in to the saved flags
635
        popfl                           # restore flags
636
 
637
        popl    %ebp                    # restore EBP
638
        ret                             # and return
639
 
640
#endif
641
 
642
#==============================================================================
643
# FPU lazy state switch VSR
644
# This is invoked via hardware exception 7 (FPU unavailable) as a result of
645
# setting the TS bit in CR0 whenever we context switch. If we discover here
646
# that a different context from the current owner of the FPU has attempted
647
# a floating point operation, we save the old context and load the new before
648
# allowing it to proceed.
649
 
650
#ifdef CYGHWR_HAL_I386_FPU_SWITCH_LAZY
651
 
652
#ifndef CYGPKG_HAL_SMP_CPU_MAX
653
#define CYGPKG_HAL_SMP_CPU_MAX 1
654
#endif
655
 
656
        .data
657
        .global cyg_hal_fpustate_owner
658
cyg_hal_fpustate_owner:
659
        .rept   CYGPKG_HAL_SMP_CPU_MAX
660
        .long   0                                # pointer to FPU owning context
661
        .endr
662
        .global cyg_hal_fpustate_current
663
cyg_hal_fpustate_current:
664
        .rept   CYGPKG_HAL_SMP_CPU_MAX
665
        .long   0                                # pointer to current threads FPU context
666
        .endr
667
 
668
        .text
669
__fpu_switch_vsr:
670
 
671
        ## We enter here with the CPU state still in the registers and:
672
        ##  0(%esp)     vector number pushed by trampoline
673
        ##  4(%esp)     PC pushed by hardware
674
        ##  8(%esp)     CS pushed by hardware
675
        ## 12(%esp)     EFLAGS pushed by hardware
676
 
677
        clts                                    # clear CR0:TS bit
678
        pusha                                   # save all regs
679
 
680
        hal_smp_cpu %ecx                        # ECX = CPU id
681
        movl    $cyg_hal_fpustate_owner,%eax    # EAX = FPU context owner table
682
        leal    0(%eax,%ecx,4),%esi             # ESI = address of owner pointer
683
        movl    $cyg_hal_fpustate_current,%ebx  # EBX = current threads context table
684
        leal    0(%ebx,%ecx,4),%edi             # EDI = address of context pointer
685
        movl    0(%esi),%eax                    # EAX = Current FPU context owner
686
        movl    0(%edi),%ebx                    # EBX = Current threads FPU context
687
        cmpl    %ebx,%eax                       # current == owner ?
688
        je      9f                              # yes, nothing else to do
689
        cmpl    $0,%eax                         # is FPU even in use?
690
        je      1f                              # if not, skip save
691
        fnsave  i386reg_fpucontext_state(%eax)  # save FPU state
692
#ifdef CYGHWR_HAL_I386_PENTIUM_SSE
693
        # Save SIMD state.
694
 
695
        # FIXME. This is awfully inefficient. Need to use FXSAVE to
696
        # save FPU and SIMD at same time. FXSAVE requires a 16 byte
697
        # alignment and does not have an implicit finit as does FSAVE.
698
 
699
        stmxcsr i386reg_simd_mxcsr(%eax)
700
        movups  %xmm0,i386reg_simd_xmm0(%eax)
701
        movups  %xmm1,i386reg_simd_xmm1(%eax)
702
        movups  %xmm2,i386reg_simd_xmm2(%eax)
703
        movups  %xmm3,i386reg_simd_xmm3(%eax)
704
        movups  %xmm4,i386reg_simd_xmm4(%eax)
705
        movups  %xmm5,i386reg_simd_xmm5(%eax)
706
        movups  %xmm6,i386reg_simd_xmm6(%eax)
707
        movups  %xmm7,i386reg_simd_xmm7(%eax)
708
#endif
709
        movl    $1,i386reg_fpucontext_valid(%eax) # mark valid
710
1:
711
        movl    %ebx,0(%esi)                    # Set new owner
712
        btl     $0,i386reg_fpucontext_valid(%ebx) # Valid state?
713
        jc      2f                              # If yes, go to restore it
714
        finit                                   # Otherwise init FPU
715
#ifdef CYGHWR_HAL_I386_PENTIUM_SSE
716
        # FIXME. Anything needed here?
717
#endif
718
        jmp     9f                              # skip restore
719
2:
720
        frstor  i386reg_fpucontext_state(%ebx)  # restore FPU state
721
#ifdef CYGHWR_HAL_I386_PENTIUM_SSE
722
        # Restore SIMD state.
723
 
724
        # FIXME. This is awfully inefficient. Need to use FXRSTOR to
725
        # restore FPU and SIMD at same time. FXRSTOR requires a 16 byte
726
        # alignment.
727
 
728
        movups  i386reg_simd_xmm0(%ebx),%xmm0
729
        movups  i386reg_simd_xmm1(%ebx),%xmm1
730
        movups  i386reg_simd_xmm2(%ebx),%xmm2
731
        movups  i386reg_simd_xmm3(%ebx),%xmm3
732
        movups  i386reg_simd_xmm4(%ebx),%xmm4
733
        movups  i386reg_simd_xmm5(%ebx),%xmm5
734
        movups  i386reg_simd_xmm6(%ebx),%xmm6
735
        movups  i386reg_simd_xmm7(%ebx),%xmm7
736
        ldmxcsr i386reg_simd_mxcsr(%ebx)
737
#endif
738
9:
739
        popa                                    # restore all our registers.
740
        addl    $4, %esp                        # skip the vector number.
741
        iret                                    # and return to the thread.
742
 
743
#endif
744
 
745
#if 0
746
#==============================================================================
747
# Assembler swap routines
748
 
749
 
750
# x = CPU_swap_u16(x)
751
        .align  4
752
        .global CPU_swap_u16
753
CPU_swap_u16:
754
        xorl    %eax, %eax
755
        movb    4(%esp), %ah
756
        movb    5(%esp), %al
757
        ret
758
 
759
# x = CPU_swap_u32(x)
760
        .align  4
761
        .global CPU_swap_u32
762
CPU_swap_u32:
763
        xorl    %eax, %eax
764
        movb    4(%esp), %ah
765
        movb    5(%esp), %al
766
        sall    $16, %eax
767
        movb    6(%esp), %ah
768
        movb    7(%esp), %al
769
        ret
770
#endif
771
 
772
#==============================================================================
773
# Exception trampolines
774
# IDT exception gates point to short code sequences that push the vector
775
# number on to the stack and then indirect via the VSR table to a handler.
776
#
777
 
778
        # Just for yuks we keep a count of the number of times each
779
        # vector is called.
780
        .bss
781
        .globl hal_vsr_stats
782
hal_vsr_stats:
783
        .rept 64        // Default VSR table is 64 entries long
784
        .long 0
785
        .endr
786
 
787
        # When an exception which supplies an error code is generated,
788
        # we move the code here.
789
hal_trap_error_code:
790
        .long 0
791
 
792
        .text
793
 
794
        # macro to create exception handler (no error code)
795
        .macro  hal_pc_exception_noerr idx
796
hal_pc_exception_\idx:
797
        movl    $0,hal_trap_error_code
798
        pushl   $\idx
799
        incl    (hal_vsr_stats+\idx*4)
800
        jmp     *(hal_vsr_table+\idx*4)
801
        .endm
802
 
803
        # macro to create exception handler (with error code)
804
        .macro  hal_pc_exception_err idx
805
hal_pc_exception_\idx:
806
        popl    hal_trap_error_code
807
        pushl   $\idx
808
        incl    (hal_vsr_stats+\idx*4)
809
        jmp     *(hal_vsr_table+\idx*4)
810
        .endm
811
 
812
        # Now generate all the default exception VSR trampolines.
813
 
814
        hal_pc_exception_noerr  0
815
        hal_pc_exception_noerr  1
816
        hal_pc_exception_noerr  2
817
        hal_pc_exception_noerr  3
818
        hal_pc_exception_noerr  4
819
        hal_pc_exception_noerr  5
820
        hal_pc_exception_noerr  6
821
        hal_pc_exception_noerr  7
822
        hal_pc_exception_err    8
823
        hal_pc_exception_noerr  9
824
        hal_pc_exception_err   10
825
        hal_pc_exception_err   11
826
        hal_pc_exception_err   12
827
        hal_pc_exception_err   13
828
        hal_pc_exception_err   14
829
        hal_pc_exception_noerr 15
830
        hal_pc_exception_noerr 16
831
        hal_pc_exception_err   17
832
        hal_pc_exception_noerr 18
833
        hal_pc_exception_noerr 19
834
        hal_pc_exception_noerr 20
835
        hal_pc_exception_noerr 21
836
        hal_pc_exception_noerr 22
837
        hal_pc_exception_noerr 23
838
        hal_pc_exception_noerr 24
839
        hal_pc_exception_noerr 25
840
        hal_pc_exception_noerr 26
841
        hal_pc_exception_noerr 27
842
        hal_pc_exception_noerr 28
843
        hal_pc_exception_noerr 29
844
        hal_pc_exception_noerr 30
845
        hal_pc_exception_noerr 31
846
 
847
#==============================================================================
848
# IRQ handler trampolines
849
 
850
 
851
        # macro to create exception handler (no error code)
852
        .macro  hal_pc_irq_handler idx
853
hal_pc_irq_\idx:
854
        pushl   $\idx
855
        incl    (hal_vsr_stats+\idx*4)
856
        jmp     *(hal_vsr_table+\idx*4)
857
        .endm
858
 
859
        hal_pc_irq_handler 32
860
        hal_pc_irq_handler 33
861
        hal_pc_irq_handler 34
862
        hal_pc_irq_handler 35
863
        hal_pc_irq_handler 36
864
        hal_pc_irq_handler 37
865
        hal_pc_irq_handler 38
866
        hal_pc_irq_handler 39
867
        hal_pc_irq_handler 40
868
        hal_pc_irq_handler 41
869
        hal_pc_irq_handler 42
870
        hal_pc_irq_handler 43
871
        hal_pc_irq_handler 44
872
        hal_pc_irq_handler 45
873
        hal_pc_irq_handler 46
874
        hal_pc_irq_handler 47
875
#ifdef CYGPKG_HAL_SMP_SUPPORT
876
 
877
        # Extra interrupt vectors for IOAPIc routed PCI and
878
        # other interrupt sources
879
        hal_pc_irq_handler 48
880
        hal_pc_irq_handler 49
881
        hal_pc_irq_handler 50
882
        hal_pc_irq_handler 51
883
        hal_pc_irq_handler 52
884
        hal_pc_irq_handler 53
885
        hal_pc_irq_handler 54
886
        hal_pc_irq_handler 55
887
        hal_pc_irq_handler 56
888
        hal_pc_irq_handler 57
889
        hal_pc_irq_handler 58
890
        hal_pc_irq_handler 59
891
        hal_pc_irq_handler 60
892
        hal_pc_irq_handler 61
893
        hal_pc_irq_handler 62
894
        hal_pc_irq_handler 63
895
 
896
        # Inter-CPU interrupts start at 64
897
        hal_pc_irq_handler 64
898
        hal_pc_irq_handler 65
899
        hal_pc_irq_handler 66
900
        hal_pc_irq_handler 67
901
#endif
902
 
903
 
904
        # default vsr entries: pop the vector code from the stack and return.
905
default_vsr_iret:
906
        add $4,%esp
907
        iret
908
 
909
        # GNUPro apps use "int $0x80" for syscalls.
910
        # There is no vsr table entry for this.
911
        .global __syscall_tramp
912
__syscall_tramp:
913
        pushl $0x80
914
        jmp __default_exception_vsr
915
 
916
#==============================================================================
917
# Initial and interrupt stack
918
 
919
#ifndef CYG_HAL_I386_INTERRUPT_STACK_DEFINED
920
 
921
        .bss
922
 
923
#ifndef CYGPKG_HAL_SMP_SUPPORT
924
 
925
        .balign 16
926
        .global cyg_interrupt_stack_base
927
cyg_interrupt_stack_base:
928
__interrupt_stack_base:
929
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
930
        .byte 0
931
        .endr
932
        .balign 16
933
        .global cyg_interrupt_stack
934
cyg_interrupt_stack:
935
__interrupt_stack:
936
 
937
        .long   0,0,0,0,0,0,0,0
938
 
939
#else // CYGPKG_HAL_SMP_SUPPORT
940
 
941
__interrupt_stack_vector:
942
        .rept CYGPKG_HAL_SMP_CPU_MAX
943
        .long 0
944
        .endr
945
 
946
        .balign 16
947
        .global cyg_interrupt_stack_base
948
cyg_interrupt_stack_base:
949
__interrupt_stack_base:
950
__interrupt_stack_first:
951
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
952
        .byte 0
953
        .endr
954
        .global cyg_interrupt_stack
955
cyg_interrupt_stack:
956
__interrupt_stack:
957
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE*(CYGPKG_HAL_SMP_CPU_MAX-1)
958
        .byte 0
959
        .endr
960
 
961
#endif // CYGPKG_HAL_SMP_SUPPORT
962
 
963
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
964
        .global __stub_stack_base
965
__stub_stack_base:
966
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
967
        .byte 0
968
        .endr
969
        .balign 16
970
        .global __stub_stack
971
__stub_stack:
972
 
973
        .long   0,0,0,0,0,0,0,0
974
#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
975
 
976
 
977
#endif // CYG_HAL_I386_INTERRUPT_STACK_DEFINED
978
 
979
#------------------------------------------------------------------------------
980
# end of vectors.S

powered by: WebSVN 2.1.0

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