2 * Microblaze helper routines.
5 * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
23 #include "exec/helper-proto.h"
24 #include "qemu/host-utils.h"
25 #include "exec/exec-all.h"
26 #include "exec/cpu_ldst.h"
27 #include "fpu/softfloat.h"
29 void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
31 int test = ctrl & STREAM_TEST;
32 int atomic = ctrl & STREAM_ATOMIC;
33 int control = ctrl & STREAM_CONTROL;
34 int nonblock = ctrl & STREAM_NONBLOCK;
35 int exception = ctrl & STREAM_EXCEPTION;
37 qemu_log_mask(LOG_UNIMP, "Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n",
46 uint32_t helper_get(uint32_t id, uint32_t ctrl)
48 int test = ctrl & STREAM_TEST;
49 int atomic = ctrl & STREAM_ATOMIC;
50 int control = ctrl & STREAM_CONTROL;
51 int nonblock = ctrl & STREAM_NONBLOCK;
52 int exception = ctrl & STREAM_EXCEPTION;
54 qemu_log_mask(LOG_UNIMP, "Unhandled stream get from stream-id=%d %s%s%s%s%s\n",
61 return 0xdead0000 | id;
64 void helper_raise_exception(CPUMBState *env, uint32_t index)
66 CPUState *cs = env_cpu(env);
68 cs->exception_index = index;
72 static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
74 if (unlikely(b == 0)) {
77 if ((env->msr & MSR_EE) &&
78 env_archcpu(env)->cfg.div_zero_exception) {
79 CPUState *cs = env_cpu(env);
81 env->esr = ESR_EC_DIVZERO;
82 cs->exception_index = EXCP_HW_EXCP;
83 cpu_loop_exit_restore(cs, ra);
90 uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
92 if (!check_divz(env, a, b, GETPC())) {
95 return (int32_t)a / (int32_t)b;
98 uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
100 if (!check_divz(env, a, b, GETPC())) {
106 /* raise FPU exception. */
107 static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
109 CPUState *cs = env_cpu(env);
111 env->esr = ESR_EC_FPU;
112 cs->exception_index = EXCP_HW_EXCP;
113 cpu_loop_exit_restore(cs, ra);
116 static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
120 if (flags & float_flag_invalid) {
124 if (flags & float_flag_divbyzero) {
128 if (flags & float_flag_overflow) {
132 if (flags & float_flag_underflow) {
137 && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK)
138 && (env->msr & MSR_EE)) {
139 raise_fpu_exception(env, ra);
143 uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
145 CPU_FloatU fd, fa, fb;
148 set_float_exception_flags(0, &env->fp_status);
151 fd.f = float32_add(fa.f, fb.f, &env->fp_status);
153 flags = get_float_exception_flags(&env->fp_status);
154 update_fpu_flags(env, flags, GETPC());
158 uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
160 CPU_FloatU fd, fa, fb;
163 set_float_exception_flags(0, &env->fp_status);
166 fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
167 flags = get_float_exception_flags(&env->fp_status);
168 update_fpu_flags(env, flags, GETPC());
172 uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
174 CPU_FloatU fd, fa, fb;
177 set_float_exception_flags(0, &env->fp_status);
180 fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
181 flags = get_float_exception_flags(&env->fp_status);
182 update_fpu_flags(env, flags, GETPC());
187 uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
189 CPU_FloatU fd, fa, fb;
192 set_float_exception_flags(0, &env->fp_status);
195 fd.f = float32_div(fb.f, fa.f, &env->fp_status);
196 flags = get_float_exception_flags(&env->fp_status);
197 update_fpu_flags(env, flags, GETPC());
202 uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
210 if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
211 float32_is_signaling_nan(fb.f, &env->fp_status)) {
212 update_fpu_flags(env, float_flag_invalid, GETPC());
216 if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
217 float32_is_quiet_nan(fb.f, &env->fp_status)) {
224 uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
230 set_float_exception_flags(0, &env->fp_status);
233 r = float32_lt(fb.f, fa.f, &env->fp_status);
234 flags = get_float_exception_flags(&env->fp_status);
235 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
240 uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
246 set_float_exception_flags(0, &env->fp_status);
249 r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
250 flags = get_float_exception_flags(&env->fp_status);
251 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
256 uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
264 set_float_exception_flags(0, &env->fp_status);
265 r = float32_le(fa.f, fb.f, &env->fp_status);
266 flags = get_float_exception_flags(&env->fp_status);
267 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
273 uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
280 set_float_exception_flags(0, &env->fp_status);
281 r = float32_lt(fa.f, fb.f, &env->fp_status);
282 flags = get_float_exception_flags(&env->fp_status);
283 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
287 uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
294 set_float_exception_flags(0, &env->fp_status);
295 r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
296 flags = get_float_exception_flags(&env->fp_status);
297 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
302 uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
309 set_float_exception_flags(0, &env->fp_status);
310 r = !float32_lt(fa.f, fb.f, &env->fp_status);
311 flags = get_float_exception_flags(&env->fp_status);
312 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
317 uint32_t helper_flt(CPUMBState *env, uint32_t a)
322 fd.f = int32_to_float32(fa.l, &env->fp_status);
326 uint32_t helper_fint(CPUMBState *env, uint32_t a)
332 set_float_exception_flags(0, &env->fp_status);
334 r = float32_to_int32(fa.f, &env->fp_status);
335 flags = get_float_exception_flags(&env->fp_status);
336 update_fpu_flags(env, flags, GETPC());
341 uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
346 set_float_exception_flags(0, &env->fp_status);
348 fd.l = float32_sqrt(fa.f, &env->fp_status);
349 flags = get_float_exception_flags(&env->fp_status);
350 update_fpu_flags(env, flags, GETPC());
355 uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
358 uint32_t mask = 0xff000000;
360 for (i = 0; i < 4; i++) {
361 if ((a & mask) == (b & mask))
368 void helper_stackprot(CPUMBState *env, target_ulong addr)
370 if (addr < env->slr || addr > env->shr) {
371 CPUState *cs = env_cpu(env);
373 qemu_log_mask(CPU_LOG_INT, "Stack protector violation at "
374 TARGET_FMT_lx " %x %x\n",
375 addr, env->slr, env->shr);
378 env->esr = ESR_EC_STACKPROT;
379 cs->exception_index = EXCP_HW_EXCP;
380 cpu_loop_exit_restore(cs, GETPC());
384 #if !defined(CONFIG_USER_ONLY)
385 /* Writes/reads to the MMU's special regs end up here. */
386 uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn)
388 return mmu_read(env, ext, rn);
391 void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v)
393 mmu_write(env, ext, rn, v);
396 void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
397 unsigned size, MMUAccessType access_type,
398 int mmu_idx, MemTxAttrs attrs,
399 MemTxResult response, uintptr_t retaddr)
401 MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
402 CPUMBState *env = &cpu->env;
404 qemu_log_mask(CPU_LOG_INT, "Transaction failed: vaddr 0x%" VADDR_PRIx
405 " physaddr 0x" TARGET_FMT_plx " size %d access type %s\n",
406 addr, physaddr, size,
407 access_type == MMU_INST_FETCH ? "INST_FETCH" :
408 (access_type == MMU_DATA_LOAD ? "DATA_LOAD" : "DATA_STORE"));
410 if (!(env->msr & MSR_EE)) {
414 if (access_type == MMU_INST_FETCH) {
415 if (!cpu->cfg.iopb_bus_exception) {
418 env->esr = ESR_EC_INSN_BUS;
420 if (!cpu->cfg.dopb_bus_exception) {
423 env->esr = ESR_EC_DATA_BUS;
427 cs->exception_index = EXCP_HW_EXCP;
428 cpu_loop_exit_restore(cs, retaddr);