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