block: remove bdrv_coroutine_enter
[qemu.git] / target / microblaze / op_helper.c
blobf6378030b7a0c41ade2cc07303d154d1e5be604c
1 /*
2 * Microblaze helper routines.
4 * Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>.
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"
22 #include "qemu/log.h"
23 #include "cpu.h"
24 #include "exec/helper-proto.h"
25 #include "qemu/host-utils.h"
26 #include "exec/exec-all.h"
27 #include "exec/cpu_ldst.h"
28 #include "fpu/softfloat.h"
30 void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
32 int test = ctrl & STREAM_TEST;
33 int atomic = ctrl & STREAM_ATOMIC;
34 int control = ctrl & STREAM_CONTROL;
35 int nonblock = ctrl & STREAM_NONBLOCK;
36 int exception = ctrl & STREAM_EXCEPTION;
38 qemu_log_mask(LOG_UNIMP, "Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n",
39 id, data,
40 test ? "t" : "",
41 nonblock ? "n" : "",
42 exception ? "e" : "",
43 control ? "c" : "",
44 atomic ? "a" : "");
47 uint32_t helper_get(uint32_t id, uint32_t ctrl)
49 int test = ctrl & STREAM_TEST;
50 int atomic = ctrl & STREAM_ATOMIC;
51 int control = ctrl & STREAM_CONTROL;
52 int nonblock = ctrl & STREAM_NONBLOCK;
53 int exception = ctrl & STREAM_EXCEPTION;
55 qemu_log_mask(LOG_UNIMP, "Unhandled stream get from stream-id=%d %s%s%s%s%s\n",
56 id,
57 test ? "t" : "",
58 nonblock ? "n" : "",
59 exception ? "e" : "",
60 control ? "c" : "",
61 atomic ? "a" : "");
62 return 0xdead0000 | id;
65 void helper_raise_exception(CPUMBState *env, uint32_t index)
67 CPUState *cs = env_cpu(env);
69 cs->exception_index = index;
70 cpu_loop_exit(cs);
73 static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
75 if (unlikely(b == 0)) {
76 env->msr |= MSR_DZ;
78 if ((env->msr & MSR_EE) &&
79 env_archcpu(env)->cfg.div_zero_exception) {
80 CPUState *cs = env_cpu(env);
82 env->esr = ESR_EC_DIVZERO;
83 cs->exception_index = EXCP_HW_EXCP;
84 cpu_loop_exit_restore(cs, ra);
86 return false;
88 return true;
91 uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
93 if (!check_divz(env, a, b, GETPC())) {
94 return 0;
96 return (int32_t)a / (int32_t)b;
99 uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
101 if (!check_divz(env, a, b, GETPC())) {
102 return 0;
104 return a / b;
107 /* raise FPU exception. */
108 static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
110 CPUState *cs = env_cpu(env);
112 env->esr = ESR_EC_FPU;
113 cs->exception_index = EXCP_HW_EXCP;
114 cpu_loop_exit_restore(cs, ra);
117 static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
119 int raise = 0;
121 if (flags & float_flag_invalid) {
122 env->fsr |= FSR_IO;
123 raise = 1;
125 if (flags & float_flag_divbyzero) {
126 env->fsr |= FSR_DZ;
127 raise = 1;
129 if (flags & float_flag_overflow) {
130 env->fsr |= FSR_OF;
131 raise = 1;
133 if (flags & float_flag_underflow) {
134 env->fsr |= FSR_UF;
135 raise = 1;
137 if (raise
138 && (env_archcpu(env)->cfg.pvr_regs[2] & PVR2_FPU_EXC_MASK)
139 && (env->msr & MSR_EE)) {
140 raise_fpu_exception(env, ra);
144 uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
146 CPU_FloatU fd, fa, fb;
147 int flags;
149 set_float_exception_flags(0, &env->fp_status);
150 fa.l = a;
151 fb.l = b;
152 fd.f = float32_add(fa.f, fb.f, &env->fp_status);
154 flags = get_float_exception_flags(&env->fp_status);
155 update_fpu_flags(env, flags, GETPC());
156 return fd.l;
159 uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
161 CPU_FloatU fd, fa, fb;
162 int flags;
164 set_float_exception_flags(0, &env->fp_status);
165 fa.l = a;
166 fb.l = b;
167 fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
168 flags = get_float_exception_flags(&env->fp_status);
169 update_fpu_flags(env, flags, GETPC());
170 return fd.l;
173 uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
175 CPU_FloatU fd, fa, fb;
176 int flags;
178 set_float_exception_flags(0, &env->fp_status);
179 fa.l = a;
180 fb.l = b;
181 fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
182 flags = get_float_exception_flags(&env->fp_status);
183 update_fpu_flags(env, flags, GETPC());
185 return fd.l;
188 uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
190 CPU_FloatU fd, fa, fb;
191 int flags;
193 set_float_exception_flags(0, &env->fp_status);
194 fa.l = a;
195 fb.l = b;
196 fd.f = float32_div(fb.f, fa.f, &env->fp_status);
197 flags = get_float_exception_flags(&env->fp_status);
198 update_fpu_flags(env, flags, GETPC());
200 return fd.l;
203 uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
205 CPU_FloatU fa, fb;
206 uint32_t r = 0;
208 fa.l = a;
209 fb.l = b;
211 if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
212 float32_is_signaling_nan(fb.f, &env->fp_status)) {
213 update_fpu_flags(env, float_flag_invalid, GETPC());
214 r = 1;
217 if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
218 float32_is_quiet_nan(fb.f, &env->fp_status)) {
219 r = 1;
222 return r;
225 uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
227 CPU_FloatU fa, fb;
228 int r;
229 int flags;
231 set_float_exception_flags(0, &env->fp_status);
232 fa.l = a;
233 fb.l = b;
234 r = float32_lt(fb.f, fa.f, &env->fp_status);
235 flags = get_float_exception_flags(&env->fp_status);
236 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
238 return r;
241 uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
243 CPU_FloatU fa, fb;
244 int flags;
245 int r;
247 set_float_exception_flags(0, &env->fp_status);
248 fa.l = a;
249 fb.l = b;
250 r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
251 flags = get_float_exception_flags(&env->fp_status);
252 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
254 return r;
257 uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
259 CPU_FloatU fa, fb;
260 int flags;
261 int r;
263 fa.l = a;
264 fb.l = b;
265 set_float_exception_flags(0, &env->fp_status);
266 r = float32_le(fa.f, fb.f, &env->fp_status);
267 flags = get_float_exception_flags(&env->fp_status);
268 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
271 return r;
274 uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
276 CPU_FloatU fa, fb;
277 int flags, r;
279 fa.l = a;
280 fb.l = b;
281 set_float_exception_flags(0, &env->fp_status);
282 r = float32_lt(fa.f, fb.f, &env->fp_status);
283 flags = get_float_exception_flags(&env->fp_status);
284 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
285 return r;
288 uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
290 CPU_FloatU fa, fb;
291 int flags, r;
293 fa.l = a;
294 fb.l = b;
295 set_float_exception_flags(0, &env->fp_status);
296 r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
297 flags = get_float_exception_flags(&env->fp_status);
298 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
300 return r;
303 uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
305 CPU_FloatU fa, fb;
306 int flags, r;
308 fa.l = a;
309 fb.l = b;
310 set_float_exception_flags(0, &env->fp_status);
311 r = !float32_lt(fa.f, fb.f, &env->fp_status);
312 flags = get_float_exception_flags(&env->fp_status);
313 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
315 return r;
318 uint32_t helper_flt(CPUMBState *env, uint32_t a)
320 CPU_FloatU fd, fa;
322 fa.l = a;
323 fd.f = int32_to_float32(fa.l, &env->fp_status);
324 return fd.l;
327 uint32_t helper_fint(CPUMBState *env, uint32_t a)
329 CPU_FloatU fa;
330 uint32_t r;
331 int flags;
333 set_float_exception_flags(0, &env->fp_status);
334 fa.l = a;
335 r = float32_to_int32(fa.f, &env->fp_status);
336 flags = get_float_exception_flags(&env->fp_status);
337 update_fpu_flags(env, flags, GETPC());
339 return r;
342 uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
344 CPU_FloatU fd, fa;
345 int flags;
347 set_float_exception_flags(0, &env->fp_status);
348 fa.l = a;
349 fd.l = float32_sqrt(fa.f, &env->fp_status);
350 flags = get_float_exception_flags(&env->fp_status);
351 update_fpu_flags(env, flags, GETPC());
353 return fd.l;
356 uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
358 unsigned int i;
359 uint32_t mask = 0xff000000;
361 for (i = 0; i < 4; i++) {
362 if ((a & mask) == (b & mask))
363 return i + 1;
364 mask >>= 8;
366 return 0;
369 void helper_stackprot(CPUMBState *env, target_ulong addr)
371 if (addr < env->slr || addr > env->shr) {
372 CPUState *cs = env_cpu(env);
374 qemu_log_mask(CPU_LOG_INT, "Stack protector violation at "
375 TARGET_FMT_lx " %x %x\n",
376 addr, env->slr, env->shr);
378 env->ear = addr;
379 env->esr = ESR_EC_STACKPROT;
380 cs->exception_index = EXCP_HW_EXCP;
381 cpu_loop_exit_restore(cs, GETPC());
385 #if !defined(CONFIG_USER_ONLY)
386 /* Writes/reads to the MMU's special regs end up here. */
387 uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn)
389 return mmu_read(env, ext, rn);
392 void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v)
394 mmu_write(env, ext, rn, v);
397 void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
398 unsigned size, MMUAccessType access_type,
399 int mmu_idx, MemTxAttrs attrs,
400 MemTxResult response, uintptr_t retaddr)
402 MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
403 CPUMBState *env = &cpu->env;
405 qemu_log_mask(CPU_LOG_INT, "Transaction failed: vaddr 0x%" VADDR_PRIx
406 " physaddr 0x" HWADDR_FMT_plx " size %d access type %s\n",
407 addr, physaddr, size,
408 access_type == MMU_INST_FETCH ? "INST_FETCH" :
409 (access_type == MMU_DATA_LOAD ? "DATA_LOAD" : "DATA_STORE"));
411 if (!(env->msr & MSR_EE)) {
412 return;
415 if (access_type == MMU_INST_FETCH) {
416 if (!cpu->cfg.iopb_bus_exception) {
417 return;
419 env->esr = ESR_EC_INSN_BUS;
420 } else {
421 if (!cpu->cfg.dopb_bus_exception) {
422 return;
424 env->esr = ESR_EC_DATA_BUS;
427 env->ear = addr;
428 cs->exception_index = EXCP_HW_EXCP;
429 cpu_loop_exit_restore(cs, retaddr);
431 #endif