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