Revision 76a66253 hw/ppc.c
b/hw/ppc.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* QEMU generic PPC hardware System Emulator |
3 | 3 |
* |
4 |
* Copyright (c) 2003-2004 Jocelyn Mayer
|
|
4 |
* Copyright (c) 2003-2007 Jocelyn Mayer
|
|
5 | 5 |
* |
6 | 6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | 7 |
* of this software and associated documentation files (the "Software"), to deal |
... | ... | |
41 | 41 |
{ |
42 | 42 |
/* TB time in tb periods */ |
43 | 43 |
return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset, |
44 |
tb_env->tb_freq, ticks_per_sec);
|
|
44 |
tb_env->tb_freq, ticks_per_sec);
|
|
45 | 45 |
} |
46 | 46 |
|
47 | 47 |
uint32_t cpu_ppc_load_tbl (CPUState *env) |
... | ... | |
52 | 52 |
tb = cpu_ppc_get_tb(tb_env); |
53 | 53 |
#ifdef DEBUG_TB |
54 | 54 |
{ |
55 |
static int last_time;
|
|
56 |
int now;
|
|
57 |
now = time(NULL);
|
|
58 |
if (last_time != now) {
|
|
59 |
last_time = now;
|
|
60 |
printf("%s: tb=0x%016lx %d %08lx\n",
|
|
61 |
__func__, tb, now, tb_env->tb_offset);
|
|
62 |
}
|
|
55 |
static int last_time; |
|
56 |
int now;
|
|
57 |
now = time(NULL);
|
|
58 |
if (last_time != now) {
|
|
59 |
last_time = now;
|
|
60 |
printf("%s: tb=0x%016lx %d %08lx\n",
|
|
61 |
__func__, tb, now, tb_env->tb_offset); |
|
62 |
}
|
|
63 | 63 |
} |
64 | 64 |
#endif |
65 | 65 |
|
... | ... | |
75 | 75 |
#ifdef DEBUG_TB |
76 | 76 |
printf("%s: tb=0x%016lx\n", __func__, tb); |
77 | 77 |
#endif |
78 |
|
|
78 | 79 |
return tb >> 32; |
79 | 80 |
} |
80 | 81 |
|
... | ... | |
117 | 118 |
#if defined(DEBUG_TB) |
118 | 119 |
printf("%s: 0x%08x\n", __func__, decr); |
119 | 120 |
#endif |
121 |
|
|
120 | 122 |
return decr; |
121 | 123 |
} |
122 | 124 |
|
... | ... | |
146 | 148 |
if (is_excp) |
147 | 149 |
next += tb_env->decr_next - now; |
148 | 150 |
if (next == now) |
149 |
next++;
|
|
151 |
next++;
|
|
150 | 152 |
tb_env->decr_next = next; |
151 | 153 |
/* Adjust timer */ |
152 | 154 |
qemu_mod_timer(tb_env->decr_timer, next); |
... | ... | |
154 | 156 |
* raise an exception. |
155 | 157 |
*/ |
156 | 158 |
if ((value & 0x80000000) && !(decr & 0x80000000)) |
157 |
cpu_ppc_decr_excp(env);
|
|
159 |
cpu_ppc_decr_excp(env);
|
|
158 | 160 |
} |
159 | 161 |
|
160 | 162 |
void cpu_ppc_store_decr (CPUState *env, uint32_t value) |
... | ... | |
177 | 179 |
return NULL; |
178 | 180 |
env->tb_env = tb_env; |
179 | 181 |
if (tb_env->tb_freq == 0 || 1) { |
180 |
tb_env->tb_freq = freq;
|
|
181 |
/* Create new timer */
|
|
182 |
tb_env->decr_timer =
|
|
182 |
tb_env->tb_freq = freq;
|
|
183 |
/* Create new timer */
|
|
184 |
tb_env->decr_timer =
|
|
183 | 185 |
qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env); |
184 |
/* There is a bug in 2.4 kernels:
|
|
185 |
* if a decrementer exception is pending when it enables msr_ee,
|
|
186 |
* it's not ready to handle it...
|
|
187 |
*/
|
|
188 |
_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
|
186 |
/* There is a bug in Linux 2.4 kernels:
|
|
187 |
* if a decrementer exception is pending when it enables msr_ee,
|
|
188 |
* it's not ready to handle it...
|
|
189 |
*/
|
|
190 |
_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
|
189 | 191 |
} |
190 | 192 |
|
191 | 193 |
return tb_env; |
192 | 194 |
} |
193 | 195 |
|
196 |
/* Specific helpers for POWER & PowerPC 601 RTC */ |
|
197 |
ppc_tb_t *cpu_ppc601_rtc_init (CPUState *env) |
|
198 |
{ |
|
199 |
return cpu_ppc_tb_init(env, 7812500); |
|
200 |
} |
|
201 |
|
|
202 |
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value) |
|
203 |
__attribute__ (( alias ("cpu_ppc_store_tbu") )); |
|
204 |
|
|
205 |
uint32_t cpu_ppc601_load_rtcu (CPUState *env) |
|
206 |
__attribute__ (( alias ("cpu_ppc_load_tbu") )); |
|
207 |
|
|
208 |
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value) |
|
209 |
{ |
|
210 |
cpu_ppc_store_tbl(env, value & 0x3FFFFF80); |
|
211 |
} |
|
212 |
|
|
213 |
uint32_t cpu_ppc601_load_rtcl (CPUState *env) |
|
214 |
{ |
|
215 |
return cpu_ppc_load_tbl(env) & 0x3FFFFF80; |
|
216 |
} |
|
217 |
|
|
218 |
/* Embedded PowerPC timers */ |
|
219 |
target_ulong load_40x_pit (CPUState *env) |
|
220 |
{ |
|
221 |
/* XXX: TODO */ |
|
222 |
return 0; |
|
223 |
} |
|
224 |
|
|
225 |
void store_40x_pit (CPUState *env, target_ulong val) |
|
226 |
{ |
|
227 |
/* XXX: TODO */ |
|
228 |
} |
|
229 |
|
|
230 |
void store_booke_tcr (CPUState *env, target_ulong val) |
|
231 |
{ |
|
232 |
/* XXX: TODO */ |
|
233 |
} |
|
234 |
|
|
235 |
void store_booke_tsr (CPUState *env, target_ulong val) |
|
236 |
{ |
|
237 |
/* XXX: TODO */ |
|
238 |
} |
|
239 |
|
|
194 | 240 |
#if 0 |
195 | 241 |
/*****************************************************************************/ |
196 | 242 |
/* Handle system reset (for now, just stop emulation) */ |
... | ... | |
264 | 310 |
tmp |= m48t59_read(nvram, addr + 1) << 16; |
265 | 311 |
tmp |= m48t59_read(nvram, addr + 2) << 8; |
266 | 312 |
tmp |= m48t59_read(nvram, addr + 3); |
313 |
|
|
267 | 314 |
return tmp; |
268 | 315 |
} |
269 | 316 |
|
... | ... | |
316 | 363 |
odd = count & 1; |
317 | 364 |
count &= ~1; |
318 | 365 |
for (i = 0; i != count; i++) { |
319 |
crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
|
|
366 |
crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
|
|
320 | 367 |
} |
321 | 368 |
if (odd) { |
322 |
crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
|
|
369 |
crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
|
|
323 | 370 |
} |
324 | 371 |
|
325 | 372 |
return crc; |
Also available in: Unified diff