Commit 74d99a5e authored by Paul Mundt's avatar Paul Mundt

sh: SH-2A FPU support.

Signed-off-by: default avatarKieran Bingham <kbingham@mpc-data.co.uk>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent a8f67f4b
...@@ -161,6 +161,7 @@ config CPU_SUBTYPE_SH7619 ...@@ -161,6 +161,7 @@ config CPU_SUBTYPE_SH7619
config CPU_SUBTYPE_SH7203 config CPU_SUBTYPE_SH7203
bool "Support SH7203 processor" bool "Support SH7203 processor"
select CPU_SH2A select CPU_SH2A
select CPU_HAS_FPU
config CPU_SUBTYPE_SH7206 config CPU_SUBTYPE_SH7206
bool "Support SH7206 processor" bool "Support SH7206 processor"
...@@ -169,6 +170,7 @@ config CPU_SUBTYPE_SH7206 ...@@ -169,6 +170,7 @@ config CPU_SUBTYPE_SH7206
config CPU_SUBTYPE_SH7263 config CPU_SUBTYPE_SH7263
bool "Support SH7263 processor" bool "Support SH7263 processor"
select CPU_SH2A select CPU_SH2A
select CPU_HAS_FPU
# SH-3 Processor Support # SH-3 Processor Support
......
...@@ -20,10 +20,6 @@ isa-$(CONFIG_CPU_SH4AL_DSP) := sh4al ...@@ -20,10 +20,6 @@ isa-$(CONFIG_CPU_SH4AL_DSP) := sh4al
isa-$(CONFIG_CPU_SH5) := shmedia isa-$(CONFIG_CPU_SH5) := shmedia
isa-$(CONFIG_SH_DSP) := $(isa-y)-dsp isa-$(CONFIG_SH_DSP) := $(isa-y)-dsp
ifndef CONFIG_MMU
isa-y := $(isa-y)-nommu
endif
ifndef CONFIG_SH_DSP ifndef CONFIG_SH_DSP
ifndef CONFIG_SH_FPU ifndef CONFIG_SH_FPU
isa-y := $(isa-y)-nofpu isa-y := $(isa-y)-nofpu
......
...@@ -149,6 +149,14 @@ ENTRY(exception_handler) ...@@ -149,6 +149,14 @@ ENTRY(exception_handler)
mov #32,r8 mov #32,r8
cmp/hs r8,r9 cmp/hs r8,r9
bt trap_entry ! 64 > vec >= 32 is trap bt trap_entry ! 64 > vec >= 32 is trap
#if defined(CONFIG_SH_FPU)
mov #13,r8
cmp/eq r8,r9
bt 10f ! fpu
nop
#endif
mov.l 4f,r8 mov.l 4f,r8
mov r9,r4 mov r9,r4
shll2 r9 shll2 r9
...@@ -158,6 +166,10 @@ ENTRY(exception_handler) ...@@ -158,6 +166,10 @@ ENTRY(exception_handler)
cmp/eq r9,r8 cmp/eq r9,r8
bf 3f bf 3f
mov.l 8f,r8 ! unhandled exception mov.l 8f,r8 ! unhandled exception
#if defined(CONFIG_SH_FPU)
10:
mov.l 9f, r8 ! unhandled exception
#endif
3: 3:
mov.l 5f,r10 mov.l 5f,r10
jmp @r8 jmp @r8
...@@ -177,7 +189,10 @@ interrupt_entry: ...@@ -177,7 +189,10 @@ interrupt_entry:
6: .long ret_from_irq 6: .long ret_from_irq
7: .long do_IRQ 7: .long do_IRQ
8: .long do_exception_error 8: .long do_exception_error
#ifdef CONFIG_SH_FPU
9: .long fpu_error_trap_handler
#endif
trap_entry: trap_entry:
mov #0x30,r8 mov #0x30,r8
cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall
......
...@@ -6,6 +6,8 @@ obj-y := common.o probe.o opcode_helper.o ...@@ -6,6 +6,8 @@ obj-y := common.o probe.o opcode_helper.o
common-y += $(addprefix ../sh2/, ex.o entry.o) common-y += $(addprefix ../sh2/, ex.o entry.o)
obj-$(CONFIG_SH_FPU) += fpu.o
obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o
obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o
This diff is collapsed.
...@@ -36,7 +36,7 @@ ENTRY(exception_handling_table) ...@@ -36,7 +36,7 @@ ENTRY(exception_handling_table)
.long exception_error ! address error store /* 100 */ .long exception_error ! address error store /* 100 */
#endif #endif
#if defined(CONFIG_SH_FPU) #if defined(CONFIG_SH_FPU)
.long do_fpu_error /* 120 */ .long fpu_error_trap_handler /* 120 */
#else #else
.long exception_error /* 120 */ .long exception_error /* 120 */
#endif #endif
......
...@@ -82,8 +82,8 @@ save_fpu(struct task_struct *tsk, struct pt_regs *regs) ...@@ -82,8 +82,8 @@ save_fpu(struct task_struct *tsk, struct pt_regs *regs)
"r" (FPSCR_INIT) "r" (FPSCR_INIT)
: "memory"); : "memory");
disable_fpu(); disable_fpu();
release_fpu(regs); release_fpu(regs);
} }
static void static void
...@@ -91,7 +91,7 @@ restore_fpu(struct task_struct *tsk) ...@@ -91,7 +91,7 @@ restore_fpu(struct task_struct *tsk)
{ {
unsigned long dummy; unsigned long dummy;
enable_fpu(); enable_fpu();
asm volatile("lds %2, fpscr\n\t" asm volatile("lds %2, fpscr\n\t"
"fmov.s @%0+, fr0\n\t" "fmov.s @%0+, fr0\n\t"
"fmov.s @%0+, fr1\n\t" "fmov.s @%0+, fr1\n\t"
...@@ -138,7 +138,7 @@ restore_fpu(struct task_struct *tsk) ...@@ -138,7 +138,7 @@ restore_fpu(struct task_struct *tsk)
/* /*
* Load the FPU with signalling NANS. This bit pattern we're using * Load the FPU with signalling NANS. This bit pattern we're using
* has the property that no matter wether considered as single or as * has the property that no matter wether considered as single or as
* double precision represents signaling NANS. * double precision represents signaling NANS.
*/ */
static void static void
...@@ -184,7 +184,7 @@ fpu_init(void) ...@@ -184,7 +184,7 @@ fpu_init(void)
"lds %2, fpscr\n\t" "lds %2, fpscr\n\t"
: /* no output */ : /* no output */
: "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT)); : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT));
disable_fpu(); disable_fpu();
} }
/** /**
...@@ -238,7 +238,6 @@ ieee_fpe_handler (struct pt_regs *regs) ...@@ -238,7 +238,6 @@ ieee_fpe_handler (struct pt_regs *regs)
if (nib[0] == 0xb || if (nib[0] == 0xb ||
(nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */ (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */
regs->pr = regs->pc + 4; regs->pr = regs->pc + 4;
if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */ if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */
nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3); nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3);
finsn = *(unsigned short *) (regs->pc + 2); finsn = *(unsigned short *) (regs->pc + 2);
...@@ -293,12 +292,10 @@ ieee_fpe_handler (struct pt_regs *regs) ...@@ -293,12 +292,10 @@ ieee_fpe_handler (struct pt_regs *regs)
return 0; return 0;
} }
asmlinkage void BUILD_TRAP_HANDLER(fpu_error)
do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6,
unsigned long r7, struct pt_regs __regs)
{ {
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
struct task_struct *tsk = current; struct task_struct *tsk = current;
TRAP_HANDLER_DECL;
if (ieee_fpe_handler(regs)) if (ieee_fpe_handler(regs))
return; return;
...@@ -308,12 +305,10 @@ do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, ...@@ -308,12 +305,10 @@ do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6,
force_sig(SIGFPE, tsk); force_sig(SIGFPE, tsk);
} }
asmlinkage void BUILD_TRAP_HANDLER(fpu_state_restore)
do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
unsigned long r7, struct pt_regs __regs)
{ {
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
struct task_struct *tsk = current; struct task_struct *tsk = current;
TRAP_HANDLER_DECL;
grab_fpu(regs); grab_fpu(regs);
if (!user_mode(regs)) { if (!user_mode(regs)) {
......
...@@ -662,11 +662,6 @@ asmlinkage void do_divide_error(unsigned long r4, unsigned long r5, ...@@ -662,11 +662,6 @@ asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
} }
#endif #endif
/* arch/sh/kernel/cpu/sh4/fpu.c */
extern int do_fpu_inst(unsigned short, struct pt_regs *);
extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, struct pt_regs __regs);
asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r6, unsigned long r7,
struct pt_regs __regs) struct pt_regs __regs)
...@@ -853,11 +848,11 @@ void __init trap_init(void) ...@@ -853,11 +848,11 @@ void __init trap_init(void)
set_exception_table_evt(0x820, do_illegal_slot_inst); set_exception_table_evt(0x820, do_illegal_slot_inst);
#elif defined(CONFIG_SH_FPU) #elif defined(CONFIG_SH_FPU)
#ifdef CONFIG_CPU_SUBTYPE_SHX3 #ifdef CONFIG_CPU_SUBTYPE_SHX3
set_exception_table_evt(0xd80, do_fpu_state_restore); set_exception_table_evt(0xd80, fpu_state_restore_trap_handler);
set_exception_table_evt(0xda0, do_fpu_state_restore); set_exception_table_evt(0xda0, fpu_state_restore_trap_handler);
#else #else
set_exception_table_evt(0x800, do_fpu_state_restore); set_exception_table_evt(0x800, fpu_state_restore_trap_handler);
set_exception_table_evt(0x820, do_fpu_state_restore); set_exception_table_evt(0x820, fpu_state_restore_trap_handler);
#endif #endif
#endif #endif
......
...@@ -26,6 +26,8 @@ extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); ...@@ -26,6 +26,8 @@ extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs);
#define save_fpu(tsk, regs) do { } while (0) #define save_fpu(tsk, regs) do { } while (0)
#endif #endif
extern int do_fpu_inst(unsigned short, struct pt_regs *);
#define unlazy_fpu(tsk, regs) do { \ #define unlazy_fpu(tsk, regs) do { \
if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \
save_fpu(tsk, regs); \ save_fpu(tsk, regs); \
......
...@@ -25,7 +25,8 @@ struct sigcontext { ...@@ -25,7 +25,8 @@ struct sigcontext {
unsigned long sc_mach; unsigned long sc_mach;
unsigned long sc_macl; unsigned long sc_macl;
#if defined(__SH4__) || defined(CONFIG_CPU_SH4) #if defined(__SH4__) || defined(CONFIG_CPU_SH4) || \
defined(__SH2A__) || defined(CONFIG_CPU_SH2A)
/* FPU registers */ /* FPU registers */
unsigned long sc_fpregs[16]; unsigned long sc_fpregs[16];
unsigned long sc_xfpregs[16]; unsigned long sc_xfpregs[16];
......
...@@ -205,6 +205,8 @@ asmlinkage void name##_trap_handler(unsigned int vec, struct pt_regs *regs) ...@@ -205,6 +205,8 @@ asmlinkage void name##_trap_handler(unsigned int vec, struct pt_regs *regs)
BUILD_TRAP_HANDLER(address_error); BUILD_TRAP_HANDLER(address_error);
BUILD_TRAP_HANDLER(debug); BUILD_TRAP_HANDLER(debug);
BUILD_TRAP_HANDLER(bug); BUILD_TRAP_HANDLER(bug);
BUILD_TRAP_HANDLER(fpu_error);
BUILD_TRAP_HANDLER(fpu_state_restore);
#define arch_align_stack(x) (x) #define arch_align_stack(x) (x)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment