xref: /qemu/target/microblaze/op_helper.c (revision 6d76d23e82d0ce8a7874b13f5951aa763e059908)
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>.
54acb54baSEdgar E. Iglesias  *
64acb54baSEdgar E. Iglesias  * This library is free software; you can redistribute it and/or
74acb54baSEdgar E. Iglesias  * modify it under the terms of the GNU Lesser General Public
84acb54baSEdgar E. Iglesias  * License as published by the Free Software Foundation; either
94acb54baSEdgar E. Iglesias  * version 2 of the License, or (at your option) any later version.
104acb54baSEdgar E. Iglesias  *
114acb54baSEdgar E. Iglesias  * This library is distributed in the hope that it will be useful,
124acb54baSEdgar E. Iglesias  * but WITHOUT ANY WARRANTY; without even the implied warranty of
134acb54baSEdgar E. Iglesias  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
144acb54baSEdgar E. Iglesias  * Lesser General Public License for more details.
154acb54baSEdgar E. Iglesias  *
164acb54baSEdgar E. Iglesias  * You should have received a copy of the GNU Lesser General Public
178167ee88SBlue Swirl  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
184acb54baSEdgar E. Iglesias  */
194acb54baSEdgar E. Iglesias 
204acb54baSEdgar E. Iglesias #include <assert.h>
214acb54baSEdgar E. Iglesias #include "exec.h"
224acb54baSEdgar E. Iglesias #include "helper.h"
234acb54baSEdgar E. Iglesias #include "host-utils.h"
244acb54baSEdgar E. Iglesias 
254acb54baSEdgar E. Iglesias #define D(x)
264acb54baSEdgar E. Iglesias 
274acb54baSEdgar E. Iglesias #if !defined(CONFIG_USER_ONLY)
284acb54baSEdgar E. Iglesias #define MMUSUFFIX _mmu
294acb54baSEdgar E. Iglesias #define SHIFT 0
304acb54baSEdgar E. Iglesias #include "softmmu_template.h"
314acb54baSEdgar E. Iglesias #define SHIFT 1
324acb54baSEdgar E. Iglesias #include "softmmu_template.h"
334acb54baSEdgar E. Iglesias #define SHIFT 2
344acb54baSEdgar E. Iglesias #include "softmmu_template.h"
354acb54baSEdgar E. Iglesias #define SHIFT 3
364acb54baSEdgar E. Iglesias #include "softmmu_template.h"
374acb54baSEdgar E. Iglesias 
384acb54baSEdgar E. Iglesias /* Try to fill the TLB and return an exception if error. If retaddr is
394acb54baSEdgar E. Iglesias    NULL, it means that the function was called in C code (i.e. not
404acb54baSEdgar E. Iglesias    from generated code or from helper.c) */
414acb54baSEdgar E. Iglesias /* XXX: fix it to restore all registers */
424acb54baSEdgar E. Iglesias void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
434acb54baSEdgar E. Iglesias {
444acb54baSEdgar E. Iglesias     TranslationBlock *tb;
454acb54baSEdgar E. Iglesias     CPUState *saved_env;
464acb54baSEdgar E. Iglesias     unsigned long pc;
474acb54baSEdgar E. Iglesias     int ret;
484acb54baSEdgar E. Iglesias 
494acb54baSEdgar E. Iglesias     /* XXX: hack to restore env in all cases, even if not called from
504acb54baSEdgar E. Iglesias        generated code */
514acb54baSEdgar E. Iglesias     saved_env = env;
524acb54baSEdgar E. Iglesias     env = cpu_single_env;
534acb54baSEdgar E. Iglesias 
544acb54baSEdgar E. Iglesias     ret = cpu_mb_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
554acb54baSEdgar E. Iglesias     if (unlikely(ret)) {
564acb54baSEdgar E. Iglesias         if (retaddr) {
574acb54baSEdgar E. Iglesias             /* now we have a real cpu fault */
584acb54baSEdgar E. Iglesias             pc = (unsigned long)retaddr;
594acb54baSEdgar E. Iglesias             tb = tb_find_pc(pc);
604acb54baSEdgar E. Iglesias             if (tb) {
614acb54baSEdgar E. Iglesias                 /* the PC is inside the translated code. It means that we have
624acb54baSEdgar E. Iglesias                    a virtual CPU fault */
634acb54baSEdgar E. Iglesias                 cpu_restore_state(tb, env, pc, NULL);
644acb54baSEdgar E. Iglesias             }
654acb54baSEdgar E. Iglesias         }
664acb54baSEdgar E. Iglesias         cpu_loop_exit();
674acb54baSEdgar E. Iglesias     }
684acb54baSEdgar E. Iglesias     env = saved_env;
694acb54baSEdgar E. Iglesias }
704acb54baSEdgar E. Iglesias #endif
714acb54baSEdgar E. Iglesias 
726d76d23eSEdgar E. Iglesias void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
736d76d23eSEdgar E. Iglesias {
746d76d23eSEdgar E. Iglesias     int test = ctrl & STREAM_TEST;
756d76d23eSEdgar E. Iglesias     int atomic = ctrl & STREAM_ATOMIC;
766d76d23eSEdgar E. Iglesias     int control = ctrl & STREAM_CONTROL;
776d76d23eSEdgar E. Iglesias     int nonblock = ctrl & STREAM_NONBLOCK;
786d76d23eSEdgar E. Iglesias     int exception = ctrl & STREAM_EXCEPTION;
796d76d23eSEdgar E. Iglesias 
806d76d23eSEdgar E. Iglesias     qemu_log("Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n",
816d76d23eSEdgar E. Iglesias              id, data,
826d76d23eSEdgar E. Iglesias              test ? "t" : "",
836d76d23eSEdgar E. Iglesias              nonblock ? "n" : "",
846d76d23eSEdgar E. Iglesias              exception ? "e" : "",
856d76d23eSEdgar E. Iglesias              control ? "c" : "",
866d76d23eSEdgar E. Iglesias              atomic ? "a" : "");
876d76d23eSEdgar E. Iglesias }
886d76d23eSEdgar E. Iglesias 
896d76d23eSEdgar E. Iglesias uint32_t helper_get(uint32_t id, uint32_t ctrl)
906d76d23eSEdgar E. Iglesias {
916d76d23eSEdgar E. Iglesias     int test = ctrl & STREAM_TEST;
926d76d23eSEdgar E. Iglesias     int atomic = ctrl & STREAM_ATOMIC;
936d76d23eSEdgar E. Iglesias     int control = ctrl & STREAM_CONTROL;
946d76d23eSEdgar E. Iglesias     int nonblock = ctrl & STREAM_NONBLOCK;
956d76d23eSEdgar E. Iglesias     int exception = ctrl & STREAM_EXCEPTION;
966d76d23eSEdgar E. Iglesias 
976d76d23eSEdgar E. Iglesias     qemu_log("Unhandled stream get from stream-id=%d %s%s%s%s%s\n",
986d76d23eSEdgar E. Iglesias              id,
996d76d23eSEdgar E. Iglesias              test ? "t" : "",
1006d76d23eSEdgar E. Iglesias              nonblock ? "n" : "",
1016d76d23eSEdgar E. Iglesias              exception ? "e" : "",
1026d76d23eSEdgar E. Iglesias              control ? "c" : "",
1036d76d23eSEdgar E. Iglesias              atomic ? "a" : "");
1046d76d23eSEdgar E. Iglesias     return 0xdead0000 | id;
1056d76d23eSEdgar E. Iglesias }
1066d76d23eSEdgar E. Iglesias 
1074acb54baSEdgar E. Iglesias void helper_raise_exception(uint32_t index)
1084acb54baSEdgar E. Iglesias {
1094acb54baSEdgar E. Iglesias     env->exception_index = index;
1104acb54baSEdgar E. Iglesias     cpu_loop_exit();
1114acb54baSEdgar E. Iglesias }
1124acb54baSEdgar E. Iglesias 
1134acb54baSEdgar E. Iglesias void helper_debug(void)
1144acb54baSEdgar E. Iglesias {
1154acb54baSEdgar E. Iglesias     int i;
1164acb54baSEdgar E. Iglesias 
1174acb54baSEdgar E. Iglesias     qemu_log("PC=%8.8x\n", env->sregs[SR_PC]);
1184c24aa0aSMichal Simek     qemu_log("rmsr=%x resr=%x rear=%x debug[%x] imm=%x iflags=%x\n",
1194c24aa0aSMichal Simek              env->sregs[SR_MSR], env->sregs[SR_ESR], env->sregs[SR_EAR],
12017c52a43SEdgar E. Iglesias              env->debug, env->imm, env->iflags);
12117c52a43SEdgar E. Iglesias     qemu_log("btaken=%d btarget=%x mode=%s(saved=%s) eip=%d ie=%d\n",
12217c52a43SEdgar E. Iglesias              env->btaken, env->btarget,
12317c52a43SEdgar E. Iglesias              (env->sregs[SR_MSR] & MSR_UM) ? "user" : "kernel",
12417c52a43SEdgar E. Iglesias              (env->sregs[SR_MSR] & MSR_UMS) ? "user" : "kernel",
12517c52a43SEdgar E. Iglesias              (env->sregs[SR_MSR] & MSR_EIP),
12617c52a43SEdgar E. Iglesias              (env->sregs[SR_MSR] & MSR_IE));
1274acb54baSEdgar E. Iglesias     for (i = 0; i < 32; i++) {
1284acb54baSEdgar E. Iglesias         qemu_log("r%2.2d=%8.8x ", i, env->regs[i]);
1294acb54baSEdgar E. Iglesias         if ((i + 1) % 4 == 0)
1304acb54baSEdgar E. Iglesias             qemu_log("\n");
1314acb54baSEdgar E. Iglesias     }
1324acb54baSEdgar E. Iglesias     qemu_log("\n\n");
1334acb54baSEdgar E. Iglesias }
1344acb54baSEdgar E. Iglesias 
1354acb54baSEdgar E. Iglesias static inline uint32_t compute_carry(uint32_t a, uint32_t b, uint32_t cin)
1364acb54baSEdgar E. Iglesias {
1374acb54baSEdgar E. Iglesias     uint32_t cout = 0;
1384acb54baSEdgar E. Iglesias 
1394acb54baSEdgar E. Iglesias     if ((b == ~0) && cin)
1404acb54baSEdgar E. Iglesias         cout = 1;
1414acb54baSEdgar E. Iglesias     else if ((~0 - a) < (b + cin))
1424acb54baSEdgar E. Iglesias         cout = 1;
1434acb54baSEdgar E. Iglesias     return cout;
1444acb54baSEdgar E. Iglesias }
1454acb54baSEdgar E. Iglesias 
1464acb54baSEdgar E. Iglesias uint32_t helper_cmp(uint32_t a, uint32_t b)
1474acb54baSEdgar E. Iglesias {
1484acb54baSEdgar E. Iglesias     uint32_t t;
1494acb54baSEdgar E. Iglesias 
1504acb54baSEdgar E. Iglesias     t = b + ~a + 1;
1514acb54baSEdgar E. Iglesias     if ((b & 0x80000000) ^ (a & 0x80000000))
1524acb54baSEdgar E. Iglesias         t = (t & 0x7fffffff) | (b & 0x80000000);
1534acb54baSEdgar E. Iglesias     return t;
1544acb54baSEdgar E. Iglesias }
1554acb54baSEdgar E. Iglesias 
1564acb54baSEdgar E. Iglesias uint32_t helper_cmpu(uint32_t a, uint32_t b)
1574acb54baSEdgar E. Iglesias {
1584acb54baSEdgar E. Iglesias     uint32_t t;
1594acb54baSEdgar E. Iglesias 
1604acb54baSEdgar E. Iglesias     t = b + ~a + 1;
1614acb54baSEdgar E. Iglesias     if ((b & 0x80000000) ^ (a & 0x80000000))
1624acb54baSEdgar E. Iglesias         t = (t & 0x7fffffff) | (a & 0x80000000);
1634acb54baSEdgar E. Iglesias     return t;
1644acb54baSEdgar E. Iglesias }
1654acb54baSEdgar E. Iglesias 
1665d0bb823SEdgar E. Iglesias uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf)
1674acb54baSEdgar E. Iglesias {
1685d0bb823SEdgar E. Iglesias     uint32_t ncf;
1694acb54baSEdgar E. Iglesias     ncf = compute_carry(a, b, cf);
17040cbf5b7SEdgar E. Iglesias     return ncf;
1714acb54baSEdgar E. Iglesias }
1724acb54baSEdgar E. Iglesias 
1734acb54baSEdgar E. Iglesias static inline int div_prepare(uint32_t a, uint32_t b)
1744acb54baSEdgar E. Iglesias {
1754acb54baSEdgar E. Iglesias     if (b == 0) {
1764acb54baSEdgar E. Iglesias         env->sregs[SR_MSR] |= MSR_DZ;
177821ebb33SEdgar E. Iglesias 
178821ebb33SEdgar E. Iglesias         if ((env->sregs[SR_MSR] & MSR_EE)
179821ebb33SEdgar E. Iglesias             && !(env->pvr.regs[2] & PVR2_DIV_ZERO_EXC_MASK)) {
180821ebb33SEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_DIVZERO;
181821ebb33SEdgar E. Iglesias             helper_raise_exception(EXCP_HW_EXCP);
182821ebb33SEdgar E. Iglesias         }
1834acb54baSEdgar E. Iglesias         return 0;
1844acb54baSEdgar E. Iglesias     }
1854acb54baSEdgar E. Iglesias     env->sregs[SR_MSR] &= ~MSR_DZ;
1864acb54baSEdgar E. Iglesias     return 1;
1874acb54baSEdgar E. Iglesias }
1884acb54baSEdgar E. Iglesias 
1894acb54baSEdgar E. Iglesias uint32_t helper_divs(uint32_t a, uint32_t b)
1904acb54baSEdgar E. Iglesias {
1914acb54baSEdgar E. Iglesias     if (!div_prepare(a, b))
1924acb54baSEdgar E. Iglesias         return 0;
1934acb54baSEdgar E. Iglesias     return (int32_t)a / (int32_t)b;
1944acb54baSEdgar E. Iglesias }
1954acb54baSEdgar E. Iglesias 
1964acb54baSEdgar E. Iglesias uint32_t helper_divu(uint32_t a, uint32_t b)
1974acb54baSEdgar E. Iglesias {
1984acb54baSEdgar E. Iglesias     if (!div_prepare(a, b))
1994acb54baSEdgar E. Iglesias         return 0;
2004acb54baSEdgar E. Iglesias     return a / b;
2014acb54baSEdgar E. Iglesias }
2024acb54baSEdgar E. Iglesias 
20397694c57SEdgar E. Iglesias /* raise FPU exception.  */
20497694c57SEdgar E. Iglesias static void raise_fpu_exception(void)
20597694c57SEdgar E. Iglesias {
20697694c57SEdgar E. Iglesias     env->sregs[SR_ESR] = ESR_EC_FPU;
20797694c57SEdgar E. Iglesias     helper_raise_exception(EXCP_HW_EXCP);
20897694c57SEdgar E. Iglesias }
20997694c57SEdgar E. Iglesias 
21097694c57SEdgar E. Iglesias static void update_fpu_flags(int flags)
21197694c57SEdgar E. Iglesias {
21297694c57SEdgar E. Iglesias     int raise = 0;
21397694c57SEdgar E. Iglesias 
21497694c57SEdgar E. Iglesias     if (flags & float_flag_invalid) {
21597694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_IO;
21697694c57SEdgar E. Iglesias         raise = 1;
21797694c57SEdgar E. Iglesias     }
21897694c57SEdgar E. Iglesias     if (flags & float_flag_divbyzero) {
21997694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_DZ;
22097694c57SEdgar E. Iglesias         raise = 1;
22197694c57SEdgar E. Iglesias     }
22297694c57SEdgar E. Iglesias     if (flags & float_flag_overflow) {
22397694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_OF;
22497694c57SEdgar E. Iglesias         raise = 1;
22597694c57SEdgar E. Iglesias     }
22697694c57SEdgar E. Iglesias     if (flags & float_flag_underflow) {
22797694c57SEdgar E. Iglesias         env->sregs[SR_FSR] |= FSR_UF;
22897694c57SEdgar E. Iglesias         raise = 1;
22997694c57SEdgar E. Iglesias     }
23097694c57SEdgar E. Iglesias     if (raise
23197694c57SEdgar E. Iglesias         && (env->pvr.regs[2] & PVR2_FPU_EXC_MASK)
23297694c57SEdgar E. Iglesias         && (env->sregs[SR_MSR] & MSR_EE)) {
23397694c57SEdgar E. Iglesias         raise_fpu_exception();
23497694c57SEdgar E. Iglesias     }
23597694c57SEdgar E. Iglesias }
23697694c57SEdgar E. Iglesias 
23797694c57SEdgar E. Iglesias uint32_t helper_fadd(uint32_t a, uint32_t b)
23897694c57SEdgar E. Iglesias {
23997694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
24097694c57SEdgar E. Iglesias     int flags;
24197694c57SEdgar E. Iglesias 
24297694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
24397694c57SEdgar E. Iglesias     fa.l = a;
24497694c57SEdgar E. Iglesias     fb.l = b;
24597694c57SEdgar E. Iglesias     fd.f = float32_add(fa.f, fb.f, &env->fp_status);
24697694c57SEdgar E. Iglesias 
24797694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
24897694c57SEdgar E. Iglesias     update_fpu_flags(flags);
24997694c57SEdgar E. Iglesias     return fd.l;
25097694c57SEdgar E. Iglesias }
25197694c57SEdgar E. Iglesias 
25297694c57SEdgar E. Iglesias uint32_t helper_frsub(uint32_t a, uint32_t b)
25397694c57SEdgar E. Iglesias {
25497694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
25597694c57SEdgar E. Iglesias     int flags;
25697694c57SEdgar E. Iglesias 
25797694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
25897694c57SEdgar E. Iglesias     fa.l = a;
25997694c57SEdgar E. Iglesias     fb.l = b;
26097694c57SEdgar E. Iglesias     fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
26197694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
26297694c57SEdgar E. Iglesias     update_fpu_flags(flags);
26397694c57SEdgar E. Iglesias     return fd.l;
26497694c57SEdgar E. Iglesias }
26597694c57SEdgar E. Iglesias 
26697694c57SEdgar E. Iglesias uint32_t helper_fmul(uint32_t a, uint32_t b)
26797694c57SEdgar E. Iglesias {
26897694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
26997694c57SEdgar E. Iglesias     int flags;
27097694c57SEdgar E. Iglesias 
27197694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
27297694c57SEdgar E. Iglesias     fa.l = a;
27397694c57SEdgar E. Iglesias     fb.l = b;
27497694c57SEdgar E. Iglesias     fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
27597694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
27697694c57SEdgar E. Iglesias     update_fpu_flags(flags);
27797694c57SEdgar E. Iglesias 
27897694c57SEdgar E. Iglesias     return fd.l;
27997694c57SEdgar E. Iglesias }
28097694c57SEdgar E. Iglesias 
28197694c57SEdgar E. Iglesias uint32_t helper_fdiv(uint32_t a, uint32_t b)
28297694c57SEdgar E. Iglesias {
28397694c57SEdgar E. Iglesias     CPU_FloatU fd, fa, fb;
28497694c57SEdgar E. Iglesias     int flags;
28597694c57SEdgar E. Iglesias 
28697694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
28797694c57SEdgar E. Iglesias     fa.l = a;
28897694c57SEdgar E. Iglesias     fb.l = b;
28997694c57SEdgar E. Iglesias     fd.f = float32_div(fb.f, fa.f, &env->fp_status);
29097694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
29197694c57SEdgar E. Iglesias     update_fpu_flags(flags);
29297694c57SEdgar E. Iglesias 
29397694c57SEdgar E. Iglesias     return fd.l;
29497694c57SEdgar E. Iglesias }
29597694c57SEdgar E. Iglesias 
29697694c57SEdgar E. Iglesias uint32_t helper_fcmp_un(uint32_t a, uint32_t b)
29797694c57SEdgar E. Iglesias {
298ef9d48daSEdgar E. Iglesias     CPU_FloatU fa, fb;
299ef9d48daSEdgar E. Iglesias     uint32_t r = 0;
300ef9d48daSEdgar E. Iglesias 
301ef9d48daSEdgar E. Iglesias     fa.l = a;
302ef9d48daSEdgar E. Iglesias     fb.l = b;
303ef9d48daSEdgar E. Iglesias 
304ef9d48daSEdgar E. Iglesias     if (float32_is_signaling_nan(fa.f) || float32_is_signaling_nan(fb.f)) {
305ef9d48daSEdgar E. Iglesias         update_fpu_flags(float_flag_invalid);
306ef9d48daSEdgar E. Iglesias         r = 1;
307ef9d48daSEdgar E. Iglesias     }
308ef9d48daSEdgar E. Iglesias 
30918569871SPeter Maydell     if (float32_is_quiet_nan(fa.f) || float32_is_quiet_nan(fb.f)) {
310ef9d48daSEdgar E. Iglesias         r = 1;
311ef9d48daSEdgar E. Iglesias     }
312ef9d48daSEdgar E. Iglesias 
313ef9d48daSEdgar E. Iglesias     return r;
31497694c57SEdgar E. Iglesias }
31597694c57SEdgar E. Iglesias 
31697694c57SEdgar E. Iglesias uint32_t helper_fcmp_lt(uint32_t a, uint32_t b)
31797694c57SEdgar E. Iglesias {
31897694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
31997694c57SEdgar E. Iglesias     int r;
32097694c57SEdgar E. Iglesias     int flags;
32197694c57SEdgar E. Iglesias 
32297694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
32397694c57SEdgar E. Iglesias     fa.l = a;
32497694c57SEdgar E. Iglesias     fb.l = b;
32597694c57SEdgar E. Iglesias     r = float32_lt(fb.f, fa.f, &env->fp_status);
32697694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
32797694c57SEdgar E. Iglesias     update_fpu_flags(flags & float_flag_invalid);
32897694c57SEdgar E. Iglesias 
32997694c57SEdgar E. Iglesias     return r;
33097694c57SEdgar E. Iglesias }
33197694c57SEdgar E. Iglesias 
33297694c57SEdgar E. Iglesias uint32_t helper_fcmp_eq(uint32_t a, uint32_t b)
33397694c57SEdgar E. Iglesias {
33497694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
33597694c57SEdgar E. Iglesias     int flags;
33697694c57SEdgar E. Iglesias     int r;
33797694c57SEdgar E. Iglesias 
33897694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
33997694c57SEdgar E. Iglesias     fa.l = a;
34097694c57SEdgar E. Iglesias     fb.l = b;
34197694c57SEdgar E. Iglesias     r = float32_eq(fa.f, fb.f, &env->fp_status);
34297694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
34397694c57SEdgar E. Iglesias     update_fpu_flags(flags & float_flag_invalid);
34497694c57SEdgar E. Iglesias 
34597694c57SEdgar E. Iglesias     return r;
34697694c57SEdgar E. Iglesias }
34797694c57SEdgar E. Iglesias 
34897694c57SEdgar E. Iglesias uint32_t helper_fcmp_le(uint32_t a, uint32_t b)
34997694c57SEdgar E. Iglesias {
35097694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
35197694c57SEdgar E. Iglesias     int flags;
35297694c57SEdgar E. Iglesias     int r;
35397694c57SEdgar E. Iglesias 
35497694c57SEdgar E. Iglesias     fa.l = a;
35597694c57SEdgar E. Iglesias     fb.l = b;
35697694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
35797694c57SEdgar E. Iglesias     r = float32_le(fa.f, fb.f, &env->fp_status);
35897694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
35997694c57SEdgar E. Iglesias     update_fpu_flags(flags & float_flag_invalid);
36097694c57SEdgar E. Iglesias 
36197694c57SEdgar E. Iglesias 
36297694c57SEdgar E. Iglesias     return r;
36397694c57SEdgar E. Iglesias }
36497694c57SEdgar E. Iglesias 
36597694c57SEdgar E. Iglesias uint32_t helper_fcmp_gt(uint32_t a, uint32_t b)
36697694c57SEdgar E. Iglesias {
36797694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
36897694c57SEdgar E. Iglesias     int flags, r;
36997694c57SEdgar E. Iglesias 
37097694c57SEdgar E. Iglesias     fa.l = a;
37197694c57SEdgar E. Iglesias     fb.l = b;
37297694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
37397694c57SEdgar E. Iglesias     r = float32_lt(fa.f, fb.f, &env->fp_status);
37497694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
37597694c57SEdgar E. Iglesias     update_fpu_flags(flags & float_flag_invalid);
37697694c57SEdgar E. Iglesias     return r;
37797694c57SEdgar E. Iglesias }
37897694c57SEdgar E. Iglesias 
37997694c57SEdgar E. Iglesias uint32_t helper_fcmp_ne(uint32_t a, uint32_t b)
38097694c57SEdgar E. Iglesias {
38197694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
38297694c57SEdgar E. Iglesias     int flags, r;
38397694c57SEdgar E. Iglesias 
38497694c57SEdgar E. Iglesias     fa.l = a;
38597694c57SEdgar E. Iglesias     fb.l = b;
38697694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
38797694c57SEdgar E. Iglesias     r = !float32_eq(fa.f, fb.f, &env->fp_status);
38897694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
38997694c57SEdgar E. Iglesias     update_fpu_flags(flags & float_flag_invalid);
39097694c57SEdgar E. Iglesias 
39197694c57SEdgar E. Iglesias     return r;
39297694c57SEdgar E. Iglesias }
39397694c57SEdgar E. Iglesias 
39497694c57SEdgar E. Iglesias uint32_t helper_fcmp_ge(uint32_t a, uint32_t b)
39597694c57SEdgar E. Iglesias {
39697694c57SEdgar E. Iglesias     CPU_FloatU fa, fb;
39797694c57SEdgar E. Iglesias     int flags, r;
39897694c57SEdgar E. Iglesias 
39997694c57SEdgar E. Iglesias     fa.l = a;
40097694c57SEdgar E. Iglesias     fb.l = b;
40197694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
40297694c57SEdgar E. Iglesias     r = !float32_lt(fa.f, fb.f, &env->fp_status);
40397694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
40497694c57SEdgar E. Iglesias     update_fpu_flags(flags & float_flag_invalid);
40597694c57SEdgar E. Iglesias 
40697694c57SEdgar E. Iglesias     return r;
40797694c57SEdgar E. Iglesias }
40897694c57SEdgar E. Iglesias 
40997694c57SEdgar E. Iglesias uint32_t helper_flt(uint32_t a)
41097694c57SEdgar E. Iglesias {
41197694c57SEdgar E. Iglesias     CPU_FloatU fd, fa;
41297694c57SEdgar E. Iglesias 
41397694c57SEdgar E. Iglesias     fa.l = a;
41497694c57SEdgar E. Iglesias     fd.f = int32_to_float32(fa.l, &env->fp_status);
41597694c57SEdgar E. Iglesias     return fd.l;
41697694c57SEdgar E. Iglesias }
41797694c57SEdgar E. Iglesias 
41897694c57SEdgar E. Iglesias uint32_t helper_fint(uint32_t a)
41997694c57SEdgar E. Iglesias {
42097694c57SEdgar E. Iglesias     CPU_FloatU fa;
42197694c57SEdgar E. Iglesias     uint32_t r;
42297694c57SEdgar E. Iglesias     int flags;
42397694c57SEdgar E. Iglesias 
42497694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
42597694c57SEdgar E. Iglesias     fa.l = a;
42697694c57SEdgar E. Iglesias     r = float32_to_int32(fa.f, &env->fp_status);
42797694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
42897694c57SEdgar E. Iglesias     update_fpu_flags(flags);
42997694c57SEdgar E. Iglesias 
43097694c57SEdgar E. Iglesias     return r;
43197694c57SEdgar E. Iglesias }
43297694c57SEdgar E. Iglesias 
43397694c57SEdgar E. Iglesias uint32_t helper_fsqrt(uint32_t a)
43497694c57SEdgar E. Iglesias {
43597694c57SEdgar E. Iglesias     CPU_FloatU fd, fa;
43697694c57SEdgar E. Iglesias     int flags;
43797694c57SEdgar E. Iglesias 
43897694c57SEdgar E. Iglesias     set_float_exception_flags(0, &env->fp_status);
43997694c57SEdgar E. Iglesias     fa.l = a;
44097694c57SEdgar E. Iglesias     fd.l = float32_sqrt(fa.f, &env->fp_status);
44197694c57SEdgar E. Iglesias     flags = get_float_exception_flags(&env->fp_status);
44297694c57SEdgar E. Iglesias     update_fpu_flags(flags);
44397694c57SEdgar E. Iglesias 
44497694c57SEdgar E. Iglesias     return fd.l;
44597694c57SEdgar E. Iglesias }
44697694c57SEdgar E. Iglesias 
4474acb54baSEdgar E. Iglesias uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
4484acb54baSEdgar E. Iglesias {
4494acb54baSEdgar E. Iglesias     unsigned int i;
4504acb54baSEdgar E. Iglesias     uint32_t mask = 0xff000000;
4514acb54baSEdgar E. Iglesias 
4524acb54baSEdgar E. Iglesias     for (i = 0; i < 4; i++) {
4534acb54baSEdgar E. Iglesias         if ((a & mask) == (b & mask))
4544acb54baSEdgar E. Iglesias             return i + 1;
4554acb54baSEdgar E. Iglesias         mask >>= 8;
4564acb54baSEdgar E. Iglesias     }
4574acb54baSEdgar E. Iglesias     return 0;
4584acb54baSEdgar E. Iglesias }
4594acb54baSEdgar E. Iglesias 
4603aa80988SEdgar E. Iglesias void helper_memalign(uint32_t addr, uint32_t dr, uint32_t wr, uint32_t mask)
461968a40f6SEdgar E. Iglesias {
462968a40f6SEdgar E. Iglesias     if (addr & mask) {
46397f90cbfSEdgar E. Iglesias             qemu_log_mask(CPU_LOG_INT,
46497f90cbfSEdgar E. Iglesias                           "unaligned access addr=%x mask=%x, wr=%d dr=r%d\n",
46597f90cbfSEdgar E. Iglesias                           addr, mask, wr, dr);
46697f90cbfSEdgar E. Iglesias             env->sregs[SR_EAR] = addr;
467968a40f6SEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_UNALIGNED_DATA | (wr << 10) \
468968a40f6SEdgar E. Iglesias                                  | (dr & 31) << 5;
4693aa80988SEdgar E. Iglesias             if (mask == 3) {
470968a40f6SEdgar E. Iglesias                 env->sregs[SR_ESR] |= 1 << 11;
471968a40f6SEdgar E. Iglesias             }
47297f90cbfSEdgar E. Iglesias             if (!(env->sregs[SR_MSR] & MSR_EE)) {
47397f90cbfSEdgar E. Iglesias                 return;
47497f90cbfSEdgar E. Iglesias             }
475968a40f6SEdgar E. Iglesias             helper_raise_exception(EXCP_HW_EXCP);
476968a40f6SEdgar E. Iglesias     }
477968a40f6SEdgar E. Iglesias }
478968a40f6SEdgar E. Iglesias 
4794acb54baSEdgar E. Iglesias #if !defined(CONFIG_USER_ONLY)
4804acb54baSEdgar E. Iglesias /* Writes/reads to the MMU's special regs end up here.  */
4814acb54baSEdgar E. Iglesias uint32_t helper_mmu_read(uint32_t rn)
4824acb54baSEdgar E. Iglesias {
4834acb54baSEdgar E. Iglesias     return mmu_read(env, rn);
4844acb54baSEdgar E. Iglesias }
4854acb54baSEdgar E. Iglesias 
4864acb54baSEdgar E. Iglesias void helper_mmu_write(uint32_t rn, uint32_t v)
4874acb54baSEdgar E. Iglesias {
4884acb54baSEdgar E. Iglesias     mmu_write(env, rn, v);
4894acb54baSEdgar E. Iglesias }
490faed1c2aSEdgar E. Iglesias 
491c227f099SAnthony Liguori void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
492faed1c2aSEdgar E. Iglesias                           int is_asi, int size)
493faed1c2aSEdgar E. Iglesias {
494faed1c2aSEdgar E. Iglesias     CPUState *saved_env;
495e1aa3254SEdgar E. Iglesias 
496e1aa3254SEdgar E. Iglesias     if (!cpu_single_env) {
497e1aa3254SEdgar E. Iglesias         /* XXX: ???   */
498e1aa3254SEdgar E. Iglesias         return;
499e1aa3254SEdgar E. Iglesias     }
500e1aa3254SEdgar E. Iglesias 
501faed1c2aSEdgar E. Iglesias     /* XXX: hack to restore env in all cases, even if not called from
502faed1c2aSEdgar E. Iglesias        generated code */
503faed1c2aSEdgar E. Iglesias     saved_env = env;
504faed1c2aSEdgar E. Iglesias     env = cpu_single_env;
50597f90cbfSEdgar E. Iglesias     qemu_log_mask(CPU_LOG_INT, "Unassigned " TARGET_FMT_plx " wr=%d exe=%d\n",
506faed1c2aSEdgar E. Iglesias              addr, is_write, is_exec);
507faed1c2aSEdgar E. Iglesias     if (!(env->sregs[SR_MSR] & MSR_EE)) {
50895b279deSEdgar E. Iglesias         env = saved_env;
509faed1c2aSEdgar E. Iglesias         return;
510faed1c2aSEdgar E. Iglesias     }
511faed1c2aSEdgar E. Iglesias 
51297f90cbfSEdgar E. Iglesias     env->sregs[SR_EAR] = addr;
513faed1c2aSEdgar E. Iglesias     if (is_exec) {
51497f90cbfSEdgar E. Iglesias         if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) {
515faed1c2aSEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_INSN_BUS;
516faed1c2aSEdgar E. Iglesias             helper_raise_exception(EXCP_HW_EXCP);
517faed1c2aSEdgar E. Iglesias         }
518faed1c2aSEdgar E. Iglesias     } else {
51997f90cbfSEdgar E. Iglesias         if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) {
520faed1c2aSEdgar E. Iglesias             env->sregs[SR_ESR] = ESR_EC_DATA_BUS;
521faed1c2aSEdgar E. Iglesias             helper_raise_exception(EXCP_HW_EXCP);
522faed1c2aSEdgar E. Iglesias         }
523faed1c2aSEdgar E. Iglesias     }
52495b279deSEdgar E. Iglesias     env = saved_env;
525faed1c2aSEdgar E. Iglesias }
5263c7b48b7SPaul Brook #endif
527