]> git.proxmox.com Git - mirror_qemu.git/blame - target/microblaze/op_helper.c
target/microblaze: Remove cpu_R[0]
[mirror_qemu.git] / target / microblaze / op_helper.c
CommitLineData
4acb54ba
EI
1/*
2 * Microblaze helper routines.
3 *
4 * Copyright (c) 2009 Edgar E. Iglesias <edgar.iglesias@gmail.com>.
dadc1064 5 * Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
4acb54ba
EI
6 *
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 of the License, or (at your option) any later version.
11 *
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.
16 *
17 * You should have received a copy of the GNU Lesser General Public
8167ee88 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
4acb54ba
EI
19 */
20
8fd9dece 21#include "qemu/osdep.h"
3e457172 22#include "cpu.h"
2ef6175a 23#include "exec/helper-proto.h"
1de7afc9 24#include "qemu/host-utils.h"
63c91552 25#include "exec/exec-all.h"
f08b6170 26#include "exec/cpu_ldst.h"
24f91e81 27#include "fpu/softfloat.h"
4acb54ba 28
6d76d23e
EI
29void helper_put(uint32_t id, uint32_t ctrl, uint32_t data)
30{
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;
36
1d512a65 37 qemu_log_mask(LOG_UNIMP, "Unhandled stream put to stream-id=%d data=%x %s%s%s%s%s\n",
6d76d23e
EI
38 id, data,
39 test ? "t" : "",
40 nonblock ? "n" : "",
41 exception ? "e" : "",
42 control ? "c" : "",
43 atomic ? "a" : "");
44}
45
46uint32_t helper_get(uint32_t id, uint32_t ctrl)
47{
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;
53
1d512a65 54 qemu_log_mask(LOG_UNIMP, "Unhandled stream get from stream-id=%d %s%s%s%s%s\n",
6d76d23e
EI
55 id,
56 test ? "t" : "",
57 nonblock ? "n" : "",
58 exception ? "e" : "",
59 control ? "c" : "",
60 atomic ? "a" : "");
61 return 0xdead0000 | id;
62}
63
64254eba 64void helper_raise_exception(CPUMBState *env, uint32_t index)
4acb54ba 65{
f5c7e93a 66 CPUState *cs = env_cpu(env);
27103424
AF
67
68 cs->exception_index = index;
5638d180 69 cpu_loop_exit(cs);
4acb54ba
EI
70}
71
e98651d9 72static bool check_divz(CPUMBState *env, uint32_t a, uint32_t b, uintptr_t ra)
4acb54ba 73{
e98651d9 74 if (unlikely(b == 0)) {
2e5282ca 75 env->msr |= MSR_DZ;
821ebb33 76
e98651d9
RH
77 if ((env->msr & MSR_EE) &&
78 env_archcpu(env)->cfg.div_zero_exception) {
79 CPUState *cs = env_cpu(env);
80
78e9caf2 81 env->esr = ESR_EC_DIVZERO;
e98651d9
RH
82 cs->exception_index = EXCP_HW_EXCP;
83 cpu_loop_exit_restore(cs, ra);
821ebb33 84 }
e98651d9 85 return false;
4acb54ba 86 }
e98651d9 87 return true;
4acb54ba
EI
88}
89
64254eba 90uint32_t helper_divs(CPUMBState *env, uint32_t a, uint32_t b)
4acb54ba 91{
e98651d9 92 if (!check_divz(env, a, b, GETPC())) {
4acb54ba 93 return 0;
64254eba 94 }
4acb54ba
EI
95 return (int32_t)a / (int32_t)b;
96}
97
64254eba 98uint32_t helper_divu(CPUMBState *env, uint32_t a, uint32_t b)
4acb54ba 99{
e98651d9 100 if (!check_divz(env, a, b, GETPC())) {
4acb54ba 101 return 0;
64254eba 102 }
4acb54ba
EI
103 return a / b;
104}
105
97694c57 106/* raise FPU exception. */
7bca6ddf 107static void raise_fpu_exception(CPUMBState *env, uintptr_t ra)
97694c57 108{
7bca6ddf
RH
109 CPUState *cs = env_cpu(env);
110
78e9caf2 111 env->esr = ESR_EC_FPU;
7bca6ddf
RH
112 cs->exception_index = EXCP_HW_EXCP;
113 cpu_loop_exit_restore(cs, ra);
97694c57
EI
114}
115
7bca6ddf 116static void update_fpu_flags(CPUMBState *env, int flags, uintptr_t ra)
97694c57
EI
117{
118 int raise = 0;
119
120 if (flags & float_flag_invalid) {
5a8e0136 121 env->fsr |= FSR_IO;
97694c57
EI
122 raise = 1;
123 }
124 if (flags & float_flag_divbyzero) {
5a8e0136 125 env->fsr |= FSR_DZ;
97694c57
EI
126 raise = 1;
127 }
128 if (flags & float_flag_overflow) {
5a8e0136 129 env->fsr |= FSR_OF;
97694c57
EI
130 raise = 1;
131 }
132 if (flags & float_flag_underflow) {
5a8e0136 133 env->fsr |= FSR_UF;
97694c57
EI
134 raise = 1;
135 }
136 if (raise
137 && (env->pvr.regs[2] & PVR2_FPU_EXC_MASK)
2e5282ca 138 && (env->msr & MSR_EE)) {
7bca6ddf 139 raise_fpu_exception(env, ra);
97694c57
EI
140 }
141}
142
64254eba 143uint32_t helper_fadd(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
144{
145 CPU_FloatU fd, fa, fb;
146 int flags;
147
148 set_float_exception_flags(0, &env->fp_status);
149 fa.l = a;
150 fb.l = b;
151 fd.f = float32_add(fa.f, fb.f, &env->fp_status);
152
153 flags = get_float_exception_flags(&env->fp_status);
7bca6ddf 154 update_fpu_flags(env, flags, GETPC());
97694c57
EI
155 return fd.l;
156}
157
64254eba 158uint32_t helper_frsub(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
159{
160 CPU_FloatU fd, fa, fb;
161 int flags;
162
163 set_float_exception_flags(0, &env->fp_status);
164 fa.l = a;
165 fb.l = b;
166 fd.f = float32_sub(fb.f, fa.f, &env->fp_status);
167 flags = get_float_exception_flags(&env->fp_status);
7bca6ddf 168 update_fpu_flags(env, flags, GETPC());
97694c57
EI
169 return fd.l;
170}
171
64254eba 172uint32_t helper_fmul(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
173{
174 CPU_FloatU fd, fa, fb;
175 int flags;
176
177 set_float_exception_flags(0, &env->fp_status);
178 fa.l = a;
179 fb.l = b;
180 fd.f = float32_mul(fa.f, fb.f, &env->fp_status);
181 flags = get_float_exception_flags(&env->fp_status);
7bca6ddf 182 update_fpu_flags(env, flags, GETPC());
97694c57
EI
183
184 return fd.l;
185}
186
64254eba 187uint32_t helper_fdiv(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
188{
189 CPU_FloatU fd, fa, fb;
190 int flags;
191
192 set_float_exception_flags(0, &env->fp_status);
193 fa.l = a;
194 fb.l = b;
195 fd.f = float32_div(fb.f, fa.f, &env->fp_status);
196 flags = get_float_exception_flags(&env->fp_status);
7bca6ddf 197 update_fpu_flags(env, flags, GETPC());
97694c57
EI
198
199 return fd.l;
200}
201
64254eba 202uint32_t helper_fcmp_un(CPUMBState *env, uint32_t a, uint32_t b)
97694c57 203{
ef9d48da
EI
204 CPU_FloatU fa, fb;
205 uint32_t r = 0;
206
207 fa.l = a;
208 fb.l = b;
209
af39bc8c
AM
210 if (float32_is_signaling_nan(fa.f, &env->fp_status) ||
211 float32_is_signaling_nan(fb.f, &env->fp_status)) {
7bca6ddf 212 update_fpu_flags(env, float_flag_invalid, GETPC());
ef9d48da
EI
213 r = 1;
214 }
215
af39bc8c
AM
216 if (float32_is_quiet_nan(fa.f, &env->fp_status) ||
217 float32_is_quiet_nan(fb.f, &env->fp_status)) {
ef9d48da
EI
218 r = 1;
219 }
220
221 return r;
97694c57
EI
222}
223
64254eba 224uint32_t helper_fcmp_lt(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
225{
226 CPU_FloatU fa, fb;
227 int r;
228 int flags;
229
230 set_float_exception_flags(0, &env->fp_status);
231 fa.l = a;
232 fb.l = b;
233 r = float32_lt(fb.f, fa.f, &env->fp_status);
234 flags = get_float_exception_flags(&env->fp_status);
7bca6ddf 235 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
97694c57
EI
236
237 return r;
238}
239
64254eba 240uint32_t helper_fcmp_eq(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
241{
242 CPU_FloatU fa, fb;
243 int flags;
244 int r;
245
246 set_float_exception_flags(0, &env->fp_status);
247 fa.l = a;
248 fb.l = b;
211315fb 249 r = float32_eq_quiet(fa.f, fb.f, &env->fp_status);
97694c57 250 flags = get_float_exception_flags(&env->fp_status);
7bca6ddf 251 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
97694c57
EI
252
253 return r;
254}
255
64254eba 256uint32_t helper_fcmp_le(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
257{
258 CPU_FloatU fa, fb;
259 int flags;
260 int r;
261
262 fa.l = a;
263 fb.l = 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);
7bca6ddf 267 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
97694c57
EI
268
269
270 return r;
271}
272
64254eba 273uint32_t helper_fcmp_gt(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
274{
275 CPU_FloatU fa, fb;
276 int flags, r;
277
278 fa.l = a;
279 fb.l = 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);
7bca6ddf 283 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
97694c57
EI
284 return r;
285}
286
64254eba 287uint32_t helper_fcmp_ne(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
288{
289 CPU_FloatU fa, fb;
290 int flags, r;
291
292 fa.l = a;
293 fb.l = b;
294 set_float_exception_flags(0, &env->fp_status);
211315fb 295 r = !float32_eq_quiet(fa.f, fb.f, &env->fp_status);
97694c57 296 flags = get_float_exception_flags(&env->fp_status);
7bca6ddf 297 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
97694c57
EI
298
299 return r;
300}
301
64254eba 302uint32_t helper_fcmp_ge(CPUMBState *env, uint32_t a, uint32_t b)
97694c57
EI
303{
304 CPU_FloatU fa, fb;
305 int flags, r;
306
307 fa.l = a;
308 fb.l = 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);
7bca6ddf 312 update_fpu_flags(env, flags & float_flag_invalid, GETPC());
97694c57
EI
313
314 return r;
315}
316
64254eba 317uint32_t helper_flt(CPUMBState *env, uint32_t a)
97694c57
EI
318{
319 CPU_FloatU fd, fa;
320
321 fa.l = a;
322 fd.f = int32_to_float32(fa.l, &env->fp_status);
323 return fd.l;
324}
325
64254eba 326uint32_t helper_fint(CPUMBState *env, uint32_t a)
97694c57
EI
327{
328 CPU_FloatU fa;
329 uint32_t r;
330 int flags;
331
332 set_float_exception_flags(0, &env->fp_status);
333 fa.l = a;
334 r = float32_to_int32(fa.f, &env->fp_status);
335 flags = get_float_exception_flags(&env->fp_status);
7bca6ddf 336 update_fpu_flags(env, flags, GETPC());
97694c57
EI
337
338 return r;
339}
340
64254eba 341uint32_t helper_fsqrt(CPUMBState *env, uint32_t a)
97694c57
EI
342{
343 CPU_FloatU fd, fa;
344 int flags;
345
346 set_float_exception_flags(0, &env->fp_status);
347 fa.l = a;
348 fd.l = float32_sqrt(fa.f, &env->fp_status);
349 flags = get_float_exception_flags(&env->fp_status);
7bca6ddf 350 update_fpu_flags(env, flags, GETPC());
97694c57
EI
351
352 return fd.l;
353}
354
4acb54ba
EI
355uint32_t helper_pcmpbf(uint32_t a, uint32_t b)
356{
357 unsigned int i;
358 uint32_t mask = 0xff000000;
359
360 for (i = 0; i < 4; i++) {
361 if ((a & mask) == (b & mask))
362 return i + 1;
363 mask >>= 8;
364 }
365 return 0;
366}
367
403322ea 368void helper_stackprot(CPUMBState *env, target_ulong addr)
5818dee5
EI
369{
370 if (addr < env->slr || addr > env->shr) {
3f203194
RH
371 CPUState *cs = env_cpu(env);
372
403322ea
EI
373 qemu_log_mask(CPU_LOG_INT, "Stack protector violation at "
374 TARGET_FMT_lx " %x %x\n",
1d512a65 375 addr, env->slr, env->shr);
3f203194 376
b2e80a3c 377 env->ear = addr;
78e9caf2 378 env->esr = ESR_EC_STACKPROT;
3f203194
RH
379 cs->exception_index = EXCP_HW_EXCP;
380 cpu_loop_exit_restore(cs, GETPC());
5818dee5
EI
381 }
382}
383
4acb54ba
EI
384#if !defined(CONFIG_USER_ONLY)
385/* Writes/reads to the MMU's special regs end up here. */
f0f7e7f7 386uint32_t helper_mmu_read(CPUMBState *env, uint32_t ext, uint32_t rn)
4acb54ba 387{
f0f7e7f7 388 return mmu_read(env, ext, rn);
4acb54ba
EI
389}
390
f0f7e7f7 391void helper_mmu_write(CPUMBState *env, uint32_t ext, uint32_t rn, uint32_t v)
4acb54ba 392{
f0f7e7f7 393 mmu_write(env, ext, rn, v);
4acb54ba 394}
faed1c2a 395
bdff8123
PM
396void 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)
faed1c2a 400{
5318223d
RH
401 MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
402 CPUMBState *env = &cpu->env;
403
bdff8123
PM
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"));
bdff8123 409
2e5282ca 410 if (!(env->msr & MSR_EE)) {
faed1c2a
EI
411 return;
412 }
413
bdff8123 414 if (access_type == MMU_INST_FETCH) {
5318223d
RH
415 if (!cpu->cfg.iopb_bus_exception) {
416 return;
faed1c2a 417 }
5318223d 418 env->esr = ESR_EC_INSN_BUS;
faed1c2a 419 } else {
5318223d
RH
420 if (!cpu->cfg.dopb_bus_exception) {
421 return;
faed1c2a 422 }
5318223d 423 env->esr = ESR_EC_DATA_BUS;
faed1c2a 424 }
5318223d
RH
425
426 env->ear = addr;
427 cs->exception_index = EXCP_HW_EXCP;
428 cpu_loop_exit_restore(cs, retaddr);
faed1c2a 429}
3c7b48b7 430#endif