1 /*
2  * include/asm-sh/processor.h
3  *
4  * Copyright (C) 1999, 2000  Niibe Yutaka
5  */
6 
7 #ifndef __ASM_SH_PROCESSOR_H
8 #define __ASM_SH_PROCESSOR_H
9 
10 #include <asm/page.h>
11 #include <asm/types.h>
12 #include <linux/threads.h>
13 
14 /*
15  * Default implementation of macro that returns current
16  * instruction pointer ("program counter").
17  */
18 #define current_text_addr() ({ void *pc; __asm__("mova	1f, %0\n1:":"=z" (pc)); pc; })
19 
20 /*
21  *  CPU type and hardware bug flags. Kept separately for each CPU.
22  */
23 enum cpu_type {
24 	CPU_SH7708,		/* Represents 7707, 7708, 7708S, 7708R, 7709 */
25 	CPU_SH7729,		/* Represents 7709A, 7729 */
26 	CPU_SH7750,             /* Represents 7750, 7751 */
27 	CPU_ST40,		/* Represents ST40STB1 and ST40GX1 */
28         CPU_SH4202,
29 	CPU_SH_NONE
30 };
31 
32 struct sh_cpuinfo {
33 	enum cpu_type type;
34 	char	hard_math;
35 	unsigned long loops_per_jiffy;
36 
37 	unsigned int cpu_clock, master_clock, bus_clock, module_clock;
38 #ifdef CONFIG_CPU_SUBTYPE_ST40
39 	unsigned int memory_clock;
40 #endif
41 };
42 
43 extern struct sh_cpuinfo boot_cpu_data;
44 
45 #define cpu_data (&boot_cpu_data)
46 #define current_cpu_data boot_cpu_data
47 
48 /*
49  * User space process size: 2GB.
50  *
51  * Since SH7709 and SH7750 have "area 7", we can't use 0x7c000000--0x7fffffff
52  */
53 #define TASK_SIZE	0x7c000000UL
54 
55 /* This decides where the kernel will search for a free chunk of vm
56  * space during mmap's.
57  */
58 #define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
59 
60 /*
61  * Bit of SR register
62  *
63  * FD-bit:
64  *     When it's set, it means the processor doesn't have right to use FPU,
65  *     and it results exception when the floating operation is executed.
66  *
67  * IMASK-bit:
68  *     Interrupt level mask
69  */
70 #define SR_FD    0x00008000
71 #define SR_DSP   0x00001000
72 #define SR_IMASK 0x000000f0
73 
74 /*
75  * FPU structure and data
76  */
77 
78 struct sh_fpu_hard_struct {
79 	unsigned long fp_regs[16];
80 	unsigned long xfp_regs[16];
81 	unsigned long fpscr;
82 	unsigned long fpul;
83 
84 	long status; /* software status information */
85 };
86 
87 /* Dummy fpu emulator  */
88 struct sh_fpu_soft_struct {
89 	unsigned long fp_regs[16];
90 	unsigned long xfp_regs[16];
91 	unsigned long fpscr;
92 	unsigned long fpul;
93 
94 	unsigned char lookahead;
95 	unsigned long entry_pc;
96 };
97 
98 union sh_fpu_union {
99 	struct sh_fpu_hard_struct hard;
100 	struct sh_fpu_soft_struct soft;
101 };
102 
103 struct thread_struct {
104 	unsigned long sp;
105 	unsigned long pc;
106 
107 	unsigned long trap_no, error_code;
108 	unsigned long address;
109 
110 	/* Hardware debugging registers */
111 	unsigned long ubc_pc1, ubc_pc2;
112 
113 	/* floating point info */
114 	union sh_fpu_union fpu;
115 };
116 
117 /* Count of active tasks with UBC settings */
118 extern int ubc_usercnt;
119 
120 #define INIT_THREAD  {						\
121 	sizeof(init_stack) + (long) &init_stack, /* sp */	\
122 	0,					 /* pc */	\
123 	0, 0, 							\
124 	0, 							\
125 	0, -1, 							\
126 	{{{0,}},} 				/* fpu state */	\
127 }
128 
129 /*
130  * Do necessary setup to start up a newly executed thread.
131  */
132 #define start_thread(regs, new_pc, new_sp)	 \
133 	set_fs(USER_DS);			 \
134 	regs->pr = 0;   		 	 \
135 	regs->sr = 0;		/* User mode. */ \
136 	regs->pc = new_pc;			 \
137 	regs->regs[15] = new_sp
138 
139 /* Forward declaration, a strange C thing */
140 struct task_struct;
141 struct mm_struct;
142 
143 /* Free all resources held by a thread. */
144 extern void release_thread(struct task_struct *);
145 /*
146  * create a kernel thread without removing it from tasklists
147  */
148 extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
149 
150 /*
151  * Bus types
152  */
153 #define EISA_bus 0
154 #define EISA_bus__is_a_macro /* for versions in ksyms.c */
155 #define MCA_bus 0
156 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
157 
158 
159 /* Copy and release all segment info associated with a VM */
160 #define copy_segments(p, mm)	do { } while(0)
161 #define release_segments(mm)	do { } while(0)
162 
163 /*
164  * FPU lazy state save handling.
165  */
166 
release_fpu(void)167 static __inline__ void release_fpu(void)
168 {
169 	unsigned long __dummy;
170 
171 	/* Set FD flag in SR */
172 	__asm__ __volatile__("stc	sr, %0\n\t"
173 			     "or	%1, %0\n\t"
174 			     "ldc	%0, sr"
175 			     : "=&r" (__dummy)
176 			     : "r" (SR_FD));
177 }
178 
grab_fpu(void)179 static __inline__ void grab_fpu(void)
180 {
181 	unsigned long __dummy;
182 
183 	/* Clear out FD flag in SR */
184 	__asm__ __volatile__("stc	sr, %0\n\t"
185 			     "and	%1, %0\n\t"
186 			     "ldc	%0, sr"
187 			     : "=&r" (__dummy)
188 			     : "r" (~SR_FD));
189 }
190 
191 extern void save_fpu(struct task_struct *__tsk);
192 
193 #define unlazy_fpu(tsk) do { 			\
194 	if ((tsk)->flags & PF_USEDFPU) {	\
195 		save_fpu(tsk); 			\
196 	}					\
197 } while (0)
198 
199 #define clear_fpu(tsk) do { 			\
200 	if ((tsk)->flags & PF_USEDFPU) { 	\
201 		(tsk)->flags &= ~PF_USEDFPU; 	\
202 		release_fpu();			\
203 	}					\
204 } while (0)
205 
206 /* Double presision, NANS as NANS, rounding to nearest, no exceptions */
207 #define FPSCR_INIT  0x00080000
208 
209 #define	FPSCR_CAUSE_MASK	0x0001f000	/* Cause bits */
210 #define	FPSCR_FLAG_MASK		0x0000007c	/* Flag bits */
211 
212 /*
213  * Return saved PC of a blocked thread.
214  */
thread_saved_pc(struct thread_struct * t)215 static __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
216 {
217 	return t->pc;
218 }
219 
220 extern unsigned long get_wchan(struct task_struct *p);
221 
222 #define KSTK_EIP(tsk)  ((tsk)->thread.pc)
223 #define KSTK_ESP(tsk)  ((tsk)->thread.sp)
224 
225 #define THREAD_SIZE (2*PAGE_SIZE)
226 extern struct task_struct * alloc_task_struct(void);
227 extern void free_task_struct(struct task_struct *);
228 #define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count)
229 
230 #define init_task	(init_task_union.task)
231 #define init_stack	(init_task_union.stack)
232 
233 #define cpu_relax()	do { } while (0)
234 
235 #endif /* __ASM_SH_PROCESSOR_H */
236