xref: /qemu/target/microblaze/op_helper.c (revision b2e80a3c191e90dee7ad05df303c237d9819bee4)
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 
294acb54baSEdgar E. Iglesias #define D(x)
304acb54baSEdgar E. Iglesias 
316d76d23eSEdgar E. Iglesias void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
326d76d23eSEdgar E. Iglesias {
336d76d23eSEdgar E. Iglesias     int test = ctrl & STREAM_TEST;
346d76d23eSEdgar E. Iglesias     int atomic = ctrl & STREAM_ATOMIC;
356d76d23eSEdgar E. Iglesias     int control = ctrl & STREAM_CONTROL;
366d76d23eSEdgar E. Iglesias     int nonblock = ctrl & STREAM_NONBLOCK;
376d76d23eSEdgar E. Iglesias     int exception = ctrl & STREAM_EXCEPTION;
386d76d23eSEdgar E. Iglesias 
391d512a65SPaolo Bonzini     qemu_log_mask(LOG_UNIMP, "Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n",
406d76d23eSEdgar E. Iglesias              id, data,
416d76d23eSEdgar E. Iglesias              test ? "t" : "",
426d76d23eSEdgar E. Iglesias              nonblock ? "n" : "",
436d76d23eSEdgar E. Iglesias              exception ? "e" : "",
446d76d23eSEdgar E. Iglesias              control ? "c" : "",
456d76d23eSEdgar E. Iglesias              atomic ? "a" : "");
466d76d23eSEdgar E. Iglesias }
476d76d23eSEdgar E. Iglesias 
486d76d23eSEdgar E. Iglesias uint32_t helper_get(uint32_t id, uint32_t ctrl)
496d76d23eSEdgar E. Iglesias {
506d76d23eSEdgar E. Iglesias     int test = ctrl & STREAM_TEST;
516d76d23eSEdgar E. Iglesias     int atomic = ctrl & STREAM_ATOMIC;
526d76d23eSEdgar E. Iglesias     int control = ctrl & STREAM_CONTROL;
536d76d23eSEdgar E. Iglesias     int nonblock = ctrl & STREAM_NONBLOCK;
546d76d23eSEdgar E. Iglesias     int exception = ctrl & STREAM_EXCEPTION;
556d76d23eSEdgar E. Iglesias 
561d512a65SPaolo Bonzini     qemu_log_mask(LOG_UNIMP, "Unhandled stream get from stream-id=%d %s%s%s%s%s\n",
576d76d23eSEdgar E. Iglesias              id,
586d76d23eSEdgar E. Iglesias              test ? "t" : "",
596d76d23eSEdgar E. Iglesias              nonblock ? "n" : "",
606d76d23eSEdgar E. Iglesias              exception ? "e" : "",
616d76d23eSEdgar E. Iglesias              control ? "c" : "",
626d76d23eSEdgar E. Iglesias              atomic ? "a" : "");
636d76d23eSEdgar E. Iglesias     return 0xdead0000 | id;
646d76d23eSEdgar E. Iglesias }
656d76d23eSEdgar E. Iglesias 
6664254ebaSBlue Swirl void helper_raise_exception(CPUMBState *env, uint32_t index)
674acb54baSEdgar E. Iglesias {
68f5c7e93aSRichard Henderson     CPUState *cs = env_cpu(env);
6927103424SAndreas Färber 
7027103424SAndreas Färber     cs->exception_index = index;
715638d180SAndreas Färber     cpu_loop_exit(cs);
724acb54baSEdgar E. Iglesias }
734acb54baSEdgar E. Iglesias 
7464254ebaSBlue Swirl void helper_debug(CPUMBState *env)
754acb54baSEdgar E. Iglesias {
764acb54baSEdgar E. Iglesias     int i;
774acb54baSEdgar E. Iglesias 
7876e8187dSRichard Henderson     qemu_log("PC=%" PRIx64 "\n", env->pc);
790a22f8cfSEdgar E. Iglesias     qemu_log("rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " "
800a22f8cfSEdgar E. Iglesias              "debug[%x] imm=%x iflags=%x\n",
81*b2e80a3cSRichard Henderson              env->msr, env->sregs[SR_ESR], env->ear,
8217c52a43SEdgar E. Iglesias              env->debug, env->imm, env->iflags);
8343d318b2SEdgar E. Iglesias     qemu_log("btaken=%d btarget=%" PRIx64 " mode=%s(saved=%s) eip=%d ie=%d\n",
8417c52a43SEdgar E. Iglesias              env->btaken, env->btarget,
852e5282caSRichard Henderson              (env->msr & MSR_UM) ? "user" : "kernel",
862e5282caSRichard Henderson              (env->msr & MSR_UMS) ? "user" : "kernel",
872e5282caSRichard Henderson              (bool)(env->msr & MSR_EIP),
882e5282caSRichard Henderson              (bool)(env->msr & MSR_IE));
894acb54baSEdgar E. Iglesias     for (i = 0; i < 32; i++) {
904acb54baSEdgar E. Iglesias         qemu_log("r%2.2d=%8.8x ", i, env->regs[i]);
914acb54baSEdgar E. Iglesias         if ((i + 1) % 4 == 0)
924acb54baSEdgar E. Iglesias             qemu_log("\n");
934acb54baSEdgar E. Iglesias     }
944acb54baSEdgar E. Iglesias     qemu_log("\n\n");
954acb54baSEdgar E. Iglesias }
964acb54baSEdgar E. Iglesias 
974acb54baSEdgar E. Iglesias static inline uint32_t compute_carry(uint32_t a, uint32_t b, uint32_t cin)
984acb54baSEdgar E. Iglesias {
994acb54baSEdgar E. Iglesias     uint32_t cout = 0;
1004acb54baSEdgar E. Iglesias 
1014acb54baSEdgar E. Iglesias     if ((b == ~0) && cin)
1024acb54baSEdgar E. Iglesias         cout = 1;
1034acb54baSEdgar E. Iglesias     else if ((~0 - a) < (b + cin))
1044acb54baSEdgar E. Iglesias         cout = 1;
1054acb54baSEdgar E. Iglesias     return cout;
1064acb54baSEdgar E. Iglesias }
1074acb54baSEdgar E. Iglesias 
1084acb54baSEdgar E. Iglesias uint32_t helper_cmp(uint32_t a, uint32_t b)
1094acb54baSEdgar E. Iglesias {
1104acb54baSEdgar E. Iglesias     uint32_t t;
1114acb54baSEdgar E. Iglesias 
1124acb54baSEdgar E. Iglesias     t = b + ~a + 1;
1134acb54baSEdgar E. Iglesias     if ((b & 0x80000000) ^ (a & 0x80000000))
1144acb54baSEdgar E. Iglesias         t = (t & 0x7fffffff) | (b & 0x80000000);
1154acb54baSEdgar E. Iglesias     return t;
1164acb54baSEdgar E. Iglesias }
1174acb54baSEdgar E. Iglesias 
1184acb54baSEdgar E. Iglesias uint32_t helper_cmpu(uint32_t a, uint32_t b)
1194acb54baSEdgar E. Iglesias {
1204acb54baSEdgar E. Iglesias     uint32_t t;
1214acb54baSEdgar E. Iglesias 
1224acb54baSEdgar E. Iglesias     t = b + ~a + 1;
1234acb54baSEdgar E. Iglesias     if ((b & 0x80000000) ^ (a & 0x80000000))
1244acb54baSEdgar E. Iglesias         t = (t & 0x7fffffff) | (a & 0x80000000);
1254acb54baSEdgar E. Iglesias     return t;
1264acb54baSEdgar E. Iglesias }
1274acb54baSEdgar E. Iglesias 
1285d0bb823SEdgar E. Iglesias uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf)
1294acb54baSEdgar E. Iglesias {
130738c8b01SShraddha Barke     return compute_carry(a, b, cf);
1314acb54baSEdgar E. Iglesias }
1324acb54baSEdgar E. Iglesias 
13364254ebaSBlue Swirl static inline int div_prepare(CPUMBState *env, uint32_t a, uint32_t b)
1344acb54baSEdgar E. Iglesias {
135622cc730SEdgar E. Iglesias     MicroBlazeCPU *cpu = env_archcpu(env);
136622cc730SEdgar E. Iglesias 
1374acb54baSEdgar E. Iglesias     if (b == 0) {
1382e5282caSRichard Henderson         env->msr |= MSR_DZ;
139821ebb33SEdgar E. Iglesias 
1402e5282caSRichard Henderson         if ((env->msr & MSR_EE) && cpu->cfg.div_zero_exception) {
141821ebb33SEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_DIVZERO;
14264254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
143821ebb33SEdgar E. Iglesias         }
1444acb54baSEdgar E. Iglesias         return 0;
1454acb54baSEdgar E. Iglesias     }
1462e5282caSRichard Henderson     env->msr &= ~MSR_DZ;
1474acb54baSEdgar E. Iglesias     return 1;
1484acb54baSEdgar E. Iglesias }
1494acb54baSEdgar E. Iglesias 
15064254ebaSBlue Swirl uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
1514acb54baSEdgar E. Iglesias {
15264254ebaSBlue Swirl     if (!div_prepare(env, a, b)) {
1534acb54baSEdgar E. Iglesias         return 0;
15464254ebaSBlue Swirl     }
1554acb54baSEdgar E. Iglesias     return (int32_t)a / (int32_t)b;
1564acb54baSEdgar E. Iglesias }
1574acb54baSEdgar E. Iglesias 
15864254ebaSBlue Swirl uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
1594acb54baSEdgar E. Iglesias {
16064254ebaSBlue Swirl     if (!div_prepare(env, a, b)) {
1614acb54baSEdgar E. Iglesias         return 0;
16264254ebaSBlue Swirl     }
1634acb54baSEdgar E. Iglesias     return a / b;
1644acb54baSEdgar E. Iglesias }
1654acb54baSEdgar E. Iglesias 
16697694c57SEdgar E. Iglesias /* raise FPU exception.  */
16764254ebaSBlue Swirl static void raise_fpu_exception(CPUMBState *env)
16897694c57SEdgar E. Iglesias {
16997694c57SEdgar E. Iglesias     env->sregs[SR_ESR] = ESR_EC_FPU;
17064254ebaSBlue Swirl     helper_raise_exception(env, EXCP_HW_EXCP);
17197694c57SEdgar E. Iglesias }
17297694c57SEdgar E. Iglesias 
17364254ebaSBlue Swirl static void update_fpu_flags(CPUMBState *env, int flags)
17497694c57SEdgar E. Iglesias {
17597694c57SEdgar E. Iglesias     int raise = 0;
17697694c57SEdgar E. Iglesias 
17797694c57SEdgar E. Iglesias     if (flags & float_flag_invalid) {
17897694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_IO;
17997694c57SEdgar E. Iglesias         raise = 1;
18097694c57SEdgar E. Iglesias     }
18197694c57SEdgar E. Iglesias     if (flags & float_flag_divbyzero) {
18297694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_DZ;
18397694c57SEdgar E. Iglesias         raise = 1;
18497694c57SEdgar E. Iglesias     }
18597694c57SEdgar E. Iglesias     if (flags & float_flag_overflow) {
18697694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_OF;
18797694c57SEdgar E. Iglesias         raise = 1;
18897694c57SEdgar E. Iglesias     }
18997694c57SEdgar E. Iglesias     if (flags & float_flag_underflow) {
19097694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_UF;
19197694c57SEdgar E. Iglesias         raise = 1;
19297694c57SEdgar E. Iglesias     }
19397694c57SEdgar E. Iglesias     if (raise
19497694c57SEdgar E. Iglesias         && (env->pvr.regs[2] & PVR2_FPU_EXC_MASK)
1952e5282caSRichard Henderson         && (env->msr & MSR_EE)) {
19664254ebaSBlue Swirl         raise_fpu_exception(env);
19797694c57SEdgar E. Iglesias     }
19897694c57SEdgar E. Iglesias }
19997694c57SEdgar E. Iglesias 
20064254ebaSBlue Swirl uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
20197694c57SEdgar E. Iglesias {
20297694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
20397694c57SEdgar E. Iglesias     int flags;
20497694c57SEdgar E. Iglesias 
20597694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
20697694c57SEdgar E. Iglesias     fa.l = a;
20797694c57SEdgar E. Iglesias     fb.l = b;
20897694c57SEdgar E. Iglesias     fd.f = float32_add(fa.f, fb.f, &env->fp_status);
20997694c57SEdgar E. Iglesias 
21097694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
21164254ebaSBlue Swirl     update_fpu_flags(env, flags);
21297694c57SEdgar E. Iglesias     return fd.l;
21397694c57SEdgar E. Iglesias }
21497694c57SEdgar E. Iglesias 
21564254ebaSBlue Swirl uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
21697694c57SEdgar E. Iglesias {
21797694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
21897694c57SEdgar E. Iglesias     int flags;
21997694c57SEdgar E. Iglesias 
22097694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
22197694c57SEdgar E. Iglesias     fa.l = a;
22297694c57SEdgar E. Iglesias     fb.l = b;
22397694c57SEdgar E. Iglesias     fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
22497694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
22564254ebaSBlue Swirl     update_fpu_flags(env, flags);
22697694c57SEdgar E. Iglesias     return fd.l;
22797694c57SEdgar E. Iglesias }
22897694c57SEdgar E. Iglesias 
22964254ebaSBlue Swirl uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
23097694c57SEdgar E. Iglesias {
23197694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
23297694c57SEdgar E. Iglesias     int flags;
23397694c57SEdgar E. Iglesias 
23497694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
23597694c57SEdgar E. Iglesias     fa.l = a;
23697694c57SEdgar E. Iglesias     fb.l = b;
23797694c57SEdgar E. Iglesias     fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
23897694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
23964254ebaSBlue Swirl     update_fpu_flags(env, flags);
24097694c57SEdgar E. Iglesias 
24197694c57SEdgar E. Iglesias     return fd.l;
24297694c57SEdgar E. Iglesias }
24397694c57SEdgar E. Iglesias 
24464254ebaSBlue Swirl uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
24597694c57SEdgar E. Iglesias {
24697694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
24797694c57SEdgar E. Iglesias     int flags;
24897694c57SEdgar E. Iglesias 
24997694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
25097694c57SEdgar E. Iglesias     fa.l = a;
25197694c57SEdgar E. Iglesias     fb.l = b;
25297694c57SEdgar E. Iglesias     fd.f = float32_div(fb.f, fa.f, &env->fp_status);
25397694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
25464254ebaSBlue Swirl     update_fpu_flags(env, flags);
25597694c57SEdgar E. Iglesias 
25697694c57SEdgar E. Iglesias     return fd.l;
25797694c57SEdgar E. Iglesias }
25897694c57SEdgar E. Iglesias 
25964254ebaSBlue Swirl uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
26097694c57SEdgar E. Iglesias {
261ef9d48daSEdgar E. Iglesias     CPU_FloatU fa, fb;
262ef9d48daSEdgar E. Iglesias     uint32_t r = 0;
263ef9d48daSEdgar E. Iglesias 
264ef9d48daSEdgar E. Iglesias     fa.l = a;
265ef9d48daSEdgar E. Iglesias     fb.l = b;
266ef9d48daSEdgar E. Iglesias 
267af39bc8cSAleksandar Markovic     if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
268af39bc8cSAleksandar Markovic         float32_is_signaling_nan(fb.f, &env->fp_status)) {
26964254ebaSBlue Swirl         update_fpu_flags(env, float_flag_invalid);
270ef9d48daSEdgar E. Iglesias         r = 1;
271ef9d48daSEdgar E. Iglesias     }
272ef9d48daSEdgar E. Iglesias 
273af39bc8cSAleksandar Markovic     if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
274af39bc8cSAleksandar Markovic         float32_is_quiet_nan(fb.f, &env->fp_status)) {
275ef9d48daSEdgar E. Iglesias         r = 1;
276ef9d48daSEdgar E. Iglesias     }
277ef9d48daSEdgar E. Iglesias 
278ef9d48daSEdgar E. Iglesias     return r;
27997694c57SEdgar E. Iglesias }
28097694c57SEdgar E. Iglesias 
28164254ebaSBlue Swirl uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
28297694c57SEdgar E. Iglesias {
28397694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
28497694c57SEdgar E. Iglesias     int r;
28597694c57SEdgar E. Iglesias     int flags;
28697694c57SEdgar E. Iglesias 
28797694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
28897694c57SEdgar E. Iglesias     fa.l = a;
28997694c57SEdgar E. Iglesias     fb.l = b;
29097694c57SEdgar E. Iglesias     r = float32_lt(fb.f, fa.f, &env->fp_status);
29197694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
29264254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
29397694c57SEdgar E. Iglesias 
29497694c57SEdgar E. Iglesias     return r;
29597694c57SEdgar E. Iglesias }
29697694c57SEdgar E. Iglesias 
29764254ebaSBlue Swirl uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
29897694c57SEdgar E. Iglesias {
29997694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
30097694c57SEdgar E. Iglesias     int flags;
30197694c57SEdgar E. Iglesias     int r;
30297694c57SEdgar E. Iglesias 
30397694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
30497694c57SEdgar E. Iglesias     fa.l = a;
30597694c57SEdgar E. Iglesias     fb.l = b;
306211315fbSAurelien Jarno     r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
30797694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
30864254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
30997694c57SEdgar E. Iglesias 
31097694c57SEdgar E. Iglesias     return r;
31197694c57SEdgar E. Iglesias }
31297694c57SEdgar E. Iglesias 
31364254ebaSBlue Swirl uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
31497694c57SEdgar E. Iglesias {
31597694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
31697694c57SEdgar E. Iglesias     int flags;
31797694c57SEdgar E. Iglesias     int r;
31897694c57SEdgar E. Iglesias 
31997694c57SEdgar E. Iglesias     fa.l = a;
32097694c57SEdgar E. Iglesias     fb.l = b;
32197694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
32297694c57SEdgar E. Iglesias     r = float32_le(fa.f, fb.f, &env->fp_status);
32397694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
32464254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
32597694c57SEdgar E. Iglesias 
32697694c57SEdgar E. Iglesias 
32797694c57SEdgar E. Iglesias     return r;
32897694c57SEdgar E. Iglesias }
32997694c57SEdgar E. Iglesias 
33064254ebaSBlue Swirl uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
33197694c57SEdgar E. Iglesias {
33297694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
33397694c57SEdgar E. Iglesias     int flags, r;
33497694c57SEdgar E. Iglesias 
33597694c57SEdgar E. Iglesias     fa.l = a;
33697694c57SEdgar E. Iglesias     fb.l = b;
33797694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
33897694c57SEdgar E. Iglesias     r = float32_lt(fa.f, fb.f, &env->fp_status);
33997694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
34064254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
34197694c57SEdgar E. Iglesias     return r;
34297694c57SEdgar E. Iglesias }
34397694c57SEdgar E. Iglesias 
34464254ebaSBlue Swirl uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
34597694c57SEdgar E. Iglesias {
34697694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
34797694c57SEdgar E. Iglesias     int flags, r;
34897694c57SEdgar E. Iglesias 
34997694c57SEdgar E. Iglesias     fa.l = a;
35097694c57SEdgar E. Iglesias     fb.l = b;
35197694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
352211315fbSAurelien Jarno     r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
35397694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
35464254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
35597694c57SEdgar E. Iglesias 
35697694c57SEdgar E. Iglesias     return r;
35797694c57SEdgar E. Iglesias }
35897694c57SEdgar E. Iglesias 
35964254ebaSBlue Swirl uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
36097694c57SEdgar E. Iglesias {
36197694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
36297694c57SEdgar E. Iglesias     int flags, r;
36397694c57SEdgar E. Iglesias 
36497694c57SEdgar E. Iglesias     fa.l = a;
36597694c57SEdgar E. Iglesias     fb.l = b;
36697694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
36797694c57SEdgar E. Iglesias     r = !float32_lt(fa.f, fb.f, &env->fp_status);
36897694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
36964254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
37097694c57SEdgar E. Iglesias 
37197694c57SEdgar E. Iglesias     return r;
37297694c57SEdgar E. Iglesias }
37397694c57SEdgar E. Iglesias 
37464254ebaSBlue Swirl uint32_t helper_flt(CPUMBState *env, uint32_t a)
37597694c57SEdgar E. Iglesias {
37697694c57SEdgar E. Iglesias     CPU_FloatU fd, fa;
37797694c57SEdgar E. Iglesias 
37897694c57SEdgar E. Iglesias     fa.l = a;
37997694c57SEdgar E. Iglesias     fd.f = int32_to_float32(fa.l, &env->fp_status);
38097694c57SEdgar E. Iglesias     return fd.l;
38197694c57SEdgar E. Iglesias }
38297694c57SEdgar E. Iglesias 
38364254ebaSBlue Swirl uint32_t helper_fint(CPUMBState *env, uint32_t a)
38497694c57SEdgar E. Iglesias {
38597694c57SEdgar E. Iglesias     CPU_FloatU fa;
38697694c57SEdgar E. Iglesias     uint32_t r;
38797694c57SEdgar E. Iglesias     int flags;
38897694c57SEdgar E. Iglesias 
38997694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
39097694c57SEdgar E. Iglesias     fa.l = a;
39197694c57SEdgar E. Iglesias     r = float32_to_int32(fa.f, &env->fp_status);
39297694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
39364254ebaSBlue Swirl     update_fpu_flags(env, flags);
39497694c57SEdgar E. Iglesias 
39597694c57SEdgar E. Iglesias     return r;
39697694c57SEdgar E. Iglesias }
39797694c57SEdgar E. Iglesias 
39864254ebaSBlue Swirl uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
39997694c57SEdgar E. Iglesias {
40097694c57SEdgar E. Iglesias     CPU_FloatU fd, fa;
40197694c57SEdgar E. Iglesias     int flags;
40297694c57SEdgar E. Iglesias 
40397694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
40497694c57SEdgar E. Iglesias     fa.l = a;
40597694c57SEdgar E. Iglesias     fd.l = float32_sqrt(fa.f, &env->fp_status);
40697694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
40764254ebaSBlue Swirl     update_fpu_flags(env, flags);
40897694c57SEdgar E. Iglesias 
40997694c57SEdgar E. Iglesias     return fd.l;
41097694c57SEdgar E. Iglesias }
41197694c57SEdgar E. Iglesias 
4124acb54baSEdgar E. Iglesias uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
4134acb54baSEdgar E. Iglesias {
4144acb54baSEdgar E. Iglesias     unsigned int i;
4154acb54baSEdgar E. Iglesias     uint32_t mask = 0xff000000;
4164acb54baSEdgar E. Iglesias 
4174acb54baSEdgar E. Iglesias     for (i = 0; i < 4; i++) {
4184acb54baSEdgar E. Iglesias         if ((a & mask) == (b & mask))
4194acb54baSEdgar E. Iglesias             return i + 1;
4204acb54baSEdgar E. Iglesias         mask >>= 8;
4214acb54baSEdgar E. Iglesias     }
4224acb54baSEdgar E. Iglesias     return 0;
4234acb54baSEdgar E. Iglesias }
4244acb54baSEdgar E. Iglesias 
425403322eaSEdgar E. Iglesias void helper_memalign(CPUMBState *env, target_ulong addr,
426403322eaSEdgar E. Iglesias                      uint32_t dr, uint32_t wr,
42764254ebaSBlue Swirl                      uint32_t mask)
428968a40f6SEdgar E. Iglesias {
429968a40f6SEdgar E. Iglesias     if (addr & mask) {
43097f90cbfSEdgar E. Iglesias             qemu_log_mask(CPU_LOG_INT,
431403322eaSEdgar E. Iglesias                           "unaligned access addr=" TARGET_FMT_lx
432403322eaSEdgar E. Iglesias                           " mask=%x, wr=%d dr=r%d\n",
43397f90cbfSEdgar E. Iglesias                           addr, mask, wr, dr);
434*b2e80a3cSRichard Henderson             env->ear = addr;
435968a40f6SEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \
436968a40f6SEdgar E. Iglesias                                  | (dr & 31) << 5;
4373aa80988SEdgar E. Iglesias             if (mask == 3) {
438968a40f6SEdgar E. Iglesias                 env->sregs[SR_ESR] |= 1 << 11;
439968a40f6SEdgar E. Iglesias             }
4402e5282caSRichard Henderson             if (!(env->msr & MSR_EE)) {
44197f90cbfSEdgar E. Iglesias                 return;
44297f90cbfSEdgar E. Iglesias             }
44364254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
444968a40f6SEdgar E. Iglesias     }
445968a40f6SEdgar E. Iglesias }
446968a40f6SEdgar E. Iglesias 
447403322eaSEdgar E. Iglesias void helper_stackprot(CPUMBState *env, target_ulong addr)
4485818dee5SEdgar E. Iglesias {
4495818dee5SEdgar E. Iglesias     if (addr < env->slr || addr > env->shr) {
450403322eaSEdgar E. Iglesias         qemu_log_mask(CPU_LOG_INT, "Stack protector violation at "
451403322eaSEdgar E. Iglesias                       TARGET_FMT_lx " %x %x\n",
4525818dee5SEdgar E. Iglesias                       addr, env->slr, env->shr);
453*b2e80a3cSRichard Henderson         env->ear = addr;
4545818dee5SEdgar E. Iglesias         env->sregs[SR_ESR] = ESR_EC_STACKPROT;
45564254ebaSBlue Swirl         helper_raise_exception(env, EXCP_HW_EXCP);
4565818dee5SEdgar E. Iglesias     }
4575818dee5SEdgar E. Iglesias }
4585818dee5SEdgar E. Iglesias 
4594acb54baSEdgar E. Iglesias #if !defined(CONFIG_USER_ONLY)
4604acb54baSEdgar E. Iglesias /* Writes/reads to the MMU's special regs end up here.  */
461f0f7e7f7SEdgar E. Iglesias uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn)
4624acb54baSEdgar E. Iglesias {
463f0f7e7f7SEdgar E. Iglesias     return mmu_read(env, ext, rn);
4644acb54baSEdgar E. Iglesias }
4654acb54baSEdgar E. Iglesias 
466f0f7e7f7SEdgar E. Iglesias void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v)
4674acb54baSEdgar E. Iglesias {
468f0f7e7f7SEdgar E. Iglesias     mmu_write(env, ext, rn, v);
4694acb54baSEdgar E. Iglesias }
470faed1c2aSEdgar E. Iglesias 
471bdff8123SPeter Maydell void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
472bdff8123SPeter Maydell                                unsigned size, MMUAccessType access_type,
473bdff8123SPeter Maydell                                int mmu_idx, MemTxAttrs attrs,
474bdff8123SPeter Maydell                                MemTxResult response, uintptr_t retaddr)
475faed1c2aSEdgar E. Iglesias {
476c658b94fSAndreas Färber     MicroBlazeCPU *cpu;
477c658b94fSAndreas Färber     CPUMBState *env;
478bdff8123SPeter Maydell     qemu_log_mask(CPU_LOG_INT, "Transaction failed: vaddr 0x%" VADDR_PRIx
479bdff8123SPeter Maydell                   " physaddr 0x" TARGET_FMT_plx " size %d access type %s\n",
480bdff8123SPeter Maydell                   addr, physaddr, size,
481bdff8123SPeter Maydell                   access_type == MMU_INST_FETCH ? "INST_FETCH" :
482bdff8123SPeter Maydell                   (access_type == MMU_DATA_LOAD ? "DATA_LOAD" : "DATA_STORE"));
483c658b94fSAndreas Färber     cpu = MICROBLAZE_CPU(cs);
484c658b94fSAndreas Färber     env = &cpu->env;
485bdff8123SPeter Maydell 
486bdff8123SPeter Maydell     cpu_restore_state(cs, retaddr, true);
4872e5282caSRichard Henderson     if (!(env->msr & MSR_EE)) {
488faed1c2aSEdgar E. Iglesias         return;
489faed1c2aSEdgar E. Iglesias     }
490faed1c2aSEdgar E. Iglesias 
491*b2e80a3cSRichard Henderson     env->ear = addr;
492bdff8123SPeter Maydell     if (access_type == MMU_INST_FETCH) {
49397f90cbfSEdgar E. Iglesias         if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) {
494faed1c2aSEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_INSN_BUS;
49564254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
496faed1c2aSEdgar E. Iglesias         }
497faed1c2aSEdgar E. Iglesias     } else {
49897f90cbfSEdgar E. Iglesias         if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) {
499faed1c2aSEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_DATA_BUS;
50064254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
501faed1c2aSEdgar E. Iglesias         }
502faed1c2aSEdgar E. Iglesias     }
503faed1c2aSEdgar E. Iglesias }
5043c7b48b7SPaul Brook #endif
505