| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  | 
|  | 74 | union fp_mant64 { | 
|  | 75 | unsigned long long m64; | 
|  | 76 | unsigned long m32[2]; | 
|  | 77 | }; | 
|  | 78 |  | 
|  | 79 | union fp_mant128 { | 
|  | 80 | unsigned long long m64[2]; | 
|  | 81 | unsigned long m32[4]; | 
|  | 82 | }; | 
|  | 83 |  | 
|  | 84 | /* internal representation of extended fp numbers */ | 
|  | 85 | struct 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 */ | 
|  | 95 | struct 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 | 
|  | 106 | extern 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 |  | 
| Al Viro | 3813561 | 2007-02-10 01:43:41 -0800 | [diff] [blame] | 229 | /* work around binutils idiocy */ | 
|  | 230 | old_gas=-1 | 
|  | 231 | .irp    gas_ident.x .x | 
|  | 232 | old_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 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 */ |