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) {
187 void cpu_m68k_close(CPUM68KState
*env
)
192 void cpu_m68k_flush_flags(CPUM68KState
*env
, int cc_op
)
199 #define HIGHBIT 0x80000000u
201 #define SET_NZ(x) do { \
204 else if ((int32_t)(x) < 0) \
208 #define SET_FLAGS_SUB(type, utype) do { \
209 SET_NZ((type)dest); \
211 if ((utype) tmp < (utype) src) \
213 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
232 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
236 SET_FLAGS_SUB(int32_t, uint32_t);
239 SET_FLAGS_SUB(int8_t, uint8_t);
242 SET_FLAGS_SUB(int16_t, uint16_t);
248 tmp
= dest
- src
- 1;
249 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
254 tmp
= dest
+ src
+ 1;
257 if (HIGHBIT
& (tmp
^ dest
) & (tmp
^ src
))
266 cpu_abort(env
, "Bad CC_OP %d", cc_op
);
268 env
->cc_op
= CC_OP_FLAGS
;
269 env
->cc_dest
= flags
;
272 void HELPER(movec
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
275 case 0x02: /* CACR */
279 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
280 /* TODO: Implement Access Control Registers. */
282 case 0x801: /* VBR */
285 /* TODO: Implement control registers. */
287 cpu_abort(env
, "Unimplemented control register write 0x%x = 0x%x\n",
292 void HELPER(set_macsr
)(CPUM68KState
*env
, uint32_t val
)
299 if ((env
->macsr
^ val
) & (MACSR_FI
| MACSR_SU
)) {
300 for (i
= 0; i
< 4; i
++) {
301 regval
= env
->macc
[i
];
302 exthigh
= regval
>> 40;
303 if (env
->macsr
& MACSR_FI
) {
308 extlow
= regval
>> 32;
310 if (env
->macsr
& MACSR_FI
) {
311 regval
= (((uint64_t)acc
) << 8) | extlow
;
312 regval
|= ((int64_t)exthigh
) << 40;
313 } else if (env
->macsr
& MACSR_SU
) {
314 regval
= acc
| (((int64_t)extlow
) << 32);
315 regval
|= ((int64_t)exthigh
) << 40;
317 regval
= acc
| (((uint64_t)extlow
) << 32);
318 regval
|= ((uint64_t)(uint8_t)exthigh
) << 40;
320 env
->macc
[i
] = regval
;
326 void m68k_switch_sp(CPUM68KState
*env
)
330 env
->sp
[env
->current_sp
] = env
->aregs
[7];
331 new_sp
= (env
->sr
& SR_S
&& env
->cacr
& M68K_CACR_EUSP
)
332 ? M68K_SSP
: M68K_USP
;
333 env
->aregs
[7] = env
->sp
[new_sp
];
334 env
->current_sp
= new_sp
;
339 /* TODO: This will need fixing once the MMU is implemented. */
340 target_phys_addr_t
cpu_get_phys_page_debug(CPUState
*env
, target_ulong addr
)
345 #if defined(CONFIG_USER_ONLY)
347 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
348 int mmu_idx
, int is_softmmu
)
350 env
->exception_index
= EXCP_ACCESS
;
351 env
->mmu
.ar
= address
;
357 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
358 int mmu_idx
, int is_softmmu
)
362 address
&= TARGET_PAGE_MASK
;
363 prot
= PAGE_READ
| PAGE_WRITE
;
364 return tlb_set_page(env
, address
, address
, prot
, mmu_idx
, is_softmmu
);
367 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
368 be handled by the interrupt controller. Real hardware only requests
369 the vector when the interrupt is acknowledged by the CPU. For
370 simplicitly we calculate it when the interrupt is signalled. */
371 void m68k_set_irq_level(CPUM68KState
*env
, int level
, uint8_t vector
)
373 env
->pending_level
= level
;
374 env
->pending_vector
= vector
;
376 cpu_interrupt(env
, CPU_INTERRUPT_HARD
);
378 cpu_reset_interrupt(env
, CPU_INTERRUPT_HARD
);
383 uint32_t HELPER(bitrev
)(uint32_t x
)
385 x
= ((x
>> 1) & 0x55555555u
) | ((x
<< 1) & 0xaaaaaaaau
);
386 x
= ((x
>> 2) & 0x33333333u
) | ((x
<< 2) & 0xccccccccu
);
387 x
= ((x
>> 4) & 0x0f0f0f0fu
) | ((x
<< 4) & 0xf0f0f0f0u
);
391 uint32_t HELPER(ff1
)(uint32_t x
)
399 uint32_t HELPER(sats
)(uint32_t val
, uint32_t ccr
)
401 /* The result has the opposite sign to the original value. */
403 val
= (((int32_t)val
) >> 31) ^ SIGNBIT
;
407 uint32_t HELPER(subx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
412 old_flags
= env
->cc_dest
;
414 env
->cc_x
= (op1
<= op2
);
415 env
->cc_op
= CC_OP_SUBX
;
416 res
= op1
- (op2
+ 1);
418 env
->cc_x
= (op1
< op2
);
419 env
->cc_op
= CC_OP_SUB
;
424 cpu_m68k_flush_flags(env
, env
->cc_op
);
426 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
430 uint32_t HELPER(addx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
435 old_flags
= env
->cc_dest
;
438 env
->cc_x
= (res
<= op2
);
439 env
->cc_op
= CC_OP_ADDX
;
442 env
->cc_x
= (res
< op2
);
443 env
->cc_op
= CC_OP_ADD
;
447 cpu_m68k_flush_flags(env
, env
->cc_op
);
449 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
453 uint32_t HELPER(xflag_lt
)(uint32_t a
, uint32_t b
)
458 void HELPER(set_sr
)(CPUState
*env
, uint32_t val
)
460 env
->sr
= val
& 0xffff;
464 uint32_t HELPER(shl_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
472 cf
= env
->cc_src
& CCF_C
;
473 } else if (shift
< 32) {
474 result
= val
<< shift
;
475 cf
= (val
>> (32 - shift
)) & 1;
476 } else if (shift
== 32) {
479 } else /* shift > 32 */ {
484 env
->cc_x
= (cf
!= 0);
485 env
->cc_dest
= result
;
489 uint32_t HELPER(shr_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
497 cf
= env
->cc_src
& CCF_C
;
498 } else if (shift
< 32) {
499 result
= val
>> shift
;
500 cf
= (val
>> (shift
- 1)) & 1;
501 } else if (shift
== 32) {
504 } else /* shift > 32 */ {
509 env
->cc_x
= (cf
!= 0);
510 env
->cc_dest
= result
;
514 uint32_t HELPER(sar_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
522 cf
= (env
->cc_src
& CCF_C
) != 0;
523 } else if (shift
< 32) {
524 result
= (int32_t)val
>> shift
;
525 cf
= (val
>> (shift
- 1)) & 1;
526 } else /* shift >= 32 */ {
527 result
= (int32_t)val
>> 31;
532 env
->cc_dest
= result
;
537 uint32_t HELPER(f64_to_i32
)(CPUState
*env
, float64 val
)
539 return float64_to_int32(val
, &env
->fp_status
);
542 float32
HELPER(f64_to_f32
)(CPUState
*env
, float64 val
)
544 return float64_to_float32(val
, &env
->fp_status
);
547 float64
HELPER(i32_to_f64
)(CPUState
*env
, uint32_t val
)
549 return int32_to_float64(val
, &env
->fp_status
);
552 float64
HELPER(f32_to_f64
)(CPUState
*env
, float32 val
)
554 return float32_to_float64(val
, &env
->fp_status
);
557 float64
HELPER(iround_f64
)(CPUState
*env
, float64 val
)
559 return float64_round_to_int(val
, &env
->fp_status
);
562 float64
HELPER(itrunc_f64
)(CPUState
*env
, float64 val
)
564 return float64_trunc_to_int(val
, &env
->fp_status
);
567 float64
HELPER(sqrt_f64
)(CPUState
*env
, float64 val
)
569 return float64_sqrt(val
, &env
->fp_status
);
572 float64
HELPER(abs_f64
)(float64 val
)
574 return float64_abs(val
);
577 float64
HELPER(chs_f64
)(float64 val
)
579 return float64_chs(val
);
582 float64
HELPER(add_f64
)(CPUState
*env
, float64 a
, float64 b
)
584 return float64_add(a
, b
, &env
->fp_status
);
587 float64
HELPER(sub_f64
)(CPUState
*env
, float64 a
, float64 b
)
589 return float64_sub(a
, b
, &env
->fp_status
);
592 float64
HELPER(mul_f64
)(CPUState
*env
, float64 a
, float64 b
)
594 return float64_mul(a
, b
, &env
->fp_status
);
597 float64
HELPER(div_f64
)(CPUState
*env
, float64 a
, float64 b
)
599 return float64_div(a
, b
, &env
->fp_status
);
602 float64
HELPER(sub_cmp_f64
)(CPUState
*env
, float64 a
, float64 b
)
604 /* ??? This may incorrectly raise exceptions. */
605 /* ??? Should flush denormals to zero. */
607 res
= float64_sub(a
, b
, &env
->fp_status
);
608 if (float64_is_nan(res
)) {
609 /* +/-inf compares equal against itself, but sub returns nan. */
610 if (!float64_is_nan(a
)
611 && !float64_is_nan(b
)) {
613 if (float64_lt_quiet(a
, res
, &env
->fp_status
))
614 res
= float64_chs(res
);
620 uint32_t HELPER(compare_f64
)(CPUState
*env
, float64 val
)
622 return float64_compare_quiet(val
, float64_zero
, &env
->fp_status
);
626 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
627 take values, others take register numbers and manipulate the contents
629 void HELPER(mac_move
)(CPUState
*env
, uint32_t dest
, uint32_t src
)
632 env
->macc
[dest
] = env
->macc
[src
];
633 mask
= MACSR_PAV0
<< dest
;
634 if (env
->macsr
& (MACSR_PAV0
<< src
))
640 uint64_t HELPER(macmuls
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
645 product
= (uint64_t)op1
* op2
;
646 res
= (product
<< 24) >> 24;
647 if (res
!= product
) {
648 env
->macsr
|= MACSR_V
;
649 if (env
->macsr
& MACSR_OMC
) {
650 /* Make sure the accumulate operation overflows. */
660 uint64_t HELPER(macmulu
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
664 product
= (uint64_t)op1
* op2
;
665 if (product
& (0xffffffull
<< 40)) {
666 env
->macsr
|= MACSR_V
;
667 if (env
->macsr
& MACSR_OMC
) {
668 /* Make sure the accumulate operation overflows. */
671 product
&= ((1ull << 40) - 1);
677 uint64_t HELPER(macmulf
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
682 product
= (uint64_t)op1
* op2
;
683 if (env
->macsr
& MACSR_RT
) {
684 remainder
= product
& 0xffffff;
686 if (remainder
> 0x800000)
688 else if (remainder
== 0x800000)
689 product
+= (product
& 1);
696 void HELPER(macsats
)(CPUState
*env
, uint32_t acc
)
700 tmp
= env
->macc
[acc
];
701 result
= ((tmp
<< 16) >> 16);
703 env
->macsr
|= MACSR_V
;
705 if (env
->macsr
& MACSR_V
) {
706 env
->macsr
|= MACSR_PAV0
<< acc
;
707 if (env
->macsr
& MACSR_OMC
) {
708 /* The result is saturated to 32 bits, despite overflow occuring
709 at 48 bits. Seems weird, but that's what the hardware docs
711 result
= (result
>> 63) ^ 0x7fffffff;
714 env
->macc
[acc
] = result
;
717 void HELPER(macsatu
)(CPUState
*env
, uint32_t acc
)
721 val
= env
->macc
[acc
];
722 if (val
& (0xffffull
<< 48)) {
723 env
->macsr
|= MACSR_V
;
725 if (env
->macsr
& MACSR_V
) {
726 env
->macsr
|= MACSR_PAV0
<< acc
;
727 if (env
->macsr
& MACSR_OMC
) {
728 if (val
> (1ull << 53))
731 val
= (1ull << 48) - 1;
733 val
&= ((1ull << 48) - 1);
736 env
->macc
[acc
] = val
;
739 void HELPER(macsatf
)(CPUState
*env
, uint32_t acc
)
744 sum
= env
->macc
[acc
];
745 result
= (sum
<< 16) >> 16;
747 env
->macsr
|= MACSR_V
;
749 if (env
->macsr
& MACSR_V
) {
750 env
->macsr
|= MACSR_PAV0
<< acc
;
751 if (env
->macsr
& MACSR_OMC
) {
752 result
= (result
>> 63) ^ 0x7fffffffffffll
;
755 env
->macc
[acc
] = result
;
758 void HELPER(mac_set_flags
)(CPUState
*env
, uint32_t acc
)
761 val
= env
->macc
[acc
];
763 env
->macsr
|= MACSR_Z
;
764 else if (val
& (1ull << 47));
765 env
->macsr
|= MACSR_N
;
766 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
767 env
->macsr
|= MACSR_V
;
769 if (env
->macsr
& MACSR_FI
) {
770 val
= ((int64_t)val
) >> 40;
771 if (val
!= 0 && val
!= -1)
772 env
->macsr
|= MACSR_EV
;
773 } else if (env
->macsr
& MACSR_SU
) {
774 val
= ((int64_t)val
) >> 32;
775 if (val
!= 0 && val
!= -1)
776 env
->macsr
|= MACSR_EV
;
778 if ((val
>> 32) != 0)
779 env
->macsr
|= MACSR_EV
;
783 void HELPER(flush_flags
)(CPUState
*env
, uint32_t cc_op
)
785 cpu_m68k_flush_flags(env
, cc_op
);
788 uint32_t HELPER(get_macf
)(CPUState
*env
, uint64_t val
)
793 if (env
->macsr
& MACSR_SU
) {
794 /* 16-bit rounding. */
795 rem
= val
& 0xffffff;
796 val
= (val
>> 24) & 0xffffu
;
799 else if (rem
== 0x800000)
801 } else if (env
->macsr
& MACSR_RT
) {
802 /* 32-bit rounding. */
807 else if (rem
== 0x80)
813 if (env
->macsr
& MACSR_OMC
) {
815 if (env
->macsr
& MACSR_SU
) {
816 if (val
!= (uint16_t) val
) {
817 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
819 result
= val
& 0xffff;
822 if (val
!= (uint32_t)val
) {
823 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
825 result
= (uint32_t)val
;
830 if (env
->macsr
& MACSR_SU
) {
831 result
= val
& 0xffff;
833 result
= (uint32_t)val
;
839 uint32_t HELPER(get_macs
)(uint64_t val
)
841 if (val
== (int32_t)val
) {
844 return (val
>> 61) ^ ~SIGNBIT
;
848 uint32_t HELPER(get_macu
)(uint64_t val
)
850 if ((val
>> 32) == 0) {
851 return (uint32_t)val
;
857 uint32_t HELPER(get_mac_extf
)(CPUState
*env
, uint32_t acc
)
860 val
= env
->macc
[acc
] & 0x00ff;
861 val
= (env
->macc
[acc
] >> 32) & 0xff00;
862 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
863 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
867 uint32_t HELPER(get_mac_exti
)(CPUState
*env
, uint32_t acc
)
870 val
= (env
->macc
[acc
] >> 32) & 0xffff;
871 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
875 void HELPER(set_mac_extf
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
879 res
= env
->macc
[acc
] & 0xffffffff00ull
;
880 tmp
= (int16_t)(val
& 0xff00);
881 res
|= ((int64_t)tmp
) << 32;
883 env
->macc
[acc
] = res
;
884 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
885 tmp
= (val
& 0xff000000);
886 res
|= ((int64_t)tmp
) << 16;
887 res
|= (val
>> 16) & 0xff;
888 env
->macc
[acc
+ 1] = res
;
891 void HELPER(set_mac_exts
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
895 res
= (uint32_t)env
->macc
[acc
];
897 res
|= ((int64_t)tmp
) << 32;
898 env
->macc
[acc
] = res
;
899 res
= (uint32_t)env
->macc
[acc
+ 1];
900 tmp
= val
& 0xffff0000;
901 res
|= (int64_t)tmp
<< 16;
902 env
->macc
[acc
+ 1] = res
;
905 void HELPER(set_mac_extu
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
908 res
= (uint32_t)env
->macc
[acc
];
909 res
|= ((uint64_t)(val
& 0xffff)) << 32;
910 env
->macc
[acc
] = res
;
911 res
= (uint32_t)env
->macc
[acc
+ 1];
912 res
|= (uint64_t)(val
& 0xffff0000) << 16;
913 env
->macc
[acc
+ 1] = res
;