root / target-ppc / op.c @ 7487953d
History | View | Annotate | Download (10.1 kB)
1 |
/*
|
---|---|
2 |
* PowerPC emulation micro-operations for qemu.
|
3 |
*
|
4 |
* Copyright (c) 2003-2007 Jocelyn Mayer
|
5 |
*
|
6 |
* This library is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU Lesser General Public
|
8 |
* License as published by the Free Software Foundation; either
|
9 |
* version 2 of the License, or (at your option) any later version.
|
10 |
*
|
11 |
* This library is distributed in the hope that it will be useful,
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 |
* Lesser General Public License for more details.
|
15 |
*
|
16 |
* You should have received a copy of the GNU Lesser General Public
|
17 |
* License along with this library; if not, write to the Free Software
|
18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19 |
*/
|
20 |
|
21 |
//#define DEBUG_OP
|
22 |
|
23 |
#include "config.h" |
24 |
#include "exec.h" |
25 |
#include "host-utils.h" |
26 |
#include "helper_regs.h" |
27 |
#include "op_helper.h" |
28 |
|
29 |
#if !defined(CONFIG_USER_ONLY)
|
30 |
/* Segment registers load and store */
|
31 |
void OPPROTO op_load_sr (void) |
32 |
{ |
33 |
T0 = env->sr[T1]; |
34 |
RETURN(); |
35 |
} |
36 |
|
37 |
void OPPROTO op_store_sr (void) |
38 |
{ |
39 |
do_store_sr(env, T1, T0); |
40 |
RETURN(); |
41 |
} |
42 |
|
43 |
#if defined(TARGET_PPC64)
|
44 |
void OPPROTO op_load_slb (void) |
45 |
{ |
46 |
T0 = ppc_load_slb(env, T1); |
47 |
RETURN(); |
48 |
} |
49 |
|
50 |
void OPPROTO op_store_slb (void) |
51 |
{ |
52 |
ppc_store_slb(env, T1, T0); |
53 |
RETURN(); |
54 |
} |
55 |
#endif /* defined(TARGET_PPC64) */ |
56 |
|
57 |
void OPPROTO op_load_sdr1 (void) |
58 |
{ |
59 |
T0 = env->sdr1; |
60 |
RETURN(); |
61 |
} |
62 |
|
63 |
void OPPROTO op_store_sdr1 (void) |
64 |
{ |
65 |
do_store_sdr1(env, T0); |
66 |
RETURN(); |
67 |
} |
68 |
|
69 |
#if defined (TARGET_PPC64)
|
70 |
void OPPROTO op_load_asr (void) |
71 |
{ |
72 |
T0 = env->asr; |
73 |
RETURN(); |
74 |
} |
75 |
|
76 |
void OPPROTO op_store_asr (void) |
77 |
{ |
78 |
ppc_store_asr(env, T0); |
79 |
RETURN(); |
80 |
} |
81 |
#endif
|
82 |
|
83 |
void OPPROTO op_load_msr (void) |
84 |
{ |
85 |
T0 = env->msr; |
86 |
RETURN(); |
87 |
} |
88 |
|
89 |
void OPPROTO op_store_msr (void) |
90 |
{ |
91 |
do_store_msr(); |
92 |
RETURN(); |
93 |
} |
94 |
|
95 |
#if defined (TARGET_PPC64)
|
96 |
void OPPROTO op_store_msr_32 (void) |
97 |
{ |
98 |
T0 = (env->msr & ~0xFFFFFFFFULL) | (T0 & 0xFFFFFFFF); |
99 |
do_store_msr(); |
100 |
RETURN(); |
101 |
} |
102 |
#endif
|
103 |
|
104 |
void OPPROTO op_update_riee (void) |
105 |
{ |
106 |
/* We don't call do_store_msr here as we won't trigger
|
107 |
* any special case nor change hflags
|
108 |
*/
|
109 |
T0 &= (1 << MSR_RI) | (1 << MSR_EE); |
110 |
env->msr &= ~(1 << MSR_RI) | (1 << MSR_EE); |
111 |
env->msr |= T0; |
112 |
RETURN(); |
113 |
} |
114 |
#endif
|
115 |
|
116 |
/* SPR */
|
117 |
void OPPROTO op_load_spr (void) |
118 |
{ |
119 |
T0 = env->spr[PARAM1]; |
120 |
RETURN(); |
121 |
} |
122 |
|
123 |
void OPPROTO op_store_spr (void) |
124 |
{ |
125 |
env->spr[PARAM1] = T0; |
126 |
RETURN(); |
127 |
} |
128 |
|
129 |
void OPPROTO op_load_dump_spr (void) |
130 |
{ |
131 |
T0 = ppc_load_dump_spr(PARAM1); |
132 |
RETURN(); |
133 |
} |
134 |
|
135 |
void OPPROTO op_store_dump_spr (void) |
136 |
{ |
137 |
ppc_store_dump_spr(PARAM1, T0); |
138 |
RETURN(); |
139 |
} |
140 |
|
141 |
void OPPROTO op_mask_spr (void) |
142 |
{ |
143 |
env->spr[PARAM1] &= ~T0; |
144 |
RETURN(); |
145 |
} |
146 |
|
147 |
void OPPROTO op_load_tbl (void) |
148 |
{ |
149 |
T0 = cpu_ppc_load_tbl(env); |
150 |
RETURN(); |
151 |
} |
152 |
|
153 |
void OPPROTO op_load_tbu (void) |
154 |
{ |
155 |
T0 = cpu_ppc_load_tbu(env); |
156 |
RETURN(); |
157 |
} |
158 |
|
159 |
void OPPROTO op_load_atbl (void) |
160 |
{ |
161 |
T0 = cpu_ppc_load_atbl(env); |
162 |
RETURN(); |
163 |
} |
164 |
|
165 |
void OPPROTO op_load_atbu (void) |
166 |
{ |
167 |
T0 = cpu_ppc_load_atbu(env); |
168 |
RETURN(); |
169 |
} |
170 |
|
171 |
#if !defined(CONFIG_USER_ONLY)
|
172 |
void OPPROTO op_store_tbl (void) |
173 |
{ |
174 |
cpu_ppc_store_tbl(env, T0); |
175 |
RETURN(); |
176 |
} |
177 |
|
178 |
void OPPROTO op_store_tbu (void) |
179 |
{ |
180 |
cpu_ppc_store_tbu(env, T0); |
181 |
RETURN(); |
182 |
} |
183 |
|
184 |
void OPPROTO op_store_atbl (void) |
185 |
{ |
186 |
cpu_ppc_store_atbl(env, T0); |
187 |
RETURN(); |
188 |
} |
189 |
|
190 |
void OPPROTO op_store_atbu (void) |
191 |
{ |
192 |
cpu_ppc_store_atbu(env, T0); |
193 |
RETURN(); |
194 |
} |
195 |
|
196 |
void OPPROTO op_load_decr (void) |
197 |
{ |
198 |
T0 = cpu_ppc_load_decr(env); |
199 |
RETURN(); |
200 |
} |
201 |
|
202 |
void OPPROTO op_store_decr (void) |
203 |
{ |
204 |
cpu_ppc_store_decr(env, T0); |
205 |
RETURN(); |
206 |
} |
207 |
|
208 |
void OPPROTO op_load_ibat (void) |
209 |
{ |
210 |
T0 = env->IBAT[PARAM1][PARAM2]; |
211 |
RETURN(); |
212 |
} |
213 |
|
214 |
void OPPROTO op_store_ibatu (void) |
215 |
{ |
216 |
do_store_ibatu(env, PARAM1, T0); |
217 |
RETURN(); |
218 |
} |
219 |
|
220 |
void OPPROTO op_store_ibatl (void) |
221 |
{ |
222 |
#if 1 |
223 |
env->IBAT[1][PARAM1] = T0;
|
224 |
#else
|
225 |
do_store_ibatl(env, PARAM1, T0); |
226 |
#endif
|
227 |
RETURN(); |
228 |
} |
229 |
|
230 |
void OPPROTO op_load_dbat (void) |
231 |
{ |
232 |
T0 = env->DBAT[PARAM1][PARAM2]; |
233 |
RETURN(); |
234 |
} |
235 |
|
236 |
void OPPROTO op_store_dbatu (void) |
237 |
{ |
238 |
do_store_dbatu(env, PARAM1, T0); |
239 |
RETURN(); |
240 |
} |
241 |
|
242 |
void OPPROTO op_store_dbatl (void) |
243 |
{ |
244 |
#if 1 |
245 |
env->DBAT[1][PARAM1] = T0;
|
246 |
#else
|
247 |
do_store_dbatl(env, PARAM1, T0); |
248 |
#endif
|
249 |
RETURN(); |
250 |
} |
251 |
#endif /* !defined(CONFIG_USER_ONLY) */ |
252 |
|
253 |
/*** Integer shift ***/
|
254 |
void OPPROTO op_srli_T1 (void) |
255 |
{ |
256 |
T1 = (uint32_t)T1 >> PARAM1; |
257 |
RETURN(); |
258 |
} |
259 |
|
260 |
/* Return from interrupt */
|
261 |
#if !defined(CONFIG_USER_ONLY)
|
262 |
/* Exception vectors */
|
263 |
void OPPROTO op_store_excp_prefix (void) |
264 |
{ |
265 |
T0 &= env->ivpr_mask; |
266 |
env->excp_prefix = T0; |
267 |
RETURN(); |
268 |
} |
269 |
|
270 |
void OPPROTO op_store_excp_vector (void) |
271 |
{ |
272 |
T0 &= env->ivor_mask; |
273 |
env->excp_vectors[PARAM1] = T0; |
274 |
RETURN(); |
275 |
} |
276 |
#endif
|
277 |
|
278 |
#if !defined(CONFIG_USER_ONLY)
|
279 |
/* tlbia */
|
280 |
void OPPROTO op_tlbia (void) |
281 |
{ |
282 |
ppc_tlb_invalidate_all(env); |
283 |
RETURN(); |
284 |
} |
285 |
|
286 |
/* tlbie */
|
287 |
void OPPROTO op_tlbie (void) |
288 |
{ |
289 |
ppc_tlb_invalidate_one(env, (uint32_t)T0); |
290 |
RETURN(); |
291 |
} |
292 |
|
293 |
#if defined(TARGET_PPC64)
|
294 |
void OPPROTO op_tlbie_64 (void) |
295 |
{ |
296 |
ppc_tlb_invalidate_one(env, T0); |
297 |
RETURN(); |
298 |
} |
299 |
#endif
|
300 |
|
301 |
#if defined(TARGET_PPC64)
|
302 |
void OPPROTO op_slbia (void) |
303 |
{ |
304 |
ppc_slb_invalidate_all(env); |
305 |
RETURN(); |
306 |
} |
307 |
|
308 |
void OPPROTO op_slbie (void) |
309 |
{ |
310 |
ppc_slb_invalidate_one(env, (uint32_t)T0); |
311 |
RETURN(); |
312 |
} |
313 |
|
314 |
void OPPROTO op_slbie_64 (void) |
315 |
{ |
316 |
ppc_slb_invalidate_one(env, T0); |
317 |
RETURN(); |
318 |
} |
319 |
#endif
|
320 |
#endif
|
321 |
|
322 |
/* 601 specific */
|
323 |
void OPPROTO op_load_601_rtcl (void) |
324 |
{ |
325 |
T0 = cpu_ppc601_load_rtcl(env); |
326 |
RETURN(); |
327 |
} |
328 |
|
329 |
void OPPROTO op_load_601_rtcu (void) |
330 |
{ |
331 |
T0 = cpu_ppc601_load_rtcu(env); |
332 |
RETURN(); |
333 |
} |
334 |
|
335 |
#if !defined(CONFIG_USER_ONLY)
|
336 |
void OPPROTO op_store_601_rtcl (void) |
337 |
{ |
338 |
cpu_ppc601_store_rtcl(env, T0); |
339 |
RETURN(); |
340 |
} |
341 |
|
342 |
void OPPROTO op_store_601_rtcu (void) |
343 |
{ |
344 |
cpu_ppc601_store_rtcu(env, T0); |
345 |
RETURN(); |
346 |
} |
347 |
|
348 |
void OPPROTO op_store_hid0_601 (void) |
349 |
{ |
350 |
do_store_hid0_601(); |
351 |
RETURN(); |
352 |
} |
353 |
|
354 |
void OPPROTO op_load_601_bat (void) |
355 |
{ |
356 |
T0 = env->IBAT[PARAM1][PARAM2]; |
357 |
RETURN(); |
358 |
} |
359 |
|
360 |
void OPPROTO op_store_601_batl (void) |
361 |
{ |
362 |
do_store_ibatl_601(env, PARAM1, T0); |
363 |
RETURN(); |
364 |
} |
365 |
|
366 |
void OPPROTO op_store_601_batu (void) |
367 |
{ |
368 |
do_store_ibatu_601(env, PARAM1, T0); |
369 |
RETURN(); |
370 |
} |
371 |
#endif /* !defined(CONFIG_USER_ONLY) */ |
372 |
|
373 |
/* PowerPC 601 specific instructions (POWER bridge) */
|
374 |
/* XXX: those micro-ops need tests ! */
|
375 |
void OPPROTO op_POWER_abs (void) |
376 |
{ |
377 |
if ((int32_t)T0 == INT32_MIN)
|
378 |
T0 = INT32_MAX; |
379 |
else if ((int32_t)T0 < 0) |
380 |
T0 = -T0; |
381 |
RETURN(); |
382 |
} |
383 |
|
384 |
void OPPROTO op_POWER_abso (void) |
385 |
{ |
386 |
do_POWER_abso(); |
387 |
RETURN(); |
388 |
} |
389 |
|
390 |
void OPPROTO op_POWER_clcs (void) |
391 |
{ |
392 |
do_POWER_clcs(); |
393 |
RETURN(); |
394 |
} |
395 |
|
396 |
void OPPROTO op_POWER_div (void) |
397 |
{ |
398 |
do_POWER_div(); |
399 |
RETURN(); |
400 |
} |
401 |
|
402 |
void OPPROTO op_POWER_divo (void) |
403 |
{ |
404 |
do_POWER_divo(); |
405 |
RETURN(); |
406 |
} |
407 |
|
408 |
void OPPROTO op_POWER_divs (void) |
409 |
{ |
410 |
do_POWER_divs(); |
411 |
RETURN(); |
412 |
} |
413 |
|
414 |
void OPPROTO op_POWER_divso (void) |
415 |
{ |
416 |
do_POWER_divso(); |
417 |
RETURN(); |
418 |
} |
419 |
|
420 |
void OPPROTO op_POWER_doz (void) |
421 |
{ |
422 |
if ((int32_t)T1 > (int32_t)T0)
|
423 |
T0 = T1 - T0; |
424 |
else
|
425 |
T0 = 0;
|
426 |
RETURN(); |
427 |
} |
428 |
|
429 |
void OPPROTO op_POWER_dozo (void) |
430 |
{ |
431 |
do_POWER_dozo(); |
432 |
RETURN(); |
433 |
} |
434 |
|
435 |
void OPPROTO op_POWER_maskg (void) |
436 |
{ |
437 |
do_POWER_maskg(); |
438 |
RETURN(); |
439 |
} |
440 |
|
441 |
void OPPROTO op_POWER_maskir (void) |
442 |
{ |
443 |
T0 = (T0 & ~T2) | (T1 & T2); |
444 |
RETURN(); |
445 |
} |
446 |
|
447 |
void OPPROTO op_POWER_mul (void) |
448 |
{ |
449 |
uint64_t tmp; |
450 |
|
451 |
tmp = (uint64_t)T0 * (uint64_t)T1; |
452 |
env->spr[SPR_MQ] = tmp >> 32;
|
453 |
T0 = tmp; |
454 |
RETURN(); |
455 |
} |
456 |
|
457 |
void OPPROTO op_POWER_mulo (void) |
458 |
{ |
459 |
do_POWER_mulo(); |
460 |
RETURN(); |
461 |
} |
462 |
|
463 |
void OPPROTO op_POWER_nabs (void) |
464 |
{ |
465 |
if (T0 > 0) |
466 |
T0 = -T0; |
467 |
RETURN(); |
468 |
} |
469 |
|
470 |
void OPPROTO op_POWER_nabso (void) |
471 |
{ |
472 |
/* nabs never overflows */
|
473 |
if (T0 > 0) |
474 |
T0 = -T0; |
475 |
env->xer &= ~(1 << XER_OV);
|
476 |
RETURN(); |
477 |
} |
478 |
|
479 |
/* POWER instructions not implemented in PowerPC 601 */
|
480 |
#if !defined(CONFIG_USER_ONLY)
|
481 |
void OPPROTO op_POWER_mfsri (void) |
482 |
{ |
483 |
T1 = T0 >> 28;
|
484 |
T0 = env->sr[T1]; |
485 |
RETURN(); |
486 |
} |
487 |
|
488 |
void OPPROTO op_POWER_rac (void) |
489 |
{ |
490 |
do_POWER_rac(); |
491 |
RETURN(); |
492 |
} |
493 |
#endif
|
494 |
|
495 |
/* PowerPC 4xx specific micro-ops */
|
496 |
void OPPROTO op_load_dcr (void) |
497 |
{ |
498 |
do_load_dcr(); |
499 |
RETURN(); |
500 |
} |
501 |
|
502 |
void OPPROTO op_store_dcr (void) |
503 |
{ |
504 |
do_store_dcr(); |
505 |
RETURN(); |
506 |
} |
507 |
|
508 |
#if !defined(CONFIG_USER_ONLY)
|
509 |
void OPPROTO op_wrte (void) |
510 |
{ |
511 |
/* We don't call do_store_msr here as we won't trigger
|
512 |
* any special case nor change hflags
|
513 |
*/
|
514 |
T0 &= 1 << MSR_EE;
|
515 |
env->msr &= ~(1 << MSR_EE);
|
516 |
env->msr |= T0; |
517 |
RETURN(); |
518 |
} |
519 |
|
520 |
void OPPROTO op_440_tlbre (void) |
521 |
{ |
522 |
do_440_tlbre(PARAM1); |
523 |
RETURN(); |
524 |
} |
525 |
|
526 |
void OPPROTO op_440_tlbsx (void) |
527 |
{ |
528 |
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF);
|
529 |
RETURN(); |
530 |
} |
531 |
|
532 |
void OPPROTO op_4xx_tlbsx_check (void) |
533 |
{ |
534 |
int tmp;
|
535 |
|
536 |
tmp = xer_so; |
537 |
if ((int)T0 != -1) |
538 |
tmp |= 0x02;
|
539 |
env->crf[0] = tmp;
|
540 |
RETURN(); |
541 |
} |
542 |
|
543 |
void OPPROTO op_440_tlbwe (void) |
544 |
{ |
545 |
do_440_tlbwe(PARAM1); |
546 |
RETURN(); |
547 |
} |
548 |
|
549 |
void OPPROTO op_4xx_tlbre_lo (void) |
550 |
{ |
551 |
do_4xx_tlbre_lo(); |
552 |
RETURN(); |
553 |
} |
554 |
|
555 |
void OPPROTO op_4xx_tlbre_hi (void) |
556 |
{ |
557 |
do_4xx_tlbre_hi(); |
558 |
RETURN(); |
559 |
} |
560 |
|
561 |
void OPPROTO op_4xx_tlbsx (void) |
562 |
{ |
563 |
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]); |
564 |
RETURN(); |
565 |
} |
566 |
|
567 |
void OPPROTO op_4xx_tlbwe_lo (void) |
568 |
{ |
569 |
do_4xx_tlbwe_lo(); |
570 |
RETURN(); |
571 |
} |
572 |
|
573 |
void OPPROTO op_4xx_tlbwe_hi (void) |
574 |
{ |
575 |
do_4xx_tlbwe_hi(); |
576 |
RETURN(); |
577 |
} |
578 |
#endif
|
579 |
|
580 |
/* SPR micro-ops */
|
581 |
/* 440 specific */
|
582 |
#if !defined(CONFIG_USER_ONLY)
|
583 |
void OPPROTO op_store_pir (void) |
584 |
{ |
585 |
env->spr[SPR_PIR] = T0 & 0x0000000FUL;
|
586 |
RETURN(); |
587 |
} |
588 |
|
589 |
void OPPROTO op_load_403_pb (void) |
590 |
{ |
591 |
do_load_403_pb(PARAM1); |
592 |
RETURN(); |
593 |
} |
594 |
|
595 |
void OPPROTO op_store_403_pb (void) |
596 |
{ |
597 |
do_store_403_pb(PARAM1); |
598 |
RETURN(); |
599 |
} |
600 |
|
601 |
void OPPROTO op_load_40x_pit (void) |
602 |
{ |
603 |
T0 = load_40x_pit(env); |
604 |
RETURN(); |
605 |
} |
606 |
|
607 |
void OPPROTO op_store_40x_pit (void) |
608 |
{ |
609 |
store_40x_pit(env, T0); |
610 |
RETURN(); |
611 |
} |
612 |
|
613 |
void OPPROTO op_store_40x_dbcr0 (void) |
614 |
{ |
615 |
store_40x_dbcr0(env, T0); |
616 |
RETURN(); |
617 |
} |
618 |
|
619 |
void OPPROTO op_store_40x_sler (void) |
620 |
{ |
621 |
store_40x_sler(env, T0); |
622 |
RETURN(); |
623 |
} |
624 |
|
625 |
void OPPROTO op_store_booke_tcr (void) |
626 |
{ |
627 |
store_booke_tcr(env, T0); |
628 |
RETURN(); |
629 |
} |
630 |
|
631 |
void OPPROTO op_store_booke_tsr (void) |
632 |
{ |
633 |
store_booke_tsr(env, T0); |
634 |
RETURN(); |
635 |
} |
636 |
#endif /* !defined(CONFIG_USER_ONLY) */ |
637 |
|