| 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 |  | 
 | 229 |  | 
 | 230 | .macro	movestack	nr,arg1,arg2,arg3,arg4,arg5 | 
 | 231 | 	.if	\nr | 
 | 232 | 	movestack	(\nr-1),\arg2,\arg3,\arg4,\arg5 | 
 | 233 | 	move.l	\arg1,-(%sp) | 
 | 234 | 	.endif | 
 | 235 | .endm | 
 | 236 |  | 
 | 237 | .macro	printf	bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5 | 
 | 238 | #ifdef FPU_EMU_DEBUG | 
 | 239 | 	.data | 
 | 240 | .Lpdata\@: | 
 | 241 | 	.string	"\string" | 
 | 242 | 	.previous | 
 | 243 |  | 
 | 244 | 	movem.l	%d0/%d1/%a0/%a1,-(%sp) | 
 | 245 | 	.if	\bit+1 | 
 | 246 | #if 0 | 
 | 247 | 	moveq	#\bit,%d0 | 
 | 248 | 	andw	#7,%d0 | 
 | 249 | 	btst	%d0,fp_debugprint+((31-\bit)/8) | 
 | 250 | #else | 
 | 251 | 	btst	#\bit,fp_debugprint+((31-\bit)/8) | 
 | 252 | #endif | 
 | 253 | 	jeq	.Lpskip\@ | 
 | 254 | 	.endif | 
 | 255 | 	movestack	\nr,\arg1,\arg2,\arg3,\arg4,\arg5 | 
 | 256 | 	pea	.Lpdata\@ | 
 | 257 | 	jsr	printk | 
 | 258 | 	lea	((\nr+1)*4,%sp),%sp | 
 | 259 | .Lpskip\@: | 
 | 260 | 	movem.l	(%sp)+,%d0/%d1/%a0/%a1 | 
 | 261 | #endif | 
 | 262 | .endm | 
 | 263 |  | 
 | 264 | .macro	printx	bit,fp | 
 | 265 | #ifdef FPU_EMU_DEBUG | 
 | 266 | 	movem.l	%d0/%a0,-(%sp) | 
 | 267 | 	lea	\fp,%a0 | 
 | 268 | #if 0 | 
 | 269 | 	moveq	#'+',%d0 | 
 | 270 | 	tst.w	(%a0) | 
 | 271 | 	jeq	.Lx1\@ | 
 | 272 | 	moveq	#'-',%d0 | 
 | 273 | .Lx1\@:	printf	\bit," %c",1,%d0 | 
 | 274 | 	move.l	(4,%a0),%d0 | 
 | 275 | 	bclr	#31,%d0 | 
 | 276 | 	jne	.Lx2\@ | 
 | 277 | 	printf	\bit,"0." | 
 | 278 | 	jra	.Lx3\@ | 
 | 279 | .Lx2\@:	printf	\bit,"1." | 
 | 280 | .Lx3\@:	printf	\bit,"%08x%08x",2,%d0,%a0@(8) | 
 | 281 | 	move.w	(2,%a0),%d0 | 
 | 282 | 	ext.l	%d0 | 
 | 283 | 	printf	\bit,"E%04x",1,%d0 | 
 | 284 | #else | 
 | 285 | 	printf	\bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8) | 
 | 286 | #endif | 
 | 287 | 	movem.l	(%sp)+,%d0/%a0 | 
 | 288 | #endif | 
 | 289 | .endm | 
 | 290 |  | 
 | 291 | .macro	debug	instr,args | 
 | 292 | #ifdef FPU_EMU_DEBUG | 
 | 293 | 	\instr	\args | 
 | 294 | #endif | 
 | 295 | .endm | 
 | 296 |  | 
 | 297 |  | 
 | 298 | #endif	/* __ASSEMBLY__ */ | 
 | 299 |  | 
 | 300 | #endif	/* _ASM_M68K_SETUP_H */ |