linux/arch/frv/include/asm/math-emu.h
<<
>>
Prefs
   1#ifndef _ASM_MATH_EMU_H
   2#define _ASM_MATH_EMU_H
   3
   4#include <asm/setup.h>
   5#include <linux/linkage.h>
   6
   7/* Status Register bits */
   8
   9/* accrued exception bits */
  10#define FPSR_AEXC_INEX  3
  11#define FPSR_AEXC_DZ    4
  12#define FPSR_AEXC_UNFL  5
  13#define FPSR_AEXC_OVFL  6
  14#define FPSR_AEXC_IOP   7
  15
  16/* exception status bits */
  17#define FPSR_EXC_INEX1  8
  18#define FPSR_EXC_INEX2  9
  19#define FPSR_EXC_DZ     10
  20#define FPSR_EXC_UNFL   11
  21#define FPSR_EXC_OVFL   12
  22#define FPSR_EXC_OPERR  13
  23#define FPSR_EXC_SNAN   14
  24#define FPSR_EXC_BSUN   15
  25
  26/* quotient byte, assumes big-endian, of course */
  27#define FPSR_QUOTIENT(fpsr) (*((signed char *) &(fpsr) + 1))
  28
  29/* condition code bits */
  30#define FPSR_CC_NAN     24
  31#define FPSR_CC_INF     25
  32#define FPSR_CC_Z       26
  33#define FPSR_CC_NEG     27
  34
  35
  36/* Control register bits */
  37
  38/* rounding mode */
  39#define FPCR_ROUND_RN   0               /* round to nearest/even */
  40#define FPCR_ROUND_RZ   1               /* round to zero */
  41#define FPCR_ROUND_RM   2               /* minus infinity */
  42#define FPCR_ROUND_RP   3               /* plus infinity */
  43
  44/* rounding precision */
  45#define FPCR_PRECISION_X        0       /* long double */
  46#define FPCR_PRECISION_S        1       /* double */
  47#define FPCR_PRECISION_D        2       /* float */
  48
  49
  50/* Flags to select the debugging output */
  51#define PDECODE         0
  52#define PEXECUTE        1
  53#define PCONV           2
  54#define PNORM           3
  55#define PREGISTER       4
  56#define PINSTR          5
  57#define PUNIMPL         6
  58#define PMOVEM          7
  59
  60#define PMDECODE        (1<<PDECODE)
  61#define PMEXECUTE       (1<<PEXECUTE)
  62#define PMCONV          (1<<PCONV)
  63#define PMNORM          (1<<PNORM)
  64#define PMREGISTER      (1<<PREGISTER)
  65#define PMINSTR         (1<<PINSTR)
  66#define PMUNIMPL        (1<<PUNIMPL)
  67#define PMMOVEM         (1<<PMOVEM)
  68
  69#ifndef __ASSEMBLY__
  70
  71#include <linux/kernel.h>
  72#include <linux/sched.h>
  73
  74union fp_mant64 {
  75        unsigned long long m64;
  76        unsigned long m32[2];
  77};
  78
  79union fp_mant128 {
  80        unsigned long long m64[2];
  81        unsigned long m32[4];
  82};
  83
  84/* internal representation of extended fp numbers */
  85struct fp_ext {
  86        unsigned char lowmant;
  87        unsigned char sign;
  88        unsigned short exp;
  89        union fp_mant64 mant;
  90};
  91
  92/* C representation of FPU registers */
  93/* NOTE: if you change this, you have to change the assembler offsets
  94   below and the size in <asm/fpu.h>, too */
  95struct fp_data {
  96        struct fp_ext fpreg[8];
  97        unsigned int fpcr;
  98        unsigned int fpsr;
  99        unsigned int fpiar;
 100        unsigned short prec;
 101        unsigned short rnd;
 102        struct fp_ext temp[2];
 103};
 104
 105#if FPU_EMU_DEBUG
 106extern unsigned int fp_debugprint;
 107
 108#define dprint(bit, fmt, args...) ({                    \
 109        if (fp_debugprint & (1 << (bit)))               \
 110                printk(fmt, ## args);                   \
 111})
 112#else
 113#define dprint(bit, fmt, args...)
 114#endif
 115
 116#define uprint(str) ({                                  \
 117        static int __count = 3;                         \
 118                                                        \
 119        if (__count > 0) {                              \
 120                printk("You just hit an unimplemented " \
 121                       "fpu instruction (%s)\n", str);  \
 122                printk("Please report this to ....\n"); \
 123                __count--;                              \
 124        }                                               \
 125})
 126
 127#define FPDATA          ((struct fp_data *)current->thread.fp)
 128
 129#else   /* __ASSEMBLY__ */
 130
 131#define FPDATA          %a2
 132
 133/* offsets from the base register to the floating point data in the task struct */
 134#define FPD_FPREG       (TASK_THREAD+THREAD_FPREG+0)
 135#define FPD_FPCR        (TASK_THREAD+THREAD_FPREG+96)
 136#define FPD_FPSR        (TASK_THREAD+THREAD_FPREG+100)
 137#define FPD_FPIAR       (TASK_THREAD+THREAD_FPREG+104)
 138#define FPD_PREC        (TASK_THREAD+THREAD_FPREG+108)
 139#define FPD_RND         (TASK_THREAD+THREAD_FPREG+110)
 140#define FPD_TEMPFP1     (TASK_THREAD+THREAD_FPREG+112)
 141#define FPD_TEMPFP2     (TASK_THREAD+THREAD_FPREG+124)
 142#define FPD_SIZEOF      (TASK_THREAD+THREAD_FPREG+136)
 143
 144/* offsets on the stack to access saved registers,
 145 * these are only used during instruction decoding
 146 * where we always know how deep we're on the stack.
 147 */
 148#define FPS_DO          (PT_D0)
 149#define FPS_D1          (PT_D1)
 150#define FPS_D2          (PT_D2)
 151#define FPS_A0          (PT_A0)
 152#define FPS_A1          (PT_A1)
 153#define FPS_A2          (PT_A2)
 154#define FPS_SR          (PT_SR)
 155#define FPS_PC          (PT_PC)
 156#define FPS_EA          (PT_PC+6)
 157#define FPS_PC2         (PT_PC+10)
 158
 159.macro  fp_get_fp_reg
 160        lea     (FPD_FPREG,FPDATA,%d0.w*4),%a0
 161        lea     (%a0,%d0.w*8),%a0
 162.endm
 163
 164/* Macros used to get/put the current program counter.
 165 * 020/030 use a different stack frame then 040/060, for the
 166 * 040/060 the return pc points already to the next location,
 167 * so this only needs to be modified for jump instructions.
 168 */
 169.macro  fp_get_pc dest
 170        move.l  (FPS_PC+4,%sp),\dest
 171.endm
 172
 173.macro  fp_put_pc src,jump=0
 174        move.l  \src,(FPS_PC+4,%sp)
 175.endm
 176
 177.macro  fp_get_instr_data       f,s,dest,label
 178        getuser \f,%sp@(FPS_PC+4)@(0),\dest,\label,%sp@(FPS_PC+4)
 179        addq.l  #\s,%sp@(FPS_PC+4)
 180.endm
 181
 182.macro  fp_get_instr_word       dest,label,addr
 183        fp_get_instr_data       w,2,\dest,\label,\addr
 184.endm
 185
 186.macro  fp_get_instr_long       dest,label,addr
 187        fp_get_instr_data       l,4,\dest,\label,\addr
 188.endm
 189
 190/* These macros are used to read from/write to user space
 191 * on error we jump to the fixup section, load the fault
 192 * address into %a0 and jump to the exit.
 193 * (derived from <asm/uaccess.h>)
 194 */
 195.macro  getuser size,src,dest,label,addr
 196|       printf  ,"[\size<%08x]",1,\addr
 197.Lu1\@: moves\size      \src,\dest
 198
 199        .section .fixup,"ax"
 200        .even
 201.Lu2\@: move.l  \addr,%a0
 202        jra     \label
 203        .previous
 204
 205        .section __ex_table,"a"
 206        .align  4
 207        .long   .Lu1\@,.Lu2\@
 208        .previous
 209.endm
 210
 211.macro  putuser size,src,dest,label,addr
 212|       printf  ,"[\size>%08x]",1,\addr
 213.Lu1\@: moves\size      \src,\dest
 214.Lu2\@:
 215
 216        .section .fixup,"ax"
 217        .even
 218.Lu3\@: move.l  \addr,%a0
 219        jra     \label
 220        .previous
 221
 222        .section __ex_table,"a"
 223        .align  4
 224        .long   .Lu1\@,.Lu3\@
 225        .long   .Lu2\@,.Lu3\@
 226        .previous
 227.endm
 228
 229
 230.macro  movestack       nr,arg1,arg2,arg3,arg4,arg5
 231        .if     \nr
 232        movestack       (\nr-1),\arg2,\arg3,\arg4,\arg5
 233        move.l  \arg1,-(%sp)
 234        .endif
 235.endm
 236
 237.macro  printf  bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5
 238#ifdef FPU_EMU_DEBUG
 239        .data
 240.Lpdata\@:
 241        .string "\string"
 242        .previous
 243
 244        movem.l %d0/%d1/%a0/%a1,-(%sp)
 245        .if     \bit+1
 246#if 0
 247        moveq   #\bit,%d0
 248        andw    #7,%d0
 249        btst    %d0,fp_debugprint+((31-\bit)/8)
 250#else
 251        btst    #\bit,fp_debugprint+((31-\bit)/8)
 252#endif
 253        jeq     .Lpskip\@
 254        .endif
 255        movestack       \nr,\arg1,\arg2,\arg3,\arg4,\arg5
 256        pea     .Lpdata\@
 257        jsr     printk
 258        lea     ((\nr+1)*4,%sp),%sp
 259.Lpskip\@:
 260        movem.l (%sp)+,%d0/%d1/%a0/%a1
 261#endif
 262.endm
 263
 264.macro  printx  bit,fp
 265#ifdef FPU_EMU_DEBUG
 266        movem.l %d0/%a0,-(%sp)
 267        lea     \fp,%a0
 268#if 0
 269        moveq   #'+',%d0
 270        tst.w   (%a0)
 271        jeq     .Lx1\@
 272        moveq   #'-',%d0
 273.Lx1\@: printf  \bit," %c",1,%d0
 274        move.l  (4,%a0),%d0
 275        bclr    #31,%d0
 276        jne     .Lx2\@
 277        printf  \bit,"0."
 278        jra     .Lx3\@
 279.Lx2\@: printf  \bit,"1."
 280.Lx3\@: printf  \bit,"%08x%08x",2,%d0,%a0@(8)
 281        move.w  (2,%a0),%d0
 282        ext.l   %d0
 283        printf  \bit,"E%04x",1,%d0
 284#else
 285        printf  \bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8)
 286#endif
 287        movem.l (%sp)+,%d0/%a0
 288#endif
 289.endm
 290
 291.macro  debug   instr,args
 292#ifdef FPU_EMU_DEBUG
 293        \instr  \args
 294#endif
 295.endm
 296
 297
 298#endif  /* __ASSEMBLY__ */
 299
 300#endif  /* _ASM_FRV_MATH_EMU_H */
 301
 302