Commit d9bc15794d122cb7bdc9a069d22f3d3166dd31d4

Authored by GuanXuetao
1 parent 6490988286

unicore32 additional architecture files: float point handling

This patch implements support for float point unit, which using UniCore-F64 FPU hardware
in UniCore32 ISA.

Signed-off-by: Guan Xuetao <gxt@mprc.pku.edu.cn>
Acked-by: Arnd Bergmann <arnd@arndb.de>

Showing 3 changed files with 205 additions and 0 deletions Side-by-side Diff

arch/unicore32/include/asm/fpstate.h
  1 +/*
  2 + * linux/arch/unicore32/include/asm/fpstate.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +
  13 +#ifndef __UNICORE_FPSTATE_H__
  14 +#define __UNICORE_FPSTATE_H__
  15 +
  16 +#ifndef __ASSEMBLY__
  17 +
  18 +#define FP_REGS_NUMBER 33
  19 +
  20 +struct fp_state {
  21 + unsigned int regs[FP_REGS_NUMBER];
  22 +} __attribute__((aligned(8)));
  23 +
  24 +#endif
  25 +
  26 +#endif
arch/unicore32/include/asm/fpu-ucf64.h
  1 +/*
  2 + * linux/arch/unicore32/include/asm/fpu-ucf64.h
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
  7 + * Copyright (C) 2001-2010 Guan Xuetao
  8 + *
  9 + * This program is free software; you can redistribute it and/or modify
  10 + * it under the terms of the GNU General Public License version 2 as
  11 + * published by the Free Software Foundation.
  12 + */
  13 +#define FPSCR s31
  14 +
  15 +/* FPSCR bits */
  16 +#define FPSCR_DEFAULT_NAN (1<<25)
  17 +
  18 +#define FPSCR_CMPINSTR_BIT (1<<31)
  19 +
  20 +#define FPSCR_CON (1<<29)
  21 +#define FPSCR_TRAP (1<<27)
  22 +
  23 +/* RND mode */
  24 +#define FPSCR_ROUND_NEAREST (0<<0)
  25 +#define FPSCR_ROUND_PLUSINF (2<<0)
  26 +#define FPSCR_ROUND_MINUSINF (3<<0)
  27 +#define FPSCR_ROUND_TOZERO (1<<0)
  28 +#define FPSCR_RMODE_BIT (0)
  29 +#define FPSCR_RMODE_MASK (7 << FPSCR_RMODE_BIT)
  30 +
  31 +/* trap enable */
  32 +#define FPSCR_IOE (1<<16)
  33 +#define FPSCR_OFE (1<<14)
  34 +#define FPSCR_UFE (1<<13)
  35 +#define FPSCR_IXE (1<<12)
  36 +#define FPSCR_HIE (1<<11)
  37 +#define FPSCR_NDE (1<<10) /* non denomal */
  38 +
  39 +/* flags */
  40 +#define FPSCR_IDC (1<<24)
  41 +#define FPSCR_HIC (1<<23)
  42 +#define FPSCR_IXC (1<<22)
  43 +#define FPSCR_OFC (1<<21)
  44 +#define FPSCR_UFC (1<<20)
  45 +#define FPSCR_IOC (1<<19)
  46 +
  47 +/* stick bits */
  48 +#define FPSCR_IOS (1<<9)
  49 +#define FPSCR_OFS (1<<7)
  50 +#define FPSCR_UFS (1<<6)
  51 +#define FPSCR_IXS (1<<5)
  52 +#define FPSCR_HIS (1<<4)
  53 +#define FPSCR_NDS (1<<3) /*non denomal */
arch/unicore32/kernel/fpu-ucf64.c
  1 +/*
  2 + * linux/arch/unicore32/kernel/fpu-ucf64.c
  3 + *
  4 + * Code specific to PKUnity SoC and UniCore ISA
  5 + *
  6 + * Copyright (C) 2001-2010 GUAN Xue-tao
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +#include <linux/module.h>
  13 +#include <linux/types.h>
  14 +#include <linux/kernel.h>
  15 +#include <linux/signal.h>
  16 +#include <linux/sched.h>
  17 +#include <linux/init.h>
  18 +
  19 +#include <asm/fpu-ucf64.h>
  20 +
  21 +/*
  22 + * A special flag to tell the normalisation code not to normalise.
  23 + */
  24 +#define F64_NAN_FLAG 0x100
  25 +
  26 +/*
  27 + * A bit pattern used to indicate the initial (unset) value of the
  28 + * exception mask, in case nothing handles an instruction. This
  29 + * doesn't include the NAN flag, which get masked out before
  30 + * we check for an error.
  31 + */
  32 +#define F64_EXCEPTION_ERROR ((u32)-1 & ~F64_NAN_FLAG)
  33 +
  34 +/*
  35 + * Since we aren't building with -mfpu=f64, we need to code
  36 + * these instructions using their MRC/MCR equivalents.
  37 + */
  38 +#define f64reg(_f64_) #_f64_
  39 +
  40 +#define cff(_f64_) ({ \
  41 + u32 __v; \
  42 + asm("cff %0, " f64reg(_f64_) "@ fmrx %0, " #_f64_ \
  43 + : "=r" (__v) : : "cc"); \
  44 + __v; \
  45 + })
  46 +
  47 +#define ctf(_f64_, _var_) \
  48 + asm("ctf %0, " f64reg(_f64_) "@ fmxr " #_f64_ ", %0" \
  49 + : : "r" (_var_) : "cc")
  50 +
  51 +/*
  52 + * Raise a SIGFPE for the current process.
  53 + * sicode describes the signal being raised.
  54 + */
  55 +void ucf64_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
  56 +{
  57 + siginfo_t info;
  58 +
  59 + memset(&info, 0, sizeof(info));
  60 +
  61 + info.si_signo = SIGFPE;
  62 + info.si_code = sicode;
  63 + info.si_addr = (void __user *)(instruction_pointer(regs) - 4);
  64 +
  65 + /*
  66 + * This is the same as NWFPE, because it's not clear what
  67 + * this is used for
  68 + */
  69 + current->thread.error_code = 0;
  70 + current->thread.trap_no = 6;
  71 +
  72 + send_sig_info(SIGFPE, &info, current);
  73 +}
  74 +
  75 +/*
  76 + * Handle exceptions of UniCore-F64.
  77 + */
  78 +void ucf64_exchandler(u32 inst, u32 fpexc, struct pt_regs *regs)
  79 +{
  80 + u32 tmp = fpexc;
  81 + u32 exc = F64_EXCEPTION_ERROR & fpexc;
  82 +
  83 + pr_debug("UniCore-F64: instruction %08x fpscr %08x\n",
  84 + inst, fpexc);
  85 +
  86 + if (exc & FPSCR_CMPINSTR_BIT) {
  87 + if (exc & FPSCR_CON)
  88 + tmp |= FPSCR_CON;
  89 + else
  90 + tmp &= ~(FPSCR_CON);
  91 + exc &= ~(FPSCR_CMPINSTR_BIT | FPSCR_CON);
  92 + } else {
  93 + pr_debug(KERN_ERR "UniCore-F64 Error: unhandled exceptions\n");
  94 + pr_debug(KERN_ERR "UniCore-F64 FPSCR 0x%08x INST 0x%08x\n",
  95 + cff(FPSCR), inst);
  96 +
  97 + ucf64_raise_sigfpe(0, regs);
  98 + return;
  99 + }
  100 +
  101 + /*
  102 + * Update the FPSCR with the additional exception flags.
  103 + * Comparison instructions always return at least one of
  104 + * these flags set.
  105 + */
  106 + tmp &= ~(FPSCR_TRAP | FPSCR_IOS | FPSCR_OFS | FPSCR_UFS |
  107 + FPSCR_IXS | FPSCR_HIS | FPSCR_IOC | FPSCR_OFC |
  108 + FPSCR_UFC | FPSCR_IXC | FPSCR_HIC);
  109 +
  110 + tmp |= exc;
  111 + ctf(FPSCR, tmp);
  112 +}
  113 +
  114 +/*
  115 + * F64 support code initialisation.
  116 + */
  117 +static int __init ucf64_init(void)
  118 +{
  119 + ctf(FPSCR, 0x0); /* FPSCR_UFE | FPSCR_NDE perhaps better */
  120 +
  121 + printk(KERN_INFO "Enable UniCore-F64 support.\n");
  122 +
  123 + return 0;
  124 +}
  125 +
  126 +late_initcall(ucf64_init);