linux/arch/m68k/include/asm/math-emu.h
<<
>>
Prefs
   1#ifndef _ASM_M68K_SETUP_H
   2#define _ASM_M68K_SETUP_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#ifdef 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_OFF_D0)
 149#define FPS_D1          (PT_OFF_D1)
 150#define FPS_D2          (PT_OFF_D2)
 151#define FPS_A0          (PT_OFF_A0)
 152#define FPS_A1          (PT_OFF_A1)
 153#define FPS_A2          (PT_OFF_A2)
 154#define FPS_SR          (PT_OFF_SR)
 155#define FPS_PC          (PT_OFF_PC)
 156#define FPS_EA          (PT_OFF_PC+6)
 157#define FPS_PC2         (PT_OFF_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/* work around binutils idiocy */
 230old_gas=-1
 231.irp    gas_ident.x .x
 232old_gas=old_gas+1
 233.endr
 234.if !old_gas
 235.irp    m b,w,l
 236.macro  getuser.\m src,dest,label,addr
 237        getuser .\m,\src,\dest,\label,\addr
 238.endm
 239.macro  putuser.\m src,dest,label,addr
 240        putuser .\m,\src,\dest,\label,\addr
 241.endm
 242.endr
 243.endif
 244
 245.macro  movestack       nr,arg1,arg2,arg3,arg4,arg5
 246        .if     \nr
 247        movestack       (\nr-1),\arg2,\arg3,\arg4,\arg5
 248        move.l  \arg1,-(%sp)
 249        .endif
 250.endm
 251
 252.macro  printf  bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5
 253#ifdef FPU_EMU_DEBUG
 254        .data
 255.Lpdata\@:
 256        .string "\string"
 257        .previous
 258
 259        movem.l %d0/%d1/%a0/%a1,-(%sp)
 260        .if     \bit+1
 261#if 0
 262        moveq   #\bit,%d0
 263        andw    #7,%d0
 264        btst    %d0,fp_debugprint+((31-\bit)/8)
 265#else
 266        btst    #\bit,fp_debugprint+((31-\bit)/8)
 267#endif
 268        jeq     .Lpskip\@
 269        .endif
 270        movestack       \nr,\arg1,\arg2,\arg3,\arg4,\arg5
 271        pea     .Lpdata\@
 272        jsr     printk
 273        lea     ((\nr+1)*4,%sp),%sp
 274.Lpskip\@:
 275        movem.l (%sp)+,%d0/%d1/%a0/%a1
 276#endif
 277.endm
 278
 279.macro  printx  bit,fp
 280#ifdef FPU_EMU_DEBUG
 281        movem.l %d0/%a0,-(%sp)
 282        lea     \fp,%a0
 283#if 0
 284        moveq   #'+',%d0
 285        tst.w   (%a0)
 286        jeq     .Lx1\@
 287        moveq   #'-',%d0
 288.Lx1\@: printf  \bit," %c",1,%d0
 289        move.l  (4,%a0),%d0
 290        bclr    #31,%d0
 291        jne     .Lx2\@
 292        printf  \bit,"0."
 293        jra     .Lx3\@
 294.Lx2\@: printf  \bit,"1."
 295.Lx3\@: printf  \bit,"%08x%08x",2,%d0,%a0@(8)
 296        move.w  (2,%a0),%d0
 297        ext.l   %d0
 298        printf  \bit,"E%04x",1,%d0
 299#else
 300        printf  \bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8)
 301#endif
 302        movem.l (%sp)+,%d0/%a0
 303#endif
 304.endm
 305
 306.macro  debug   instr,args
 307#ifdef FPU_EMU_DEBUG
 308        \instr  \args
 309#endif
 310.endm
 311
 312
 313#endif  /* __ASSEMBLY__ */
 314
 315#endif  /* _ASM_M68K_SETUP_H */
 316