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, see <http://www.gnu.org/licenses/>.
27 #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 void m68k_cpu_list(FILE *f
, int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...))
60 for (i
= 0; m68k_cpu_defs
[i
].name
; i
++) {
61 (*cpu_fprintf
)(f
, "%s\n", m68k_cpu_defs
[i
].name
);
65 static int fpu_gdb_get_reg(CPUState
*env
, uint8_t *mem_buf
, int n
)
68 stfq_p(mem_buf
, env
->fregs
[n
]);
72 /* FP control registers (not implemented) */
73 memset(mem_buf
, 0, 4);
79 static int fpu_gdb_set_reg(CPUState
*env
, uint8_t *mem_buf
, int n
)
82 env
->fregs
[n
] = ldfq_p(mem_buf
);
86 /* FP control registers (not implemented) */
92 static void m68k_set_feature(CPUM68KState
*env
, int feature
)
94 env
->features
|= (1u << feature
);
97 static int cpu_m68k_set_model(CPUM68KState
*env
, const char *name
)
101 for (def
= m68k_cpu_defs
; def
->name
; def
++) {
102 if (strcmp(def
->name
, name
) == 0)
109 case M68K_CPUID_M5206
:
110 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
112 case M68K_CPUID_M5208
:
113 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
114 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_APLUSC
);
115 m68k_set_feature(env
, M68K_FEATURE_BRAL
);
116 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC
);
117 m68k_set_feature(env
, M68K_FEATURE_USP
);
119 case M68K_CPUID_CFV4E
:
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_BRAL
);
123 m68k_set_feature(env
, M68K_FEATURE_CF_FPU
);
124 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC
);
125 m68k_set_feature(env
, M68K_FEATURE_USP
);
128 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_A
);
129 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_B
);
130 m68k_set_feature(env
, M68K_FEATURE_CF_ISA_APLUSC
);
131 m68k_set_feature(env
, M68K_FEATURE_BRAL
);
132 m68k_set_feature(env
, M68K_FEATURE_CF_FPU
);
133 /* MAC and EMAC are mututally exclusive, so pick EMAC.
134 It's mostly backwards compatible. */
135 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC
);
136 m68k_set_feature(env
, M68K_FEATURE_CF_EMAC_B
);
137 m68k_set_feature(env
, M68K_FEATURE_USP
);
138 m68k_set_feature(env
, M68K_FEATURE_EXT_FULL
);
139 m68k_set_feature(env
, M68K_FEATURE_WORD_INDEX
);
143 register_m68k_insns(env
);
144 if (m68k_feature (env
, M68K_FEATURE_CF_FPU
)) {
145 gdb_register_coprocessor(env
, fpu_gdb_get_reg
, fpu_gdb_set_reg
,
146 11, "cf-fp.xml", 18);
148 /* TODO: Add [E]MAC registers. */
152 void cpu_reset(CPUM68KState
*env
)
154 if (qemu_loglevel_mask(CPU_LOG_RESET
)) {
155 qemu_log("CPU Reset (CPU %d)\n", env
->cpu_index
);
156 log_cpu_state(env
, 0);
159 memset(env
, 0, offsetof(CPUM68KState
, breakpoints
));
160 #if !defined (CONFIG_USER_ONLY)
164 /* ??? FP regs should be initialized to NaN. */
165 env
->cc_op
= CC_OP_FLAGS
;
166 /* TODO: We should set PC from the interrupt vector. */
171 CPUM68KState
*cpu_m68k_init(const char *cpu_model
)
176 env
= qemu_mallocz(sizeof(CPUM68KState
));
183 env
->cpu_model_str
= cpu_model
;
185 if (cpu_m68k_set_model(env
, cpu_model
) < 0) {
195 void cpu_m68k_close(CPUM68KState
*env
)
200 void cpu_m68k_flush_flags(CPUM68KState
*env
, int cc_op
)
207 #define HIGHBIT 0x80000000u
209 #define SET_NZ(x) do { \
212 else if ((int32_t)(x) < 0) \
216 #define SET_FLAGS_SUB(type, utype) do { \
217 SET_NZ((type)dest); \
219 if ((utype) tmp < (utype) src) \
221 if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
240 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
244 SET_FLAGS_SUB(int32_t, uint32_t);
247 SET_FLAGS_SUB(int8_t, uint8_t);
250 SET_FLAGS_SUB(int16_t, uint16_t);
256 tmp
= dest
- src
- 1;
257 if (HIGHBIT
& (src
^ dest
) & ~(tmp
^ src
))
262 tmp
= dest
+ src
+ 1;
265 if (HIGHBIT
& (tmp
^ dest
) & (tmp
^ src
))
274 cpu_abort(env
, "Bad CC_OP %d", cc_op
);
276 env
->cc_op
= CC_OP_FLAGS
;
277 env
->cc_dest
= flags
;
280 void HELPER(movec
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
283 case 0x02: /* CACR */
287 case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
288 /* TODO: Implement Access Control Registers. */
290 case 0x801: /* VBR */
293 /* TODO: Implement control registers. */
295 cpu_abort(env
, "Unimplemented control register write 0x%x = 0x%x\n",
300 void HELPER(set_macsr
)(CPUM68KState
*env
, uint32_t val
)
307 if ((env
->macsr
^ val
) & (MACSR_FI
| MACSR_SU
)) {
308 for (i
= 0; i
< 4; i
++) {
309 regval
= env
->macc
[i
];
310 exthigh
= regval
>> 40;
311 if (env
->macsr
& MACSR_FI
) {
316 extlow
= regval
>> 32;
318 if (env
->macsr
& MACSR_FI
) {
319 regval
= (((uint64_t)acc
) << 8) | extlow
;
320 regval
|= ((int64_t)exthigh
) << 40;
321 } else if (env
->macsr
& MACSR_SU
) {
322 regval
= acc
| (((int64_t)extlow
) << 32);
323 regval
|= ((int64_t)exthigh
) << 40;
325 regval
= acc
| (((uint64_t)extlow
) << 32);
326 regval
|= ((uint64_t)(uint8_t)exthigh
) << 40;
328 env
->macc
[i
] = regval
;
334 void m68k_switch_sp(CPUM68KState
*env
)
338 env
->sp
[env
->current_sp
] = env
->aregs
[7];
339 new_sp
= (env
->sr
& SR_S
&& env
->cacr
& M68K_CACR_EUSP
)
340 ? M68K_SSP
: M68K_USP
;
341 env
->aregs
[7] = env
->sp
[new_sp
];
342 env
->current_sp
= new_sp
;
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
;
359 /* TODO: This will need fixing once the MMU is implemented. */
360 target_phys_addr_t
cpu_get_phys_page_debug(CPUState
*env
, target_ulong addr
)
365 int cpu_m68k_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
366 int mmu_idx
, int is_softmmu
)
370 address
&= TARGET_PAGE_MASK
;
371 prot
= PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
;
372 tlb_set_page(env
, address
, address
, prot
, mmu_idx
, TARGET_PAGE_SIZE
);
376 /* Notify CPU of a pending interrupt. Prioritization and vectoring should
377 be handled by the interrupt controller. Real hardware only requests
378 the vector when the interrupt is acknowledged by the CPU. For
379 simplicitly we calculate it when the interrupt is signalled. */
380 void m68k_set_irq_level(CPUM68KState
*env
, int level
, uint8_t vector
)
382 env
->pending_level
= level
;
383 env
->pending_vector
= vector
;
385 cpu_interrupt(env
, CPU_INTERRUPT_HARD
);
387 cpu_reset_interrupt(env
, CPU_INTERRUPT_HARD
);
392 uint32_t HELPER(bitrev
)(uint32_t x
)
394 x
= ((x
>> 1) & 0x55555555u
) | ((x
<< 1) & 0xaaaaaaaau
);
395 x
= ((x
>> 2) & 0x33333333u
) | ((x
<< 2) & 0xccccccccu
);
396 x
= ((x
>> 4) & 0x0f0f0f0fu
) | ((x
<< 4) & 0xf0f0f0f0u
);
400 uint32_t HELPER(ff1
)(uint32_t x
)
408 uint32_t HELPER(sats
)(uint32_t val
, uint32_t ccr
)
410 /* The result has the opposite sign to the original value. */
412 val
= (((int32_t)val
) >> 31) ^ SIGNBIT
;
416 uint32_t HELPER(subx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
421 old_flags
= env
->cc_dest
;
423 env
->cc_x
= (op1
<= op2
);
424 env
->cc_op
= CC_OP_SUBX
;
425 res
= op1
- (op2
+ 1);
427 env
->cc_x
= (op1
< op2
);
428 env
->cc_op
= CC_OP_SUB
;
433 cpu_m68k_flush_flags(env
, env
->cc_op
);
435 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
439 uint32_t HELPER(addx_cc
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
444 old_flags
= env
->cc_dest
;
447 env
->cc_x
= (res
<= op2
);
448 env
->cc_op
= CC_OP_ADDX
;
451 env
->cc_x
= (res
< op2
);
452 env
->cc_op
= CC_OP_ADD
;
456 cpu_m68k_flush_flags(env
, env
->cc_op
);
458 env
->cc_dest
&= (old_flags
| ~CCF_Z
);
462 uint32_t HELPER(xflag_lt
)(uint32_t a
, uint32_t b
)
467 void HELPER(set_sr
)(CPUState
*env
, uint32_t val
)
469 env
->sr
= val
& 0xffff;
473 uint32_t HELPER(shl_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
481 cf
= env
->cc_src
& CCF_C
;
482 } else if (shift
< 32) {
483 result
= val
<< shift
;
484 cf
= (val
>> (32 - shift
)) & 1;
485 } else if (shift
== 32) {
488 } else /* shift > 32 */ {
493 env
->cc_x
= (cf
!= 0);
494 env
->cc_dest
= result
;
498 uint32_t HELPER(shr_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
506 cf
= env
->cc_src
& CCF_C
;
507 } else if (shift
< 32) {
508 result
= val
>> shift
;
509 cf
= (val
>> (shift
- 1)) & 1;
510 } else if (shift
== 32) {
513 } else /* shift > 32 */ {
518 env
->cc_x
= (cf
!= 0);
519 env
->cc_dest
= result
;
523 uint32_t HELPER(sar_cc
)(CPUState
*env
, uint32_t val
, uint32_t shift
)
531 cf
= (env
->cc_src
& CCF_C
) != 0;
532 } else if (shift
< 32) {
533 result
= (int32_t)val
>> shift
;
534 cf
= (val
>> (shift
- 1)) & 1;
535 } else /* shift >= 32 */ {
536 result
= (int32_t)val
>> 31;
541 env
->cc_dest
= result
;
546 uint32_t HELPER(f64_to_i32
)(CPUState
*env
, float64 val
)
548 return float64_to_int32(val
, &env
->fp_status
);
551 float32
HELPER(f64_to_f32
)(CPUState
*env
, float64 val
)
553 return float64_to_float32(val
, &env
->fp_status
);
556 float64
HELPER(i32_to_f64
)(CPUState
*env
, uint32_t val
)
558 return int32_to_float64(val
, &env
->fp_status
);
561 float64
HELPER(f32_to_f64
)(CPUState
*env
, float32 val
)
563 return float32_to_float64(val
, &env
->fp_status
);
566 float64
HELPER(iround_f64
)(CPUState
*env
, float64 val
)
568 return float64_round_to_int(val
, &env
->fp_status
);
571 float64
HELPER(itrunc_f64
)(CPUState
*env
, float64 val
)
573 return float64_trunc_to_int(val
, &env
->fp_status
);
576 float64
HELPER(sqrt_f64
)(CPUState
*env
, float64 val
)
578 return float64_sqrt(val
, &env
->fp_status
);
581 float64
HELPER(abs_f64
)(float64 val
)
583 return float64_abs(val
);
586 float64
HELPER(chs_f64
)(float64 val
)
588 return float64_chs(val
);
591 float64
HELPER(add_f64
)(CPUState
*env
, float64 a
, float64 b
)
593 return float64_add(a
, b
, &env
->fp_status
);
596 float64
HELPER(sub_f64
)(CPUState
*env
, float64 a
, float64 b
)
598 return float64_sub(a
, b
, &env
->fp_status
);
601 float64
HELPER(mul_f64
)(CPUState
*env
, float64 a
, float64 b
)
603 return float64_mul(a
, b
, &env
->fp_status
);
606 float64
HELPER(div_f64
)(CPUState
*env
, float64 a
, float64 b
)
608 return float64_div(a
, b
, &env
->fp_status
);
611 float64
HELPER(sub_cmp_f64
)(CPUState
*env
, float64 a
, float64 b
)
613 /* ??? This may incorrectly raise exceptions. */
614 /* ??? Should flush denormals to zero. */
616 res
= float64_sub(a
, b
, &env
->fp_status
);
617 if (float64_is_nan(res
)) {
618 /* +/-inf compares equal against itself, but sub returns nan. */
619 if (!float64_is_nan(a
)
620 && !float64_is_nan(b
)) {
622 if (float64_lt_quiet(a
, res
, &env
->fp_status
))
623 res
= float64_chs(res
);
629 uint32_t HELPER(compare_f64
)(CPUState
*env
, float64 val
)
631 return float64_compare_quiet(val
, float64_zero
, &env
->fp_status
);
635 /* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
636 take values, others take register numbers and manipulate the contents
638 void HELPER(mac_move
)(CPUState
*env
, uint32_t dest
, uint32_t src
)
641 env
->macc
[dest
] = env
->macc
[src
];
642 mask
= MACSR_PAV0
<< dest
;
643 if (env
->macsr
& (MACSR_PAV0
<< src
))
649 uint64_t HELPER(macmuls
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
654 product
= (uint64_t)op1
* op2
;
655 res
= (product
<< 24) >> 24;
656 if (res
!= product
) {
657 env
->macsr
|= MACSR_V
;
658 if (env
->macsr
& MACSR_OMC
) {
659 /* Make sure the accumulate operation overflows. */
669 uint64_t HELPER(macmulu
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
673 product
= (uint64_t)op1
* op2
;
674 if (product
& (0xffffffull
<< 40)) {
675 env
->macsr
|= MACSR_V
;
676 if (env
->macsr
& MACSR_OMC
) {
677 /* Make sure the accumulate operation overflows. */
680 product
&= ((1ull << 40) - 1);
686 uint64_t HELPER(macmulf
)(CPUState
*env
, uint32_t op1
, uint32_t op2
)
691 product
= (uint64_t)op1
* op2
;
692 if (env
->macsr
& MACSR_RT
) {
693 remainder
= product
& 0xffffff;
695 if (remainder
> 0x800000)
697 else if (remainder
== 0x800000)
698 product
+= (product
& 1);
705 void HELPER(macsats
)(CPUState
*env
, uint32_t acc
)
709 tmp
= env
->macc
[acc
];
710 result
= ((tmp
<< 16) >> 16);
712 env
->macsr
|= MACSR_V
;
714 if (env
->macsr
& MACSR_V
) {
715 env
->macsr
|= MACSR_PAV0
<< acc
;
716 if (env
->macsr
& MACSR_OMC
) {
717 /* The result is saturated to 32 bits, despite overflow occuring
718 at 48 bits. Seems weird, but that's what the hardware docs
720 result
= (result
>> 63) ^ 0x7fffffff;
723 env
->macc
[acc
] = result
;
726 void HELPER(macsatu
)(CPUState
*env
, uint32_t acc
)
730 val
= env
->macc
[acc
];
731 if (val
& (0xffffull
<< 48)) {
732 env
->macsr
|= MACSR_V
;
734 if (env
->macsr
& MACSR_V
) {
735 env
->macsr
|= MACSR_PAV0
<< acc
;
736 if (env
->macsr
& MACSR_OMC
) {
737 if (val
> (1ull << 53))
740 val
= (1ull << 48) - 1;
742 val
&= ((1ull << 48) - 1);
745 env
->macc
[acc
] = val
;
748 void HELPER(macsatf
)(CPUState
*env
, uint32_t acc
)
753 sum
= env
->macc
[acc
];
754 result
= (sum
<< 16) >> 16;
756 env
->macsr
|= MACSR_V
;
758 if (env
->macsr
& MACSR_V
) {
759 env
->macsr
|= MACSR_PAV0
<< acc
;
760 if (env
->macsr
& MACSR_OMC
) {
761 result
= (result
>> 63) ^ 0x7fffffffffffll
;
764 env
->macc
[acc
] = result
;
767 void HELPER(mac_set_flags
)(CPUState
*env
, uint32_t acc
)
770 val
= env
->macc
[acc
];
772 env
->macsr
|= MACSR_Z
;
773 else if (val
& (1ull << 47));
774 env
->macsr
|= MACSR_N
;
775 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
776 env
->macsr
|= MACSR_V
;
778 if (env
->macsr
& MACSR_FI
) {
779 val
= ((int64_t)val
) >> 40;
780 if (val
!= 0 && val
!= -1)
781 env
->macsr
|= MACSR_EV
;
782 } else if (env
->macsr
& MACSR_SU
) {
783 val
= ((int64_t)val
) >> 32;
784 if (val
!= 0 && val
!= -1)
785 env
->macsr
|= MACSR_EV
;
787 if ((val
>> 32) != 0)
788 env
->macsr
|= MACSR_EV
;
792 void HELPER(flush_flags
)(CPUState
*env
, uint32_t cc_op
)
794 cpu_m68k_flush_flags(env
, cc_op
);
797 uint32_t HELPER(get_macf
)(CPUState
*env
, uint64_t val
)
802 if (env
->macsr
& MACSR_SU
) {
803 /* 16-bit rounding. */
804 rem
= val
& 0xffffff;
805 val
= (val
>> 24) & 0xffffu
;
808 else if (rem
== 0x800000)
810 } else if (env
->macsr
& MACSR_RT
) {
811 /* 32-bit rounding. */
816 else if (rem
== 0x80)
822 if (env
->macsr
& MACSR_OMC
) {
824 if (env
->macsr
& MACSR_SU
) {
825 if (val
!= (uint16_t) val
) {
826 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
828 result
= val
& 0xffff;
831 if (val
!= (uint32_t)val
) {
832 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
834 result
= (uint32_t)val
;
839 if (env
->macsr
& MACSR_SU
) {
840 result
= val
& 0xffff;
842 result
= (uint32_t)val
;
848 uint32_t HELPER(get_macs
)(uint64_t val
)
850 if (val
== (int32_t)val
) {
853 return (val
>> 61) ^ ~SIGNBIT
;
857 uint32_t HELPER(get_macu
)(uint64_t val
)
859 if ((val
>> 32) == 0) {
860 return (uint32_t)val
;
866 uint32_t HELPER(get_mac_extf
)(CPUState
*env
, uint32_t acc
)
869 val
= env
->macc
[acc
] & 0x00ff;
870 val
= (env
->macc
[acc
] >> 32) & 0xff00;
871 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
872 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
876 uint32_t HELPER(get_mac_exti
)(CPUState
*env
, uint32_t acc
)
879 val
= (env
->macc
[acc
] >> 32) & 0xffff;
880 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
884 void HELPER(set_mac_extf
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
888 res
= env
->macc
[acc
] & 0xffffffff00ull
;
889 tmp
= (int16_t)(val
& 0xff00);
890 res
|= ((int64_t)tmp
) << 32;
892 env
->macc
[acc
] = res
;
893 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
894 tmp
= (val
& 0xff000000);
895 res
|= ((int64_t)tmp
) << 16;
896 res
|= (val
>> 16) & 0xff;
897 env
->macc
[acc
+ 1] = res
;
900 void HELPER(set_mac_exts
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
904 res
= (uint32_t)env
->macc
[acc
];
906 res
|= ((int64_t)tmp
) << 32;
907 env
->macc
[acc
] = res
;
908 res
= (uint32_t)env
->macc
[acc
+ 1];
909 tmp
= val
& 0xffff0000;
910 res
|= (int64_t)tmp
<< 16;
911 env
->macc
[acc
+ 1] = res
;
914 void HELPER(set_mac_extu
)(CPUState
*env
, uint32_t val
, uint32_t acc
)
917 res
= (uint32_t)env
->macc
[acc
];
918 res
|= ((uint64_t)(val
& 0xffff)) << 32;
919 env
->macc
[acc
] = res
;
920 res
= (uint32_t)env
->macc
[acc
+ 1];
921 res
|= (uint64_t)(val
& 0xffff0000) << 16;
922 env
->macc
[acc
+ 1] = res
;