xref: /qemu/target/microblaze/op_helper.c (revision f0f7e7f7b284f536389a3c5b67de681055325317)
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 
314acb54baSEdgar E. Iglesias #if !defined(CONFIG_USER_ONLY)
323e457172SBlue Swirl 
334acb54baSEdgar E. Iglesias /* Try to fill the TLB and return an exception if error. If retaddr is
34d5a11fefSAndreas Färber  * NULL, it means that the function was called in C code (i.e. not
35d5a11fefSAndreas Färber  * from generated code or from helper.c)
36d5a11fefSAndreas Färber  */
3798670d47SLaurent Vivier void tlb_fill(CPUState *cs, target_ulong addr, int size,
3898670d47SLaurent Vivier               MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
394acb54baSEdgar E. Iglesias {
404acb54baSEdgar E. Iglesias     int ret;
414acb54baSEdgar E. Iglesias 
4298670d47SLaurent Vivier     ret = mb_cpu_handle_mmu_fault(cs, addr, size, access_type, mmu_idx);
434acb54baSEdgar E. Iglesias     if (unlikely(ret)) {
444acb54baSEdgar E. Iglesias         /* now we have a real cpu fault */
4565255e8eSAlex Bennée         cpu_loop_exit_restore(cs, retaddr);
464acb54baSEdgar E. Iglesias     }
474acb54baSEdgar E. Iglesias }
484acb54baSEdgar E. Iglesias #endif
494acb54baSEdgar E. Iglesias 
506d76d23eSEdgar E. Iglesias void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
516d76d23eSEdgar E. Iglesias {
526d76d23eSEdgar E. Iglesias     int test = ctrl & STREAM_TEST;
536d76d23eSEdgar E. Iglesias     int atomic = ctrl & STREAM_ATOMIC;
546d76d23eSEdgar E. Iglesias     int control = ctrl & STREAM_CONTROL;
556d76d23eSEdgar E. Iglesias     int nonblock = ctrl & STREAM_NONBLOCK;
566d76d23eSEdgar E. Iglesias     int exception = ctrl & STREAM_EXCEPTION;
576d76d23eSEdgar E. Iglesias 
581d512a65SPaolo Bonzini     qemu_log_mask(LOG_UNIMP, "Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n",
596d76d23eSEdgar E. Iglesias              id, data,
606d76d23eSEdgar E. Iglesias              test ? "t" : "",
616d76d23eSEdgar E. Iglesias              nonblock ? "n" : "",
626d76d23eSEdgar E. Iglesias              exception ? "e" : "",
636d76d23eSEdgar E. Iglesias              control ? "c" : "",
646d76d23eSEdgar E. Iglesias              atomic ? "a" : "");
656d76d23eSEdgar E. Iglesias }
666d76d23eSEdgar E. Iglesias 
676d76d23eSEdgar E. Iglesias uint32_t helper_get(uint32_t id, uint32_t ctrl)
686d76d23eSEdgar E. Iglesias {
696d76d23eSEdgar E. Iglesias     int test = ctrl & STREAM_TEST;
706d76d23eSEdgar E. Iglesias     int atomic = ctrl & STREAM_ATOMIC;
716d76d23eSEdgar E. Iglesias     int control = ctrl & STREAM_CONTROL;
726d76d23eSEdgar E. Iglesias     int nonblock = ctrl & STREAM_NONBLOCK;
736d76d23eSEdgar E. Iglesias     int exception = ctrl & STREAM_EXCEPTION;
746d76d23eSEdgar E. Iglesias 
751d512a65SPaolo Bonzini     qemu_log_mask(LOG_UNIMP, "Unhandled stream get from stream-id=%d %s%s%s%s%s\n",
766d76d23eSEdgar E. Iglesias              id,
776d76d23eSEdgar E. Iglesias              test ? "t" : "",
786d76d23eSEdgar E. Iglesias              nonblock ? "n" : "",
796d76d23eSEdgar E. Iglesias              exception ? "e" : "",
806d76d23eSEdgar E. Iglesias              control ? "c" : "",
816d76d23eSEdgar E. Iglesias              atomic ? "a" : "");
826d76d23eSEdgar E. Iglesias     return 0xdead0000 | id;
836d76d23eSEdgar E. Iglesias }
846d76d23eSEdgar E. Iglesias 
8564254ebaSBlue Swirl void helper_raise_exception(CPUMBState *env, uint32_t index)
864acb54baSEdgar E. Iglesias {
8727103424SAndreas Färber     CPUState *cs = CPU(mb_env_get_cpu(env));
8827103424SAndreas Färber 
8927103424SAndreas Färber     cs->exception_index = index;
905638d180SAndreas Färber     cpu_loop_exit(cs);
914acb54baSEdgar E. Iglesias }
924acb54baSEdgar E. Iglesias 
9364254ebaSBlue Swirl void helper_debug(CPUMBState *env)
944acb54baSEdgar E. Iglesias {
954acb54baSEdgar E. Iglesias     int i;
964acb54baSEdgar E. Iglesias 
970a22f8cfSEdgar E. Iglesias     qemu_log("PC=%" PRIx64 "\n", env->sregs[SR_PC]);
980a22f8cfSEdgar E. Iglesias     qemu_log("rmsr=%" PRIx64 " resr=%" PRIx64 " rear=%" PRIx64 " "
990a22f8cfSEdgar E. Iglesias              "debug[%x] imm=%x iflags=%x\n",
1004c24aa0aSMichal Simek              env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
10117c52a43SEdgar E. Iglesias              env->debug, env->imm, env->iflags);
10217c52a43SEdgar E. Iglesias     qemu_log("btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
10317c52a43SEdgar E. Iglesias              env->btaken, env->btarget,
10417c52a43SEdgar E. Iglesias              (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
10517c52a43SEdgar E. Iglesias              (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
1060a22f8cfSEdgar E. Iglesias              (bool)(env->sregs[SR_MSR] & MSR_EIP),
1070a22f8cfSEdgar E. Iglesias              (bool)(env->sregs[SR_MSR] & MSR_IE));
1084acb54baSEdgar E. Iglesias     for (i = 0; i < 32; i++) {
1094acb54baSEdgar E. Iglesias         qemu_log("r%2.2d=%8.8x ", i, env->regs[i]);
1104acb54baSEdgar E. Iglesias         if ((i + 1) % 4 == 0)
1114acb54baSEdgar E. Iglesias             qemu_log("\n");
1124acb54baSEdgar E. Iglesias     }
1134acb54baSEdgar E. Iglesias     qemu_log("\n\n");
1144acb54baSEdgar E. Iglesias }
1154acb54baSEdgar E. Iglesias 
1164acb54baSEdgar E. Iglesias static inline uint32_t compute_carry(uint32_t a, uint32_t b, uint32_t cin)
1174acb54baSEdgar E. Iglesias {
1184acb54baSEdgar E. Iglesias     uint32_t cout = 0;
1194acb54baSEdgar E. Iglesias 
1204acb54baSEdgar E. Iglesias     if ((b == ~0) && cin)
1214acb54baSEdgar E. Iglesias         cout = 1;
1224acb54baSEdgar E. Iglesias     else if ((~0 - a) < (b + cin))
1234acb54baSEdgar E. Iglesias         cout = 1;
1244acb54baSEdgar E. Iglesias     return cout;
1254acb54baSEdgar E. Iglesias }
1264acb54baSEdgar E. Iglesias 
1274acb54baSEdgar E. Iglesias uint32_t helper_cmp(uint32_t a, uint32_t b)
1284acb54baSEdgar E. Iglesias {
1294acb54baSEdgar E. Iglesias     uint32_t t;
1304acb54baSEdgar E. Iglesias 
1314acb54baSEdgar E. Iglesias     t = b + ~a + 1;
1324acb54baSEdgar E. Iglesias     if ((b & 0x80000000) ^ (a & 0x80000000))
1334acb54baSEdgar E. Iglesias         t = (t & 0x7fffffff) | (b & 0x80000000);
1344acb54baSEdgar E. Iglesias     return t;
1354acb54baSEdgar E. Iglesias }
1364acb54baSEdgar E. Iglesias 
1374acb54baSEdgar E. Iglesias uint32_t helper_cmpu(uint32_t a, uint32_t b)
1384acb54baSEdgar E. Iglesias {
1394acb54baSEdgar E. Iglesias     uint32_t t;
1404acb54baSEdgar E. Iglesias 
1414acb54baSEdgar E. Iglesias     t = b + ~a + 1;
1424acb54baSEdgar E. Iglesias     if ((b & 0x80000000) ^ (a & 0x80000000))
1434acb54baSEdgar E. Iglesias         t = (t & 0x7fffffff) | (a & 0x80000000);
1444acb54baSEdgar E. Iglesias     return t;
1454acb54baSEdgar E. Iglesias }
1464acb54baSEdgar E. Iglesias 
1475d0bb823SEdgar E. Iglesias uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf)
1484acb54baSEdgar E. Iglesias {
149738c8b01SShraddha Barke     return compute_carry(a, b, cf);
1504acb54baSEdgar E. Iglesias }
1514acb54baSEdgar E. Iglesias 
15264254ebaSBlue Swirl static inline int div_prepare(CPUMBState *env, uint32_t a, uint32_t b)
1534acb54baSEdgar E. Iglesias {
1544acb54baSEdgar E. Iglesias     if (b == 0) {
1554acb54baSEdgar E. Iglesias         env->sregs[SR_MSR] |= MSR_DZ;
156821ebb33SEdgar E. Iglesias 
157821ebb33SEdgar E. Iglesias         if ((env->sregs[SR_MSR] & MSR_EE)
158821ebb33SEdgar E. Iglesias             && !(env->pvr.regs[2] & PVR2_DIV_ZERO_EXC_MASK)) {
159821ebb33SEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_DIVZERO;
16064254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
161821ebb33SEdgar E. Iglesias         }
1624acb54baSEdgar E. Iglesias         return 0;
1634acb54baSEdgar E. Iglesias     }
1644acb54baSEdgar E. Iglesias     env->sregs[SR_MSR] &= ~MSR_DZ;
1654acb54baSEdgar E. Iglesias     return 1;
1664acb54baSEdgar E. Iglesias }
1674acb54baSEdgar E. Iglesias 
16864254ebaSBlue Swirl uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
1694acb54baSEdgar E. Iglesias {
17064254ebaSBlue Swirl     if (!div_prepare(env, a, b)) {
1714acb54baSEdgar E. Iglesias         return 0;
17264254ebaSBlue Swirl     }
1734acb54baSEdgar E. Iglesias     return (int32_t)a / (int32_t)b;
1744acb54baSEdgar E. Iglesias }
1754acb54baSEdgar E. Iglesias 
17664254ebaSBlue Swirl uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
1774acb54baSEdgar E. Iglesias {
17864254ebaSBlue Swirl     if (!div_prepare(env, a, b)) {
1794acb54baSEdgar E. Iglesias         return 0;
18064254ebaSBlue Swirl     }
1814acb54baSEdgar E. Iglesias     return a / b;
1824acb54baSEdgar E. Iglesias }
1834acb54baSEdgar E. Iglesias 
18497694c57SEdgar E. Iglesias /* raise FPU exception.  */
18564254ebaSBlue Swirl static void raise_fpu_exception(CPUMBState *env)
18697694c57SEdgar E. Iglesias {
18797694c57SEdgar E. Iglesias     env->sregs[SR_ESR] = ESR_EC_FPU;
18864254ebaSBlue Swirl     helper_raise_exception(env, EXCP_HW_EXCP);
18997694c57SEdgar E. Iglesias }
19097694c57SEdgar E. Iglesias 
19164254ebaSBlue Swirl static void update_fpu_flags(CPUMBState *env, int flags)
19297694c57SEdgar E. Iglesias {
19397694c57SEdgar E. Iglesias     int raise = 0;
19497694c57SEdgar E. Iglesias 
19597694c57SEdgar E. Iglesias     if (flags & float_flag_invalid) {
19697694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_IO;
19797694c57SEdgar E. Iglesias         raise = 1;
19897694c57SEdgar E. Iglesias     }
19997694c57SEdgar E. Iglesias     if (flags & float_flag_divbyzero) {
20097694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_DZ;
20197694c57SEdgar E. Iglesias         raise = 1;
20297694c57SEdgar E. Iglesias     }
20397694c57SEdgar E. Iglesias     if (flags & float_flag_overflow) {
20497694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_OF;
20597694c57SEdgar E. Iglesias         raise = 1;
20697694c57SEdgar E. Iglesias     }
20797694c57SEdgar E. Iglesias     if (flags & float_flag_underflow) {
20897694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_UF;
20997694c57SEdgar E. Iglesias         raise = 1;
21097694c57SEdgar E. Iglesias     }
21197694c57SEdgar E. Iglesias     if (raise
21297694c57SEdgar E. Iglesias         && (env->pvr.regs[2] & PVR2_FPU_EXC_MASK)
21397694c57SEdgar E. Iglesias         && (env->sregs[SR_MSR] & MSR_EE)) {
21464254ebaSBlue Swirl         raise_fpu_exception(env);
21597694c57SEdgar E. Iglesias     }
21697694c57SEdgar E. Iglesias }
21797694c57SEdgar E. Iglesias 
21864254ebaSBlue Swirl uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
21997694c57SEdgar E. Iglesias {
22097694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
22197694c57SEdgar E. Iglesias     int flags;
22297694c57SEdgar E. Iglesias 
22397694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
22497694c57SEdgar E. Iglesias     fa.l = a;
22597694c57SEdgar E. Iglesias     fb.l = b;
22697694c57SEdgar E. Iglesias     fd.f = float32_add(fa.f, fb.f, &env->fp_status);
22797694c57SEdgar E. Iglesias 
22897694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
22964254ebaSBlue Swirl     update_fpu_flags(env, flags);
23097694c57SEdgar E. Iglesias     return fd.l;
23197694c57SEdgar E. Iglesias }
23297694c57SEdgar E. Iglesias 
23364254ebaSBlue Swirl uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
23497694c57SEdgar E. Iglesias {
23597694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
23697694c57SEdgar E. Iglesias     int flags;
23797694c57SEdgar E. Iglesias 
23897694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
23997694c57SEdgar E. Iglesias     fa.l = a;
24097694c57SEdgar E. Iglesias     fb.l = b;
24197694c57SEdgar E. Iglesias     fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
24297694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
24364254ebaSBlue Swirl     update_fpu_flags(env, flags);
24497694c57SEdgar E. Iglesias     return fd.l;
24597694c57SEdgar E. Iglesias }
24697694c57SEdgar E. Iglesias 
24764254ebaSBlue Swirl uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
24897694c57SEdgar E. Iglesias {
24997694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
25097694c57SEdgar E. Iglesias     int flags;
25197694c57SEdgar E. Iglesias 
25297694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
25397694c57SEdgar E. Iglesias     fa.l = a;
25497694c57SEdgar E. Iglesias     fb.l = b;
25597694c57SEdgar E. Iglesias     fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
25697694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
25764254ebaSBlue Swirl     update_fpu_flags(env, flags);
25897694c57SEdgar E. Iglesias 
25997694c57SEdgar E. Iglesias     return fd.l;
26097694c57SEdgar E. Iglesias }
26197694c57SEdgar E. Iglesias 
26264254ebaSBlue Swirl uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
26397694c57SEdgar E. Iglesias {
26497694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
26597694c57SEdgar E. Iglesias     int flags;
26697694c57SEdgar E. Iglesias 
26797694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
26897694c57SEdgar E. Iglesias     fa.l = a;
26997694c57SEdgar E. Iglesias     fb.l = b;
27097694c57SEdgar E. Iglesias     fd.f = float32_div(fb.f, fa.f, &env->fp_status);
27197694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
27264254ebaSBlue Swirl     update_fpu_flags(env, flags);
27397694c57SEdgar E. Iglesias 
27497694c57SEdgar E. Iglesias     return fd.l;
27597694c57SEdgar E. Iglesias }
27697694c57SEdgar E. Iglesias 
27764254ebaSBlue Swirl uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
27897694c57SEdgar E. Iglesias {
279ef9d48daSEdgar E. Iglesias     CPU_FloatU fa, fb;
280ef9d48daSEdgar E. Iglesias     uint32_t r = 0;
281ef9d48daSEdgar E. Iglesias 
282ef9d48daSEdgar E. Iglesias     fa.l = a;
283ef9d48daSEdgar E. Iglesias     fb.l = b;
284ef9d48daSEdgar E. Iglesias 
285af39bc8cSAleksandar Markovic     if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
286af39bc8cSAleksandar Markovic         float32_is_signaling_nan(fb.f, &env->fp_status)) {
28764254ebaSBlue Swirl         update_fpu_flags(env, float_flag_invalid);
288ef9d48daSEdgar E. Iglesias         r = 1;
289ef9d48daSEdgar E. Iglesias     }
290ef9d48daSEdgar E. Iglesias 
291af39bc8cSAleksandar Markovic     if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
292af39bc8cSAleksandar Markovic         float32_is_quiet_nan(fb.f, &env->fp_status)) {
293ef9d48daSEdgar E. Iglesias         r = 1;
294ef9d48daSEdgar E. Iglesias     }
295ef9d48daSEdgar E. Iglesias 
296ef9d48daSEdgar E. Iglesias     return r;
29797694c57SEdgar E. Iglesias }
29897694c57SEdgar E. Iglesias 
29964254ebaSBlue Swirl uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
30097694c57SEdgar E. Iglesias {
30197694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
30297694c57SEdgar E. Iglesias     int r;
30397694c57SEdgar E. Iglesias     int flags;
30497694c57SEdgar E. Iglesias 
30597694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
30697694c57SEdgar E. Iglesias     fa.l = a;
30797694c57SEdgar E. Iglesias     fb.l = b;
30897694c57SEdgar E. Iglesias     r = float32_lt(fb.f, fa.f, &env->fp_status);
30997694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
31064254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
31197694c57SEdgar E. Iglesias 
31297694c57SEdgar E. Iglesias     return r;
31397694c57SEdgar E. Iglesias }
31497694c57SEdgar E. Iglesias 
31564254ebaSBlue Swirl uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
31697694c57SEdgar E. Iglesias {
31797694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
31897694c57SEdgar E. Iglesias     int flags;
31997694c57SEdgar E. Iglesias     int r;
32097694c57SEdgar E. Iglesias 
32197694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
32297694c57SEdgar E. Iglesias     fa.l = a;
32397694c57SEdgar E. Iglesias     fb.l = b;
324211315fbSAurelien Jarno     r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
32597694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
32664254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
32797694c57SEdgar E. Iglesias 
32897694c57SEdgar E. Iglesias     return r;
32997694c57SEdgar E. Iglesias }
33097694c57SEdgar E. Iglesias 
33164254ebaSBlue Swirl uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
33297694c57SEdgar E. Iglesias {
33397694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
33497694c57SEdgar E. Iglesias     int flags;
33597694c57SEdgar E. Iglesias     int r;
33697694c57SEdgar E. Iglesias 
33797694c57SEdgar E. Iglesias     fa.l = a;
33897694c57SEdgar E. Iglesias     fb.l = b;
33997694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
34097694c57SEdgar E. Iglesias     r = float32_le(fa.f, fb.f, &env->fp_status);
34197694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
34264254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
34397694c57SEdgar E. Iglesias 
34497694c57SEdgar E. Iglesias 
34597694c57SEdgar E. Iglesias     return r;
34697694c57SEdgar E. Iglesias }
34797694c57SEdgar E. Iglesias 
34864254ebaSBlue Swirl uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
34997694c57SEdgar E. Iglesias {
35097694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
35197694c57SEdgar E. Iglesias     int flags, r;
35297694c57SEdgar E. Iglesias 
35397694c57SEdgar E. Iglesias     fa.l = a;
35497694c57SEdgar E. Iglesias     fb.l = b;
35597694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
35697694c57SEdgar E. Iglesias     r = float32_lt(fa.f, fb.f, &env->fp_status);
35797694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
35864254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
35997694c57SEdgar E. Iglesias     return r;
36097694c57SEdgar E. Iglesias }
36197694c57SEdgar E. Iglesias 
36264254ebaSBlue Swirl uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
36397694c57SEdgar E. Iglesias {
36497694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
36597694c57SEdgar E. Iglesias     int flags, r;
36697694c57SEdgar E. Iglesias 
36797694c57SEdgar E. Iglesias     fa.l = a;
36897694c57SEdgar E. Iglesias     fb.l = b;
36997694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
370211315fbSAurelien Jarno     r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
37197694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
37264254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
37397694c57SEdgar E. Iglesias 
37497694c57SEdgar E. Iglesias     return r;
37597694c57SEdgar E. Iglesias }
37697694c57SEdgar E. Iglesias 
37764254ebaSBlue Swirl uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
37897694c57SEdgar E. Iglesias {
37997694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
38097694c57SEdgar E. Iglesias     int flags, r;
38197694c57SEdgar E. Iglesias 
38297694c57SEdgar E. Iglesias     fa.l = a;
38397694c57SEdgar E. Iglesias     fb.l = b;
38497694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
38597694c57SEdgar E. Iglesias     r = !float32_lt(fa.f, fb.f, &env->fp_status);
38697694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
38764254ebaSBlue Swirl     update_fpu_flags(env, flags & float_flag_invalid);
38897694c57SEdgar E. Iglesias 
38997694c57SEdgar E. Iglesias     return r;
39097694c57SEdgar E. Iglesias }
39197694c57SEdgar E. Iglesias 
39264254ebaSBlue Swirl uint32_t helper_flt(CPUMBState *env, uint32_t a)
39397694c57SEdgar E. Iglesias {
39497694c57SEdgar E. Iglesias     CPU_FloatU fd, fa;
39597694c57SEdgar E. Iglesias 
39697694c57SEdgar E. Iglesias     fa.l = a;
39797694c57SEdgar E. Iglesias     fd.f = int32_to_float32(fa.l, &env->fp_status);
39897694c57SEdgar E. Iglesias     return fd.l;
39997694c57SEdgar E. Iglesias }
40097694c57SEdgar E. Iglesias 
40164254ebaSBlue Swirl uint32_t helper_fint(CPUMBState *env, uint32_t a)
40297694c57SEdgar E. Iglesias {
40397694c57SEdgar E. Iglesias     CPU_FloatU fa;
40497694c57SEdgar E. Iglesias     uint32_t r;
40597694c57SEdgar E. Iglesias     int flags;
40697694c57SEdgar E. Iglesias 
40797694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
40897694c57SEdgar E. Iglesias     fa.l = a;
40997694c57SEdgar E. Iglesias     r = float32_to_int32(fa.f, &env->fp_status);
41097694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
41164254ebaSBlue Swirl     update_fpu_flags(env, flags);
41297694c57SEdgar E. Iglesias 
41397694c57SEdgar E. Iglesias     return r;
41497694c57SEdgar E. Iglesias }
41597694c57SEdgar E. Iglesias 
41664254ebaSBlue Swirl uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
41797694c57SEdgar E. Iglesias {
41897694c57SEdgar E. Iglesias     CPU_FloatU fd, fa;
41997694c57SEdgar E. Iglesias     int flags;
42097694c57SEdgar E. Iglesias 
42197694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
42297694c57SEdgar E. Iglesias     fa.l = a;
42397694c57SEdgar E. Iglesias     fd.l = float32_sqrt(fa.f, &env->fp_status);
42497694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
42564254ebaSBlue Swirl     update_fpu_flags(env, flags);
42697694c57SEdgar E. Iglesias 
42797694c57SEdgar E. Iglesias     return fd.l;
42897694c57SEdgar E. Iglesias }
42997694c57SEdgar E. Iglesias 
4304acb54baSEdgar E. Iglesias uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
4314acb54baSEdgar E. Iglesias {
4324acb54baSEdgar E. Iglesias     unsigned int i;
4334acb54baSEdgar E. Iglesias     uint32_t mask = 0xff000000;
4344acb54baSEdgar E. Iglesias 
4354acb54baSEdgar E. Iglesias     for (i = 0; i < 4; i++) {
4364acb54baSEdgar E. Iglesias         if ((a & mask) == (b & mask))
4374acb54baSEdgar E. Iglesias             return i + 1;
4384acb54baSEdgar E. Iglesias         mask >>= 8;
4394acb54baSEdgar E. Iglesias     }
4404acb54baSEdgar E. Iglesias     return 0;
4414acb54baSEdgar E. Iglesias }
4424acb54baSEdgar E. Iglesias 
443403322eaSEdgar E. Iglesias void helper_memalign(CPUMBState *env, target_ulong addr,
444403322eaSEdgar E. Iglesias                      uint32_t dr, uint32_t wr,
44564254ebaSBlue Swirl                      uint32_t mask)
446968a40f6SEdgar E. Iglesias {
447968a40f6SEdgar E. Iglesias     if (addr & mask) {
44897f90cbfSEdgar E. Iglesias             qemu_log_mask(CPU_LOG_INT,
449403322eaSEdgar E. Iglesias                           "unaligned access addr=" TARGET_FMT_lx
450403322eaSEdgar E. Iglesias                           " mask=%x, wr=%d dr=r%d\n",
45197f90cbfSEdgar E. Iglesias                           addr, mask, wr, dr);
45297f90cbfSEdgar E. Iglesias             env->sregs[SR_EAR] = addr;
453968a40f6SEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \
454968a40f6SEdgar E. Iglesias                                  | (dr & 31) << 5;
4553aa80988SEdgar E. Iglesias             if (mask == 3) {
456968a40f6SEdgar E. Iglesias                 env->sregs[SR_ESR] |= 1 << 11;
457968a40f6SEdgar E. Iglesias             }
45897f90cbfSEdgar E. Iglesias             if (!(env->sregs[SR_MSR] & MSR_EE)) {
45997f90cbfSEdgar E. Iglesias                 return;
46097f90cbfSEdgar E. Iglesias             }
46164254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
462968a40f6SEdgar E. Iglesias     }
463968a40f6SEdgar E. Iglesias }
464968a40f6SEdgar E. Iglesias 
465403322eaSEdgar E. Iglesias void helper_stackprot(CPUMBState *env, target_ulong addr)
4665818dee5SEdgar E. Iglesias {
4675818dee5SEdgar E. Iglesias     if (addr < env->slr || addr > env->shr) {
468403322eaSEdgar E. Iglesias         qemu_log_mask(CPU_LOG_INT, "Stack protector violation at "
469403322eaSEdgar E. Iglesias                       TARGET_FMT_lx " %x %x\n",
4705818dee5SEdgar E. Iglesias                       addr, env->slr, env->shr);
4715818dee5SEdgar E. Iglesias         env->sregs[SR_EAR] = addr;
4725818dee5SEdgar E. Iglesias         env->sregs[SR_ESR] = ESR_EC_STACKPROT;
47364254ebaSBlue Swirl         helper_raise_exception(env, EXCP_HW_EXCP);
4745818dee5SEdgar E. Iglesias     }
4755818dee5SEdgar E. Iglesias }
4765818dee5SEdgar E. Iglesias 
4774acb54baSEdgar E. Iglesias #if !defined(CONFIG_USER_ONLY)
4784acb54baSEdgar E. Iglesias /* Writes/reads to the MMU's special regs end up here.  */
479*f0f7e7f7SEdgar E. Iglesias uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn)
4804acb54baSEdgar E. Iglesias {
481*f0f7e7f7SEdgar E. Iglesias     return mmu_read(env, ext, rn);
4824acb54baSEdgar E. Iglesias }
4834acb54baSEdgar E. Iglesias 
484*f0f7e7f7SEdgar E. Iglesias void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v)
4854acb54baSEdgar E. Iglesias {
486*f0f7e7f7SEdgar E. Iglesias     mmu_write(env, ext, rn, v);
4874acb54baSEdgar E. Iglesias }
488faed1c2aSEdgar E. Iglesias 
489c658b94fSAndreas Färber void mb_cpu_unassigned_access(CPUState *cs, hwaddr addr,
490c658b94fSAndreas Färber                               bool is_write, bool is_exec, int is_asi,
491c658b94fSAndreas Färber                               unsigned size)
492faed1c2aSEdgar E. Iglesias {
493c658b94fSAndreas Färber     MicroBlazeCPU *cpu;
494c658b94fSAndreas Färber     CPUMBState *env;
495c658b94fSAndreas Färber 
49697f90cbfSEdgar E. Iglesias     qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
497c658b94fSAndreas Färber              addr, is_write ? 1 : 0, is_exec ? 1 : 0);
498c658b94fSAndreas Färber     if (cs == NULL) {
499c658b94fSAndreas Färber         return;
500c658b94fSAndreas Färber     }
501c658b94fSAndreas Färber     cpu = MICROBLAZE_CPU(cs);
502c658b94fSAndreas Färber     env = &cpu->env;
503c658b94fSAndreas Färber     if (!(env->sregs[SR_MSR] & MSR_EE)) {
504faed1c2aSEdgar E. Iglesias         return;
505faed1c2aSEdgar E. Iglesias     }
506faed1c2aSEdgar E. Iglesias 
50797f90cbfSEdgar E. Iglesias     env->sregs[SR_EAR] = addr;
508faed1c2aSEdgar E. Iglesias     if (is_exec) {
50997f90cbfSEdgar E. Iglesias         if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) {
510faed1c2aSEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_INSN_BUS;
51164254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
512faed1c2aSEdgar E. Iglesias         }
513faed1c2aSEdgar E. Iglesias     } else {
51497f90cbfSEdgar E. Iglesias         if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) {
515faed1c2aSEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_DATA_BUS;
51664254ebaSBlue Swirl             helper_raise_exception(env, EXCP_HW_EXCP);
517faed1c2aSEdgar E. Iglesias         }
518faed1c2aSEdgar E. Iglesias     }
519faed1c2aSEdgar E. Iglesias }
5203c7b48b7SPaul Brook #endif
521