4 * Copyright (c) 2006-2007 CodeSourcery
5 * Written by Paul Brook
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.
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 * 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, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
28 #include "qemu-common.h"
33 #define SIGNBIT (1u << 31)
42 typedef struct m68k_def_t m68k_def_t;
49 static m68k_def_t m68k_cpu_defs[] = {
50 {"m5206", M68K_CPUID_M5206},
51 {"m5208", M68K_CPUID_M5208},
52 {"cfv4e", M68K_CPUID_CFV4E},
53 {"any", M68K_CPUID_ANY},
57 static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
60 stfq_p(mem_buf, env->fregs[n]);
64 /* FP control registers (not implemented) */
65 memset(mem_buf, 0, 4);
71 static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
74 env->fregs[n] = ldfq_p(mem_buf);
78 /* FP control registers (not implemented) */
84 static void m68k_set_feature(CPUM68KState *env, int feature)
86 env->features |= (1u << feature);
89 static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
93 for (def = m68k_cpu_defs; def->name; def++) {
94 if (strcmp(def->name, name) == 0)
101 case M68K_CPUID_M5206:
102 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
104 case M68K_CPUID_M5208:
105 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
106 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
107 m68k_set_feature(env, M68K_FEATURE_BRAL);
108 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
109 m68k_set_feature(env, M68K_FEATURE_USP);
111 case M68K_CPUID_CFV4E:
112 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
113 m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
114 m68k_set_feature(env, M68K_FEATURE_BRAL);
115 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
116 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
117 m68k_set_feature(env, M68K_FEATURE_USP);
120 m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
121 m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
122 m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
123 m68k_set_feature(env, M68K_FEATURE_BRAL);
124 m68k_set_feature(env, M68K_FEATURE_CF_FPU);
125 /* MAC and EMAC are mututally exclusive, so pick EMAC.
126 It's mostly backwards compatible. */
127 m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
128 m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
129 m68k_set_feature(env, M68K_FEATURE_USP);
130 m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
131 m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
135 register_m68k_insns(env);
136 if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
137 gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
138 11, "cf-fp.xml", 18);
140 /* TODO: Add [E]MAC registers. */
144 void cpu_reset(CPUM68KState *env)
146 memset(env, 0, offsetof(CPUM68KState, breakpoints));
147 #if !defined (CONFIG_USER_ONLY)
151 /* ??? FP regs should be initialized to NaN. */
152 env->cc_op = CC_OP_FLAGS;
153 /* TODO: We should set PC from the interrupt vector. */
158 CPUM68KState *cpu_m68k_init(const char *cpu_model)
163 env = qemu_mallocz(sizeof(CPUM68KState));
172 env->cpu_model_str = cpu_model;
174 if (cpu_m68k_set_model(env, cpu_model) < 0) {
183 void cpu_m68k_close(CPUM68KState *env)
188 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
195 #define HIGHBIT 0x80000000u
197 #define SET_NZ(x) do { \
200 else if ((int32_t)(x) < 0) \
204 #define SET_FLAGS_SUB(type, utype) do { \
205 SET_NZ((type)dest); \
207 if ((utype) tmp < (utype) src) \
209 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
228 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
232 SET_FLAGS_SUB(int32_t, uint32_t);
235 SET_FLAGS_SUB(int8_t, uint8_t);
238 SET_FLAGS_SUB(int16_t, uint16_t);
244 tmp = dest - src - 1;
245 if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
250 tmp = dest + src + 1;
253 if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
262 cpu_abort(env, "Bad CC_OP %d", cc_op);
264 env->cc_op = CC_OP_FLAGS;
265 env->cc_dest = flags;
268 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
271 case 0x02: /* CACR */
275 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
276 /* TODO: Implement Access Control Registers. */
278 case 0x801: /* VBR */
281 /* TODO: Implement control registers. */
283 cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
288 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
295 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
296 for (i = 0; i < 4; i++) {
297 regval = env->macc[i];
298 exthigh = regval >> 40;
299 if (env->macsr & MACSR_FI) {
304 extlow = regval >> 32;
306 if (env->macsr & MACSR_FI) {
307 regval = (((uint64_t)acc) << 8) | extlow;
308 regval |= ((int64_t)exthigh) << 40;
309 } else if (env->macsr & MACSR_SU) {
310 regval = acc | (((int64_t)extlow) << 32);
311 regval |= ((int64_t)exthigh) << 40;
313 regval = acc | (((uint64_t)extlow) << 32);
314 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
316 env->macc[i] = regval;
322 void m68k_switch_sp(CPUM68KState *env)
326 env->sp[env->current_sp] = env->aregs[7];
327 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
328 ? M68K_SSP : M68K_USP;
329 env->aregs[7] = env->sp[new_sp];
330 env->current_sp = new_sp;
335 /* TODO: This will need fixing once the MMU is implemented. */
336 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
341 #if defined(CONFIG_USER_ONLY)
343 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
344 int mmu_idx, int is_softmmu)
346 env->exception_index = EXCP_ACCESS;
347 env->mmu.ar = address;
353 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
354 int mmu_idx, int is_softmmu)
358 address &= TARGET_PAGE_MASK;
359 prot = PAGE_READ | PAGE_WRITE;
360 return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
363 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
364 be handled by the interrupt controller. Real hardware only requests
365 the vector when the interrupt is acknowledged by the CPU. For
366 simplicitly we calculate it when the interrupt is signalled. */
367 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
369 env->pending_level = level;
370 env->pending_vector = vector;
372 cpu_interrupt(env, CPU_INTERRUPT_HARD);
374 cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
379 uint32_t HELPER(bitrev)(uint32_t x)
381 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
382 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
383 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
387 uint32_t HELPER(ff1)(uint32_t x)
395 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
397 /* The result has the opposite sign to the original value. */
399 val = (((int32_t)val) >> 31) ^ SIGNBIT;
403 uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
408 old_flags = env->cc_dest;
410 env->cc_x = (op1 <= op2);
411 env->cc_op = CC_OP_SUBX;
412 res = op1 - (op2 + 1);
414 env->cc_x = (op1 < op2);
415 env->cc_op = CC_OP_SUB;
420 cpu_m68k_flush_flags(env, env->cc_op);
422 env->cc_dest &= (old_flags | ~CCF_Z);
426 uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
431 old_flags = env->cc_dest;
434 env->cc_x = (res <= op2);
435 env->cc_op = CC_OP_ADDX;
438 env->cc_x = (res < op2);
439 env->cc_op = CC_OP_ADD;
443 cpu_m68k_flush_flags(env, env->cc_op);
445 env->cc_dest &= (old_flags | ~CCF_Z);
449 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
454 uint32_t HELPER(btest)(uint32_t x)
459 void HELPER(set_sr)(CPUState *env, uint32_t val)
461 env->sr = val & 0xffff;
465 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
473 cf = env->cc_src & CCF_C;
474 } else if (shift < 32) {
475 result = val << shift;
476 cf = (val >> (32 - shift)) & 1;
477 } else if (shift == 32) {
480 } else /* shift > 32 */ {
485 env->cc_x = (cf != 0);
486 env->cc_dest = result;
490 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
498 cf = env->cc_src & CCF_C;
499 } else if (shift < 32) {
500 result = val >> shift;
501 cf = (val >> (shift - 1)) & 1;
502 } else if (shift == 32) {
505 } else /* shift > 32 */ {
510 env->cc_x = (cf != 0);
511 env->cc_dest = result;
515 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
523 cf = (env->cc_src & CCF_C) != 0;
524 } else if (shift < 32) {
525 result = (int32_t)val >> shift;
526 cf = (val >> (shift - 1)) & 1;
527 } else /* shift >= 32 */ {
528 result = (int32_t)val >> 31;
533 env->cc_dest = result;
538 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
540 return float64_to_int32(val, &env->fp_status);
543 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
545 return float64_to_float32(val, &env->fp_status);
548 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
550 return int32_to_float64(val, &env->fp_status);
553 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
555 return float32_to_float64(val, &env->fp_status);
558 float64 HELPER(iround_f64)(CPUState *env, float64 val)
560 return float64_round_to_int(val, &env->fp_status);
563 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
565 return float64_trunc_to_int(val, &env->fp_status);
568 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
570 return float64_sqrt(val, &env->fp_status);
573 float64 HELPER(abs_f64)(float64 val)
575 return float64_abs(val);
578 float64 HELPER(chs_f64)(float64 val)
580 return float64_chs(val);
583 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
585 return float64_add(a, b, &env->fp_status);
588 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
590 return float64_sub(a, b, &env->fp_status);
593 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
595 return float64_mul(a, b, &env->fp_status);
598 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
600 return float64_div(a, b, &env->fp_status);
603 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
605 /* ??? This may incorrectly raise exceptions. */
606 /* ??? Should flush denormals to zero. */
608 res = float64_sub(a, b, &env->fp_status);
609 if (float64_is_nan(res)) {
610 /* +/-inf compares equal against itself, but sub returns nan. */
611 if (!float64_is_nan(a)
612 && !float64_is_nan(b)) {
614 if (float64_lt_quiet(a, res, &env->fp_status))
615 res = float64_chs(res);
621 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
623 return float64_compare_quiet(val, float64_zero, &env->fp_status);
627 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
628 take values, others take register numbers and manipulate the contents
630 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
633 env->macc[dest] = env->macc[src];
634 mask = MACSR_PAV0 << dest;
635 if (env->macsr & (MACSR_PAV0 << src))
641 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
646 product = (uint64_t)op1 * op2;
647 res = (product << 24) >> 24;
648 if (res != product) {
649 env->macsr |= MACSR_V;
650 if (env->macsr & MACSR_OMC) {
651 /* Make sure the accumulate operation overflows. */
661 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
665 product = (uint64_t)op1 * op2;
666 if (product & (0xffffffull << 40)) {
667 env->macsr |= MACSR_V;
668 if (env->macsr & MACSR_OMC) {
669 /* Make sure the accumulate operation overflows. */
672 product &= ((1ull << 40) - 1);
678 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
683 product = (uint64_t)op1 * op2;
684 if (env->macsr & MACSR_RT) {
685 remainder = product & 0xffffff;
687 if (remainder > 0x800000)
689 else if (remainder == 0x800000)
690 product += (product & 1);
697 void HELPER(macsats)(CPUState *env, uint32_t acc)
701 tmp = env->macc[acc];
702 result = ((tmp << 16) >> 16);
704 env->macsr |= MACSR_V;
706 if (env->macsr & MACSR_V) {
707 env->macsr |= MACSR_PAV0 << acc;
708 if (env->macsr & MACSR_OMC) {
709 /* The result is saturated to 32 bits, despite overflow occuring
710 at 48 bits. Seems weird, but that's what the hardware docs
712 result = (result >> 63) ^ 0x7fffffff;
715 env->macc[acc] = result;
718 void HELPER(macsatu)(CPUState *env, uint32_t acc)
722 val = env->macc[acc];
723 if (val & (0xffffull << 48)) {
724 env->macsr |= MACSR_V;
726 if (env->macsr & MACSR_V) {
727 env->macsr |= MACSR_PAV0 << acc;
728 if (env->macsr & MACSR_OMC) {
729 if (val > (1ull << 53))
732 val = (1ull << 48) - 1;
734 val &= ((1ull << 48) - 1);
737 env->macc[acc] = val;
740 void HELPER(macsatf)(CPUState *env, uint32_t acc)
745 sum = env->macc[acc];
746 result = (sum << 16) >> 16;
748 env->macsr |= MACSR_V;
750 if (env->macsr & MACSR_V) {
751 env->macsr |= MACSR_PAV0 << acc;
752 if (env->macsr & MACSR_OMC) {
753 result = (result >> 63) ^ 0x7fffffffffffll;
756 env->macc[acc] = result;
759 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
762 val = env->macc[acc];
764 env->macsr |= MACSR_Z;
765 else if (val & (1ull << 47));
766 env->macsr |= MACSR_N;
767 if (env->macsr & (MACSR_PAV0 << acc)) {
768 env->macsr |= MACSR_V;
770 if (env->macsr & MACSR_FI) {
771 val = ((int64_t)val) >> 40;
772 if (val != 0 && val != -1)
773 env->macsr |= MACSR_EV;
774 } else if (env->macsr & MACSR_SU) {
775 val = ((int64_t)val) >> 32;
776 if (val != 0 && val != -1)
777 env->macsr |= MACSR_EV;
779 if ((val >> 32) != 0)
780 env->macsr |= MACSR_EV;
784 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
786 cpu_m68k_flush_flags(env, cc_op);
789 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
794 if (env->macsr & MACSR_SU) {
795 /* 16-bit rounding. */
796 rem = val & 0xffffff;
797 val = (val >> 24) & 0xffffu;
800 else if (rem == 0x800000)
802 } else if (env->macsr & MACSR_RT) {
803 /* 32-bit rounding. */
808 else if (rem == 0x80)
814 if (env->macsr & MACSR_OMC) {
816 if (env->macsr & MACSR_SU) {
817 if (val != (uint16_t) val) {
818 result = ((val >> 63) ^ 0x7fff) & 0xffff;
820 result = val & 0xffff;
823 if (val != (uint32_t)val) {
824 result = ((uint32_t)(val >> 63) & 0x7fffffff);
826 result = (uint32_t)val;
831 if (env->macsr & MACSR_SU) {
832 result = val & 0xffff;
834 result = (uint32_t)val;
840 uint32_t HELPER(get_macs)(uint64_t val)
842 if (val == (int32_t)val) {
845 return (val >> 61) ^ ~SIGNBIT;
849 uint32_t HELPER(get_macu)(uint64_t val)
851 if ((val >> 32) == 0) {
852 return (uint32_t)val;
858 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
861 val = env->macc[acc] & 0x00ff;
862 val = (env->macc[acc] >> 32) & 0xff00;
863 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
864 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
868 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
871 val = (env->macc[acc] >> 32) & 0xffff;
872 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
876 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
880 res = env->macc[acc] & 0xffffffff00ull;
881 tmp = (int16_t)(val & 0xff00);
882 res |= ((int64_t)tmp) << 32;
884 env->macc[acc] = res;
885 res = env->macc[acc + 1] & 0xffffffff00ull;
886 tmp = (val & 0xff000000);
887 res |= ((int64_t)tmp) << 16;
888 res |= (val >> 16) & 0xff;
889 env->macc[acc + 1] = res;
892 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
896 res = (uint32_t)env->macc[acc];
898 res |= ((int64_t)tmp) << 32;
899 env->macc[acc] = res;
900 res = (uint32_t)env->macc[acc + 1];
901 tmp = val & 0xffff0000;
902 res |= (int64_t)tmp << 16;
903 env->macc[acc + 1] = res;
906 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
909 res = (uint32_t)env->macc[acc];
910 res |= ((uint64_t)(val & 0xffff)) << 32;
911 env->macc[acc] = res;
912 res = (uint32_t)env->macc[acc + 1];
913 res |= (uint64_t)(val & 0xffff0000) << 16;
914 env->macc[acc + 1] = res;