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