⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 math.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  arch/s390/math-emu/math.c * *  S390 version *    Copyright (C) 1999-2001 IBM Deutschland Entwicklung GmbH, IBM Corporation *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * * 'math.c' emulates IEEE instructions on a S390 processor *          that does not have the IEEE fpu (all processors before G5). */#include <linux/config.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/mm.h>#include <asm/uaccess.h>#include <asm/lowcore.h>#include "sfp-util.h"#include <math-emu/soft-fp.h>#include <math-emu/single.h>#include <math-emu/double.h>#include <math-emu/quad.h>/* * I miss a macro to round a floating point number to the * nearest integer in the same floating point format. */#define _FP_TO_FPINT_ROUND(fs, wc, X)					\  do {									\    switch (X##_c)							\      {									\      case FP_CLS_NORMAL:						\        if (X##_e > _FP_FRACBITS_##fs + _FP_EXPBIAS_##fs)		\          { /* floating point number has no bits after the dot. */	\          }								\        else if (X##_e <= _FP_FRACBITS_##fs + _FP_EXPBIAS_##fs &&	\                 X##_e > _FP_EXPBIAS_##fs)				\	  { /* some bits before the dot, some after it. */		\            _FP_FRAC_SRS_##wc(X, _FP_WFRACBITS_##fs,			\                              X##_e - _FP_EXPBIAS_##fs			\                              + _FP_FRACBITS_##fs);			\	    _FP_ROUND(wc, X);						\	    _FP_FRAC_SLL_##wc(X, X##_e - _FP_EXPBIAS_##fs		\                              + _FP_FRACBITS_##fs);			\          }								\        else								\          { /* all bits after the dot. */				\	    FP_SET_EXCEPTION(FP_EX_INEXACT);				\            X##_c = FP_CLS_ZERO;					\	  }								\        break;								\      case FP_CLS_NAN:							\      case FP_CLS_INF:							\      case FP_CLS_ZERO:							\        break;								\      }									\  } while (0)#define FP_TO_FPINT_ROUND_S(X)	_FP_TO_FPINT_ROUND(S,1,X)#define FP_TO_FPINT_ROUND_D(X)	_FP_TO_FPINT_ROUND(D,2,X)#define FP_TO_FPINT_ROUND_Q(X)	_FP_TO_FPINT_ROUND(Q,4,X)typedef union {        long double ld;        struct {                __u64 high;                __u64 low;        } w;} mathemu_ldcv;#ifdef CONFIG_SYSCTLint sysctl_ieee_emulation_warnings=1;#endif#define mathemu_put_user(x, p) \        do { \                if (put_user((x),(p))) \                        return SIGSEGV; \        } while (0)#define mathemu_get_user(x, p) \        do { \                if (get_user((x),(p))) \                        return SIGSEGV; \        } while (0)#define mathemu_copy_from_user(d, s, n)\        do { \                if (copy_from_user((d),(s),(n)) != 0) \                        return SIGSEGV; \        } while (0)#define mathemu_copy_to_user(d, s, n) \        do { \                if (copy_to_user((d),(s),(n)) != 0) \                        return SIGSEGV; \        } while (0)static void display_emulation_not_implemented(struct pt_regs *regs, char *instr){        __u16 *location;        #ifdef CONFIG_SYSCTL        if(sysctl_ieee_emulation_warnings)#endif        {                location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);                printk("%s ieee fpu instruction not emulated "                       "process name: %s pid: %d \n",                       instr, current->comm, current->pid);                printk("%s's PSW:    %08lx %08lx\n", instr,                       (unsigned long) regs->psw.mask,                       (unsigned long) location);        }}static inline void emu_set_CC (struct pt_regs *regs, int cc){        regs->psw.mask = (regs->psw.mask & 0xFFFFCFFF) | ((cc&3) << 12);}/* * Set the condition code in the user psw. *  0 : Result is zero *  1 : Result is less than zero *  2 : Result is greater than zero *  3 : Result is NaN or INF */static inline void emu_set_CC_cs(struct pt_regs *regs, int class, int sign){        switch (class) {        case FP_CLS_NORMAL:        case FP_CLS_INF:                emu_set_CC(regs, sign ? 1 : 2);                break;        case FP_CLS_ZERO:                emu_set_CC(regs, 0);                break;        case FP_CLS_NAN:                emu_set_CC(regs, 3);                break;        }}/* Add long double */static int emu_axbr (struct pt_regs *regs, int rx, int ry) {        FP_DECL_Q(QA); FP_DECL_Q(QB); FP_DECL_Q(QR);        FP_DECL_EX;	mathemu_ldcv cvt;        int mode;	mode = current->thread.fp_regs.fpc & 3;        cvt.w.high = current->thread.fp_regs.fprs[rx].ui;        cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;        FP_UNPACK_QP(QA, &cvt.ld);        cvt.w.high = current->thread.fp_regs.fprs[ry].ui;        cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;        FP_UNPACK_QP(QB, &cvt.ld);        FP_ADD_Q(QR, QA, QB);        FP_PACK_QP(&cvt.ld, QR);        current->thread.fp_regs.fprs[rx].ui = cvt.w.high;        current->thread.fp_regs.fprs[rx+2].ui = cvt.w.low;        emu_set_CC_cs(regs, QR_c, QR_s);        return _fex;}/* Add double */static int emu_adbr (struct pt_regs *regs, int rx, int ry) {        FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);        FP_DECL_EX;        int mode;	mode = current->thread.fp_regs.fpc & 3;        FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);        FP_UNPACK_DP(DB, &current->thread.fp_regs.fprs[ry].d);        FP_ADD_D(DR, DA, DB);	FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);        emu_set_CC_cs(regs, DR_c, DR_s);        return _fex;}/* Add double */static int emu_adb (struct pt_regs *regs, int rx, double *val) {        FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);        FP_DECL_EX;        int mode;	mode = current->thread.fp_regs.fpc & 3;        FP_UNPACK_DP(DA, &current->thread.fp_regs.fprs[rx].d);        FP_UNPACK_DP(DB, val);        FP_ADD_D(DR, DA, DB);	FP_PACK_DP(&current->thread.fp_regs.fprs[rx].d, DR);        emu_set_CC_cs(regs, DR_c, DR_s);        return _fex;}/* Add float */static int emu_aebr (struct pt_regs *regs, int rx, int ry) {        FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);        FP_DECL_EX;        int mode;	mode = current->thread.fp_regs.fpc & 3;        FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);        FP_UNPACK_SP(SB, &current->thread.fp_regs.fprs[ry].f);        FP_ADD_S(SR, SA, SB);	FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);        emu_set_CC_cs(regs, SR_c, SR_s);        return _fex;}/* Add float */static int emu_aeb (struct pt_regs *regs, int rx, float *val) {        FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);        FP_DECL_EX;        int mode;	mode = current->thread.fp_regs.fpc & 3;        FP_UNPACK_SP(SA, &current->thread.fp_regs.fprs[rx].f);        FP_UNPACK_SP(SB, val);        FP_ADD_S(SR, SA, SB);	FP_PACK_SP(&current->thread.fp_regs.fprs[rx].f, SR);        emu_set_CC_cs(regs, SR_c, SR_s);        return _fex;}/* Compare long double */static int emu_cxbr (struct pt_regs *regs, int rx, int ry) {        FP_DECL_Q(QA); FP_DECL_Q(QB);	mathemu_ldcv cvt;        int IR;        cvt.w.high = current->thread.fp_regs.fprs[rx].ui;        cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;        FP_UNPACK_RAW_QP(QA, &cvt.ld);        cvt.w.high = current->thread.fp_regs.fprs[ry].ui;        cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;        FP_UNPACK_RAW_QP(QB, &cvt.ld);        FP_CMP_Q(IR, QA, QB, 3);        /*         * IR == -1 if DA < DB, IR == 0 if DA == DB,         * IR == 1 if DA > DB and IR == 3 if unorderded         */        emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);        return 0;}/* Compare double */static int emu_cdbr (struct pt_regs *regs, int rx, int ry) {        FP_DECL_D(DA); FP_DECL_D(DB);        int IR;        FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d);        FP_UNPACK_RAW_DP(DB, &current->thread.fp_regs.fprs[ry].d);        FP_CMP_D(IR, DA, DB, 3);        /*         * IR == -1 if DA < DB, IR == 0 if DA == DB,         * IR == 1 if DA > DB and IR == 3 if unorderded         */        emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);        return 0;}/* Compare double */static int emu_cdb (struct pt_regs *regs, int rx, double *val) {        FP_DECL_D(DA); FP_DECL_D(DB);        int IR;        FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d);        FP_UNPACK_RAW_DP(DB, val);        FP_CMP_D(IR, DA, DB, 3);        /*         * IR == -1 if DA < DB, IR == 0 if DA == DB,         * IR == 1 if DA > DB and IR == 3 if unorderded         */        emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);        return 0;}/* Compare float */static int emu_cebr (struct pt_regs *regs, int rx, int ry) {        FP_DECL_S(SA); FP_DECL_S(SB);        int IR;        FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f);        FP_UNPACK_RAW_SP(SB, &current->thread.fp_regs.fprs[ry].f);        FP_CMP_S(IR, SA, SB, 3);        /*         * IR == -1 if DA < DB, IR == 0 if DA == DB,         * IR == 1 if DA > DB and IR == 3 if unorderded         */        emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);        return 0;}/* Compare float */static int emu_ceb (struct pt_regs *regs, int rx, float *val) {        FP_DECL_S(SA); FP_DECL_S(SB);        int IR;        FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f);        FP_UNPACK_RAW_SP(SB, val);        FP_CMP_S(IR, SA, SB, 3);        /*         * IR == -1 if DA < DB, IR == 0 if DA == DB,         * IR == 1 if DA > DB and IR == 3 if unorderded         */        emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);        return 0;}/* Compare and signal long double */static int emu_kxbr (struct pt_regs *regs, int rx, int ry) {        FP_DECL_Q(QA); FP_DECL_Q(QB);        FP_DECL_EX;	mathemu_ldcv cvt;        int IR;        cvt.w.high = current->thread.fp_regs.fprs[rx].ui;        cvt.w.low = current->thread.fp_regs.fprs[rx+2].ui;        FP_UNPACK_RAW_QP(QA, &cvt.ld);        cvt.w.high = current->thread.fp_regs.fprs[ry].ui;        cvt.w.low = current->thread.fp_regs.fprs[ry+2].ui;        FP_UNPACK_QP(QB, &cvt.ld);        FP_CMP_Q(IR, QA, QB, 3);        /*         * IR == -1 if DA < DB, IR == 0 if DA == DB,         * IR == 1 if DA > DB and IR == 3 if unorderded         */        emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);        if (IR == 3)                FP_SET_EXCEPTION (FP_EX_INVALID);        return _fex;}/* Compare and signal double */static int emu_kdbr (struct pt_regs *regs, int rx, int ry) {        FP_DECL_D(DA); FP_DECL_D(DB);        FP_DECL_EX;        int IR;        FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d);        FP_UNPACK_RAW_DP(DB, &current->thread.fp_regs.fprs[ry].d);        FP_CMP_D(IR, DA, DB, 3);        /*         * IR == -1 if DA < DB, IR == 0 if DA == DB,         * IR == 1 if DA > DB and IR == 3 if unorderded         */        emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);        if (IR == 3)                FP_SET_EXCEPTION (FP_EX_INVALID);        return _fex;}/* Compare and signal double */static int emu_kdb (struct pt_regs *regs, int rx, double *val) {        FP_DECL_D(DA); FP_DECL_D(DB);        FP_DECL_EX;        int IR;        FP_UNPACK_RAW_DP(DA, &current->thread.fp_regs.fprs[rx].d);        FP_UNPACK_RAW_DP(DB, val);        FP_CMP_D(IR, DA, DB, 3);        /*         * IR == -1 if DA < DB, IR == 0 if DA == DB,         * IR == 1 if DA > DB and IR == 3 if unorderded         */        emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);        if (IR == 3)                FP_SET_EXCEPTION (FP_EX_INVALID);        return _fex;}/* Compare and signal float */static int emu_kebr (struct pt_regs *regs, int rx, int ry) {        FP_DECL_S(SA); FP_DECL_S(SB);        FP_DECL_EX;        int IR;        FP_UNPACK_RAW_SP(SA, &current->thread.fp_regs.fprs[rx].f);        FP_UNPACK_RAW_SP(SB, &current->thread.fp_regs.fprs[ry].f);        FP_CMP_S(IR, SA, SB, 3);        /*         * IR == -1 if DA < DB, IR == 0 if DA == DB,         * IR == 1 if DA > DB and IR == 3 if unorderded         */        emu_set_CC(regs, (IR == -1) ? 1 : (IR == 1) ? 2 : IR);        if (IR == 3)                FP_SET_EXCEPTION (FP_EX_INVALID);        return _fex;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -