xref: /qemu/target/microblaze/op_helper.c (revision 3072961b6edc99abfbd87caac3de29bb58a52ccf)
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
10ee452036SChetan Pant  * version 2.1 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"
22cd617484SPhilippe Mathieu-Daudé #include "qemu/log.h"
233e457172SBlue Swirl #include "cpu.h"
242ef6175aSRichard Henderson #include "exec/helper-proto.h"
251de7afc9SPaolo Bonzini #include "qemu/host-utils.h"
2642fa9665SPhilippe Mathieu-Daudé #include "accel/tcg/cpu-ldst.h"
2724f91e81SAlex Bennée #include "fpu/softfloat.h"
284acb54baSEdgar E. Iglesias 
helper_put(uint32_t id,uint32_t ctrl,uint32_t data)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 
helper_get(uint32_t id,uint32_t ctrl)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 
helper_raise_exception(CPUMBState * env,uint32_t index)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 
check_divz(CPUMBState * env,uint32_t a,uint32_t b,uintptr_t ra)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 
helper_divs(CPUMBState * env,uint32_t a,uint32_t b)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 
helper_divu(CPUMBState * env,uint32_t a,uint32_t b)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.  */
raise_fpu_exception(CPUMBState * env,uintptr_t ra)1077bca6ddfSRichard Henderson static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
10897694c57SEdgar E. Iglesias {
1097bca6ddfSRichard Henderson     CPUState *cs = env_cpu(env);
1107bca6ddfSRichard Henderson 
11178e9caf2SRichard Henderson     env->esr = ESR_EC_FPU;
1127bca6ddfSRichard Henderson     cs->exception_index = EXCP_HW_EXCP;
1137bca6ddfSRichard Henderson     cpu_loop_exit_restore(cs, ra);
11497694c57SEdgar E. Iglesias }
11597694c57SEdgar E. Iglesias 
update_fpu_flags(CPUMBState * env,int flags,uintptr_t ra)1167bca6ddfSRichard 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
137a4bcfc33SRichard Henderson         && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK)
1382e5282caSRichard Henderson         && (env->msr & MSR_EE)) {
1397bca6ddfSRichard Henderson         raise_fpu_exception(env, ra);
14097694c57SEdgar E. Iglesias     }
14197694c57SEdgar E. Iglesias }
14297694c57SEdgar E. Iglesias 
helper_fadd(CPUMBState * env,uint32_t a,uint32_t b)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);
1547bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
15597694c57SEdgar E. Iglesias     return fd.l;
15697694c57SEdgar E. Iglesias }
15797694c57SEdgar E. Iglesias 
helper_frsub(CPUMBState * env,uint32_t a,uint32_t b)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);
1687bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
16997694c57SEdgar E. Iglesias     return fd.l;
17097694c57SEdgar E. Iglesias }
17197694c57SEdgar E. Iglesias 
helper_fmul(CPUMBState * env,uint32_t a,uint32_t b)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);
1827bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
18397694c57SEdgar E. Iglesias 
18497694c57SEdgar E. Iglesias     return fd.l;
18597694c57SEdgar E. Iglesias }
18697694c57SEdgar E. Iglesias 
helper_fdiv(CPUMBState * env,uint32_t a,uint32_t b)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);
1977bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
19897694c57SEdgar E. Iglesias 
19997694c57SEdgar E. Iglesias     return fd.l;
20097694c57SEdgar E. Iglesias }
20197694c57SEdgar E. Iglesias 
helper_fcmp_un(CPUMBState * env,uint32_t a,uint32_t b)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)) {
2127bca6ddfSRichard 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 
helper_fcmp_lt(CPUMBState * env,uint32_t a,uint32_t b)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);
2357bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
23697694c57SEdgar E. Iglesias 
23797694c57SEdgar E. Iglesias     return r;
23897694c57SEdgar E. Iglesias }
23997694c57SEdgar E. Iglesias 
helper_fcmp_eq(CPUMBState * env,uint32_t a,uint32_t b)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);
2517bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
25297694c57SEdgar E. Iglesias 
25397694c57SEdgar E. Iglesias     return r;
25497694c57SEdgar E. Iglesias }
25597694c57SEdgar E. Iglesias 
helper_fcmp_le(CPUMBState * env,uint32_t a,uint32_t b)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);
2677bca6ddfSRichard 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 
helper_fcmp_gt(CPUMBState * env,uint32_t a,uint32_t b)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);
2837bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
28497694c57SEdgar E. Iglesias     return r;
28597694c57SEdgar E. Iglesias }
28697694c57SEdgar E. Iglesias 
helper_fcmp_ne(CPUMBState * env,uint32_t a,uint32_t b)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);
2977bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
29897694c57SEdgar E. Iglesias 
29997694c57SEdgar E. Iglesias     return r;
30097694c57SEdgar E. Iglesias }
30197694c57SEdgar E. Iglesias 
helper_fcmp_ge(CPUMBState * env,uint32_t a,uint32_t b)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);
3127bca6ddfSRichard Henderson     update_fpu_flags(env, flags & float_flag_invalid, GETPC());
31397694c57SEdgar E. Iglesias 
31497694c57SEdgar E. Iglesias     return r;
31597694c57SEdgar E. Iglesias }
31697694c57SEdgar E. Iglesias 
helper_flt(CPUMBState * env,uint32_t a)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 
helper_fint(CPUMBState * env,uint32_t a)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);
3367bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
33797694c57SEdgar E. Iglesias 
33897694c57SEdgar E. Iglesias     return r;
33997694c57SEdgar E. Iglesias }
34097694c57SEdgar E. Iglesias 
helper_fsqrt(CPUMBState * env,uint32_t a)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);
3507bca6ddfSRichard Henderson     update_fpu_flags(env, flags, GETPC());
35197694c57SEdgar E. Iglesias 
35297694c57SEdgar E. Iglesias     return fd.l;
35397694c57SEdgar E. Iglesias }
35497694c57SEdgar E. Iglesias 
helper_pcmpbf(uint32_t a,uint32_t b)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 
helper_stackprot(CPUMBState * env,target_ulong addr)368403322eaSEdgar E. Iglesias void helper_stackprot(CPUMBState *env, target_ulong addr)
3695818dee5SEdgar E. Iglesias {
3705818dee5SEdgar E. Iglesias     if (addr < env->slr || addr > env->shr) {
3713f203194SRichard Henderson         CPUState *cs = env_cpu(env);
3723f203194SRichard Henderson 
373403322eaSEdgar E. Iglesias         qemu_log_mask(CPU_LOG_INT, "Stack protector violation at "
374403322eaSEdgar E. Iglesias                       TARGET_FMT_lx " %x %x\n",
3755818dee5SEdgar E. Iglesias                       addr, env->slr, env->shr);
3763f203194SRichard Henderson 
377b2e80a3cSRichard Henderson         env->ear = addr;
37878e9caf2SRichard Henderson         env->esr = ESR_EC_STACKPROT;
3793f203194SRichard Henderson         cs->exception_index = EXCP_HW_EXCP;
3803f203194SRichard Henderson         cpu_loop_exit_restore(cs, GETPC());
3815818dee5SEdgar E. Iglesias     }
3825818dee5SEdgar E. Iglesias }
3835818dee5SEdgar E. Iglesias 
3844acb54baSEdgar E. Iglesias #if !defined(CONFIG_USER_ONLY)
385*beea7726SRichard Henderson #include "system/memory.h"
386*beea7726SRichard Henderson 
3874acb54baSEdgar E. Iglesias /* Writes/reads to the MMU's special regs end up here.  */
helper_mmu_read(CPUMBState * env,uint32_t ext,uint32_t rn)388f0f7e7f7SEdgar E. Iglesias uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn)
3894acb54baSEdgar E. Iglesias {
390f0f7e7f7SEdgar E. Iglesias     return mmu_read(env, ext, rn);
3914acb54baSEdgar E. Iglesias }
3924acb54baSEdgar E. Iglesias 
helper_mmu_write(CPUMBState * env,uint32_t ext,uint32_t rn,uint32_t v)393f0f7e7f7SEdgar E. Iglesias void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v)
3944acb54baSEdgar E. Iglesias {
395f0f7e7f7SEdgar E. Iglesias     mmu_write(env, ext, rn, v);
3964acb54baSEdgar E. Iglesias }
397faed1c2aSEdgar E. Iglesias 
mb_transaction_failed_internal(CPUState * cs,hwaddr physaddr,uint64_t addr,unsigned size,MMUAccessType access_type,uintptr_t retaddr)398526b0d36SRichard Henderson static void mb_transaction_failed_internal(CPUState *cs, hwaddr physaddr,
399526b0d36SRichard Henderson                                            uint64_t addr, unsigned size,
400526b0d36SRichard Henderson                                            MMUAccessType access_type,
401526b0d36SRichard Henderson                                            uintptr_t retaddr)
402526b0d36SRichard Henderson {
403526b0d36SRichard Henderson     CPUMBState *env = cpu_env(cs);
404526b0d36SRichard Henderson     MicroBlazeCPU *cpu = env_archcpu(env);
405526b0d36SRichard Henderson     const char *access_name = "INVALID";
406526b0d36SRichard Henderson     bool take = env->msr & MSR_EE;
407526b0d36SRichard Henderson     uint32_t esr = ESR_EC_DATA_BUS;
408526b0d36SRichard Henderson 
409526b0d36SRichard Henderson     switch (access_type) {
410526b0d36SRichard Henderson     case MMU_INST_FETCH:
411526b0d36SRichard Henderson         access_name = "INST_FETCH";
412526b0d36SRichard Henderson         esr = ESR_EC_INSN_BUS;
413526b0d36SRichard Henderson         take &= cpu->cfg.iopb_bus_exception;
414526b0d36SRichard Henderson         break;
415526b0d36SRichard Henderson     case MMU_DATA_LOAD:
416526b0d36SRichard Henderson         access_name = "DATA_LOAD";
417526b0d36SRichard Henderson         take &= cpu->cfg.dopb_bus_exception;
418526b0d36SRichard Henderson         break;
419526b0d36SRichard Henderson     case MMU_DATA_STORE:
420526b0d36SRichard Henderson         access_name = "DATA_STORE";
421526b0d36SRichard Henderson         take &= cpu->cfg.dopb_bus_exception;
422526b0d36SRichard Henderson         break;
423526b0d36SRichard Henderson     }
424526b0d36SRichard Henderson 
425526b0d36SRichard Henderson     qemu_log_mask(CPU_LOG_INT, "Transaction failed: addr 0x%" PRIx64
426526b0d36SRichard Henderson                   "physaddr 0x" HWADDR_FMT_plx " size %d access-type %s (%s)\n",
427526b0d36SRichard Henderson                   addr, physaddr, size, access_name,
428526b0d36SRichard Henderson                   take ? "TAKEN" : "DROPPED");
429526b0d36SRichard Henderson 
430526b0d36SRichard Henderson     if (take) {
431526b0d36SRichard Henderson         env->esr = esr;
432526b0d36SRichard Henderson         env->ear = addr;
433526b0d36SRichard Henderson         cs->exception_index = EXCP_HW_EXCP;
434526b0d36SRichard Henderson         cpu_loop_exit_restore(cs, retaddr);
435526b0d36SRichard Henderson     }
436526b0d36SRichard Henderson }
437526b0d36SRichard Henderson 
mb_cpu_transaction_failed(CPUState * cs,hwaddr physaddr,vaddr addr,unsigned size,MMUAccessType access_type,int mmu_idx,MemTxAttrs attrs,MemTxResult response,uintptr_t retaddr)438bdff8123SPeter Maydell void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
439bdff8123SPeter Maydell                                unsigned size, MMUAccessType access_type,
440bdff8123SPeter Maydell                                int mmu_idx, MemTxAttrs attrs,
441bdff8123SPeter Maydell                                MemTxResult response, uintptr_t retaddr)
442faed1c2aSEdgar E. Iglesias {
443526b0d36SRichard Henderson     mb_transaction_failed_internal(cs, physaddr, addr, size,
444526b0d36SRichard Henderson                                    access_type, retaddr);
445faed1c2aSEdgar E. Iglesias }
446*beea7726SRichard Henderson 
447*beea7726SRichard Henderson #define LD_EA(NAME, TYPE, FUNC) \
448*beea7726SRichard Henderson uint32_t HELPER(NAME)(CPUMBState *env, uint64_t ea)                     \
449*beea7726SRichard Henderson {                                                                       \
450*beea7726SRichard Henderson     CPUState *cs = env_cpu(env);                                        \
451*beea7726SRichard Henderson     MemTxResult txres;                                                  \
452*beea7726SRichard Henderson     TYPE ret = FUNC(cs->as, ea, MEMTXATTRS_UNSPECIFIED, &txres);        \
453*beea7726SRichard Henderson     if (unlikely(txres != MEMTX_OK)) {                                  \
454*beea7726SRichard Henderson         mb_transaction_failed_internal(cs, ea, ea, sizeof(TYPE),        \
455*beea7726SRichard Henderson                                        MMU_DATA_LOAD, GETPC());         \
456*beea7726SRichard Henderson     }                                                                   \
457*beea7726SRichard Henderson     return ret;                                                         \
458*beea7726SRichard Henderson }
459*beea7726SRichard Henderson 
460*beea7726SRichard Henderson LD_EA(lbuea, uint8_t, address_space_ldub)
461*beea7726SRichard Henderson LD_EA(lhuea_be, uint16_t, address_space_lduw_be)
462*beea7726SRichard Henderson LD_EA(lhuea_le, uint16_t, address_space_lduw_le)
463*beea7726SRichard Henderson LD_EA(lwea_be, uint32_t, address_space_ldl_be)
464*beea7726SRichard Henderson LD_EA(lwea_le, uint32_t, address_space_ldl_le)
465*beea7726SRichard Henderson 
466*beea7726SRichard Henderson #define ST_EA(NAME, TYPE, FUNC) \
467*beea7726SRichard Henderson void HELPER(NAME)(CPUMBState *env, uint32_t data, uint64_t ea)          \
468*beea7726SRichard Henderson {                                                                       \
469*beea7726SRichard Henderson     CPUState *cs = env_cpu(env);                                        \
470*beea7726SRichard Henderson     MemTxResult txres;                                                  \
471*beea7726SRichard Henderson     FUNC(cs->as, ea, data, MEMTXATTRS_UNSPECIFIED, &txres);             \
472*beea7726SRichard Henderson     if (unlikely(txres != MEMTX_OK)) {                                  \
473*beea7726SRichard Henderson         mb_transaction_failed_internal(cs, ea, ea, sizeof(TYPE),        \
474*beea7726SRichard Henderson                                        MMU_DATA_STORE, GETPC());        \
475*beea7726SRichard Henderson     }                                                                   \
476*beea7726SRichard Henderson }
477*beea7726SRichard Henderson 
478*beea7726SRichard Henderson ST_EA(sbea, uint8_t, address_space_stb)
479*beea7726SRichard Henderson ST_EA(shea_be, uint16_t, address_space_stw_be)
480*beea7726SRichard Henderson ST_EA(shea_le, uint16_t, address_space_stw_le)
481*beea7726SRichard Henderson ST_EA(swea_be, uint32_t, address_space_stl_be)
482*beea7726SRichard Henderson ST_EA(swea_le, uint32_t, address_space_stl_le)
483*beea7726SRichard Henderson 
4843c7b48b7SPaul Brook #endif
485