root/arch/m68k/include/asm/math-emu.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


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

/* [<][>][^][v][top][bottom][index][help] */