| /* MN10300 Low level FPU management operations |
| * |
| * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. |
| * Written by David Howells (dhowells@redhat.com) |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public Licence |
| * as published by the Free Software Foundation; either version |
| * 2 of the Licence, or (at your option) any later version. |
| */ |
| #include <linux/linkage.h> |
| #include <asm/cpu-regs.h> |
| #include <asm/smp.h> |
| #include <asm/thread_info.h> |
| #include <asm/asm-offsets.h> |
| #include <asm/frame.inc> |
| |
| .macro FPU_INIT_STATE_ALL |
| fmov 0,fs0 |
| fmov fs0,fs1 |
| fmov fs0,fs2 |
| fmov fs0,fs3 |
| fmov fs0,fs4 |
| fmov fs0,fs5 |
| fmov fs0,fs6 |
| fmov fs0,fs7 |
| fmov fs0,fs8 |
| fmov fs0,fs9 |
| fmov fs0,fs10 |
| fmov fs0,fs11 |
| fmov fs0,fs12 |
| fmov fs0,fs13 |
| fmov fs0,fs14 |
| fmov fs0,fs15 |
| fmov fs0,fs16 |
| fmov fs0,fs17 |
| fmov fs0,fs18 |
| fmov fs0,fs19 |
| fmov fs0,fs20 |
| fmov fs0,fs21 |
| fmov fs0,fs22 |
| fmov fs0,fs23 |
| fmov fs0,fs24 |
| fmov fs0,fs25 |
| fmov fs0,fs26 |
| fmov fs0,fs27 |
| fmov fs0,fs28 |
| fmov fs0,fs29 |
| fmov fs0,fs30 |
| fmov fs0,fs31 |
| fmov FPCR_INIT,fpcr |
| .endm |
| |
| .macro FPU_SAVE_ALL areg,dreg |
| fmov fs0,(\areg+) |
| fmov fs1,(\areg+) |
| fmov fs2,(\areg+) |
| fmov fs3,(\areg+) |
| fmov fs4,(\areg+) |
| fmov fs5,(\areg+) |
| fmov fs6,(\areg+) |
| fmov fs7,(\areg+) |
| fmov fs8,(\areg+) |
| fmov fs9,(\areg+) |
| fmov fs10,(\areg+) |
| fmov fs11,(\areg+) |
| fmov fs12,(\areg+) |
| fmov fs13,(\areg+) |
| fmov fs14,(\areg+) |
| fmov fs15,(\areg+) |
| fmov fs16,(\areg+) |
| fmov fs17,(\areg+) |
| fmov fs18,(\areg+) |
| fmov fs19,(\areg+) |
| fmov fs20,(\areg+) |
| fmov fs21,(\areg+) |
| fmov fs22,(\areg+) |
| fmov fs23,(\areg+) |
| fmov fs24,(\areg+) |
| fmov fs25,(\areg+) |
| fmov fs26,(\areg+) |
| fmov fs27,(\areg+) |
| fmov fs28,(\areg+) |
| fmov fs29,(\areg+) |
| fmov fs30,(\areg+) |
| fmov fs31,(\areg+) |
| fmov fpcr,\dreg |
| mov \dreg,(\areg) |
| .endm |
| |
| .macro FPU_RESTORE_ALL areg,dreg |
| fmov (\areg+),fs0 |
| fmov (\areg+),fs1 |
| fmov (\areg+),fs2 |
| fmov (\areg+),fs3 |
| fmov (\areg+),fs4 |
| fmov (\areg+),fs5 |
| fmov (\areg+),fs6 |
| fmov (\areg+),fs7 |
| fmov (\areg+),fs8 |
| fmov (\areg+),fs9 |
| fmov (\areg+),fs10 |
| fmov (\areg+),fs11 |
| fmov (\areg+),fs12 |
| fmov (\areg+),fs13 |
| fmov (\areg+),fs14 |
| fmov (\areg+),fs15 |
| fmov (\areg+),fs16 |
| fmov (\areg+),fs17 |
| fmov (\areg+),fs18 |
| fmov (\areg+),fs19 |
| fmov (\areg+),fs20 |
| fmov (\areg+),fs21 |
| fmov (\areg+),fs22 |
| fmov (\areg+),fs23 |
| fmov (\areg+),fs24 |
| fmov (\areg+),fs25 |
| fmov (\areg+),fs26 |
| fmov (\areg+),fs27 |
| fmov (\areg+),fs28 |
| fmov (\areg+),fs29 |
| fmov (\areg+),fs30 |
| fmov (\areg+),fs31 |
| mov (\areg),\dreg |
| fmov \dreg,fpcr |
| .endm |
| |
| ############################################################################### |
| # |
| # void fpu_init_state(void) |
| # - initialise the FPU |
| # |
| ############################################################################### |
| .globl fpu_init_state |
| .type fpu_init_state,@function |
| fpu_init_state: |
| mov epsw,d0 |
| or EPSW_FE,epsw |
| |
| #ifdef CONFIG_MN10300_PROC_MN103E010 |
| nop |
| nop |
| nop |
| #endif |
| FPU_INIT_STATE_ALL |
| #ifdef CONFIG_MN10300_PROC_MN103E010 |
| nop |
| nop |
| nop |
| #endif |
| mov d0,epsw |
| ret [],0 |
| |
| .size fpu_init_state,.-fpu_init_state |
| |
| ############################################################################### |
| # |
| # void fpu_save(struct fpu_state_struct *) |
| # - save the fpu state |
| # - note that an FPU Operational exception might occur during this process |
| # |
| ############################################################################### |
| .globl fpu_save |
| .type fpu_save,@function |
| fpu_save: |
| mov epsw,d1 |
| or EPSW_FE,epsw /* enable the FPU so we can access it */ |
| |
| #ifdef CONFIG_MN10300_PROC_MN103E010 |
| nop |
| nop |
| #endif |
| mov d0,a0 |
| FPU_SAVE_ALL a0,d0 |
| #ifdef CONFIG_MN10300_PROC_MN103E010 |
| nop |
| nop |
| #endif |
| |
| mov d1,epsw |
| ret [],0 |
| |
| .size fpu_save,.-fpu_save |
| |
| ############################################################################### |
| # |
| # void fpu_disabled(void) |
| # - handle an exception due to the FPU being disabled |
| # when CONFIG_FPU is enabled |
| # |
| ############################################################################### |
| .type fpu_disabled,@function |
| .globl fpu_disabled |
| fpu_disabled: |
| or EPSW_nAR|EPSW_FE,epsw |
| nop |
| nop |
| nop |
| |
| mov sp,a1 |
| mov (a1),d1 /* get epsw of user context */ |
| and ~(THREAD_SIZE-1),a1 /* a1: (thread_info *ti) */ |
| mov (TI_task,a1),a2 /* a2: (task_struct *tsk) */ |
| btst EPSW_nSL,d1 |
| beq fpu_used_in_kernel |
| |
| or EPSW_FE,d1 |
| mov d1,(sp) |
| mov (TASK_THREAD+THREAD_FPU_FLAGS,a2),d1 |
| #ifndef CONFIG_LAZY_SAVE_FPU |
| or __THREAD_HAS_FPU,d1 |
| mov d1,(TASK_THREAD+THREAD_FPU_FLAGS,a2) |
| #else /* !CONFIG_LAZY_SAVE_FPU */ |
| mov (fpu_state_owner),a0 |
| cmp 0,a0 |
| beq fpu_regs_save_end |
| |
| mov (TASK_THREAD+THREAD_UREGS,a0),a1 |
| add TASK_THREAD+THREAD_FPU_STATE,a0 |
| FPU_SAVE_ALL a0,d0 |
| |
| mov (REG_EPSW,a1),d0 |
| and ~EPSW_FE,d0 |
| mov d0,(REG_EPSW,a1) |
| |
| fpu_regs_save_end: |
| mov a2,(fpu_state_owner) |
| #endif /* !CONFIG_LAZY_SAVE_FPU */ |
| |
| btst __THREAD_USING_FPU,d1 |
| beq fpu_regs_init |
| add TASK_THREAD+THREAD_FPU_STATE,a2 |
| FPU_RESTORE_ALL a2,d0 |
| rti |
| |
| fpu_regs_init: |
| FPU_INIT_STATE_ALL |
| add TASK_THREAD+THREAD_FPU_FLAGS,a2 |
| bset __THREAD_USING_FPU,(0,a2) |
| rti |
| |
| fpu_used_in_kernel: |
| and ~(EPSW_nAR|EPSW_FE),epsw |
| nop |
| nop |
| |
| add -4,sp |
| SAVE_ALL |
| mov -1,d0 |
| mov d0,(REG_ORIG_D0,fp) |
| |
| and ~EPSW_NMID,epsw |
| |
| mov fp,d0 |
| call fpu_disabled_in_kernel[],0 |
| jmp ret_from_exception |
| |
| .size fpu_disabled,.-fpu_disabled |