2 |
#define CPU_SPARC_H |
#define CPU_SPARC_H |
3 |
|
|
4 |
/* |
/* |
5 |
* Copyright (C) 2005 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2006 Anders Gavare. All rights reserved. |
6 |
* |
* |
7 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
8 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
28 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
29 |
* |
* |
30 |
* |
* |
31 |
* $Id: cpu_sparc.h,v 1.15 2005/11/16 21:15:19 debug Exp $ |
* $Id: cpu_sparc.h,v 1.41 2006/07/23 12:40:24 debug Exp $ |
32 |
*/ |
*/ |
33 |
|
|
34 |
#include "misc.h" |
#include "misc.h" |
37 |
struct cpu_family; |
struct cpu_family; |
38 |
|
|
39 |
|
|
40 |
|
/* SPARC CPU types: */ |
41 |
|
struct sparc_cpu_type_def { |
42 |
|
char *name; |
43 |
|
int v; /* v8, v9 etc */ |
44 |
|
int bits; /* 32 or 64 */ |
45 |
|
int nwindows; /* usually 8 or more */ |
46 |
|
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 |
|
/* 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 |
|
#define SPARC_CPU_TYPE_DEFS { \ |
64 |
|
{ "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 |
|
} |
72 |
|
|
73 |
|
|
74 |
#define SPARC_N_IC_ARGS 3 |
#define SPARC_N_IC_ARGS 3 |
75 |
#define SPARC_INSTR_ALIGNMENT_SHIFT 2 |
#define SPARC_INSTR_ALIGNMENT_SHIFT 2 |
76 |
#define SPARC_IC_ENTRIES_SHIFT 10 |
#define SPARC_IC_ENTRIES_SHIFT 10 |
80 |
#define SPARC_ADDR_TO_PAGENR(a) ((a) >> (SPARC_IC_ENTRIES_SHIFT \ |
#define SPARC_ADDR_TO_PAGENR(a) ((a) >> (SPARC_IC_ENTRIES_SHIFT \ |
81 |
+ SPARC_INSTR_ALIGNMENT_SHIFT)) |
+ SPARC_INSTR_ALIGNMENT_SHIFT)) |
82 |
|
|
83 |
struct sparc_instr_call { |
#define SPARC_L2N 17 |
84 |
void (*f)(struct cpu *, struct sparc_instr_call *); |
#define SPARC_L3N 18 /* 4KB pages on 32-bit sparc, */ |
85 |
size_t arg[SPARC_N_IC_ARGS]; |
/* 8KB pages on 64-bit? TODO */ |
86 |
}; |
|
87 |
|
DYNTRANS_MISC_DECLARATIONS(sparc,SPARC,uint64_t) |
88 |
|
DYNTRANS_MISC64_DECLARATIONS(sparc,SPARC,uint8_t) |
89 |
|
|
90 |
|
#define SPARC_MAX_VPH_TLB_ENTRIES 128 |
91 |
|
|
92 |
|
|
93 |
|
#define N_SPARC_REG 32 |
94 |
|
#define N_SPARC_INOUT_REG 8 |
95 |
|
#define N_SPARC_LOCAL_REG 8 |
96 |
|
#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 |
|
|
102 |
|
#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 |
|
"wstate", "fq", "reserved16", "reserved17", "reserved18", \ |
142 |
|
"reserved19", "reserved20", "reserved21", "reserved22", \ |
143 |
|
"reserved23", "reserved24", "reserved25", "reserved26", \ |
144 |
|
"reserved27", "reserved28", "reserved29", "reserved30", \ |
145 |
|
"ver" } |
146 |
|
|
147 |
|
#define N_SPARC_BRANCH_TYPES 16 |
148 |
|
#define SPARC_BRANCH_NAMES { \ |
149 |
|
"bn", "be", "ble", "bl", "bleu", "bcs", "bneg", "bvs", \ |
150 |
|
"ba", "bne", "bg", "bge", "bgu", "bcc", "bpos", "bvc" } |
151 |
|
|
152 |
|
#define N_SPARC_REGBRANCH_TYPES 8 |
153 |
|
#define SPARC_REGBRANCH_NAMES { \ |
154 |
|
"br?","brz","brlez","brlz","br??","brnz", "brgz", "brgez" } |
155 |
|
|
156 |
|
#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 |
|
"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 |
|
"jmpl", "rett", "trap", "flush", "save", "restore", "[62]","[63]" } |
168 |
|
|
169 |
|
#define N_LOADSTORE_TYPES 64 |
170 |
|
#define SPARC_LOADSTORE_NAMES { \ |
171 |
|
"lduw","ldub","lduh","ldd", "st","stb","sth","std", \ |
172 |
|
"ldsw","ldsb","ldsh","ldx", "[12]","ldstub","stx","swap", \ |
173 |
|
"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 |
|
"[40]","[41]","[42]","[43]", "[44]","prefetch","[46]","[47]", \ |
177 |
|
"ldc","ldcsr","[50]","lddc", "stc","stcsr","scdfq","scdf", \ |
178 |
|
"[56]","[57]","[58]","[59]", "[60]","prefetcha","casxa","[63]" } |
179 |
|
|
180 |
|
|
181 |
|
/* Max number of Trap Levels and Windows: */ |
182 |
|
#define MAXTL 4 |
183 |
|
#define MAXWIN 32 |
184 |
|
|
|
/* Translation cache struct for each physical page: */ |
|
|
struct sparc_tc_physpage { |
|
|
struct sparc_instr_call ics[SPARC_IC_ENTRIES_PER_PAGE + 1]; |
|
|
uint32_t next_ofs; /* or 0 for end of chain */ |
|
|
int flags; |
|
|
uint64_t physaddr; |
|
|
}; |
|
185 |
|
|
186 |
#define SPARC_N_VPH_ENTRIES 1048576 |
struct sparc_cpu { |
187 |
|
struct sparc_cpu_type_def cpu_type; |
188 |
|
|
189 |
#define SPARC_MAX_VPH_TLB_ENTRIES 256 |
/* Registers in the Current Window: */ |
190 |
struct sparc_vpg_tlb_entry { |
uint64_t r[N_SPARC_REG]; |
|
uint8_t valid; |
|
|
uint8_t writeflag; |
|
|
unsigned char *host_page; |
|
|
int64_t timestamp; |
|
|
uint64_t vaddr_page; |
|
|
uint64_t paddr_page; |
|
|
}; |
|
191 |
|
|
192 |
struct sparc_cpu { |
uint64_t r_inout[MAXWIN][N_SPARC_INOUT_REG]; |
193 |
/* TODO */ |
uint64_t r_local[MAXWIN][N_SPARC_LOCAL_REG]; |
194 |
uint64_t r_i[8]; |
|
195 |
|
uint64_t scratch; |
196 |
|
|
197 |
|
/* 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 |
/* |
/* |
231 |
* Instruction translation cache: |
* Instruction translation cache and Virtual->Physical->Host |
232 |
|
* address translation: |
233 |
*/ |
*/ |
234 |
|
DYNTRANS_ITC(sparc) |
235 |
|
VPH_TLBS(sparc,SPARC) |
236 |
|
VPH32(sparc,SPARC,uint64_t,uint8_t) |
237 |
|
VPH64(sparc,SPARC,uint8_t) |
238 |
|
}; |
239 |
|
|
|
/* cur_ic_page is a pointer to an array of SPARC_IC_ENTRIES_PER_PAGE |
|
|
instruction call entries. next_ic points to the next such |
|
|
call to be executed. */ |
|
|
struct sparc_tc_physpage *cur_physpage; |
|
|
struct sparc_instr_call *cur_ic_page; |
|
|
struct sparc_instr_call *next_ic; |
|
240 |
|
|
241 |
void (*combination_check)(struct cpu *, |
/* Processor State Register (PSTATE) bit definitions: */ |
242 |
struct sparc_instr_call *, int low_addr); |
#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 |
|
|
|
/* |
|
|
* Virtual -> physical -> host address translation: |
|
|
* |
|
|
* host_load and host_store point to arrays of SPARC_N_VPH_ENTRIES |
|
|
* pointers (to host pages); phys_addr points to an array of |
|
|
* SPARC_N_VPH_ENTRIES uint32_t. |
|
|
*/ |
|
255 |
|
|
256 |
struct sparc_vpg_tlb_entry vph_tlb_entry[SPARC_MAX_VPH_TLB_ENTRIES]; |
/* Condition Code Register bit definitions: */ |
257 |
unsigned char *host_load[SPARC_N_VPH_ENTRIES]; |
#define SPARC_CCR_XCC_MASK 0xf0 |
258 |
unsigned char *host_store[SPARC_N_VPH_ENTRIES]; |
#define SPARC_CCR_XCC_SHIFT 4 |
259 |
uint32_t phys_addr[SPARC_N_VPH_ENTRIES]; |
#define SPARC_CCR_ICC_MASK 0x0f |
260 |
struct sparc_tc_physpage *phys_page[SPARC_N_VPH_ENTRIES]; |
#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 |
uint32_t phystranslation[SPARC_N_VPH_ENTRIES/32]; |
|
266 |
uint8_t vaddr_to_tlbindex[SPARC_N_VPH_ENTRIES]; |
/* 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 |
/* cpu_sparc.c: */ |
/* cpu_sparc.c: */ |
317 |
|
int sparc_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib); |
318 |
|
int sparc_run_instr(struct cpu *cpu); |
319 |
void sparc_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, |
void sparc_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, |
320 |
unsigned char *host_page, int writeflag, uint64_t paddr_page); |
unsigned char *host_page, int writeflag, uint64_t paddr_page); |
321 |
void sparc_invalidate_translation_caches(struct cpu *cpu, uint64_t, int); |
void sparc_invalidate_translation_caches(struct cpu *cpu, uint64_t, int); |
322 |
void sparc_invalidate_code_translation(struct cpu *cpu, uint64_t, int); |
void sparc_invalidate_code_translation(struct cpu *cpu, uint64_t, int); |
323 |
|
int sparc32_run_instr(struct cpu *cpu); |
324 |
|
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 |
|
void sparc_init_64bit_dummy_tables(struct cpu *cpu); |
329 |
int sparc_memory_rw(struct cpu *cpu, struct memory *mem, uint64_t vaddr, |
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); |
unsigned char *data, size_t len, int writeflag, int cache_flags); |
331 |
int sparc_cpu_family_init(struct cpu_family *); |
int sparc_cpu_family_init(struct cpu_family *); |