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