Mercurial > ecos
diff packages/hal/i386/arch/current/include/arch.inc @ 161:ac086aa3217e
Merge from eCos master repository on 2001-06-08-21:11:51-BST
| author | jlarmour |
|---|---|
| date | Sun, 10 Jun 2001 19:35:23 +0000 |
| parents | da3908c9cd10 |
| children | 42f843b391aa |
line wrap: on
line diff
--- a/packages/hal/i386/arch/current/include/arch.inc +++ b/packages/hal/i386/arch/current/include/arch.inc @@ -86,70 +86,320 @@ #ifdef CYGHWR_HAL_I386_FPU +#define CYGPKG_HAL_I386_FPU_DEFINED + .macro hal_fpu_init - .endm - - .macro hal_fpu_save regs + # Tell the CPU to use the math hardware. + movl %cr0, %eax + orl $0x32, %eax + movl %eax, %cr0 + + finit # and initialize... + + ## Enable floating point exceptions. Bit mask: + ## 1 - invalid operation + ## 2 - denormalized operand + ## 4 - zero divide + ## 8 - overflow + ## 16 - underflow + ## 32 - precision + pushl $0 # space for CW + fstcw 0(%esp) # store FPCW to stack + movl 0(%esp),%eax # get into EAX + andb $(~0x04),%al # allow only zero divide exceptions + movl %eax,0(%esp) # put back into memory + fldcw 0(%esp) # reload + addl $4,%esp # pop value + +#ifdef CYGHWR_HAL_I386_FPU_SWITCH_LAZY + # Tell the CPU to generate an FPU unavailable exception + # when the FPU is first used. + movl %cr0, %eax + orl $0x8, %eax + movl %eax, %cr0 + # Plant a pointer to the FPU switch VSR into slot 7 + # of the VSR table. + movl $__fpu_switch_vsr,%eax + movl %eax,(hal_vsr_table+7*4) + # Now create an FPU context on the stack so that we can take + # FPU-using interrupts and exceptions before the machine starts + # up. + subl $i386reg_fpucontext_size,%esp + movl $0,i386reg_fpucontext_valid(%esp) + movl %esp,cyg_hal_fpustate_current +#endif .endm - .macro hal_fpu_save_caller regs +#ifndef CYGHWR_HAL_I386_FPU_SWITCH_LAZY + + # Non-lazy CPU state switching. We simply switch the entire + # FPU state on every context switch, interrupt or exception. + + # ------------------------------------------------------------ + # Context switch handling + + .macro hal_fpu_push_ctx + subl $i386reg_fpstate_size,%esp # make space + fsave i386reg_fpstate(%esp) # save FPU state + movl $1,i386reg_fpstate_valid(%esp) # indicate it is valid + .endm + + .macro hal_fpu_pop_ctx + btl $0,i386reg_fpstate_valid(%esp) # check ls bit of valid flag + jc 1f # if set, restore state + finit # otherwise init FPU + jmp 2f # and skip restore +1: + frstor i386reg_fpstate(%esp) # restore FPU state +2: + addl $i386reg_fpstate_size,%esp # pop space used + .endm + + # ------------------------------------------------------------ + # Interrupt and exception handling + + # In this configuration, the interrupt and exception code behaves in + # exactly the same way as the context switch code. + + .macro hal_fpu_push_int + hal_fpu_push_ctx + .endm + + .macro hal_fpu_push_int_annex + .endm + + .macro hal_fpu_pop_int_annex + .endm + + .macro hal_fpu_pop_int + hal_fpu_pop_ctx + .endm + + .macro hal_fpu_push_exc + hal_fpu_push_ctx + .endm + + .macro hal_fpu_push_exc_annex + .endm + + .macro hal_fpu_pop_exc_annex + .endm + + .macro hal_fpu_pop_exc + hal_fpu_pop_ctx .endm - .macro hal_fpu_save_callee regs +#else // CYGHWR_HAL_I386_FPU_SWITCH_LAZY + + # Lazy CPU state switching. We defer CPU state switching until the new + # thread actually uses the FPU. This state switch is handled by + # __fpu_switch_vsr in vectors.S. + + .extern cyg_hal_fpustate_owner + .extern cyg_hal_fpustate_current + + # ------------------------------------------------------------ + # Context switch handling + + # On context switch we simply stack a pointer to this + # threads FPU context save area. + + .macro hal_fpu_push_ctx + pushl cyg_hal_fpustate_current # push our FPU state ptr + .endm + + # We do nothing here but set the CR0:TS bit to force + # an exception when the FPU is next used and pop the + # FPU save area pointer into the static variable. + + .macro hal_fpu_pop_ctx + movl %cr0, %ecx # get CR0 + orl $0x8, %ecx # set TS bit + movl %ecx, %cr0 # restore CR0 + popl cyg_hal_fpustate_current # set current FPU state pointer + .endm + + # ------------------------------------------------------------ + # Interrupt handling + + # On entry to an interrupt we save the current threads FPU context + # pointer and set the CR0:TS bit to trap any FP operations in the + # interrupt. + + .macro hal_fpu_push_int + pushl cyg_hal_fpustate_current # push current threads FPU state ptr + # ensure that CR0:TS bit is set + movl %cr0, %ecx # get CR0 + orl $0x8, %ecx # set TS bit + movl %ecx, %cr0 # restore CR0 + .endm + + # The following is called after we transfer to the interrupt + # stack. We make space here for the FPU state of the interrupt + # handler to be saved in case we get nested interrupts that use FP. + + .macro hal_fpu_push_int_annex + subl $i386reg_fpucontext_size,%esp + movl $0,i386reg_fpucontext_valid(%esp) + movl %esp,cyg_hal_fpustate_current .endm - .macro hal_fpu_load_caller regs + # This is invoked just before any transfer back to the thread stack. + # We check whether we are the FPU state owner, and if so, abdicate. + # There is no need to save the state, the next thread will load its + # own state over the top of it. + + .macro hal_fpu_pop_int_annex + cmpl cyg_hal_fpustate_owner,%esp # are we FPU owner? + jne 1f # if not, then just continue + movl $0,cyg_hal_fpustate_owner # no one owns FPU now + # ensure that CR0:TS bit is set to force a reload of + # the previous FPU state + movl %cr0, %ecx # get CR0 + orl $0x8, %ecx # set TS bit + movl %ecx, %cr0 # restore CR0 +1: + addl $i386reg_fpucontext_size,%esp # pop FPU save area .endm - - .macro hal_fpu_load_callee regs + + # Final return from interrupt handling. Just pull the current + # FPU context off the stack. + .macro hal_fpu_pop_int + popl cyg_hal_fpustate_current # set current FPU state pointer .endm - - .macro hal_fpu_load regs + + # ------------------------------------------------------------ + # Exception handling + + # Whenever we take an exception, we save the current FPU state away + # into its save area. This way, if we are going to end up in GDB, the + # whole machine state is saved in memory. + + .macro hal_fpu_push_exc + pushl cyg_hal_fpustate_current # push our FPU state ptr + movl cyg_hal_fpustate_owner,%eax # EAX = FPU state owner + jz 1f # skip if zero + fsave i386reg_fpucontext_state(%eax) # save state + movl $1,i386reg_fpucontext_valid(%eax) # set valid + movl $0,cyg_hal_fpustate_owner # zero owner pointer +1: .endm - + + # The rest of the exception macros behave exactly like the + # interrupt ones. + + .macro hal_fpu_push_exc_annex + hal_fpu_push_int_annex + .endm + + .macro hal_fpu_pop_exc_annex + hal_fpu_pop_int_annex + .endm + + .macro hal_fpu_pop_exc + hal_fpu_pop_int + .endm + +#endif // CYGHWR_HAL_I386_FPU_SWITCH_LAZY + #else /* !CYGHWR_HAL_I386_FPU */ + # Non-FP macros. + .macro hal_fpu_init .endm - - .macro hal_fpu_save regs + + .macro hal_fpu_push_ctx + .endm + + .macro hal_fpu_pop_ctx .endm - .macro hal_fpu_save_caller regs + .macro hal_fpu_push_int .endm - .macro hal_fpu_save_callee regs + .macro hal_fpu_push_int_annex + .endm + + .macro hal_fpu_pop_int_annex .endm - .macro hal_fpu_load_caller regs + .macro hal_fpu_pop_int .endm - - .macro hal_fpu_load_callee regs + + .macro hal_fpu_push_exc + .endm + + .macro hal_fpu_push_exc_annex .endm - - .macro hal_fpu_load regs + + .macro hal_fpu_pop_exc_annex .endm - + + .macro hal_fpu_pop_exc + .endm + #endif - + #endif #------------------------------------------------------------------------------ # MMU macros. - + #ifndef CYGPKG_HAL_I386_MMU_DEFINED - .macro hal_mmu_init +#define CYGPKG_HAL_I386_MMU_DEFINED + + .macro hal_mmu_init .endm #endif #------------------------------------------------------------------------------ +# A20 gate enable + +#define K_RDWR 0x60 +#define K_STATUS 0x64 +#define K_CMD 0x64 +#define K_OBUF_FUL 0x01 +#define K_IBUF_FUL 0x02 +#define KC_CMD_WIN 0xD0 +#define KC_CMD_WOUT 0xD1 +#define KB_A20 0xDF + + .macro hal_a20_enable + // Enable A20 so that addresses at 1MB don't wrap around back to 0. +1: inb $K_STATUS, %al + testb $K_IBUF_FUL, %al + jnz 1b + +2: inb $K_STATUS, %al + testb $K_OBUF_FUL, %al + jz 3f + inb $K_RDWR, %al + jmp 2b + +3: movb $KC_CMD_WOUT, %al + outb %al, $K_CMD +1: inb $K_STATUS, %al + testb $K_IBUF_FUL, %al + jnz 1b + + movb $KB_A20, %al + outb %al, $K_RDWR +1: inb $K_STATUS, %al + testb $K_IBUF_FUL, %al + jnz 1b + .endm + +#------------------------------------------------------------------------------ # MEMC macros. +# This version simply enables the A20 gate. #ifndef CYGPKG_HAL_I386_MEMC_DEFINED .macro hal_memc_init + hal_a20_enable .endm #endif
