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 if (qemu_loglevel_mask(CPU_LOG_RESET
)) {
147 qemu_log("CPU Reset (CPU %d)\n", env
->cpu_index
);
148 log_cpu_state(env
, 0);
151 memset(env
, 0, offsetof(CPUM68KState
, breakpoints
));
152 #if !defined (CONFIG_USER_ONLY)
156 /* ??? FP regs should be initialized to NaN. */
157 env
->cc_op
= CC_OP_FLAGS
;
158 /* TODO: We should set PC from the interrupt vector. */
163 CPUM68KState
*cpu_m68k_init(const char *cpu_model
)
168 env
= qemu_mallocz(sizeof(CPUM68KState
));
175 env
->cpu_model_str
= cpu_model
;
177 if (cpu_m68k_set_model(env
, cpu_model
) < 0) {
186 void cpu_m68k_close(CPUM68KState
*env
)
191 void cpu_m68k_flush_flags(CPUM68KState
*env
, int cc_op
)
198 #define HIGHBIT 0x80000000u
200 #define SET_NZ(x) do { \
203 else if ((int32_t)(x) < 0) \
207 #define SET_FLAGS_SUB(type, utype) do { \
208 SET_NZ((type)dest); \
210 if ((utype) tmp < (utype) src) \
212 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
231 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
235 SET_FLAGS_SUB(int32_t, uint32_t);
238 SET_FLAGS_SUB(int8_t, uint8_t);
241 SET_FLAGS_SUB(int16_t, uint16_t);
247 tmp
= dest
- src
- 1;
248 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
253 tmp
= dest
+ src
+ 1;
256 if (HIGHBIT
& (tmp
^ dest
) & (tmp
^ src
))
265 cpu_abort(env
, "Bad CC_OP %d", cc_op
);
267 env
->cc_op
= CC_OP_FLAGS
;
268 env
->cc_dest
= flags
;
271 void HELPER(movec
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
274 case 0x02: /* CACR */
278 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
279 /* TODO: Implement Access Control Registers. */
281 case 0x801: /* VBR */
284 /* TODO: Implement control registers. */
286 cpu_abort(env
, "Unimplemented control register write 0x%x = 0x%x\n",
291 void HELPER(set_macsr
)(CPUM68KState
*env
, uint32_t val
)
298 if ((env
->macsr
^ val
) & (MACSR_FI
| MACSR_SU
)) {
299 for (i
= 0; i
< 4; i
++) {
300 regval
= env
->macc
[i
];
301 exthigh
= regval
>> 40;
302 if (env
->macsr
& MACSR_FI
) {
307 extlow
= regval
>> 32;
309 if (env
->macsr
& MACSR_FI
) {
310 regval
= (((uint64_t)acc
) << 8) | extlow
;
311 regval
|= ((int64_t)exthigh
) << 40;
312 } else if (env
->macsr
& MACSR_SU
) {
313 regval
= acc
| (((int64_t)extlow
) << 32);
314 regval
|= ((int64_t)exthigh
) << 40;
316 regval
= acc
| (((uint64_t)extlow
) << 32);
317 regval
|= ((uint64_t)(uint8_t)exthigh
) << 40;
319 env
->macc
[i
] = regval
;
325 void m68k_switch_sp(CPUM68KState
*env
)
329 env
->sp
[env
->current_sp
] = env
->aregs
[7];
330 new_sp
= (env
->sr
& SR_S
&& env
->cacr
& M68K_CACR_EUSP
)
331 ? M68K_SSP
: M68K_USP
;
332 env
->aregs
[7] = env
->sp
[new_sp
];
333 env
->current_sp
= new_sp
;
338 /* TODO: This will need fixing once the MMU is implemented. */
339 target_phys_addr_t
cpu_get_phys_page_debug(CPUState
*env
, target_ulong addr
)
344 #if defined(CONFIG_USER_ONLY)
346 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
347 int mmu_idx
, int is_softmmu
)
349 env
->exception_index
= EXCP_ACCESS
;
350 env
->mmu
.ar
= address
;
356 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
357 int mmu_idx
, int is_softmmu
)
361 address
&= TARGET_PAGE_MASK
;
362 prot
= PAGE_READ
| PAGE_WRITE
;
363 return tlb_set_page(env
, address
, address
, prot
, mmu_idx
, is_softmmu
);
366 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
367 be handled by the interrupt controller. Real hardware only requests
368 the vector when the interrupt is acknowledged by the CPU. For
369 simplicitly we calculate it when the interrupt is signalled. */
370 void m68k_set_irq_level(CPUM68KState
*env
, int level
, uint8_t vector
)
372 env
->pending_level
= level
;
373 env
->pending_vector
= vector
;
375 cpu_interrupt(env
, CPU_INTERRUPT_HARD
);
377 cpu_reset_interrupt(env
, CPU_INTERRUPT_HARD
);
382 uint32_t HELPER(bitrev
)(uint32_t x
)
384 x
= ((x
>> 1) & 0x55555555u
) | ((x
<< 1) & 0xaaaaaaaau
);
385 x
= ((x
>> 2) & 0x33333333u
) | ((x
<< 2) & 0xccccccccu
);
386 x
= ((x
>> 4) & 0x0f0f0f0fu
) | ((x
<< 4) & 0xf0f0f0f0u
);
390 uint32_t HELPER(ff1
)(uint32_t x
)
398 uint32_t HELPER(sats
)(uint32_t val
, uint32_t ccr
)
400 /* The result has the opposite sign to the original value. */
402 val
= (((int32_t)val
) >> 31) ^ SIGNBIT
;
406 uint32_t HELPER(subx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
411 old_flags
= env
->cc_dest
;
413 env
->cc_x
= (op1
<= op2
);
414 env
->cc_op
= CC_OP_SUBX
;
415 res
= op1
- (op2
+ 1);
417 env
->cc_x
= (op1
< op2
);
418 env
->cc_op
= CC_OP_SUB
;
423 cpu_m68k_flush_flags(env
, env
->cc_op
);
425 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
429 uint32_t HELPER(addx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
434 old_flags
= env
->cc_dest
;
437 env
->cc_x
= (res
<= op2
);
438 env
->cc_op
= CC_OP_ADDX
;
441 env
->cc_x
= (res
< op2
);
442 env
->cc_op
= CC_OP_ADD
;
446 cpu_m68k_flush_flags(env
, env
->cc_op
);
448 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
452 uint32_t HELPER(xflag_lt
)(uint32_t a
, uint32_t b
)
457 void HELPER(set_sr
)(CPUState
*env
, uint32_t val
)
459 env
->sr
= val
& 0xffff;
463 uint32_t HELPER(shl_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
471 cf
= env
->cc_src
& CCF_C
;
472 } else if (shift
< 32) {
473 result
= val
<< shift
;
474 cf
= (val
>> (32 - shift
)) & 1;
475 } else if (shift
== 32) {
478 } else /* shift > 32 */ {
483 env
->cc_x
= (cf
!= 0);
484 env
->cc_dest
= result
;
488 uint32_t HELPER(shr_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
496 cf
= env
->cc_src
& CCF_C
;
497 } else if (shift
< 32) {
498 result
= val
>> shift
;
499 cf
= (val
>> (shift
- 1)) & 1;
500 } else if (shift
== 32) {
503 } else /* shift > 32 */ {
508 env
->cc_x
= (cf
!= 0);
509 env
->cc_dest
= result
;
513 uint32_t HELPER(sar_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
521 cf
= (env
->cc_src
& CCF_C
) != 0;
522 } else if (shift
< 32) {
523 result
= (int32_t)val
>> shift
;
524 cf
= (val
>> (shift
- 1)) & 1;
525 } else /* shift >= 32 */ {
526 result
= (int32_t)val
>> 31;
531 env
->cc_dest
= result
;
536 uint32_t HELPER(f64_to_i32
)(CPUState
*env
, float64 val
)
538 return float64_to_int32(val
, &env
->fp_status
);
541 float32
HELPER(f64_to_f32
)(CPUState
*env
, float64 val
)
543 return float64_to_float32(val
, &env
->fp_status
);
546 float64
HELPER(i32_to_f64
)(CPUState
*env
, uint32_t val
)
548 return int32_to_float64(val
, &env
->fp_status
);
551 float64
HELPER(f32_to_f64
)(CPUState
*env
, float32 val
)
553 return float32_to_float64(val
, &env
->fp_status
);
556 float64
HELPER(iround_f64
)(CPUState
*env
, float64 val
)
558 return float64_round_to_int(val
, &env
->fp_status
);
561 float64
HELPER(itrunc_f64
)(CPUState
*env
, float64 val
)
563 return float64_trunc_to_int(val
, &env
->fp_status
);
566 float64
HELPER(sqrt_f64
)(CPUState
*env
, float64 val
)
568 return float64_sqrt(val
, &env
->fp_status
);
571 float64
HELPER(abs_f64
)(float64 val
)
573 return float64_abs(val
);
576 float64
HELPER(chs_f64
)(float64 val
)
578 return float64_chs(val
);
581 float64
HELPER(add_f64
)(CPUState
*env
, float64 a
, float64 b
)
583 return float64_add(a
, b
, &env
->fp_status
);
586 float64
HELPER(sub_f64
)(CPUState
*env
, float64 a
, float64 b
)
588 return float64_sub(a
, b
, &env
->fp_status
);
591 float64
HELPER(mul_f64
)(CPUState
*env
, float64 a
, float64 b
)
593 return float64_mul(a
, b
, &env
->fp_status
);
596 float64
HELPER(div_f64
)(CPUState
*env
, float64 a
, float64 b
)
598 return float64_div(a
, b
, &env
->fp_status
);
601 float64
HELPER(sub_cmp_f64
)(CPUState
*env
, float64 a
, float64 b
)
603 /* ??? This may incorrectly raise exceptions. */
604 /* ??? Should flush denormals to zero. */
606 res
= float64_sub(a
, b
, &env
->fp_status
);
607 if (float64_is_nan(res
)) {
608 /* +/-inf compares equal against itself, but sub returns nan. */
609 if (!float64_is_nan(a
)
610 && !float64_is_nan(b
)) {
612 if (float64_lt_quiet(a
, res
, &env
->fp_status
))
613 res
= float64_chs(res
);
619 uint32_t HELPER(compare_f64
)(CPUState
*env
, float64 val
)
621 return float64_compare_quiet(val
, float64_zero
, &env
->fp_status
);
625 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
626 take values, others take register numbers and manipulate the contents
628 void HELPER(mac_move
)(CPUState
*env
, uint32_t dest
, uint32_t src
)
631 env
->macc
[dest
] = env
->macc
[src
];
632 mask
= MACSR_PAV0
<< dest
;
633 if (env
->macsr
& (MACSR_PAV0
<< src
))
639 uint64_t HELPER(macmuls
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
644 product
= (uint64_t)op1
* op2
;
645 res
= (product
<< 24) >> 24;
646 if (res
!= product
) {
647 env
->macsr
|= MACSR_V
;
648 if (env
->macsr
& MACSR_OMC
) {
649 /* Make sure the accumulate operation overflows. */
659 uint64_t HELPER(macmulu
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
663 product
= (uint64_t)op1
* op2
;
664 if (product
& (0xffffffull
<< 40)) {
665 env
->macsr
|= MACSR_V
;
666 if (env
->macsr
& MACSR_OMC
) {
667 /* Make sure the accumulate operation overflows. */
670 product
&= ((1ull << 40) - 1);
676 uint64_t HELPER(macmulf
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
681 product
= (uint64_t)op1
* op2
;
682 if (env
->macsr
& MACSR_RT
) {
683 remainder
= product
& 0xffffff;
685 if (remainder
> 0x800000)
687 else if (remainder
== 0x800000)
688 product
+= (product
& 1);
695 void HELPER(macsats
)(CPUState
*env
, uint32_t acc
)
699 tmp
= env
->macc
[acc
];
700 result
= ((tmp
<< 16) >> 16);
702 env
->macsr
|= MACSR_V
;
704 if (env
->macsr
& MACSR_V
) {
705 env
->macsr
|= MACSR_PAV0
<< acc
;
706 if (env
->macsr
& MACSR_OMC
) {
707 /* The result is saturated to 32 bits, despite overflow occuring
708 at 48 bits. Seems weird, but that's what the hardware docs
710 result
= (result
>> 63) ^ 0x7fffffff;
713 env
->macc
[acc
] = result
;
716 void HELPER(macsatu
)(CPUState
*env
, uint32_t acc
)
720 val
= env
->macc
[acc
];
721 if (val
& (0xffffull
<< 48)) {
722 env
->macsr
|= MACSR_V
;
724 if (env
->macsr
& MACSR_V
) {
725 env
->macsr
|= MACSR_PAV0
<< acc
;
726 if (env
->macsr
& MACSR_OMC
) {
727 if (val
> (1ull << 53))
730 val
= (1ull << 48) - 1;
732 val
&= ((1ull << 48) - 1);
735 env
->macc
[acc
] = val
;
738 void HELPER(macsatf
)(CPUState
*env
, uint32_t acc
)
743 sum
= env
->macc
[acc
];
744 result
= (sum
<< 16) >> 16;
746 env
->macsr
|= MACSR_V
;
748 if (env
->macsr
& MACSR_V
) {
749 env
->macsr
|= MACSR_PAV0
<< acc
;
750 if (env
->macsr
& MACSR_OMC
) {
751 result
= (result
>> 63) ^ 0x7fffffffffffll
;
754 env
->macc
[acc
] = result
;
757 void HELPER(mac_set_flags
)(CPUState
*env
, uint32_t acc
)
760 val
= env
->macc
[acc
];
762 env
->macsr
|= MACSR_Z
;
763 else if (val
& (1ull << 47));
764 env
->macsr
|= MACSR_N
;
765 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
766 env
->macsr
|= MACSR_V
;
768 if (env
->macsr
& MACSR_FI
) {
769 val
= ((int64_t)val
) >> 40;
770 if (val
!= 0 && val
!= -1)
771 env
->macsr
|= MACSR_EV
;
772 } else if (env
->macsr
& MACSR_SU
) {
773 val
= ((int64_t)val
) >> 32;
774 if (val
!= 0 && val
!= -1)
775 env
->macsr
|= MACSR_EV
;
777 if ((val
>> 32) != 0)
778 env
->macsr
|= MACSR_EV
;
782 void HELPER(flush_flags
)(CPUState
*env
, uint32_t cc_op
)
784 cpu_m68k_flush_flags(env
, cc_op
);
787 uint32_t HELPER(get_macf
)(CPUState
*env
, uint64_t val
)
792 if (env
->macsr
& MACSR_SU
) {
793 /* 16-bit rounding. */
794 rem
= val
& 0xffffff;
795 val
= (val
>> 24) & 0xffffu
;
798 else if (rem
== 0x800000)
800 } else if (env
->macsr
& MACSR_RT
) {
801 /* 32-bit rounding. */
806 else if (rem
== 0x80)
812 if (env
->macsr
& MACSR_OMC
) {
814 if (env
->macsr
& MACSR_SU
) {
815 if (val
!= (uint16_t) val
) {
816 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
818 result
= val
& 0xffff;
821 if (val
!= (uint32_t)val
) {
822 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
824 result
= (uint32_t)val
;
829 if (env
->macsr
& MACSR_SU
) {
830 result
= val
& 0xffff;
832 result
= (uint32_t)val
;
838 uint32_t HELPER(get_macs
)(uint64_t val
)
840 if (val
== (int32_t)val
) {
843 return (val
>> 61) ^ ~SIGNBIT
;
847 uint32_t HELPER(get_macu
)(uint64_t val
)
849 if ((val
>> 32) == 0) {
850 return (uint32_t)val
;
856 uint32_t HELPER(get_mac_extf
)(CPUState
*env
, uint32_t acc
)
859 val
= env
->macc
[acc
] & 0x00ff;
860 val
= (env
->macc
[acc
] >> 32) & 0xff00;
861 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
862 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
866 uint32_t HELPER(get_mac_exti
)(CPUState
*env
, uint32_t acc
)
869 val
= (env
->macc
[acc
] >> 32) & 0xffff;
870 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
874 void HELPER(set_mac_extf
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
878 res
= env
->macc
[acc
] & 0xffffffff00ull
;
879 tmp
= (int16_t)(val
& 0xff00);
880 res
|= ((int64_t)tmp
) << 32;
882 env
->macc
[acc
] = res
;
883 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
884 tmp
= (val
& 0xff000000);
885 res
|= ((int64_t)tmp
) << 16;
886 res
|= (val
>> 16) & 0xff;
887 env
->macc
[acc
+ 1] = res
;
890 void HELPER(set_mac_exts
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
894 res
= (uint32_t)env
->macc
[acc
];
896 res
|= ((int64_t)tmp
) << 32;
897 env
->macc
[acc
] = res
;
898 res
= (uint32_t)env
->macc
[acc
+ 1];
899 tmp
= val
& 0xffff0000;
900 res
|= (int64_t)tmp
<< 16;
901 env
->macc
[acc
+ 1] = res
;
904 void HELPER(set_mac_extu
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
907 res
= (uint32_t)env
->macc
[acc
];
908 res
|= ((uint64_t)(val
& 0xffff)) << 32;
909 env
->macc
[acc
] = res
;
910 res
= (uint32_t)env
->macc
[acc
+ 1];
911 res
|= (uint64_t)(val
& 0xffff0000) << 16;
912 env
->macc
[acc
+ 1] = res
;