]> git.proxmox.com Git - mirror_qemu.git/blame - target/m68k/helper.c
hmp: obsolete "info ioapic"
[mirror_qemu.git] / target / m68k / helper.c
CommitLineData
e6e5906b
PB
1/*
2 * m68k op helpers
5fafdf24 3 *
0633879f 4 * Copyright (c) 2006-2007 CodeSourcery
e6e5906b
PB
5 * Written by Paul Brook
6 *
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.
11 *
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.
16 *
17 * You should have received a copy of the GNU Lesser General Public
8167ee88 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
e6e5906b
PB
19 */
20
d8416665 21#include "qemu/osdep.h"
e6e5906b 22#include "cpu.h"
63c91552 23#include "exec/exec-all.h"
022c62cb 24#include "exec/gdbstub.h"
e6e5906b 25
2ef6175a 26#include "exec/helper-proto.h"
24f91e81 27#include "fpu/softfloat.h"
e1f3808e
PB
28
29#define SIGNBIT (1u << 31)
30
11150915
AF
31/* Sort alphabetically, except for "any". */
32static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
009a4356 33{
11150915
AF
34 ObjectClass *class_a = (ObjectClass *)a;
35 ObjectClass *class_b = (ObjectClass *)b;
36 const char *name_a, *name_b;
37
38 name_a = object_class_get_name(class_a);
39 name_b = object_class_get_name(class_b);
7a9f812b 40 if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
11150915 41 return 1;
7a9f812b 42 } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
11150915
AF
43 return -1;
44 } else {
45 return strcasecmp(name_a, name_b);
009a4356
LV
46 }
47}
48
11150915
AF
49static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
50{
51 ObjectClass *c = data;
92a31361 52 CPUListState *s = user_data;
7a9f812b
AF
53 const char *typename;
54 char *name;
11150915 55
7a9f812b
AF
56 typename = object_class_get_name(c);
57 name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
11150915 58 (*s->cpu_fprintf)(s->file, "%s\n",
7a9f812b
AF
59 name);
60 g_free(name);
11150915
AF
61}
62
63void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
64{
92a31361 65 CPUListState s = {
11150915
AF
66 .file = f,
67 .cpu_fprintf = cpu_fprintf,
68 };
69 GSList *list;
70
71 list = object_class_get_list(TYPE_M68K_CPU, false);
72 list = g_slist_sort(list, m68k_cpu_list_compare);
73 g_slist_foreach(list, m68k_cpu_list_entry, &s);
74 g_slist_free(list);
75}
76
f83311e4 77static int cf_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
56aebc89
PB
78{
79 if (n < 8) {
f83311e4
LV
80 float_status s;
81 stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
56aebc89
PB
82 return 8;
83 }
ba624944
LV
84 switch (n) {
85 case 8: /* fpcontrol */
86 stl_be_p(mem_buf, env->fpcr);
87 return 4;
88 case 9: /* fpstatus */
89 stl_be_p(mem_buf, env->fpsr);
90 return 4;
91 case 10: /* fpiar, not implemented */
56aebc89
PB
92 memset(mem_buf, 0, 4);
93 return 4;
94 }
95 return 0;
96}
97
f83311e4 98static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
56aebc89
PB
99{
100 if (n < 8) {
f83311e4
LV
101 float_status s;
102 env->fregs[n].d = float64_to_floatx80(ldfq_p(mem_buf), &s);
56aebc89
PB
103 return 8;
104 }
ba624944
LV
105 switch (n) {
106 case 8: /* fpcontrol */
107 cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
108 return 4;
109 case 9: /* fpstatus */
110 env->fpsr = ldl_p(mem_buf);
111 return 4;
112 case 10: /* fpiar, not implemented */
56aebc89
PB
113 return 4;
114 }
115 return 0;
116}
117
5a4526b2
LV
118static int m68k_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
119{
120 if (n < 8) {
121 stw_be_p(mem_buf, env->fregs[n].l.upper);
122 memset(mem_buf + 2, 0, 2);
123 stq_be_p(mem_buf + 4, env->fregs[n].l.lower);
124 return 12;
125 }
126 switch (n) {
127 case 8: /* fpcontrol */
128 stl_be_p(mem_buf, env->fpcr);
129 return 4;
130 case 9: /* fpstatus */
131 stl_be_p(mem_buf, env->fpsr);
132 return 4;
133 case 10: /* fpiar, not implemented */
134 memset(mem_buf, 0, 4);
135 return 4;
136 }
137 return 0;
138}
139
140static int m68k_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
141{
142 if (n < 8) {
143 env->fregs[n].l.upper = lduw_be_p(mem_buf);
144 env->fregs[n].l.lower = ldq_be_p(mem_buf + 4);
145 return 12;
146 }
147 switch (n) {
148 case 8: /* fpcontrol */
ba624944 149 cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
5a4526b2
LV
150 return 4;
151 case 9: /* fpstatus */
152 env->fpsr = ldl_p(mem_buf);
153 return 4;
154 case 10: /* fpiar, not implemented */
155 return 4;
156 }
157 return 0;
158}
159
6d1bbc62
AF
160void m68k_cpu_init_gdb(M68kCPU *cpu)
161{
22169d41 162 CPUState *cs = CPU(cpu);
6d1bbc62
AF
163 CPUM68KState *env = &cpu->env;
164
11150915 165 if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
f83311e4 166 gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg,
11150915 167 11, "cf-fp.xml", 18);
5a4526b2
LV
168 } else if (m68k_feature(env, M68K_FEATURE_FPU)) {
169 gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg,
170 m68k_fpu_gdb_set_reg, 11, "m68k-fp.xml", 18);
aaed909a 171 }
11150915 172 /* TODO: Add [E]MAC registers. */
aaed909a 173}
0402f767 174
6e22b28e 175void HELPER(cf_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
0633879f 176{
a47dddd7
AF
177 M68kCPU *cpu = m68k_env_get_cpu(env);
178
0633879f 179 switch (reg) {
6e22b28e 180 case M68K_CR_CACR:
20dcee94
PB
181 env->cacr = val;
182 m68k_switch_sp(env);
183 break;
6e22b28e
LV
184 case M68K_CR_ACR0:
185 case M68K_CR_ACR1:
186 case M68K_CR_ACR2:
187 case M68K_CR_ACR3:
20dcee94 188 /* TODO: Implement Access Control Registers. */
0633879f 189 break;
6e22b28e 190 case M68K_CR_VBR:
0633879f
PB
191 env->vbr = val;
192 break;
193 /* TODO: Implement control registers. */
194 default:
6e22b28e
LV
195 cpu_abort(CPU(cpu),
196 "Unimplemented control register write 0x%x = 0x%x\n",
0633879f
PB
197 reg, val);
198 }
199}
200
6e22b28e
LV
201void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
202{
203 M68kCPU *cpu = m68k_env_get_cpu(env);
204
205 switch (reg) {
206 /* MC680[1234]0 */
5fa9f1f2
LV
207 case M68K_CR_SFC:
208 env->sfc = val & 7;
209 return;
210 case M68K_CR_DFC:
211 env->dfc = val & 7;
212 return;
6e22b28e
LV
213 case M68K_CR_VBR:
214 env->vbr = val;
215 return;
216 /* MC680[234]0 */
217 case M68K_CR_CACR:
218 env->cacr = val;
219 m68k_switch_sp(env);
220 return;
221 /* MC680[34]0 */
88b2fef6
LV
222 case M68K_CR_TC:
223 env->mmu.tcr = val;
224 return;
e55886c3
LV
225 case M68K_CR_MMUSR:
226 env->mmu.mmusr = val;
227 return;
88b2fef6
LV
228 case M68K_CR_SRP:
229 env->mmu.srp = val;
230 return;
231 case M68K_CR_URP:
232 env->mmu.urp = val;
233 return;
6e22b28e
LV
234 case M68K_CR_USP:
235 env->sp[M68K_USP] = val;
236 return;
237 case M68K_CR_MSP:
238 env->sp[M68K_SSP] = val;
239 return;
240 case M68K_CR_ISP:
241 env->sp[M68K_ISP] = val;
242 return;
c05c73b0
LV
243 /* MC68040/MC68LC040 */
244 case M68K_CR_ITT0:
245 env->mmu.ttr[M68K_ITTR0] = val;
246 return;
247 case M68K_CR_ITT1:
248 env->mmu.ttr[M68K_ITTR1] = val;
249 return;
250 case M68K_CR_DTT0:
251 env->mmu.ttr[M68K_DTTR0] = val;
252 return;
253 case M68K_CR_DTT1:
254 env->mmu.ttr[M68K_DTTR1] = val;
255 return;
6e22b28e
LV
256 }
257 cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
258 reg, val);
259}
260
261uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg)
262{
263 M68kCPU *cpu = m68k_env_get_cpu(env);
264
265 switch (reg) {
266 /* MC680[1234]0 */
5fa9f1f2
LV
267 case M68K_CR_SFC:
268 return env->sfc;
269 case M68K_CR_DFC:
270 return env->dfc;
6e22b28e
LV
271 case M68K_CR_VBR:
272 return env->vbr;
273 /* MC680[234]0 */
274 case M68K_CR_CACR:
275 return env->cacr;
276 /* MC680[34]0 */
88b2fef6
LV
277 case M68K_CR_TC:
278 return env->mmu.tcr;
e55886c3
LV
279 case M68K_CR_MMUSR:
280 return env->mmu.mmusr;
88b2fef6
LV
281 case M68K_CR_SRP:
282 return env->mmu.srp;
6e22b28e
LV
283 case M68K_CR_USP:
284 return env->sp[M68K_USP];
285 case M68K_CR_MSP:
286 return env->sp[M68K_SSP];
287 case M68K_CR_ISP:
288 return env->sp[M68K_ISP];
88b2fef6
LV
289 /* MC68040/MC68LC040 */
290 case M68K_CR_URP:
291 return env->mmu.urp;
c05c73b0
LV
292 case M68K_CR_ITT0:
293 return env->mmu.ttr[M68K_ITTR0];
294 case M68K_CR_ITT1:
295 return env->mmu.ttr[M68K_ITTR1];
296 case M68K_CR_DTT0:
297 return env->mmu.ttr[M68K_DTTR0];
298 case M68K_CR_DTT1:
299 return env->mmu.ttr[M68K_DTTR1];
6e22b28e
LV
300 }
301 cpu_abort(CPU(cpu), "Unimplemented control register read 0x%x\n",
302 reg);
303}
304
e1f3808e 305void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
acf930aa
PB
306{
307 uint32_t acc;
308 int8_t exthigh;
309 uint8_t extlow;
310 uint64_t regval;
311 int i;
312 if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
313 for (i = 0; i < 4; i++) {
314 regval = env->macc[i];
315 exthigh = regval >> 40;
316 if (env->macsr & MACSR_FI) {
317 acc = regval >> 8;
318 extlow = regval;
319 } else {
320 acc = regval;
321 extlow = regval >> 32;
322 }
323 if (env->macsr & MACSR_FI) {
324 regval = (((uint64_t)acc) << 8) | extlow;
325 regval |= ((int64_t)exthigh) << 40;
326 } else if (env->macsr & MACSR_SU) {
327 regval = acc | (((int64_t)extlow) << 32);
328 regval |= ((int64_t)exthigh) << 40;
329 } else {
330 regval = acc | (((uint64_t)extlow) << 32);
331 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
332 }
333 env->macc[i] = regval;
334 }
335 }
336 env->macsr = val;
337}
338
20dcee94
PB
339void m68k_switch_sp(CPUM68KState *env)
340{
341 int new_sp;
342
343 env->sp[env->current_sp] = env->aregs[7];
6e22b28e
LV
344 if (m68k_feature(env, M68K_FEATURE_M68000)) {
345 if (env->sr & SR_S) {
346 if (env->sr & SR_M) {
347 new_sp = M68K_SSP;
348 } else {
349 new_sp = M68K_ISP;
350 }
351 } else {
352 new_sp = M68K_USP;
353 }
354 } else {
355 new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
356 ? M68K_SSP : M68K_USP;
357 }
20dcee94
PB
358 env->aregs[7] = env->sp[new_sp];
359 env->current_sp = new_sp;
360}
361
5fafdf24 362#if defined(CONFIG_USER_ONLY)
0633879f 363
98670d47 364int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
7510454e 365 int mmu_idx)
0633879f 366{
7510454e
AF
367 M68kCPU *cpu = M68K_CPU(cs);
368
27103424 369 cs->exception_index = EXCP_ACCESS;
7510454e 370 cpu->env.mmu.ar = address;
0633879f
PB
371 return 1;
372}
373
374#else
375
88b2fef6
LV
376/* MMU: 68040 only */
377
2097dca6
LV
378static void print_address_zone(FILE *f, fprintf_function cpu_fprintf,
379 uint32_t logical, uint32_t physical,
380 uint32_t size, int attr)
381{
382 cpu_fprintf(f, "%08x - %08x -> %08x - %08x %c ",
383 logical, logical + size - 1,
384 physical, physical + size - 1,
385 attr & 4 ? 'W' : '-');
386 size >>= 10;
387 if (size < 1024) {
388 cpu_fprintf(f, "(%d KiB)\n", size);
389 } else {
390 size >>= 10;
391 if (size < 1024) {
392 cpu_fprintf(f, "(%d MiB)\n", size);
393 } else {
394 size >>= 10;
395 cpu_fprintf(f, "(%d GiB)\n", size);
396 }
397 }
398}
399
400static void dump_address_map(FILE *f, fprintf_function cpu_fprintf,
401 CPUM68KState *env, uint32_t root_pointer)
402{
403 int i, j, k;
404 int tic_size, tic_shift;
405 uint32_t tib_mask;
406 uint32_t tia, tib, tic;
407 uint32_t logical = 0xffffffff, physical = 0xffffffff;
408 uint32_t first_logical = 0xffffffff, first_physical = 0xffffffff;
409 uint32_t last_logical, last_physical;
410 int32_t size;
411 int last_attr = -1, attr = -1;
412 M68kCPU *cpu = m68k_env_get_cpu(env);
413 CPUState *cs = CPU(cpu);
414
415 if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
416 /* 8k page */
417 tic_size = 32;
418 tic_shift = 13;
419 tib_mask = M68K_8K_PAGE_MASK;
420 } else {
421 /* 4k page */
422 tic_size = 64;
423 tic_shift = 12;
424 tib_mask = M68K_4K_PAGE_MASK;
425 }
426 for (i = 0; i < M68K_ROOT_POINTER_ENTRIES; i++) {
427 tia = ldl_phys(cs->as, M68K_POINTER_BASE(root_pointer) + i * 4);
428 if (!M68K_UDT_VALID(tia)) {
429 continue;
430 }
431 for (j = 0; j < M68K_ROOT_POINTER_ENTRIES; j++) {
432 tib = ldl_phys(cs->as, M68K_POINTER_BASE(tia) + j * 4);
433 if (!M68K_UDT_VALID(tib)) {
434 continue;
435 }
436 for (k = 0; k < tic_size; k++) {
437 tic = ldl_phys(cs->as, (tib & tib_mask) + k * 4);
438 if (!M68K_PDT_VALID(tic)) {
439 continue;
440 }
441 if (M68K_PDT_INDIRECT(tic)) {
442 tic = ldl_phys(cs->as, M68K_INDIRECT_POINTER(tic));
443 }
444
445 last_logical = logical;
446 logical = (i << M68K_TTS_ROOT_SHIFT) |
447 (j << M68K_TTS_POINTER_SHIFT) |
448 (k << tic_shift);
449
450 last_physical = physical;
451 physical = tic & ~((1 << tic_shift) - 1);
452
453 last_attr = attr;
454 attr = tic & ((1 << tic_shift) - 1);
455
456 if ((logical != (last_logical + (1 << tic_shift))) ||
457 (physical != (last_physical + (1 << tic_shift))) ||
458 (attr & 4) != (last_attr & 4)) {
459
460 if (first_logical != 0xffffffff) {
461 size = last_logical + (1 << tic_shift) -
462 first_logical;
463 print_address_zone(f, cpu_fprintf, first_logical,
464 first_physical, size, last_attr);
465 }
466 first_logical = logical;
467 first_physical = physical;
468 }
469 }
470 }
471 }
472 if (first_logical != logical || (attr & 4) != (last_attr & 4)) {
473 size = logical + (1 << tic_shift) - first_logical;
474 print_address_zone(f, cpu_fprintf, first_logical, first_physical, size,
475 last_attr);
476 }
477}
478
479#define DUMP_CACHEFLAGS(a) \
480 switch (a & M68K_DESC_CACHEMODE) { \
481 case M68K_DESC_CM_WRTHRU: /* cachable, write-through */ \
482 cpu_fprintf(f, "T"); \
483 break; \
484 case M68K_DESC_CM_COPYBK: /* cachable, copyback */ \
485 cpu_fprintf(f, "C"); \
486 break; \
487 case M68K_DESC_CM_SERIAL: /* noncachable, serialized */ \
488 cpu_fprintf(f, "S"); \
489 break; \
490 case M68K_DESC_CM_NCACHE: /* noncachable */ \
491 cpu_fprintf(f, "N"); \
492 break; \
493 }
494
495static void dump_ttr(FILE *f, fprintf_function cpu_fprintf, uint32_t ttr)
496{
497 if ((ttr & M68K_TTR_ENABLED) == 0) {
498 cpu_fprintf(f, "disabled\n");
499 return;
500 }
501 cpu_fprintf(f, "Base: 0x%08x Mask: 0x%08x Control: ",
502 ttr & M68K_TTR_ADDR_BASE,
503 (ttr & M68K_TTR_ADDR_MASK) << M68K_TTR_ADDR_MASK_SHIFT);
504 switch (ttr & M68K_TTR_SFIELD) {
505 case M68K_TTR_SFIELD_USER:
506 cpu_fprintf(f, "U");
507 break;
508 case M68K_TTR_SFIELD_SUPER:
509 cpu_fprintf(f, "S");
510 break;
511 default:
512 cpu_fprintf(f, "*");
513 break;
514 }
515 DUMP_CACHEFLAGS(ttr);
516 if (ttr & M68K_DESC_WRITEPROT) {
517 cpu_fprintf(f, "R");
518 } else {
519 cpu_fprintf(f, "W");
520 }
521 cpu_fprintf(f, " U: %d\n", (ttr & M68K_DESC_USERATTR) >>
522 M68K_DESC_USERATTR_SHIFT);
523}
524
525void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUM68KState *env)
526{
527 if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
528 cpu_fprintf(f, "Translation disabled\n");
529 return;
530 }
531 cpu_fprintf(f, "Page Size: ");
532 if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
533 cpu_fprintf(f, "8kB\n");
534 } else {
535 cpu_fprintf(f, "4kB\n");
536 }
537
538 cpu_fprintf(f, "MMUSR: ");
539 if (env->mmu.mmusr & M68K_MMU_B_040) {
540 cpu_fprintf(f, "BUS ERROR\n");
541 } else {
542 cpu_fprintf(f, "Phy=%08x Flags: ", env->mmu.mmusr & 0xfffff000);
543 /* flags found on the page descriptor */
544 if (env->mmu.mmusr & M68K_MMU_G_040) {
545 cpu_fprintf(f, "G"); /* Global */
546 } else {
547 cpu_fprintf(f, ".");
548 }
549 if (env->mmu.mmusr & M68K_MMU_S_040) {
550 cpu_fprintf(f, "S"); /* Supervisor */
551 } else {
552 cpu_fprintf(f, ".");
553 }
554 if (env->mmu.mmusr & M68K_MMU_M_040) {
555 cpu_fprintf(f, "M"); /* Modified */
556 } else {
557 cpu_fprintf(f, ".");
558 }
559 if (env->mmu.mmusr & M68K_MMU_WP_040) {
560 cpu_fprintf(f, "W"); /* Write protect */
561 } else {
562 cpu_fprintf(f, ".");
563 }
564 if (env->mmu.mmusr & M68K_MMU_T_040) {
565 cpu_fprintf(f, "T"); /* Transparent */
566 } else {
567 cpu_fprintf(f, ".");
568 }
569 if (env->mmu.mmusr & M68K_MMU_R_040) {
570 cpu_fprintf(f, "R"); /* Resident */
571 } else {
572 cpu_fprintf(f, ".");
573 }
574 cpu_fprintf(f, " Cache: ");
575 DUMP_CACHEFLAGS(env->mmu.mmusr);
576 cpu_fprintf(f, " U: %d\n", (env->mmu.mmusr >> 8) & 3);
577 cpu_fprintf(f, "\n");
578 }
579
580 cpu_fprintf(f, "ITTR0: ");
581 dump_ttr(f, cpu_fprintf, env->mmu.ttr[M68K_ITTR0]);
582 cpu_fprintf(f, "ITTR1: ");
583 dump_ttr(f, cpu_fprintf, env->mmu.ttr[M68K_ITTR1]);
584 cpu_fprintf(f, "DTTR0: ");
585 dump_ttr(f, cpu_fprintf, env->mmu.ttr[M68K_DTTR0]);
586 cpu_fprintf(f, "DTTR1: ");
587 dump_ttr(f, cpu_fprintf, env->mmu.ttr[M68K_DTTR1]);
588
589 cpu_fprintf(f, "SRP: 0x%08x\n", env->mmu.srp);
590 dump_address_map(f, cpu_fprintf, env, env->mmu.srp);
591
592 cpu_fprintf(f, "URP: 0x%08x\n", env->mmu.urp);
593 dump_address_map(f, cpu_fprintf, env, env->mmu.urp);
594}
595
c05c73b0
LV
596static int check_TTR(uint32_t ttr, int *prot, target_ulong addr,
597 int access_type)
598{
599 uint32_t base, mask;
600
601 /* check if transparent translation is enabled */
602 if ((ttr & M68K_TTR_ENABLED) == 0) {
603 return 0;
604 }
605
606 /* check mode access */
607 switch (ttr & M68K_TTR_SFIELD) {
608 case M68K_TTR_SFIELD_USER:
609 /* match only if user */
610 if ((access_type & ACCESS_SUPER) != 0) {
611 return 0;
612 }
613 break;
614 case M68K_TTR_SFIELD_SUPER:
615 /* match only if supervisor */
616 if ((access_type & ACCESS_SUPER) == 0) {
617 return 0;
618 }
619 break;
620 default:
621 /* all other values disable mode matching (FC2) */
622 break;
623 }
624
625 /* check address matching */
626
627 base = ttr & M68K_TTR_ADDR_BASE;
628 mask = (ttr & M68K_TTR_ADDR_MASK) ^ M68K_TTR_ADDR_MASK;
629 mask <<= M68K_TTR_ADDR_MASK_SHIFT;
630
631 if ((addr & mask) != (base & mask)) {
632 return 0;
633 }
634
635 *prot = PAGE_READ | PAGE_EXEC;
636 if ((ttr & M68K_DESC_WRITEPROT) == 0) {
637 *prot |= PAGE_WRITE;
638 }
639
640 return 1;
641}
642
88b2fef6
LV
643static int get_physical_address(CPUM68KState *env, hwaddr *physical,
644 int *prot, target_ulong address,
645 int access_type, target_ulong *page_size)
646{
647 M68kCPU *cpu = m68k_env_get_cpu(env);
648 CPUState *cs = CPU(cpu);
649 uint32_t entry;
650 uint32_t next;
651 target_ulong page_mask;
652 bool debug = access_type & ACCESS_DEBUG;
653 int page_bits;
c05c73b0
LV
654 int i;
655
656 /* Transparent Translation (physical = logical) */
657 for (i = 0; i < M68K_MAX_TTR; i++) {
658 if (check_TTR(env->mmu.TTR(access_type, i),
659 prot, address, access_type)) {
e55886c3
LV
660 if (access_type & ACCESS_PTEST) {
661 /* Transparent Translation Register bit */
662 env->mmu.mmusr = M68K_MMU_T_040 | M68K_MMU_R_040;
663 }
c05c73b0
LV
664 *physical = address & TARGET_PAGE_MASK;
665 *page_size = TARGET_PAGE_SIZE;
666 return 0;
667 }
668 }
88b2fef6
LV
669
670 /* Page Table Root Pointer */
671 *prot = PAGE_READ | PAGE_WRITE;
672 if (access_type & ACCESS_CODE) {
673 *prot |= PAGE_EXEC;
674 }
675 if (access_type & ACCESS_SUPER) {
676 next = env->mmu.srp;
677 } else {
678 next = env->mmu.urp;
679 }
680
681 /* Root Index */
682 entry = M68K_POINTER_BASE(next) | M68K_ROOT_INDEX(address);
683
684 next = ldl_phys(cs->as, entry);
685 if (!M68K_UDT_VALID(next)) {
686 return -1;
687 }
688 if (!(next & M68K_DESC_USED) && !debug) {
689 stl_phys(cs->as, entry, next | M68K_DESC_USED);
690 }
691 if (next & M68K_DESC_WRITEPROT) {
e55886c3
LV
692 if (access_type & ACCESS_PTEST) {
693 env->mmu.mmusr |= M68K_MMU_WP_040;
694 }
88b2fef6
LV
695 *prot &= ~PAGE_WRITE;
696 if (access_type & ACCESS_STORE) {
697 return -1;
698 }
699 }
700
701 /* Pointer Index */
702 entry = M68K_POINTER_BASE(next) | M68K_POINTER_INDEX(address);
703
704 next = ldl_phys(cs->as, entry);
705 if (!M68K_UDT_VALID(next)) {
706 return -1;
707 }
708 if (!(next & M68K_DESC_USED) && !debug) {
709 stl_phys(cs->as, entry, next | M68K_DESC_USED);
710 }
711 if (next & M68K_DESC_WRITEPROT) {
e55886c3
LV
712 if (access_type & ACCESS_PTEST) {
713 env->mmu.mmusr |= M68K_MMU_WP_040;
714 }
88b2fef6
LV
715 *prot &= ~PAGE_WRITE;
716 if (access_type & ACCESS_STORE) {
717 return -1;
718 }
719 }
720
721 /* Page Index */
722 if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
723 entry = M68K_8K_PAGE_BASE(next) | M68K_8K_PAGE_INDEX(address);
724 } else {
725 entry = M68K_4K_PAGE_BASE(next) | M68K_4K_PAGE_INDEX(address);
726 }
727
728 next = ldl_phys(cs->as, entry);
729
730 if (!M68K_PDT_VALID(next)) {
731 return -1;
732 }
733 if (M68K_PDT_INDIRECT(next)) {
734 next = ldl_phys(cs->as, M68K_INDIRECT_POINTER(next));
735 }
736 if (access_type & ACCESS_STORE) {
737 if (next & M68K_DESC_WRITEPROT) {
738 if (!(next & M68K_DESC_USED) && !debug) {
739 stl_phys(cs->as, entry, next | M68K_DESC_USED);
740 }
741 } else if ((next & (M68K_DESC_MODIFIED | M68K_DESC_USED)) !=
742 (M68K_DESC_MODIFIED | M68K_DESC_USED) && !debug) {
743 stl_phys(cs->as, entry,
744 next | (M68K_DESC_MODIFIED | M68K_DESC_USED));
745 }
746 } else {
747 if (!(next & M68K_DESC_USED) && !debug) {
748 stl_phys(cs->as, entry, next | M68K_DESC_USED);
749 }
750 }
751
752 if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
753 page_bits = 13;
754 } else {
755 page_bits = 12;
756 }
757 *page_size = 1 << page_bits;
758 page_mask = ~(*page_size - 1);
759 *physical = next & page_mask;
760
e55886c3
LV
761 if (access_type & ACCESS_PTEST) {
762 env->mmu.mmusr |= next & M68K_MMU_SR_MASK_040;
763 env->mmu.mmusr |= *physical & 0xfffff000;
764 env->mmu.mmusr |= M68K_MMU_R_040;
765 }
766
88b2fef6
LV
767 if (next & M68K_DESC_WRITEPROT) {
768 *prot &= ~PAGE_WRITE;
769 if (access_type & ACCESS_STORE) {
770 return -1;
771 }
772 }
773 if (next & M68K_DESC_SUPERONLY) {
774 if ((access_type & ACCESS_SUPER) == 0) {
775 return -1;
776 }
777 }
778
779 return 0;
780}
4fcc562b 781
00b941e5 782hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
4fcc562b 783{
88b2fef6
LV
784 M68kCPU *cpu = M68K_CPU(cs);
785 CPUM68KState *env = &cpu->env;
786 hwaddr phys_addr;
787 int prot;
788 int access_type;
789 target_ulong page_size;
790
791 if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
792 /* MMU disabled */
793 return addr;
794 }
795
796 access_type = ACCESS_DATA | ACCESS_DEBUG;
797 if (env->sr & SR_S) {
798 access_type |= ACCESS_SUPER;
799 }
800 if (get_physical_address(env, &phys_addr, &prot,
801 addr, access_type, &page_size) != 0) {
802 return -1;
803 }
804 return phys_addr;
4fcc562b
PB
805}
806
98670d47 807int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
7510454e 808 int mmu_idx)
0633879f 809{
88b2fef6
LV
810 M68kCPU *cpu = M68K_CPU(cs);
811 CPUM68KState *env = &cpu->env;
812 hwaddr physical;
0633879f 813 int prot;
88b2fef6
LV
814 int access_type;
815 int ret;
816 target_ulong page_size;
817
818 if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
819 /* MMU disabled */
820 tlb_set_page(cs, address & TARGET_PAGE_MASK,
821 address & TARGET_PAGE_MASK,
822 PAGE_READ | PAGE_WRITE | PAGE_EXEC,
823 mmu_idx, TARGET_PAGE_SIZE);
824 return 0;
825 }
0633879f 826
88b2fef6
LV
827 if (rw == 2) {
828 access_type = ACCESS_CODE;
829 rw = 0;
830 } else {
831 access_type = ACCESS_DATA;
832 if (rw) {
833 access_type |= ACCESS_STORE;
834 }
835 }
836
837 if (mmu_idx != MMU_USER_IDX) {
838 access_type |= ACCESS_SUPER;
839 }
840
841 ret = get_physical_address(&cpu->env, &physical, &prot,
842 address, access_type, &page_size);
843 if (ret == 0) {
844 address &= TARGET_PAGE_MASK;
845 physical += address & (page_size - 1);
846 tlb_set_page(cs, address, physical,
847 prot, mmu_idx, TARGET_PAGE_SIZE);
848 return 0;
849 }
850 /* page fault */
851 env->mmu.ssw = M68K_ATC_040;
852 switch (size) {
853 case 1:
854 env->mmu.ssw |= M68K_BA_SIZE_BYTE;
855 break;
856 case 2:
857 env->mmu.ssw |= M68K_BA_SIZE_WORD;
858 break;
859 case 4:
860 env->mmu.ssw |= M68K_BA_SIZE_LONG;
861 break;
862 }
863 if (access_type & ACCESS_SUPER) {
864 env->mmu.ssw |= M68K_TM_040_SUPER;
865 }
866 if (access_type & ACCESS_CODE) {
867 env->mmu.ssw |= M68K_TM_040_CODE;
868 } else {
869 env->mmu.ssw |= M68K_TM_040_DATA;
870 }
871 if (!(access_type & ACCESS_STORE)) {
872 env->mmu.ssw |= M68K_RW_040;
873 }
874 env->mmu.ar = address;
875 cs->exception_index = EXCP_ACCESS;
876 return 1;
0633879f
PB
877}
878
879/* Notify CPU of a pending interrupt. Prioritization and vectoring should
880 be handled by the interrupt controller. Real hardware only requests
881 the vector when the interrupt is acknowledged by the CPU. For
882 simplicitly we calculate it when the interrupt is signalled. */
cb3fb38e 883void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
0633879f 884{
d8ed887b 885 CPUState *cs = CPU(cpu);
cb3fb38e
AF
886 CPUM68KState *env = &cpu->env;
887
0633879f
PB
888 env->pending_level = level;
889 env->pending_vector = vector;
d8ed887b 890 if (level) {
c3affe56 891 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
d8ed887b
AF
892 } else {
893 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
894 }
0633879f
PB
895}
896
897#endif
e1f3808e
PB
898
899uint32_t HELPER(bitrev)(uint32_t x)
900{
901 x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
902 x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
903 x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
904 return bswap32(x);
905}
906
907uint32_t HELPER(ff1)(uint32_t x)
908{
909 int n;
910 for (n = 32; x; n--)
911 x >>= 1;
912 return n;
913}
914
620c6cf6 915uint32_t HELPER(sats)(uint32_t val, uint32_t v)
e1f3808e
PB
916{
917 /* The result has the opposite sign to the original value. */
620c6cf6 918 if ((int32_t)v < 0) {
e1f3808e 919 val = (((int32_t)val) >> 31) ^ SIGNBIT;
620c6cf6 920 }
e1f3808e
PB
921 return val;
922}
923
d2f8fb8e 924void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
e1f3808e 925{
d2f8fb8e
LV
926 env->sr = sr & 0xffe0;
927 cpu_m68k_set_ccr(env, sr);
e1f3808e
PB
928 m68k_switch_sp(env);
929}
930
d2f8fb8e
LV
931void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
932{
933 cpu_m68k_set_sr(env, val);
934}
e1f3808e
PB
935
936/* MAC unit. */
937/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
938 take values, others take register numbers and manipulate the contents
939 in-place. */
2b3e3cfe 940void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
e1f3808e
PB
941{
942 uint32_t mask;
943 env->macc[dest] = env->macc[src];
944 mask = MACSR_PAV0 << dest;
945 if (env->macsr & (MACSR_PAV0 << src))
946 env->macsr |= mask;
947 else
948 env->macsr &= ~mask;
949}
950
2b3e3cfe 951uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
952{
953 int64_t product;
954 int64_t res;
955
956 product = (uint64_t)op1 * op2;
957 res = (product << 24) >> 24;
958 if (res != product) {
959 env->macsr |= MACSR_V;
960 if (env->macsr & MACSR_OMC) {
961 /* Make sure the accumulate operation overflows. */
962 if (product < 0)
963 res = ~(1ll << 50);
964 else
965 res = 1ll << 50;
966 }
967 }
968 return res;
969}
970
2b3e3cfe 971uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
972{
973 uint64_t product;
974
975 product = (uint64_t)op1 * op2;
976 if (product & (0xffffffull << 40)) {
977 env->macsr |= MACSR_V;
978 if (env->macsr & MACSR_OMC) {
979 /* Make sure the accumulate operation overflows. */
980 product = 1ll << 50;
981 } else {
982 product &= ((1ull << 40) - 1);
983 }
984 }
985 return product;
986}
987
2b3e3cfe 988uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
e1f3808e
PB
989{
990 uint64_t product;
991 uint32_t remainder;
992
993 product = (uint64_t)op1 * op2;
994 if (env->macsr & MACSR_RT) {
995 remainder = product & 0xffffff;
996 product >>= 24;
997 if (remainder > 0x800000)
998 product++;
999 else if (remainder == 0x800000)
1000 product += (product & 1);
1001 } else {
1002 product >>= 24;
1003 }
1004 return product;
1005}
1006
2b3e3cfe 1007void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
1008{
1009 int64_t tmp;
1010 int64_t result;
1011 tmp = env->macc[acc];
1012 result = ((tmp << 16) >> 16);
1013 if (result != tmp) {
1014 env->macsr |= MACSR_V;
1015 }
1016 if (env->macsr & MACSR_V) {
1017 env->macsr |= MACSR_PAV0 << acc;
1018 if (env->macsr & MACSR_OMC) {
a1c7273b 1019 /* The result is saturated to 32 bits, despite overflow occurring
e1f3808e
PB
1020 at 48 bits. Seems weird, but that's what the hardware docs
1021 say. */
1022 result = (result >> 63) ^ 0x7fffffff;
1023 }
1024 }
1025 env->macc[acc] = result;
1026}
1027
2b3e3cfe 1028void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
1029{
1030 uint64_t val;
1031
1032 val = env->macc[acc];
1033 if (val & (0xffffull << 48)) {
1034 env->macsr |= MACSR_V;
1035 }
1036 if (env->macsr & MACSR_V) {
1037 env->macsr |= MACSR_PAV0 << acc;
1038 if (env->macsr & MACSR_OMC) {
1039 if (val > (1ull << 53))
1040 val = 0;
1041 else
1042 val = (1ull << 48) - 1;
1043 } else {
1044 val &= ((1ull << 48) - 1);
1045 }
1046 }
1047 env->macc[acc] = val;
1048}
1049
2b3e3cfe 1050void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
1051{
1052 int64_t sum;
1053 int64_t result;
1054
1055 sum = env->macc[acc];
1056 result = (sum << 16) >> 16;
1057 if (result != sum) {
1058 env->macsr |= MACSR_V;
1059 }
1060 if (env->macsr & MACSR_V) {
1061 env->macsr |= MACSR_PAV0 << acc;
1062 if (env->macsr & MACSR_OMC) {
1063 result = (result >> 63) ^ 0x7fffffffffffll;
1064 }
1065 }
1066 env->macc[acc] = result;
1067}
1068
2b3e3cfe 1069void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
1070{
1071 uint64_t val;
1072 val = env->macc[acc];
c4162574 1073 if (val == 0) {
e1f3808e 1074 env->macsr |= MACSR_Z;
c4162574 1075 } else if (val & (1ull << 47)) {
e1f3808e 1076 env->macsr |= MACSR_N;
c4162574 1077 }
e1f3808e
PB
1078 if (env->macsr & (MACSR_PAV0 << acc)) {
1079 env->macsr |= MACSR_V;
1080 }
1081 if (env->macsr & MACSR_FI) {
1082 val = ((int64_t)val) >> 40;
1083 if (val != 0 && val != -1)
1084 env->macsr |= MACSR_EV;
1085 } else if (env->macsr & MACSR_SU) {
1086 val = ((int64_t)val) >> 32;
1087 if (val != 0 && val != -1)
1088 env->macsr |= MACSR_EV;
1089 } else {
1090 if ((val >> 32) != 0)
1091 env->macsr |= MACSR_EV;
1092 }
1093}
1094
db3d7945
LV
1095#define EXTSIGN(val, index) ( \
1096 (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
1097)
620c6cf6
RH
1098
1099#define COMPUTE_CCR(op, x, n, z, v, c) { \
1100 switch (op) { \
1101 case CC_OP_FLAGS: \
1102 /* Everything in place. */ \
1103 break; \
db3d7945
LV
1104 case CC_OP_ADDB: \
1105 case CC_OP_ADDW: \
1106 case CC_OP_ADDL: \
620c6cf6
RH
1107 res = n; \
1108 src2 = v; \
db3d7945 1109 src1 = EXTSIGN(res - src2, op - CC_OP_ADDB); \
620c6cf6
RH
1110 c = x; \
1111 z = n; \
1112 v = (res ^ src1) & ~(src1 ^ src2); \
1113 break; \
db3d7945
LV
1114 case CC_OP_SUBB: \
1115 case CC_OP_SUBW: \
1116 case CC_OP_SUBL: \
620c6cf6
RH
1117 res = n; \
1118 src2 = v; \
db3d7945 1119 src1 = EXTSIGN(res + src2, op - CC_OP_SUBB); \
620c6cf6
RH
1120 c = x; \
1121 z = n; \
1122 v = (res ^ src1) & (src1 ^ src2); \
1123 break; \
db3d7945
LV
1124 case CC_OP_CMPB: \
1125 case CC_OP_CMPW: \
1126 case CC_OP_CMPL: \
620c6cf6
RH
1127 src1 = n; \
1128 src2 = v; \
db3d7945 1129 res = EXTSIGN(src1 - src2, op - CC_OP_CMPB); \
620c6cf6
RH
1130 n = res; \
1131 z = res; \
1132 c = src1 < src2; \
1133 v = (res ^ src1) & (src1 ^ src2); \
1134 break; \
1135 case CC_OP_LOGIC: \
1136 c = v = 0; \
1137 z = n; \
1138 break; \
1139 default: \
1140 cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op); \
1141 } \
1142} while (0)
1143
1144uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
e1f3808e 1145{
620c6cf6
RH
1146 uint32_t x, c, n, z, v;
1147 uint32_t res, src1, src2;
1148
1149 x = env->cc_x;
620c6cf6
RH
1150 n = env->cc_n;
1151 z = env->cc_z;
1152 v = env->cc_v;
db3d7945 1153 c = env->cc_c;
620c6cf6
RH
1154
1155 COMPUTE_CCR(env->cc_op, x, n, z, v, c);
1156
1157 n = n >> 31;
620c6cf6 1158 z = (z == 0);
db3d7945 1159 v = v >> 31;
620c6cf6
RH
1160
1161 return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
1162}
1163
1164uint32_t HELPER(get_ccr)(CPUM68KState *env)
1165{
1166 return cpu_m68k_get_ccr(env);
1167}
1168
1169void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
1170{
1171 env->cc_x = (ccr & CCF_X ? 1 : 0);
1172 env->cc_n = (ccr & CCF_N ? -1 : 0);
1173 env->cc_z = (ccr & CCF_Z ? 0 : 1);
1174 env->cc_v = (ccr & CCF_V ? -1 : 0);
1175 env->cc_c = (ccr & CCF_C ? 1 : 0);
1176 env->cc_op = CC_OP_FLAGS;
1177}
1178
1179void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
1180{
1181 cpu_m68k_set_ccr(env, ccr);
1182}
1183
1184void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
1185{
1186 uint32_t res, src1, src2;
1187
1188 COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
1189 env->cc_op = CC_OP_FLAGS;
e1f3808e
PB
1190}
1191
2b3e3cfe 1192uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
e1f3808e
PB
1193{
1194 int rem;
1195 uint32_t result;
1196
1197 if (env->macsr & MACSR_SU) {
1198 /* 16-bit rounding. */
1199 rem = val & 0xffffff;
1200 val = (val >> 24) & 0xffffu;
1201 if (rem > 0x800000)
1202 val++;
1203 else if (rem == 0x800000)
1204 val += (val & 1);
1205 } else if (env->macsr & MACSR_RT) {
1206 /* 32-bit rounding. */
1207 rem = val & 0xff;
1208 val >>= 8;
1209 if (rem > 0x80)
1210 val++;
1211 else if (rem == 0x80)
1212 val += (val & 1);
1213 } else {
1214 /* No rounding. */
1215 val >>= 8;
1216 }
1217 if (env->macsr & MACSR_OMC) {
1218 /* Saturate. */
1219 if (env->macsr & MACSR_SU) {
1220 if (val != (uint16_t) val) {
1221 result = ((val >> 63) ^ 0x7fff) & 0xffff;
1222 } else {
1223 result = val & 0xffff;
1224 }
1225 } else {
1226 if (val != (uint32_t)val) {
1227 result = ((uint32_t)(val >> 63) & 0x7fffffff);
1228 } else {
1229 result = (uint32_t)val;
1230 }
1231 }
1232 } else {
1233 /* No saturation. */
1234 if (env->macsr & MACSR_SU) {
1235 result = val & 0xffff;
1236 } else {
1237 result = (uint32_t)val;
1238 }
1239 }
1240 return result;
1241}
1242
1243uint32_t HELPER(get_macs)(uint64_t val)
1244{
1245 if (val == (int32_t)val) {
1246 return (int32_t)val;
1247 } else {
1248 return (val >> 61) ^ ~SIGNBIT;
1249 }
1250}
1251
1252uint32_t HELPER(get_macu)(uint64_t val)
1253{
1254 if ((val >> 32) == 0) {
1255 return (uint32_t)val;
1256 } else {
1257 return 0xffffffffu;
1258 }
1259}
1260
2b3e3cfe 1261uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
1262{
1263 uint32_t val;
1264 val = env->macc[acc] & 0x00ff;
5ce747cf 1265 val |= (env->macc[acc] >> 32) & 0xff00;
e1f3808e
PB
1266 val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
1267 val |= (env->macc[acc + 1] >> 16) & 0xff000000;
1268 return val;
1269}
1270
2b3e3cfe 1271uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
e1f3808e
PB
1272{
1273 uint32_t val;
1274 val = (env->macc[acc] >> 32) & 0xffff;
1275 val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
1276 return val;
1277}
1278
2b3e3cfe 1279void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
1280{
1281 int64_t res;
1282 int32_t tmp;
1283 res = env->macc[acc] & 0xffffffff00ull;
1284 tmp = (int16_t)(val & 0xff00);
1285 res |= ((int64_t)tmp) << 32;
1286 res |= val & 0xff;
1287 env->macc[acc] = res;
1288 res = env->macc[acc + 1] & 0xffffffff00ull;
1289 tmp = (val & 0xff000000);
1290 res |= ((int64_t)tmp) << 16;
1291 res |= (val >> 16) & 0xff;
1292 env->macc[acc + 1] = res;
1293}
1294
2b3e3cfe 1295void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
1296{
1297 int64_t res;
1298 int32_t tmp;
1299 res = (uint32_t)env->macc[acc];
1300 tmp = (int16_t)val;
1301 res |= ((int64_t)tmp) << 32;
1302 env->macc[acc] = res;
1303 res = (uint32_t)env->macc[acc + 1];
1304 tmp = val & 0xffff0000;
1305 res |= (int64_t)tmp << 16;
1306 env->macc[acc + 1] = res;
1307}
1308
2b3e3cfe 1309void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
e1f3808e
PB
1310{
1311 uint64_t res;
1312 res = (uint32_t)env->macc[acc];
1313 res |= ((uint64_t)(val & 0xffff)) << 32;
1314 env->macc[acc] = res;
1315 res = (uint32_t)env->macc[acc + 1];
1316 res |= (uint64_t)(val & 0xffff0000) << 16;
1317 env->macc[acc + 1] = res;
1318}
0bdb2b3b
LV
1319
1320#if defined(CONFIG_SOFTMMU)
e55886c3
LV
1321void HELPER(ptest)(CPUM68KState *env, uint32_t addr, uint32_t is_read)
1322{
1323 M68kCPU *cpu = m68k_env_get_cpu(env);
1324 CPUState *cs = CPU(cpu);
1325 hwaddr physical;
1326 int access_type;
1327 int prot;
1328 int ret;
1329 target_ulong page_size;
1330
1331 access_type = ACCESS_PTEST;
1332 if (env->dfc & 4) {
1333 access_type |= ACCESS_SUPER;
1334 }
1335 if ((env->dfc & 3) == 2) {
1336 access_type |= ACCESS_CODE;
1337 }
1338 if (!is_read) {
1339 access_type |= ACCESS_STORE;
1340 }
1341
1342 env->mmu.mmusr = 0;
1343 env->mmu.ssw = 0;
1344 ret = get_physical_address(env, &physical, &prot, addr,
1345 access_type, &page_size);
1346 if (ret == 0) {
1347 addr &= TARGET_PAGE_MASK;
1348 physical += addr & (page_size - 1);
1349 tlb_set_page(cs, addr, physical,
1350 prot, access_type & ACCESS_SUPER ?
1351 MMU_KERNEL_IDX : MMU_USER_IDX, page_size);
1352 }
1353}
1354
1355void HELPER(pflush)(CPUM68KState *env, uint32_t addr, uint32_t opmode)
1356{
1357 M68kCPU *cpu = m68k_env_get_cpu(env);
1358
1359 switch (opmode) {
1360 case 0: /* Flush page entry if not global */
1361 case 1: /* Flush page entry */
1362 tlb_flush_page(CPU(cpu), addr);
1363 break;
1364 case 2: /* Flush all except global entries */
1365 tlb_flush(CPU(cpu));
1366 break;
1367 case 3: /* Flush all entries */
1368 tlb_flush(CPU(cpu));
1369 break;
1370 }
1371}
1372
0bdb2b3b
LV
1373void HELPER(reset)(CPUM68KState *env)
1374{
1375 /* FIXME: reset all except CPU */
1376}
1377#endif