xref: /qemu/target/microblaze/op_helper.c (revision 7bca6ddf901bba39f890fc80d22c26ed2606f4d5)
14acb54baSEdgar E. Iglesias /*
24acb54baSEdgar E. Iglesias  *  Microblaze helper routines.
34acb54baSEdgar E. Iglesias  *
44acb54baSEdgar E. Iglesias  *  Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>.
5dadc1064SPeter A. G. Crosthwaite  *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
64acb54baSEdgar E. Iglesias  *
74acb54baSEdgar E. Iglesias  * This library is free software; you can redistribute it and/or
84acb54baSEdgar E. Iglesias  * modify it under the terms of the GNU Lesser General Public
94acb54baSEdgar E. Iglesias  * License as published by the Free Software Foundation; either
104acb54baSEdgar E. Iglesias  * version 2 of the License, or (at your option) any later version.
114acb54baSEdgar E. Iglesias  *
124acb54baSEdgar E. Iglesias  * This library is distributed in the hope that it will be useful,
134acb54baSEdgar E. Iglesias  * but WITHOUT ANY WARRANTY; without even the implied warranty of
144acb54baSEdgar E. Iglesias  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
154acb54baSEdgar E. Iglesias  * Lesser General Public License for more details.
164acb54baSEdgar E. Iglesias  *
174acb54baSEdgar E. Iglesias  * You should have received a copy of the GNU Lesser General Public
188167ee88SBlue Swirl  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
194acb54baSEdgar E. Iglesias  */
204acb54baSEdgar E. Iglesias 
218fd9deceSPeter Maydell #include "qemu/osdep.h"
223e457172SBlue Swirl #include "cpu.h"
232ef6175aSRichard Henderson #include "exec/helper-proto.h"
241de7afc9SPaolo Bonzini #include "qemu/host-utils.h"
2563c91552SPaolo Bonzini #include "exec/exec-all.h"
26f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h"
2724f91e81SAlex Bennée #include "fpu/softfloat.h"
284acb54baSEdgar E. Iglesias 
296d76d23eSEdgar E. Iglesias void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
306d76d23eSEdgar E. Iglesias {
316d76d23eSEdgar E. Iglesias     int test = ctrl & STREAM_TEST;
326d76d23eSEdgar E. Iglesias     int atomic = ctrl & STREAM_ATOMIC;
336d76d23eSEdgar E. Iglesias     int control = ctrl & STREAM_CONTROL;
346d76d23eSEdgar E. Iglesias     int nonblock = ctrl & STREAM_NONBLOCK;
356d76d23eSEdgar E. Iglesias     int exception = ctrl & STREAM_EXCEPTION;
366d76d23eSEdgar E. Iglesias 
371d512a65SPaolo Bonzini     qemu_log_mask(LOG_UNIMP, "Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n",
386d76d23eSEdgar E. Iglesias              id, data,
396d76d23eSEdgar E. Iglesias              test ? "t" : "",
406d76d23eSEdgar E. Iglesias              nonblock ? "n" : "",
416d76d23eSEdgar E. Iglesias              exception ? "e" : "",
426d76d23eSEdgar E. Iglesias              control ? "c" : "",
436d76d23eSEdgar E. Iglesias              atomic ? "a" : "");
446d76d23eSEdgar E. Iglesias }
456d76d23eSEdgar E. Iglesias 
466d76d23eSEdgar E. Iglesias uint32_t helper_get(uint32_t id, uint32_t ctrl)
476d76d23eSEdgar E. Iglesias {
486d76d23eSEdgar E. Iglesias     int test = ctrl & STREAM_TEST;
496d76d23eSEdgar E. Iglesias     int atomic = ctrl & STREAM_ATOMIC;
506d76d23eSEdgar E. Iglesias     int control = ctrl & STREAM_CONTROL;
516d76d23eSEdgar E. Iglesias     int nonblock = ctrl & STREAM_NONBLOCK;
526d76d23eSEdgar E. Iglesias     int exception = ctrl & STREAM_EXCEPTION;
536d76d23eSEdgar E. Iglesias 
541d512a65SPaolo Bonzini     qemu_log_mask(LOG_UNIMP, "Unhandled stream get from stream-id=%d %s%s%s%s%s\n",
556d76d23eSEdgar E. Iglesias              id,
566d76d23eSEdgar E. Iglesias              test ? "t" : "",
576d76d23eSEdgar E. Iglesias              nonblock ? "n" : "",
586d76d23eSEdgar E. Iglesias              exception ? "e" : "",
596d76d23eSEdgar E. Iglesias              control ? "c" : "",
606d76d23eSEdgar E. Iglesias              atomic ? "a" : "");
616d76d23eSEdgar E. Iglesias     return 0xdead0000 | id;
626d76d23eSEdgar E. Iglesias }
636d76d23eSEdgar E. Iglesias 
6464254ebaSBlue Swirl void helper_raise_exception(CPUMBState *env, uint32_t index)
654acb54baSEdgar E. Iglesias {
66f5c7e93aSRichard Henderson     CPUState *cs = env_cpu(env);
6727103424SAndreas Färber 
6827103424SAndreas Färber     cs->exception_index = index;
695638d180SAndreas Färber     cpu_loop_exit(cs);
704acb54baSEdgar E. Iglesias }
714acb54baSEdgar E. Iglesias 
72e98651d9SRichard Henderson static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
734acb54baSEdgar E. Iglesias {
74e98651d9SRichard Henderson     if (unlikely(b == 0)) {
752e5282caSRichard Henderson         env->msr |= MSR_DZ;
76821ebb33SEdgar E. Iglesias 
77e98651d9SRichard Henderson         if ((env->msr & MSR_EE) &&
78e98651d9SRichard Henderson             env_archcpu(env)->cfg.div_zero_exception) {
79e98651d9SRichard Henderson             CPUState *cs = env_cpu(env);
80e98651d9SRichard Henderson 
8178e9caf2SRichard Henderson             env->esr = ESR_EC_DIVZERO;
82e98651d9SRichard Henderson             cs->exception_index = EXCP_HW_EXCP;
83e98651d9SRichard Henderson             cpu_loop_exit_restore(cs, ra);
84821ebb33SEdgar E. Iglesias         }
85e98651d9SRichard Henderson         return false;
864acb54baSEdgar E. Iglesias     }
87e98651d9SRichard Henderson     return true;
884acb54baSEdgar E. Iglesias }
894acb54baSEdgar E. Iglesias 
9064254ebaSBlue Swirl uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
914acb54baSEdgar E. Iglesias {
92e98651d9SRichard Henderson     if (!check_divz(env, a, b, GETPC())) {
934acb54baSEdgar E. Iglesias         return 0;
9464254ebaSBlue Swirl     }
954acb54baSEdgar E. Iglesias     return (int32_t)a / (int32_t)b;
964acb54baSEdgar E. Iglesias }
974acb54baSEdgar E. Iglesias 
9864254ebaSBlue Swirl uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
994acb54baSEdgar E. Iglesias {
100e98651d9SRichard Henderson     if (!check_divz(env, a, b, GETPC())) {
1014acb54baSEdgar E. Iglesias         return 0;
10264254ebaSBlue Swirl     }
1034acb54baSEdgar E. Iglesias     return a / b;
1044acb54baSEdgar E. Iglesias }
1054acb54baSEdgar E. Iglesias 
10697694c57SEdgar E. Iglesias /* raise FPU exception.  */
107*7bca6ddfSRichard Henderson static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
10897694c57SEdgar E. Iglesias {
109*7bca6ddfSRichard Henderson     CPUState *cs = env_cpu(env);
110*7bca6ddfSRichard Henderson 
11178e9caf2SRichard Henderson     env->esr = ESR_EC_FPU;
112*7bca6ddfSRichard Henderson     cs->exception_index = EXCP_HW_EXCP;
113*7bca6ddfSRichard Henderson     cpu_loop_exit_restore(cs, ra);
11497694c57SEdgar E. Iglesias }
11597694c57SEdgar E. Iglesias 
116*7bca6ddfSRichard Henderson static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
11797694c57SEdgar E. Iglesias {
11897694c57SEdgar E. Iglesias     int raise = 0;
11997694c57SEdgar E. Iglesias 
12097694c57SEdgar E. Iglesias     if (flags & float_flag_invalid) {
1215a8e0136SRichard Henderson         env->fsr |= FSR_IO;
12297694c57SEdgar E. Iglesias         raise = 1;
12397694c57SEdgar E. Iglesias     }
12497694c57SEdgar E. Iglesias     if (flags & float_flag_divbyzero) {
1255a8e0136SRichard Henderson         env->fsr |= FSR_DZ;
12697694c57SEdgar E. Iglesias         raise = 1;
12797694c57SEdgar E. Iglesias     }
12897694c57SEdgar E. Iglesias     if (flags & float_flag_overflow) {
1295a8e0136SRichard Henderson         env->fsr |= FSR_OF;
13097694c57SEdgar E. Iglesias         raise = 1;
13197694c57SEdgar E. Iglesias     }
13297694c57SEdgar E. Iglesias     if (flags & float_flag_underflow) {
1335a8e0136SRichard Henderson         env->fsr |= FSR_UF;
13497694c57SEdgar E. Iglesias         raise = 1;
13597694c57SEdgar E. Iglesias     }
13697694c57SEdgar E. Iglesias     if (raise
13797694c57SEdgar E. Iglesias         && (env->pvr.regs[2] & PVR2_FPU_EXC_MASK)
1382e5282caSRichard Henderson         && (env->msr & MSR_EE)) {
139*7bca6ddfSRichard Henderson         raise_fpu_exception(env, ra);
14097694c57SEdgar E. Iglesias     }
14197694c57SEdgar E. Iglesias }
14297694c57SEdgar E. Iglesias 
14364254ebaSBlue Swirl uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
14497694c57SEdgar E. Iglesias {
14597694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
14697694c57SEdgar E. Iglesias     int flags;
14797694c57SEdgar E. Iglesias 
14897694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
14997694c57SEdgar E. Iglesias     fa.l = a;
15097694c57SEdgar E. Iglesias     fb.l = b;
15197694c57SEdgar E. Iglesias     fd.f = float32_add(fa.f, fb.f, &env->fp_status);
15297694c57SEdgar E. Iglesias 
15397694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
154*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
15597694c57SEdgar E. Iglesias     return fd.l;
15697694c57SEdgar E. Iglesias }
15797694c57SEdgar E. Iglesias 
15864254ebaSBlue Swirl uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
15997694c57SEdgar E. Iglesias {
16097694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
16197694c57SEdgar E. Iglesias     int flags;
16297694c57SEdgar E. Iglesias 
16397694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
16497694c57SEdgar E. Iglesias     fa.l = a;
16597694c57SEdgar E. Iglesias     fb.l = b;
16697694c57SEdgar E. Iglesias     fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
16797694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
168*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
16997694c57SEdgar E. Iglesias     return fd.l;
17097694c57SEdgar E. Iglesias }
17197694c57SEdgar E. Iglesias 
17264254ebaSBlue Swirl uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
17397694c57SEdgar E. Iglesias {
17497694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
17597694c57SEdgar E. Iglesias     int flags;
17697694c57SEdgar E. Iglesias 
17797694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
17897694c57SEdgar E. Iglesias     fa.l = a;
17997694c57SEdgar E. Iglesias     fb.l = b;
18097694c57SEdgar E. Iglesias     fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
18197694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
182*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
18397694c57SEdgar E. Iglesias 
18497694c57SEdgar E. Iglesias     return fd.l;
18597694c57SEdgar E. Iglesias }
18697694c57SEdgar E. Iglesias 
18764254ebaSBlue Swirl uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
18897694c57SEdgar E. Iglesias {
18997694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
19097694c57SEdgar E. Iglesias     int flags;
19197694c57SEdgar E. Iglesias 
19297694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
19397694c57SEdgar E. Iglesias     fa.l = a;
19497694c57SEdgar E. Iglesias     fb.l = b;
19597694c57SEdgar E. Iglesias     fd.f = float32_div(fb.f, fa.f, &env->fp_status);
19697694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
197*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
19897694c57SEdgar E. Iglesias 
19997694c57SEdgar E. Iglesias     return fd.l;
20097694c57SEdgar E. Iglesias }
20197694c57SEdgar E. Iglesias 
20264254ebaSBlue Swirl uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
20397694c57SEdgar E. Iglesias {
204ef9d48daSEdgar E. Iglesias     CPU_FloatU fa, fb;
205ef9d48daSEdgar E. Iglesias     uint32_t r = 0;
206ef9d48daSEdgar E. Iglesias 
207ef9d48daSEdgar E. Iglesias     fa.l = a;
208ef9d48daSEdgar E. Iglesias     fb.l = b;
209ef9d48daSEdgar E. Iglesias 
210af39bc8cSAleksandar Markovic     if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
211af39bc8cSAleksandar Markovic         float32_is_signaling_nan(fb.f, &env->fp_status)) {
212*7bca6ddfSRichard Henderson         update_fpu_flags(env, float_flag_invalid, GETPC());
213ef9d48daSEdgar E. Iglesias         r = 1;
214ef9d48daSEdgar E. Iglesias     }
215ef9d48daSEdgar E. Iglesias 
216af39bc8cSAleksandar Markovic     if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
217af39bc8cSAleksandar Markovic         float32_is_quiet_nan(fb.f, &env->fp_status)) {
218ef9d48daSEdgar E. Iglesias         r = 1;
219ef9d48daSEdgar E. Iglesias     }
220ef9d48daSEdgar E. Iglesias 
221ef9d48daSEdgar E. Iglesias     return r;
22297694c57SEdgar E. Iglesias }
22397694c57SEdgar E. Iglesias 
22464254ebaSBlue Swirl uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
22597694c57SEdgar E. Iglesias {
22697694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
22797694c57SEdgar E. Iglesias     int r;
22897694c57SEdgar E. Iglesias     int flags;
22997694c57SEdgar E. Iglesias 
23097694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
23197694c57SEdgar E. Iglesias     fa.l = a;
23297694c57SEdgar E. Iglesias     fb.l = b;
23397694c57SEdgar E. Iglesias     r = float32_lt(fb.f, fa.f, &env->fp_status);
23497694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
235*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
23697694c57SEdgar E. Iglesias 
23797694c57SEdgar E. Iglesias     return r;
23897694c57SEdgar E. Iglesias }
23997694c57SEdgar E. Iglesias 
24064254ebaSBlue Swirl uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
24197694c57SEdgar E. Iglesias {
24297694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
24397694c57SEdgar E. Iglesias     int flags;
24497694c57SEdgar E. Iglesias     int r;
24597694c57SEdgar E. Iglesias 
24697694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
24797694c57SEdgar E. Iglesias     fa.l = a;
24897694c57SEdgar E. Iglesias     fb.l = b;
249211315fbSAurelien Jarno     r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
25097694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
251*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
25297694c57SEdgar E. Iglesias 
25397694c57SEdgar E. Iglesias     return r;
25497694c57SEdgar E. Iglesias }
25597694c57SEdgar E. Iglesias 
25664254ebaSBlue Swirl uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
25797694c57SEdgar E. Iglesias {
25897694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
25997694c57SEdgar E. Iglesias     int flags;
26097694c57SEdgar E. Iglesias     int r;
26197694c57SEdgar E. Iglesias 
26297694c57SEdgar E. Iglesias     fa.l = a;
26397694c57SEdgar E. Iglesias     fb.l = b;
26497694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
26597694c57SEdgar E. Iglesias     r = float32_le(fa.f, fb.f, &env->fp_status);
26697694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
267*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
26897694c57SEdgar E. Iglesias 
26997694c57SEdgar E. Iglesias 
27097694c57SEdgar E. Iglesias     return r;
27197694c57SEdgar E. Iglesias }
27297694c57SEdgar E. Iglesias 
27364254ebaSBlue Swirl uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
27497694c57SEdgar E. Iglesias {
27597694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
27697694c57SEdgar E. Iglesias     int flags, r;
27797694c57SEdgar E. Iglesias 
27897694c57SEdgar E. Iglesias     fa.l = a;
27997694c57SEdgar E. Iglesias     fb.l = b;
28097694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
28197694c57SEdgar E. Iglesias     r = float32_lt(fa.f, fb.f, &env->fp_status);
28297694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
283*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
28497694c57SEdgar E. Iglesias     return r;
28597694c57SEdgar E. Iglesias }
28697694c57SEdgar E. Iglesias 
28764254ebaSBlue Swirl uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
28897694c57SEdgar E. Iglesias {
28997694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
29097694c57SEdgar E. Iglesias     int flags, r;
29197694c57SEdgar E. Iglesias 
29297694c57SEdgar E. Iglesias     fa.l = a;
29397694c57SEdgar E. Iglesias     fb.l = b;
29497694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
295211315fbSAurelien Jarno     r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
29697694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
297*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
29897694c57SEdgar E. Iglesias 
29997694c57SEdgar E. Iglesias     return r;
30097694c57SEdgar E. Iglesias }
30197694c57SEdgar E. Iglesias 
30264254ebaSBlue Swirl uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
30397694c57SEdgar E. Iglesias {
30497694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
30597694c57SEdgar E. Iglesias     int flags, r;
30697694c57SEdgar E. Iglesias 
30797694c57SEdgar E. Iglesias     fa.l = a;
30897694c57SEdgar E. Iglesias     fb.l = b;
30997694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
31097694c57SEdgar E. Iglesias     r = !float32_lt(fa.f, fb.f, &env->fp_status);
31197694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
312*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
31397694c57SEdgar E. Iglesias 
31497694c57SEdgar E. Iglesias     return r;
31597694c57SEdgar E. Iglesias }
31697694c57SEdgar E. Iglesias 
31764254ebaSBlue Swirl uint32_t helper_flt(CPUMBState *env, uint32_t a)
31897694c57SEdgar E. Iglesias {
31997694c57SEdgar E. Iglesias     CPU_FloatU fd, fa;
32097694c57SEdgar E. Iglesias 
32197694c57SEdgar E. Iglesias     fa.l = a;
32297694c57SEdgar E. Iglesias     fd.f = int32_to_float32(fa.l, &env->fp_status);
32397694c57SEdgar E. Iglesias     return fd.l;
32497694c57SEdgar E. Iglesias }
32597694c57SEdgar E. Iglesias 
32664254ebaSBlue Swirl uint32_t helper_fint(CPUMBState *env, uint32_t a)
32797694c57SEdgar E. Iglesias {
32897694c57SEdgar E. Iglesias     CPU_FloatU fa;
32997694c57SEdgar E. Iglesias     uint32_t r;
33097694c57SEdgar E. Iglesias     int flags;
33197694c57SEdgar E. Iglesias 
33297694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
33397694c57SEdgar E. Iglesias     fa.l = a;
33497694c57SEdgar E. Iglesias     r = float32_to_int32(fa.f, &env->fp_status);
33597694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
336*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
33797694c57SEdgar E. Iglesias 
33897694c57SEdgar E. Iglesias     return r;
33997694c57SEdgar E. Iglesias }
34097694c57SEdgar E. Iglesias 
34164254ebaSBlue Swirl uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
34297694c57SEdgar E. Iglesias {
34397694c57SEdgar E. Iglesias     CPU_FloatU fd, fa;
34497694c57SEdgar E. Iglesias     int flags;
34597694c57SEdgar E. Iglesias 
34697694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
34797694c57SEdgar E. Iglesias     fa.l = a;
34897694c57SEdgar E. Iglesias     fd.l = float32_sqrt(fa.f, &env->fp_status);
34997694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
350*7bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
35197694c57SEdgar E. Iglesias 
35297694c57SEdgar E. Iglesias     return fd.l;
35397694c57SEdgar E. Iglesias }
35497694c57SEdgar E. Iglesias 
3554acb54baSEdgar E. Iglesias uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
3564acb54baSEdgar E. Iglesias {
3574acb54baSEdgar E. Iglesias     unsigned int i;
3584acb54baSEdgar E. Iglesias     uint32_t mask = 0xff000000;
3594acb54baSEdgar E. Iglesias 
3604acb54baSEdgar E. Iglesias     for (i = 0; i < 4; i++) {
3614acb54baSEdgar E. Iglesias         if ((a & mask) == (b & mask))
3624acb54baSEdgar E. Iglesias             return i + 1;
3634acb54baSEdgar E. Iglesias         mask >>= 8;
3644acb54baSEdgar E. Iglesias     }
3654acb54baSEdgar E. Iglesias     return 0;
3664acb54baSEdgar E. Iglesias }
3674acb54baSEdgar E. Iglesias 
368403322eaSEdgar E. Iglesias void helper_memalign(CPUMBState *env, target_ulong addr,
369403322eaSEdgar E. Iglesias                      uint32_t dr, uint32_t wr,
37064254ebaSBlue Swirl                      uint32_t mask)
371968a40f6SEdgar E. Iglesias {
372968a40f6SEdgar E. Iglesias     if (addr & mask) {
37397f90cbfSEdgar E. Iglesias             qemu_log_mask(CPU_LOG_INT,
374403322eaSEdgar E. Iglesias                           "unaligned access addr=" TARGET_FMT_lx
375403322eaSEdgar E. Iglesias                           " mask=%x, wr=%d dr=r%d\n",
37697f90cbfSEdgar E. Iglesias                           addr, mask, wr, dr);
377b2e80a3cSRichard Henderson             env->ear = addr;
37878e9caf2SRichard Henderson             env->esr = ESR_EC_UNALIGNED_DATA | (wr << 10) | (dr & 31) << 5;
3793aa80988SEdgar E. Iglesias             if (mask == 3) {
38078e9caf2SRichard Henderson                 env->esr |= 1 << 11;
381968a40f6SEdgar E. Iglesias             }
3822e5282caSRichard Henderson             if (!(env->msr & MSR_EE)) {
38397f90cbfSEdgar E. Iglesias                 return;
38497f90cbfSEdgar E. Iglesias             }
38564254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
386968a40f6SEdgar E. Iglesias     }
387968a40f6SEdgar E. Iglesias }
388968a40f6SEdgar E. Iglesias 
389403322eaSEdgar E. Iglesias void helper_stackprot(CPUMBState *env, target_ulong addr)
3905818dee5SEdgar E. Iglesias {
3915818dee5SEdgar E. Iglesias     if (addr < env->slr || addr > env->shr) {
392403322eaSEdgar E. Iglesias         qemu_log_mask(CPU_LOG_INT, "Stack protector violation at "
393403322eaSEdgar E. Iglesias                       TARGET_FMT_lx " %x %x\n",
3945818dee5SEdgar E. Iglesias                       addr, env->slr, env->shr);
395b2e80a3cSRichard Henderson         env->ear = addr;
39678e9caf2SRichard Henderson         env->esr = ESR_EC_STACKPROT;
39764254ebaSBlue Swirl         helper_raise_exception(env, EXCP_HW_EXCP);
3985818dee5SEdgar E. Iglesias     }
3995818dee5SEdgar E. Iglesias }
4005818dee5SEdgar E. Iglesias 
4014acb54baSEdgar E. Iglesias #if !defined(CONFIG_USER_ONLY)
4024acb54baSEdgar E. Iglesias /* Writes/reads to the MMU's special regs end up here.  */
403f0f7e7f7SEdgar E. Iglesias uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn)
4044acb54baSEdgar E. Iglesias {
405f0f7e7f7SEdgar E. Iglesias     return mmu_read(env, ext, rn);
4064acb54baSEdgar E. Iglesias }
4074acb54baSEdgar E. Iglesias 
408f0f7e7f7SEdgar E. Iglesias void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v)
4094acb54baSEdgar E. Iglesias {
410f0f7e7f7SEdgar E. Iglesias     mmu_write(env, ext, rn, v);
4114acb54baSEdgar E. Iglesias }
412faed1c2aSEdgar E. Iglesias 
413bdff8123SPeter Maydell void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
414bdff8123SPeter Maydell                                unsigned size, MMUAccessType access_type,
415bdff8123SPeter Maydell                                int mmu_idx, MemTxAttrs attrs,
416bdff8123SPeter Maydell                                MemTxResult response, uintptr_t retaddr)
417faed1c2aSEdgar E. Iglesias {
418c658b94fSAndreas Färber     MicroBlazeCPU *cpu;
419c658b94fSAndreas Färber     CPUMBState *env;
420bdff8123SPeter Maydell     qemu_log_mask(CPU_LOG_INT, "Transaction failed: vaddr 0x%" VADDR_PRIx
421bdff8123SPeter Maydell                   " physaddr 0x" TARGET_FMT_plx " size %d access type %s\n",
422bdff8123SPeter Maydell                   addr, physaddr, size,
423bdff8123SPeter Maydell                   access_type == MMU_INST_FETCH ? "INST_FETCH" :
424bdff8123SPeter Maydell                   (access_type == MMU_DATA_LOAD ? "DATA_LOAD" : "DATA_STORE"));
425c658b94fSAndreas Färber     cpu = MICROBLAZE_CPU(cs);
426c658b94fSAndreas Färber     env = &cpu->env;
427bdff8123SPeter Maydell 
428bdff8123SPeter Maydell     cpu_restore_state(cs, retaddr, true);
4292e5282caSRichard Henderson     if (!(env->msr & MSR_EE)) {
430faed1c2aSEdgar E. Iglesias         return;
431faed1c2aSEdgar E. Iglesias     }
432faed1c2aSEdgar E. Iglesias 
433b2e80a3cSRichard Henderson     env->ear = addr;
434bdff8123SPeter Maydell     if (access_type == MMU_INST_FETCH) {
43597f90cbfSEdgar E. Iglesias         if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) {
43678e9caf2SRichard Henderson             env->esr = ESR_EC_INSN_BUS;
43764254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
438faed1c2aSEdgar E. Iglesias         }
439faed1c2aSEdgar E. Iglesias     } else {
44097f90cbfSEdgar E. Iglesias         if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) {
44178e9caf2SRichard Henderson             env->esr = ESR_EC_DATA_BUS;
44264254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
443faed1c2aSEdgar E. Iglesias         }
444faed1c2aSEdgar E. Iglesias     }
445faed1c2aSEdgar E. Iglesias }
4463c7b48b7SPaul Brook #endif
447