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 296d76d23eSEdgar E. Iglesias void helper_put(uint32_t id, uint32_t ctrl, uint32_t data) 306d76d23eSEdgar E. Iglesias { 316d76d23eSEdgar E. Iglesias int test = ctrl & STREAM_TEST; 326d76d23eSEdgar E. Iglesias int atomic = ctrl & STREAM_ATOMIC; 336d76d23eSEdgar E. Iglesias int control = ctrl & STREAM_CONTROL; 346d76d23eSEdgar E. Iglesias int nonblock = ctrl & STREAM_NONBLOCK; 356d76d23eSEdgar E. Iglesias int exception = ctrl & STREAM_EXCEPTION; 366d76d23eSEdgar E. Iglesias 371d512a65SPaolo Bonzini qemu_log_mask(LOG_UNIMP, "Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n", 386d76d23eSEdgar E. Iglesias id, data, 396d76d23eSEdgar E. Iglesias test ? "t" : "", 406d76d23eSEdgar E. Iglesias nonblock ? "n" : "", 416d76d23eSEdgar E. Iglesias exception ? "e" : "", 426d76d23eSEdgar E. Iglesias control ? "c" : "", 436d76d23eSEdgar E. Iglesias atomic ? "a" : ""); 446d76d23eSEdgar E. Iglesias } 456d76d23eSEdgar E. Iglesias 466d76d23eSEdgar E. Iglesias uint32_t helper_get(uint32_t id, uint32_t ctrl) 476d76d23eSEdgar E. Iglesias { 486d76d23eSEdgar E. Iglesias int test = ctrl & STREAM_TEST; 496d76d23eSEdgar E. Iglesias int atomic = ctrl & STREAM_ATOMIC; 506d76d23eSEdgar E. Iglesias int control = ctrl & STREAM_CONTROL; 516d76d23eSEdgar E. Iglesias int nonblock = ctrl & STREAM_NONBLOCK; 526d76d23eSEdgar E. Iglesias int exception = ctrl & STREAM_EXCEPTION; 536d76d23eSEdgar E. Iglesias 541d512a65SPaolo Bonzini qemu_log_mask(LOG_UNIMP, "Unhandled stream get from stream-id=%d %s%s%s%s%s\n", 556d76d23eSEdgar E. Iglesias id, 566d76d23eSEdgar E. Iglesias test ? "t" : "", 576d76d23eSEdgar E. Iglesias nonblock ? "n" : "", 586d76d23eSEdgar E. Iglesias exception ? "e" : "", 596d76d23eSEdgar E. Iglesias control ? "c" : "", 606d76d23eSEdgar E. Iglesias atomic ? "a" : ""); 616d76d23eSEdgar E. Iglesias return 0xdead0000 | id; 626d76d23eSEdgar E. Iglesias } 636d76d23eSEdgar E. Iglesias 6464254ebaSBlue Swirl void helper_raise_exception(CPUMBState *env, uint32_t index) 654acb54baSEdgar E. Iglesias { 66f5c7e93aSRichard Henderson CPUState *cs = env_cpu(env); 6727103424SAndreas Färber 6827103424SAndreas Färber cs->exception_index = index; 695638d180SAndreas Färber cpu_loop_exit(cs); 704acb54baSEdgar E. Iglesias } 714acb54baSEdgar E. Iglesias 72e98651d9SRichard Henderson static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra) 734acb54baSEdgar E. Iglesias { 74e98651d9SRichard Henderson if (unlikely(b == 0)) { 752e5282caSRichard Henderson env->msr |= MSR_DZ; 76821ebb33SEdgar E. Iglesias 77e98651d9SRichard Henderson if ((env->msr & MSR_EE) && 78e98651d9SRichard Henderson env_archcpu(env)->cfg.div_zero_exception) { 79e98651d9SRichard Henderson CPUState *cs = env_cpu(env); 80e98651d9SRichard Henderson 8178e9caf2SRichard Henderson env->esr = ESR_EC_DIVZERO; 82e98651d9SRichard Henderson cs->exception_index = EXCP_HW_EXCP; 83e98651d9SRichard Henderson cpu_loop_exit_restore(cs, ra); 84821ebb33SEdgar E. Iglesias } 85e98651d9SRichard Henderson return false; 864acb54baSEdgar E. Iglesias } 87e98651d9SRichard Henderson return true; 884acb54baSEdgar E. Iglesias } 894acb54baSEdgar E. Iglesias 9064254ebaSBlue Swirl uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b) 914acb54baSEdgar E. Iglesias { 92e98651d9SRichard Henderson if (!check_divz(env, a, b, GETPC())) { 934acb54baSEdgar E. Iglesias return 0; 9464254ebaSBlue Swirl } 954acb54baSEdgar E. Iglesias return (int32_t)a / (int32_t)b; 964acb54baSEdgar E. Iglesias } 974acb54baSEdgar E. Iglesias 9864254ebaSBlue Swirl uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b) 994acb54baSEdgar E. Iglesias { 100e98651d9SRichard Henderson if (!check_divz(env, a, b, GETPC())) { 1014acb54baSEdgar E. Iglesias return 0; 10264254ebaSBlue Swirl } 1034acb54baSEdgar E. Iglesias return a / b; 1044acb54baSEdgar E. Iglesias } 1054acb54baSEdgar E. Iglesias 10697694c57SEdgar E. Iglesias /* raise FPU exception. */ 107*7bca6ddfSRichard Henderson static void raise_fpu_exception(CPUMBState *env, uintptr_t ra) 10897694c57SEdgar E. Iglesias { 109*7bca6ddfSRichard Henderson CPUState *cs = env_cpu(env); 110*7bca6ddfSRichard Henderson 11178e9caf2SRichard Henderson env->esr = ESR_EC_FPU; 112*7bca6ddfSRichard Henderson cs->exception_index = EXCP_HW_EXCP; 113*7bca6ddfSRichard Henderson cpu_loop_exit_restore(cs, ra); 11497694c57SEdgar E. Iglesias } 11597694c57SEdgar E. Iglesias 116*7bca6ddfSRichard Henderson static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra) 11797694c57SEdgar E. Iglesias { 11897694c57SEdgar E. Iglesias int raise = 0; 11997694c57SEdgar E. Iglesias 12097694c57SEdgar E. Iglesias if (flags & float_flag_invalid) { 1215a8e0136SRichard Henderson env->fsr |= FSR_IO; 12297694c57SEdgar E. Iglesias raise = 1; 12397694c57SEdgar E. Iglesias } 12497694c57SEdgar E. Iglesias if (flags & float_flag_divbyzero) { 1255a8e0136SRichard Henderson env->fsr |= FSR_DZ; 12697694c57SEdgar E. Iglesias raise = 1; 12797694c57SEdgar E. Iglesias } 12897694c57SEdgar E. Iglesias if (flags & float_flag_overflow) { 1295a8e0136SRichard Henderson env->fsr |= FSR_OF; 13097694c57SEdgar E. Iglesias raise = 1; 13197694c57SEdgar E. Iglesias } 13297694c57SEdgar E. Iglesias if (flags & float_flag_underflow) { 1335a8e0136SRichard Henderson env->fsr |= FSR_UF; 13497694c57SEdgar E. Iglesias raise = 1; 13597694c57SEdgar E. Iglesias } 13697694c57SEdgar E. Iglesias if (raise 13797694c57SEdgar E. Iglesias && (env->pvr.regs[2] & PVR2_FPU_EXC_MASK) 1382e5282caSRichard Henderson && (env->msr & MSR_EE)) { 139*7bca6ddfSRichard Henderson raise_fpu_exception(env, ra); 14097694c57SEdgar E. Iglesias } 14197694c57SEdgar E. Iglesias } 14297694c57SEdgar E. Iglesias 14364254ebaSBlue Swirl uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b) 14497694c57SEdgar E. Iglesias { 14597694c57SEdgar E. Iglesias CPU_FloatU fd, fa, fb; 14697694c57SEdgar E. Iglesias int flags; 14797694c57SEdgar E. Iglesias 14897694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 14997694c57SEdgar E. Iglesias fa.l = a; 15097694c57SEdgar E. Iglesias fb.l = b; 15197694c57SEdgar E. Iglesias fd.f = float32_add(fa.f, fb.f, &env->fp_status); 15297694c57SEdgar E. Iglesias 15397694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 154*7bca6ddfSRichard Henderson update_fpu_flags(env, flags, GETPC()); 15597694c57SEdgar E. Iglesias return fd.l; 15697694c57SEdgar E. Iglesias } 15797694c57SEdgar E. Iglesias 15864254ebaSBlue Swirl uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b) 15997694c57SEdgar E. Iglesias { 16097694c57SEdgar E. Iglesias CPU_FloatU fd, fa, fb; 16197694c57SEdgar E. Iglesias int flags; 16297694c57SEdgar E. Iglesias 16397694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 16497694c57SEdgar E. Iglesias fa.l = a; 16597694c57SEdgar E. Iglesias fb.l = b; 16697694c57SEdgar E. Iglesias fd.f = float32_sub(fb.f, fa.f, &env->fp_status); 16797694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 168*7bca6ddfSRichard Henderson update_fpu_flags(env, flags, GETPC()); 16997694c57SEdgar E. Iglesias return fd.l; 17097694c57SEdgar E. Iglesias } 17197694c57SEdgar E. Iglesias 17264254ebaSBlue Swirl uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b) 17397694c57SEdgar E. Iglesias { 17497694c57SEdgar E. Iglesias CPU_FloatU fd, fa, fb; 17597694c57SEdgar E. Iglesias int flags; 17697694c57SEdgar E. Iglesias 17797694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 17897694c57SEdgar E. Iglesias fa.l = a; 17997694c57SEdgar E. Iglesias fb.l = b; 18097694c57SEdgar E. Iglesias fd.f = float32_mul(fa.f, fb.f, &env->fp_status); 18197694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 182*7bca6ddfSRichard Henderson update_fpu_flags(env, flags, GETPC()); 18397694c57SEdgar E. Iglesias 18497694c57SEdgar E. Iglesias return fd.l; 18597694c57SEdgar E. Iglesias } 18697694c57SEdgar E. Iglesias 18764254ebaSBlue Swirl uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b) 18897694c57SEdgar E. Iglesias { 18997694c57SEdgar E. Iglesias CPU_FloatU fd, fa, fb; 19097694c57SEdgar E. Iglesias int flags; 19197694c57SEdgar E. Iglesias 19297694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 19397694c57SEdgar E. Iglesias fa.l = a; 19497694c57SEdgar E. Iglesias fb.l = b; 19597694c57SEdgar E. Iglesias fd.f = float32_div(fb.f, fa.f, &env->fp_status); 19697694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 197*7bca6ddfSRichard Henderson update_fpu_flags(env, flags, GETPC()); 19897694c57SEdgar E. Iglesias 19997694c57SEdgar E. Iglesias return fd.l; 20097694c57SEdgar E. Iglesias } 20197694c57SEdgar E. Iglesias 20264254ebaSBlue Swirl uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b) 20397694c57SEdgar E. Iglesias { 204ef9d48daSEdgar E. Iglesias CPU_FloatU fa, fb; 205ef9d48daSEdgar E. Iglesias uint32_t r = 0; 206ef9d48daSEdgar E. Iglesias 207ef9d48daSEdgar E. Iglesias fa.l = a; 208ef9d48daSEdgar E. Iglesias fb.l = b; 209ef9d48daSEdgar E. Iglesias 210af39bc8cSAleksandar Markovic if (float32_is_signaling_nan(fa.f, &env->fp_status) || 211af39bc8cSAleksandar Markovic float32_is_signaling_nan(fb.f, &env->fp_status)) { 212*7bca6ddfSRichard Henderson update_fpu_flags(env, float_flag_invalid, GETPC()); 213ef9d48daSEdgar E. Iglesias r = 1; 214ef9d48daSEdgar E. Iglesias } 215ef9d48daSEdgar E. Iglesias 216af39bc8cSAleksandar Markovic if (float32_is_quiet_nan(fa.f, &env->fp_status) || 217af39bc8cSAleksandar Markovic float32_is_quiet_nan(fb.f, &env->fp_status)) { 218ef9d48daSEdgar E. Iglesias r = 1; 219ef9d48daSEdgar E. Iglesias } 220ef9d48daSEdgar E. Iglesias 221ef9d48daSEdgar E. Iglesias return r; 22297694c57SEdgar E. Iglesias } 22397694c57SEdgar E. Iglesias 22464254ebaSBlue Swirl uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b) 22597694c57SEdgar E. Iglesias { 22697694c57SEdgar E. Iglesias CPU_FloatU fa, fb; 22797694c57SEdgar E. Iglesias int r; 22897694c57SEdgar E. Iglesias int flags; 22997694c57SEdgar E. Iglesias 23097694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 23197694c57SEdgar E. Iglesias fa.l = a; 23297694c57SEdgar E. Iglesias fb.l = b; 23397694c57SEdgar E. Iglesias r = float32_lt(fb.f, fa.f, &env->fp_status); 23497694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 235*7bca6ddfSRichard Henderson update_fpu_flags(env, flags & float_flag_invalid, GETPC()); 23697694c57SEdgar E. Iglesias 23797694c57SEdgar E. Iglesias return r; 23897694c57SEdgar E. Iglesias } 23997694c57SEdgar E. Iglesias 24064254ebaSBlue Swirl uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b) 24197694c57SEdgar E. Iglesias { 24297694c57SEdgar E. Iglesias CPU_FloatU fa, fb; 24397694c57SEdgar E. Iglesias int flags; 24497694c57SEdgar E. Iglesias int r; 24597694c57SEdgar E. Iglesias 24697694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 24797694c57SEdgar E. Iglesias fa.l = a; 24897694c57SEdgar E. Iglesias fb.l = b; 249211315fbSAurelien Jarno r = float32_eq_quiet(fa.f, fb.f, &env->fp_status); 25097694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 251*7bca6ddfSRichard Henderson update_fpu_flags(env, flags & float_flag_invalid, GETPC()); 25297694c57SEdgar E. Iglesias 25397694c57SEdgar E. Iglesias return r; 25497694c57SEdgar E. Iglesias } 25597694c57SEdgar E. Iglesias 25664254ebaSBlue Swirl uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b) 25797694c57SEdgar E. Iglesias { 25897694c57SEdgar E. Iglesias CPU_FloatU fa, fb; 25997694c57SEdgar E. Iglesias int flags; 26097694c57SEdgar E. Iglesias int r; 26197694c57SEdgar E. Iglesias 26297694c57SEdgar E. Iglesias fa.l = a; 26397694c57SEdgar E. Iglesias fb.l = b; 26497694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 26597694c57SEdgar E. Iglesias r = float32_le(fa.f, fb.f, &env->fp_status); 26697694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 267*7bca6ddfSRichard Henderson update_fpu_flags(env, flags & float_flag_invalid, GETPC()); 26897694c57SEdgar E. Iglesias 26997694c57SEdgar E. Iglesias 27097694c57SEdgar E. Iglesias return r; 27197694c57SEdgar E. Iglesias } 27297694c57SEdgar E. Iglesias 27364254ebaSBlue Swirl uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b) 27497694c57SEdgar E. Iglesias { 27597694c57SEdgar E. Iglesias CPU_FloatU fa, fb; 27697694c57SEdgar E. Iglesias int flags, r; 27797694c57SEdgar E. Iglesias 27897694c57SEdgar E. Iglesias fa.l = a; 27997694c57SEdgar E. Iglesias fb.l = b; 28097694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 28197694c57SEdgar E. Iglesias r = float32_lt(fa.f, fb.f, &env->fp_status); 28297694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 283*7bca6ddfSRichard Henderson update_fpu_flags(env, flags & float_flag_invalid, GETPC()); 28497694c57SEdgar E. Iglesias return r; 28597694c57SEdgar E. Iglesias } 28697694c57SEdgar E. Iglesias 28764254ebaSBlue Swirl uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b) 28897694c57SEdgar E. Iglesias { 28997694c57SEdgar E. Iglesias CPU_FloatU fa, fb; 29097694c57SEdgar E. Iglesias int flags, r; 29197694c57SEdgar E. Iglesias 29297694c57SEdgar E. Iglesias fa.l = a; 29397694c57SEdgar E. Iglesias fb.l = b; 29497694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 295211315fbSAurelien Jarno r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status); 29697694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 297*7bca6ddfSRichard Henderson update_fpu_flags(env, flags & float_flag_invalid, GETPC()); 29897694c57SEdgar E. Iglesias 29997694c57SEdgar E. Iglesias return r; 30097694c57SEdgar E. Iglesias } 30197694c57SEdgar E. Iglesias 30264254ebaSBlue Swirl uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b) 30397694c57SEdgar E. Iglesias { 30497694c57SEdgar E. Iglesias CPU_FloatU fa, fb; 30597694c57SEdgar E. Iglesias int flags, r; 30697694c57SEdgar E. Iglesias 30797694c57SEdgar E. Iglesias fa.l = a; 30897694c57SEdgar E. Iglesias fb.l = b; 30997694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 31097694c57SEdgar E. Iglesias r = !float32_lt(fa.f, fb.f, &env->fp_status); 31197694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 312*7bca6ddfSRichard Henderson update_fpu_flags(env, flags & float_flag_invalid, GETPC()); 31397694c57SEdgar E. Iglesias 31497694c57SEdgar E. Iglesias return r; 31597694c57SEdgar E. Iglesias } 31697694c57SEdgar E. Iglesias 31764254ebaSBlue Swirl uint32_t helper_flt(CPUMBState *env, uint32_t a) 31897694c57SEdgar E. Iglesias { 31997694c57SEdgar E. Iglesias CPU_FloatU fd, fa; 32097694c57SEdgar E. Iglesias 32197694c57SEdgar E. Iglesias fa.l = a; 32297694c57SEdgar E. Iglesias fd.f = int32_to_float32(fa.l, &env->fp_status); 32397694c57SEdgar E. Iglesias return fd.l; 32497694c57SEdgar E. Iglesias } 32597694c57SEdgar E. Iglesias 32664254ebaSBlue Swirl uint32_t helper_fint(CPUMBState *env, uint32_t a) 32797694c57SEdgar E. Iglesias { 32897694c57SEdgar E. Iglesias CPU_FloatU fa; 32997694c57SEdgar E. Iglesias uint32_t r; 33097694c57SEdgar E. Iglesias int flags; 33197694c57SEdgar E. Iglesias 33297694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 33397694c57SEdgar E. Iglesias fa.l = a; 33497694c57SEdgar E. Iglesias r = float32_to_int32(fa.f, &env->fp_status); 33597694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 336*7bca6ddfSRichard Henderson update_fpu_flags(env, flags, GETPC()); 33797694c57SEdgar E. Iglesias 33897694c57SEdgar E. Iglesias return r; 33997694c57SEdgar E. Iglesias } 34097694c57SEdgar E. Iglesias 34164254ebaSBlue Swirl uint32_t helper_fsqrt(CPUMBState *env, uint32_t a) 34297694c57SEdgar E. Iglesias { 34397694c57SEdgar E. Iglesias CPU_FloatU fd, fa; 34497694c57SEdgar E. Iglesias int flags; 34597694c57SEdgar E. Iglesias 34697694c57SEdgar E. Iglesias set_float_exception_flags(0, &env->fp_status); 34797694c57SEdgar E. Iglesias fa.l = a; 34897694c57SEdgar E. Iglesias fd.l = float32_sqrt(fa.f, &env->fp_status); 34997694c57SEdgar E. Iglesias flags = get_float_exception_flags(&env->fp_status); 350*7bca6ddfSRichard Henderson update_fpu_flags(env, flags, GETPC()); 35197694c57SEdgar E. Iglesias 35297694c57SEdgar E. Iglesias return fd.l; 35397694c57SEdgar E. Iglesias } 35497694c57SEdgar E. Iglesias 3554acb54baSEdgar E. Iglesias uint32_t helper_pcmpbf(uint32_t a, uint32_t b) 3564acb54baSEdgar E. Iglesias { 3574acb54baSEdgar E. Iglesias unsigned int i; 3584acb54baSEdgar E. Iglesias uint32_t mask = 0xff000000; 3594acb54baSEdgar E. Iglesias 3604acb54baSEdgar E. Iglesias for (i = 0; i < 4; i++) { 3614acb54baSEdgar E. Iglesias if ((a & mask) == (b & mask)) 3624acb54baSEdgar E. Iglesias return i + 1; 3634acb54baSEdgar E. Iglesias mask >>= 8; 3644acb54baSEdgar E. Iglesias } 3654acb54baSEdgar E. Iglesias return 0; 3664acb54baSEdgar E. Iglesias } 3674acb54baSEdgar E. Iglesias 368403322eaSEdgar E. Iglesias void helper_memalign(CPUMBState *env, target_ulong addr, 369403322eaSEdgar E. Iglesias uint32_t dr, uint32_t wr, 37064254ebaSBlue Swirl uint32_t mask) 371968a40f6SEdgar E. Iglesias { 372968a40f6SEdgar E. Iglesias if (addr & mask) { 37397f90cbfSEdgar E. Iglesias qemu_log_mask(CPU_LOG_INT, 374403322eaSEdgar E. Iglesias "unaligned access addr=" TARGET_FMT_lx 375403322eaSEdgar E. Iglesias " mask=%x, wr=%d dr=r%d\n", 37697f90cbfSEdgar E. Iglesias addr, mask, wr, dr); 377b2e80a3cSRichard Henderson env->ear = addr; 37878e9caf2SRichard Henderson env->esr = ESR_EC_UNALIGNED_DATA | (wr << 10) | (dr & 31) << 5; 3793aa80988SEdgar E. Iglesias if (mask == 3) { 38078e9caf2SRichard Henderson env->esr |= 1 << 11; 381968a40f6SEdgar E. Iglesias } 3822e5282caSRichard Henderson if (!(env->msr & MSR_EE)) { 38397f90cbfSEdgar E. Iglesias return; 38497f90cbfSEdgar E. Iglesias } 38564254ebaSBlue Swirl helper_raise_exception(env, EXCP_HW_EXCP); 386968a40f6SEdgar E. Iglesias } 387968a40f6SEdgar E. Iglesias } 388968a40f6SEdgar E. Iglesias 389403322eaSEdgar E. Iglesias void helper_stackprot(CPUMBState *env, target_ulong addr) 3905818dee5SEdgar E. Iglesias { 3915818dee5SEdgar E. Iglesias if (addr < env->slr || addr > env->shr) { 392403322eaSEdgar E. Iglesias qemu_log_mask(CPU_LOG_INT, "Stack protector violation at " 393403322eaSEdgar E. Iglesias TARGET_FMT_lx " %x %x\n", 3945818dee5SEdgar E. Iglesias addr, env->slr, env->shr); 395b2e80a3cSRichard Henderson env->ear = addr; 39678e9caf2SRichard Henderson env->esr = ESR_EC_STACKPROT; 39764254ebaSBlue Swirl helper_raise_exception(env, EXCP_HW_EXCP); 3985818dee5SEdgar E. Iglesias } 3995818dee5SEdgar E. Iglesias } 4005818dee5SEdgar E. Iglesias 4014acb54baSEdgar E. Iglesias #if !defined(CONFIG_USER_ONLY) 4024acb54baSEdgar E. Iglesias /* Writes/reads to the MMU's special regs end up here. */ 403f0f7e7f7SEdgar E. Iglesias uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn) 4044acb54baSEdgar E. Iglesias { 405f0f7e7f7SEdgar E. Iglesias return mmu_read(env, ext, rn); 4064acb54baSEdgar E. Iglesias } 4074acb54baSEdgar E. Iglesias 408f0f7e7f7SEdgar E. Iglesias void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v) 4094acb54baSEdgar E. Iglesias { 410f0f7e7f7SEdgar E. Iglesias mmu_write(env, ext, rn, v); 4114acb54baSEdgar E. Iglesias } 412faed1c2aSEdgar E. Iglesias 413bdff8123SPeter Maydell void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, 414bdff8123SPeter Maydell unsigned size, MMUAccessType access_type, 415bdff8123SPeter Maydell int mmu_idx, MemTxAttrs attrs, 416bdff8123SPeter Maydell MemTxResult response, uintptr_t retaddr) 417faed1c2aSEdgar E. Iglesias { 418c658b94fSAndreas Färber MicroBlazeCPU *cpu; 419c658b94fSAndreas Färber CPUMBState *env; 420bdff8123SPeter Maydell qemu_log_mask(CPU_LOG_INT, "Transaction failed: vaddr 0x%" VADDR_PRIx 421bdff8123SPeter Maydell " physaddr 0x" TARGET_FMT_plx " size %d access type %s\n", 422bdff8123SPeter Maydell addr, physaddr, size, 423bdff8123SPeter Maydell access_type == MMU_INST_FETCH ? "INST_FETCH" : 424bdff8123SPeter Maydell (access_type == MMU_DATA_LOAD ? "DATA_LOAD" : "DATA_STORE")); 425c658b94fSAndreas Färber cpu = MICROBLAZE_CPU(cs); 426c658b94fSAndreas Färber env = &cpu->env; 427bdff8123SPeter Maydell 428bdff8123SPeter Maydell cpu_restore_state(cs, retaddr, true); 4292e5282caSRichard Henderson if (!(env->msr & MSR_EE)) { 430faed1c2aSEdgar E. Iglesias return; 431faed1c2aSEdgar E. Iglesias } 432faed1c2aSEdgar E. Iglesias 433b2e80a3cSRichard Henderson env->ear = addr; 434bdff8123SPeter Maydell if (access_type == MMU_INST_FETCH) { 43597f90cbfSEdgar E. Iglesias if ((env->pvr.regs[2] & PVR2_IOPB_BUS_EXC_MASK)) { 43678e9caf2SRichard Henderson env->esr = ESR_EC_INSN_BUS; 43764254ebaSBlue Swirl helper_raise_exception(env, EXCP_HW_EXCP); 438faed1c2aSEdgar E. Iglesias } 439faed1c2aSEdgar E. Iglesias } else { 44097f90cbfSEdgar E. Iglesias if ((env->pvr.regs[2] & PVR2_DOPB_BUS_EXC_MASK)) { 44178e9caf2SRichard Henderson env->esr = ESR_EC_DATA_BUS; 44264254ebaSBlue Swirl helper_raise_exception(env, EXCP_HW_EXCP); 443faed1c2aSEdgar E. Iglesias } 444faed1c2aSEdgar E. Iglesias } 445faed1c2aSEdgar E. Iglesias } 4463c7b48b7SPaul Brook #endif 447