58
void do_raise_exception (uint32_t exception)
60
do_raise_exception_err(exception, 0);
63
void cpu_dump_EA (target_ulong EA);
64
void do_print_mem_EA (target_ulong EA)
69
/*****************************************************************************/
70
/* Registers load and stores */
71
void do_load_cr (void)
73
T0 = (env->crf[0] << 28) |
83
void do_store_cr (uint32_t mask)
87
for (i = 0, sh = 7; i < 8; i++, sh--) {
89
env->crf[i] = (T0 >> (sh * 4)) & 0xFUL;
50
void helper_raise_exception (uint32_t exception)
52
helper_raise_exception_err(exception, 0);
55
/*****************************************************************************/
57
void helper_load_dump_spr (uint32_t sprn)
59
qemu_log("Read SPR %d %03x => " TARGET_FMT_lx "\n", sprn, sprn,
63
void helper_store_dump_spr (uint32_t sprn)
65
qemu_log("Write SPR %d %03x <= " TARGET_FMT_lx "\n", sprn, sprn,
69
target_ulong helper_load_tbl (void)
71
return cpu_ppc_load_tbl(env);
74
target_ulong helper_load_tbu (void)
76
return cpu_ppc_load_tbu(env);
79
target_ulong helper_load_atbl (void)
81
return cpu_ppc_load_atbl(env);
84
target_ulong helper_load_atbu (void)
86
return cpu_ppc_load_atbu(env);
89
target_ulong helper_load_601_rtcl (void)
91
return cpu_ppc601_load_rtcl(env);
94
target_ulong helper_load_601_rtcu (void)
96
return cpu_ppc601_load_rtcu(env);
99
#if !defined(CONFIG_USER_ONLY)
100
#if defined (TARGET_PPC64)
101
void helper_store_asr (target_ulong val)
103
ppc_store_asr(env, val);
107
void helper_store_sdr1 (target_ulong val)
109
ppc_store_sdr1(env, val);
112
void helper_store_tbl (target_ulong val)
114
cpu_ppc_store_tbl(env, val);
117
void helper_store_tbu (target_ulong val)
119
cpu_ppc_store_tbu(env, val);
122
void helper_store_atbl (target_ulong val)
124
cpu_ppc_store_atbl(env, val);
127
void helper_store_atbu (target_ulong val)
129
cpu_ppc_store_atbu(env, val);
132
void helper_store_601_rtcl (target_ulong val)
134
cpu_ppc601_store_rtcl(env, val);
137
void helper_store_601_rtcu (target_ulong val)
139
cpu_ppc601_store_rtcu(env, val);
142
target_ulong helper_load_decr (void)
144
return cpu_ppc_load_decr(env);
147
void helper_store_decr (target_ulong val)
149
cpu_ppc_store_decr(env, val);
152
void helper_store_hid0_601 (target_ulong val)
156
hid0 = env->spr[SPR_HID0];
157
if ((val ^ hid0) & 0x00000008) {
158
/* Change current endianness */
159
env->hflags &= ~(1 << MSR_LE);
160
env->hflags_nmsr &= ~(1 << MSR_LE);
161
env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
162
env->hflags |= env->hflags_nmsr;
163
qemu_log("%s: set endianness to %c => " TARGET_FMT_lx "\n", __func__,
164
val & 0x8 ? 'l' : 'b', env->hflags);
166
env->spr[SPR_HID0] = (uint32_t)val;
169
void helper_store_403_pbr (uint32_t num, target_ulong value)
171
if (likely(env->pb[num] != value)) {
172
env->pb[num] = value;
173
/* Should be optimized */
178
target_ulong helper_load_40x_pit (void)
180
return load_40x_pit(env);
183
void helper_store_40x_pit (target_ulong val)
185
store_40x_pit(env, val);
188
void helper_store_40x_dbcr0 (target_ulong val)
190
store_40x_dbcr0(env, val);
193
void helper_store_40x_sler (target_ulong val)
195
store_40x_sler(env, val);
198
void helper_store_booke_tcr (target_ulong val)
200
store_booke_tcr(env, val);
203
void helper_store_booke_tsr (target_ulong val)
205
store_booke_tsr(env, val);
208
void helper_store_ibatu (uint32_t nr, target_ulong val)
210
ppc_store_ibatu(env, nr, val);
213
void helper_store_ibatl (uint32_t nr, target_ulong val)
215
ppc_store_ibatl(env, nr, val);
218
void helper_store_dbatu (uint32_t nr, target_ulong val)
220
ppc_store_dbatu(env, nr, val);
223
void helper_store_dbatl (uint32_t nr, target_ulong val)
225
ppc_store_dbatl(env, nr, val);
228
void helper_store_601_batl (uint32_t nr, target_ulong val)
230
ppc_store_ibatl_601(env, nr, val);
233
void helper_store_601_batu (uint32_t nr, target_ulong val)
235
ppc_store_ibatu_601(env, nr, val);
239
/*****************************************************************************/
240
/* Memory load and stores */
242
static inline target_ulong addr_add(target_ulong addr, target_long arg)
93
244
#if defined(TARGET_PPC64)
94
void do_store_pri (int prio)
96
env->spr[SPR_PPR] &= ~0x001C000000000000ULL;
97
env->spr[SPR_PPR] |= ((uint64_t)prio & 0x7) << 50;
246
return (uint32_t)(addr + arg);
101
target_ulong ppc_load_dump_spr (int sprn)
104
fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
105
sprn, sprn, env->spr[sprn]);
108
return env->spr[sprn];
111
void ppc_store_dump_spr (int sprn, target_ulong val)
114
fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n",
115
sprn, sprn, env->spr[sprn], val);
117
env->spr[sprn] = val;
252
void helper_lmw (target_ulong addr, uint32_t reg)
254
for (; reg < 32; reg++) {
256
env->gpr[reg] = bswap32(ldl(addr));
258
env->gpr[reg] = ldl(addr);
259
addr = addr_add(addr, 4);
263
void helper_stmw (target_ulong addr, uint32_t reg)
265
for (; reg < 32; reg++) {
267
stl(addr, bswap32((uint32_t)env->gpr[reg]));
269
stl(addr, (uint32_t)env->gpr[reg]);
270
addr = addr_add(addr, 4);
274
void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg)
277
for (; nb > 3; nb -= 4) {
278
env->gpr[reg] = ldl(addr);
279
reg = (reg + 1) % 32;
280
addr = addr_add(addr, 4);
282
if (unlikely(nb > 0)) {
284
for (sh = 24; nb > 0; nb--, sh -= 8) {
285
env->gpr[reg] |= ldub(addr) << sh;
286
addr = addr_add(addr, 1);
290
/* PPC32 specification says we must generate an exception if
291
* rA is in the range of registers to be loaded.
292
* In an other hand, IBM says this is valid, but rA won't be loaded.
293
* For now, I'll follow the spec...
295
void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
297
if (likely(xer_bc != 0)) {
298
if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) ||
299
(reg < rb && (reg + xer_bc) > rb))) {
300
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
302
POWERPC_EXCP_INVAL_LSWX);
304
helper_lsw(addr, xer_bc, reg);
309
void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg)
312
for (; nb > 3; nb -= 4) {
313
stl(addr, env->gpr[reg]);
314
reg = (reg + 1) % 32;
315
addr = addr_add(addr, 4);
317
if (unlikely(nb > 0)) {
318
for (sh = 24; nb > 0; nb--, sh -= 8) {
319
stb(addr, (env->gpr[reg] >> sh) & 0xFF);
320
addr = addr_add(addr, 1);
325
static void do_dcbz(target_ulong addr, int dcache_line_size)
327
addr &= ~(dcache_line_size - 1);
329
for (i = 0 ; i < dcache_line_size ; i += 4) {
332
if (env->reserve_addr == addr)
333
env->reserve_addr = (target_ulong)-1ULL;
336
void helper_dcbz(target_ulong addr)
338
do_dcbz(addr, env->dcache_line_size);
341
void helper_dcbz_970(target_ulong addr)
343
if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1)
346
do_dcbz(addr, env->dcache_line_size);
349
void helper_icbi(target_ulong addr)
353
addr &= ~(env->dcache_line_size - 1);
354
/* Invalidate one cache line :
355
* PowerPC specification says this is to be treated like a load
356
* (not a fetch) by the MMU. To be sure it will be so,
357
* do the load "by hand".
360
tb_invalidate_page_range(addr, addr + env->icache_line_size);
364
target_ulong helper_lscbx (target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
368
for (i = 0; i < xer_bc; i++) {
370
addr = addr_add(addr, 1);
371
/* ra (if not 0) and rb are never modified */
372
if (likely(reg != rb && (ra == 0 || reg != ra))) {
373
env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
375
if (unlikely(c == xer_cmp))
377
if (likely(d != 0)) {
120
388
/*****************************************************************************/
121
389
/* Fixed point operations helpers */
126
if (likely(!((uint32_t)T0 < (uint32_t)T2 ||
127
(xer_ca == 1 && (uint32_t)T0 == (uint32_t)T2)))) {
134
#if defined(TARGET_PPC64)
135
void do_adde_64 (void)
139
if (likely(!((uint64_t)T0 < (uint64_t)T2 ||
140
(xer_ca == 1 && (uint64_t)T0 == (uint64_t)T2)))) {
148
void do_addmeo (void)
152
xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31;
160
#if defined(TARGET_PPC64)
161
void do_addmeo_64 (void)
165
xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63;
176
if (likely(!(((int32_t)T0 == INT32_MIN && (int32_t)T1 == (int32_t)-1) ||
177
(int32_t)T1 == 0))) {
179
T0 = (int32_t)T0 / (int32_t)T1;
182
T0 = UINT32_MAX * ((uint32_t)T0 >> 31);
187
#if defined(TARGET_PPC64)
190
if (likely(!(((int64_t)T0 == INT64_MIN && (int64_t)T1 == (int64_t)-1LL) ||
191
(int64_t)T1 == 0))) {
193
T0 = (int64_t)T0 / (int64_t)T1;
196
T0 = UINT64_MAX * ((uint64_t)T0 >> 63);
202
void do_divwuo (void)
204
if (likely((uint32_t)T1 != 0)) {
206
T0 = (uint32_t)T0 / (uint32_t)T1;
214
#if defined(TARGET_PPC64)
215
void do_divduo (void)
217
if (likely((uint64_t)T1 != 0)) {
219
T0 = (uint64_t)T0 / (uint64_t)T1;
228
void do_mullwo (void)
230
int64_t res = (int64_t)T0 * (int64_t)T1;
232
if (likely((int32_t)res == res)) {
241
#if defined(TARGET_PPC64)
242
void do_mulldo (void)
390
#if defined(TARGET_PPC64)
392
/* multiply high word */
393
uint64_t helper_mulhd (uint64_t arg1, uint64_t arg2)
397
muls64(&tl, &th, arg1, arg2);
401
/* multiply high word unsigned */
402
uint64_t helper_mulhdu (uint64_t arg1, uint64_t arg2)
406
mulu64(&tl, &th, arg1, arg2);
410
uint64_t helper_mulldo (uint64_t arg1, uint64_t arg2)
247
muls64(&tl, &th, T0, T1);
415
muls64(&tl, (uint64_t *)&th, arg1, arg2);
249
416
/* If th != 0 && th != -1, then we had an overflow */
250
417
if (likely((uint64_t)(th + 1) <= 1)) {
261
if (likely((int32_t)T0 != INT32_MIN)) {
270
#if defined(TARGET_PPC64)
271
void do_nego_64 (void)
273
if (likely((int64_t)T0 != INT64_MIN)) {
285
T0 = T1 + ~T0 + xer_ca;
286
if (likely((uint32_t)T0 >= (uint32_t)T1 &&
287
(xer_ca == 0 || (uint32_t)T0 != (uint32_t)T1))) {
294
#if defined(TARGET_PPC64)
295
void do_subfe_64 (void)
297
T0 = T1 + ~T0 + xer_ca;
298
if (likely((uint64_t)T0 >= (uint64_t)T1 &&
299
(xer_ca == 0 || (uint64_t)T0 != (uint64_t)T1))) {
307
void do_subfmeo (void)
310
T0 = ~T0 + xer_ca - 1;
311
xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31;
313
if (likely((uint32_t)T1 != UINT32_MAX))
319
#if defined(TARGET_PPC64)
320
void do_subfmeo_64 (void)
323
T0 = ~T0 + xer_ca - 1;
324
xer_ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63;
326
if (likely((uint64_t)T1 != UINT64_MAX))
333
void do_subfzeo (void)
337
xer_ov = (((uint32_t)~T1 ^ UINT32_MAX) &
338
((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31;
340
if (likely((uint32_t)T0 >= (uint32_t)~T1)) {
347
#if defined(TARGET_PPC64)
348
void do_subfzeo_64 (void)
352
xer_ov = (((uint64_t)~T1 ^ UINT64_MAX) &
353
((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63;
355
if (likely((uint64_t)T0 >= (uint64_t)~T1)) {
363
void do_cntlzw (void)
368
#if defined(TARGET_PPC64)
369
void do_cntlzd (void)
418
env->xer &= ~(1 << XER_OV);
420
env->xer |= (1 << XER_OV) | (1 << XER_SO);
426
target_ulong helper_cntlzw (target_ulong t)
431
#if defined(TARGET_PPC64)
432
target_ulong helper_cntlzd (target_ulong t)
375
438
/* shift right arithmetic helper */
439
target_ulong helper_sraw (target_ulong value, target_ulong shift)
380
if (likely(!(T1 & 0x20UL))) {
381
if (likely((uint32_t)T1 != 0)) {
382
ret = (int32_t)T0 >> (T1 & 0x1fUL);
383
if (likely(ret >= 0 || ((int32_t)T0 & ((1 << T1) - 1)) == 0)) {
443
if (likely(!(shift & 0x20))) {
444
if (likely((uint32_t)shift != 0)) {
446
ret = (int32_t)value >> shift;
447
if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
448
env->xer &= ~(1 << XER_CA);
450
env->xer |= (1 << XER_CA);
453
ret = (int32_t)value;
454
env->xer &= ~(1 << XER_CA);
393
ret = UINT32_MAX * ((uint32_t)T0 >> 31);
394
if (likely(ret >= 0 || ((uint32_t)T0 & ~0x80000000UL) == 0)) {
457
ret = (int32_t)value >> 31;
459
env->xer |= (1 << XER_CA);
461
env->xer &= ~(1 << XER_CA);
464
return (target_long)ret;
403
467
#if defined(TARGET_PPC64)
468
target_ulong helper_srad (target_ulong value, target_ulong shift)
408
if (likely(!(T1 & 0x40UL))) {
409
if (likely((uint64_t)T1 != 0)) {
410
ret = (int64_t)T0 >> (T1 & 0x3FUL);
411
if (likely(ret >= 0 || ((int64_t)T0 & ((1 << T1) - 1)) == 0)) {
472
if (likely(!(shift & 0x40))) {
473
if (likely((uint64_t)shift != 0)) {
475
ret = (int64_t)value >> shift;
476
if (likely(ret >= 0 || (value & ((1 << shift) - 1)) == 0)) {
477
env->xer &= ~(1 << XER_CA);
479
env->xer |= (1 << XER_CA);
482
ret = (int64_t)value;
483
env->xer &= ~(1 << XER_CA);
421
ret = UINT64_MAX * ((uint64_t)T0 >> 63);
422
if (likely(ret >= 0 || ((uint64_t)T0 & ~0x8000000000000000ULL) == 0)) {
486
ret = (int64_t)value >> 63;
488
env->xer |= (1 << XER_CA);
490
env->xer &= ~(1 << XER_CA);
432
void do_popcntb (void)
497
target_ulong helper_popcntb (target_ulong val)
438
for (i = 0; i < 32; i += 8)
439
ret |= ctpop8((T0 >> i) & 0xFF) << i;
499
val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
500
val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
501
val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
443
505
#if defined(TARGET_PPC64)
444
void do_popcntb_64 (void)
506
target_ulong helper_popcntb_64 (target_ulong val)
450
for (i = 0; i < 64; i += 8)
451
ret |= ctpop8((T0 >> i) & 0xFF) << i;
508
val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL);
509
val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL);
510
val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fULL);
456
515
/*****************************************************************************/
457
516
/* Floating point operations helpers */
458
static always_inline int fpisneg (float64 d)
464
return u.ll >> 63 != 0;
467
static always_inline int isden (float64 d)
517
uint64_t helper_float32_to_float64(uint32_t arg)
522
d.d = float32_to_float64(f.f, &env->fp_status);
526
uint32_t helper_float64_to_float32(uint64_t arg)
531
f.f = float64_to_float32(d.d, &env->fp_status);
535
static inline int isden(float64 d)
901
931
env->fpscr &= ~(1 << FPSCR_FEX);
902
932
fpscr_set_rounding_mode();
907
#ifdef CONFIG_SOFTFLOAT
908
void do_float_check_status (void)
910
if (env->exception_index == POWERPC_EXCP_PROGRAM &&
911
(env->error_code & POWERPC_EXCP_FP)) {
912
/* Differred floating-point exception after target FPR update */
913
if (msr_fe0 != 0 || msr_fe1 != 0)
914
do_raise_exception_err(env->exception_index, env->error_code);
915
} else if (env->fp_status.float_exception_flags & float_flag_overflow) {
916
float_overflow_excp();
917
} else if (env->fp_status.float_exception_flags & float_flag_underflow) {
918
float_underflow_excp();
919
} else if (env->fp_status.float_exception_flags & float_flag_inexact) {
920
float_inexact_excp();
935
void helper_float_check_status (void)
937
#ifdef CONFIG_SOFTFLOAT
938
if (env->exception_index == POWERPC_EXCP_PROGRAM &&
939
(env->error_code & POWERPC_EXCP_FP)) {
940
/* Differred floating-point exception after target FPR update */
941
if (msr_fe0 != 0 || msr_fe1 != 0)
942
helper_raise_exception_err(env->exception_index, env->error_code);
944
int status = get_float_exception_flags(&env->fp_status);
945
if (status & float_flag_divbyzero) {
946
float_zero_divide_excp();
947
} else if (status & float_flag_overflow) {
948
float_overflow_excp();
949
} else if (status & float_flag_underflow) {
950
float_underflow_excp();
951
} else if (status & float_flag_inexact) {
952
float_inexact_excp();
956
if (env->exception_index == POWERPC_EXCP_PROGRAM &&
957
(env->error_code & POWERPC_EXCP_FP)) {
958
/* Differred floating-point exception after target FPR update */
959
if (msr_fe0 != 0 || msr_fe1 != 0)
960
helper_raise_exception_err(env->exception_index, env->error_code);
965
#ifdef CONFIG_SOFTFLOAT
966
void helper_reset_fpstatus (void)
968
set_float_exception_flags(0, &env->fp_status);
973
uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
975
CPU_DoubleU farg1, farg2;
925
979
#if USE_PRECISE_EMULATION
928
if (unlikely(float64_is_signaling_nan(FT0) ||
929
float64_is_signaling_nan(FT1))) {
980
if (unlikely(float64_is_signaling_nan(farg1.d) ||
981
float64_is_signaling_nan(farg2.d))) {
930
982
/* sNaN addition */
931
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
932
} else if (likely(isfinite(FT0) || isfinite(FT1) ||
933
fpisneg(FT0) == fpisneg(FT1))) {
934
FT0 = float64_add(FT0, FT1, &env->fp_status);
983
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
984
} else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
985
float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
986
/* Magnitude subtraction of infinities */
987
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
936
/* Magnitude subtraction of infinities */
937
fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
989
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
992
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
943
if (unlikely(float64_is_signaling_nan(FT0) ||
944
float64_is_signaling_nan(FT1))) {
998
uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
1000
CPU_DoubleU farg1, farg2;
1004
#if USE_PRECISE_EMULATION
1006
if (unlikely(float64_is_signaling_nan(farg1.d) ||
1007
float64_is_signaling_nan(farg2.d))) {
945
1008
/* sNaN subtraction */
946
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
947
} else if (likely(isfinite(FT0) || isfinite(FT1) ||
948
fpisneg(FT0) != fpisneg(FT1))) {
949
FT0 = float64_sub(FT0, FT1, &env->fp_status);
1009
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1010
} else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
1011
float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
1012
/* Magnitude subtraction of infinities */
1013
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
951
/* Magnitude subtraction of infinities */
952
fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1015
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1019
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
1025
uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
958
if (unlikely(float64_is_signaling_nan(FT0) ||
959
float64_is_signaling_nan(FT1))) {
1027
CPU_DoubleU farg1, farg2;
1031
#if USE_PRECISE_EMULATION
1032
if (unlikely(float64_is_signaling_nan(farg1.d) ||
1033
float64_is_signaling_nan(farg2.d))) {
960
1034
/* sNaN multiplication */
961
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
962
} else if (unlikely((isinfinity(FT0) && iszero(FT1)) ||
963
(iszero(FT0) && isinfinity(FT1)))) {
1035
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1036
} else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1037
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
964
1038
/* Multiplication of zero by infinity */
965
fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1039
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
967
FT0 = float64_mul(FT0, FT1, &env->fp_status);
1041
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1044
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1050
uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
973
if (unlikely(float64_is_signaling_nan(FT0) ||
974
float64_is_signaling_nan(FT1))) {
1052
CPU_DoubleU farg1, farg2;
1056
#if USE_PRECISE_EMULATION
1057
if (unlikely(float64_is_signaling_nan(farg1.d) ||
1058
float64_is_signaling_nan(farg2.d))) {
975
1059
/* sNaN division */
976
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
977
} else if (unlikely(isinfinity(FT0) && isinfinity(FT1))) {
1060
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1061
} else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
978
1062
/* Division of infinity by infinity */
979
fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
980
} else if (unlikely(iszero(FT1))) {
982
/* Division of zero by zero */
983
fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
985
/* Division by zero */
986
float_zero_divide_excp();
989
FT0 = float64_div(FT0, FT1, &env->fp_status);
992
#endif /* USE_PRECISE_EMULATION */
998
if (unlikely(float64_is_signaling_nan(FT0))) {
999
/* sNaN conversion */
1000
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1001
} else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1002
/* qNan / infinity conversion */
1003
fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1005
p.ll = float64_to_int32(FT0, &env->fp_status);
1006
#if USE_PRECISE_EMULATION
1007
/* XXX: higher bits are not supposed to be significant.
1008
* to make tests easier, return the same as a real PowerPC 750
1010
p.ll |= 0xFFF80000ULL << 32;
1016
void do_fctiwz (void)
1020
if (unlikely(float64_is_signaling_nan(FT0))) {
1021
/* sNaN conversion */
1022
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1023
} else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1024
/* qNan / infinity conversion */
1025
fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1027
p.ll = float64_to_int32_round_to_zero(FT0, &env->fp_status);
1028
#if USE_PRECISE_EMULATION
1029
/* XXX: higher bits are not supposed to be significant.
1030
* to make tests easier, return the same as a real PowerPC 750
1032
p.ll |= 0xFFF80000ULL << 32;
1063
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
1064
} else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
1065
/* Division of zero by zero */
1066
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
1068
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1071
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
1077
uint64_t helper_fabs (uint64_t arg)
1082
farg.d = float64_abs(farg.d);
1087
uint64_t helper_fnabs (uint64_t arg)
1092
farg.d = float64_abs(farg.d);
1093
farg.d = float64_chs(farg.d);
1098
uint64_t helper_fneg (uint64_t arg)
1103
farg.d = float64_chs(farg.d);
1107
/* fctiw - fctiw. */
1108
uint64_t helper_fctiw (uint64_t arg)
1113
if (unlikely(float64_is_signaling_nan(farg.d))) {
1114
/* sNaN conversion */
1115
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1116
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1117
/* qNan / infinity conversion */
1118
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1120
farg.ll = float64_to_int32(farg.d, &env->fp_status);
1121
#if USE_PRECISE_EMULATION
1122
/* XXX: higher bits are not supposed to be significant.
1123
* to make tests easier, return the same as a real PowerPC 750
1125
farg.ll |= 0xFFF80000ULL << 32;
1131
/* fctiwz - fctiwz. */
1132
uint64_t helper_fctiwz (uint64_t arg)
1137
if (unlikely(float64_is_signaling_nan(farg.d))) {
1138
/* sNaN conversion */
1139
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1140
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1141
/* qNan / infinity conversion */
1142
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1144
farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
1145
#if USE_PRECISE_EMULATION
1146
/* XXX: higher bits are not supposed to be significant.
1147
* to make tests easier, return the same as a real PowerPC 750
1149
farg.ll |= 0xFFF80000ULL << 32;
1038
1155
#if defined(TARGET_PPC64)
1039
void do_fcfid (void)
1044
FT0 = int64_to_float64(p.ll, &env->fp_status);
1047
void do_fctid (void)
1051
if (unlikely(float64_is_signaling_nan(FT0))) {
1052
/* sNaN conversion */
1053
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1054
} else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1055
/* qNan / infinity conversion */
1056
fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1058
p.ll = float64_to_int64(FT0, &env->fp_status);
1063
void do_fctidz (void)
1067
if (unlikely(float64_is_signaling_nan(FT0))) {
1068
/* sNaN conversion */
1069
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1070
} else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1071
/* qNan / infinity conversion */
1072
fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1074
p.ll = float64_to_int64_round_to_zero(FT0, &env->fp_status);
1156
/* fcfid - fcfid. */
1157
uint64_t helper_fcfid (uint64_t arg)
1160
farg.d = int64_to_float64(arg, &env->fp_status);
1164
/* fctid - fctid. */
1165
uint64_t helper_fctid (uint64_t arg)
1170
if (unlikely(float64_is_signaling_nan(farg.d))) {
1171
/* sNaN conversion */
1172
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1173
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1174
/* qNan / infinity conversion */
1175
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1177
farg.ll = float64_to_int64(farg.d, &env->fp_status);
1182
/* fctidz - fctidz. */
1183
uint64_t helper_fctidz (uint64_t arg)
1188
if (unlikely(float64_is_signaling_nan(farg.d))) {
1189
/* sNaN conversion */
1190
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1191
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1192
/* qNan / infinity conversion */
1193
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1195
farg.ll = float64_to_int64_round_to_zero(farg.d, &env->fp_status);
1081
static always_inline void do_fri (int rounding_mode)
1202
static inline uint64_t do_fri(uint64_t arg, int rounding_mode)
1083
if (unlikely(float64_is_signaling_nan(FT0))) {
1207
if (unlikely(float64_is_signaling_nan(farg.d))) {
1084
1208
/* sNaN round */
1085
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1086
} else if (unlikely(float64_is_nan(FT0) || isinfinity(FT0))) {
1209
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
1210
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
1087
1211
/* qNan / infinity round */
1088
fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1212
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
1090
1214
set_float_rounding_mode(rounding_mode, &env->fp_status);
1091
FT0 = float64_round_to_int(FT0, &env->fp_status);
1215
farg.ll = float64_round_to_int(farg.d, &env->fp_status);
1092
1216
/* Restore rounding mode from FPSCR */
1093
1217
fpscr_set_rounding_mode();
1099
do_fri(float_round_nearest_even);
1104
do_fri(float_round_to_zero);
1109
do_fri(float_round_up);
1114
do_fri(float_round_down);
1117
#if USE_PRECISE_EMULATION
1118
void do_fmadd (void)
1120
if (unlikely(float64_is_signaling_nan(FT0) ||
1121
float64_is_signaling_nan(FT1) ||
1122
float64_is_signaling_nan(FT2))) {
1123
/* sNaN operation */
1124
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1127
/* This is the way the PowerPC specification defines it */
1128
float128 ft0_128, ft1_128;
1130
ft0_128 = float64_to_float128(FT0, &env->fp_status);
1131
ft1_128 = float64_to_float128(FT1, &env->fp_status);
1132
ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1133
ft1_128 = float64_to_float128(FT2, &env->fp_status);
1134
ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1135
FT0 = float128_to_float64(ft0_128, &env->fp_status);
1137
/* This is OK on x86 hosts */
1138
FT0 = (FT0 * FT1) + FT2;
1143
void do_fmsub (void)
1145
if (unlikely(float64_is_signaling_nan(FT0) ||
1146
float64_is_signaling_nan(FT1) ||
1147
float64_is_signaling_nan(FT2))) {
1148
/* sNaN operation */
1149
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1152
/* This is the way the PowerPC specification defines it */
1153
float128 ft0_128, ft1_128;
1155
ft0_128 = float64_to_float128(FT0, &env->fp_status);
1156
ft1_128 = float64_to_float128(FT1, &env->fp_status);
1157
ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1158
ft1_128 = float64_to_float128(FT2, &env->fp_status);
1159
ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1160
FT0 = float128_to_float64(ft0_128, &env->fp_status);
1162
/* This is OK on x86 hosts */
1163
FT0 = (FT0 * FT1) - FT2;
1167
#endif /* USE_PRECISE_EMULATION */
1169
void do_fnmadd (void)
1171
if (unlikely(float64_is_signaling_nan(FT0) ||
1172
float64_is_signaling_nan(FT1) ||
1173
float64_is_signaling_nan(FT2))) {
1174
/* sNaN operation */
1175
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1177
#if USE_PRECISE_EMULATION
1179
/* This is the way the PowerPC specification defines it */
1180
float128 ft0_128, ft1_128;
1182
ft0_128 = float64_to_float128(FT0, &env->fp_status);
1183
ft1_128 = float64_to_float128(FT1, &env->fp_status);
1184
ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1185
ft1_128 = float64_to_float128(FT2, &env->fp_status);
1186
ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1187
FT0 = float128_to_float64(ft0_128, &env->fp_status);
1189
/* This is OK on x86 hosts */
1190
FT0 = (FT0 * FT1) + FT2;
1193
FT0 = float64_mul(FT0, FT1, &env->fp_status);
1194
FT0 = float64_add(FT0, FT2, &env->fp_status);
1196
if (likely(!isnan(FT0)))
1197
FT0 = float64_chs(FT0);
1201
void do_fnmsub (void)
1203
if (unlikely(float64_is_signaling_nan(FT0) ||
1204
float64_is_signaling_nan(FT1) ||
1205
float64_is_signaling_nan(FT2))) {
1206
/* sNaN operation */
1207
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1209
#if USE_PRECISE_EMULATION
1211
/* This is the way the PowerPC specification defines it */
1212
float128 ft0_128, ft1_128;
1214
ft0_128 = float64_to_float128(FT0, &env->fp_status);
1215
ft1_128 = float64_to_float128(FT1, &env->fp_status);
1216
ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1217
ft1_128 = float64_to_float128(FT2, &env->fp_status);
1218
ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1219
FT0 = float128_to_float64(ft0_128, &env->fp_status);
1221
/* This is OK on x86 hosts */
1222
FT0 = (FT0 * FT1) - FT2;
1225
FT0 = float64_mul(FT0, FT1, &env->fp_status);
1226
FT0 = float64_sub(FT0, FT2, &env->fp_status);
1228
if (likely(!isnan(FT0)))
1229
FT0 = float64_chs(FT0);
1233
#if USE_PRECISE_EMULATION
1236
if (unlikely(float64_is_signaling_nan(FT0))) {
1237
/* sNaN square root */
1238
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1240
FT0 = float64_to_float32(FT0, &env->fp_status);
1243
#endif /* USE_PRECISE_EMULATION */
1245
void do_fsqrt (void)
1247
if (unlikely(float64_is_signaling_nan(FT0))) {
1248
/* sNaN square root */
1249
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1250
} else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
1222
uint64_t helper_frin (uint64_t arg)
1224
return do_fri(arg, float_round_nearest_even);
1227
uint64_t helper_friz (uint64_t arg)
1229
return do_fri(arg, float_round_to_zero);
1232
uint64_t helper_frip (uint64_t arg)
1234
return do_fri(arg, float_round_up);
1237
uint64_t helper_frim (uint64_t arg)
1239
return do_fri(arg, float_round_down);
1242
/* fmadd - fmadd. */
1243
uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1245
CPU_DoubleU farg1, farg2, farg3;
1250
#if USE_PRECISE_EMULATION
1251
if (unlikely(float64_is_signaling_nan(farg1.d) ||
1252
float64_is_signaling_nan(farg2.d) ||
1253
float64_is_signaling_nan(farg3.d))) {
1254
/* sNaN operation */
1255
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1256
} else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1257
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1258
/* Multiplication of zero by infinity */
1259
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1262
/* This is the way the PowerPC specification defines it */
1263
float128 ft0_128, ft1_128;
1265
ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1266
ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1267
ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1268
if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1269
float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1270
/* Magnitude subtraction of infinities */
1271
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1273
ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1274
ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1275
farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1278
/* This is OK on x86 hosts */
1279
farg1.d = (farg1.d * farg2.d) + farg3.d;
1283
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1284
farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1289
/* fmsub - fmsub. */
1290
uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1292
CPU_DoubleU farg1, farg2, farg3;
1297
#if USE_PRECISE_EMULATION
1298
if (unlikely(float64_is_signaling_nan(farg1.d) ||
1299
float64_is_signaling_nan(farg2.d) ||
1300
float64_is_signaling_nan(farg3.d))) {
1301
/* sNaN operation */
1302
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1303
} else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1304
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1305
/* Multiplication of zero by infinity */
1306
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1309
/* This is the way the PowerPC specification defines it */
1310
float128 ft0_128, ft1_128;
1312
ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1313
ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1314
ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1315
if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1316
float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1317
/* Magnitude subtraction of infinities */
1318
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1320
ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1321
ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1322
farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1325
/* This is OK on x86 hosts */
1326
farg1.d = (farg1.d * farg2.d) - farg3.d;
1330
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1331
farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1336
/* fnmadd - fnmadd. */
1337
uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1339
CPU_DoubleU farg1, farg2, farg3;
1345
if (unlikely(float64_is_signaling_nan(farg1.d) ||
1346
float64_is_signaling_nan(farg2.d) ||
1347
float64_is_signaling_nan(farg3.d))) {
1348
/* sNaN operation */
1349
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1350
} else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1351
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1352
/* Multiplication of zero by infinity */
1353
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1355
#if USE_PRECISE_EMULATION
1357
/* This is the way the PowerPC specification defines it */
1358
float128 ft0_128, ft1_128;
1360
ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1361
ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1362
ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1363
if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1364
float128_is_neg(ft0_128) != float64_is_neg(farg3.d))) {
1365
/* Magnitude subtraction of infinities */
1366
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1368
ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1369
ft0_128 = float128_add(ft0_128, ft1_128, &env->fp_status);
1370
farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1373
/* This is OK on x86 hosts */
1374
farg1.d = (farg1.d * farg2.d) + farg3.d;
1377
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1378
farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
1380
if (likely(!float64_is_nan(farg1.d)))
1381
farg1.d = float64_chs(farg1.d);
1386
/* fnmsub - fnmsub. */
1387
uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1389
CPU_DoubleU farg1, farg2, farg3;
1395
if (unlikely(float64_is_signaling_nan(farg1.d) ||
1396
float64_is_signaling_nan(farg2.d) ||
1397
float64_is_signaling_nan(farg3.d))) {
1398
/* sNaN operation */
1399
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1400
} else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
1401
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
1402
/* Multiplication of zero by infinity */
1403
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
1405
#if USE_PRECISE_EMULATION
1407
/* This is the way the PowerPC specification defines it */
1408
float128 ft0_128, ft1_128;
1410
ft0_128 = float64_to_float128(farg1.d, &env->fp_status);
1411
ft1_128 = float64_to_float128(farg2.d, &env->fp_status);
1412
ft0_128 = float128_mul(ft0_128, ft1_128, &env->fp_status);
1413
if (unlikely(float128_is_infinity(ft0_128) && float64_is_infinity(farg3.d) &&
1414
float128_is_neg(ft0_128) == float64_is_neg(farg3.d))) {
1415
/* Magnitude subtraction of infinities */
1416
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
1418
ft1_128 = float64_to_float128(farg3.d, &env->fp_status);
1419
ft0_128 = float128_sub(ft0_128, ft1_128, &env->fp_status);
1420
farg1.d = float128_to_float64(ft0_128, &env->fp_status);
1423
/* This is OK on x86 hosts */
1424
farg1.d = (farg1.d * farg2.d) - farg3.d;
1427
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
1428
farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
1430
if (likely(!float64_is_nan(farg1.d)))
1431
farg1.d = float64_chs(farg1.d);
1437
uint64_t helper_frsp (uint64_t arg)
1443
#if USE_PRECISE_EMULATION
1444
if (unlikely(float64_is_signaling_nan(farg.d))) {
1445
/* sNaN square root */
1446
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1448
f32 = float64_to_float32(farg.d, &env->fp_status);
1449
farg.d = float32_to_float64(f32, &env->fp_status);
1452
f32 = float64_to_float32(farg.d, &env->fp_status);
1453
farg.d = float32_to_float64(f32, &env->fp_status);
1458
/* fsqrt - fsqrt. */
1459
uint64_t helper_fsqrt (uint64_t arg)
1464
if (unlikely(float64_is_signaling_nan(farg.d))) {
1465
/* sNaN square root */
1466
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1467
} else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1251
1468
/* Square root of a negative nonzero number */
1252
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1254
FT0 = float64_sqrt(FT0, &env->fp_status);
1262
if (unlikely(float64_is_signaling_nan(FT0))) {
1263
/* sNaN reciprocal */
1264
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1265
} else if (unlikely(iszero(FT0))) {
1266
/* Zero reciprocal */
1267
float_zero_divide_excp();
1268
} else if (likely(isnormal(FT0))) {
1269
FT0 = float64_div(1.0, FT0, &env->fp_status);
1272
if (p.ll == 0x8000000000000000ULL) {
1273
p.ll = 0xFFF0000000000000ULL;
1274
} else if (p.ll == 0x0000000000000000ULL) {
1275
p.ll = 0x7FF0000000000000ULL;
1276
} else if (isnan(FT0)) {
1277
p.ll = 0x7FF8000000000000ULL;
1278
} else if (fpisneg(FT0)) {
1279
p.ll = 0x8000000000000000ULL;
1281
p.ll = 0x0000000000000000ULL;
1291
if (unlikely(float64_is_signaling_nan(FT0))) {
1292
/* sNaN reciprocal */
1293
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1294
} else if (unlikely(iszero(FT0))) {
1295
/* Zero reciprocal */
1296
float_zero_divide_excp();
1297
} else if (likely(isnormal(FT0))) {
1298
#if USE_PRECISE_EMULATION
1299
FT0 = float64_div(1.0, FT0, &env->fp_status);
1300
FT0 = float64_to_float32(FT0, &env->fp_status);
1302
FT0 = float32_div(1.0, FT0, &env->fp_status);
1306
if (p.ll == 0x8000000000000000ULL) {
1307
p.ll = 0xFFF0000000000000ULL;
1308
} else if (p.ll == 0x0000000000000000ULL) {
1309
p.ll = 0x7FF0000000000000ULL;
1310
} else if (isnan(FT0)) {
1311
p.ll = 0x7FF8000000000000ULL;
1312
} else if (fpisneg(FT0)) {
1313
p.ll = 0x8000000000000000ULL;
1315
p.ll = 0x0000000000000000ULL;
1321
void do_frsqrte (void)
1325
if (unlikely(float64_is_signaling_nan(FT0))) {
1469
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1471
farg.d = float64_sqrt(farg.d, &env->fp_status);
1477
uint64_t helper_fre (uint64_t arg)
1482
if (unlikely(float64_is_signaling_nan(farg.d))) {
1483
/* sNaN reciprocal */
1484
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1486
farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1492
uint64_t helper_fres (uint64_t arg)
1498
if (unlikely(float64_is_signaling_nan(farg.d))) {
1499
/* sNaN reciprocal */
1500
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1502
farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1503
f32 = float64_to_float32(farg.d, &env->fp_status);
1504
farg.d = float32_to_float64(f32, &env->fp_status);
1509
/* frsqrte - frsqrte. */
1510
uint64_t helper_frsqrte (uint64_t arg)
1516
if (unlikely(float64_is_signaling_nan(farg.d))) {
1326
1517
/* sNaN reciprocal square root */
1327
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1328
} else if (unlikely(fpisneg(FT0) && !iszero(FT0))) {
1518
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1519
} else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
1329
1520
/* Reciprocal square root of a negative nonzero number */
1330
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1331
} else if (likely(isnormal(FT0))) {
1332
FT0 = float64_sqrt(FT0, &env->fp_status);
1333
FT0 = float32_div(1.0, FT0, &env->fp_status);
1521
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
1336
if (p.ll == 0x8000000000000000ULL) {
1337
p.ll = 0xFFF0000000000000ULL;
1338
} else if (p.ll == 0x0000000000000000ULL) {
1339
p.ll = 0x7FF0000000000000ULL;
1340
} else if (isnan(FT0)) {
1341
p.ll |= 0x000FFFFFFFFFFFFFULL;
1342
} else if (fpisneg(FT0)) {
1343
p.ll = 0x7FF8000000000000ULL;
1345
p.ll = 0x0000000000000000ULL;
1523
farg.d = float64_sqrt(farg.d, &env->fp_status);
1524
farg.d = float64_div(float64_one, farg.d, &env->fp_status);
1525
f32 = float64_to_float32(farg.d, &env->fp_status);
1526
farg.d = float32_to_float64(f32, &env->fp_status);
1532
uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
1353
if (!fpisneg(FT0) || iszero(FT0))
1538
if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_nan(farg1.d))
1359
void do_fcmpu (void)
1544
void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1361
if (unlikely(float64_is_signaling_nan(FT0) ||
1362
float64_is_signaling_nan(FT1))) {
1546
CPU_DoubleU farg1, farg2;
1551
if (unlikely(float64_is_nan(farg1.d) ||
1552
float64_is_nan(farg2.d))) {
1554
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1556
} else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1562
env->fpscr &= ~(0x0F << FPSCR_FPRF);
1563
env->fpscr |= ret << FPSCR_FPRF;
1564
env->crf[crfD] = ret;
1565
if (unlikely(ret == 0x01UL
1566
&& (float64_is_signaling_nan(farg1.d) ||
1567
float64_is_signaling_nan(farg2.d)))) {
1363
1568
/* sNaN comparison */
1364
1569
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
1573
void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
1575
CPU_DoubleU farg1, farg2;
1580
if (unlikely(float64_is_nan(farg1.d) ||
1581
float64_is_nan(farg2.d))) {
1583
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
1585
} else if (!float64_le(farg1.d, farg2.d, &env->fp_status)) {
1366
if (float64_lt(FT0, FT1, &env->fp_status)) {
1368
} else if (!float64_le(FT0, FT1, &env->fp_status)) {
1374
1591
env->fpscr &= ~(0x0F << FPSCR_FPRF);
1375
env->fpscr |= T0 << FPSCR_FPRF;
1378
void do_fcmpo (void)
1380
if (unlikely(float64_is_nan(FT0) ||
1381
float64_is_nan(FT1))) {
1382
if (float64_is_signaling_nan(FT0) ||
1383
float64_is_signaling_nan(FT1)) {
1592
env->fpscr |= ret << FPSCR_FPRF;
1593
env->crf[crfD] = ret;
1594
if (unlikely (ret == 0x01UL)) {
1595
if (float64_is_signaling_nan(farg1.d) ||
1596
float64_is_signaling_nan(farg2.d)) {
1384
1597
/* sNaN comparison */
1385
1598
fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN |
1386
1599
POWERPC_EXCP_FP_VXVC);
1688
1808
/* 602 specific instructions */
1689
1809
/* mfrom is the most crazy instruction ever seen, imho ! */
1690
1810
/* Real implementation uses a ROM table. Do the same */
1691
#define USE_MFROM_ROM_TABLE
1692
void do_op_602_mfrom (void)
1811
/* Extremly decomposed:
1813
* return 256 * log10(10 + 1.0) + 0.5
1815
#if !defined (CONFIG_USER_ONLY)
1816
target_ulong helper_602_mfrom (target_ulong arg)
1694
if (likely(T0 < 602)) {
1695
#if defined(USE_MFROM_ROM_TABLE)
1818
if (likely(arg < 602)) {
1696
1819
#include "mfrom_table.c"
1697
T0 = mfrom_ROM_table[T0];
1700
/* Extremly decomposed:
1702
* T0 = 256 * log10(10 + 1.0) + 0.5
1705
d = float64_div(d, 256, &env->fp_status);
1707
d = exp10(d); // XXX: use float emulation function
1708
d = float64_add(d, 1.0, &env->fp_status);
1709
d = log10(d); // XXX: use float emulation function
1710
d = float64_mul(d, 256, &env->fp_status);
1711
d = float64_add(d, 0.5, &env->fp_status);
1712
T0 = float64_round_to_int(d, &env->fp_status);
1820
return mfrom_ROM_table[arg];
1719
1827
/*****************************************************************************/
1720
1828
/* Embedded PowerPC specific helpers */
1721
void do_405_check_sat (void)
1723
if (!likely((((uint32_t)T1 ^ (uint32_t)T2) >> 31) ||
1724
!(((uint32_t)T0 ^ (uint32_t)T2) >> 31))) {
1725
/* Saturate result */
1734
1830
/* XXX: to be improved to check access rights when in user-mode */
1735
void do_load_dcr (void)
1831
target_ulong helper_load_dcr (target_ulong dcrn)
1833
target_ulong val = 0;
1739
1835
if (unlikely(env->dcr_env == NULL)) {
1740
if (loglevel != 0) {
1741
fprintf(logfile, "No DCR environment\n");
1743
do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1744
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1745
} else if (unlikely(ppc_dcr_read(env->dcr_env, T0, &val) != 0)) {
1746
if (loglevel != 0) {
1747
fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
1749
do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1750
POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1836
qemu_log("No DCR environment\n");
1837
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1838
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1839
} else if (unlikely(ppc_dcr_read(env->dcr_env, dcrn, &val) != 0)) {
1840
qemu_log("DCR read error %d %03x\n", (int)dcrn, (int)dcrn);
1841
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1842
POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1756
void do_store_dcr (void)
1847
void helper_store_dcr (target_ulong dcrn, target_ulong val)
1758
1849
if (unlikely(env->dcr_env == NULL)) {
1759
if (loglevel != 0) {
1760
fprintf(logfile, "No DCR environment\n");
1762
do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1763
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1764
} else if (unlikely(ppc_dcr_write(env->dcr_env, T0, T1) != 0)) {
1765
if (loglevel != 0) {
1766
fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
1768
do_raise_exception_err(POWERPC_EXCP_PROGRAM,
1769
POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1850
qemu_log("No DCR environment\n");
1851
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1852
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
1853
} else if (unlikely(ppc_dcr_write(env->dcr_env, dcrn, val) != 0)) {
1854
qemu_log("DCR write error %d %03x\n", (int)dcrn, (int)dcrn);
1855
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
1856
POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
1773
1860
#if !defined(CONFIG_USER_ONLY)
1774
void do_40x_rfci (void)
1776
__do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1777
~((target_ulong)0xFFFF0000), 0);
1782
__do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1783
~((target_ulong)0x3FFF0000), 0);
1788
__do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1789
~((target_ulong)0x3FFF0000), 0);
1792
void do_rfmci (void)
1794
__do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1795
~((target_ulong)0x3FFF0000), 0);
1798
void do_load_403_pb (int num)
1803
void do_store_403_pb (int num)
1805
if (likely(env->pb[num] != T0)) {
1807
/* Should be optimized */
1861
void helper_40x_rfci (void)
1863
do_rfi(env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
1864
~((target_ulong)0xFFFF0000), 0);
1867
void helper_rfci (void)
1869
do_rfi(env->spr[SPR_BOOKE_CSRR0], SPR_BOOKE_CSRR1,
1870
~((target_ulong)0x3FFF0000), 0);
1873
void helper_rfdi (void)
1875
do_rfi(env->spr[SPR_BOOKE_DSRR0], SPR_BOOKE_DSRR1,
1876
~((target_ulong)0x3FFF0000), 0);
1879
void helper_rfmci (void)
1881
do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
1882
~((target_ulong)0x3FFF0000), 0);
1813
1886
/* 440 specific */
1814
void do_440_dlmzb (void)
1887
target_ulong helper_dlmzb (target_ulong high, target_ulong low, uint32_t update_Rc)
1816
1889
target_ulong mask;
1820
1893
for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1821
if ((T0 & mask) == 0)
1894
if ((high & mask) == 0) {
1825
1902
for (mask = 0xFF000000; mask != 0; mask = mask >> 8) {
1826
if ((T1 & mask) == 0)
1903
if ((low & mask) == 0) {
1915
env->xer = (env->xer & ~0x7F) | i;
1917
env->crf[0] |= xer_so;
1922
/*****************************************************************************/
1923
/* Altivec extension helpers */
1924
#if defined(HOST_WORDS_BIGENDIAN)
1932
#if defined(HOST_WORDS_BIGENDIAN)
1933
#define VECTOR_FOR_INORDER_I(index, element) \
1934
for (index = 0; index < ARRAY_SIZE(r->element); index++)
1936
#define VECTOR_FOR_INORDER_I(index, element) \
1937
for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
1940
/* If X is a NaN, store the corresponding QNaN into RESULT. Otherwise,
1941
* execute the following block. */
1942
#define DO_HANDLE_NAN(result, x) \
1943
if (float32_is_nan(x) || float32_is_signaling_nan(x)) { \
1946
__f.l = __f.l | (1 << 22); /* Set QNaN bit. */ \
1950
#define HANDLE_NAN1(result, x) \
1951
DO_HANDLE_NAN(result, x)
1952
#define HANDLE_NAN2(result, x, y) \
1953
DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y)
1954
#define HANDLE_NAN3(result, x, y, z) \
1955
DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z)
1957
/* Saturating arithmetic helpers. */
1958
#define SATCVT(from, to, from_type, to_type, min, max, use_min, use_max) \
1959
static inline to_type cvt##from##to(from_type x, int *sat) \
1962
if (use_min && x < min) { \
1965
} else if (use_max && x > max) { \
1973
SATCVT(sh, sb, int16_t, int8_t, INT8_MIN, INT8_MAX, 1, 1)
1974
SATCVT(sw, sh, int32_t, int16_t, INT16_MIN, INT16_MAX, 1, 1)
1975
SATCVT(sd, sw, int64_t, int32_t, INT32_MIN, INT32_MAX, 1, 1)
1977
/* Work around gcc problems with the macro version */
1978
static inline uint8_t cvtuhub(uint16_t x, int *sat)
1982
if (x > UINT8_MAX) {
1990
//SATCVT(uh, ub, uint16_t, uint8_t, 0, UINT8_MAX, 0, 1)
1991
SATCVT(uw, uh, uint32_t, uint16_t, 0, UINT16_MAX, 0, 1)
1992
SATCVT(ud, uw, uint64_t, uint32_t, 0, UINT32_MAX, 0, 1)
1993
SATCVT(sh, ub, int16_t, uint8_t, 0, UINT8_MAX, 1, 1)
1994
SATCVT(sw, uh, int32_t, uint16_t, 0, UINT16_MAX, 1, 1)
1995
SATCVT(sd, uw, int64_t, uint32_t, 0, UINT32_MAX, 1, 1)
1998
#define LVE(name, access, swap, element) \
1999
void helper_##name (ppc_avr_t *r, target_ulong addr) \
2001
size_t n_elems = ARRAY_SIZE(r->element); \
2002
int adjust = HI_IDX*(n_elems-1); \
2003
int sh = sizeof(r->element[0]) >> 1; \
2004
int index = (addr & 0xf) >> sh; \
2006
r->element[LO_IDX ? index : (adjust - index)] = swap(access(addr)); \
2008
r->element[LO_IDX ? index : (adjust - index)] = access(addr); \
2012
LVE(lvebx, ldub, I, u8)
2013
LVE(lvehx, lduw, bswap16, u16)
2014
LVE(lvewx, ldl, bswap32, u32)
2018
void helper_lvsl (ppc_avr_t *r, target_ulong sh)
2020
int i, j = (sh & 0xf);
2022
VECTOR_FOR_INORDER_I (i, u8) {
2027
void helper_lvsr (ppc_avr_t *r, target_ulong sh)
2029
int i, j = 0x10 - (sh & 0xf);
2031
VECTOR_FOR_INORDER_I (i, u8) {
2036
#define STVE(name, access, swap, element) \
2037
void helper_##name (ppc_avr_t *r, target_ulong addr) \
2039
size_t n_elems = ARRAY_SIZE(r->element); \
2040
int adjust = HI_IDX*(n_elems-1); \
2041
int sh = sizeof(r->element[0]) >> 1; \
2042
int index = (addr & 0xf) >> sh; \
2044
access(addr, swap(r->element[LO_IDX ? index : (adjust - index)])); \
2046
access(addr, r->element[LO_IDX ? index : (adjust - index)]); \
2050
STVE(stvebx, stb, I, u8)
2051
STVE(stvehx, stw, bswap16, u16)
2052
STVE(stvewx, stl, bswap32, u32)
2056
void helper_mtvscr (ppc_avr_t *r)
2058
#if defined(HOST_WORDS_BIGENDIAN)
2059
env->vscr = r->u32[3];
2061
env->vscr = r->u32[0];
2063
set_flush_to_zero(vscr_nj, &env->vec_status);
2066
void helper_vaddcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2069
for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2070
r->u32[i] = ~a->u32[i] < b->u32[i];
2074
#define VARITH_DO(name, op, element) \
2075
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2078
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2079
r->element[i] = a->element[i] op b->element[i]; \
2082
#define VARITH(suffix, element) \
2083
VARITH_DO(add##suffix, +, element) \
2084
VARITH_DO(sub##suffix, -, element)
2091
#define VARITHFP(suffix, func) \
2092
void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2095
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
2096
HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \
2097
r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
2101
VARITHFP(addfp, float32_add)
2102
VARITHFP(subfp, float32_sub)
2105
#define VARITHSAT_CASE(type, op, cvt, element) \
2107
type result = (type)a->element[i] op (type)b->element[i]; \
2108
r->element[i] = cvt(result, &sat); \
2111
#define VARITHSAT_DO(name, op, optype, cvt, element) \
2112
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2116
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2117
switch (sizeof(r->element[0])) { \
2118
case 1: VARITHSAT_CASE(optype, op, cvt, element); break; \
2119
case 2: VARITHSAT_CASE(optype, op, cvt, element); break; \
2120
case 4: VARITHSAT_CASE(optype, op, cvt, element); break; \
2124
env->vscr |= (1 << VSCR_SAT); \
2127
#define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
2128
VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element) \
2129
VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
2130
#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt) \
2131
VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element) \
2132
VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
2133
VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
2134
VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
2135
VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
2136
VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
2137
VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
2138
VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
2139
#undef VARITHSAT_CASE
2141
#undef VARITHSAT_SIGNED
2142
#undef VARITHSAT_UNSIGNED
2144
#define VAVG_DO(name, element, etype) \
2145
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2148
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2149
etype x = (etype)a->element[i] + (etype)b->element[i] + 1; \
2150
r->element[i] = x >> 1; \
2154
#define VAVG(type, signed_element, signed_type, unsigned_element, unsigned_type) \
2155
VAVG_DO(avgs##type, signed_element, signed_type) \
2156
VAVG_DO(avgu##type, unsigned_element, unsigned_type)
2157
VAVG(b, s8, int16_t, u8, uint16_t)
2158
VAVG(h, s16, int32_t, u16, uint32_t)
2159
VAVG(w, s32, int64_t, u32, uint64_t)
2163
#define VCF(suffix, cvt, element) \
2164
void helper_vcf##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim) \
2167
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
2168
float32 t = cvt(b->element[i], &env->vec_status); \
2169
r->f[i] = float32_scalbn (t, -uim, &env->vec_status); \
2172
VCF(ux, uint32_to_float32, u32)
2173
VCF(sx, int32_to_float32, s32)
2176
#define VCMP_DO(suffix, compare, element, record) \
2177
void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2179
uint32_t ones = (uint32_t)-1; \
2180
uint32_t all = ones; \
2181
uint32_t none = 0; \
2183
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2184
uint32_t result = (a->element[i] compare b->element[i] ? ones : 0x0); \
2185
switch (sizeof (a->element[0])) { \
2186
case 4: r->u32[i] = result; break; \
2187
case 2: r->u16[i] = result; break; \
2188
case 1: r->u8[i] = result; break; \
2194
env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
2197
#define VCMP(suffix, compare, element) \
2198
VCMP_DO(suffix, compare, element, 0) \
2199
VCMP_DO(suffix##_dot, compare, element, 1)
2212
#define VCMPFP_DO(suffix, compare, order, record) \
2213
void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2215
uint32_t ones = (uint32_t)-1; \
2216
uint32_t all = ones; \
2217
uint32_t none = 0; \
2219
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
2221
int rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status); \
2222
if (rel == float_relation_unordered) { \
2224
} else if (rel compare order) { \
2229
r->u32[i] = result; \
2234
env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
2237
#define VCMPFP(suffix, compare, order) \
2238
VCMPFP_DO(suffix, compare, order, 0) \
2239
VCMPFP_DO(suffix##_dot, compare, order, 1)
2240
VCMPFP(eqfp, ==, float_relation_equal)
2241
VCMPFP(gefp, !=, float_relation_less)
2242
VCMPFP(gtfp, ==, float_relation_greater)
2246
static inline void vcmpbfp_internal(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
2251
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2252
int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
2253
if (le_rel == float_relation_unordered) {
2254
r->u32[i] = 0xc0000000;
2255
/* ALL_IN does not need to be updated here. */
2257
float32 bneg = float32_chs(b->f[i]);
2258
int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
2259
int le = le_rel != float_relation_greater;
2260
int ge = ge_rel != float_relation_less;
2261
r->u32[i] = ((!le) << 31) | ((!ge) << 30);
2262
all_in |= (!le | !ge);
2266
env->crf[6] = (all_in == 0) << 1;
2270
void helper_vcmpbfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2272
vcmpbfp_internal(r, a, b, 0);
2275
void helper_vcmpbfp_dot (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2277
vcmpbfp_internal(r, a, b, 1);
2280
#define VCT(suffix, satcvt, element) \
2281
void helper_vct##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim) \
2285
float_status s = env->vec_status; \
2286
set_float_rounding_mode(float_round_to_zero, &s); \
2287
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
2288
if (float32_is_nan(b->f[i]) || \
2289
float32_is_signaling_nan(b->f[i])) { \
2290
r->element[i] = 0; \
2292
float64 t = float32_to_float64(b->f[i], &s); \
2294
t = float64_scalbn(t, uim, &s); \
2295
j = float64_to_int64(t, &s); \
2296
r->element[i] = satcvt(j, &sat); \
2300
env->vscr |= (1 << VSCR_SAT); \
2303
VCT(uxs, cvtsduw, u32)
2304
VCT(sxs, cvtsdsw, s32)
2307
void helper_vmaddfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2310
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2311
HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2312
/* Need to do the computation in higher precision and round
2313
* once at the end. */
2314
float64 af, bf, cf, t;
2315
af = float32_to_float64(a->f[i], &env->vec_status);
2316
bf = float32_to_float64(b->f[i], &env->vec_status);
2317
cf = float32_to_float64(c->f[i], &env->vec_status);
2318
t = float64_mul(af, cf, &env->vec_status);
2319
t = float64_add(t, bf, &env->vec_status);
2320
r->f[i] = float64_to_float32(t, &env->vec_status);
2325
void helper_vmhaddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2330
for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2331
int32_t prod = a->s16[i] * b->s16[i];
2332
int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2333
r->s16[i] = cvtswsh (t, &sat);
2337
env->vscr |= (1 << VSCR_SAT);
2341
void helper_vmhraddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2346
for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2347
int32_t prod = a->s16[i] * b->s16[i] + 0x00004000;
2348
int32_t t = (int32_t)c->s16[i] + (prod >> 15);
2349
r->s16[i] = cvtswsh (t, &sat);
2353
env->vscr |= (1 << VSCR_SAT);
2357
#define VMINMAX_DO(name, compare, element) \
2358
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2361
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2362
if (a->element[i] compare b->element[i]) { \
2363
r->element[i] = b->element[i]; \
2365
r->element[i] = a->element[i]; \
2369
#define VMINMAX(suffix, element) \
2370
VMINMAX_DO(min##suffix, >, element) \
2371
VMINMAX_DO(max##suffix, <, element)
2381
#define VMINMAXFP(suffix, rT, rF) \
2382
void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2385
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
2386
HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \
2387
if (float32_lt_quiet(a->f[i], b->f[i], &env->vec_status)) { \
2388
r->f[i] = rT->f[i]; \
2390
r->f[i] = rF->f[i]; \
2395
VMINMAXFP(minfp, a, b)
2396
VMINMAXFP(maxfp, b, a)
2399
void helper_vmladduhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2402
for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2403
int32_t prod = a->s16[i] * b->s16[i];
2404
r->s16[i] = (int16_t) (prod + c->s16[i]);
2408
#define VMRG_DO(name, element, highp) \
2409
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2413
size_t n_elems = ARRAY_SIZE(r->element); \
2414
for (i = 0; i < n_elems/2; i++) { \
2416
result.element[i*2+HI_IDX] = a->element[i]; \
2417
result.element[i*2+LO_IDX] = b->element[i]; \
2419
result.element[n_elems - i*2 - (1+HI_IDX)] = b->element[n_elems - i - 1]; \
2420
result.element[n_elems - i*2 - (1+LO_IDX)] = a->element[n_elems - i - 1]; \
2425
#if defined(HOST_WORDS_BIGENDIAN)
2432
#define VMRG(suffix, element) \
2433
VMRG_DO(mrgl##suffix, element, MRGHI) \
2434
VMRG_DO(mrgh##suffix, element, MRGLO)
2443
void helper_vmsummbm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2448
for (i = 0; i < ARRAY_SIZE(r->s8); i++) {
2449
prod[i] = (int32_t)a->s8[i] * b->u8[i];
2452
VECTOR_FOR_INORDER_I(i, s32) {
2453
r->s32[i] = c->s32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2457
void helper_vmsumshm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2462
for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2463
prod[i] = a->s16[i] * b->s16[i];
2466
VECTOR_FOR_INORDER_I(i, s32) {
2467
r->s32[i] = c->s32[i] + prod[2*i] + prod[2*i+1];
2471
void helper_vmsumshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2477
for (i = 0; i < ARRAY_SIZE(r->s16); i++) {
2478
prod[i] = (int32_t)a->s16[i] * b->s16[i];
2481
VECTOR_FOR_INORDER_I (i, s32) {
2482
int64_t t = (int64_t)c->s32[i] + prod[2*i] + prod[2*i+1];
2483
r->u32[i] = cvtsdsw(t, &sat);
2487
env->vscr |= (1 << VSCR_SAT);
2491
void helper_vmsumubm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2496
for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2497
prod[i] = a->u8[i] * b->u8[i];
2500
VECTOR_FOR_INORDER_I(i, u32) {
2501
r->u32[i] = c->u32[i] + prod[4*i] + prod[4*i+1] + prod[4*i+2] + prod[4*i+3];
2505
void helper_vmsumuhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2510
for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2511
prod[i] = a->u16[i] * b->u16[i];
2514
VECTOR_FOR_INORDER_I(i, u32) {
2515
r->u32[i] = c->u32[i] + prod[2*i] + prod[2*i+1];
2519
void helper_vmsumuhs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2525
for (i = 0; i < ARRAY_SIZE(r->u16); i++) {
2526
prod[i] = a->u16[i] * b->u16[i];
2529
VECTOR_FOR_INORDER_I (i, s32) {
2530
uint64_t t = (uint64_t)c->u32[i] + prod[2*i] + prod[2*i+1];
2531
r->u32[i] = cvtuduw(t, &sat);
2535
env->vscr |= (1 << VSCR_SAT);
2539
#define VMUL_DO(name, mul_element, prod_element, evenp) \
2540
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2543
VECTOR_FOR_INORDER_I(i, prod_element) { \
2545
r->prod_element[i] = a->mul_element[i*2+HI_IDX] * b->mul_element[i*2+HI_IDX]; \
2547
r->prod_element[i] = a->mul_element[i*2+LO_IDX] * b->mul_element[i*2+LO_IDX]; \
2551
#define VMUL(suffix, mul_element, prod_element) \
2552
VMUL_DO(mule##suffix, mul_element, prod_element, 1) \
2553
VMUL_DO(mulo##suffix, mul_element, prod_element, 0)
2561
void helper_vnmsubfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2564
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2565
HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
2566
/* Need to do the computation is higher precision and round
2567
* once at the end. */
2568
float64 af, bf, cf, t;
2569
af = float32_to_float64(a->f[i], &env->vec_status);
2570
bf = float32_to_float64(b->f[i], &env->vec_status);
2571
cf = float32_to_float64(c->f[i], &env->vec_status);
2572
t = float64_mul(af, cf, &env->vec_status);
2573
t = float64_sub(t, bf, &env->vec_status);
2575
r->f[i] = float64_to_float32(t, &env->vec_status);
2580
void helper_vperm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2584
VECTOR_FOR_INORDER_I (i, u8) {
2585
int s = c->u8[i] & 0x1f;
2586
#if defined(HOST_WORDS_BIGENDIAN)
2587
int index = s & 0xf;
2589
int index = 15 - (s & 0xf);
2592
result.u8[i] = b->u8[index];
2594
result.u8[i] = a->u8[index];
2600
#if defined(HOST_WORDS_BIGENDIAN)
2605
void helper_vpkpx (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2609
#if defined(HOST_WORDS_BIGENDIAN)
2610
const ppc_avr_t *x[2] = { a, b };
2612
const ppc_avr_t *x[2] = { b, a };
2615
VECTOR_FOR_INORDER_I (i, u64) {
2616
VECTOR_FOR_INORDER_I (j, u32){
2617
uint32_t e = x[i]->u32[j];
2618
result.u16[4*i+j] = (((e >> 9) & 0xfc00) |
2619
((e >> 6) & 0x3e0) |
2626
#define VPK(suffix, from, to, cvt, dosat) \
2627
void helper_vpk##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2632
ppc_avr_t *a0 = PKBIG ? a : b; \
2633
ppc_avr_t *a1 = PKBIG ? b : a; \
2634
VECTOR_FOR_INORDER_I (i, from) { \
2635
result.to[i] = cvt(a0->from[i], &sat); \
2636
result.to[i+ARRAY_SIZE(r->from)] = cvt(a1->from[i], &sat); \
2639
if (dosat && sat) { \
2640
env->vscr |= (1 << VSCR_SAT); \
2644
VPK(shss, s16, s8, cvtshsb, 1)
2645
VPK(shus, s16, u8, cvtshub, 1)
2646
VPK(swss, s32, s16, cvtswsh, 1)
2647
VPK(swus, s32, u16, cvtswuh, 1)
2648
VPK(uhus, u16, u8, cvtuhub, 1)
2649
VPK(uwus, u32, u16, cvtuwuh, 1)
2650
VPK(uhum, u16, u8, I, 0)
2651
VPK(uwum, u32, u16, I, 0)
2656
void helper_vrefp (ppc_avr_t *r, ppc_avr_t *b)
2659
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2660
HANDLE_NAN1(r->f[i], b->f[i]) {
2661
r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
2666
#define VRFI(suffix, rounding) \
2667
void helper_vrfi##suffix (ppc_avr_t *r, ppc_avr_t *b) \
2670
float_status s = env->vec_status; \
2671
set_float_rounding_mode(rounding, &s); \
2672
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
2673
HANDLE_NAN1(r->f[i], b->f[i]) { \
2674
r->f[i] = float32_round_to_int (b->f[i], &s); \
2678
VRFI(n, float_round_nearest_even)
2679
VRFI(m, float_round_down)
2680
VRFI(p, float_round_up)
2681
VRFI(z, float_round_to_zero)
2684
#define VROTATE(suffix, element) \
2685
void helper_vrl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2688
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2689
unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2690
unsigned int shift = b->element[i] & mask; \
2691
r->element[i] = (a->element[i] << shift) | (a->element[i] >> (sizeof(a->element[0]) * 8 - shift)); \
2699
void helper_vrsqrtefp (ppc_avr_t *r, ppc_avr_t *b)
2702
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2703
HANDLE_NAN1(r->f[i], b->f[i]) {
2704
float32 t = float32_sqrt(b->f[i], &env->vec_status);
2705
r->f[i] = float32_div(float32_one, t, &env->vec_status);
2710
void helper_vsel (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
2712
r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
2713
r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
2716
void helper_vlogefp (ppc_avr_t *r, ppc_avr_t *b)
2719
for (i = 0; i < ARRAY_SIZE(r->f); i++) {
2720
HANDLE_NAN1(r->f[i], b->f[i]) {
2721
r->f[i] = float32_log2(b->f[i], &env->vec_status);
2726
#if defined(HOST_WORDS_BIGENDIAN)
2733
/* The specification says that the results are undefined if all of the
2734
* shift counts are not identical. We check to make sure that they are
2735
* to conform to what real hardware appears to do. */
2736
#define VSHIFT(suffix, leftp) \
2737
void helper_vs##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2739
int shift = b->u8[LO_IDX*15] & 0x7; \
2742
for (i = 0; i < ARRAY_SIZE(r->u8); i++) { \
2743
doit = doit && ((b->u8[i] & 0x7) == shift); \
2748
} else if (leftp) { \
2749
uint64_t carry = a->u64[LO_IDX] >> (64 - shift); \
2750
r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \
2751
r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \
2753
uint64_t carry = a->u64[HI_IDX] << (64 - shift); \
2754
r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \
2755
r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \
2765
#define VSL(suffix, element) \
2766
void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2769
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2770
unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2771
unsigned int shift = b->element[i] & mask; \
2772
r->element[i] = a->element[i] << shift; \
2780
void helper_vsldoi (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
2782
int sh = shift & 0xf;
2786
#if defined(HOST_WORDS_BIGENDIAN)
2787
for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2790
result.u8[i] = b->u8[index-0x10];
2792
result.u8[i] = a->u8[index];
2796
for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
2797
int index = (16 - sh) + i;
2799
result.u8[i] = a->u8[index-0x10];
2801
result.u8[i] = b->u8[index];
2808
void helper_vslo (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2810
int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2812
#if defined (HOST_WORDS_BIGENDIAN)
2813
memmove (&r->u8[0], &a->u8[sh], 16-sh);
2814
memset (&r->u8[16-sh], 0, sh);
2816
memmove (&r->u8[sh], &a->u8[0], 16-sh);
2817
memset (&r->u8[0], 0, sh);
2821
/* Experimental testing shows that hardware masks the immediate. */
2822
#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
2823
#if defined(HOST_WORDS_BIGENDIAN)
2824
#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
2826
#define SPLAT_ELEMENT(element) (ARRAY_SIZE(r->element)-1 - _SPLAT_MASKED(element))
2828
#define VSPLT(suffix, element) \
2829
void helper_vsplt##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
2831
uint32_t s = b->element[SPLAT_ELEMENT(element)]; \
2833
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2834
r->element[i] = s; \
2841
#undef SPLAT_ELEMENT
2842
#undef _SPLAT_MASKED
2844
#define VSPLTI(suffix, element, splat_type) \
2845
void helper_vspltis##suffix (ppc_avr_t *r, uint32_t splat) \
2847
splat_type x = (int8_t)(splat << 3) >> 3; \
2849
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2850
r->element[i] = x; \
2853
VSPLTI(b, s8, int8_t)
2854
VSPLTI(h, s16, int16_t)
2855
VSPLTI(w, s32, int32_t)
2858
#define VSR(suffix, element) \
2859
void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
2862
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
2863
unsigned int mask = ((1 << (3 + (sizeof (a->element[0]) >> 1))) - 1); \
2864
unsigned int shift = b->element[i] & mask; \
2865
r->element[i] = a->element[i] >> shift; \
2876
void helper_vsro (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2878
int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf;
2880
#if defined (HOST_WORDS_BIGENDIAN)
2881
memmove (&r->u8[sh], &a->u8[0], 16-sh);
2882
memset (&r->u8[0], 0, sh);
2884
memmove (&r->u8[0], &a->u8[sh], 16-sh);
2885
memset (&r->u8[16-sh], 0, sh);
2889
void helper_vsubcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2892
for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2893
r->u32[i] = a->u32[i] >= b->u32[i];
2897
void helper_vsumsws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2904
#if defined(HOST_WORDS_BIGENDIAN)
2905
upper = ARRAY_SIZE(r->s32)-1;
2909
t = (int64_t)b->s32[upper];
2910
for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2914
result.s32[upper] = cvtsdsw(t, &sat);
2918
env->vscr |= (1 << VSCR_SAT);
2922
void helper_vsum2sws (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2928
#if defined(HOST_WORDS_BIGENDIAN)
2933
for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
2934
int64_t t = (int64_t)b->s32[upper+i*2];
2936
for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
2939
result.s32[upper+i*2] = cvtsdsw(t, &sat);
2944
env->vscr |= (1 << VSCR_SAT);
2948
void helper_vsum4sbs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2953
for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2954
int64_t t = (int64_t)b->s32[i];
2955
for (j = 0; j < ARRAY_SIZE(r->s32); j++) {
2958
r->s32[i] = cvtsdsw(t, &sat);
2962
env->vscr |= (1 << VSCR_SAT);
2966
void helper_vsum4shs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2971
for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
2972
int64_t t = (int64_t)b->s32[i];
2973
t += a->s16[2*i] + a->s16[2*i+1];
2974
r->s32[i] = cvtsdsw(t, &sat);
2978
env->vscr |= (1 << VSCR_SAT);
2982
void helper_vsum4ubs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
2987
for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
2988
uint64_t t = (uint64_t)b->u32[i];
2989
for (j = 0; j < ARRAY_SIZE(r->u32); j++) {
2992
r->u32[i] = cvtuduw(t, &sat);
2996
env->vscr |= (1 << VSCR_SAT);
3000
#if defined(HOST_WORDS_BIGENDIAN)
3007
#define VUPKPX(suffix, hi) \
3008
void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b) \
3012
for (i = 0; i < ARRAY_SIZE(r->u32); i++) { \
3013
uint16_t e = b->u16[hi ? i : i+4]; \
3014
uint8_t a = (e >> 15) ? 0xff : 0; \
3015
uint8_t r = (e >> 10) & 0x1f; \
3016
uint8_t g = (e >> 5) & 0x1f; \
3017
uint8_t b = e & 0x1f; \
3018
result.u32[i] = (a << 24) | (r << 16) | (g << 8) | b; \
3026
#define VUPK(suffix, unpacked, packee, hi) \
3027
void helper_vupk##suffix (ppc_avr_t *r, ppc_avr_t *b) \
3032
for (i = 0; i < ARRAY_SIZE(r->unpacked); i++) { \
3033
result.unpacked[i] = b->packee[i]; \
3036
for (i = ARRAY_SIZE(r->unpacked); i < ARRAY_SIZE(r->packee); i++) { \
3037
result.unpacked[i-ARRAY_SIZE(r->unpacked)] = b->packee[i]; \
3042
VUPK(hsb, s16, s8, UPKHI)
3043
VUPK(hsh, s32, s16, UPKHI)
3044
VUPK(lsb, s16, s8, UPKLO)
3045
VUPK(lsh, s32, s16, UPKLO)
3050
#undef DO_HANDLE_NAN
3054
#undef VECTOR_FOR_INORDER_I
3058
/*****************************************************************************/
1834
3059
/* SPE extension helpers */
1835
3060
/* Use a table to make this quicker */
1836
3061
static uint8_t hbrev[16] = {
1897
3094
return clz32(val);
1900
static always_inline int _do_ecntlzw (uint32_t val)
3097
uint32_t helper_cntlzw32 (uint32_t val)
1902
3099
return clz32(val);
1905
static always_inline uint32_t _do_eneg (uint32_t val)
1907
if (val != 0x80000000)
1913
static always_inline uint32_t _do_erlw (uint32_t op1, uint32_t op2)
1915
return rotl32(op1, op2);
1918
static always_inline uint32_t _do_erndw (uint32_t val)
1920
return (val + 0x000080000000) & 0xFFFF0000;
1923
static always_inline uint32_t _do_eslw (uint32_t op1, uint32_t op2)
1925
/* No error here: 6 bits are used */
1926
return op1 << (op2 & 0x3F);
1929
static always_inline int32_t _do_esrws (int32_t op1, uint32_t op2)
1931
/* No error here: 6 bits are used */
1932
return op1 >> (op2 & 0x3F);
1935
static always_inline uint32_t _do_esrwu (uint32_t op1, uint32_t op2)
1937
/* No error here: 6 bits are used */
1938
return op1 >> (op2 & 0x3F);
1941
static always_inline uint32_t _do_esubfw (uint32_t op1, uint32_t op2)
1969
/* evsel is a little bit more complicated... */
1970
static always_inline uint32_t _do_esel (uint32_t op1, uint32_t op2, int n)
1978
void do_evsel (void)
1980
T0_64 = ((uint64_t)_do_esel(T0_64 >> 32, T1_64 >> 32, T0 >> 3) << 32) |
1981
(uint64_t)_do_esel(T0_64, T1_64, (T0 >> 2) & 1);
1984
/* Fixed-point vector comparisons */
1985
#define DO_SPE_CMP(name) \
1986
void do_ev##name (void) \
1988
T0 = _do_evcmp_merge((uint64_t)_do_e##name(T0_64 >> 32, \
1989
T1_64 >> 32) << 32, \
1990
_do_e##name(T0_64, T1_64)); \
1993
static always_inline uint32_t _do_evcmp_merge (int t0, int t1)
1995
return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
1997
static always_inline int _do_ecmpeq (uint32_t op1, uint32_t op2)
1999
return op1 == op2 ? 1 : 0;
2002
static always_inline int _do_ecmpgts (int32_t op1, int32_t op2)
2004
return op1 > op2 ? 1 : 0;
2007
static always_inline int _do_ecmpgtu (uint32_t op1, uint32_t op2)
2009
return op1 > op2 ? 1 : 0;
2012
static always_inline int _do_ecmplts (int32_t op1, int32_t op2)
2014
return op1 < op2 ? 1 : 0;
2017
static always_inline int _do_ecmpltu (uint32_t op1, uint32_t op2)
2019
return op1 < op2 ? 1 : 0;
2033
/* Single precision floating-point conversions from/to integer */
2034
static always_inline uint32_t _do_efscfsi (int32_t val)
2038
u.f = int32_to_float32(val, &env->spe_status);
2043
static always_inline uint32_t _do_efscfui (uint32_t val)
2047
u.f = uint32_to_float32(val, &env->spe_status);
2052
static always_inline int32_t _do_efsctsi (uint32_t val)
2057
/* NaN are not treated the same way IEEE 754 does */
2058
if (unlikely(isnan(u.f)))
2061
return float32_to_int32(u.f, &env->spe_status);
2064
static always_inline uint32_t _do_efsctui (uint32_t val)
2069
/* NaN are not treated the same way IEEE 754 does */
2070
if (unlikely(isnan(u.f)))
2073
return float32_to_uint32(u.f, &env->spe_status);
2076
static always_inline int32_t _do_efsctsiz (uint32_t val)
2081
/* NaN are not treated the same way IEEE 754 does */
2082
if (unlikely(isnan(u.f)))
2085
return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2088
static always_inline uint32_t _do_efsctuiz (uint32_t val)
2093
/* NaN are not treated the same way IEEE 754 does */
2094
if (unlikely(isnan(u.f)))
2097
return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2100
void do_efscfsi (void)
2102
T0_64 = _do_efscfsi(T0_64);
2105
void do_efscfui (void)
2107
T0_64 = _do_efscfui(T0_64);
2110
void do_efsctsi (void)
2112
T0_64 = _do_efsctsi(T0_64);
2115
void do_efsctui (void)
2117
T0_64 = _do_efsctui(T0_64);
2120
void do_efsctsiz (void)
2122
T0_64 = _do_efsctsiz(T0_64);
2125
void do_efsctuiz (void)
2127
T0_64 = _do_efsctuiz(T0_64);
2130
/* Single precision floating-point conversion to/from fractional */
2131
static always_inline uint32_t _do_efscfsf (uint32_t val)
2136
u.f = int32_to_float32(val, &env->spe_status);
2137
tmp = int64_to_float32(1ULL << 32, &env->spe_status);
2138
u.f = float32_div(u.f, tmp, &env->spe_status);
2143
static always_inline uint32_t _do_efscfuf (uint32_t val)
2148
u.f = uint32_to_float32(val, &env->spe_status);
2149
tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2150
u.f = float32_div(u.f, tmp, &env->spe_status);
2155
static always_inline int32_t _do_efsctsf (uint32_t val)
2161
/* NaN are not treated the same way IEEE 754 does */
2162
if (unlikely(isnan(u.f)))
2164
tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2165
u.f = float32_mul(u.f, tmp, &env->spe_status);
2167
return float32_to_int32(u.f, &env->spe_status);
2170
static always_inline uint32_t _do_efsctuf (uint32_t val)
2176
/* NaN are not treated the same way IEEE 754 does */
2177
if (unlikely(isnan(u.f)))
2179
tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2180
u.f = float32_mul(u.f, tmp, &env->spe_status);
2182
return float32_to_uint32(u.f, &env->spe_status);
2185
static always_inline int32_t _do_efsctsfz (uint32_t val)
2191
/* NaN are not treated the same way IEEE 754 does */
2192
if (unlikely(isnan(u.f)))
2194
tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2195
u.f = float32_mul(u.f, tmp, &env->spe_status);
2197
return float32_to_int32_round_to_zero(u.f, &env->spe_status);
2200
static always_inline uint32_t _do_efsctufz (uint32_t val)
2206
/* NaN are not treated the same way IEEE 754 does */
2207
if (unlikely(isnan(u.f)))
2209
tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
2210
u.f = float32_mul(u.f, tmp, &env->spe_status);
2212
return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
2215
void do_efscfsf (void)
2217
T0_64 = _do_efscfsf(T0_64);
2220
void do_efscfuf (void)
2222
T0_64 = _do_efscfuf(T0_64);
2225
void do_efsctsf (void)
2227
T0_64 = _do_efsctsf(T0_64);
2230
void do_efsctuf (void)
2232
T0_64 = _do_efsctuf(T0_64);
2235
void do_efsctsfz (void)
2237
T0_64 = _do_efsctsfz(T0_64);
2240
void do_efsctufz (void)
2242
T0_64 = _do_efsctufz(T0_64);
2245
/* Double precision floating point helpers */
2246
static always_inline int _do_efdcmplt (uint64_t op1, uint64_t op2)
2248
/* XXX: TODO: test special values (NaN, infinites, ...) */
2249
return _do_efdtstlt(op1, op2);
2252
static always_inline int _do_efdcmpgt (uint64_t op1, uint64_t op2)
2254
/* XXX: TODO: test special values (NaN, infinites, ...) */
2255
return _do_efdtstgt(op1, op2);
2258
static always_inline int _do_efdcmpeq (uint64_t op1, uint64_t op2)
2260
/* XXX: TODO: test special values (NaN, infinites, ...) */
2261
return _do_efdtsteq(op1, op2);
2264
void do_efdcmplt (void)
2266
T0 = _do_efdcmplt(T0_64, T1_64);
2269
void do_efdcmpgt (void)
2271
T0 = _do_efdcmpgt(T0_64, T1_64);
2274
void do_efdcmpeq (void)
2276
T0 = _do_efdcmpeq(T0_64, T1_64);
2279
/* Double precision floating-point conversion to/from integer */
2280
static always_inline uint64_t _do_efdcfsi (int64_t val)
2284
u.d = int64_to_float64(val, &env->spe_status);
2289
static always_inline uint64_t _do_efdcfui (uint64_t val)
2293
u.d = uint64_to_float64(val, &env->spe_status);
2298
static always_inline int64_t _do_efdctsi (uint64_t val)
2303
/* NaN are not treated the same way IEEE 754 does */
2304
if (unlikely(isnan(u.d)))
2307
return float64_to_int64(u.d, &env->spe_status);
2310
static always_inline uint64_t _do_efdctui (uint64_t val)
2315
/* NaN are not treated the same way IEEE 754 does */
2316
if (unlikely(isnan(u.d)))
2319
return float64_to_uint64(u.d, &env->spe_status);
2322
static always_inline int64_t _do_efdctsiz (uint64_t val)
2327
/* NaN are not treated the same way IEEE 754 does */
2328
if (unlikely(isnan(u.d)))
2331
return float64_to_int64_round_to_zero(u.d, &env->spe_status);
2334
static always_inline uint64_t _do_efdctuiz (uint64_t val)
2339
/* NaN are not treated the same way IEEE 754 does */
2340
if (unlikely(isnan(u.d)))
2343
return float64_to_uint64_round_to_zero(u.d, &env->spe_status);
2346
void do_efdcfsi (void)
2348
T0_64 = _do_efdcfsi(T0_64);
2351
void do_efdcfui (void)
2353
T0_64 = _do_efdcfui(T0_64);
2356
void do_efdctsi (void)
2358
T0_64 = _do_efdctsi(T0_64);
2361
void do_efdctui (void)
2363
T0_64 = _do_efdctui(T0_64);
2366
void do_efdctsiz (void)
2368
T0_64 = _do_efdctsiz(T0_64);
2371
void do_efdctuiz (void)
2373
T0_64 = _do_efdctuiz(T0_64);
2376
/* Double precision floating-point conversion to/from fractional */
2377
static always_inline uint64_t _do_efdcfsf (int64_t val)
2382
u.d = int32_to_float64(val, &env->spe_status);
2383
tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2384
u.d = float64_div(u.d, tmp, &env->spe_status);
2389
static always_inline uint64_t _do_efdcfuf (uint64_t val)
2394
u.d = uint32_to_float64(val, &env->spe_status);
2395
tmp = int64_to_float64(1ULL << 32, &env->spe_status);
2396
u.d = float64_div(u.d, tmp, &env->spe_status);
2401
static always_inline int64_t _do_efdctsf (uint64_t val)
2407
/* NaN are not treated the same way IEEE 754 does */
2408
if (unlikely(isnan(u.d)))
2410
tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2411
u.d = float64_mul(u.d, tmp, &env->spe_status);
2413
return float64_to_int32(u.d, &env->spe_status);
2416
static always_inline uint64_t _do_efdctuf (uint64_t val)
2422
/* NaN are not treated the same way IEEE 754 does */
2423
if (unlikely(isnan(u.d)))
2425
tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2426
u.d = float64_mul(u.d, tmp, &env->spe_status);
2428
return float64_to_uint32(u.d, &env->spe_status);
2431
static always_inline int64_t _do_efdctsfz (uint64_t val)
2437
/* NaN are not treated the same way IEEE 754 does */
2438
if (unlikely(isnan(u.d)))
2440
tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2441
u.d = float64_mul(u.d, tmp, &env->spe_status);
2443
return float64_to_int32_round_to_zero(u.d, &env->spe_status);
2446
static always_inline uint64_t _do_efdctufz (uint64_t val)
2452
/* NaN are not treated the same way IEEE 754 does */
2453
if (unlikely(isnan(u.d)))
2455
tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
2456
u.d = float64_mul(u.d, tmp, &env->spe_status);
2458
return float64_to_uint32_round_to_zero(u.d, &env->spe_status);
2461
void do_efdcfsf (void)
2463
T0_64 = _do_efdcfsf(T0_64);
2466
void do_efdcfuf (void)
2468
T0_64 = _do_efdcfuf(T0_64);
2471
void do_efdctsf (void)
2473
T0_64 = _do_efdctsf(T0_64);
2476
void do_efdctuf (void)
2478
T0_64 = _do_efdctuf(T0_64);
2481
void do_efdctsfz (void)
2483
T0_64 = _do_efdctsfz(T0_64);
2486
void do_efdctufz (void)
2488
T0_64 = _do_efdctufz(T0_64);
2491
/* Floating point conversion between single and double precision */
2492
static always_inline uint32_t _do_efscfd (uint64_t val)
2498
u2.f = float64_to_float32(u1.d, &env->spe_status);
2503
static always_inline uint64_t _do_efdcfs (uint32_t val)
2509
u2.d = float32_to_float64(u1.f, &env->spe_status);
2514
void do_efscfd (void)
2516
T0_64 = _do_efscfd(T0_64);
2519
void do_efdcfs (void)
2521
T0_64 = _do_efdcfs(T0_64);
2524
/* Single precision fixed-point vector arithmetic */
2540
/* Single-precision floating-point comparisons */
2541
static always_inline int _do_efscmplt (uint32_t op1, uint32_t op2)
2543
/* XXX: TODO: test special values (NaN, infinites, ...) */
2544
return _do_efststlt(op1, op2);
2547
static always_inline int _do_efscmpgt (uint32_t op1, uint32_t op2)
2549
/* XXX: TODO: test special values (NaN, infinites, ...) */
2550
return _do_efststgt(op1, op2);
2553
static always_inline int _do_efscmpeq (uint32_t op1, uint32_t op2)
2555
/* XXX: TODO: test special values (NaN, infinites, ...) */
2556
return _do_efststeq(op1, op2);
2559
void do_efscmplt (void)
2561
T0 = _do_efscmplt(T0_64, T1_64);
2564
void do_efscmpgt (void)
2566
T0 = _do_efscmpgt(T0_64, T1_64);
2569
void do_efscmpeq (void)
2571
T0 = _do_efscmpeq(T0_64, T1_64);
2574
/* Single-precision floating-point vector comparisons */
2576
DO_SPE_CMP(fscmplt);
2578
DO_SPE_CMP(fscmpgt);
2580
DO_SPE_CMP(fscmpeq);
2582
DO_SPE_CMP(fststlt);
2584
DO_SPE_CMP(fststgt);
2586
DO_SPE_CMP(fststeq);
2588
/* Single-precision floating-point vector conversions */
3102
/* Single-precision floating-point conversions */
3103
static inline uint32_t efscfsi(uint32_t val)
3107
u.f = int32_to_float32(val, &env->vec_status);
3112
static inline uint32_t efscfui(uint32_t val)
3116
u.f = uint32_to_float32(val, &env->vec_status);
3121
static inline int32_t efsctsi(uint32_t val)
3126
/* NaN are not treated the same way IEEE 754 does */
3127
if (unlikely(float32_is_nan(u.f)))
3130
return float32_to_int32(u.f, &env->vec_status);
3133
static inline uint32_t efsctui(uint32_t val)
3138
/* NaN are not treated the same way IEEE 754 does */
3139
if (unlikely(float32_is_nan(u.f)))
3142
return float32_to_uint32(u.f, &env->vec_status);
3145
static inline uint32_t efsctsiz(uint32_t val)
3150
/* NaN are not treated the same way IEEE 754 does */
3151
if (unlikely(float32_is_nan(u.f)))
3154
return float32_to_int32_round_to_zero(u.f, &env->vec_status);
3157
static inline uint32_t efsctuiz(uint32_t val)
3162
/* NaN are not treated the same way IEEE 754 does */
3163
if (unlikely(float32_is_nan(u.f)))
3166
return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
3169
static inline uint32_t efscfsf(uint32_t val)
3174
u.f = int32_to_float32(val, &env->vec_status);
3175
tmp = int64_to_float32(1ULL << 32, &env->vec_status);
3176
u.f = float32_div(u.f, tmp, &env->vec_status);
3181
static inline uint32_t efscfuf(uint32_t val)
3186
u.f = uint32_to_float32(val, &env->vec_status);
3187
tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3188
u.f = float32_div(u.f, tmp, &env->vec_status);
3193
static inline uint32_t efsctsf(uint32_t val)
3199
/* NaN are not treated the same way IEEE 754 does */
3200
if (unlikely(float32_is_nan(u.f)))
3202
tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3203
u.f = float32_mul(u.f, tmp, &env->vec_status);
3205
return float32_to_int32(u.f, &env->vec_status);
3208
static inline uint32_t efsctuf(uint32_t val)
3214
/* NaN are not treated the same way IEEE 754 does */
3215
if (unlikely(float32_is_nan(u.f)))
3217
tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
3218
u.f = float32_mul(u.f, tmp, &env->vec_status);
3220
return float32_to_uint32(u.f, &env->vec_status);
3223
#define HELPER_SPE_SINGLE_CONV(name) \
3224
uint32_t helper_e##name (uint32_t val) \
3226
return e##name(val); \
3229
HELPER_SPE_SINGLE_CONV(fscfsi);
3231
HELPER_SPE_SINGLE_CONV(fscfui);
3233
HELPER_SPE_SINGLE_CONV(fscfuf);
3235
HELPER_SPE_SINGLE_CONV(fscfsf);
3237
HELPER_SPE_SINGLE_CONV(fsctsi);
3239
HELPER_SPE_SINGLE_CONV(fsctui);
3241
HELPER_SPE_SINGLE_CONV(fsctsiz);
3243
HELPER_SPE_SINGLE_CONV(fsctuiz);
3245
HELPER_SPE_SINGLE_CONV(fsctsf);
3247
HELPER_SPE_SINGLE_CONV(fsctuf);
3249
#define HELPER_SPE_VECTOR_CONV(name) \
3250
uint64_t helper_ev##name (uint64_t val) \
3252
return ((uint64_t)e##name(val >> 32) << 32) | \
3253
(uint64_t)e##name(val); \
3256
HELPER_SPE_VECTOR_CONV(fscfsi);
3258
HELPER_SPE_VECTOR_CONV(fscfui);
3260
HELPER_SPE_VECTOR_CONV(fscfuf);
3262
HELPER_SPE_VECTOR_CONV(fscfsf);
3264
HELPER_SPE_VECTOR_CONV(fsctsi);
3266
HELPER_SPE_VECTOR_CONV(fsctui);
2601
3267
/* evfsctsiz */
2602
DO_SPE_OP1(fsctsiz);
3268
HELPER_SPE_VECTOR_CONV(fsctsiz);
2603
3269
/* evfsctuiz */
2604
DO_SPE_OP1(fsctuiz);
3270
HELPER_SPE_VECTOR_CONV(fsctuiz);
3272
HELPER_SPE_VECTOR_CONV(fsctsf);
3274
HELPER_SPE_VECTOR_CONV(fsctuf);
3276
/* Single-precision floating-point arithmetic */
3277
static inline uint32_t efsadd(uint32_t op1, uint32_t op2)
3282
u1.f = float32_add(u1.f, u2.f, &env->vec_status);
3286
static inline uint32_t efssub(uint32_t op1, uint32_t op2)
3291
u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
3295
static inline uint32_t efsmul(uint32_t op1, uint32_t op2)
3300
u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
3304
static inline uint32_t efsdiv(uint32_t op1, uint32_t op2)
3309
u1.f = float32_div(u1.f, u2.f, &env->vec_status);
3313
#define HELPER_SPE_SINGLE_ARITH(name) \
3314
uint32_t helper_e##name (uint32_t op1, uint32_t op2) \
3316
return e##name(op1, op2); \
3319
HELPER_SPE_SINGLE_ARITH(fsadd);
3321
HELPER_SPE_SINGLE_ARITH(fssub);
3323
HELPER_SPE_SINGLE_ARITH(fsmul);
3325
HELPER_SPE_SINGLE_ARITH(fsdiv);
3327
#define HELPER_SPE_VECTOR_ARITH(name) \
3328
uint64_t helper_ev##name (uint64_t op1, uint64_t op2) \
3330
return ((uint64_t)e##name(op1 >> 32, op2 >> 32) << 32) | \
3331
(uint64_t)e##name(op1, op2); \
3334
HELPER_SPE_VECTOR_ARITH(fsadd);
3336
HELPER_SPE_VECTOR_ARITH(fssub);
3338
HELPER_SPE_VECTOR_ARITH(fsmul);
3340
HELPER_SPE_VECTOR_ARITH(fsdiv);
3342
/* Single-precision floating-point comparisons */
3343
static inline uint32_t efststlt(uint32_t op1, uint32_t op2)
3348
return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3351
static inline uint32_t efststgt(uint32_t op1, uint32_t op2)
3356
return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
3359
static inline uint32_t efststeq(uint32_t op1, uint32_t op2)
3364
return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
3367
static inline uint32_t efscmplt(uint32_t op1, uint32_t op2)
3369
/* XXX: TODO: test special values (NaN, infinites, ...) */
3370
return efststlt(op1, op2);
3373
static inline uint32_t efscmpgt(uint32_t op1, uint32_t op2)
3375
/* XXX: TODO: test special values (NaN, infinites, ...) */
3376
return efststgt(op1, op2);
3379
static inline uint32_t efscmpeq(uint32_t op1, uint32_t op2)
3381
/* XXX: TODO: test special values (NaN, infinites, ...) */
3382
return efststeq(op1, op2);
3385
#define HELPER_SINGLE_SPE_CMP(name) \
3386
uint32_t helper_e##name (uint32_t op1, uint32_t op2) \
3388
return e##name(op1, op2) << 2; \
3391
HELPER_SINGLE_SPE_CMP(fststlt);
3393
HELPER_SINGLE_SPE_CMP(fststgt);
3395
HELPER_SINGLE_SPE_CMP(fststeq);
3397
HELPER_SINGLE_SPE_CMP(fscmplt);
3399
HELPER_SINGLE_SPE_CMP(fscmpgt);
3401
HELPER_SINGLE_SPE_CMP(fscmpeq);
3403
static inline uint32_t evcmp_merge(int t0, int t1)
3405
return (t0 << 3) | (t1 << 2) | ((t0 | t1) << 1) | (t0 & t1);
3408
#define HELPER_VECTOR_SPE_CMP(name) \
3409
uint32_t helper_ev##name (uint64_t op1, uint64_t op2) \
3411
return evcmp_merge(e##name(op1 >> 32, op2 >> 32), e##name(op1, op2)); \
3414
HELPER_VECTOR_SPE_CMP(fststlt);
3416
HELPER_VECTOR_SPE_CMP(fststgt);
3418
HELPER_VECTOR_SPE_CMP(fststeq);
3420
HELPER_VECTOR_SPE_CMP(fscmplt);
3422
HELPER_VECTOR_SPE_CMP(fscmpgt);
3424
HELPER_VECTOR_SPE_CMP(fscmpeq);
3426
/* Double-precision floating-point conversion */
3427
uint64_t helper_efdcfsi (uint32_t val)
3431
u.d = int32_to_float64(val, &env->vec_status);
3436
uint64_t helper_efdcfsid (uint64_t val)
3440
u.d = int64_to_float64(val, &env->vec_status);
3445
uint64_t helper_efdcfui (uint32_t val)
3449
u.d = uint32_to_float64(val, &env->vec_status);
3454
uint64_t helper_efdcfuid (uint64_t val)
3458
u.d = uint64_to_float64(val, &env->vec_status);
3463
uint32_t helper_efdctsi (uint64_t val)
3468
/* NaN are not treated the same way IEEE 754 does */
3469
if (unlikely(float64_is_nan(u.d)))
3472
return float64_to_int32(u.d, &env->vec_status);
3475
uint32_t helper_efdctui (uint64_t val)
3480
/* NaN are not treated the same way IEEE 754 does */
3481
if (unlikely(float64_is_nan(u.d)))
3484
return float64_to_uint32(u.d, &env->vec_status);
3487
uint32_t helper_efdctsiz (uint64_t val)
3492
/* NaN are not treated the same way IEEE 754 does */
3493
if (unlikely(float64_is_nan(u.d)))
3496
return float64_to_int32_round_to_zero(u.d, &env->vec_status);
3499
uint64_t helper_efdctsidz (uint64_t val)
3504
/* NaN are not treated the same way IEEE 754 does */
3505
if (unlikely(float64_is_nan(u.d)))
3508
return float64_to_int64_round_to_zero(u.d, &env->vec_status);
3511
uint32_t helper_efdctuiz (uint64_t val)
3516
/* NaN are not treated the same way IEEE 754 does */
3517
if (unlikely(float64_is_nan(u.d)))
3520
return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
3523
uint64_t helper_efdctuidz (uint64_t val)
3528
/* NaN are not treated the same way IEEE 754 does */
3529
if (unlikely(float64_is_nan(u.d)))
3532
return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
3535
uint64_t helper_efdcfsf (uint32_t val)
3540
u.d = int32_to_float64(val, &env->vec_status);
3541
tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3542
u.d = float64_div(u.d, tmp, &env->vec_status);
3547
uint64_t helper_efdcfuf (uint32_t val)
3552
u.d = uint32_to_float64(val, &env->vec_status);
3553
tmp = int64_to_float64(1ULL << 32, &env->vec_status);
3554
u.d = float64_div(u.d, tmp, &env->vec_status);
3559
uint32_t helper_efdctsf (uint64_t val)
3565
/* NaN are not treated the same way IEEE 754 does */
3566
if (unlikely(float64_is_nan(u.d)))
3568
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3569
u.d = float64_mul(u.d, tmp, &env->vec_status);
3571
return float64_to_int32(u.d, &env->vec_status);
3574
uint32_t helper_efdctuf (uint64_t val)
3580
/* NaN are not treated the same way IEEE 754 does */
3581
if (unlikely(float64_is_nan(u.d)))
3583
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
3584
u.d = float64_mul(u.d, tmp, &env->vec_status);
3586
return float64_to_uint32(u.d, &env->vec_status);
3589
uint32_t helper_efscfd (uint64_t val)
3595
u2.f = float64_to_float32(u1.d, &env->vec_status);
3600
uint64_t helper_efdcfs (uint32_t val)
3606
u2.d = float32_to_float64(u1.f, &env->vec_status);
3611
/* Double precision fixed-point arithmetic */
3612
uint64_t helper_efdadd (uint64_t op1, uint64_t op2)
3617
u1.d = float64_add(u1.d, u2.d, &env->vec_status);
3621
uint64_t helper_efdsub (uint64_t op1, uint64_t op2)
3626
u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
3630
uint64_t helper_efdmul (uint64_t op1, uint64_t op2)
3635
u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
3639
uint64_t helper_efddiv (uint64_t op1, uint64_t op2)
3644
u1.d = float64_div(u1.d, u2.d, &env->vec_status);
3648
/* Double precision floating point helpers */
3649
uint32_t helper_efdtstlt (uint64_t op1, uint64_t op2)
3654
return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3657
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
3662
return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
3665
uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
3670
return float64_eq(u1.d, u2.d, &env->vec_status) ? 4 : 0;
3673
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
3675
/* XXX: TODO: test special values (NaN, infinites, ...) */
3676
return helper_efdtstlt(op1, op2);
3679
uint32_t helper_efdcmpgt (uint64_t op1, uint64_t op2)
3681
/* XXX: TODO: test special values (NaN, infinites, ...) */
3682
return helper_efdtstgt(op1, op2);
3685
uint32_t helper_efdcmpeq (uint64_t op1, uint64_t op2)
3687
/* XXX: TODO: test special values (NaN, infinites, ...) */
3688
return helper_efdtsteq(op1, op2);
2610
3691
/*****************************************************************************/
2611
3692
/* Softmmu support */
2777
3921
/* Helpers for 4xx TLB management */
2778
void do_4xx_tlbre_lo (void)
3922
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
2780
3924
ppcemb_tlb_t *tlb;
2784
tlb = &env->tlb[T0].tlbe;
3929
tlb = &env->tlb[entry].tlbe;
2786
3931
if (tlb->prot & PAGE_VALID)
2788
3933
size = booke_page_size_to_tlb(tlb->size);
2789
3934
if (size < 0 || size > 0x7)
2792
3937
env->spr[SPR_40x_PID] = tlb->PID;
2795
void do_4xx_tlbre_hi (void)
3941
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
2797
3943
ppcemb_tlb_t *tlb;
2800
tlb = &env->tlb[T0].tlbe;
3947
tlb = &env->tlb[entry].tlbe;
2802
3949
if (tlb->prot & PAGE_EXEC)
2804
3951
if (tlb->prot & PAGE_WRITE)
2808
void do_4xx_tlbwe_hi (void)
3956
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
2810
3958
ppcemb_tlb_t *tlb;
2811
3959
target_ulong page, end;
2813
#if defined (DEBUG_SOFTWARE_TLB)
2814
if (loglevel != 0) {
2815
fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
2819
tlb = &env->tlb[T0].tlbe;
3961
LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
3964
tlb = &env->tlb[entry].tlbe;
2820
3965
/* Invalidate previous TLB (if it's valid) */
2821
3966
if (tlb->prot & PAGE_VALID) {
2822
3967
end = tlb->EPN + tlb->size;
2823
#if defined (DEBUG_SOFTWARE_TLB)
2824
if (loglevel != 0) {
2825
fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
2826
" end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
3968
LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
3969
TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2829
3970
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2830
3971
tlb_flush_page(env, page);
2832
tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
3973
tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
2833
3974
/* We cannot handle TLB size < TARGET_PAGE_SIZE.
2834
3975
* If this ever occurs, one should use the ppcemb target instead
2835
3976
* of the ppc or ppc64 one
2837
if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
3978
if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
2838
3979
cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2839
3980
"are not supported (%d)\n",
2840
tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
3981
tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2842
tlb->EPN = T1 & ~(tlb->size - 1);
3983
tlb->EPN = val & ~(tlb->size - 1);
2844
3985
tlb->prot |= PAGE_VALID;
2846
3987
tlb->prot &= ~PAGE_VALID;
2848
3989
/* XXX: TO BE FIXED */
2849
3990
cpu_abort(env, "Little-endian TLB entries are not supported by now\n");
2851
3992
tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2852
tlb->attr = T1 & 0xFF;
2853
#if defined (DEBUG_SOFTWARE_TLB)
2854
if (loglevel != 0) {
2855
fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2856
" size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2857
(int)T0, tlb->RPN, tlb->EPN, tlb->size,
2858
tlb->prot & PAGE_READ ? 'r' : '-',
2859
tlb->prot & PAGE_WRITE ? 'w' : '-',
2860
tlb->prot & PAGE_EXEC ? 'x' : '-',
2861
tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
3993
tlb->attr = val & 0xFF;
3994
LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
3995
" size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
3996
(int)entry, tlb->RPN, tlb->EPN, tlb->size,
3997
tlb->prot & PAGE_READ ? 'r' : '-',
3998
tlb->prot & PAGE_WRITE ? 'w' : '-',
3999
tlb->prot & PAGE_EXEC ? 'x' : '-',
4000
tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2864
4001
/* Invalidate new TLB (if valid) */
2865
4002
if (tlb->prot & PAGE_VALID) {
2866
4003
end = tlb->EPN + tlb->size;
2867
#if defined (DEBUG_SOFTWARE_TLB)
2868
if (loglevel != 0) {
2869
fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
2870
" end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
4004
LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
4005
TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2873
4006
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2874
4007
tlb_flush_page(env, page);
2878
void do_4xx_tlbwe_lo (void)
4011
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
2880
4013
ppcemb_tlb_t *tlb;
2882
#if defined (DEBUG_SOFTWARE_TLB)
2883
if (loglevel != 0) {
2884
fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
2888
tlb = &env->tlb[T0].tlbe;
2889
tlb->RPN = T1 & 0xFFFFFC00;
4015
LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
4018
tlb = &env->tlb[entry].tlbe;
4019
tlb->RPN = val & 0xFFFFFC00;
2890
4020
tlb->prot = PAGE_READ;
2892
4022
tlb->prot |= PAGE_EXEC;
2894
4024
tlb->prot |= PAGE_WRITE;
2895
#if defined (DEBUG_SOFTWARE_TLB)
2896
if (loglevel != 0) {
2897
fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
2898
" size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
2899
(int)T0, tlb->RPN, tlb->EPN, tlb->size,
2900
tlb->prot & PAGE_READ ? 'r' : '-',
2901
tlb->prot & PAGE_WRITE ? 'w' : '-',
2902
tlb->prot & PAGE_EXEC ? 'x' : '-',
2903
tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
4025
LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
4026
" size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
4027
(int)entry, tlb->RPN, tlb->EPN, tlb->size,
4028
tlb->prot & PAGE_READ ? 'r' : '-',
4029
tlb->prot & PAGE_WRITE ? 'w' : '-',
4030
tlb->prot & PAGE_EXEC ? 'x' : '-',
4031
tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
4034
target_ulong helper_4xx_tlbsx (target_ulong address)
4036
return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2908
4039
/* PowerPC 440 TLB management */
2909
void do_440_tlbwe (int word)
4040
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
2911
4042
ppcemb_tlb_t *tlb;
2912
4043
target_ulong EPN, RPN, size;
2913
4044
int do_flush_tlbs;
2915
#if defined (DEBUG_SOFTWARE_TLB)
2916
if (loglevel != 0) {
2917
fprintf(logfile, "%s word %d T0 " TDX " T1 " TDX "\n",
2918
__func__, word, T0, T1);
4046
LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
4047
__func__, word, (int)entry, value);
2921
4048
do_flush_tlbs = 0;
2923
tlb = &env->tlb[T0].tlbe;
4050
tlb = &env->tlb[entry].tlbe;
2924
4051
switch (word) {
2926
4053
/* Just here to please gcc */
2928
EPN = T1 & 0xFFFFFC00;
4055
EPN = value & 0xFFFFFC00;
2929
4056
if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN)
2930
4057
do_flush_tlbs = 1;
2931
4058
tlb->EPN = EPN;
2932
size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
4059
size = booke_tlb_to_page_size((value >> 4) & 0xF);
2933
4060
if ((tlb->prot & PAGE_VALID) && tlb->size < size)
2934
4061
do_flush_tlbs = 1;
2935
4062
tlb->size = size;
2936
4063
tlb->attr &= ~0x1;
2937
tlb->attr |= (T1 >> 8) & 1;
4064
tlb->attr |= (value >> 8) & 1;
4065
if (value & 0x200) {
2939
4066
tlb->prot |= PAGE_VALID;
2941
4068
if (tlb->prot & PAGE_VALID) {