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 uint32_t HELPER(btest
)(uint32_t x
)
462 void HELPER(set_sr
)(CPUState
*env
, uint32_t val
)
464 env
->sr
= val
& 0xffff;
468 uint32_t HELPER(shl_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
476 cf
= env
->cc_src
& CCF_C
;
477 } else if (shift
< 32) {
478 result
= val
<< shift
;
479 cf
= (val
>> (32 - shift
)) & 1;
480 } else if (shift
== 32) {
483 } else /* shift > 32 */ {
488 env
->cc_x
= (cf
!= 0);
489 env
->cc_dest
= result
;
493 uint32_t HELPER(shr_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
501 cf
= env
->cc_src
& CCF_C
;
502 } else if (shift
< 32) {
503 result
= val
>> shift
;
504 cf
= (val
>> (shift
- 1)) & 1;
505 } else if (shift
== 32) {
508 } else /* shift > 32 */ {
513 env
->cc_x
= (cf
!= 0);
514 env
->cc_dest
= result
;
518 uint32_t HELPER(sar_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
526 cf
= (env
->cc_src
& CCF_C
) != 0;
527 } else if (shift
< 32) {
528 result
= (int32_t)val
>> shift
;
529 cf
= (val
>> (shift
- 1)) & 1;
530 } else /* shift >= 32 */ {
531 result
= (int32_t)val
>> 31;
536 env
->cc_dest
= result
;
541 uint32_t HELPER(f64_to_i32
)(CPUState
*env
, float64 val
)
543 return float64_to_int32(val
, &env
->fp_status
);
546 float32
HELPER(f64_to_f32
)(CPUState
*env
, float64 val
)
548 return float64_to_float32(val
, &env
->fp_status
);
551 float64
HELPER(i32_to_f64
)(CPUState
*env
, uint32_t val
)
553 return int32_to_float64(val
, &env
->fp_status
);
556 float64
HELPER(f32_to_f64
)(CPUState
*env
, float32 val
)
558 return float32_to_float64(val
, &env
->fp_status
);
561 float64
HELPER(iround_f64
)(CPUState
*env
, float64 val
)
563 return float64_round_to_int(val
, &env
->fp_status
);
566 float64
HELPER(itrunc_f64
)(CPUState
*env
, float64 val
)
568 return float64_trunc_to_int(val
, &env
->fp_status
);
571 float64
HELPER(sqrt_f64
)(CPUState
*env
, float64 val
)
573 return float64_sqrt(val
, &env
->fp_status
);
576 float64
HELPER(abs_f64
)(float64 val
)
578 return float64_abs(val
);
581 float64
HELPER(chs_f64
)(float64 val
)
583 return float64_chs(val
);
586 float64
HELPER(add_f64
)(CPUState
*env
, float64 a
, float64 b
)
588 return float64_add(a
, b
, &env
->fp_status
);
591 float64
HELPER(sub_f64
)(CPUState
*env
, float64 a
, float64 b
)
593 return float64_sub(a
, b
, &env
->fp_status
);
596 float64
HELPER(mul_f64
)(CPUState
*env
, float64 a
, float64 b
)
598 return float64_mul(a
, b
, &env
->fp_status
);
601 float64
HELPER(div_f64
)(CPUState
*env
, float64 a
, float64 b
)
603 return float64_div(a
, b
, &env
->fp_status
);
606 float64
HELPER(sub_cmp_f64
)(CPUState
*env
, float64 a
, float64 b
)
608 /* ??? This may incorrectly raise exceptions. */
609 /* ??? Should flush denormals to zero. */
611 res
= float64_sub(a
, b
, &env
->fp_status
);
612 if (float64_is_nan(res
)) {
613 /* +/-inf compares equal against itself, but sub returns nan. */
614 if (!float64_is_nan(a
)
615 && !float64_is_nan(b
)) {
617 if (float64_lt_quiet(a
, res
, &env
->fp_status
))
618 res
= float64_chs(res
);
624 uint32_t HELPER(compare_f64
)(CPUState
*env
, float64 val
)
626 return float64_compare_quiet(val
, float64_zero
, &env
->fp_status
);
630 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
631 take values, others take register numbers and manipulate the contents
633 void HELPER(mac_move
)(CPUState
*env
, uint32_t dest
, uint32_t src
)
636 env
->macc
[dest
] = env
->macc
[src
];
637 mask
= MACSR_PAV0
<< dest
;
638 if (env
->macsr
& (MACSR_PAV0
<< src
))
644 uint64_t HELPER(macmuls
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
649 product
= (uint64_t)op1
* op2
;
650 res
= (product
<< 24) >> 24;
651 if (res
!= product
) {
652 env
->macsr
|= MACSR_V
;
653 if (env
->macsr
& MACSR_OMC
) {
654 /* Make sure the accumulate operation overflows. */
664 uint64_t HELPER(macmulu
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
668 product
= (uint64_t)op1
* op2
;
669 if (product
& (0xffffffull
<< 40)) {
670 env
->macsr
|= MACSR_V
;
671 if (env
->macsr
& MACSR_OMC
) {
672 /* Make sure the accumulate operation overflows. */
675 product
&= ((1ull << 40) - 1);
681 uint64_t HELPER(macmulf
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
686 product
= (uint64_t)op1
* op2
;
687 if (env
->macsr
& MACSR_RT
) {
688 remainder
= product
& 0xffffff;
690 if (remainder
> 0x800000)
692 else if (remainder
== 0x800000)
693 product
+= (product
& 1);
700 void HELPER(macsats
)(CPUState
*env
, uint32_t acc
)
704 tmp
= env
->macc
[acc
];
705 result
= ((tmp
<< 16) >> 16);
707 env
->macsr
|= MACSR_V
;
709 if (env
->macsr
& MACSR_V
) {
710 env
->macsr
|= MACSR_PAV0
<< acc
;
711 if (env
->macsr
& MACSR_OMC
) {
712 /* The result is saturated to 32 bits, despite overflow occuring
713 at 48 bits. Seems weird, but that's what the hardware docs
715 result
= (result
>> 63) ^ 0x7fffffff;
718 env
->macc
[acc
] = result
;
721 void HELPER(macsatu
)(CPUState
*env
, uint32_t acc
)
725 val
= env
->macc
[acc
];
726 if (val
& (0xffffull
<< 48)) {
727 env
->macsr
|= MACSR_V
;
729 if (env
->macsr
& MACSR_V
) {
730 env
->macsr
|= MACSR_PAV0
<< acc
;
731 if (env
->macsr
& MACSR_OMC
) {
732 if (val
> (1ull << 53))
735 val
= (1ull << 48) - 1;
737 val
&= ((1ull << 48) - 1);
740 env
->macc
[acc
] = val
;
743 void HELPER(macsatf
)(CPUState
*env
, uint32_t acc
)
748 sum
= env
->macc
[acc
];
749 result
= (sum
<< 16) >> 16;
751 env
->macsr
|= MACSR_V
;
753 if (env
->macsr
& MACSR_V
) {
754 env
->macsr
|= MACSR_PAV0
<< acc
;
755 if (env
->macsr
& MACSR_OMC
) {
756 result
= (result
>> 63) ^ 0x7fffffffffffll
;
759 env
->macc
[acc
] = result
;
762 void HELPER(mac_set_flags
)(CPUState
*env
, uint32_t acc
)
765 val
= env
->macc
[acc
];
767 env
->macsr
|= MACSR_Z
;
768 else if (val
& (1ull << 47));
769 env
->macsr
|= MACSR_N
;
770 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
771 env
->macsr
|= MACSR_V
;
773 if (env
->macsr
& MACSR_FI
) {
774 val
= ((int64_t)val
) >> 40;
775 if (val
!= 0 && val
!= -1)
776 env
->macsr
|= MACSR_EV
;
777 } else if (env
->macsr
& MACSR_SU
) {
778 val
= ((int64_t)val
) >> 32;
779 if (val
!= 0 && val
!= -1)
780 env
->macsr
|= MACSR_EV
;
782 if ((val
>> 32) != 0)
783 env
->macsr
|= MACSR_EV
;
787 void HELPER(flush_flags
)(CPUState
*env
, uint32_t cc_op
)
789 cpu_m68k_flush_flags(env
, cc_op
);
792 uint32_t HELPER(get_macf
)(CPUState
*env
, uint64_t val
)
797 if (env
->macsr
& MACSR_SU
) {
798 /* 16-bit rounding. */
799 rem
= val
& 0xffffff;
800 val
= (val
>> 24) & 0xffffu
;
803 else if (rem
== 0x800000)
805 } else if (env
->macsr
& MACSR_RT
) {
806 /* 32-bit rounding. */
811 else if (rem
== 0x80)
817 if (env
->macsr
& MACSR_OMC
) {
819 if (env
->macsr
& MACSR_SU
) {
820 if (val
!= (uint16_t) val
) {
821 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
823 result
= val
& 0xffff;
826 if (val
!= (uint32_t)val
) {
827 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
829 result
= (uint32_t)val
;
834 if (env
->macsr
& MACSR_SU
) {
835 result
= val
& 0xffff;
837 result
= (uint32_t)val
;
843 uint32_t HELPER(get_macs
)(uint64_t val
)
845 if (val
== (int32_t)val
) {
848 return (val
>> 61) ^ ~SIGNBIT
;
852 uint32_t HELPER(get_macu
)(uint64_t val
)
854 if ((val
>> 32) == 0) {
855 return (uint32_t)val
;
861 uint32_t HELPER(get_mac_extf
)(CPUState
*env
, uint32_t acc
)
864 val
= env
->macc
[acc
] & 0x00ff;
865 val
= (env
->macc
[acc
] >> 32) & 0xff00;
866 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
867 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
871 uint32_t HELPER(get_mac_exti
)(CPUState
*env
, uint32_t acc
)
874 val
= (env
->macc
[acc
] >> 32) & 0xffff;
875 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
879 void HELPER(set_mac_extf
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
883 res
= env
->macc
[acc
] & 0xffffffff00ull
;
884 tmp
= (int16_t)(val
& 0xff00);
885 res
|= ((int64_t)tmp
) << 32;
887 env
->macc
[acc
] = res
;
888 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
889 tmp
= (val
& 0xff000000);
890 res
|= ((int64_t)tmp
) << 16;
891 res
|= (val
>> 16) & 0xff;
892 env
->macc
[acc
+ 1] = res
;
895 void HELPER(set_mac_exts
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
899 res
= (uint32_t)env
->macc
[acc
];
901 res
|= ((int64_t)tmp
) << 32;
902 env
->macc
[acc
] = res
;
903 res
= (uint32_t)env
->macc
[acc
+ 1];
904 tmp
= val
& 0xffff0000;
905 res
|= (int64_t)tmp
<< 16;
906 env
->macc
[acc
+ 1] = res
;
909 void HELPER(set_mac_extu
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
912 res
= (uint32_t)env
->macc
[acc
];
913 res
|= ((uint64_t)(val
& 0xffff)) << 32;
914 env
->macc
[acc
] = res
;
915 res
= (uint32_t)env
->macc
[acc
+ 1];
916 res
|= (uint64_t)(val
& 0xffff0000) << 16;
917 env
->macc
[acc
+ 1] = res
;