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