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 "fpu/softfloat.h"
27 #include "qemu/qemu-print.h"
29 #define SIGNBIT (1u << 31)
31 /* Sort alphabetically, except for "any". */
32 static gint
m68k_cpu_list_compare(gconstpointer a
, gconstpointer b
)
34 ObjectClass
*class_a
= (ObjectClass
*)a
;
35 ObjectClass
*class_b
= (ObjectClass
*)b
;
36 const char *name_a
, *name_b
;
38 name_a
= object_class_get_name(class_a
);
39 name_b
= object_class_get_name(class_b
);
40 if (strcmp(name_a
, "any-" TYPE_M68K_CPU
) == 0) {
42 } else if (strcmp(name_b
, "any-" TYPE_M68K_CPU
) == 0) {
45 return strcasecmp(name_a
, name_b
);
49 static void m68k_cpu_list_entry(gpointer data
, gpointer user_data
)
51 ObjectClass
*c
= data
;
55 typename
= object_class_get_name(c
);
56 name
= g_strndup(typename
, strlen(typename
) - strlen("-" TYPE_M68K_CPU
));
57 qemu_printf("%s\n", name
);
61 void m68k_cpu_list(void)
65 list
= object_class_get_list(TYPE_M68K_CPU
, false);
66 list
= g_slist_sort(list
, m68k_cpu_list_compare
);
67 g_slist_foreach(list
, m68k_cpu_list_entry
, NULL
);
71 static int cf_fpu_gdb_get_reg(CPUM68KState
*env
, uint8_t *mem_buf
, int n
)
75 stfq_p(mem_buf
, floatx80_to_float64(env
->fregs
[n
].d
, &s
));
79 case 8: /* fpcontrol */
80 stl_be_p(mem_buf
, env
->fpcr
);
82 case 9: /* fpstatus */
83 stl_be_p(mem_buf
, env
->fpsr
);
85 case 10: /* fpiar, not implemented */
86 memset(mem_buf
, 0, 4);
92 static int cf_fpu_gdb_set_reg(CPUM68KState
*env
, uint8_t *mem_buf
, int n
)
96 env
->fregs
[n
].d
= float64_to_floatx80(ldfq_p(mem_buf
), &s
);
100 case 8: /* fpcontrol */
101 cpu_m68k_set_fpcr(env
, ldl_p(mem_buf
));
103 case 9: /* fpstatus */
104 env
->fpsr
= ldl_p(mem_buf
);
106 case 10: /* fpiar, not implemented */
112 static int m68k_fpu_gdb_get_reg(CPUM68KState
*env
, uint8_t *mem_buf
, int n
)
115 stw_be_p(mem_buf
, env
->fregs
[n
].l
.upper
);
116 memset(mem_buf
+ 2, 0, 2);
117 stq_be_p(mem_buf
+ 4, env
->fregs
[n
].l
.lower
);
121 case 8: /* fpcontrol */
122 stl_be_p(mem_buf
, env
->fpcr
);
124 case 9: /* fpstatus */
125 stl_be_p(mem_buf
, env
->fpsr
);
127 case 10: /* fpiar, not implemented */
128 memset(mem_buf
, 0, 4);
134 static int m68k_fpu_gdb_set_reg(CPUM68KState
*env
, uint8_t *mem_buf
, int n
)
137 env
->fregs
[n
].l
.upper
= lduw_be_p(mem_buf
);
138 env
->fregs
[n
].l
.lower
= ldq_be_p(mem_buf
+ 4);
142 case 8: /* fpcontrol */
143 cpu_m68k_set_fpcr(env
, ldl_p(mem_buf
));
145 case 9: /* fpstatus */
146 env
->fpsr
= ldl_p(mem_buf
);
148 case 10: /* fpiar, not implemented */
154 void m68k_cpu_init_gdb(M68kCPU
*cpu
)
156 CPUState
*cs
= CPU(cpu
);
157 CPUM68KState
*env
= &cpu
->env
;
159 if (m68k_feature(env
, M68K_FEATURE_CF_FPU
)) {
160 gdb_register_coprocessor(cs
, cf_fpu_gdb_get_reg
, cf_fpu_gdb_set_reg
,
161 11, "cf-fp.xml", 18);
162 } else if (m68k_feature(env
, M68K_FEATURE_FPU
)) {
163 gdb_register_coprocessor(cs
, m68k_fpu_gdb_get_reg
,
164 m68k_fpu_gdb_set_reg
, 11, "m68k-fp.xml", 18);
166 /* TODO: Add [E]MAC registers. */
169 void HELPER(cf_movec_to
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
180 /* TODO: Implement Access Control Registers. */
185 /* TODO: Implement control registers. */
187 cpu_abort(env_cpu(env
),
188 "Unimplemented control register write 0x%x = 0x%x\n",
193 void HELPER(m68k_movec_to
)(CPUM68KState
*env
, uint32_t reg
, uint32_t val
)
208 if (m68k_feature(env
, M68K_FEATURE_M68020
)) {
209 env
->cacr
= val
& 0x0000000f;
210 } else if (m68k_feature(env
, M68K_FEATURE_M68030
)) {
211 env
->cacr
= val
& 0x00003f1f;
212 } else if (m68k_feature(env
, M68K_FEATURE_M68040
)) {
213 env
->cacr
= val
& 0x80008000;
214 } else if (m68k_feature(env
, M68K_FEATURE_M68060
)) {
215 env
->cacr
= val
& 0xf8e0e000;
224 env
->mmu
.mmusr
= val
;
233 env
->sp
[M68K_USP
] = val
;
236 env
->sp
[M68K_SSP
] = val
;
239 env
->sp
[M68K_ISP
] = val
;
241 /* MC68040/MC68LC040 */
243 env
->mmu
.ttr
[M68K_ITTR0
] = val
;
246 env
->mmu
.ttr
[M68K_ITTR1
] = val
;
249 env
->mmu
.ttr
[M68K_DTTR0
] = val
;
252 env
->mmu
.ttr
[M68K_DTTR1
] = val
;
255 cpu_abort(env_cpu(env
),
256 "Unimplemented control register write 0x%x = 0x%x\n",
260 uint32_t HELPER(m68k_movec_from
)(CPUM68KState
*env
, uint32_t reg
)
277 return env
->mmu
.mmusr
;
281 return env
->sp
[M68K_USP
];
283 return env
->sp
[M68K_SSP
];
285 return env
->sp
[M68K_ISP
];
286 /* MC68040/MC68LC040 */
290 return env
->mmu
.ttr
[M68K_ITTR0
];
292 return env
->mmu
.ttr
[M68K_ITTR1
];
294 return env
->mmu
.ttr
[M68K_DTTR0
];
296 return env
->mmu
.ttr
[M68K_DTTR1
];
298 cpu_abort(env_cpu(env
), "Unimplemented control register read 0x%x\n",
302 void HELPER(set_macsr
)(CPUM68KState
*env
, uint32_t val
)
309 if ((env
->macsr
^ val
) & (MACSR_FI
| MACSR_SU
)) {
310 for (i
= 0; i
< 4; i
++) {
311 regval
= env
->macc
[i
];
312 exthigh
= regval
>> 40;
313 if (env
->macsr
& MACSR_FI
) {
318 extlow
= regval
>> 32;
320 if (env
->macsr
& MACSR_FI
) {
321 regval
= (((uint64_t)acc
) << 8) | extlow
;
322 regval
|= ((int64_t)exthigh
) << 40;
323 } else if (env
->macsr
& MACSR_SU
) {
324 regval
= acc
| (((int64_t)extlow
) << 32);
325 regval
|= ((int64_t)exthigh
) << 40;
327 regval
= acc
| (((uint64_t)extlow
) << 32);
328 regval
|= ((uint64_t)(uint8_t)exthigh
) << 40;
330 env
->macc
[i
] = regval
;
336 void m68k_switch_sp(CPUM68KState
*env
)
340 env
->sp
[env
->current_sp
] = env
->aregs
[7];
341 if (m68k_feature(env
, M68K_FEATURE_M68000
)) {
342 if (env
->sr
& SR_S
) {
343 if (env
->sr
& SR_M
) {
352 new_sp
= (env
->sr
& SR_S
&& env
->cacr
& M68K_CACR_EUSP
)
353 ? M68K_SSP
: M68K_USP
;
355 env
->aregs
[7] = env
->sp
[new_sp
];
356 env
->current_sp
= new_sp
;
359 #if !defined(CONFIG_USER_ONLY)
360 /* MMU: 68040 only */
362 static void print_address_zone(uint32_t logical
, uint32_t physical
,
363 uint32_t size
, int attr
)
365 qemu_printf("%08x - %08x -> %08x - %08x %c ",
366 logical
, logical
+ size
- 1,
367 physical
, physical
+ size
- 1,
368 attr
& 4 ? 'W' : '-');
371 qemu_printf("(%d KiB)\n", size
);
375 qemu_printf("(%d MiB)\n", size
);
378 qemu_printf("(%d GiB)\n", size
);
383 static void dump_address_map(CPUM68KState
*env
, uint32_t root_pointer
)
386 int tic_size
, tic_shift
;
388 uint32_t tia
, tib
, tic
;
389 uint32_t logical
= 0xffffffff, physical
= 0xffffffff;
390 uint32_t first_logical
= 0xffffffff, first_physical
= 0xffffffff;
391 uint32_t last_logical
, last_physical
;
393 int last_attr
= -1, attr
= -1;
394 CPUState
*cs
= env_cpu(env
);
397 if (env
->mmu
.tcr
& M68K_TCR_PAGE_8K
) {
401 tib_mask
= M68K_8K_PAGE_MASK
;
406 tib_mask
= M68K_4K_PAGE_MASK
;
408 for (i
= 0; i
< M68K_ROOT_POINTER_ENTRIES
; i
++) {
409 tia
= address_space_ldl(cs
->as
, M68K_POINTER_BASE(root_pointer
) + i
* 4,
410 MEMTXATTRS_UNSPECIFIED
, &txres
);
411 if (txres
!= MEMTX_OK
|| !M68K_UDT_VALID(tia
)) {
414 for (j
= 0; j
< M68K_ROOT_POINTER_ENTRIES
; j
++) {
415 tib
= address_space_ldl(cs
->as
, M68K_POINTER_BASE(tia
) + j
* 4,
416 MEMTXATTRS_UNSPECIFIED
, &txres
);
417 if (txres
!= MEMTX_OK
|| !M68K_UDT_VALID(tib
)) {
420 for (k
= 0; k
< tic_size
; k
++) {
421 tic
= address_space_ldl(cs
->as
, (tib
& tib_mask
) + k
* 4,
422 MEMTXATTRS_UNSPECIFIED
, &txres
);
423 if (txres
!= MEMTX_OK
|| !M68K_PDT_VALID(tic
)) {
426 if (M68K_PDT_INDIRECT(tic
)) {
427 tic
= address_space_ldl(cs
->as
, M68K_INDIRECT_POINTER(tic
),
428 MEMTXATTRS_UNSPECIFIED
, &txres
);
429 if (txres
!= MEMTX_OK
) {
434 last_logical
= logical
;
435 logical
= (i
<< M68K_TTS_ROOT_SHIFT
) |
436 (j
<< M68K_TTS_POINTER_SHIFT
) |
439 last_physical
= physical
;
440 physical
= tic
& ~((1 << tic_shift
) - 1);
443 attr
= tic
& ((1 << tic_shift
) - 1);
445 if ((logical
!= (last_logical
+ (1 << tic_shift
))) ||
446 (physical
!= (last_physical
+ (1 << tic_shift
))) ||
447 (attr
& 4) != (last_attr
& 4)) {
449 if (first_logical
!= 0xffffffff) {
450 size
= last_logical
+ (1 << tic_shift
) -
452 print_address_zone(first_logical
,
453 first_physical
, size
, last_attr
);
455 first_logical
= logical
;
456 first_physical
= physical
;
461 if (first_logical
!= logical
|| (attr
& 4) != (last_attr
& 4)) {
462 size
= logical
+ (1 << tic_shift
) - first_logical
;
463 print_address_zone(first_logical
, first_physical
, size
, last_attr
);
467 #define DUMP_CACHEFLAGS(a) \
468 switch (a & M68K_DESC_CACHEMODE) { \
469 case M68K_DESC_CM_WRTHRU: /* cachable, write-through */ \
472 case M68K_DESC_CM_COPYBK: /* cachable, copyback */ \
475 case M68K_DESC_CM_SERIAL: /* noncachable, serialized */ \
478 case M68K_DESC_CM_NCACHE: /* noncachable */ \
483 static void dump_ttr(uint32_t ttr
)
485 if ((ttr
& M68K_TTR_ENABLED
) == 0) {
486 qemu_printf("disabled\n");
489 qemu_printf("Base: 0x%08x Mask: 0x%08x Control: ",
490 ttr
& M68K_TTR_ADDR_BASE
,
491 (ttr
& M68K_TTR_ADDR_MASK
) << M68K_TTR_ADDR_MASK_SHIFT
);
492 switch (ttr
& M68K_TTR_SFIELD
) {
493 case M68K_TTR_SFIELD_USER
:
496 case M68K_TTR_SFIELD_SUPER
:
503 DUMP_CACHEFLAGS(ttr
);
504 if (ttr
& M68K_DESC_WRITEPROT
) {
509 qemu_printf(" U: %d\n", (ttr
& M68K_DESC_USERATTR
) >>
510 M68K_DESC_USERATTR_SHIFT
);
513 void dump_mmu(CPUM68KState
*env
)
515 if ((env
->mmu
.tcr
& M68K_TCR_ENABLED
) == 0) {
516 qemu_printf("Translation disabled\n");
519 qemu_printf("Page Size: ");
520 if (env
->mmu
.tcr
& M68K_TCR_PAGE_8K
) {
521 qemu_printf("8kB\n");
523 qemu_printf("4kB\n");
526 qemu_printf("MMUSR: ");
527 if (env
->mmu
.mmusr
& M68K_MMU_B_040
) {
528 qemu_printf("BUS ERROR\n");
530 qemu_printf("Phy=%08x Flags: ", env
->mmu
.mmusr
& 0xfffff000);
531 /* flags found on the page descriptor */
532 if (env
->mmu
.mmusr
& M68K_MMU_G_040
) {
533 qemu_printf("G"); /* Global */
537 if (env
->mmu
.mmusr
& M68K_MMU_S_040
) {
538 qemu_printf("S"); /* Supervisor */
542 if (env
->mmu
.mmusr
& M68K_MMU_M_040
) {
543 qemu_printf("M"); /* Modified */
547 if (env
->mmu
.mmusr
& M68K_MMU_WP_040
) {
548 qemu_printf("W"); /* Write protect */
552 if (env
->mmu
.mmusr
& M68K_MMU_T_040
) {
553 qemu_printf("T"); /* Transparent */
557 if (env
->mmu
.mmusr
& M68K_MMU_R_040
) {
558 qemu_printf("R"); /* Resident */
562 qemu_printf(" Cache: ");
563 DUMP_CACHEFLAGS(env
->mmu
.mmusr
);
564 qemu_printf(" U: %d\n", (env
->mmu
.mmusr
>> 8) & 3);
568 qemu_printf("ITTR0: ");
569 dump_ttr(env
->mmu
.ttr
[M68K_ITTR0
]);
570 qemu_printf("ITTR1: ");
571 dump_ttr(env
->mmu
.ttr
[M68K_ITTR1
]);
572 qemu_printf("DTTR0: ");
573 dump_ttr(env
->mmu
.ttr
[M68K_DTTR0
]);
574 qemu_printf("DTTR1: ");
575 dump_ttr(env
->mmu
.ttr
[M68K_DTTR1
]);
577 qemu_printf("SRP: 0x%08x\n", env
->mmu
.srp
);
578 dump_address_map(env
, env
->mmu
.srp
);
580 qemu_printf("URP: 0x%08x\n", env
->mmu
.urp
);
581 dump_address_map(env
, env
->mmu
.urp
);
584 static int check_TTR(uint32_t ttr
, int *prot
, target_ulong addr
,
589 /* check if transparent translation is enabled */
590 if ((ttr
& M68K_TTR_ENABLED
) == 0) {
594 /* check mode access */
595 switch (ttr
& M68K_TTR_SFIELD
) {
596 case M68K_TTR_SFIELD_USER
:
597 /* match only if user */
598 if ((access_type
& ACCESS_SUPER
) != 0) {
602 case M68K_TTR_SFIELD_SUPER
:
603 /* match only if supervisor */
604 if ((access_type
& ACCESS_SUPER
) == 0) {
609 /* all other values disable mode matching (FC2) */
613 /* check address matching */
615 base
= ttr
& M68K_TTR_ADDR_BASE
;
616 mask
= (ttr
& M68K_TTR_ADDR_MASK
) ^ M68K_TTR_ADDR_MASK
;
617 mask
<<= M68K_TTR_ADDR_MASK_SHIFT
;
619 if ((addr
& mask
) != (base
& mask
)) {
623 *prot
= PAGE_READ
| PAGE_EXEC
;
624 if ((ttr
& M68K_DESC_WRITEPROT
) == 0) {
631 static int get_physical_address(CPUM68KState
*env
, hwaddr
*physical
,
632 int *prot
, target_ulong address
,
633 int access_type
, target_ulong
*page_size
)
635 CPUState
*cs
= env_cpu(env
);
638 target_ulong page_mask
;
639 bool debug
= access_type
& ACCESS_DEBUG
;
644 /* Transparent Translation (physical = logical) */
645 for (i
= 0; i
< M68K_MAX_TTR
; i
++) {
646 if (check_TTR(env
->mmu
.TTR(access_type
, i
),
647 prot
, address
, access_type
)) {
648 if (access_type
& ACCESS_PTEST
) {
649 /* Transparent Translation Register bit */
650 env
->mmu
.mmusr
= M68K_MMU_T_040
| M68K_MMU_R_040
;
652 *physical
= address
& TARGET_PAGE_MASK
;
653 *page_size
= TARGET_PAGE_SIZE
;
658 /* Page Table Root Pointer */
659 *prot
= PAGE_READ
| PAGE_WRITE
;
660 if (access_type
& ACCESS_CODE
) {
663 if (access_type
& ACCESS_SUPER
) {
670 entry
= M68K_POINTER_BASE(next
) | M68K_ROOT_INDEX(address
);
672 next
= address_space_ldl(cs
->as
, entry
, MEMTXATTRS_UNSPECIFIED
, &txres
);
673 if (txres
!= MEMTX_OK
) {
676 if (!M68K_UDT_VALID(next
)) {
679 if (!(next
& M68K_DESC_USED
) && !debug
) {
680 address_space_stl(cs
->as
, entry
, next
| M68K_DESC_USED
,
681 MEMTXATTRS_UNSPECIFIED
, &txres
);
682 if (txres
!= MEMTX_OK
) {
686 if (next
& M68K_DESC_WRITEPROT
) {
687 if (access_type
& ACCESS_PTEST
) {
688 env
->mmu
.mmusr
|= M68K_MMU_WP_040
;
690 *prot
&= ~PAGE_WRITE
;
691 if (access_type
& ACCESS_STORE
) {
697 entry
= M68K_POINTER_BASE(next
) | M68K_POINTER_INDEX(address
);
699 next
= address_space_ldl(cs
->as
, entry
, MEMTXATTRS_UNSPECIFIED
, &txres
);
700 if (txres
!= MEMTX_OK
) {
703 if (!M68K_UDT_VALID(next
)) {
706 if (!(next
& M68K_DESC_USED
) && !debug
) {
707 address_space_stl(cs
->as
, entry
, next
| M68K_DESC_USED
,
708 MEMTXATTRS_UNSPECIFIED
, &txres
);
709 if (txres
!= MEMTX_OK
) {
713 if (next
& M68K_DESC_WRITEPROT
) {
714 if (access_type
& ACCESS_PTEST
) {
715 env
->mmu
.mmusr
|= M68K_MMU_WP_040
;
717 *prot
&= ~PAGE_WRITE
;
718 if (access_type
& ACCESS_STORE
) {
724 if (env
->mmu
.tcr
& M68K_TCR_PAGE_8K
) {
725 entry
= M68K_8K_PAGE_BASE(next
) | M68K_8K_PAGE_INDEX(address
);
727 entry
= M68K_4K_PAGE_BASE(next
) | M68K_4K_PAGE_INDEX(address
);
730 next
= address_space_ldl(cs
->as
, entry
, MEMTXATTRS_UNSPECIFIED
, &txres
);
731 if (txres
!= MEMTX_OK
) {
735 if (!M68K_PDT_VALID(next
)) {
738 if (M68K_PDT_INDIRECT(next
)) {
739 next
= address_space_ldl(cs
->as
, M68K_INDIRECT_POINTER(next
),
740 MEMTXATTRS_UNSPECIFIED
, &txres
);
741 if (txres
!= MEMTX_OK
) {
745 if (access_type
& ACCESS_STORE
) {
746 if (next
& M68K_DESC_WRITEPROT
) {
747 if (!(next
& M68K_DESC_USED
) && !debug
) {
748 address_space_stl(cs
->as
, entry
, next
| M68K_DESC_USED
,
749 MEMTXATTRS_UNSPECIFIED
, &txres
);
750 if (txres
!= MEMTX_OK
) {
754 } else if ((next
& (M68K_DESC_MODIFIED
| M68K_DESC_USED
)) !=
755 (M68K_DESC_MODIFIED
| M68K_DESC_USED
) && !debug
) {
756 address_space_stl(cs
->as
, entry
,
757 next
| (M68K_DESC_MODIFIED
| M68K_DESC_USED
),
758 MEMTXATTRS_UNSPECIFIED
, &txres
);
759 if (txres
!= MEMTX_OK
) {
764 if (!(next
& M68K_DESC_USED
) && !debug
) {
765 address_space_stl(cs
->as
, entry
, next
| M68K_DESC_USED
,
766 MEMTXATTRS_UNSPECIFIED
, &txres
);
767 if (txres
!= MEMTX_OK
) {
773 if (env
->mmu
.tcr
& M68K_TCR_PAGE_8K
) {
778 *page_size
= 1 << page_bits
;
779 page_mask
= ~(*page_size
- 1);
780 *physical
= next
& page_mask
;
782 if (access_type
& ACCESS_PTEST
) {
783 env
->mmu
.mmusr
|= next
& M68K_MMU_SR_MASK_040
;
784 env
->mmu
.mmusr
|= *physical
& 0xfffff000;
785 env
->mmu
.mmusr
|= M68K_MMU_R_040
;
788 if (next
& M68K_DESC_WRITEPROT
) {
789 *prot
&= ~PAGE_WRITE
;
790 if (access_type
& ACCESS_STORE
) {
794 if (next
& M68K_DESC_SUPERONLY
) {
795 if ((access_type
& ACCESS_SUPER
) == 0) {
804 * A page table load/store failed. TODO: we should really raise a
805 * suitable guest fault here if this is not a debug access.
806 * For now just return that the translation failed.
811 hwaddr
m68k_cpu_get_phys_page_debug(CPUState
*cs
, vaddr addr
)
813 M68kCPU
*cpu
= M68K_CPU(cs
);
814 CPUM68KState
*env
= &cpu
->env
;
818 target_ulong page_size
;
820 if ((env
->mmu
.tcr
& M68K_TCR_ENABLED
) == 0) {
825 access_type
= ACCESS_DATA
| ACCESS_DEBUG
;
826 if (env
->sr
& SR_S
) {
827 access_type
|= ACCESS_SUPER
;
829 if (get_physical_address(env
, &phys_addr
, &prot
,
830 addr
, access_type
, &page_size
) != 0) {
837 * Notify CPU of a pending interrupt. Prioritization and vectoring should
838 * be handled by the interrupt controller. Real hardware only requests
839 * the vector when the interrupt is acknowledged by the CPU. For
840 * simplicity we calculate it when the interrupt is signalled.
842 void m68k_set_irq_level(M68kCPU
*cpu
, int level
, uint8_t vector
)
844 CPUState
*cs
= CPU(cpu
);
845 CPUM68KState
*env
= &cpu
->env
;
847 env
->pending_level
= level
;
848 env
->pending_vector
= vector
;
850 cpu_interrupt(cs
, CPU_INTERRUPT_HARD
);
852 cpu_reset_interrupt(cs
, CPU_INTERRUPT_HARD
);
858 bool m68k_cpu_tlb_fill(CPUState
*cs
, vaddr address
, int size
,
859 MMUAccessType qemu_access_type
, int mmu_idx
,
860 bool probe
, uintptr_t retaddr
)
862 M68kCPU
*cpu
= M68K_CPU(cs
);
863 CPUM68KState
*env
= &cpu
->env
;
865 #ifndef CONFIG_USER_ONLY
870 target_ulong page_size
;
872 if ((env
->mmu
.tcr
& M68K_TCR_ENABLED
) == 0) {
874 tlb_set_page(cs
, address
& TARGET_PAGE_MASK
,
875 address
& TARGET_PAGE_MASK
,
876 PAGE_READ
| PAGE_WRITE
| PAGE_EXEC
,
877 mmu_idx
, TARGET_PAGE_SIZE
);
881 if (qemu_access_type
== MMU_INST_FETCH
) {
882 access_type
= ACCESS_CODE
;
884 access_type
= ACCESS_DATA
;
885 if (qemu_access_type
== MMU_DATA_STORE
) {
886 access_type
|= ACCESS_STORE
;
889 if (mmu_idx
!= MMU_USER_IDX
) {
890 access_type
|= ACCESS_SUPER
;
893 ret
= get_physical_address(&cpu
->env
, &physical
, &prot
,
894 address
, access_type
, &page_size
);
895 if (likely(ret
== 0)) {
896 address
&= TARGET_PAGE_MASK
;
897 physical
+= address
& (page_size
- 1);
898 tlb_set_page(cs
, address
, physical
,
899 prot
, mmu_idx
, TARGET_PAGE_SIZE
);
908 env
->mmu
.ssw
= M68K_ATC_040
;
911 env
->mmu
.ssw
|= M68K_BA_SIZE_BYTE
;
914 env
->mmu
.ssw
|= M68K_BA_SIZE_WORD
;
917 env
->mmu
.ssw
|= M68K_BA_SIZE_LONG
;
920 if (access_type
& ACCESS_SUPER
) {
921 env
->mmu
.ssw
|= M68K_TM_040_SUPER
;
923 if (access_type
& ACCESS_CODE
) {
924 env
->mmu
.ssw
|= M68K_TM_040_CODE
;
926 env
->mmu
.ssw
|= M68K_TM_040_DATA
;
928 if (!(access_type
& ACCESS_STORE
)) {
929 env
->mmu
.ssw
|= M68K_RW_040
;
933 cs
->exception_index
= EXCP_ACCESS
;
934 env
->mmu
.ar
= address
;
935 cpu_loop_exit_restore(cs
, retaddr
);
938 uint32_t HELPER(bitrev
)(uint32_t x
)
940 x
= ((x
>> 1) & 0x55555555u
) | ((x
<< 1) & 0xaaaaaaaau
);
941 x
= ((x
>> 2) & 0x33333333u
) | ((x
<< 2) & 0xccccccccu
);
942 x
= ((x
>> 4) & 0x0f0f0f0fu
) | ((x
<< 4) & 0xf0f0f0f0u
);
946 uint32_t HELPER(ff1
)(uint32_t x
)
954 uint32_t HELPER(sats
)(uint32_t val
, uint32_t v
)
956 /* The result has the opposite sign to the original value. */
957 if ((int32_t)v
< 0) {
958 val
= (((int32_t)val
) >> 31) ^ SIGNBIT
;
963 void cpu_m68k_set_sr(CPUM68KState
*env
, uint32_t sr
)
965 env
->sr
= sr
& 0xffe0;
966 cpu_m68k_set_ccr(env
, sr
);
970 void HELPER(set_sr
)(CPUM68KState
*env
, uint32_t val
)
972 cpu_m68k_set_sr(env
, val
);
977 * FIXME: The MAC unit implementation is a bit of a mess. Some helpers
978 * take values, others take register numbers and manipulate the contents
981 void HELPER(mac_move
)(CPUM68KState
*env
, uint32_t dest
, uint32_t src
)
984 env
->macc
[dest
] = env
->macc
[src
];
985 mask
= MACSR_PAV0
<< dest
;
986 if (env
->macsr
& (MACSR_PAV0
<< src
))
992 uint64_t HELPER(macmuls
)(CPUM68KState
*env
, uint32_t op1
, uint32_t op2
)
997 product
= (uint64_t)op1
* op2
;
998 res
= (product
<< 24) >> 24;
999 if (res
!= product
) {
1000 env
->macsr
|= MACSR_V
;
1001 if (env
->macsr
& MACSR_OMC
) {
1002 /* Make sure the accumulate operation overflows. */
1012 uint64_t HELPER(macmulu
)(CPUM68KState
*env
, uint32_t op1
, uint32_t op2
)
1016 product
= (uint64_t)op1
* op2
;
1017 if (product
& (0xffffffull
<< 40)) {
1018 env
->macsr
|= MACSR_V
;
1019 if (env
->macsr
& MACSR_OMC
) {
1020 /* Make sure the accumulate operation overflows. */
1021 product
= 1ll << 50;
1023 product
&= ((1ull << 40) - 1);
1029 uint64_t HELPER(macmulf
)(CPUM68KState
*env
, uint32_t op1
, uint32_t op2
)
1034 product
= (uint64_t)op1
* op2
;
1035 if (env
->macsr
& MACSR_RT
) {
1036 remainder
= product
& 0xffffff;
1038 if (remainder
> 0x800000)
1040 else if (remainder
== 0x800000)
1041 product
+= (product
& 1);
1048 void HELPER(macsats
)(CPUM68KState
*env
, uint32_t acc
)
1052 tmp
= env
->macc
[acc
];
1053 result
= ((tmp
<< 16) >> 16);
1054 if (result
!= tmp
) {
1055 env
->macsr
|= MACSR_V
;
1057 if (env
->macsr
& MACSR_V
) {
1058 env
->macsr
|= MACSR_PAV0
<< acc
;
1059 if (env
->macsr
& MACSR_OMC
) {
1061 * The result is saturated to 32 bits, despite overflow occurring
1062 * at 48 bits. Seems weird, but that's what the hardware docs
1065 result
= (result
>> 63) ^ 0x7fffffff;
1068 env
->macc
[acc
] = result
;
1071 void HELPER(macsatu
)(CPUM68KState
*env
, uint32_t acc
)
1075 val
= env
->macc
[acc
];
1076 if (val
& (0xffffull
<< 48)) {
1077 env
->macsr
|= MACSR_V
;
1079 if (env
->macsr
& MACSR_V
) {
1080 env
->macsr
|= MACSR_PAV0
<< acc
;
1081 if (env
->macsr
& MACSR_OMC
) {
1082 if (val
> (1ull << 53))
1085 val
= (1ull << 48) - 1;
1087 val
&= ((1ull << 48) - 1);
1090 env
->macc
[acc
] = val
;
1093 void HELPER(macsatf
)(CPUM68KState
*env
, uint32_t acc
)
1098 sum
= env
->macc
[acc
];
1099 result
= (sum
<< 16) >> 16;
1100 if (result
!= sum
) {
1101 env
->macsr
|= MACSR_V
;
1103 if (env
->macsr
& MACSR_V
) {
1104 env
->macsr
|= MACSR_PAV0
<< acc
;
1105 if (env
->macsr
& MACSR_OMC
) {
1106 result
= (result
>> 63) ^ 0x7fffffffffffll
;
1109 env
->macc
[acc
] = result
;
1112 void HELPER(mac_set_flags
)(CPUM68KState
*env
, uint32_t acc
)
1115 val
= env
->macc
[acc
];
1117 env
->macsr
|= MACSR_Z
;
1118 } else if (val
& (1ull << 47)) {
1119 env
->macsr
|= MACSR_N
;
1121 if (env
->macsr
& (MACSR_PAV0
<< acc
)) {
1122 env
->macsr
|= MACSR_V
;
1124 if (env
->macsr
& MACSR_FI
) {
1125 val
= ((int64_t)val
) >> 40;
1126 if (val
!= 0 && val
!= -1)
1127 env
->macsr
|= MACSR_EV
;
1128 } else if (env
->macsr
& MACSR_SU
) {
1129 val
= ((int64_t)val
) >> 32;
1130 if (val
!= 0 && val
!= -1)
1131 env
->macsr
|= MACSR_EV
;
1133 if ((val
>> 32) != 0)
1134 env
->macsr
|= MACSR_EV
;
1138 #define EXTSIGN(val, index) ( \
1139 (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
1142 #define COMPUTE_CCR(op, x, n, z, v, c) { \
1145 /* Everything in place. */ \
1152 src1 = EXTSIGN(res - src2, op - CC_OP_ADDB); \
1155 v = (res ^ src1) & ~(src1 ^ src2); \
1162 src1 = EXTSIGN(res + src2, op - CC_OP_SUBB); \
1165 v = (res ^ src1) & (src1 ^ src2); \
1172 res = EXTSIGN(src1 - src2, op - CC_OP_CMPB); \
1176 v = (res ^ src1) & (src1 ^ src2); \
1183 cpu_abort(env_cpu(env), "Bad CC_OP %d", op); \
1187 uint32_t cpu_m68k_get_ccr(CPUM68KState
*env
)
1189 uint32_t x
, c
, n
, z
, v
;
1190 uint32_t res
, src1
, src2
;
1198 COMPUTE_CCR(env
->cc_op
, x
, n
, z
, v
, c
);
1204 return x
* CCF_X
+ n
* CCF_N
+ z
* CCF_Z
+ v
* CCF_V
+ c
* CCF_C
;
1207 uint32_t HELPER(get_ccr
)(CPUM68KState
*env
)
1209 return cpu_m68k_get_ccr(env
);
1212 void cpu_m68k_set_ccr(CPUM68KState
*env
, uint32_t ccr
)
1214 env
->cc_x
= (ccr
& CCF_X
? 1 : 0);
1215 env
->cc_n
= (ccr
& CCF_N
? -1 : 0);
1216 env
->cc_z
= (ccr
& CCF_Z
? 0 : 1);
1217 env
->cc_v
= (ccr
& CCF_V
? -1 : 0);
1218 env
->cc_c
= (ccr
& CCF_C
? 1 : 0);
1219 env
->cc_op
= CC_OP_FLAGS
;
1222 void HELPER(set_ccr
)(CPUM68KState
*env
, uint32_t ccr
)
1224 cpu_m68k_set_ccr(env
, ccr
);
1227 void HELPER(flush_flags
)(CPUM68KState
*env
, uint32_t cc_op
)
1229 uint32_t res
, src1
, src2
;
1231 COMPUTE_CCR(cc_op
, env
->cc_x
, env
->cc_n
, env
->cc_z
, env
->cc_v
, env
->cc_c
);
1232 env
->cc_op
= CC_OP_FLAGS
;
1235 uint32_t HELPER(get_macf
)(CPUM68KState
*env
, uint64_t val
)
1240 if (env
->macsr
& MACSR_SU
) {
1241 /* 16-bit rounding. */
1242 rem
= val
& 0xffffff;
1243 val
= (val
>> 24) & 0xffffu
;
1246 else if (rem
== 0x800000)
1248 } else if (env
->macsr
& MACSR_RT
) {
1249 /* 32-bit rounding. */
1254 else if (rem
== 0x80)
1260 if (env
->macsr
& MACSR_OMC
) {
1262 if (env
->macsr
& MACSR_SU
) {
1263 if (val
!= (uint16_t) val
) {
1264 result
= ((val
>> 63) ^ 0x7fff) & 0xffff;
1266 result
= val
& 0xffff;
1269 if (val
!= (uint32_t)val
) {
1270 result
= ((uint32_t)(val
>> 63) & 0x7fffffff);
1272 result
= (uint32_t)val
;
1276 /* No saturation. */
1277 if (env
->macsr
& MACSR_SU
) {
1278 result
= val
& 0xffff;
1280 result
= (uint32_t)val
;
1286 uint32_t HELPER(get_macs
)(uint64_t val
)
1288 if (val
== (int32_t)val
) {
1289 return (int32_t)val
;
1291 return (val
>> 61) ^ ~SIGNBIT
;
1295 uint32_t HELPER(get_macu
)(uint64_t val
)
1297 if ((val
>> 32) == 0) {
1298 return (uint32_t)val
;
1304 uint32_t HELPER(get_mac_extf
)(CPUM68KState
*env
, uint32_t acc
)
1307 val
= env
->macc
[acc
] & 0x00ff;
1308 val
|= (env
->macc
[acc
] >> 32) & 0xff00;
1309 val
|= (env
->macc
[acc
+ 1] << 16) & 0x00ff0000;
1310 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xff000000;
1314 uint32_t HELPER(get_mac_exti
)(CPUM68KState
*env
, uint32_t acc
)
1317 val
= (env
->macc
[acc
] >> 32) & 0xffff;
1318 val
|= (env
->macc
[acc
+ 1] >> 16) & 0xffff0000;
1322 void HELPER(set_mac_extf
)(CPUM68KState
*env
, uint32_t val
, uint32_t acc
)
1326 res
= env
->macc
[acc
] & 0xffffffff00ull
;
1327 tmp
= (int16_t)(val
& 0xff00);
1328 res
|= ((int64_t)tmp
) << 32;
1330 env
->macc
[acc
] = res
;
1331 res
= env
->macc
[acc
+ 1] & 0xffffffff00ull
;
1332 tmp
= (val
& 0xff000000);
1333 res
|= ((int64_t)tmp
) << 16;
1334 res
|= (val
>> 16) & 0xff;
1335 env
->macc
[acc
+ 1] = res
;
1338 void HELPER(set_mac_exts
)(CPUM68KState
*env
, uint32_t val
, uint32_t acc
)
1342 res
= (uint32_t)env
->macc
[acc
];
1344 res
|= ((int64_t)tmp
) << 32;
1345 env
->macc
[acc
] = res
;
1346 res
= (uint32_t)env
->macc
[acc
+ 1];
1347 tmp
= val
& 0xffff0000;
1348 res
|= (int64_t)tmp
<< 16;
1349 env
->macc
[acc
+ 1] = res
;
1352 void HELPER(set_mac_extu
)(CPUM68KState
*env
, uint32_t val
, uint32_t acc
)
1355 res
= (uint32_t)env
->macc
[acc
];
1356 res
|= ((uint64_t)(val
& 0xffff)) << 32;
1357 env
->macc
[acc
] = res
;
1358 res
= (uint32_t)env
->macc
[acc
+ 1];
1359 res
|= (uint64_t)(val
& 0xffff0000) << 16;
1360 env
->macc
[acc
+ 1] = res
;
1363 #if defined(CONFIG_SOFTMMU)
1364 void HELPER(ptest
)(CPUM68KState
*env
, uint32_t addr
, uint32_t is_read
)
1370 target_ulong page_size
;
1372 access_type
= ACCESS_PTEST
;
1374 access_type
|= ACCESS_SUPER
;
1376 if ((env
->dfc
& 3) == 2) {
1377 access_type
|= ACCESS_CODE
;
1380 access_type
|= ACCESS_STORE
;
1385 ret
= get_physical_address(env
, &physical
, &prot
, addr
,
1386 access_type
, &page_size
);
1388 addr
&= TARGET_PAGE_MASK
;
1389 physical
+= addr
& (page_size
- 1);
1390 tlb_set_page(env_cpu(env
), addr
, physical
,
1391 prot
, access_type
& ACCESS_SUPER
?
1392 MMU_KERNEL_IDX
: MMU_USER_IDX
, page_size
);
1396 void HELPER(pflush
)(CPUM68KState
*env
, uint32_t addr
, uint32_t opmode
)
1398 CPUState
*cs
= env_cpu(env
);
1401 case 0: /* Flush page entry if not global */
1402 case 1: /* Flush page entry */
1403 tlb_flush_page(cs
, addr
);
1405 case 2: /* Flush all except global entries */
1408 case 3: /* Flush all entries */
1414 void HELPER(reset
)(CPUM68KState
*env
)
1416 /* FIXME: reset all except CPU */