Add support of boot on NOR flash.
[qemu/mini2440.git] / target-sh4 / op_helper.c
blob616b4f9a4d28928bcb1615e8866d65c88a7ae7cf
1 /*
2 * SH4 emulation
4 * Copyright (c) 2005 Samuel Tardieu
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
20 #include <assert.h>
21 #include <stdlib.h>
22 #include "exec.h"
23 #include "helper.h"
25 #ifndef CONFIG_USER_ONLY
27 #define MMUSUFFIX _mmu
29 #define SHIFT 0
30 #include "softmmu_template.h"
32 #define SHIFT 1
33 #include "softmmu_template.h"
35 #define SHIFT 2
36 #include "softmmu_template.h"
38 #define SHIFT 3
39 #include "softmmu_template.h"
41 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
43 TranslationBlock *tb;
44 CPUState *saved_env;
45 unsigned long pc;
46 int ret;
48 /* XXX: hack to restore env in all cases, even if not called from
49 generated code */
50 saved_env = env;
51 env = cpu_single_env;
52 ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
53 if (ret) {
54 if (retaddr) {
55 /* now we have a real cpu fault */
56 pc = (unsigned long) retaddr;
57 tb = tb_find_pc(pc);
58 if (tb) {
59 /* the PC is inside the translated code. It means that we have
60 a virtual CPU fault */
61 cpu_restore_state(tb, env, pc, NULL);
64 cpu_loop_exit();
66 env = saved_env;
69 #endif
71 void helper_ldtlb(void)
73 #ifdef CONFIG_USER_ONLY
74 /* XXXXX */
75 assert(0);
76 #else
77 cpu_load_tlb(env);
78 #endif
81 void helper_raise_illegal_instruction(void)
83 env->exception_index = 0x180;
84 cpu_loop_exit();
87 void helper_raise_slot_illegal_instruction(void)
89 env->exception_index = 0x1a0;
90 cpu_loop_exit();
93 void helper_raise_fpu_disable(void)
95 env->exception_index = 0x800;
96 cpu_loop_exit();
99 void helper_raise_slot_fpu_disable(void)
101 env->exception_index = 0x820;
102 cpu_loop_exit();
105 void helper_debug(void)
107 env->exception_index = EXCP_DEBUG;
108 cpu_loop_exit();
111 void helper_sleep(uint32_t next_pc)
113 env->halted = 1;
114 env->exception_index = EXCP_HLT;
115 env->pc = next_pc;
116 cpu_loop_exit();
119 void helper_trapa(uint32_t tra)
121 env->tra = tra << 2;
122 env->exception_index = 0x160;
123 cpu_loop_exit();
126 void helper_movcal(uint32_t address, uint32_t value)
128 if (cpu_sh4_is_cached (env, address))
130 memory_content *r = malloc (sizeof(memory_content));
131 r->address = address;
132 r->value = value;
133 r->next = NULL;
135 *(env->movcal_backup_tail) = r;
136 env->movcal_backup_tail = &(r->next);
140 void helper_discard_movcal_backup(void)
142 memory_content *current = env->movcal_backup;
144 while(current)
146 memory_content *next = current->next;
147 free (current);
148 env->movcal_backup = current = next;
149 if (current == 0)
150 env->movcal_backup_tail = &(env->movcal_backup);
154 void helper_ocbi(uint32_t address)
156 memory_content **current = &(env->movcal_backup);
157 while (*current)
159 uint32_t a = (*current)->address;
160 if ((a & ~0x1F) == (address & ~0x1F))
162 memory_content *next = (*current)->next;
163 stl(a, (*current)->value);
165 if (next == 0)
167 env->movcal_backup_tail = current;
170 free (*current);
171 *current = next;
172 break;
177 uint32_t helper_addc(uint32_t arg0, uint32_t arg1)
179 uint32_t tmp0, tmp1;
181 tmp1 = arg0 + arg1;
182 tmp0 = arg1;
183 arg1 = tmp1 + (env->sr & 1);
184 if (tmp0 > tmp1)
185 env->sr |= SR_T;
186 else
187 env->sr &= ~SR_T;
188 if (tmp1 > arg1)
189 env->sr |= SR_T;
190 return arg1;
193 uint32_t helper_addv(uint32_t arg0, uint32_t arg1)
195 uint32_t dest, src, ans;
197 if ((int32_t) arg1 >= 0)
198 dest = 0;
199 else
200 dest = 1;
201 if ((int32_t) arg0 >= 0)
202 src = 0;
203 else
204 src = 1;
205 src += dest;
206 arg1 += arg0;
207 if ((int32_t) arg1 >= 0)
208 ans = 0;
209 else
210 ans = 1;
211 ans += dest;
212 if (src == 0 || src == 2) {
213 if (ans == 1)
214 env->sr |= SR_T;
215 else
216 env->sr &= ~SR_T;
217 } else
218 env->sr &= ~SR_T;
219 return arg1;
222 #define T (env->sr & SR_T)
223 #define Q (env->sr & SR_Q ? 1 : 0)
224 #define M (env->sr & SR_M ? 1 : 0)
225 #define SETT env->sr |= SR_T
226 #define CLRT env->sr &= ~SR_T
227 #define SETQ env->sr |= SR_Q
228 #define CLRQ env->sr &= ~SR_Q
229 #define SETM env->sr |= SR_M
230 #define CLRM env->sr &= ~SR_M
232 uint32_t helper_div1(uint32_t arg0, uint32_t arg1)
234 uint32_t tmp0, tmp2;
235 uint8_t old_q, tmp1 = 0xff;
237 //printf("div1 arg0=0x%08x arg1=0x%08x M=%d Q=%d T=%d\n", arg0, arg1, M, Q, T);
238 old_q = Q;
239 if ((0x80000000 & arg1) != 0)
240 SETQ;
241 else
242 CLRQ;
243 tmp2 = arg0;
244 arg1 <<= 1;
245 arg1 |= T;
246 switch (old_q) {
247 case 0:
248 switch (M) {
249 case 0:
250 tmp0 = arg1;
251 arg1 -= tmp2;
252 tmp1 = arg1 > tmp0;
253 switch (Q) {
254 case 0:
255 if (tmp1)
256 SETQ;
257 else
258 CLRQ;
259 break;
260 case 1:
261 if (tmp1 == 0)
262 SETQ;
263 else
264 CLRQ;
265 break;
267 break;
268 case 1:
269 tmp0 = arg1;
270 arg1 += tmp2;
271 tmp1 = arg1 < tmp0;
272 switch (Q) {
273 case 0:
274 if (tmp1 == 0)
275 SETQ;
276 else
277 CLRQ;
278 break;
279 case 1:
280 if (tmp1)
281 SETQ;
282 else
283 CLRQ;
284 break;
286 break;
288 break;
289 case 1:
290 switch (M) {
291 case 0:
292 tmp0 = arg1;
293 arg1 += tmp2;
294 tmp1 = arg1 < tmp0;
295 switch (Q) {
296 case 0:
297 if (tmp1)
298 SETQ;
299 else
300 CLRQ;
301 break;
302 case 1:
303 if (tmp1 == 0)
304 SETQ;
305 else
306 CLRQ;
307 break;
309 break;
310 case 1:
311 tmp0 = arg1;
312 arg1 -= tmp2;
313 tmp1 = arg1 > tmp0;
314 switch (Q) {
315 case 0:
316 if (tmp1 == 0)
317 SETQ;
318 else
319 CLRQ;
320 break;
321 case 1:
322 if (tmp1)
323 SETQ;
324 else
325 CLRQ;
326 break;
328 break;
330 break;
332 if (Q == M)
333 SETT;
334 else
335 CLRT;
336 //printf("Output: arg1=0x%08x M=%d Q=%d T=%d\n", arg1, M, Q, T);
337 return arg1;
340 void helper_macl(uint32_t arg0, uint32_t arg1)
342 int64_t res;
344 res = ((uint64_t) env->mach << 32) | env->macl;
345 res += (int64_t) (int32_t) arg0 *(int64_t) (int32_t) arg1;
346 env->mach = (res >> 32) & 0xffffffff;
347 env->macl = res & 0xffffffff;
348 if (env->sr & SR_S) {
349 if (res < 0)
350 env->mach |= 0xffff0000;
351 else
352 env->mach &= 0x00007fff;
356 void helper_macw(uint32_t arg0, uint32_t arg1)
358 int64_t res;
360 res = ((uint64_t) env->mach << 32) | env->macl;
361 res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
362 env->mach = (res >> 32) & 0xffffffff;
363 env->macl = res & 0xffffffff;
364 if (env->sr & SR_S) {
365 if (res < -0x80000000) {
366 env->mach = 1;
367 env->macl = 0x80000000;
368 } else if (res > 0x000000007fffffff) {
369 env->mach = 1;
370 env->macl = 0x7fffffff;
375 uint32_t helper_negc(uint32_t arg)
377 uint32_t temp;
379 temp = -arg;
380 arg = temp - (env->sr & SR_T);
381 if (0 < temp)
382 env->sr |= SR_T;
383 else
384 env->sr &= ~SR_T;
385 if (temp < arg)
386 env->sr |= SR_T;
387 return arg;
390 uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
392 uint32_t tmp0, tmp1;
394 tmp1 = arg1 - arg0;
395 tmp0 = arg1;
396 arg1 = tmp1 - (env->sr & SR_T);
397 if (tmp0 < tmp1)
398 env->sr |= SR_T;
399 else
400 env->sr &= ~SR_T;
401 if (tmp1 < arg1)
402 env->sr |= SR_T;
403 return arg1;
406 uint32_t helper_subv(uint32_t arg0, uint32_t arg1)
408 int32_t dest, src, ans;
410 if ((int32_t) arg1 >= 0)
411 dest = 0;
412 else
413 dest = 1;
414 if ((int32_t) arg0 >= 0)
415 src = 0;
416 else
417 src = 1;
418 src += dest;
419 arg1 -= arg0;
420 if ((int32_t) arg1 >= 0)
421 ans = 0;
422 else
423 ans = 1;
424 ans += dest;
425 if (src == 1) {
426 if (ans == 1)
427 env->sr |= SR_T;
428 else
429 env->sr &= ~SR_T;
430 } else
431 env->sr &= ~SR_T;
432 return arg1;
435 static inline void set_t(void)
437 env->sr |= SR_T;
440 static inline void clr_t(void)
442 env->sr &= ~SR_T;
445 void helper_ld_fpscr(uint32_t val)
447 env->fpscr = val & 0x003fffff;
448 if (val & 0x01)
449 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
450 else
451 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
454 uint32_t helper_fabs_FT(uint32_t t0)
456 CPU_FloatU f;
457 f.l = t0;
458 f.f = float32_abs(f.f);
459 return f.l;
462 uint64_t helper_fabs_DT(uint64_t t0)
464 CPU_DoubleU d;
465 d.ll = t0;
466 d.d = float64_abs(d.d);
467 return d.ll;
470 uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
472 CPU_FloatU f0, f1;
473 f0.l = t0;
474 f1.l = t1;
475 f0.f = float32_add(f0.f, f1.f, &env->fp_status);
476 return f0.l;
479 uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
481 CPU_DoubleU d0, d1;
482 d0.ll = t0;
483 d1.ll = t1;
484 d0.d = float64_add(d0.d, d1.d, &env->fp_status);
485 return d0.ll;
488 void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
490 CPU_FloatU f0, f1;
491 f0.l = t0;
492 f1.l = t1;
494 if (float32_compare(f0.f, f1.f, &env->fp_status) == 0)
495 set_t();
496 else
497 clr_t();
500 void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
502 CPU_DoubleU d0, d1;
503 d0.ll = t0;
504 d1.ll = t1;
506 if (float64_compare(d0.d, d1.d, &env->fp_status) == 0)
507 set_t();
508 else
509 clr_t();
512 void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
514 CPU_FloatU f0, f1;
515 f0.l = t0;
516 f1.l = t1;
518 if (float32_compare(f0.f, f1.f, &env->fp_status) == 1)
519 set_t();
520 else
521 clr_t();
524 void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
526 CPU_DoubleU d0, d1;
527 d0.ll = t0;
528 d1.ll = t1;
530 if (float64_compare(d0.d, d1.d, &env->fp_status) == 1)
531 set_t();
532 else
533 clr_t();
536 uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
538 CPU_DoubleU d;
539 CPU_FloatU f;
540 f.l = t0;
541 d.d = float32_to_float64(f.f, &env->fp_status);
542 return d.ll;
545 uint32_t helper_fcnvds_DT_FT(uint64_t t0)
547 CPU_DoubleU d;
548 CPU_FloatU f;
549 d.ll = t0;
550 f.f = float64_to_float32(d.d, &env->fp_status);
551 return f.l;
554 uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
556 CPU_FloatU f0, f1;
557 f0.l = t0;
558 f1.l = t1;
559 f0.f = float32_div(f0.f, f1.f, &env->fp_status);
560 return f0.l;
563 uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
565 CPU_DoubleU d0, d1;
566 d0.ll = t0;
567 d1.ll = t1;
568 d0.d = float64_div(d0.d, d1.d, &env->fp_status);
569 return d0.ll;
572 uint32_t helper_float_FT(uint32_t t0)
574 CPU_FloatU f;
575 f.f = int32_to_float32(t0, &env->fp_status);
576 return f.l;
579 uint64_t helper_float_DT(uint32_t t0)
581 CPU_DoubleU d;
582 d.d = int32_to_float64(t0, &env->fp_status);
583 return d.ll;
586 uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2)
588 CPU_FloatU f0, f1, f2;
589 f0.l = t0;
590 f1.l = t1;
591 f2.l = t2;
592 f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
593 f0.f = float32_add(f0.f, f2.f, &env->fp_status);
594 return f0.l;
597 uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
599 CPU_FloatU f0, f1;
600 f0.l = t0;
601 f1.l = t1;
602 f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
603 return f0.l;
606 uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
608 CPU_DoubleU d0, d1;
609 d0.ll = t0;
610 d1.ll = t1;
611 d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
612 return d0.ll;
615 uint32_t helper_fneg_T(uint32_t t0)
617 CPU_FloatU f;
618 f.l = t0;
619 f.f = float32_chs(f.f);
620 return f.l;
623 uint32_t helper_fsqrt_FT(uint32_t t0)
625 CPU_FloatU f;
626 f.l = t0;
627 f.f = float32_sqrt(f.f, &env->fp_status);
628 return f.l;
631 uint64_t helper_fsqrt_DT(uint64_t t0)
633 CPU_DoubleU d;
634 d.ll = t0;
635 d.d = float64_sqrt(d.d, &env->fp_status);
636 return d.ll;
639 uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
641 CPU_FloatU f0, f1;
642 f0.l = t0;
643 f1.l = t1;
644 f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
645 return f0.l;
648 uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
650 CPU_DoubleU d0, d1;
651 d0.ll = t0;
652 d1.ll = t1;
653 d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
654 return d0.ll;
657 uint32_t helper_ftrc_FT(uint32_t t0)
659 CPU_FloatU f;
660 f.l = t0;
661 return float32_to_int32_round_to_zero(f.f, &env->fp_status);
664 uint32_t helper_ftrc_DT(uint64_t t0)
666 CPU_DoubleU d;
667 d.ll = t0;
668 return float64_to_int32_round_to_zero(d.d, &env->fp_status);