]>
git.proxmox.com Git - mirror_qemu.git/blob - target-ppc/op_helper.c
2 * PowerPC emulation helpers for qemu.
4 * Copyright (c) 2003-2005 Jocelyn Mayer
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.
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.
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
23 #define MEMSUFFIX _raw
24 #include "op_helper_mem.h"
25 #if !defined(CONFIG_USER_ONLY)
26 #define MEMSUFFIX _user
27 #include "op_helper_mem.h"
28 #define MEMSUFFIX _kernel
29 #include "op_helper_mem.h"
32 /*****************************************************************************/
33 /* Exceptions processing helpers */
34 void cpu_loop_exit(void)
36 longjmp(env
->jmp_env
, 1);
39 void do_raise_exception_err (uint32_t exception
, int error_code
)
42 printf("Raise exception %3x code : %d\n", exception
, error_code
);
46 if (error_code
== EXCP_FP
&& msr_fe0
== 0 && msr_fe1
== 0)
52 env
->exception_index
= exception
;
53 env
->error_code
= error_code
;
57 void do_raise_exception (uint32_t exception
)
59 do_raise_exception_err(exception
, 0);
62 /*****************************************************************************/
63 /* Helpers for "fat" micro operations */
64 /* shift right arithmetic helper */
71 ret
= (-1) * (T0
>> 31);
72 if (ret
< 0 && (T0
& ~0x80000000) != 0)
79 ret
= (int32_t)T0
>> (T1
& 0x1f);
80 if (ret
< 0 && ((int32_t)T0
& ((1 << T1
) - 1)) != 0)
86 /* Floating point operations helpers */
94 /* XXX: higher bits are not supposed to be significant.
95 * to make tests easier, return the same as a real PowerPC 750 (aka G3)
97 p
.i
= float64_to_int32(FT0
, &env
->fp_status
);
98 p
.i
|= 0xFFF80000ULL
<< 32;
102 void do_fctiwz (void)
109 /* XXX: higher bits are not supposed to be significant.
110 * to make tests easier, return the same as a real PowerPC 750 (aka G3)
112 p
.i
= float64_to_int32_round_to_zero(FT0
, &env
->fp_status
);
113 p
.i
|= 0xFFF80000ULL
<< 32;
117 void do_fnmadd (void)
119 FT0
= (FT0
* FT1
) + FT2
;
124 void do_fnmsub (void)
126 FT0
= (FT0
* FT1
) - FT2
;
133 if (FT0
== -0.0 && FT1
== -0.0)
152 FT0
= (float)(1.0 / FT0
);
155 if (p
.i
== 0x8000000000000000ULL
) {
156 p
.i
= 0xFFF0000000000000ULL
;
157 } else if (p
.i
== 0x0000000000000000ULL
) {
158 p
.i
= 0x7FF0000000000000ULL
;
159 } else if (isnan(FT0
)) {
160 p
.i
= 0x7FF8000000000000ULL
;
161 } else if (FT0
< 0.0) {
162 p
.i
= 0x8000000000000000ULL
;
164 p
.i
= 0x0000000000000000ULL
;
170 void do_frsqrte (void)
177 if (isnormal(FT0
) && FT0
> 0.0) {
178 FT0
= (float)(1.0 / sqrt(FT0
));
181 if (p
.i
== 0x8000000000000000ULL
) {
182 p
.i
= 0xFFF0000000000000ULL
;
183 } else if (p
.i
== 0x0000000000000000ULL
) {
184 p
.i
= 0x7FF0000000000000ULL
;
185 } else if (isnan(FT0
)) {
186 if (!(p
.i
& 0x0008000000000000ULL
))
187 p
.i
|= 0x000FFFFFFFFFFFFFULL
;
188 } else if (FT0
< 0) {
189 p
.i
= 0x7FF8000000000000ULL
;
191 p
.i
= 0x0000000000000000ULL
;
207 if (isnan(FT0
) || isnan(FT1
)) {
209 env
->fpscr
[4] |= 0x1;
210 env
->fpscr
[6] |= 0x1;
211 } else if (FT0
< FT1
) {
213 } else if (FT0
> FT1
) {
223 env
->fpscr
[4] &= ~0x1;
224 if (isnan(FT0
) || isnan(FT1
)) {
226 env
->fpscr
[4] |= 0x1;
227 /* I don't know how to test "quiet" nan... */
228 if (0 /* || ! quiet_nan(...) */) {
229 env
->fpscr
[6] |= 0x1;
230 if (!(env
->fpscr
[1] & 0x8))
231 env
->fpscr
[4] |= 0x8;
233 env
->fpscr
[4] |= 0x8;
235 } else if (FT0
< FT1
) {
237 } else if (FT0
> FT1
) {
253 p
.i
&= ~0x8000000000000000ULL
;
265 p
.i
|= 0x8000000000000000ULL
;
269 /* Instruction cache invalidation helper */
270 #define ICACHE_LINE_SIZE 32
272 void do_check_reservation (void)
274 if ((env
->reserve
& ~0x03) == T0
)
280 /* Invalidate one cache line */
281 T0
&= ~(ICACHE_LINE_SIZE
- 1);
282 tb_invalidate_page_range(T0
, T0
+ ICACHE_LINE_SIZE
);
285 /* TLB invalidation helpers */
293 tlb_flush_page(env
, T0
);