mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-02 00:24:12 +08:00
e46bf83c18
This patch set contains basic components for supporting the nds32 FPU, such as exception handlers and context switch for FPU registers. By default, the lazy FPU scheme is supported and the user can configure it via CONFIG_LZAY_FPU. Signed-off-by: Vincent Chen <vincentc@andestech.com> Acked-by: Greentime Hu <greentime@andestech.com> Signed-off-by: Greentime Hu <greentime@andestech.com>
101 lines
2.2 KiB
ArmAsm
101 lines
2.2 KiB
ArmAsm
// SPDX-License-Identifier: GPL-2.0
|
|
// Copyright (C) 2005-2017 Andes Technology Corporation
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/unistd.h>
|
|
#include <asm/assembler.h>
|
|
#include <asm/nds32.h>
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm/thread_info.h>
|
|
#include <asm/current.h>
|
|
|
|
/*
|
|
* $r0 = previous task_struct,
|
|
* $r1 = next task_struct,
|
|
* previous and next are guaranteed not to be the same.
|
|
*/
|
|
|
|
ENTRY(__switch_to)
|
|
|
|
la $p0, __entry_task
|
|
sw $r1, [$p0]
|
|
addi $p1, $r0, #THREAD_CPU_CONTEXT
|
|
smw.bi $r6, [$p1], $r14, #0xb ! push r6~r14, fp, lp, sp
|
|
move $r25, $r1
|
|
#if defined(CONFIG_FPU)
|
|
call _switch_fpu
|
|
#endif
|
|
addi $r1, $r25, #THREAD_CPU_CONTEXT
|
|
lmw.bi $r6, [$r1], $r14, #0xb ! pop r6~r14, fp, lp, sp
|
|
ret
|
|
|
|
|
|
#define tbl $r8
|
|
|
|
/*
|
|
* $r7 will be writen as syscall nr
|
|
*/
|
|
.macro get_scno
|
|
lwi $r7, [$sp + R15_OFFSET]
|
|
swi $r7, [$sp + SYSCALLNO_OFFSET]
|
|
.endm
|
|
|
|
.macro updateipc
|
|
addi $r17, $r13, #4 ! $r13 is $IPC
|
|
swi $r17, [$sp + IPC_OFFSET]
|
|
.endm
|
|
|
|
ENTRY(eh_syscall)
|
|
updateipc
|
|
|
|
get_scno
|
|
gie_enable
|
|
|
|
lwi $p0, [tsk+#TSK_TI_FLAGS] ! check for syscall tracing
|
|
|
|
andi $p1, $p0, #_TIF_WORK_SYSCALL_ENTRY ! are we tracing syscalls?
|
|
bnez $p1, __sys_trace
|
|
|
|
la $lp, ret_fast_syscall ! return address
|
|
jmp_systbl:
|
|
addi $p1, $r7, #-__NR_syscalls ! syscall number of syscall instruction is guarded by addembler
|
|
bgez $p1, _SCNO_EXCEED ! call sys_* routine
|
|
la tbl, sys_call_table ! load syscall table pointer
|
|
slli $p1, $r7, #2
|
|
add $p1, tbl, $p1
|
|
lwi $p1, [$p1]
|
|
jr $p1 ! no return
|
|
|
|
_SCNO_EXCEED:
|
|
ori $r0, $r7, #0
|
|
ori $r1, $sp, #0
|
|
b bad_syscall
|
|
|
|
/*
|
|
* This is the really slow path. We're going to be doing
|
|
* context switches, and waiting for our parent to respond.
|
|
*/
|
|
__sys_trace:
|
|
move $r0, $sp
|
|
bal syscall_trace_enter
|
|
move $r7, $r0
|
|
la $lp, __sys_trace_return ! return address
|
|
|
|
addi $p1, $r7, #1
|
|
beqz $p1, ret_slow_syscall ! fatal signal is pending
|
|
|
|
addi $p1, $sp, #R0_OFFSET ! pointer to regs
|
|
lmw.bi $r0, [$p1], $r5 ! have to reload $r0 - $r5
|
|
b jmp_systbl
|
|
|
|
__sys_trace_return:
|
|
swi $r0, [$sp+#R0_OFFSET] ! T: save returned $r0
|
|
move $r0, $sp ! set pt_regs for syscall_trace_leave
|
|
bal syscall_trace_leave
|
|
b ret_slow_syscall
|
|
|
|
ENTRY(sys_rt_sigreturn_wrapper)
|
|
addi $r0, $sp, #0
|
|
b sys_rt_sigreturn
|
|
ENDPROC(sys_rt_sigreturn_wrapper)
|