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, see <http://www.gnu.org/licenses/>.
26 #include "qemu-common.h"
31 #define SIGNBIT (1u << 31)
40 typedef struct m68k_def_t m68k_def_t
;
47 static m68k_def_t m68k_cpu_defs
[] = {
48 {"m5206", M68K_CPUID_M5206
},
49 {"m5208", M68K_CPUID_M5208
},
50 {"cfv4e", M68K_CPUID_CFV4E
},
51 {"any", M68K_CPUID_ANY
},
55 void m68k_cpu_list(FILE *f
, fprintf_function cpu_fprintf
)
59 for (i
= 0; m68k_cpu_defs
[i
].name
; i
++) {
60 (*cpu_fprintf
)(f
, "%s\n", m68k_cpu_defs
[i
].name
);
64 static int fpu_gdb_get_reg(CPUState
*env
, uint8_t *mem_buf
, int n
)
67 stfq_p(mem_buf
, env
->fregs
[n
]);
71 /* FP control registers (not implemented) */
72 memset(mem_buf
, 0, 4);
78 static int fpu_gdb_set_reg(CPUState
*env
, uint8_t *mem_buf
, int n
)
81 env
->fregs
[n
] = ldfq_p(mem_buf
);
85 /* FP control registers (not implemented) */
91 static void m68k_set_feature(CPUM68KState
*env
, int feature
)
93 env
->features
|= (1u << feature
);
96 static int cpu_m68k_set_model(CPUM68KState
*env
, const char *name
)
100 for (def
= m68k_cpu_defs
; def
->name
; def
++) {
101 if (strcmp(def
->name
, name
) == 0)
108 case M68K_CPUID_M5206
:
109 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
111 case M68K_CPUID_M5208
:
112 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
113 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_APLUSC
);
114 m68k_set_feature(env
, M68K_FEATURE_BRAL
);
115 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC
);
116 m68k_set_feature(env
, M68K_FEATURE_USP
);
118 case M68K_CPUID_CFV4E
:
119 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
120 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_B
);
121 m68k_set_feature(env
, M68K_FEATURE_BRAL
);
122 m68k_set_feature(env
, M68K_FEATURE_CF_FPU
);
123 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC
);
124 m68k_set_feature(env
, M68K_FEATURE_USP
);
127 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
128 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_B
);
129 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_APLUSC
);
130 m68k_set_feature(env
, M68K_FEATURE_BRAL
);
131 m68k_set_feature(env
, M68K_FEATURE_CF_FPU
);
132 /* MAC and EMAC are mututally exclusive, so pick EMAC.
133 It's mostly backwards compatible. */
134 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC
);
135 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC_B
);
136 m68k_set_feature(env
, M68K_FEATURE_USP
);
137 m68k_set_feature(env
, M68K_FEATURE_EXT_FULL
);
138 m68k_set_feature(env
, M68K_FEATURE_WORD_INDEX
);
142 register_m68k_insns(env
);
143 if (m68k_feature (env
, M68K_FEATURE_CF_FPU
)) {
144 gdb_register_coprocessor(env
, fpu_gdb_get_reg
, fpu_gdb_set_reg
,
145 11, "cf-fp.xml", 18);
147 /* TODO: Add [E]MAC registers. */
151 void cpu_reset(CPUM68KState
*env
)
153 if (qemu_loglevel_mask(CPU_LOG_RESET
)) {
154 qemu_log("CPU Reset (CPU %d)\n", env
->cpu_index
);
155 log_cpu_state(env
, 0);
158 memset(env
, 0, offsetof(CPUM68KState
, breakpoints
));
159 #if !defined (CONFIG_USER_ONLY)
163 /* ??? FP regs should be initialized to NaN. */
164 env
->cc_op
= CC_OP_FLAGS
;
165 /* TODO: We should set PC from the interrupt vector. */
170 CPUM68KState
*cpu_m68k_init(const char *cpu_model
)
175 env
= g_malloc0(sizeof(CPUM68KState
));
182 env
->cpu_model_str
= cpu_model
;
184 if (cpu_m68k_set_model(env
, cpu_model
) < 0) {
194 void cpu_m68k_close(CPUM68KState
*env
)
199 void cpu_m68k_flush_flags(CPUM68KState
*env
, int cc_op
)
206 #define HIGHBIT 0x80000000u
208 #define SET_NZ(x) do { \
211 else if ((int32_t)(x) < 0) \
215 #define SET_FLAGS_SUB(type, utype) do { \
216 SET_NZ((type)dest); \
218 if ((utype) tmp < (utype) src) \
220 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
239 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
243 SET_FLAGS_SUB(int32_t, uint32_t);
246 SET_FLAGS_SUB(int8_t, uint8_t);
249 SET_FLAGS_SUB(int16_t, uint16_t);
255 tmp
= dest
- src
- 1;
256 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
261 tmp
= dest
+ src
+ 1;
264 if (HIGHBIT
& (tmp
^ dest
) & (tmp
^ src
))
273 cpu_abort(env
, "Bad CC_OP %d", cc_op
);
275 env
->cc_op
= CC_OP_FLAGS
;
276 env
->cc_dest
= flags
;
279 void HELPER(movec
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
282 case 0x02: /* CACR */
286 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
287 /* TODO: Implement Access Control Registers. */
289 case 0x801: /* VBR */
292 /* TODO: Implement control registers. */
294 cpu_abort(env
, "Unimplemented control register write 0x%x = 0x%x\n",
299 void HELPER(set_macsr
)(CPUM68KState
*env
, uint32_t val
)
306 if ((env
->macsr
^ val
) & (MACSR_FI
| MACSR_SU
)) {
307 for (i
= 0; i
< 4; i
++) {
308 regval
= env
->macc
[i
];
309 exthigh
= regval
>> 40;
310 if (env
->macsr
& MACSR_FI
) {
315 extlow
= regval
>> 32;
317 if (env
->macsr
& MACSR_FI
) {
318 regval
= (((uint64_t)acc
) << 8) | extlow
;
319 regval
|= ((int64_t)exthigh
) << 40;
320 } else if (env
->macsr
& MACSR_SU
) {
321 regval
= acc
| (((int64_t)extlow
) << 32);
322 regval
|= ((int64_t)exthigh
) << 40;
324 regval
= acc
| (((uint64_t)extlow
) << 32);
325 regval
|= ((uint64_t)(uint8_t)exthigh
) << 40;
327 env
->macc
[i
] = regval
;
333 void m68k_switch_sp(CPUM68KState
*env
)
337 env
->sp
[env
->current_sp
] = env
->aregs
[7];
338 new_sp
= (env
->sr
& SR_S
&& env
->cacr
& M68K_CACR_EUSP
)
339 ? M68K_SSP
: M68K_USP
;
340 env
->aregs
[7] = env
->sp
[new_sp
];
341 env
->current_sp
= new_sp
;
344 #if defined(CONFIG_USER_ONLY)
346 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
349 env
->exception_index
= EXCP_ACCESS
;
350 env
->mmu
.ar
= address
;
358 /* TODO: This will need fixing once the MMU is implemented. */
359 target_phys_addr_t
cpu_get_phys_page_debug(CPUState
*env
, target_ulong addr
)
364 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
369 address
&= TARGET_PAGE_MASK
;
370 prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
371 tlb_set_page(env
, address
, address
, prot
, mmu_idx
, TARGET_PAGE_SIZE
);
375 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
376 be handled by the interrupt controller. Real hardware only requests
377 the vector when the interrupt is acknowledged by the CPU. For
378 simplicitly we calculate it when the interrupt is signalled. */
379 void m68k_set_irq_level(CPUM68KState
*env
, int level
, uint8_t vector
)
381 env
->pending_level
= level
;
382 env
->pending_vector
= vector
;
384 cpu_interrupt(env
, CPU_INTERRUPT_HARD
);
386 cpu_reset_interrupt(env
, CPU_INTERRUPT_HARD
);
391 uint32_t HELPER(bitrev
)(uint32_t x
)
393 x
= ((x
>> 1) & 0x55555555u
) | ((x
<< 1) & 0xaaaaaaaau
);
394 x
= ((x
>> 2) & 0x33333333u
) | ((x
<< 2) & 0xccccccccu
);
395 x
= ((x
>> 4) & 0x0f0f0f0fu
) | ((x
<< 4) & 0xf0f0f0f0u
);
399 uint32_t HELPER(ff1
)(uint32_t x
)
407 uint32_t HELPER(sats
)(uint32_t val
, uint32_t ccr
)
409 /* The result has the opposite sign to the original value. */
411 val
= (((int32_t)val
) >> 31) ^ SIGNBIT
;
415 uint32_t HELPER(subx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
420 old_flags
= env
->cc_dest
;
422 env
->cc_x
= (op1
<= op2
);
423 env
->cc_op
= CC_OP_SUBX
;
424 res
= op1
- (op2
+ 1);
426 env
->cc_x
= (op1
< op2
);
427 env
->cc_op
= CC_OP_SUB
;
432 cpu_m68k_flush_flags(env
, env
->cc_op
);
434 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
438 uint32_t HELPER(addx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
443 old_flags
= env
->cc_dest
;
446 env
->cc_x
= (res
<= op2
);
447 env
->cc_op
= CC_OP_ADDX
;
450 env
->cc_x
= (res
< op2
);
451 env
->cc_op
= CC_OP_ADD
;
455 cpu_m68k_flush_flags(env
, env
->cc_op
);
457 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
461 uint32_t HELPER(xflag_lt
)(uint32_t a
, uint32_t b
)
466 void HELPER(set_sr
)(CPUState
*env
, uint32_t val
)
468 env
->sr
= val
& 0xffff;
472 uint32_t HELPER(shl_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
480 cf
= env
->cc_src
& CCF_C
;
481 } else if (shift
< 32) {
482 result
= val
<< shift
;
483 cf
= (val
>> (32 - shift
)) & 1;
484 } else if (shift
== 32) {
487 } else /* shift > 32 */ {
492 env
->cc_x
= (cf
!= 0);
493 env
->cc_dest
= result
;
497 uint32_t HELPER(shr_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
505 cf
= env
->cc_src
& CCF_C
;
506 } else if (shift
< 32) {
507 result
= val
>> shift
;
508 cf
= (val
>> (shift
- 1)) & 1;
509 } else if (shift
== 32) {
512 } else /* shift > 32 */ {
517 env
->cc_x
= (cf
!= 0);
518 env
->cc_dest
= result
;
522 uint32_t HELPER(sar_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
530 cf
= (env
->cc_src
& CCF_C
) != 0;
531 } else if (shift
< 32) {
532 result
= (int32_t)val
>> shift
;
533 cf
= (val
>> (shift
- 1)) & 1;
534 } else /* shift >= 32 */ {
535 result
= (int32_t)val
>> 31;
540 env
->cc_dest
= result
;
545 uint32_t HELPER(f64_to_i32
)(CPUState
*env
, float64 val
)
547 return float64_to_int32(val
, &env
->fp_status
);
550 float32
HELPER(f64_to_f32
)(CPUState
*env
, float64 val
)
552 return float64_to_float32(val
, &env
->fp_status
);
555 float64
HELPER(i32_to_f64
)(CPUState
*env
, uint32_t val
)
557 return int32_to_float64(val
, &env
->fp_status
);
560 float64
HELPER(f32_to_f64
)(CPUState
*env
, float32 val
)
562 return float32_to_float64(val
, &env
->fp_status
);
565 float64
HELPER(iround_f64
)(CPUState
*env
, float64 val
)
567 return float64_round_to_int(val
, &env
->fp_status
);
570 float64
HELPER(itrunc_f64
)(CPUState
*env
, float64 val
)
572 return float64_trunc_to_int(val
, &env
->fp_status
);
575 float64
HELPER(sqrt_f64
)(CPUState
*env
, float64 val
)
577 return float64_sqrt(val
, &env
->fp_status
);
580 float64
HELPER(abs_f64
)(float64 val
)
582 return float64_abs(val
);
585 float64
HELPER(chs_f64
)(float64 val
)
587 return float64_chs(val
);
590 float64
HELPER(add_f64
)(CPUState
*env
, float64 a
, float64 b
)
592 return float64_add(a
, b
, &env
->fp_status
);
595 float64
HELPER(sub_f64
)(CPUState
*env
, float64 a
, float64 b
)
597 return float64_sub(a
, b
, &env
->fp_status
);
600 float64
HELPER(mul_f64
)(CPUState
*env
, float64 a
, float64 b
)
602 return float64_mul(a
, b
, &env
->fp_status
);
605 float64
HELPER(div_f64
)(CPUState
*env
, float64 a
, float64 b
)
607 return float64_div(a
, b
, &env
->fp_status
);
610 float64
HELPER(sub_cmp_f64
)(CPUState
*env
, float64 a
, float64 b
)
612 /* ??? This may incorrectly raise exceptions. */
613 /* ??? Should flush denormals to zero. */
615 res
= float64_sub(a
, b
, &env
->fp_status
);
616 if (float64_is_quiet_nan(res
)) {
617 /* +/-inf compares equal against itself, but sub returns nan. */
618 if (!float64_is_quiet_nan(a
)
619 && !float64_is_quiet_nan(b
)) {
621 if (float64_lt_quiet(a
, res
, &env
->fp_status
))
622 res
= float64_chs(res
);
628 uint32_t HELPER(compare_f64
)(CPUState
*env
, float64 val
)
630 return float64_compare_quiet(val
, float64_zero
, &env
->fp_status
);
634 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
635 take values, others take register numbers and manipulate the contents
637 void HELPER(mac_move
)(CPUState
*env
, uint32_t dest
, uint32_t src
)
640 env
->macc
[dest
] = env
->macc
[src
];
641 mask
= MACSR_PAV0
<< dest
;
642 if (env
->macsr
& (MACSR_PAV0
<< src
))
648 uint64_t HELPER(macmuls
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
653 product
= (uint64_t)op1
* op2
;
654 res
= (product
<< 24) >> 24;
655 if (res
!= product
) {
656 env
->macsr
|= MACSR_V
;
657 if (env
->macsr
& MACSR_OMC
) {
658 /* Make sure the accumulate operation overflows. */
668 uint64_t HELPER(macmulu
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
672 product
= (uint64_t)op1
* op2
;
673 if (product
& (0xffffffull
<< 40)) {
674 env
->macsr
|= MACSR_V
;
675 if (env
->macsr
& MACSR_OMC
) {
676 /* Make sure the accumulate operation overflows. */
679 product
&= ((1ull << 40) - 1);
685 uint64_t HELPER(macmulf
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
690 product
= (uint64_t)op1
* op2
;
691 if (env
->macsr
& MACSR_RT
) {
692 remainder
= product
& 0xffffff;
694 if (remainder
> 0x800000)
696 else if (remainder
== 0x800000)
697 product
+= (product
& 1);
704 void HELPER(macsats
)(CPUState
*env
, uint32_t acc
)
708 tmp
= env
->macc
[acc
];
709 result
= ((tmp
<< 16) >> 16);
711 env
->macsr
|= MACSR_V
;
713 if (env
->macsr
& MACSR_V
) {
714 env
->macsr
|= MACSR_PAV0
<< acc
;
715 if (env
->macsr
& MACSR_OMC
) {
716 /* The result is saturated to 32 bits, despite overflow occurring
717 at 48 bits. Seems weird, but that's what the hardware docs
719 result
= (result
>> 63) ^ 0x7fffffff;
722 env
->macc
[acc
] = result
;
725 void HELPER(macsatu
)(CPUState
*env
, uint32_t acc
)
729 val
= env
->macc
[acc
];
730 if (val
& (0xffffull
<< 48)) {
731 env
->macsr
|= MACSR_V
;
733 if (env
->macsr
& MACSR_V
) {
734 env
->macsr
|= MACSR_PAV0
<< acc
;
735 if (env
->macsr
& MACSR_OMC
) {
736 if (val
> (1ull << 53))
739 val
= (1ull << 48) - 1;
741 val
&= ((1ull << 48) - 1);
744 env
->macc
[acc
] = val
;
747 void HELPER(macsatf
)(CPUState
*env
, uint32_t acc
)
752 sum
= env
->macc
[acc
];
753 result
= (sum
<< 16) >> 16;
755 env
->macsr
|= MACSR_V
;
757 if (env
->macsr
& MACSR_V
) {
758 env
->macsr
|= MACSR_PAV0
<< acc
;
759 if (env
->macsr
& MACSR_OMC
) {
760 result
= (result
>> 63) ^ 0x7fffffffffffll
;
763 env
->macc
[acc
] = result
;
766 void HELPER(mac_set_flags
)(CPUState
*env
, uint32_t acc
)
769 val
= env
->macc
[acc
];
771 env
->macsr
|= MACSR_Z
;
772 } else if (val
& (1ull << 47)) {
773 env
->macsr
|= MACSR_N
;
775 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
776 env
->macsr
|= MACSR_V
;
778 if (env
->macsr
& MACSR_FI
) {
779 val
= ((int64_t)val
) >> 40;
780 if (val
!= 0 && val
!= -1)
781 env
->macsr
|= MACSR_EV
;
782 } else if (env
->macsr
& MACSR_SU
) {
783 val
= ((int64_t)val
) >> 32;
784 if (val
!= 0 && val
!= -1)
785 env
->macsr
|= MACSR_EV
;
787 if ((val
>> 32) != 0)
788 env
->macsr
|= MACSR_EV
;
792 void HELPER(flush_flags
)(CPUState
*env
, uint32_t cc_op
)
794 cpu_m68k_flush_flags(env
, cc_op
);
797 uint32_t HELPER(get_macf
)(CPUState
*env
, uint64_t val
)
802 if (env
->macsr
& MACSR_SU
) {
803 /* 16-bit rounding. */
804 rem
= val
& 0xffffff;
805 val
= (val
>> 24) & 0xffffu
;
808 else if (rem
== 0x800000)
810 } else if (env
->macsr
& MACSR_RT
) {
811 /* 32-bit rounding. */
816 else if (rem
== 0x80)
822 if (env
->macsr
& MACSR_OMC
) {
824 if (env
->macsr
& MACSR_SU
) {
825 if (val
!= (uint16_t) val
) {
826 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
828 result
= val
& 0xffff;
831 if (val
!= (uint32_t)val
) {
832 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
834 result
= (uint32_t)val
;
839 if (env
->macsr
& MACSR_SU
) {
840 result
= val
& 0xffff;
842 result
= (uint32_t)val
;
848 uint32_t HELPER(get_macs
)(uint64_t val
)
850 if (val
== (int32_t)val
) {
853 return (val
>> 61) ^ ~SIGNBIT
;
857 uint32_t HELPER(get_macu
)(uint64_t val
)
859 if ((val
>> 32) == 0) {
860 return (uint32_t)val
;
866 uint32_t HELPER(get_mac_extf
)(CPUState
*env
, uint32_t acc
)
869 val
= env
->macc
[acc
] & 0x00ff;
870 val
= (env
->macc
[acc
] >> 32) & 0xff00;
871 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
872 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
876 uint32_t HELPER(get_mac_exti
)(CPUState
*env
, uint32_t acc
)
879 val
= (env
->macc
[acc
] >> 32) & 0xffff;
880 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
884 void HELPER(set_mac_extf
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
888 res
= env
->macc
[acc
] & 0xffffffff00ull
;
889 tmp
= (int16_t)(val
& 0xff00);
890 res
|= ((int64_t)tmp
) << 32;
892 env
->macc
[acc
] = res
;
893 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
894 tmp
= (val
& 0xff000000);
895 res
|= ((int64_t)tmp
) << 16;
896 res
|= (val
>> 16) & 0xff;
897 env
->macc
[acc
+ 1] = res
;
900 void HELPER(set_mac_exts
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
904 res
= (uint32_t)env
->macc
[acc
];
906 res
|= ((int64_t)tmp
) << 32;
907 env
->macc
[acc
] = res
;
908 res
= (uint32_t)env
->macc
[acc
+ 1];
909 tmp
= val
& 0xffff0000;
910 res
|= (int64_t)tmp
<< 16;
911 env
->macc
[acc
+ 1] = res
;
914 void HELPER(set_mac_extu
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
917 res
= (uint32_t)env
->macc
[acc
];
918 res
|= ((uint64_t)(val
& 0xffff)) << 32;
919 env
->macc
[acc
] = res
;
920 res
= (uint32_t)env
->macc
[acc
+ 1];
921 res
|= (uint64_t)(val
& 0xffff0000) << 16;
922 env
->macc
[acc
+ 1] = res
;