1 |
#ifndef CPU_SPARC_H |
2 |
#define CPU_SPARC_H |
3 |
|
4 |
/* |
5 |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
6 |
* |
7 |
* Redistribution and use in source and binary forms, with or without |
8 |
* modification, are permitted provided that the following conditions are met: |
9 |
* |
10 |
* 1. Redistributions of source code must retain the above copyright |
11 |
* notice, this list of conditions and the following disclaimer. |
12 |
* 2. Redistributions in binary form must reproduce the above copyright |
13 |
* notice, this list of conditions and the following disclaimer in the |
14 |
* documentation and/or other materials provided with the distribution. |
15 |
* 3. The name of the author may not be used to endorse or promote products |
16 |
* derived from this software without specific prior written permission. |
17 |
* |
18 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
19 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
20 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
21 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
22 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
24 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
25 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
26 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
27 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 |
* SUCH DAMAGE. |
29 |
* |
30 |
* |
31 |
* $Id: cpu_sparc.h,v 1.48 2007/06/07 15:36:25 debug Exp $ |
32 |
*/ |
33 |
|
34 |
#include "misc.h" |
35 |
|
36 |
|
37 |
struct cpu_family; |
38 |
struct timer; |
39 |
|
40 |
|
41 |
/* SPARC CPU types: */ |
42 |
struct sparc_cpu_type_def { |
43 |
char *name; |
44 |
int v; /* v8, v9 etc */ |
45 |
int h; /* hypervisor? sun4v = 1 */ |
46 |
int bits; /* 32 or 64 */ |
47 |
int nwindows; /* usually 8 or more */ |
48 |
int icache_shift; |
49 |
int ilinesize; |
50 |
int iway; |
51 |
int dcache_shift; |
52 |
int dlinesize; |
53 |
int dway; |
54 |
int l2cache_shift; |
55 |
int l2linesize; |
56 |
int l2way; |
57 |
}; |
58 |
|
59 |
/* NOTE/TODO: Maybe some of the types listed below as v8 are in |
60 |
fact v7; I haven't had time to check. Also, the nwindows value is |
61 |
just bogus. */ |
62 |
/* See http://www.sparc.com/standards/v8v9-numbers.html for |
63 |
implementation numbers! */ |
64 |
/* Note/TODO: sun4v is listed as 10 */ |
65 |
|
66 |
#define SPARC_CPU_TYPE_DEFS { \ |
67 |
{ "TMS390Z50", 8, 0, 32, 8, 14,5,2, 14,5,2, 0,0,0 }, \ |
68 |
{ "MB86904", 8, 0, 32, 8, 14,5,2, 13,4,2, 0,0,0 }, \ |
69 |
{ "MB86907", 8, 0, 32, 8, 14,5,2, 14,5,2, 19,5,1 }, \ |
70 |
{ "UltraSPARC", 9, 0, 64, 8, 14,5,4, 14,5,4, 19,6,1 }, \ |
71 |
{ "UltraSPARC-IIi", 9, 0, 64, 8, 15,5,2, 14,5,2, 21,6,1 }, \ |
72 |
{ "UltraSPARC-II", 9, 0, 64, 8, 15,5,2, 14,5,2, 22,6,1 }, \ |
73 |
{ "T1", 9, 1, 64, 8, 15,5,2, 14,5,2, 22,6,1 }, \ |
74 |
{ NULL, 0, 0, 0, 0, 0,0,0, 0,0,0, 0,0,0 } \ |
75 |
} |
76 |
|
77 |
|
78 |
#define SPARC_N_IC_ARGS 3 |
79 |
#define SPARC_INSTR_ALIGNMENT_SHIFT 2 |
80 |
#define SPARC_IC_ENTRIES_SHIFT 10 |
81 |
#define SPARC_IC_ENTRIES_PER_PAGE (1 << SPARC_IC_ENTRIES_SHIFT) |
82 |
#define SPARC_PC_TO_IC_ENTRY(a) (((a)>>SPARC_INSTR_ALIGNMENT_SHIFT) \ |
83 |
& (SPARC_IC_ENTRIES_PER_PAGE-1)) |
84 |
#define SPARC_ADDR_TO_PAGENR(a) ((a) >> (SPARC_IC_ENTRIES_SHIFT \ |
85 |
+ SPARC_INSTR_ALIGNMENT_SHIFT)) |
86 |
|
87 |
#define SPARC_L2N 17 |
88 |
#define SPARC_L3N 18 /* 4KB pages on 32-bit sparc, */ |
89 |
/* 8KB pages on 64-bit? TODO */ |
90 |
|
91 |
DYNTRANS_MISC_DECLARATIONS(sparc,SPARC,uint64_t) |
92 |
DYNTRANS_MISC64_DECLARATIONS(sparc,SPARC,uint8_t) |
93 |
|
94 |
#define SPARC_MAX_VPH_TLB_ENTRIES 128 |
95 |
|
96 |
|
97 |
#define N_SPARC_REG 32 |
98 |
#define N_SPARC_GLOBAL_REG 8 |
99 |
#define N_SPARC_INOUT_REG 8 |
100 |
#define N_SPARC_LOCAL_REG 8 |
101 |
#define SPARC_REG_NAMES { \ |
102 |
"g0","g1","g2","g3","g4","g5","g6","g7", \ |
103 |
"o0","o1","o2","o3","o4","o5","sp","o7", \ |
104 |
"l0","l1","l2","l3","l4","l5","l6","l7", \ |
105 |
"i0","i1","i2","i3","i4","i5","fp","i7" } |
106 |
|
107 |
#define SPARC_ZEROREG 0 /* g0 */ |
108 |
#define SPARC_REG_G0 0 |
109 |
#define SPARC_REG_G1 1 |
110 |
#define SPARC_REG_G2 2 |
111 |
#define SPARC_REG_G3 3 |
112 |
#define SPARC_REG_G4 4 |
113 |
#define SPARC_REG_G5 5 |
114 |
#define SPARC_REG_G6 6 |
115 |
#define SPARC_REG_G7 7 |
116 |
#define SPARC_REG_O0 8 |
117 |
#define SPARC_REG_O1 9 |
118 |
#define SPARC_REG_O2 10 |
119 |
#define SPARC_REG_O3 11 |
120 |
#define SPARC_REG_O4 12 |
121 |
#define SPARC_REG_O5 13 |
122 |
#define SPARC_REG_O6 14 |
123 |
#define SPARC_REG_O7 15 |
124 |
#define SPARC_REG_L0 16 |
125 |
#define SPARC_REG_L1 17 |
126 |
#define SPARC_REG_L2 18 |
127 |
#define SPARC_REG_L3 19 |
128 |
#define SPARC_REG_L4 20 |
129 |
#define SPARC_REG_L5 21 |
130 |
#define SPARC_REG_L6 22 |
131 |
#define SPARC_REG_L7 23 |
132 |
#define SPARC_REG_I0 24 |
133 |
#define SPARC_REG_I1 25 |
134 |
#define SPARC_REG_I2 26 |
135 |
#define SPARC_REG_I3 27 |
136 |
#define SPARC_REG_I4 28 |
137 |
#define SPARC_REG_I5 29 |
138 |
#define SPARC_REG_I6 30 |
139 |
#define SPARC_REG_I7 31 |
140 |
|
141 |
/* Privileged registers: */ |
142 |
#define N_SPARC_PREG 32 |
143 |
#define SPARC_PREG_NAMES { \ |
144 |
"tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl", \ |
145 |
"pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin", \ |
146 |
"wstate", "fq", "reserved16", "reserved17", "reserved18", \ |
147 |
"reserved19", "reserved20", "reserved21", "reserved22", \ |
148 |
"reserved23", "reserved24", "reserved25", "reserved26", \ |
149 |
"reserved27", "reserved28", "reserved29", "reserved30", \ |
150 |
"ver" } |
151 |
|
152 |
#define N_SPARC_BRANCH_TYPES 16 |
153 |
#define SPARC_BRANCH_NAMES { \ |
154 |
"bn", "be", "ble", "bl", "bleu", "bcs", "bneg", "bvs", \ |
155 |
"ba", "bne", "bg", "bge", "bgu", "bcc", "bpos", "bvc" } |
156 |
|
157 |
#define N_SPARC_REGBRANCH_TYPES 8 |
158 |
#define SPARC_REGBRANCH_NAMES { \ |
159 |
"br?","brz","brlez","brlz","br??","brnz", "brgz", "brgez" } |
160 |
|
161 |
#define N_ALU_INSTR_TYPES 64 |
162 |
#define SPARC_ALU_NAMES { \ |
163 |
"add", "and", "or", "xor", "sub", "andn", "orn", "xnor", \ |
164 |
"addx", "[9]", "umul", "smul", "subx", "[13]", "udiv", "sdiv", \ |
165 |
"addcc","andcc","orcc","xorcc","subcc","andncc","orncc","xnorcc",\ |
166 |
"addxcc","[25]","umulcc","smulcc","subxcc","[29]","udivcc","sdivcc",\ |
167 |
"taddcc","tsubcc","taddcctv","tsubcctv","mulscc","sll","srl","sra",\ |
168 |
"rd" /* membar/stbar on sparcv9 */, \ |
169 |
"rd" /* rd psr on pre-sparcv9 */, "rdpr","rd", \ |
170 |
"[44]","[45]","popc","movre", \ |
171 |
"wr*","saved/restored","wrpr","[51]", "[52]","[53]","[54]","[55]",\ |
172 |
"jmpl", "rett", "trap", "flush", "save", "restore", "[62]","[63]" } |
173 |
|
174 |
#define N_LOADSTORE_TYPES 64 |
175 |
#define SPARC_LOADSTORE_NAMES { \ |
176 |
"lduw","ldub","lduh","ldd", "st","stb","sth","std", \ |
177 |
"ldsw","ldsb","ldsh","ldx", "[12]","ldstub","stx","swap", \ |
178 |
"lda","lduba","lduha","ldda", "sta","stba","stha","stda", \ |
179 |
"[24]","ldsba","ldsha","ldxa", "[28]","ldstuba","stxa","swapa", \ |
180 |
"ldf","ldfsr","[34]","lddf", "stf","stfsr","stdfq","stdf", \ |
181 |
"[40]","[41]","[42]","[43]", "[44]","prefetch","[46]","[47]", \ |
182 |
"ldc","ldcsr","[50]","lddc", "stc","stcsr","scdfq","scdf", \ |
183 |
"[56]","[57]","[58]","[59]", "[60]","prefetcha","casxa","[63]" } |
184 |
|
185 |
|
186 |
/* Max number of Trap Levels, Global Levels, and Register Windows: */ |
187 |
#define MAXTL 6 |
188 |
#define MAXGL 7 |
189 |
#define N_REG_WINDOWS 8 |
190 |
|
191 |
|
192 |
struct sparc_cpu { |
193 |
struct sparc_cpu_type_def cpu_type; |
194 |
|
195 |
/* Registers in the Current Window: */ |
196 |
uint64_t r[N_SPARC_REG]; |
197 |
|
198 |
uint64_t r_inout[N_REG_WINDOWS][N_SPARC_INOUT_REG]; |
199 |
uint64_t r_local[N_REG_WINDOWS][N_SPARC_LOCAL_REG]; |
200 |
|
201 |
uint64_t r_global[MAXGL+1][N_SPARC_GLOBAL_REG]; |
202 |
|
203 |
uint64_t scratch; |
204 |
|
205 |
/* Pre-SPARCv9 specific: */ |
206 |
uint32_t psr; /* Processor State Register */ |
207 |
uint32_t tbr; /* Trap base register */ |
208 |
uint32_t wim; /* Window invalid mask */ |
209 |
|
210 |
/* SPARCv9 etc.: */ |
211 |
uint64_t pstate; /* Processor State Register */ |
212 |
uint64_t y; /* Y-reg (only low 32-bits used) */ |
213 |
uint64_t fprs; /* Floating Point Register Status */ |
214 |
uint64_t tick; /* Tick Register */ |
215 |
uint64_t tick_cmpr; /* Tick Compare Register (?) */ |
216 |
uint64_t ver; /* Version register */ |
217 |
|
218 |
uint8_t cwp; /* Current Window Pointer */ |
219 |
uint8_t cansave; /* CANSAVE register */ |
220 |
uint8_t canrestore; /* CANRESTORE register */ |
221 |
uint8_t otherwin; /* OTHERWIN register */ |
222 |
uint8_t cleanwin; /* CLEANWIN register */ |
223 |
|
224 |
uint8_t wstate; /* Window state */ |
225 |
|
226 |
uint8_t ccr; /* Condition Code Register */ |
227 |
uint8_t asi; /* Address Space Identifier */ |
228 |
uint8_t tl; /* Trap Level Register */ |
229 |
uint8_t gl; /* Global Level Register */ |
230 |
uint8_t pil; /* Processor Interrupt Level Reg. */ |
231 |
|
232 |
uint64_t tpc[MAXTL]; /* Trap Program Counter */ |
233 |
uint64_t tnpc[MAXTL]; /* Trap Next Program Counter */ |
234 |
uint64_t tstate[MAXTL]; /* Trap State */ |
235 |
uint32_t ttype[MAXTL]; /* Trap Type */ |
236 |
|
237 |
uint64_t tba; /* Trap Base Address */ |
238 |
|
239 |
uint64_t hpstate; /* Hyper-Privileged State Register */ |
240 |
uint64_t htstate[MAXTL]; /* Hyper-Privileged Trap State */ |
241 |
uint64_t hintp; /* Hyper-Privileged InterruptPending */ |
242 |
uint64_t htba; /* Hyper-Privileged Trap Base Addr */ |
243 |
uint64_t hver; /* Hyper-Privileged Version Reg. */ |
244 |
|
245 |
|
246 |
/* |
247 |
* Instruction translation cache and Virtual->Physical->Host |
248 |
* address translation: |
249 |
*/ |
250 |
DYNTRANS_ITC(sparc) |
251 |
VPH_TLBS(sparc,SPARC) |
252 |
VPH32(sparc,SPARC) |
253 |
VPH64(sparc,SPARC) |
254 |
}; |
255 |
|
256 |
|
257 |
/* Processor State Register (PSTATE) bit definitions: */ |
258 |
#define SPARC_PSTATE_PID1 0x800 |
259 |
#define SPARC_PSTATE_PID0 0x400 |
260 |
#define SPARC_PSTATE_CLE 0x200 /* Current Little Endian */ |
261 |
#define SPARC_PSTATE_TLE 0x100 /* Trap Little Endian */ |
262 |
#define SPARC_PSTATE_MM_MASK 0x0c0 /* Memory Model (TODO) */ |
263 |
#define SPARC_PSTATE_MM_SHIFT 6 |
264 |
#define SPARC_PSTATE_RED 0x020 /* Reset/Error/Debug state */ |
265 |
#define SPARC_PSTATE_PEF 0x010 /* Enable Floating-point */ |
266 |
#define SPARC_PSTATE_AM 0x008 /* Address Mask */ |
267 |
#define SPARC_PSTATE_PRIV 0x004 /* Privileged Mode */ |
268 |
#define SPARC_PSTATE_IE 0x002 /* Interrupt Enable */ |
269 |
#define SPARC_PSTATE_AG 0x001 /* Alternate Globals */ |
270 |
|
271 |
|
272 |
/* Hyper-Privileged State Register (HPSTATE) bit definitions: */ |
273 |
#define SPARC_HPSTATE_ID 0x800 |
274 |
#define SPARC_HPSTATE_IBE 0x400 /* Instruction Break Enable */ |
275 |
#define SPARC_HPSTATE_RED 0x020 /* Reset/Error/Debug state */ |
276 |
#define SPARC_HPSTATE_HPRIV 0x004 /* Hyper-Privileged mode */ |
277 |
#define SPARC_HPSTATE_TLZ 0x001 /* Trap Level Zero trap enable */ |
278 |
|
279 |
|
280 |
/* Condition Code Register bit definitions: */ |
281 |
#define SPARC_CCR_XCC_MASK 0xf0 |
282 |
#define SPARC_CCR_XCC_SHIFT 4 |
283 |
#define SPARC_CCR_ICC_MASK 0x0f |
284 |
#define SPARC_CCR_N 8 |
285 |
#define SPARC_CCR_Z 4 |
286 |
#define SPARC_CCR_V 2 |
287 |
#define SPARC_CCR_C 1 |
288 |
|
289 |
|
290 |
/* CWP, CANSAVE, CANRESTORE, OTHERWIN, CLEANWIN bitmask: */ |
291 |
#define SPARC_CWP_MASK 0x1f |
292 |
|
293 |
|
294 |
/* Window State bit definitions: */ |
295 |
#define SPARC_WSTATE_OTHER_MASK 0x38 |
296 |
#define SPARC_WSTATE_OTHER_SHIFT 3 |
297 |
#define SPARC_WSTATE_NORMAL_MASK 0x07 |
298 |
|
299 |
|
300 |
/* Tick Register bit definitions: */ |
301 |
#define SPARC_TICK_NPT (1ULL << 63) /* Non-privileged trap */ |
302 |
|
303 |
|
304 |
/* Addess Space Identifier bit definitions: */ |
305 |
#define SPARC_ASI_RESTRICTED 0x80 |
306 |
|
307 |
|
308 |
/* Trap Level Register bit definitions: */ |
309 |
#define SPARC_TL_MASK 0x07 |
310 |
|
311 |
|
312 |
/* Processor Interrupt Level Register bit definitions: */ |
313 |
#define SPARC_PIL_MASK 0x0f |
314 |
|
315 |
|
316 |
/* Trap Type Register bit definitions: */ |
317 |
#define SPARC_TTYPE_MASK 0x1ff |
318 |
|
319 |
|
320 |
/* Trap Base Address bit definitions: */ |
321 |
#define SPARC_TBA_MASK 0xffffffffffff8000ULL |
322 |
|
323 |
|
324 |
/* |
325 |
* Full address for a trap is: |
326 |
* TBA<bits 63..15> || X || TTYPE[TL] || 00000 |
327 |
* |
328 |
* where X is a bit which is true if TL>0 when the trap was taken. |
329 |
*/ |
330 |
|
331 |
|
332 |
/* Version Register bit definitions: */ |
333 |
#define SPARC_VER_MANUF_SHIFT 48 |
334 |
#define SPARC_VER_IMPL_SHIFT 32 |
335 |
#define SPARC_VER_MASK_SHIFT 24 |
336 |
#define SPARC_VER_MAXTL_SHIFT 8 |
337 |
#define SPARC_VER_MAXWIN_SHIFT 0 |
338 |
|
339 |
|
340 |
/* cpu_sparc.c: */ |
341 |
int sparc_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib); |
342 |
int sparc_run_instr(struct cpu *cpu); |
343 |
void sparc_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, |
344 |
unsigned char *host_page, int writeflag, uint64_t paddr_page); |
345 |
void sparc_invalidate_translation_caches(struct cpu *cpu, uint64_t, int); |
346 |
void sparc_invalidate_code_translation(struct cpu *cpu, uint64_t, int); |
347 |
int sparc32_run_instr(struct cpu *cpu); |
348 |
void sparc32_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, |
349 |
unsigned char *host_page, int writeflag, uint64_t paddr_page); |
350 |
void sparc32_invalidate_translation_caches(struct cpu *cpu, uint64_t, int); |
351 |
void sparc32_invalidate_code_translation(struct cpu *cpu, uint64_t, int); |
352 |
void sparc_init_64bit_dummy_tables(struct cpu *cpu); |
353 |
void sparc_timer_sample_tick(struct timer *, void *); |
354 |
int sparc_memory_rw(struct cpu *cpu, struct memory *mem, uint64_t vaddr, |
355 |
unsigned char *data, size_t len, int writeflag, int cache_flags); |
356 |
int sparc_cpu_family_init(struct cpu_family *); |
357 |
|
358 |
/* memory_sparc.c: */ |
359 |
int sparc_translate_v2p(struct cpu *cpu, uint64_t vaddr, |
360 |
uint64_t *return_addr, int flags); |
361 |
|
362 |
|
363 |
#endif /* CPU_SPARC_H */ |