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
));
177 env
->cpu_model_str
= cpu_model
;
179 if (cpu_m68k_set_model(env
, cpu_model
) < 0) {
188 void cpu_m68k_close(CPUM68KState
*env
)
193 void cpu_m68k_flush_flags(CPUM68KState
*env
, int cc_op
)
200 #define HIGHBIT 0x80000000u
202 #define SET_NZ(x) do { \
205 else if ((int32_t)(x) < 0) \
209 #define SET_FLAGS_SUB(type, utype) do { \
210 SET_NZ((type)dest); \
212 if ((utype) tmp < (utype) src) \
214 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
233 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
237 SET_FLAGS_SUB(int32_t, uint32_t);
240 SET_FLAGS_SUB(int8_t, uint8_t);
243 SET_FLAGS_SUB(int16_t, uint16_t);
249 tmp
= dest
- src
- 1;
250 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
255 tmp
= dest
+ src
+ 1;
258 if (HIGHBIT
& (tmp
^ dest
) & (tmp
^ src
))
267 cpu_abort(env
, "Bad CC_OP %d", cc_op
);
269 env
->cc_op
= CC_OP_FLAGS
;
270 env
->cc_dest
= flags
;
273 void HELPER(movec
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
276 case 0x02: /* CACR */
280 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
281 /* TODO: Implement Access Control Registers. */
283 case 0x801: /* VBR */
286 /* TODO: Implement control registers. */
288 cpu_abort(env
, "Unimplemented control register write 0x%x = 0x%x\n",
293 void HELPER(set_macsr
)(CPUM68KState
*env
, uint32_t val
)
300 if ((env
->macsr
^ val
) & (MACSR_FI
| MACSR_SU
)) {
301 for (i
= 0; i
< 4; i
++) {
302 regval
= env
->macc
[i
];
303 exthigh
= regval
>> 40;
304 if (env
->macsr
& MACSR_FI
) {
309 extlow
= regval
>> 32;
311 if (env
->macsr
& MACSR_FI
) {
312 regval
= (((uint64_t)acc
) << 8) | extlow
;
313 regval
|= ((int64_t)exthigh
) << 40;
314 } else if (env
->macsr
& MACSR_SU
) {
315 regval
= acc
| (((int64_t)extlow
) << 32);
316 regval
|= ((int64_t)exthigh
) << 40;
318 regval
= acc
| (((uint64_t)extlow
) << 32);
319 regval
|= ((uint64_t)(uint8_t)exthigh
) << 40;
321 env
->macc
[i
] = regval
;
327 void m68k_switch_sp(CPUM68KState
*env
)
331 env
->sp
[env
->current_sp
] = env
->aregs
[7];
332 new_sp
= (env
->sr
& SR_S
&& env
->cacr
& M68K_CACR_EUSP
)
333 ? M68K_SSP
: M68K_USP
;
334 env
->aregs
[7] = env
->sp
[new_sp
];
335 env
->current_sp
= new_sp
;
340 /* TODO: This will need fixing once the MMU is implemented. */
341 target_phys_addr_t
cpu_get_phys_page_debug(CPUState
*env
, target_ulong addr
)
346 #if defined(CONFIG_USER_ONLY)
348 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
349 int mmu_idx
, int is_softmmu
)
351 env
->exception_index
= EXCP_ACCESS
;
352 env
->mmu
.ar
= address
;
358 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
359 int mmu_idx
, int is_softmmu
)
363 address
&= TARGET_PAGE_MASK
;
364 prot
= PAGE_READ
| PAGE_WRITE
;
365 return tlb_set_page(env
, address
, address
, prot
, mmu_idx
, is_softmmu
);
368 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
369 be handled by the interrupt controller. Real hardware only requests
370 the vector when the interrupt is acknowledged by the CPU. For
371 simplicitly we calculate it when the interrupt is signalled. */
372 void m68k_set_irq_level(CPUM68KState
*env
, int level
, uint8_t vector
)
374 env
->pending_level
= level
;
375 env
->pending_vector
= vector
;
377 cpu_interrupt(env
, CPU_INTERRUPT_HARD
);
379 cpu_reset_interrupt(env
, CPU_INTERRUPT_HARD
);
384 uint32_t HELPER(bitrev
)(uint32_t x
)
386 x
= ((x
>> 1) & 0x55555555u
) | ((x
<< 1) & 0xaaaaaaaau
);
387 x
= ((x
>> 2) & 0x33333333u
) | ((x
<< 2) & 0xccccccccu
);
388 x
= ((x
>> 4) & 0x0f0f0f0fu
) | ((x
<< 4) & 0xf0f0f0f0u
);
392 uint32_t HELPER(ff1
)(uint32_t x
)
400 uint32_t HELPER(sats
)(uint32_t val
, uint32_t ccr
)
402 /* The result has the opposite sign to the original value. */
404 val
= (((int32_t)val
) >> 31) ^ SIGNBIT
;
408 uint32_t HELPER(subx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
413 old_flags
= env
->cc_dest
;
415 env
->cc_x
= (op1
<= op2
);
416 env
->cc_op
= CC_OP_SUBX
;
417 res
= op1
- (op2
+ 1);
419 env
->cc_x
= (op1
< op2
);
420 env
->cc_op
= CC_OP_SUB
;
425 cpu_m68k_flush_flags(env
, env
->cc_op
);
427 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
431 uint32_t HELPER(addx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
436 old_flags
= env
->cc_dest
;
439 env
->cc_x
= (res
<= op2
);
440 env
->cc_op
= CC_OP_ADDX
;
443 env
->cc_x
= (res
< op2
);
444 env
->cc_op
= CC_OP_ADD
;
448 cpu_m68k_flush_flags(env
, env
->cc_op
);
450 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
454 uint32_t HELPER(xflag_lt
)(uint32_t a
, uint32_t b
)
459 uint32_t HELPER(btest
)(uint32_t x
)
464 void HELPER(set_sr
)(CPUState
*env
, uint32_t val
)
466 env
->sr
= val
& 0xffff;
470 uint32_t HELPER(shl_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
478 cf
= env
->cc_src
& CCF_C
;
479 } else if (shift
< 32) {
480 result
= val
<< shift
;
481 cf
= (val
>> (32 - shift
)) & 1;
482 } else if (shift
== 32) {
485 } else /* shift > 32 */ {
490 env
->cc_x
= (cf
!= 0);
491 env
->cc_dest
= result
;
495 uint32_t HELPER(shr_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
503 cf
= env
->cc_src
& CCF_C
;
504 } else if (shift
< 32) {
505 result
= val
>> shift
;
506 cf
= (val
>> (shift
- 1)) & 1;
507 } else if (shift
== 32) {
510 } else /* shift > 32 */ {
515 env
->cc_x
= (cf
!= 0);
516 env
->cc_dest
= result
;
520 uint32_t HELPER(sar_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
528 cf
= (env
->cc_src
& CCF_C
) != 0;
529 } else if (shift
< 32) {
530 result
= (int32_t)val
>> shift
;
531 cf
= (val
>> (shift
- 1)) & 1;
532 } else /* shift >= 32 */ {
533 result
= (int32_t)val
>> 31;
538 env
->cc_dest
= result
;
543 uint32_t HELPER(f64_to_i32
)(CPUState
*env
, float64 val
)
545 return float64_to_int32(val
, &env
->fp_status
);
548 float32
HELPER(f64_to_f32
)(CPUState
*env
, float64 val
)
550 return float64_to_float32(val
, &env
->fp_status
);
553 float64
HELPER(i32_to_f64
)(CPUState
*env
, uint32_t val
)
555 return int32_to_float64(val
, &env
->fp_status
);
558 float64
HELPER(f32_to_f64
)(CPUState
*env
, float32 val
)
560 return float32_to_float64(val
, &env
->fp_status
);
563 float64
HELPER(iround_f64
)(CPUState
*env
, float64 val
)
565 return float64_round_to_int(val
, &env
->fp_status
);
568 float64
HELPER(itrunc_f64
)(CPUState
*env
, float64 val
)
570 return float64_trunc_to_int(val
, &env
->fp_status
);
573 float64
HELPER(sqrt_f64
)(CPUState
*env
, float64 val
)
575 return float64_sqrt(val
, &env
->fp_status
);
578 float64
HELPER(abs_f64
)(float64 val
)
580 return float64_abs(val
);
583 float64
HELPER(chs_f64
)(float64 val
)
585 return float64_chs(val
);
588 float64
HELPER(add_f64
)(CPUState
*env
, float64 a
, float64 b
)
590 return float64_add(a
, b
, &env
->fp_status
);
593 float64
HELPER(sub_f64
)(CPUState
*env
, float64 a
, float64 b
)
595 return float64_sub(a
, b
, &env
->fp_status
);
598 float64
HELPER(mul_f64
)(CPUState
*env
, float64 a
, float64 b
)
600 return float64_mul(a
, b
, &env
->fp_status
);
603 float64
HELPER(div_f64
)(CPUState
*env
, float64 a
, float64 b
)
605 return float64_div(a
, b
, &env
->fp_status
);
608 float64
HELPER(sub_cmp_f64
)(CPUState
*env
, float64 a
, float64 b
)
610 /* ??? This may incorrectly raise exceptions. */
611 /* ??? Should flush denormals to zero. */
613 res
= float64_sub(a
, b
, &env
->fp_status
);
614 if (float64_is_nan(res
)) {
615 /* +/-inf compares equal against itself, but sub returns nan. */
616 if (!float64_is_nan(a
)
617 && !float64_is_nan(b
)) {
619 if (float64_lt_quiet(a
, res
, &env
->fp_status
))
620 res
= float64_chs(res
);
626 uint32_t HELPER(compare_f64
)(CPUState
*env
, float64 val
)
628 return float64_compare_quiet(val
, float64_zero
, &env
->fp_status
);
632 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
633 take values, others take register numbers and manipulate the contents
635 void HELPER(mac_move
)(CPUState
*env
, uint32_t dest
, uint32_t src
)
638 env
->macc
[dest
] = env
->macc
[src
];
639 mask
= MACSR_PAV0
<< dest
;
640 if (env
->macsr
& (MACSR_PAV0
<< src
))
646 uint64_t HELPER(macmuls
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
651 product
= (uint64_t)op1
* op2
;
652 res
= (product
<< 24) >> 24;
653 if (res
!= product
) {
654 env
->macsr
|= MACSR_V
;
655 if (env
->macsr
& MACSR_OMC
) {
656 /* Make sure the accumulate operation overflows. */
666 uint64_t HELPER(macmulu
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
670 product
= (uint64_t)op1
* op2
;
671 if (product
& (0xffffffull
<< 40)) {
672 env
->macsr
|= MACSR_V
;
673 if (env
->macsr
& MACSR_OMC
) {
674 /* Make sure the accumulate operation overflows. */
677 product
&= ((1ull << 40) - 1);
683 uint64_t HELPER(macmulf
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
688 product
= (uint64_t)op1
* op2
;
689 if (env
->macsr
& MACSR_RT
) {
690 remainder
= product
& 0xffffff;
692 if (remainder
> 0x800000)
694 else if (remainder
== 0x800000)
695 product
+= (product
& 1);
702 void HELPER(macsats
)(CPUState
*env
, uint32_t acc
)
706 tmp
= env
->macc
[acc
];
707 result
= ((tmp
<< 16) >> 16);
709 env
->macsr
|= MACSR_V
;
711 if (env
->macsr
& MACSR_V
) {
712 env
->macsr
|= MACSR_PAV0
<< acc
;
713 if (env
->macsr
& MACSR_OMC
) {
714 /* The result is saturated to 32 bits, despite overflow occuring
715 at 48 bits. Seems weird, but that's what the hardware docs
717 result
= (result
>> 63) ^ 0x7fffffff;
720 env
->macc
[acc
] = result
;
723 void HELPER(macsatu
)(CPUState
*env
, uint32_t acc
)
727 val
= env
->macc
[acc
];
728 if (val
& (0xffffull
<< 48)) {
729 env
->macsr
|= MACSR_V
;
731 if (env
->macsr
& MACSR_V
) {
732 env
->macsr
|= MACSR_PAV0
<< acc
;
733 if (env
->macsr
& MACSR_OMC
) {
734 if (val
> (1ull << 53))
737 val
= (1ull << 48) - 1;
739 val
&= ((1ull << 48) - 1);
742 env
->macc
[acc
] = val
;
745 void HELPER(macsatf
)(CPUState
*env
, uint32_t acc
)
750 sum
= env
->macc
[acc
];
751 result
= (sum
<< 16) >> 16;
753 env
->macsr
|= MACSR_V
;
755 if (env
->macsr
& MACSR_V
) {
756 env
->macsr
|= MACSR_PAV0
<< acc
;
757 if (env
->macsr
& MACSR_OMC
) {
758 result
= (result
>> 63) ^ 0x7fffffffffffll
;
761 env
->macc
[acc
] = result
;
764 void HELPER(mac_set_flags
)(CPUState
*env
, uint32_t acc
)
767 val
= env
->macc
[acc
];
769 env
->macsr
|= MACSR_Z
;
770 else if (val
& (1ull << 47));
771 env
->macsr
|= MACSR_N
;
772 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
773 env
->macsr
|= MACSR_V
;
775 if (env
->macsr
& MACSR_FI
) {
776 val
= ((int64_t)val
) >> 40;
777 if (val
!= 0 && val
!= -1)
778 env
->macsr
|= MACSR_EV
;
779 } else if (env
->macsr
& MACSR_SU
) {
780 val
= ((int64_t)val
) >> 32;
781 if (val
!= 0 && val
!= -1)
782 env
->macsr
|= MACSR_EV
;
784 if ((val
>> 32) != 0)
785 env
->macsr
|= MACSR_EV
;
789 void HELPER(flush_flags
)(CPUState
*env
, uint32_t cc_op
)
791 cpu_m68k_flush_flags(env
, cc_op
);
794 uint32_t HELPER(get_macf
)(CPUState
*env
, uint64_t val
)
799 if (env
->macsr
& MACSR_SU
) {
800 /* 16-bit rounding. */
801 rem
= val
& 0xffffff;
802 val
= (val
>> 24) & 0xffffu
;
805 else if (rem
== 0x800000)
807 } else if (env
->macsr
& MACSR_RT
) {
808 /* 32-bit rounding. */
813 else if (rem
== 0x80)
819 if (env
->macsr
& MACSR_OMC
) {
821 if (env
->macsr
& MACSR_SU
) {
822 if (val
!= (uint16_t) val
) {
823 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
825 result
= val
& 0xffff;
828 if (val
!= (uint32_t)val
) {
829 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
831 result
= (uint32_t)val
;
836 if (env
->macsr
& MACSR_SU
) {
837 result
= val
& 0xffff;
839 result
= (uint32_t)val
;
845 uint32_t HELPER(get_macs
)(uint64_t val
)
847 if (val
== (int32_t)val
) {
850 return (val
>> 61) ^ ~SIGNBIT
;
854 uint32_t HELPER(get_macu
)(uint64_t val
)
856 if ((val
>> 32) == 0) {
857 return (uint32_t)val
;
863 uint32_t HELPER(get_mac_extf
)(CPUState
*env
, uint32_t acc
)
866 val
= env
->macc
[acc
] & 0x00ff;
867 val
= (env
->macc
[acc
] >> 32) & 0xff00;
868 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
869 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
873 uint32_t HELPER(get_mac_exti
)(CPUState
*env
, uint32_t acc
)
876 val
= (env
->macc
[acc
] >> 32) & 0xffff;
877 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
881 void HELPER(set_mac_extf
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
885 res
= env
->macc
[acc
] & 0xffffffff00ull
;
886 tmp
= (int16_t)(val
& 0xff00);
887 res
|= ((int64_t)tmp
) << 32;
889 env
->macc
[acc
] = res
;
890 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
891 tmp
= (val
& 0xff000000);
892 res
|= ((int64_t)tmp
) << 16;
893 res
|= (val
>> 16) & 0xff;
894 env
->macc
[acc
+ 1] = res
;
897 void HELPER(set_mac_exts
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
901 res
= (uint32_t)env
->macc
[acc
];
903 res
|= ((int64_t)tmp
) << 32;
904 env
->macc
[acc
] = res
;
905 res
= (uint32_t)env
->macc
[acc
+ 1];
906 tmp
= val
& 0xffff0000;
907 res
|= (int64_t)tmp
<< 16;
908 env
->macc
[acc
+ 1] = res
;
911 void HELPER(set_mac_extu
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
914 res
= (uint32_t)env
->macc
[acc
];
915 res
|= ((uint64_t)(val
& 0xffff)) << 32;
916 env
->macc
[acc
] = res
;
917 res
= (uint32_t)env
->macc
[acc
+ 1];
918 res
|= (uint64_t)(val
& 0xffff0000) << 16;
919 env
->macc
[acc
+ 1] = res
;