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.1 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 * Lesser 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/>.
21 #include "qemu/osdep.h"
23 #include "exec/exec-all.h"
24 #include "exec/gdbstub.h"
25 #include "exec/helper-proto.h"
26 #include "gdbstub/helpers.h"
27 #include "fpu/softfloat.h"
28 #include "qemu/qemu-print.h"
30 #define SIGNBIT (1u << 31)
32 /* Sort alphabetically, except for "any". */
33 static gint
m68k_cpu_list_compare(gconstpointer a
, gconstpointer b
)
35 ObjectClass
*class_a
= (ObjectClass
*)a
;
36 ObjectClass
*class_b
= (ObjectClass
*)b
;
37 const char *name_a
, *name_b
;
39 name_a
= object_class_get_name(class_a
);
40 name_b
= object_class_get_name(class_b
);
41 if (strcmp(name_a
, "any-" TYPE_M68K_CPU
) == 0) {
43 } else if (strcmp(name_b
, "any-" TYPE_M68K_CPU
) == 0) {
46 return strcasecmp(name_a
, name_b
);
50 static void m68k_cpu_list_entry(gpointer data
, gpointer user_data
)
52 ObjectClass
*c
= data
;
56 typename
= object_class_get_name(c
);
57 name
= g_strndup(typename
, strlen(typename
) - strlen("-" TYPE_M68K_CPU
));
58 qemu_printf("%s\n", name
);
62 void m68k_cpu_list(void)
66 list
= object_class_get_list(TYPE_M68K_CPU
, false);
67 list
= g_slist_sort(list
, m68k_cpu_list_compare
);
68 g_slist_foreach(list
, m68k_cpu_list_entry
, NULL
);
72 static int cf_fpu_gdb_get_reg(CPUM68KState
*env
, GByteArray
*mem_buf
, int n
)
76 return gdb_get_reg64(mem_buf
, floatx80_to_float64(env
->fregs
[n
].d
, &s
));
79 case 8: /* fpcontrol */
80 return gdb_get_reg32(mem_buf
, env
->fpcr
);
81 case 9: /* fpstatus */
82 return gdb_get_reg32(mem_buf
, env
->fpsr
);
83 case 10: /* fpiar, not implemented */
84 return gdb_get_reg32(mem_buf
, 0);
89 static int cf_fpu_gdb_set_reg(CPUM68KState
*env
, uint8_t *mem_buf
, int n
)
93 env
->fregs
[n
].d
= float64_to_floatx80(ldq_p(mem_buf
), &s
);
97 case 8: /* fpcontrol */
98 cpu_m68k_set_fpcr(env
, ldl_p(mem_buf
));
100 case 9: /* fpstatus */
101 env
->fpsr
= ldl_p(mem_buf
);
103 case 10: /* fpiar, not implemented */
109 static int m68k_fpu_gdb_get_reg(CPUM68KState
*env
, GByteArray
*mem_buf
, int n
)
112 int len
= gdb_get_reg16(mem_buf
, env
->fregs
[n
].l
.upper
);
113 len
+= gdb_get_reg16(mem_buf
, 0);
114 len
+= gdb_get_reg64(mem_buf
, env
->fregs
[n
].l
.lower
);
118 case 8: /* fpcontrol */
119 return gdb_get_reg32(mem_buf
, env
->fpcr
);
120 case 9: /* fpstatus */
121 return gdb_get_reg32(mem_buf
, env
->fpsr
);
122 case 10: /* fpiar, not implemented */
123 return gdb_get_reg32(mem_buf
, 0);
128 static int m68k_fpu_gdb_set_reg(CPUM68KState
*env
, uint8_t *mem_buf
, int n
)
131 env
->fregs
[n
].l
.upper
= lduw_be_p(mem_buf
);
132 env
->fregs
[n
].l
.lower
= ldq_be_p(mem_buf
+ 4);
136 case 8: /* fpcontrol */
137 cpu_m68k_set_fpcr(env
, ldl_p(mem_buf
));
139 case 9: /* fpstatus */
140 env
->fpsr
= ldl_p(mem_buf
);
142 case 10: /* fpiar, not implemented */
148 void m68k_cpu_init_gdb(M68kCPU
*cpu
)
150 CPUState
*cs
= CPU(cpu
);
151 CPUM68KState
*env
= &cpu
->env
;
153 if (m68k_feature(env
, M68K_FEATURE_CF_FPU
)) {
154 gdb_register_coprocessor(cs
, cf_fpu_gdb_get_reg
, cf_fpu_gdb_set_reg
,
155 11, "cf-fp.xml", 18);
156 } else if (m68k_feature(env
, M68K_FEATURE_FPU
)) {
157 gdb_register_coprocessor(cs
, m68k_fpu_gdb_get_reg
,
158 m68k_fpu_gdb_set_reg
, 11, "m68k-fp.xml", 18);
160 /* TODO: Add [E]MAC registers. */
163 void HELPER(cf_movec_to
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
174 /* TODO: Implement Access Control Registers. */
179 /* TODO: Implement control registers. */
181 cpu_abort(env_cpu(env
),
182 "Unimplemented control register write 0x%x = 0x%x\n",
187 static void raise_exception_ra(CPUM68KState
*env
, int tt
, uintptr_t raddr
)
189 CPUState
*cs
= env_cpu(env
);
191 cs
->exception_index
= tt
;
192 cpu_loop_exit_restore(cs
, raddr
);
195 void HELPER(m68k_movec_to
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
212 if (m68k_feature(env
, M68K_FEATURE_M68020
)) {
213 env
->cacr
= val
& 0x0000000f;
214 } else if (m68k_feature(env
, M68K_FEATURE_M68030
)) {
215 env
->cacr
= val
& 0x00003f1f;
216 } else if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
217 env
->cacr
= val
& 0x80008000;
218 } else if (m68k_feature(env
, M68K_FEATURE_M68060
)) {
219 env
->cacr
= val
& 0xf8e0e000;
227 if (m68k_feature(env
, M68K_FEATURE_M68040
)
228 || m68k_feature(env
, M68K_FEATURE_M68060
)) {
235 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
236 env
->mmu
.mmusr
= val
;
242 if (m68k_feature(env
, M68K_FEATURE_M68040
)
243 || m68k_feature(env
, M68K_FEATURE_M68060
)) {
250 if (m68k_feature(env
, M68K_FEATURE_M68040
)
251 || m68k_feature(env
, M68K_FEATURE_M68060
)) {
258 env
->sp
[M68K_USP
] = val
;
262 if (m68k_feature(env
, M68K_FEATURE_M68020
)
263 || m68k_feature(env
, M68K_FEATURE_M68030
)
264 || m68k_feature(env
, M68K_FEATURE_M68040
)) {
265 env
->sp
[M68K_SSP
] = val
;
271 if (m68k_feature(env
, M68K_FEATURE_M68020
)
272 || m68k_feature(env
, M68K_FEATURE_M68030
)
273 || m68k_feature(env
, M68K_FEATURE_M68040
)) {
274 env
->sp
[M68K_ISP
] = val
;
278 /* MC68040/MC68LC040 */
279 case M68K_CR_ITT0
: /* MC68EC040 only: M68K_CR_IACR0 */
280 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
281 env
->mmu
.ttr
[M68K_ITTR0
] = val
;
285 /* MC68040/MC68LC040 */
286 case M68K_CR_ITT1
: /* MC68EC040 only: M68K_CR_IACR1 */
287 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
288 env
->mmu
.ttr
[M68K_ITTR1
] = val
;
292 /* MC68040/MC68LC040 */
293 case M68K_CR_DTT0
: /* MC68EC040 only: M68K_CR_DACR0 */
294 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
295 env
->mmu
.ttr
[M68K_DTTR0
] = val
;
299 /* MC68040/MC68LC040 */
300 case M68K_CR_DTT1
: /* MC68EC040 only: M68K_CR_DACR1 */
301 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
302 env
->mmu
.ttr
[M68K_DTTR1
] = val
;
306 /* Unimplemented Registers */
310 cpu_abort(env_cpu(env
),
311 "Unimplemented control register write 0x%x = 0x%x\n",
315 /* Invalid control registers will generate an exception. */
316 raise_exception_ra(env
, EXCP_ILLEGAL
, 0);
320 uint32_t HELPER(m68k_movec_from
)(CPUM68KState
*env
, uint32_t reg
)
334 if (m68k_feature(env
, M68K_FEATURE_M68020
)
335 || m68k_feature(env
, M68K_FEATURE_M68030
)
336 || m68k_feature(env
, M68K_FEATURE_M68040
)
337 || m68k_feature(env
, M68K_FEATURE_M68060
)) {
343 if (m68k_feature(env
, M68K_FEATURE_M68040
)
344 || m68k_feature(env
, M68K_FEATURE_M68060
)) {
350 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
351 return env
->mmu
.mmusr
;
356 if (m68k_feature(env
, M68K_FEATURE_M68040
)
357 || m68k_feature(env
, M68K_FEATURE_M68060
)) {
361 /* MC68040/MC68LC040 */
363 if (m68k_feature(env
, M68K_FEATURE_M68040
)
364 || m68k_feature(env
, M68K_FEATURE_M68060
)) {
370 return env
->sp
[M68K_USP
];
373 if (m68k_feature(env
, M68K_FEATURE_M68020
)
374 || m68k_feature(env
, M68K_FEATURE_M68030
)
375 || m68k_feature(env
, M68K_FEATURE_M68040
)) {
376 return env
->sp
[M68K_SSP
];
381 if (m68k_feature(env
, M68K_FEATURE_M68020
)
382 || m68k_feature(env
, M68K_FEATURE_M68030
)
383 || m68k_feature(env
, M68K_FEATURE_M68040
)) {
384 return env
->sp
[M68K_ISP
];
387 /* MC68040/MC68LC040 */
388 case M68K_CR_ITT0
: /* MC68EC040 only: M68K_CR_IACR0 */
389 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
390 return env
->mmu
.ttr
[M68K_ITTR0
];
393 /* MC68040/MC68LC040 */
394 case M68K_CR_ITT1
: /* MC68EC040 only: M68K_CR_IACR1 */
395 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
396 return env
->mmu
.ttr
[M68K_ITTR1
];
399 /* MC68040/MC68LC040 */
400 case M68K_CR_DTT0
: /* MC68EC040 only: M68K_CR_DACR0 */
401 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
402 return env
->mmu
.ttr
[M68K_DTTR0
];
405 /* MC68040/MC68LC040 */
406 case M68K_CR_DTT1
: /* MC68EC040 only: M68K_CR_DACR1 */
407 if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
408 return env
->mmu
.ttr
[M68K_DTTR1
];
411 /* Unimplemented Registers */
415 cpu_abort(env_cpu(env
), "Unimplemented control register read 0x%x\n",
419 /* Invalid control registers will generate an exception. */
420 raise_exception_ra(env
, EXCP_ILLEGAL
, 0);
425 void HELPER(set_macsr
)(CPUM68KState
*env
, uint32_t val
)
432 if ((env
->macsr
^ val
) & (MACSR_FI
| MACSR_SU
)) {
433 for (i
= 0; i
< 4; i
++) {
434 regval
= env
->macc
[i
];
435 exthigh
= regval
>> 40;
436 if (env
->macsr
& MACSR_FI
) {
441 extlow
= regval
>> 32;
443 if (env
->macsr
& MACSR_FI
) {
444 regval
= (((uint64_t)acc
) << 8) | extlow
;
445 regval
|= ((int64_t)exthigh
) << 40;
446 } else if (env
->macsr
& MACSR_SU
) {
447 regval
= acc
| (((int64_t)extlow
) << 32);
448 regval
|= ((int64_t)exthigh
) << 40;
450 regval
= acc
| (((uint64_t)extlow
) << 32);
451 regval
|= ((uint64_t)(uint8_t)exthigh
) << 40;
453 env
->macc
[i
] = regval
;
459 void m68k_switch_sp(CPUM68KState
*env
)
463 env
->sp
[env
->current_sp
] = env
->aregs
[7];
464 if (m68k_feature(env
, M68K_FEATURE_M68K
)) {
465 if (env
->sr
& SR_S
) {
466 /* SR:Master-Mode bit unimplemented then ISP is not available */
467 if (!m68k_feature(env
, M68K_FEATURE_MSP
) || env
->sr
& SR_M
) {
476 new_sp
= (env
->sr
& SR_S
&& env
->cacr
& M68K_CACR_EUSP
)
477 ? M68K_SSP
: M68K_USP
;
479 env
->aregs
[7] = env
->sp
[new_sp
];
480 env
->current_sp
= new_sp
;
483 #if !defined(CONFIG_USER_ONLY)
484 /* MMU: 68040 only */
486 static void print_address_zone(uint32_t logical
, uint32_t physical
,
487 uint32_t size
, int attr
)
489 qemu_printf("%08x - %08x -> %08x - %08x %c ",
490 logical
, logical
+ size
- 1,
491 physical
, physical
+ size
- 1,
492 attr
& 4 ? 'W' : '-');
495 qemu_printf("(%d KiB)\n", size
);
499 qemu_printf("(%d MiB)\n", size
);
502 qemu_printf("(%d GiB)\n", size
);
507 static void dump_address_map(CPUM68KState
*env
, uint32_t root_pointer
)
510 int tic_size
, tic_shift
;
512 uint32_t tia
, tib
, tic
;
513 uint32_t logical
= 0xffffffff, physical
= 0xffffffff;
514 uint32_t first_logical
= 0xffffffff, first_physical
= 0xffffffff;
515 uint32_t last_logical
, last_physical
;
517 int last_attr
= -1, attr
= -1;
518 CPUState
*cs
= env_cpu(env
);
521 if (env
->mmu
.tcr
& M68K_TCR_PAGE_8K
) {
525 tib_mask
= M68K_8K_PAGE_MASK
;
530 tib_mask
= M68K_4K_PAGE_MASK
;
532 for (i
= 0; i
< M68K_ROOT_POINTER_ENTRIES
; i
++) {
533 tia
= address_space_ldl(cs
->as
, M68K_POINTER_BASE(root_pointer
) + i
* 4,
534 MEMTXATTRS_UNSPECIFIED
, &txres
);
535 if (txres
!= MEMTX_OK
|| !M68K_UDT_VALID(tia
)) {
538 for (j
= 0; j
< M68K_ROOT_POINTER_ENTRIES
; j
++) {
539 tib
= address_space_ldl(cs
->as
, M68K_POINTER_BASE(tia
) + j
* 4,
540 MEMTXATTRS_UNSPECIFIED
, &txres
);
541 if (txres
!= MEMTX_OK
|| !M68K_UDT_VALID(tib
)) {
544 for (k
= 0; k
< tic_size
; k
++) {
545 tic
= address_space_ldl(cs
->as
, (tib
& tib_mask
) + k
* 4,
546 MEMTXATTRS_UNSPECIFIED
, &txres
);
547 if (txres
!= MEMTX_OK
|| !M68K_PDT_VALID(tic
)) {
550 if (M68K_PDT_INDIRECT(tic
)) {
551 tic
= address_space_ldl(cs
->as
, M68K_INDIRECT_POINTER(tic
),
552 MEMTXATTRS_UNSPECIFIED
, &txres
);
553 if (txres
!= MEMTX_OK
) {
558 last_logical
= logical
;
559 logical
= (i
<< M68K_TTS_ROOT_SHIFT
) |
560 (j
<< M68K_TTS_POINTER_SHIFT
) |
563 last_physical
= physical
;
564 physical
= tic
& ~((1 << tic_shift
) - 1);
567 attr
= tic
& ((1 << tic_shift
) - 1);
569 if ((logical
!= (last_logical
+ (1 << tic_shift
))) ||
570 (physical
!= (last_physical
+ (1 << tic_shift
))) ||
571 (attr
& 4) != (last_attr
& 4)) {
573 if (first_logical
!= 0xffffffff) {
574 size
= last_logical
+ (1 << tic_shift
) -
576 print_address_zone(first_logical
,
577 first_physical
, size
, last_attr
);
579 first_logical
= logical
;
580 first_physical
= physical
;
585 if (first_logical
!= logical
|| (attr
& 4) != (last_attr
& 4)) {
586 size
= logical
+ (1 << tic_shift
) - first_logical
;
587 print_address_zone(first_logical
, first_physical
, size
, last_attr
);
591 #define DUMP_CACHEFLAGS(a) \
592 switch (a & M68K_DESC_CACHEMODE) { \
593 case M68K_DESC_CM_WRTHRU: /* cachable, write-through */ \
596 case M68K_DESC_CM_COPYBK: /* cachable, copyback */ \
599 case M68K_DESC_CM_SERIAL: /* noncachable, serialized */ \
602 case M68K_DESC_CM_NCACHE: /* noncachable */ \
607 static void dump_ttr(uint32_t ttr
)
609 if ((ttr
& M68K_TTR_ENABLED
) == 0) {
610 qemu_printf("disabled\n");
613 qemu_printf("Base: 0x%08x Mask: 0x%08x Control: ",
614 ttr
& M68K_TTR_ADDR_BASE
,
615 (ttr
& M68K_TTR_ADDR_MASK
) << M68K_TTR_ADDR_MASK_SHIFT
);
616 switch (ttr
& M68K_TTR_SFIELD
) {
617 case M68K_TTR_SFIELD_USER
:
620 case M68K_TTR_SFIELD_SUPER
:
627 DUMP_CACHEFLAGS(ttr
);
628 if (ttr
& M68K_DESC_WRITEPROT
) {
633 qemu_printf(" U: %d\n", (ttr
& M68K_DESC_USERATTR
) >>
634 M68K_DESC_USERATTR_SHIFT
);
637 void dump_mmu(CPUM68KState
*env
)
639 if ((env
->mmu
.tcr
& M68K_TCR_ENABLED
) == 0) {
640 qemu_printf("Translation disabled\n");
643 qemu_printf("Page Size: ");
644 if (env
->mmu
.tcr
& M68K_TCR_PAGE_8K
) {
645 qemu_printf("8kB\n");
647 qemu_printf("4kB\n");
650 qemu_printf("MMUSR: ");
651 if (env
->mmu
.mmusr
& M68K_MMU_B_040
) {
652 qemu_printf("BUS ERROR\n");
654 qemu_printf("Phy=%08x Flags: ", env
->mmu
.mmusr
& 0xfffff000);
655 /* flags found on the page descriptor */
656 if (env
->mmu
.mmusr
& M68K_MMU_G_040
) {
657 qemu_printf("G"); /* Global */
661 if (env
->mmu
.mmusr
& M68K_MMU_S_040
) {
662 qemu_printf("S"); /* Supervisor */
666 if (env
->mmu
.mmusr
& M68K_MMU_M_040
) {
667 qemu_printf("M"); /* Modified */
671 if (env
->mmu
.mmusr
& M68K_MMU_WP_040
) {
672 qemu_printf("W"); /* Write protect */
676 if (env
->mmu
.mmusr
& M68K_MMU_T_040
) {
677 qemu_printf("T"); /* Transparent */
681 if (env
->mmu
.mmusr
& M68K_MMU_R_040
) {
682 qemu_printf("R"); /* Resident */
686 qemu_printf(" Cache: ");
687 DUMP_CACHEFLAGS(env
->mmu
.mmusr
);
688 qemu_printf(" U: %d\n", (env
->mmu
.mmusr
>> 8) & 3);
692 qemu_printf("ITTR0: ");
693 dump_ttr(env
->mmu
.ttr
[M68K_ITTR0
]);
694 qemu_printf("ITTR1: ");
695 dump_ttr(env
->mmu
.ttr
[M68K_ITTR1
]);
696 qemu_printf("DTTR0: ");
697 dump_ttr(env
->mmu
.ttr
[M68K_DTTR0
]);
698 qemu_printf("DTTR1: ");
699 dump_ttr(env
->mmu
.ttr
[M68K_DTTR1
]);
701 qemu_printf("SRP: 0x%08x\n", env
->mmu
.srp
);
702 dump_address_map(env
, env
->mmu
.srp
);
704 qemu_printf("URP: 0x%08x\n", env
->mmu
.urp
);
705 dump_address_map(env
, env
->mmu
.urp
);
708 static int check_TTR(uint32_t ttr
, int *prot
, target_ulong addr
,
713 /* check if transparent translation is enabled */
714 if ((ttr
& M68K_TTR_ENABLED
) == 0) {
718 /* check mode access */
719 switch (ttr
& M68K_TTR_SFIELD
) {
720 case M68K_TTR_SFIELD_USER
:
721 /* match only if user */
722 if ((access_type
& ACCESS_SUPER
) != 0) {
726 case M68K_TTR_SFIELD_SUPER
:
727 /* match only if supervisor */
728 if ((access_type
& ACCESS_SUPER
) == 0) {
733 /* all other values disable mode matching (FC2) */
737 /* check address matching */
739 base
= ttr
& M68K_TTR_ADDR_BASE
;
740 mask
= (ttr
& M68K_TTR_ADDR_MASK
) ^ M68K_TTR_ADDR_MASK
;
741 mask
<<= M68K_TTR_ADDR_MASK_SHIFT
;
743 if ((addr
& mask
) != (base
& mask
)) {
747 *prot
= PAGE_READ
| PAGE_EXEC
;
748 if ((ttr
& M68K_DESC_WRITEPROT
) == 0) {
755 static int get_physical_address(CPUM68KState
*env
, hwaddr
*physical
,
756 int *prot
, target_ulong address
,
757 int access_type
, target_ulong
*page_size
)
759 CPUState
*cs
= env_cpu(env
);
762 target_ulong page_mask
;
763 bool debug
= access_type
& ACCESS_DEBUG
;
768 /* Transparent Translation (physical = logical) */
769 for (i
= 0; i
< M68K_MAX_TTR
; i
++) {
770 if (check_TTR(env
->mmu
.TTR(access_type
, i
),
771 prot
, address
, access_type
)) {
772 if (access_type
& ACCESS_PTEST
) {
773 /* Transparent Translation Register bit */
774 env
->mmu
.mmusr
= M68K_MMU_T_040
| M68K_MMU_R_040
;
777 *page_size
= TARGET_PAGE_SIZE
;
782 /* Page Table Root Pointer */
783 *prot
= PAGE_READ
| PAGE_WRITE
;
784 if (access_type
& ACCESS_CODE
) {
787 if (access_type
& ACCESS_SUPER
) {
794 entry
= M68K_POINTER_BASE(next
) | M68K_ROOT_INDEX(address
);
796 next
= address_space_ldl(cs
->as
, entry
, MEMTXATTRS_UNSPECIFIED
, &txres
);
797 if (txres
!= MEMTX_OK
) {
800 if (!M68K_UDT_VALID(next
)) {
803 if (!(next
& M68K_DESC_USED
) && !debug
) {
804 address_space_stl(cs
->as
, entry
, next
| M68K_DESC_USED
,
805 MEMTXATTRS_UNSPECIFIED
, &txres
);
806 if (txres
!= MEMTX_OK
) {
810 if (next
& M68K_DESC_WRITEPROT
) {
811 if (access_type
& ACCESS_PTEST
) {
812 env
->mmu
.mmusr
|= M68K_MMU_WP_040
;
814 *prot
&= ~PAGE_WRITE
;
815 if (access_type
& ACCESS_STORE
) {
821 entry
= M68K_POINTER_BASE(next
) | M68K_POINTER_INDEX(address
);
823 next
= address_space_ldl(cs
->as
, entry
, MEMTXATTRS_UNSPECIFIED
, &txres
);
824 if (txres
!= MEMTX_OK
) {
827 if (!M68K_UDT_VALID(next
)) {
830 if (!(next
& M68K_DESC_USED
) && !debug
) {
831 address_space_stl(cs
->as
, entry
, next
| M68K_DESC_USED
,
832 MEMTXATTRS_UNSPECIFIED
, &txres
);
833 if (txres
!= MEMTX_OK
) {
837 if (next
& M68K_DESC_WRITEPROT
) {
838 if (access_type
& ACCESS_PTEST
) {
839 env
->mmu
.mmusr
|= M68K_MMU_WP_040
;
841 *prot
&= ~PAGE_WRITE
;
842 if (access_type
& ACCESS_STORE
) {
848 if (env
->mmu
.tcr
& M68K_TCR_PAGE_8K
) {
849 entry
= M68K_8K_PAGE_BASE(next
) | M68K_8K_PAGE_INDEX(address
);
851 entry
= M68K_4K_PAGE_BASE(next
) | M68K_4K_PAGE_INDEX(address
);
854 next
= address_space_ldl(cs
->as
, entry
, MEMTXATTRS_UNSPECIFIED
, &txres
);
855 if (txres
!= MEMTX_OK
) {
859 if (!M68K_PDT_VALID(next
)) {
862 if (M68K_PDT_INDIRECT(next
)) {
863 next
= address_space_ldl(cs
->as
, M68K_INDIRECT_POINTER(next
),
864 MEMTXATTRS_UNSPECIFIED
, &txres
);
865 if (txres
!= MEMTX_OK
) {
869 if (access_type
& ACCESS_STORE
) {
870 if (next
& M68K_DESC_WRITEPROT
) {
871 if (!(next
& M68K_DESC_USED
) && !debug
) {
872 address_space_stl(cs
->as
, entry
, next
| M68K_DESC_USED
,
873 MEMTXATTRS_UNSPECIFIED
, &txres
);
874 if (txres
!= MEMTX_OK
) {
878 } else if ((next
& (M68K_DESC_MODIFIED
| M68K_DESC_USED
)) !=
879 (M68K_DESC_MODIFIED
| M68K_DESC_USED
) && !debug
) {
880 address_space_stl(cs
->as
, entry
,
881 next
| (M68K_DESC_MODIFIED
| M68K_DESC_USED
),
882 MEMTXATTRS_UNSPECIFIED
, &txres
);
883 if (txres
!= MEMTX_OK
) {
888 if (!(next
& M68K_DESC_USED
) && !debug
) {
889 address_space_stl(cs
->as
, entry
, next
| M68K_DESC_USED
,
890 MEMTXATTRS_UNSPECIFIED
, &txres
);
891 if (txres
!= MEMTX_OK
) {
897 if (env
->mmu
.tcr
& M68K_TCR_PAGE_8K
) {
902 *page_size
= 1 << page_bits
;
903 page_mask
= ~(*page_size
- 1);
904 *physical
= (next
& page_mask
) + (address
& (*page_size
- 1));
906 if (access_type
& ACCESS_PTEST
) {
907 env
->mmu
.mmusr
|= next
& M68K_MMU_SR_MASK_040
;
908 env
->mmu
.mmusr
|= *physical
& 0xfffff000;
909 env
->mmu
.mmusr
|= M68K_MMU_R_040
;
912 if (next
& M68K_DESC_WRITEPROT
) {
913 *prot
&= ~PAGE_WRITE
;
914 if (access_type
& ACCESS_STORE
) {
918 if (next
& M68K_DESC_SUPERONLY
) {
919 if ((access_type
& ACCESS_SUPER
) == 0) {
928 * A page table load/store failed. TODO: we should really raise a
929 * suitable guest fault here if this is not a debug access.
930 * For now just return that the translation failed.
935 hwaddr
m68k_cpu_get_phys_page_debug(CPUState
*cs
, vaddr addr
)
937 M68kCPU
*cpu
= M68K_CPU(cs
);
938 CPUM68KState
*env
= &cpu
->env
;
942 target_ulong page_size
;
944 if ((env
->mmu
.tcr
& M68K_TCR_ENABLED
) == 0) {
949 access_type
= ACCESS_DATA
| ACCESS_DEBUG
;
950 if (env
->sr
& SR_S
) {
951 access_type
|= ACCESS_SUPER
;
954 if (get_physical_address(env
, &phys_addr
, &prot
,
955 addr
, access_type
, &page_size
) != 0) {
963 * Notify CPU of a pending interrupt. Prioritization and vectoring should
964 * be handled by the interrupt controller. Real hardware only requests
965 * the vector when the interrupt is acknowledged by the CPU. For
966 * simplicity we calculate it when the interrupt is signalled.
968 void m68k_set_irq_level(M68kCPU
*cpu
, int level
, uint8_t vector
)
970 CPUState
*cs
= CPU(cpu
);
971 CPUM68KState
*env
= &cpu
->env
;
973 env
->pending_level
= level
;
974 env
->pending_vector
= vector
;
976 cpu_interrupt(cs
, CPU_INTERRUPT_HARD
);
978 cpu_reset_interrupt(cs
, CPU_INTERRUPT_HARD
);
982 bool m68k_cpu_tlb_fill(CPUState
*cs
, vaddr address
, int size
,
983 MMUAccessType qemu_access_type
, int mmu_idx
,
984 bool probe
, uintptr_t retaddr
)
986 M68kCPU
*cpu
= M68K_CPU(cs
);
987 CPUM68KState
*env
= &cpu
->env
;
992 target_ulong page_size
;
994 if ((env
->mmu
.tcr
& M68K_TCR_ENABLED
) == 0) {
996 tlb_set_page(cs
, address
& TARGET_PAGE_MASK
,
997 address
& TARGET_PAGE_MASK
,
998 PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
,
999 mmu_idx
, TARGET_PAGE_SIZE
);
1003 if (qemu_access_type
== MMU_INST_FETCH
) {
1004 access_type
= ACCESS_CODE
;
1006 access_type
= ACCESS_DATA
;
1007 if (qemu_access_type
== MMU_DATA_STORE
) {
1008 access_type
|= ACCESS_STORE
;
1011 if (mmu_idx
!= MMU_USER_IDX
) {
1012 access_type
|= ACCESS_SUPER
;
1015 ret
= get_physical_address(&cpu
->env
, &physical
, &prot
,
1016 address
, access_type
, &page_size
);
1017 if (likely(ret
== 0)) {
1018 tlb_set_page(cs
, address
& TARGET_PAGE_MASK
,
1019 physical
& TARGET_PAGE_MASK
, prot
, mmu_idx
, page_size
);
1028 env
->mmu
.ssw
= M68K_ATC_040
;
1031 env
->mmu
.ssw
|= M68K_BA_SIZE_BYTE
;
1034 env
->mmu
.ssw
|= M68K_BA_SIZE_WORD
;
1037 env
->mmu
.ssw
|= M68K_BA_SIZE_LONG
;
1040 if (access_type
& ACCESS_SUPER
) {
1041 env
->mmu
.ssw
|= M68K_TM_040_SUPER
;
1043 if (access_type
& ACCESS_CODE
) {
1044 env
->mmu
.ssw
|= M68K_TM_040_CODE
;
1046 env
->mmu
.ssw
|= M68K_TM_040_DATA
;
1048 if (!(access_type
& ACCESS_STORE
)) {
1049 env
->mmu
.ssw
|= M68K_RW_040
;
1052 cs
->exception_index
= EXCP_ACCESS
;
1053 env
->mmu
.ar
= address
;
1054 cpu_loop_exit_restore(cs
, retaddr
);
1056 #endif /* !CONFIG_USER_ONLY */
1058 uint32_t HELPER(bitrev
)(uint32_t x
)
1060 x
= ((x
>> 1) & 0x55555555u
) | ((x
<< 1) & 0xaaaaaaaau
);
1061 x
= ((x
>> 2) & 0x33333333u
) | ((x
<< 2) & 0xccccccccu
);
1062 x
= ((x
>> 4) & 0x0f0f0f0fu
) | ((x
<< 4) & 0xf0f0f0f0u
);
1066 uint32_t HELPER(ff1
)(uint32_t x
)
1069 for (n
= 32; x
; n
--)
1074 uint32_t HELPER(sats
)(uint32_t val
, uint32_t v
)
1076 /* The result has the opposite sign to the original value. */
1077 if ((int32_t)v
< 0) {
1078 val
= (((int32_t)val
) >> 31) ^ SIGNBIT
;
1083 void cpu_m68k_set_sr(CPUM68KState
*env
, uint32_t sr
)
1085 env
->sr
= sr
& 0xffe0;
1086 cpu_m68k_set_ccr(env
, sr
);
1087 m68k_switch_sp(env
);
1090 void HELPER(set_sr
)(CPUM68KState
*env
, uint32_t val
)
1092 cpu_m68k_set_sr(env
, val
);
1097 * FIXME: The MAC unit implementation is a bit of a mess. Some helpers
1098 * take values, others take register numbers and manipulate the contents
1101 void HELPER(mac_move
)(CPUM68KState
*env
, uint32_t dest
, uint32_t src
)
1104 env
->macc
[dest
] = env
->macc
[src
];
1105 mask
= MACSR_PAV0
<< dest
;
1106 if (env
->macsr
& (MACSR_PAV0
<< src
))
1109 env
->macsr
&= ~mask
;
1112 uint64_t HELPER(macmuls
)(CPUM68KState
*env
, uint32_t op1
, uint32_t op2
)
1117 product
= (uint64_t)op1
* op2
;
1118 res
= (product
<< 24) >> 24;
1119 if (res
!= product
) {
1120 env
->macsr
|= MACSR_V
;
1121 if (env
->macsr
& MACSR_OMC
) {
1122 /* Make sure the accumulate operation overflows. */
1132 uint64_t HELPER(macmulu
)(CPUM68KState
*env
, uint32_t op1
, uint32_t op2
)
1136 product
= (uint64_t)op1
* op2
;
1137 if (product
& (0xffffffull
<< 40)) {
1138 env
->macsr
|= MACSR_V
;
1139 if (env
->macsr
& MACSR_OMC
) {
1140 /* Make sure the accumulate operation overflows. */
1141 product
= 1ll << 50;
1143 product
&= ((1ull << 40) - 1);
1149 uint64_t HELPER(macmulf
)(CPUM68KState
*env
, uint32_t op1
, uint32_t op2
)
1154 product
= (uint64_t)op1
* op2
;
1155 if (env
->macsr
& MACSR_RT
) {
1156 remainder
= product
& 0xffffff;
1158 if (remainder
> 0x800000)
1160 else if (remainder
== 0x800000)
1161 product
+= (product
& 1);
1168 void HELPER(macsats
)(CPUM68KState
*env
, uint32_t acc
)
1172 tmp
= env
->macc
[acc
];
1173 result
= ((tmp
<< 16) >> 16);
1174 if (result
!= tmp
) {
1175 env
->macsr
|= MACSR_V
;
1177 if (env
->macsr
& MACSR_V
) {
1178 env
->macsr
|= MACSR_PAV0
<< acc
;
1179 if (env
->macsr
& MACSR_OMC
) {
1181 * The result is saturated to 32 bits, despite overflow occurring
1182 * at 48 bits. Seems weird, but that's what the hardware docs
1185 result
= (result
>> 63) ^ 0x7fffffff;
1188 env
->macc
[acc
] = result
;
1191 void HELPER(macsatu
)(CPUM68KState
*env
, uint32_t acc
)
1195 val
= env
->macc
[acc
];
1196 if (val
& (0xffffull
<< 48)) {
1197 env
->macsr
|= MACSR_V
;
1199 if (env
->macsr
& MACSR_V
) {
1200 env
->macsr
|= MACSR_PAV0
<< acc
;
1201 if (env
->macsr
& MACSR_OMC
) {
1202 if (val
> (1ull << 53))
1205 val
= (1ull << 48) - 1;
1207 val
&= ((1ull << 48) - 1);
1210 env
->macc
[acc
] = val
;
1213 void HELPER(macsatf
)(CPUM68KState
*env
, uint32_t acc
)
1218 sum
= env
->macc
[acc
];
1219 result
= (sum
<< 16) >> 16;
1220 if (result
!= sum
) {
1221 env
->macsr
|= MACSR_V
;
1223 if (env
->macsr
& MACSR_V
) {
1224 env
->macsr
|= MACSR_PAV0
<< acc
;
1225 if (env
->macsr
& MACSR_OMC
) {
1226 result
= (result
>> 63) ^ 0x7fffffffffffll
;
1229 env
->macc
[acc
] = result
;
1232 void HELPER(mac_set_flags
)(CPUM68KState
*env
, uint32_t acc
)
1235 val
= env
->macc
[acc
];
1237 env
->macsr
|= MACSR_Z
;
1238 } else if (val
& (1ull << 47)) {
1239 env
->macsr
|= MACSR_N
;
1241 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
1242 env
->macsr
|= MACSR_V
;
1244 if (env
->macsr
& MACSR_FI
) {
1245 val
= ((int64_t)val
) >> 40;
1246 if (val
!= 0 && val
!= -1)
1247 env
->macsr
|= MACSR_EV
;
1248 } else if (env
->macsr
& MACSR_SU
) {
1249 val
= ((int64_t)val
) >> 32;
1250 if (val
!= 0 && val
!= -1)
1251 env
->macsr
|= MACSR_EV
;
1253 if ((val
>> 32) != 0)
1254 env
->macsr
|= MACSR_EV
;
1258 #define EXTSIGN(val, index) ( \
1259 (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
1262 #define COMPUTE_CCR(op, x, n, z, v, c) { \
1265 /* Everything in place. */ \
1272 src1 = EXTSIGN(res - src2, op - CC_OP_ADDB); \
1275 v = (res ^ src1) & ~(src1 ^ src2); \
1282 src1 = EXTSIGN(res + src2, op - CC_OP_SUBB); \
1285 v = (res ^ src1) & (src1 ^ src2); \
1292 res = EXTSIGN(src1 - src2, op - CC_OP_CMPB); \
1296 v = (res ^ src1) & (src1 ^ src2); \
1303 cpu_abort(env_cpu(env), "Bad CC_OP %d", op); \
1307 uint32_t cpu_m68k_get_ccr(CPUM68KState
*env
)
1309 uint32_t x
, c
, n
, z
, v
;
1310 uint32_t res
, src1
, src2
;
1318 COMPUTE_CCR(env
->cc_op
, x
, n
, z
, v
, c
);
1324 return x
* CCF_X
+ n
* CCF_N
+ z
* CCF_Z
+ v
* CCF_V
+ c
* CCF_C
;
1327 uint32_t HELPER(get_ccr
)(CPUM68KState
*env
)
1329 return cpu_m68k_get_ccr(env
);
1332 void cpu_m68k_set_ccr(CPUM68KState
*env
, uint32_t ccr
)
1334 env
->cc_x
= (ccr
& CCF_X
? 1 : 0);
1335 env
->cc_n
= (ccr
& CCF_N
? -1 : 0);
1336 env
->cc_z
= (ccr
& CCF_Z
? 0 : 1);
1337 env
->cc_v
= (ccr
& CCF_V
? -1 : 0);
1338 env
->cc_c
= (ccr
& CCF_C
? 1 : 0);
1339 env
->cc_op
= CC_OP_FLAGS
;
1342 void HELPER(set_ccr
)(CPUM68KState
*env
, uint32_t ccr
)
1344 cpu_m68k_set_ccr(env
, ccr
);
1347 void HELPER(flush_flags
)(CPUM68KState
*env
, uint32_t cc_op
)
1349 uint32_t res
, src1
, src2
;
1351 COMPUTE_CCR(cc_op
, env
->cc_x
, env
->cc_n
, env
->cc_z
, env
->cc_v
, env
->cc_c
);
1352 env
->cc_op
= CC_OP_FLAGS
;
1355 uint32_t HELPER(get_macf
)(CPUM68KState
*env
, uint64_t val
)
1360 if (env
->macsr
& MACSR_SU
) {
1361 /* 16-bit rounding. */
1362 rem
= val
& 0xffffff;
1363 val
= (val
>> 24) & 0xffffu
;
1366 else if (rem
== 0x800000)
1368 } else if (env
->macsr
& MACSR_RT
) {
1369 /* 32-bit rounding. */
1374 else if (rem
== 0x80)
1380 if (env
->macsr
& MACSR_OMC
) {
1382 if (env
->macsr
& MACSR_SU
) {
1383 if (val
!= (uint16_t) val
) {
1384 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
1386 result
= val
& 0xffff;
1389 if (val
!= (uint32_t)val
) {
1390 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
1392 result
= (uint32_t)val
;
1396 /* No saturation. */
1397 if (env
->macsr
& MACSR_SU
) {
1398 result
= val
& 0xffff;
1400 result
= (uint32_t)val
;
1406 uint32_t HELPER(get_macs
)(uint64_t val
)
1408 if (val
== (int32_t)val
) {
1409 return (int32_t)val
;
1411 return (val
>> 61) ^ ~SIGNBIT
;
1415 uint32_t HELPER(get_macu
)(uint64_t val
)
1417 if ((val
>> 32) == 0) {
1418 return (uint32_t)val
;
1424 uint32_t HELPER(get_mac_extf
)(CPUM68KState
*env
, uint32_t acc
)
1427 val
= env
->macc
[acc
] & 0x00ff;
1428 val
|= (env
->macc
[acc
] >> 32) & 0xff00;
1429 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
1430 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
1434 uint32_t HELPER(get_mac_exti
)(CPUM68KState
*env
, uint32_t acc
)
1437 val
= (env
->macc
[acc
] >> 32) & 0xffff;
1438 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
1442 void HELPER(set_mac_extf
)(CPUM68KState
*env
, uint32_t val
, uint32_t acc
)
1446 res
= env
->macc
[acc
] & 0xffffffff00ull
;
1447 tmp
= (int16_t)(val
& 0xff00);
1448 res
|= ((int64_t)tmp
) << 32;
1450 env
->macc
[acc
] = res
;
1451 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
1452 tmp
= (val
& 0xff000000);
1453 res
|= ((int64_t)tmp
) << 16;
1454 res
|= (val
>> 16) & 0xff;
1455 env
->macc
[acc
+ 1] = res
;
1458 void HELPER(set_mac_exts
)(CPUM68KState
*env
, uint32_t val
, uint32_t acc
)
1462 res
= (uint32_t)env
->macc
[acc
];
1464 res
|= ((int64_t)tmp
) << 32;
1465 env
->macc
[acc
] = res
;
1466 res
= (uint32_t)env
->macc
[acc
+ 1];
1467 tmp
= val
& 0xffff0000;
1468 res
|= (int64_t)tmp
<< 16;
1469 env
->macc
[acc
+ 1] = res
;
1472 void HELPER(set_mac_extu
)(CPUM68KState
*env
, uint32_t val
, uint32_t acc
)
1475 res
= (uint32_t)env
->macc
[acc
];
1476 res
|= ((uint64_t)(val
& 0xffff)) << 32;
1477 env
->macc
[acc
] = res
;
1478 res
= (uint32_t)env
->macc
[acc
+ 1];
1479 res
|= (uint64_t)(val
& 0xffff0000) << 16;
1480 env
->macc
[acc
+ 1] = res
;
1483 #if !defined(CONFIG_USER_ONLY)
1484 void HELPER(ptest
)(CPUM68KState
*env
, uint32_t addr
, uint32_t is_read
)
1490 target_ulong page_size
;
1492 access_type
= ACCESS_PTEST
;
1494 access_type
|= ACCESS_SUPER
;
1496 if ((env
->dfc
& 3) == 2) {
1497 access_type
|= ACCESS_CODE
;
1500 access_type
|= ACCESS_STORE
;
1505 ret
= get_physical_address(env
, &physical
, &prot
, addr
,
1506 access_type
, &page_size
);
1508 tlb_set_page(env_cpu(env
), addr
& TARGET_PAGE_MASK
,
1509 physical
& TARGET_PAGE_MASK
,
1510 prot
, access_type
& ACCESS_SUPER
?
1511 MMU_KERNEL_IDX
: MMU_USER_IDX
, page_size
);
1515 void HELPER(pflush
)(CPUM68KState
*env
, uint32_t addr
, uint32_t opmode
)
1517 CPUState
*cs
= env_cpu(env
);
1520 case 0: /* Flush page entry if not global */
1521 case 1: /* Flush page entry */
1522 tlb_flush_page(cs
, addr
);
1524 case 2: /* Flush all except global entries */
1527 case 3: /* Flush all entries */
1533 void HELPER(reset
)(CPUM68KState
*env
)
1535 /* FIXME: reset all except CPU */
1537 #endif /* !CONFIG_USER_ONLY */