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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "qemu-common.h"
32 #define SIGNBIT (1u << 31)
41 typedef struct m68k_def_t m68k_def_t
;
48 static m68k_def_t m68k_cpu_defs
[] = {
49 {"m5206", M68K_CPUID_M5206
},
50 {"m5208", M68K_CPUID_M5208
},
51 {"cfv4e", M68K_CPUID_CFV4E
},
52 {"any", M68K_CPUID_ANY
},
56 static void m68k_set_feature(CPUM68KState
*env
, int feature
)
58 env
->features
|= (1u << feature
);
61 static int cpu_m68k_set_model(CPUM68KState
*env
, const char *name
)
65 for (def
= m68k_cpu_defs
; def
->name
; def
++) {
66 if (strcmp(def
->name
, name
) == 0)
73 case M68K_CPUID_M5206
:
74 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
76 case M68K_CPUID_M5208
:
77 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
78 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_APLUSC
);
79 m68k_set_feature(env
, M68K_FEATURE_BRAL
);
80 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC
);
81 m68k_set_feature(env
, M68K_FEATURE_USP
);
83 case M68K_CPUID_CFV4E
:
84 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
85 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_B
);
86 m68k_set_feature(env
, M68K_FEATURE_BRAL
);
87 m68k_set_feature(env
, M68K_FEATURE_CF_FPU
);
88 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC
);
89 m68k_set_feature(env
, M68K_FEATURE_USP
);
92 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
93 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_B
);
94 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_APLUSC
);
95 m68k_set_feature(env
, M68K_FEATURE_BRAL
);
96 m68k_set_feature(env
, M68K_FEATURE_CF_FPU
);
97 /* MAC and EMAC are mututally exclusive, so pick EMAC.
98 It's mostly backwards compatible. */
99 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC
);
100 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC_B
);
101 m68k_set_feature(env
, M68K_FEATURE_USP
);
102 m68k_set_feature(env
, M68K_FEATURE_EXT_FULL
);
103 m68k_set_feature(env
, M68K_FEATURE_WORD_INDEX
);
107 register_m68k_insns(env
);
111 void cpu_reset(CPUM68KState
*env
)
113 memset(env
, 0, offsetof(CPUM68KState
, breakpoints
));
114 #if !defined (CONFIG_USER_ONLY)
118 /* ??? FP regs should be initialized to NaN. */
119 env
->cc_op
= CC_OP_FLAGS
;
120 /* TODO: We should set PC from the interrupt vector. */
125 CPUM68KState
*cpu_m68k_init(const char *cpu_model
)
130 env
= malloc(sizeof(CPUM68KState
));
139 env
->cpu_model_str
= cpu_model
;
141 if (cpu_m68k_set_model(env
, cpu_model
) < 0) {
150 void cpu_m68k_close(CPUM68KState
*env
)
155 void cpu_m68k_flush_flags(CPUM68KState
*env
, int cc_op
)
162 #define HIGHBIT 0x80000000u
164 #define SET_NZ(x) do { \
167 else if ((int32_t)(x) < 0) \
171 #define SET_FLAGS_SUB(type, utype) do { \
172 SET_NZ((type)dest); \
174 if ((utype) tmp < (utype) src) \
176 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
195 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
199 SET_FLAGS_SUB(int32_t, uint32_t);
202 SET_FLAGS_SUB(int8_t, uint8_t);
205 SET_FLAGS_SUB(int16_t, uint16_t);
211 tmp
= dest
- src
- 1;
212 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
217 tmp
= dest
+ src
+ 1;
220 if (HIGHBIT
& (tmp
^ dest
) & (tmp
^ src
))
229 cpu_abort(env
, "Bad CC_OP %d", cc_op
);
231 env
->cc_op
= CC_OP_FLAGS
;
232 env
->cc_dest
= flags
;
235 void HELPER(movec
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
238 case 0x02: /* CACR */
242 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
243 /* TODO: Implement Access Control Registers. */
245 case 0x801: /* VBR */
248 /* TODO: Implement control registers. */
250 cpu_abort(env
, "Unimplemented control register write 0x%x = 0x%x\n",
255 void HELPER(set_macsr
)(CPUM68KState
*env
, uint32_t val
)
262 if ((env
->macsr
^ val
) & (MACSR_FI
| MACSR_SU
)) {
263 for (i
= 0; i
< 4; i
++) {
264 regval
= env
->macc
[i
];
265 exthigh
= regval
>> 40;
266 if (env
->macsr
& MACSR_FI
) {
271 extlow
= regval
>> 32;
273 if (env
->macsr
& MACSR_FI
) {
274 regval
= (((uint64_t)acc
) << 8) | extlow
;
275 regval
|= ((int64_t)exthigh
) << 40;
276 } else if (env
->macsr
& MACSR_SU
) {
277 regval
= acc
| (((int64_t)extlow
) << 32);
278 regval
|= ((int64_t)exthigh
) << 40;
280 regval
= acc
| (((uint64_t)extlow
) << 32);
281 regval
|= ((uint64_t)(uint8_t)exthigh
) << 40;
283 env
->macc
[i
] = regval
;
289 void m68k_switch_sp(CPUM68KState
*env
)
293 env
->sp
[env
->current_sp
] = env
->aregs
[7];
294 new_sp
= (env
->sr
& SR_S
&& env
->cacr
& M68K_CACR_EUSP
)
295 ? M68K_SSP
: M68K_USP
;
296 env
->aregs
[7] = env
->sp
[new_sp
];
297 env
->current_sp
= new_sp
;
302 /* TODO: This will need fixing once the MMU is implemented. */
303 target_phys_addr_t
cpu_get_phys_page_debug(CPUState
*env
, target_ulong addr
)
308 #if defined(CONFIG_USER_ONLY)
310 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
311 int mmu_idx
, int is_softmmu
)
313 env
->exception_index
= EXCP_ACCESS
;
314 env
->mmu
.ar
= address
;
320 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
321 int mmu_idx
, int is_softmmu
)
325 address
&= TARGET_PAGE_MASK
;
326 prot
= PAGE_READ
| PAGE_WRITE
;
327 return tlb_set_page(env
, address
, address
, prot
, mmu_idx
, is_softmmu
);
330 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
331 be handled by the interrupt controller. Real hardware only requests
332 the vector when the interrupt is acknowledged by the CPU. For
333 simplicitly we calculate it when the interrupt is signalled. */
334 void m68k_set_irq_level(CPUM68KState
*env
, int level
, uint8_t vector
)
336 env
->pending_level
= level
;
337 env
->pending_vector
= vector
;
339 cpu_interrupt(env
, CPU_INTERRUPT_HARD
);
341 cpu_reset_interrupt(env
, CPU_INTERRUPT_HARD
);
346 uint32_t HELPER(bitrev
)(uint32_t x
)
348 x
= ((x
>> 1) & 0x55555555u
) | ((x
<< 1) & 0xaaaaaaaau
);
349 x
= ((x
>> 2) & 0x33333333u
) | ((x
<< 2) & 0xccccccccu
);
350 x
= ((x
>> 4) & 0x0f0f0f0fu
) | ((x
<< 4) & 0xf0f0f0f0u
);
354 uint32_t HELPER(ff1
)(uint32_t x
)
362 uint32_t HELPER(sats
)(uint32_t val
, uint32_t ccr
)
364 /* The result has the opposite sign to the original value. */
366 val
= (((int32_t)val
) >> 31) ^ SIGNBIT
;
370 uint32_t HELPER(subx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
375 old_flags
= env
->cc_dest
;
377 env
->cc_x
= (op1
<= op2
);
378 env
->cc_op
= CC_OP_SUBX
;
379 res
= op1
- (op2
+ 1);
381 env
->cc_x
= (op1
< op2
);
382 env
->cc_op
= CC_OP_SUB
;
387 cpu_m68k_flush_flags(env
, env
->cc_op
);
389 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
393 uint32_t HELPER(addx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
398 old_flags
= env
->cc_dest
;
401 env
->cc_x
= (res
<= op2
);
402 env
->cc_op
= CC_OP_ADDX
;
405 env
->cc_x
= (res
< op2
);
406 env
->cc_op
= CC_OP_ADD
;
410 cpu_m68k_flush_flags(env
, env
->cc_op
);
412 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
416 uint32_t HELPER(xflag_lt
)(uint32_t a
, uint32_t b
)
421 uint32_t HELPER(btest
)(uint32_t x
)
426 void HELPER(set_sr
)(CPUState
*env
, uint32_t val
)
428 env
->sr
= val
& 0xffff;
432 uint32_t HELPER(shl_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
440 cf
= env
->cc_src
& CCF_C
;
441 } else if (shift
< 32) {
442 result
= val
<< shift
;
443 cf
= (val
>> (32 - shift
)) & 1;
444 } else if (shift
== 32) {
447 } else /* shift > 32 */ {
452 env
->cc_x
= (cf
!= 0);
453 env
->cc_dest
= result
;
457 uint32_t HELPER(shr_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
465 cf
= env
->cc_src
& CCF_C
;
466 } else if (shift
< 32) {
467 result
= val
>> shift
;
468 cf
= (val
>> (shift
- 1)) & 1;
469 } else if (shift
== 32) {
472 } else /* shift > 32 */ {
477 env
->cc_x
= (cf
!= 0);
478 env
->cc_dest
= result
;
482 uint32_t HELPER(sar_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
490 cf
= (env
->cc_src
& CCF_C
) != 0;
491 } else if (shift
< 32) {
492 result
= (int32_t)val
>> shift
;
493 cf
= (val
>> (shift
- 1)) & 1;
494 } else /* shift >= 32 */ {
495 result
= (int32_t)val
>> 31;
500 env
->cc_dest
= result
;
505 uint32_t HELPER(f64_to_i32
)(CPUState
*env
, float64 val
)
507 return float64_to_int32(val
, &env
->fp_status
);
510 float32
HELPER(f64_to_f32
)(CPUState
*env
, float64 val
)
512 return float64_to_float32(val
, &env
->fp_status
);
515 float64
HELPER(i32_to_f64
)(CPUState
*env
, uint32_t val
)
517 return int32_to_float64(val
, &env
->fp_status
);
520 float64
HELPER(f32_to_f64
)(CPUState
*env
, float32 val
)
522 return float32_to_float64(val
, &env
->fp_status
);
525 float64
HELPER(iround_f64
)(CPUState
*env
, float64 val
)
527 return float64_round_to_int(val
, &env
->fp_status
);
530 float64
HELPER(itrunc_f64
)(CPUState
*env
, float64 val
)
532 return float64_trunc_to_int(val
, &env
->fp_status
);
535 float64
HELPER(sqrt_f64
)(CPUState
*env
, float64 val
)
537 return float64_sqrt(val
, &env
->fp_status
);
540 float64
HELPER(abs_f64
)(float64 val
)
542 return float64_abs(val
);
545 float64
HELPER(chs_f64
)(float64 val
)
547 return float64_chs(val
);
550 float64
HELPER(add_f64
)(CPUState
*env
, float64 a
, float64 b
)
552 return float64_add(a
, b
, &env
->fp_status
);
555 float64
HELPER(sub_f64
)(CPUState
*env
, float64 a
, float64 b
)
557 return float64_sub(a
, b
, &env
->fp_status
);
560 float64
HELPER(mul_f64
)(CPUState
*env
, float64 a
, float64 b
)
562 return float64_mul(a
, b
, &env
->fp_status
);
565 float64
HELPER(div_f64
)(CPUState
*env
, float64 a
, float64 b
)
567 return float64_div(a
, b
, &env
->fp_status
);
570 float64
HELPER(sub_cmp_f64
)(CPUState
*env
, float64 a
, float64 b
)
572 /* ??? This may incorrectly raise exceptions. */
573 /* ??? Should flush denormals to zero. */
575 res
= float64_sub(a
, b
, &env
->fp_status
);
576 if (float64_is_nan(res
)) {
577 /* +/-inf compares equal against itself, but sub returns nan. */
578 if (!float64_is_nan(a
)
579 && !float64_is_nan(b
)) {
581 if (float64_lt_quiet(a
, res
, &env
->fp_status
))
582 res
= float64_chs(res
);
588 uint32_t HELPER(compare_f64
)(CPUState
*env
, float64 val
)
590 return float64_compare_quiet(val
, float64_zero
, &env
->fp_status
);
594 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
595 take values, others take register numbers and manipulate the contents
597 void HELPER(mac_move
)(CPUState
*env
, uint32_t dest
, uint32_t src
)
600 env
->macc
[dest
] = env
->macc
[src
];
601 mask
= MACSR_PAV0
<< dest
;
602 if (env
->macsr
& (MACSR_PAV0
<< src
))
608 uint64_t HELPER(macmuls
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
613 product
= (uint64_t)op1
* op2
;
614 res
= (product
<< 24) >> 24;
615 if (res
!= product
) {
616 env
->macsr
|= MACSR_V
;
617 if (env
->macsr
& MACSR_OMC
) {
618 /* Make sure the accumulate operation overflows. */
628 uint64_t HELPER(macmulu
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
632 product
= (uint64_t)op1
* op2
;
633 if (product
& (0xffffffull
<< 40)) {
634 env
->macsr
|= MACSR_V
;
635 if (env
->macsr
& MACSR_OMC
) {
636 /* Make sure the accumulate operation overflows. */
639 product
&= ((1ull << 40) - 1);
645 uint64_t HELPER(macmulf
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
650 product
= (uint64_t)op1
* op2
;
651 if (env
->macsr
& MACSR_RT
) {
652 remainder
= product
& 0xffffff;
654 if (remainder
> 0x800000)
656 else if (remainder
== 0x800000)
657 product
+= (product
& 1);
664 void HELPER(macsats
)(CPUState
*env
, uint32_t acc
)
668 tmp
= env
->macc
[acc
];
669 result
= ((tmp
<< 16) >> 16);
671 env
->macsr
|= MACSR_V
;
673 if (env
->macsr
& MACSR_V
) {
674 env
->macsr
|= MACSR_PAV0
<< acc
;
675 if (env
->macsr
& MACSR_OMC
) {
676 /* The result is saturated to 32 bits, despite overflow occuring
677 at 48 bits. Seems weird, but that's what the hardware docs
679 result
= (result
>> 63) ^ 0x7fffffff;
682 env
->macc
[acc
] = result
;
685 void HELPER(macsatu
)(CPUState
*env
, uint32_t acc
)
689 val
= env
->macc
[acc
];
690 if (val
& (0xffffull
<< 48)) {
691 env
->macsr
|= MACSR_V
;
693 if (env
->macsr
& MACSR_V
) {
694 env
->macsr
|= MACSR_PAV0
<< acc
;
695 if (env
->macsr
& MACSR_OMC
) {
696 if (val
> (1ull << 53))
699 val
= (1ull << 48) - 1;
701 val
&= ((1ull << 48) - 1);
704 env
->macc
[acc
] = val
;
707 void HELPER(macsatf
)(CPUState
*env
, uint32_t acc
)
712 sum
= env
->macc
[acc
];
713 result
= (sum
<< 16) >> 16;
715 env
->macsr
|= MACSR_V
;
717 if (env
->macsr
& MACSR_V
) {
718 env
->macsr
|= MACSR_PAV0
<< acc
;
719 if (env
->macsr
& MACSR_OMC
) {
720 result
= (result
>> 63) ^ 0x7fffffffffffll
;
723 env
->macc
[acc
] = result
;
726 void HELPER(mac_set_flags
)(CPUState
*env
, uint32_t acc
)
729 val
= env
->macc
[acc
];
731 env
->macsr
|= MACSR_Z
;
732 else if (val
& (1ull << 47));
733 env
->macsr
|= MACSR_N
;
734 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
735 env
->macsr
|= MACSR_V
;
737 if (env
->macsr
& MACSR_FI
) {
738 val
= ((int64_t)val
) >> 40;
739 if (val
!= 0 && val
!= -1)
740 env
->macsr
|= MACSR_EV
;
741 } else if (env
->macsr
& MACSR_SU
) {
742 val
= ((int64_t)val
) >> 32;
743 if (val
!= 0 && val
!= -1)
744 env
->macsr
|= MACSR_EV
;
746 if ((val
>> 32) != 0)
747 env
->macsr
|= MACSR_EV
;
751 void HELPER(flush_flags
)(CPUState
*env
, uint32_t cc_op
)
753 cpu_m68k_flush_flags(env
, cc_op
);
756 uint32_t HELPER(get_macf
)(CPUState
*env
, uint64_t val
)
761 if (env
->macsr
& MACSR_SU
) {
762 /* 16-bit rounding. */
763 rem
= val
& 0xffffff;
764 val
= (val
>> 24) & 0xffffu
;
767 else if (rem
== 0x800000)
769 } else if (env
->macsr
& MACSR_RT
) {
770 /* 32-bit rounding. */
775 else if (rem
== 0x80)
781 if (env
->macsr
& MACSR_OMC
) {
783 if (env
->macsr
& MACSR_SU
) {
784 if (val
!= (uint16_t) val
) {
785 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
787 result
= val
& 0xffff;
790 if (val
!= (uint32_t)val
) {
791 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
793 result
= (uint32_t)val
;
798 if (env
->macsr
& MACSR_SU
) {
799 result
= val
& 0xffff;
801 result
= (uint32_t)val
;
807 uint32_t HELPER(get_macs
)(uint64_t val
)
809 if (val
== (int32_t)val
) {
812 return (val
>> 61) ^ ~SIGNBIT
;
816 uint32_t HELPER(get_macu
)(uint64_t val
)
818 if ((val
>> 32) == 0) {
819 return (uint32_t)val
;
825 uint32_t HELPER(get_mac_extf
)(CPUState
*env
, uint32_t acc
)
828 val
= env
->macc
[acc
] & 0x00ff;
829 val
= (env
->macc
[acc
] >> 32) & 0xff00;
830 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
831 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
835 uint32_t HELPER(get_mac_exti
)(CPUState
*env
, uint32_t acc
)
838 val
= (env
->macc
[acc
] >> 32) & 0xffff;
839 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
843 void HELPER(set_mac_extf
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
847 res
= env
->macc
[acc
] & 0xffffffff00ull
;
848 tmp
= (int16_t)(val
& 0xff00);
849 res
|= ((int64_t)tmp
) << 32;
851 env
->macc
[acc
] = res
;
852 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
853 tmp
= (val
& 0xff000000);
854 res
|= ((int64_t)tmp
) << 16;
855 res
|= (val
>> 16) & 0xff;
856 env
->macc
[acc
+ 1] = res
;
859 void HELPER(set_mac_exts
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
863 res
= (uint32_t)env
->macc
[acc
];
865 res
|= ((int64_t)tmp
) << 32;
866 env
->macc
[acc
] = res
;
867 res
= (uint32_t)env
->macc
[acc
+ 1];
868 tmp
= val
& 0xffff0000;
869 res
|= (int64_t)tmp
<< 16;
870 env
->macc
[acc
+ 1] = res
;
873 void HELPER(set_mac_extu
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
876 res
= (uint32_t)env
->macc
[acc
];
877 res
|= ((uint64_t)(val
& 0xffff)) << 32;
878 env
->macc
[acc
] = res
;
879 res
= (uint32_t)env
->macc
[acc
+ 1];
880 res
|= (uint64_t)(val
& 0xffff0000) << 16;
881 env
->macc
[acc
+ 1] = res
;