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 */ 317