xref: /qemu/target/m68k/helper.c (revision e55886c3340c3a3f1267a3a3d42082008bb255fb)
1e6e5906bSpbrook /*
2e6e5906bSpbrook  *  m68k op helpers
3e6e5906bSpbrook  *
40633879fSpbrook  *  Copyright (c) 2006-2007 CodeSourcery
5e6e5906bSpbrook  *  Written by Paul Brook
6e6e5906bSpbrook  *
7e6e5906bSpbrook  * This library is free software; you can redistribute it and/or
8e6e5906bSpbrook  * modify it under the terms of the GNU Lesser General Public
9e6e5906bSpbrook  * License as published by the Free Software Foundation; either
10e6e5906bSpbrook  * version 2 of the License, or (at your option) any later version.
11e6e5906bSpbrook  *
12e6e5906bSpbrook  * This library is distributed in the hope that it will be useful,
13e6e5906bSpbrook  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14e6e5906bSpbrook  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15e6e5906bSpbrook  * General Public License for more details.
16e6e5906bSpbrook  *
17e6e5906bSpbrook  * You should have received a copy of the GNU Lesser General Public
188167ee88SBlue Swirl  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19e6e5906bSpbrook  */
20e6e5906bSpbrook 
21d8416665SPeter Maydell #include "qemu/osdep.h"
22e6e5906bSpbrook #include "cpu.h"
2363c91552SPaolo Bonzini #include "exec/exec-all.h"
24022c62cbSPaolo Bonzini #include "exec/gdbstub.h"
25e6e5906bSpbrook 
262ef6175aSRichard Henderson #include "exec/helper-proto.h"
27e1f3808eSpbrook 
28e1f3808eSpbrook #define SIGNBIT (1u << 31)
29e1f3808eSpbrook 
3011150915SAndreas Färber /* Sort alphabetically, except for "any". */
3111150915SAndreas Färber static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
3211150915SAndreas Färber {
3311150915SAndreas Färber     ObjectClass *class_a = (ObjectClass *)a;
3411150915SAndreas Färber     ObjectClass *class_b = (ObjectClass *)b;
3511150915SAndreas Färber     const char *name_a, *name_b;
36aaed909aSbellard 
3711150915SAndreas Färber     name_a = object_class_get_name(class_a);
3811150915SAndreas Färber     name_b = object_class_get_name(class_b);
397a9f812bSAndreas Färber     if (strcmp(name_a, "any-" TYPE_M68K_CPU) == 0) {
4011150915SAndreas Färber         return 1;
417a9f812bSAndreas Färber     } else if (strcmp(name_b, "any-" TYPE_M68K_CPU) == 0) {
4211150915SAndreas Färber         return -1;
4311150915SAndreas Färber     } else {
4411150915SAndreas Färber         return strcasecmp(name_a, name_b);
4511150915SAndreas Färber     }
4611150915SAndreas Färber }
470402f767Spbrook 
4811150915SAndreas Färber static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
4911150915SAndreas Färber {
5011150915SAndreas Färber     ObjectClass *c = data;
5192a31361SAndreas Färber     CPUListState *s = user_data;
527a9f812bSAndreas Färber     const char *typename;
537a9f812bSAndreas Färber     char *name;
5411150915SAndreas Färber 
557a9f812bSAndreas Färber     typename = object_class_get_name(c);
567a9f812bSAndreas Färber     name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_M68K_CPU));
5711150915SAndreas Färber     (*s->cpu_fprintf)(s->file, "%s\n",
587a9f812bSAndreas Färber                       name);
597a9f812bSAndreas Färber     g_free(name);
6011150915SAndreas Färber }
610402f767Spbrook 
629a78eeadSStefan Weil void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
63009a4356SLaurent Vivier {
6492a31361SAndreas Färber     CPUListState s = {
6511150915SAndreas Färber         .file = f,
6611150915SAndreas Färber         .cpu_fprintf = cpu_fprintf,
6711150915SAndreas Färber     };
6811150915SAndreas Färber     GSList *list;
69009a4356SLaurent Vivier 
7011150915SAndreas Färber     list = object_class_get_list(TYPE_M68K_CPU, false);
7111150915SAndreas Färber     list = g_slist_sort(list, m68k_cpu_list_compare);
7211150915SAndreas Färber     g_slist_foreach(list, m68k_cpu_list_entry, &s);
7311150915SAndreas Färber     g_slist_free(list);
74009a4356SLaurent Vivier }
75009a4356SLaurent Vivier 
76f83311e4SLaurent Vivier static int cf_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
7756aebc89Spbrook {
7856aebc89Spbrook     if (n < 8) {
79f83311e4SLaurent Vivier         float_status s;
80f83311e4SLaurent Vivier         stfq_p(mem_buf, floatx80_to_float64(env->fregs[n].d, &s));
8156aebc89Spbrook         return 8;
8256aebc89Spbrook     }
83ba624944SLaurent Vivier     switch (n) {
84ba624944SLaurent Vivier     case 8: /* fpcontrol */
85ba624944SLaurent Vivier         stl_be_p(mem_buf, env->fpcr);
86ba624944SLaurent Vivier         return 4;
87ba624944SLaurent Vivier     case 9: /* fpstatus */
88ba624944SLaurent Vivier         stl_be_p(mem_buf, env->fpsr);
89ba624944SLaurent Vivier         return 4;
90ba624944SLaurent Vivier     case 10: /* fpiar, not implemented */
9156aebc89Spbrook         memset(mem_buf, 0, 4);
9256aebc89Spbrook         return 4;
9356aebc89Spbrook     }
9456aebc89Spbrook     return 0;
9556aebc89Spbrook }
9656aebc89Spbrook 
97f83311e4SLaurent Vivier static int cf_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
9856aebc89Spbrook {
9956aebc89Spbrook     if (n < 8) {
100f83311e4SLaurent Vivier         float_status s;
101f83311e4SLaurent Vivier         env->fregs[n].d = float64_to_floatx80(ldfq_p(mem_buf), &s);
10256aebc89Spbrook         return 8;
10356aebc89Spbrook     }
104ba624944SLaurent Vivier     switch (n) {
105ba624944SLaurent Vivier     case 8: /* fpcontrol */
106ba624944SLaurent Vivier         cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
107ba624944SLaurent Vivier         return 4;
108ba624944SLaurent Vivier     case 9: /* fpstatus */
109ba624944SLaurent Vivier         env->fpsr = ldl_p(mem_buf);
110ba624944SLaurent Vivier         return 4;
111ba624944SLaurent Vivier     case 10: /* fpiar, not implemented */
11256aebc89Spbrook         return 4;
11356aebc89Spbrook     }
11456aebc89Spbrook     return 0;
11556aebc89Spbrook }
11656aebc89Spbrook 
1175a4526b2SLaurent Vivier static int m68k_fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
1185a4526b2SLaurent Vivier {
1195a4526b2SLaurent Vivier     if (n < 8) {
1205a4526b2SLaurent Vivier         stw_be_p(mem_buf, env->fregs[n].l.upper);
1215a4526b2SLaurent Vivier         memset(mem_buf + 2, 0, 2);
1225a4526b2SLaurent Vivier         stq_be_p(mem_buf + 4, env->fregs[n].l.lower);
1235a4526b2SLaurent Vivier         return 12;
1245a4526b2SLaurent Vivier     }
1255a4526b2SLaurent Vivier     switch (n) {
1265a4526b2SLaurent Vivier     case 8: /* fpcontrol */
1275a4526b2SLaurent Vivier         stl_be_p(mem_buf, env->fpcr);
1285a4526b2SLaurent Vivier         return 4;
1295a4526b2SLaurent Vivier     case 9: /* fpstatus */
1305a4526b2SLaurent Vivier         stl_be_p(mem_buf, env->fpsr);
1315a4526b2SLaurent Vivier         return 4;
1325a4526b2SLaurent Vivier     case 10: /* fpiar, not implemented */
1335a4526b2SLaurent Vivier         memset(mem_buf, 0, 4);
1345a4526b2SLaurent Vivier         return 4;
1355a4526b2SLaurent Vivier     }
1365a4526b2SLaurent Vivier     return 0;
1375a4526b2SLaurent Vivier }
1385a4526b2SLaurent Vivier 
1395a4526b2SLaurent Vivier static int m68k_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
1405a4526b2SLaurent Vivier {
1415a4526b2SLaurent Vivier     if (n < 8) {
1425a4526b2SLaurent Vivier         env->fregs[n].l.upper = lduw_be_p(mem_buf);
1435a4526b2SLaurent Vivier         env->fregs[n].l.lower = ldq_be_p(mem_buf + 4);
1445a4526b2SLaurent Vivier         return 12;
1455a4526b2SLaurent Vivier     }
1465a4526b2SLaurent Vivier     switch (n) {
1475a4526b2SLaurent Vivier     case 8: /* fpcontrol */
148ba624944SLaurent Vivier         cpu_m68k_set_fpcr(env, ldl_p(mem_buf));
1495a4526b2SLaurent Vivier         return 4;
1505a4526b2SLaurent Vivier     case 9: /* fpstatus */
1515a4526b2SLaurent Vivier         env->fpsr = ldl_p(mem_buf);
1525a4526b2SLaurent Vivier         return 4;
1535a4526b2SLaurent Vivier     case 10: /* fpiar, not implemented */
1545a4526b2SLaurent Vivier         return 4;
1555a4526b2SLaurent Vivier     }
1565a4526b2SLaurent Vivier     return 0;
1575a4526b2SLaurent Vivier }
1585a4526b2SLaurent Vivier 
1596d1bbc62SAndreas Färber void m68k_cpu_init_gdb(M68kCPU *cpu)
1606d1bbc62SAndreas Färber {
16122169d41SAndreas Färber     CPUState *cs = CPU(cpu);
1626d1bbc62SAndreas Färber     CPUM68KState *env = &cpu->env;
1636d1bbc62SAndreas Färber 
16411150915SAndreas Färber     if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
165f83311e4SLaurent Vivier         gdb_register_coprocessor(cs, cf_fpu_gdb_get_reg, cf_fpu_gdb_set_reg,
16611150915SAndreas Färber                                  11, "cf-fp.xml", 18);
1675a4526b2SLaurent Vivier     } else if (m68k_feature(env, M68K_FEATURE_FPU)) {
1685a4526b2SLaurent Vivier         gdb_register_coprocessor(cs, m68k_fpu_gdb_get_reg,
1695a4526b2SLaurent Vivier                                  m68k_fpu_gdb_set_reg, 11, "m68k-fp.xml", 18);
170aaed909aSbellard     }
17111150915SAndreas Färber     /* TODO: Add [E]MAC registers.  */
172aaed909aSbellard }
173aaed909aSbellard 
1746e22b28eSLaurent Vivier void HELPER(cf_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
1750633879fSpbrook {
176a47dddd7SAndreas Färber     M68kCPU *cpu = m68k_env_get_cpu(env);
177a47dddd7SAndreas Färber 
1780633879fSpbrook     switch (reg) {
1796e22b28eSLaurent Vivier     case M68K_CR_CACR:
18020dcee94Spbrook         env->cacr = val;
18120dcee94Spbrook         m68k_switch_sp(env);
18220dcee94Spbrook         break;
1836e22b28eSLaurent Vivier     case M68K_CR_ACR0:
1846e22b28eSLaurent Vivier     case M68K_CR_ACR1:
1856e22b28eSLaurent Vivier     case M68K_CR_ACR2:
1866e22b28eSLaurent Vivier     case M68K_CR_ACR3:
18720dcee94Spbrook         /* TODO: Implement Access Control Registers.  */
1880633879fSpbrook         break;
1896e22b28eSLaurent Vivier     case M68K_CR_VBR:
1900633879fSpbrook         env->vbr = val;
1910633879fSpbrook         break;
1920633879fSpbrook     /* TODO: Implement control registers.  */
1930633879fSpbrook     default:
1946e22b28eSLaurent Vivier         cpu_abort(CPU(cpu),
1956e22b28eSLaurent Vivier                   "Unimplemented control register write 0x%x = 0x%x\n",
1966e22b28eSLaurent Vivier                   reg, val);
1976e22b28eSLaurent Vivier     }
1986e22b28eSLaurent Vivier }
1996e22b28eSLaurent Vivier 
2006e22b28eSLaurent Vivier void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val)
2016e22b28eSLaurent Vivier {
2026e22b28eSLaurent Vivier     M68kCPU *cpu = m68k_env_get_cpu(env);
2036e22b28eSLaurent Vivier 
2046e22b28eSLaurent Vivier     switch (reg) {
2056e22b28eSLaurent Vivier     /* MC680[1234]0 */
2065fa9f1f2SLaurent Vivier     case M68K_CR_SFC:
2075fa9f1f2SLaurent Vivier         env->sfc = val & 7;
2085fa9f1f2SLaurent Vivier         return;
2095fa9f1f2SLaurent Vivier     case M68K_CR_DFC:
2105fa9f1f2SLaurent Vivier         env->dfc = val & 7;
2115fa9f1f2SLaurent Vivier         return;
2126e22b28eSLaurent Vivier     case M68K_CR_VBR:
2136e22b28eSLaurent Vivier         env->vbr = val;
2146e22b28eSLaurent Vivier         return;
2156e22b28eSLaurent Vivier     /* MC680[234]0 */
2166e22b28eSLaurent Vivier     case M68K_CR_CACR:
2176e22b28eSLaurent Vivier         env->cacr = val;
2186e22b28eSLaurent Vivier         m68k_switch_sp(env);
2196e22b28eSLaurent Vivier         return;
2206e22b28eSLaurent Vivier     /* MC680[34]0 */
22188b2fef6SLaurent Vivier     case M68K_CR_TC:
22288b2fef6SLaurent Vivier         env->mmu.tcr = val;
22388b2fef6SLaurent Vivier         return;
224*e55886c3SLaurent Vivier     case M68K_CR_MMUSR:
225*e55886c3SLaurent Vivier         env->mmu.mmusr = val;
226*e55886c3SLaurent Vivier         return;
22788b2fef6SLaurent Vivier     case M68K_CR_SRP:
22888b2fef6SLaurent Vivier         env->mmu.srp = val;
22988b2fef6SLaurent Vivier         return;
23088b2fef6SLaurent Vivier     case M68K_CR_URP:
23188b2fef6SLaurent Vivier         env->mmu.urp = val;
23288b2fef6SLaurent Vivier         return;
2336e22b28eSLaurent Vivier     case M68K_CR_USP:
2346e22b28eSLaurent Vivier         env->sp[M68K_USP] = val;
2356e22b28eSLaurent Vivier         return;
2366e22b28eSLaurent Vivier     case M68K_CR_MSP:
2376e22b28eSLaurent Vivier         env->sp[M68K_SSP] = val;
2386e22b28eSLaurent Vivier         return;
2396e22b28eSLaurent Vivier     case M68K_CR_ISP:
2406e22b28eSLaurent Vivier         env->sp[M68K_ISP] = val;
2416e22b28eSLaurent Vivier         return;
242c05c73b0SLaurent Vivier     /* MC68040/MC68LC040 */
243c05c73b0SLaurent Vivier     case M68K_CR_ITT0:
244c05c73b0SLaurent Vivier         env->mmu.ttr[M68K_ITTR0] = val;
245c05c73b0SLaurent Vivier         return;
246c05c73b0SLaurent Vivier     case M68K_CR_ITT1:
247c05c73b0SLaurent Vivier          env->mmu.ttr[M68K_ITTR1] = val;
248c05c73b0SLaurent Vivier         return;
249c05c73b0SLaurent Vivier     case M68K_CR_DTT0:
250c05c73b0SLaurent Vivier         env->mmu.ttr[M68K_DTTR0] = val;
251c05c73b0SLaurent Vivier         return;
252c05c73b0SLaurent Vivier     case M68K_CR_DTT1:
253c05c73b0SLaurent Vivier         env->mmu.ttr[M68K_DTTR1] = val;
254c05c73b0SLaurent Vivier         return;
2556e22b28eSLaurent Vivier     }
256a47dddd7SAndreas Färber     cpu_abort(CPU(cpu), "Unimplemented control register write 0x%x = 0x%x\n",
2570633879fSpbrook               reg, val);
2580633879fSpbrook }
2596e22b28eSLaurent Vivier 
2606e22b28eSLaurent Vivier uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg)
2616e22b28eSLaurent Vivier {
2626e22b28eSLaurent Vivier     M68kCPU *cpu = m68k_env_get_cpu(env);
2636e22b28eSLaurent Vivier 
2646e22b28eSLaurent Vivier     switch (reg) {
2656e22b28eSLaurent Vivier     /* MC680[1234]0 */
2665fa9f1f2SLaurent Vivier     case M68K_CR_SFC:
2675fa9f1f2SLaurent Vivier         return env->sfc;
2685fa9f1f2SLaurent Vivier     case M68K_CR_DFC:
2695fa9f1f2SLaurent Vivier         return env->dfc;
2706e22b28eSLaurent Vivier     case M68K_CR_VBR:
2716e22b28eSLaurent Vivier         return env->vbr;
2726e22b28eSLaurent Vivier     /* MC680[234]0 */
2736e22b28eSLaurent Vivier     case M68K_CR_CACR:
2746e22b28eSLaurent Vivier         return env->cacr;
2756e22b28eSLaurent Vivier     /* MC680[34]0 */
27688b2fef6SLaurent Vivier     case M68K_CR_TC:
27788b2fef6SLaurent Vivier         return env->mmu.tcr;
278*e55886c3SLaurent Vivier     case M68K_CR_MMUSR:
279*e55886c3SLaurent Vivier         return env->mmu.mmusr;
28088b2fef6SLaurent Vivier     case M68K_CR_SRP:
28188b2fef6SLaurent Vivier         return env->mmu.srp;
2826e22b28eSLaurent Vivier     case M68K_CR_USP:
2836e22b28eSLaurent Vivier         return env->sp[M68K_USP];
2846e22b28eSLaurent Vivier     case M68K_CR_MSP:
2856e22b28eSLaurent Vivier         return env->sp[M68K_SSP];
2866e22b28eSLaurent Vivier     case M68K_CR_ISP:
2876e22b28eSLaurent Vivier         return env->sp[M68K_ISP];
28888b2fef6SLaurent Vivier     /* MC68040/MC68LC040 */
28988b2fef6SLaurent Vivier     case M68K_CR_URP:
29088b2fef6SLaurent Vivier         return env->mmu.urp;
291c05c73b0SLaurent Vivier     case M68K_CR_ITT0:
292c05c73b0SLaurent Vivier         return env->mmu.ttr[M68K_ITTR0];
293c05c73b0SLaurent Vivier     case M68K_CR_ITT1:
294c05c73b0SLaurent Vivier         return env->mmu.ttr[M68K_ITTR1];
295c05c73b0SLaurent Vivier     case M68K_CR_DTT0:
296c05c73b0SLaurent Vivier         return env->mmu.ttr[M68K_DTTR0];
297c05c73b0SLaurent Vivier     case M68K_CR_DTT1:
298c05c73b0SLaurent Vivier         return env->mmu.ttr[M68K_DTTR1];
2996e22b28eSLaurent Vivier     }
3006e22b28eSLaurent Vivier     cpu_abort(CPU(cpu), "Unimplemented control register read 0x%x\n",
3016e22b28eSLaurent Vivier               reg);
3020633879fSpbrook }
3030633879fSpbrook 
304e1f3808eSpbrook void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
305acf930aaSpbrook {
306acf930aaSpbrook     uint32_t acc;
307acf930aaSpbrook     int8_t exthigh;
308acf930aaSpbrook     uint8_t extlow;
309acf930aaSpbrook     uint64_t regval;
310acf930aaSpbrook     int i;
311acf930aaSpbrook     if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
312acf930aaSpbrook         for (i = 0; i < 4; i++) {
313acf930aaSpbrook             regval = env->macc[i];
314acf930aaSpbrook             exthigh = regval >> 40;
315acf930aaSpbrook             if (env->macsr & MACSR_FI) {
316acf930aaSpbrook                 acc = regval >> 8;
317acf930aaSpbrook                 extlow = regval;
318acf930aaSpbrook             } else {
319acf930aaSpbrook                 acc = regval;
320acf930aaSpbrook                 extlow = regval >> 32;
321acf930aaSpbrook             }
322acf930aaSpbrook             if (env->macsr & MACSR_FI) {
323acf930aaSpbrook                 regval = (((uint64_t)acc) << 8) | extlow;
324acf930aaSpbrook                 regval |= ((int64_t)exthigh) << 40;
325acf930aaSpbrook             } else if (env->macsr & MACSR_SU) {
326acf930aaSpbrook                 regval = acc | (((int64_t)extlow) << 32);
327acf930aaSpbrook                 regval |= ((int64_t)exthigh) << 40;
328acf930aaSpbrook             } else {
329acf930aaSpbrook                 regval = acc | (((uint64_t)extlow) << 32);
330acf930aaSpbrook                 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
331acf930aaSpbrook             }
332acf930aaSpbrook             env->macc[i] = regval;
333acf930aaSpbrook         }
334acf930aaSpbrook     }
335acf930aaSpbrook     env->macsr = val;
336acf930aaSpbrook }
337acf930aaSpbrook 
33820dcee94Spbrook void m68k_switch_sp(CPUM68KState *env)
33920dcee94Spbrook {
34020dcee94Spbrook     int new_sp;
34120dcee94Spbrook 
34220dcee94Spbrook     env->sp[env->current_sp] = env->aregs[7];
3436e22b28eSLaurent Vivier     if (m68k_feature(env, M68K_FEATURE_M68000)) {
3446e22b28eSLaurent Vivier         if (env->sr & SR_S) {
3456e22b28eSLaurent Vivier             if (env->sr & SR_M) {
3466e22b28eSLaurent Vivier                 new_sp = M68K_SSP;
3476e22b28eSLaurent Vivier             } else {
3486e22b28eSLaurent Vivier                 new_sp = M68K_ISP;
3496e22b28eSLaurent Vivier             }
3506e22b28eSLaurent Vivier         } else {
3516e22b28eSLaurent Vivier             new_sp = M68K_USP;
3526e22b28eSLaurent Vivier         }
3536e22b28eSLaurent Vivier     } else {
35420dcee94Spbrook         new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
35520dcee94Spbrook                  ? M68K_SSP : M68K_USP;
3566e22b28eSLaurent Vivier     }
35720dcee94Spbrook     env->aregs[7] = env->sp[new_sp];
35820dcee94Spbrook     env->current_sp = new_sp;
35920dcee94Spbrook }
36020dcee94Spbrook 
3610633879fSpbrook #if defined(CONFIG_USER_ONLY)
3620633879fSpbrook 
36398670d47SLaurent Vivier int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
36497b348e7SBlue Swirl                               int mmu_idx)
3650633879fSpbrook {
3667510454eSAndreas Färber     M68kCPU *cpu = M68K_CPU(cs);
3677510454eSAndreas Färber 
36827103424SAndreas Färber     cs->exception_index = EXCP_ACCESS;
3697510454eSAndreas Färber     cpu->env.mmu.ar = address;
3700633879fSpbrook     return 1;
3710633879fSpbrook }
3720633879fSpbrook 
3730633879fSpbrook #else
3740633879fSpbrook 
37588b2fef6SLaurent Vivier /* MMU: 68040 only */
3764fcc562bSPaul Brook 
377c05c73b0SLaurent Vivier static int check_TTR(uint32_t ttr, int *prot, target_ulong addr,
378c05c73b0SLaurent Vivier                      int access_type)
379c05c73b0SLaurent Vivier {
380c05c73b0SLaurent Vivier     uint32_t base, mask;
381c05c73b0SLaurent Vivier 
382c05c73b0SLaurent Vivier     /* check if transparent translation is enabled */
383c05c73b0SLaurent Vivier     if ((ttr & M68K_TTR_ENABLED) == 0) {
384c05c73b0SLaurent Vivier         return 0;
385c05c73b0SLaurent Vivier     }
386c05c73b0SLaurent Vivier 
387c05c73b0SLaurent Vivier     /* check mode access */
388c05c73b0SLaurent Vivier     switch (ttr & M68K_TTR_SFIELD) {
389c05c73b0SLaurent Vivier     case M68K_TTR_SFIELD_USER:
390c05c73b0SLaurent Vivier         /* match only if user */
391c05c73b0SLaurent Vivier         if ((access_type & ACCESS_SUPER) != 0) {
392c05c73b0SLaurent Vivier             return 0;
393c05c73b0SLaurent Vivier         }
394c05c73b0SLaurent Vivier         break;
395c05c73b0SLaurent Vivier     case M68K_TTR_SFIELD_SUPER:
396c05c73b0SLaurent Vivier         /* match only if supervisor */
397c05c73b0SLaurent Vivier         if ((access_type & ACCESS_SUPER) == 0) {
398c05c73b0SLaurent Vivier             return 0;
399c05c73b0SLaurent Vivier         }
400c05c73b0SLaurent Vivier         break;
401c05c73b0SLaurent Vivier     default:
402c05c73b0SLaurent Vivier         /* all other values disable mode matching (FC2) */
403c05c73b0SLaurent Vivier         break;
404c05c73b0SLaurent Vivier     }
405c05c73b0SLaurent Vivier 
406c05c73b0SLaurent Vivier     /* check address matching */
407c05c73b0SLaurent Vivier 
408c05c73b0SLaurent Vivier     base = ttr & M68K_TTR_ADDR_BASE;
409c05c73b0SLaurent Vivier     mask = (ttr & M68K_TTR_ADDR_MASK) ^ M68K_TTR_ADDR_MASK;
410c05c73b0SLaurent Vivier     mask <<= M68K_TTR_ADDR_MASK_SHIFT;
411c05c73b0SLaurent Vivier 
412c05c73b0SLaurent Vivier     if ((addr & mask) != (base & mask)) {
413c05c73b0SLaurent Vivier         return 0;
414c05c73b0SLaurent Vivier     }
415c05c73b0SLaurent Vivier 
416c05c73b0SLaurent Vivier     *prot = PAGE_READ | PAGE_EXEC;
417c05c73b0SLaurent Vivier     if ((ttr & M68K_DESC_WRITEPROT) == 0) {
418c05c73b0SLaurent Vivier         *prot |= PAGE_WRITE;
419c05c73b0SLaurent Vivier     }
420c05c73b0SLaurent Vivier 
421c05c73b0SLaurent Vivier     return 1;
422c05c73b0SLaurent Vivier }
423c05c73b0SLaurent Vivier 
42488b2fef6SLaurent Vivier static int get_physical_address(CPUM68KState *env, hwaddr *physical,
42588b2fef6SLaurent Vivier                                 int *prot, target_ulong address,
42688b2fef6SLaurent Vivier                                 int access_type, target_ulong *page_size)
42788b2fef6SLaurent Vivier {
42888b2fef6SLaurent Vivier     M68kCPU *cpu = m68k_env_get_cpu(env);
42988b2fef6SLaurent Vivier     CPUState *cs = CPU(cpu);
43088b2fef6SLaurent Vivier     uint32_t entry;
43188b2fef6SLaurent Vivier     uint32_t next;
43288b2fef6SLaurent Vivier     target_ulong page_mask;
43388b2fef6SLaurent Vivier     bool debug = access_type & ACCESS_DEBUG;
43488b2fef6SLaurent Vivier     int page_bits;
435c05c73b0SLaurent Vivier     int i;
436c05c73b0SLaurent Vivier 
437c05c73b0SLaurent Vivier     /* Transparent Translation (physical = logical) */
438c05c73b0SLaurent Vivier     for (i = 0; i < M68K_MAX_TTR; i++) {
439c05c73b0SLaurent Vivier         if (check_TTR(env->mmu.TTR(access_type, i),
440c05c73b0SLaurent Vivier                       prot, address, access_type)) {
441*e55886c3SLaurent Vivier             if (access_type & ACCESS_PTEST) {
442*e55886c3SLaurent Vivier                 /* Transparent Translation Register bit */
443*e55886c3SLaurent Vivier                 env->mmu.mmusr = M68K_MMU_T_040 | M68K_MMU_R_040;
444*e55886c3SLaurent Vivier             }
445c05c73b0SLaurent Vivier             *physical = address & TARGET_PAGE_MASK;
446c05c73b0SLaurent Vivier             *page_size = TARGET_PAGE_SIZE;
447c05c73b0SLaurent Vivier             return 0;
448c05c73b0SLaurent Vivier         }
449c05c73b0SLaurent Vivier     }
45088b2fef6SLaurent Vivier 
45188b2fef6SLaurent Vivier     /* Page Table Root Pointer */
45288b2fef6SLaurent Vivier     *prot = PAGE_READ | PAGE_WRITE;
45388b2fef6SLaurent Vivier     if (access_type & ACCESS_CODE) {
45488b2fef6SLaurent Vivier         *prot |= PAGE_EXEC;
45588b2fef6SLaurent Vivier     }
45688b2fef6SLaurent Vivier     if (access_type & ACCESS_SUPER) {
45788b2fef6SLaurent Vivier         next = env->mmu.srp;
45888b2fef6SLaurent Vivier     } else {
45988b2fef6SLaurent Vivier         next = env->mmu.urp;
46088b2fef6SLaurent Vivier     }
46188b2fef6SLaurent Vivier 
46288b2fef6SLaurent Vivier     /* Root Index */
46388b2fef6SLaurent Vivier     entry = M68K_POINTER_BASE(next) | M68K_ROOT_INDEX(address);
46488b2fef6SLaurent Vivier 
46588b2fef6SLaurent Vivier     next = ldl_phys(cs->as, entry);
46688b2fef6SLaurent Vivier     if (!M68K_UDT_VALID(next)) {
46788b2fef6SLaurent Vivier         return -1;
46888b2fef6SLaurent Vivier     }
46988b2fef6SLaurent Vivier     if (!(next & M68K_DESC_USED) && !debug) {
47088b2fef6SLaurent Vivier         stl_phys(cs->as, entry, next | M68K_DESC_USED);
47188b2fef6SLaurent Vivier     }
47288b2fef6SLaurent Vivier     if (next & M68K_DESC_WRITEPROT) {
473*e55886c3SLaurent Vivier         if (access_type & ACCESS_PTEST) {
474*e55886c3SLaurent Vivier             env->mmu.mmusr |= M68K_MMU_WP_040;
475*e55886c3SLaurent Vivier         }
47688b2fef6SLaurent Vivier         *prot &= ~PAGE_WRITE;
47788b2fef6SLaurent Vivier         if (access_type & ACCESS_STORE) {
47888b2fef6SLaurent Vivier             return -1;
47988b2fef6SLaurent Vivier         }
48088b2fef6SLaurent Vivier     }
48188b2fef6SLaurent Vivier 
48288b2fef6SLaurent Vivier     /* Pointer Index */
48388b2fef6SLaurent Vivier     entry = M68K_POINTER_BASE(next) | M68K_POINTER_INDEX(address);
48488b2fef6SLaurent Vivier 
48588b2fef6SLaurent Vivier     next = ldl_phys(cs->as, entry);
48688b2fef6SLaurent Vivier     if (!M68K_UDT_VALID(next)) {
48788b2fef6SLaurent Vivier         return -1;
48888b2fef6SLaurent Vivier     }
48988b2fef6SLaurent Vivier     if (!(next & M68K_DESC_USED) && !debug) {
49088b2fef6SLaurent Vivier         stl_phys(cs->as, entry, next | M68K_DESC_USED);
49188b2fef6SLaurent Vivier     }
49288b2fef6SLaurent Vivier     if (next & M68K_DESC_WRITEPROT) {
493*e55886c3SLaurent Vivier         if (access_type & ACCESS_PTEST) {
494*e55886c3SLaurent Vivier             env->mmu.mmusr |= M68K_MMU_WP_040;
495*e55886c3SLaurent Vivier         }
49688b2fef6SLaurent Vivier         *prot &= ~PAGE_WRITE;
49788b2fef6SLaurent Vivier         if (access_type & ACCESS_STORE) {
49888b2fef6SLaurent Vivier             return -1;
49988b2fef6SLaurent Vivier         }
50088b2fef6SLaurent Vivier     }
50188b2fef6SLaurent Vivier 
50288b2fef6SLaurent Vivier     /* Page Index */
50388b2fef6SLaurent Vivier     if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
50488b2fef6SLaurent Vivier         entry = M68K_8K_PAGE_BASE(next) | M68K_8K_PAGE_INDEX(address);
50588b2fef6SLaurent Vivier     } else {
50688b2fef6SLaurent Vivier         entry = M68K_4K_PAGE_BASE(next) | M68K_4K_PAGE_INDEX(address);
50788b2fef6SLaurent Vivier     }
50888b2fef6SLaurent Vivier 
50988b2fef6SLaurent Vivier     next = ldl_phys(cs->as, entry);
51088b2fef6SLaurent Vivier 
51188b2fef6SLaurent Vivier     if (!M68K_PDT_VALID(next)) {
51288b2fef6SLaurent Vivier         return -1;
51388b2fef6SLaurent Vivier     }
51488b2fef6SLaurent Vivier     if (M68K_PDT_INDIRECT(next)) {
51588b2fef6SLaurent Vivier         next = ldl_phys(cs->as, M68K_INDIRECT_POINTER(next));
51688b2fef6SLaurent Vivier     }
51788b2fef6SLaurent Vivier     if (access_type & ACCESS_STORE) {
51888b2fef6SLaurent Vivier         if (next & M68K_DESC_WRITEPROT) {
51988b2fef6SLaurent Vivier             if (!(next & M68K_DESC_USED) && !debug) {
52088b2fef6SLaurent Vivier                 stl_phys(cs->as, entry, next | M68K_DESC_USED);
52188b2fef6SLaurent Vivier             }
52288b2fef6SLaurent Vivier         } else if ((next & (M68K_DESC_MODIFIED | M68K_DESC_USED)) !=
52388b2fef6SLaurent Vivier                            (M68K_DESC_MODIFIED | M68K_DESC_USED) && !debug) {
52488b2fef6SLaurent Vivier                 stl_phys(cs->as, entry,
52588b2fef6SLaurent Vivier                          next | (M68K_DESC_MODIFIED | M68K_DESC_USED));
52688b2fef6SLaurent Vivier         }
52788b2fef6SLaurent Vivier     } else {
52888b2fef6SLaurent Vivier         if (!(next & M68K_DESC_USED) && !debug) {
52988b2fef6SLaurent Vivier             stl_phys(cs->as, entry, next | M68K_DESC_USED);
53088b2fef6SLaurent Vivier         }
53188b2fef6SLaurent Vivier     }
53288b2fef6SLaurent Vivier 
53388b2fef6SLaurent Vivier     if (env->mmu.tcr & M68K_TCR_PAGE_8K) {
53488b2fef6SLaurent Vivier         page_bits = 13;
53588b2fef6SLaurent Vivier     } else {
53688b2fef6SLaurent Vivier         page_bits = 12;
53788b2fef6SLaurent Vivier     }
53888b2fef6SLaurent Vivier     *page_size = 1 << page_bits;
53988b2fef6SLaurent Vivier     page_mask = ~(*page_size - 1);
54088b2fef6SLaurent Vivier     *physical = next & page_mask;
54188b2fef6SLaurent Vivier 
542*e55886c3SLaurent Vivier     if (access_type & ACCESS_PTEST) {
543*e55886c3SLaurent Vivier         env->mmu.mmusr |= next & M68K_MMU_SR_MASK_040;
544*e55886c3SLaurent Vivier         env->mmu.mmusr |= *physical & 0xfffff000;
545*e55886c3SLaurent Vivier         env->mmu.mmusr |= M68K_MMU_R_040;
546*e55886c3SLaurent Vivier     }
547*e55886c3SLaurent Vivier 
54888b2fef6SLaurent Vivier     if (next & M68K_DESC_WRITEPROT) {
54988b2fef6SLaurent Vivier         *prot &= ~PAGE_WRITE;
55088b2fef6SLaurent Vivier         if (access_type & ACCESS_STORE) {
55188b2fef6SLaurent Vivier             return -1;
55288b2fef6SLaurent Vivier         }
55388b2fef6SLaurent Vivier     }
55488b2fef6SLaurent Vivier     if (next & M68K_DESC_SUPERONLY) {
55588b2fef6SLaurent Vivier         if ((access_type & ACCESS_SUPER) == 0) {
55688b2fef6SLaurent Vivier             return -1;
55788b2fef6SLaurent Vivier         }
55888b2fef6SLaurent Vivier     }
55988b2fef6SLaurent Vivier 
56088b2fef6SLaurent Vivier     return 0;
56188b2fef6SLaurent Vivier }
56288b2fef6SLaurent Vivier 
56300b941e5SAndreas Färber hwaddr m68k_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
5644fcc562bSPaul Brook {
56588b2fef6SLaurent Vivier     M68kCPU *cpu = M68K_CPU(cs);
56688b2fef6SLaurent Vivier     CPUM68KState *env = &cpu->env;
56788b2fef6SLaurent Vivier     hwaddr phys_addr;
56888b2fef6SLaurent Vivier     int prot;
56988b2fef6SLaurent Vivier     int access_type;
57088b2fef6SLaurent Vivier     target_ulong page_size;
57188b2fef6SLaurent Vivier 
57288b2fef6SLaurent Vivier     if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
57388b2fef6SLaurent Vivier         /* MMU disabled */
5744fcc562bSPaul Brook         return addr;
5754fcc562bSPaul Brook     }
5764fcc562bSPaul Brook 
57788b2fef6SLaurent Vivier     access_type = ACCESS_DATA | ACCESS_DEBUG;
57888b2fef6SLaurent Vivier     if (env->sr & SR_S) {
57988b2fef6SLaurent Vivier         access_type |= ACCESS_SUPER;
58088b2fef6SLaurent Vivier     }
58188b2fef6SLaurent Vivier     if (get_physical_address(env, &phys_addr, &prot,
58288b2fef6SLaurent Vivier                              addr, access_type, &page_size) != 0) {
58388b2fef6SLaurent Vivier         return -1;
58488b2fef6SLaurent Vivier     }
58588b2fef6SLaurent Vivier     return phys_addr;
58688b2fef6SLaurent Vivier }
58788b2fef6SLaurent Vivier 
58898670d47SLaurent Vivier int m68k_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
58997b348e7SBlue Swirl                               int mmu_idx)
5900633879fSpbrook {
59188b2fef6SLaurent Vivier     M68kCPU *cpu = M68K_CPU(cs);
59288b2fef6SLaurent Vivier     CPUM68KState *env = &cpu->env;
59388b2fef6SLaurent Vivier     hwaddr physical;
5940633879fSpbrook     int prot;
59588b2fef6SLaurent Vivier     int access_type;
59688b2fef6SLaurent Vivier     int ret;
59788b2fef6SLaurent Vivier     target_ulong page_size;
5980633879fSpbrook 
59988b2fef6SLaurent Vivier     if ((env->mmu.tcr & M68K_TCR_ENABLED) == 0) {
60088b2fef6SLaurent Vivier         /* MMU disabled */
60188b2fef6SLaurent Vivier         tlb_set_page(cs, address & TARGET_PAGE_MASK,
60288b2fef6SLaurent Vivier                      address & TARGET_PAGE_MASK,
60388b2fef6SLaurent Vivier                      PAGE_READ | PAGE_WRITE | PAGE_EXEC,
60488b2fef6SLaurent Vivier                      mmu_idx, TARGET_PAGE_SIZE);
605d4c430a8SPaul Brook         return 0;
6060633879fSpbrook     }
6070633879fSpbrook 
60888b2fef6SLaurent Vivier     if (rw == 2) {
60988b2fef6SLaurent Vivier         access_type = ACCESS_CODE;
61088b2fef6SLaurent Vivier         rw = 0;
61188b2fef6SLaurent Vivier     } else {
61288b2fef6SLaurent Vivier         access_type = ACCESS_DATA;
61388b2fef6SLaurent Vivier         if (rw) {
61488b2fef6SLaurent Vivier             access_type |= ACCESS_STORE;
61588b2fef6SLaurent Vivier         }
61688b2fef6SLaurent Vivier     }
61788b2fef6SLaurent Vivier 
61888b2fef6SLaurent Vivier     if (mmu_idx != MMU_USER_IDX) {
61988b2fef6SLaurent Vivier         access_type |= ACCESS_SUPER;
62088b2fef6SLaurent Vivier     }
62188b2fef6SLaurent Vivier 
62288b2fef6SLaurent Vivier     ret = get_physical_address(&cpu->env, &physical, &prot,
62388b2fef6SLaurent Vivier                                address, access_type, &page_size);
62488b2fef6SLaurent Vivier     if (ret == 0) {
62588b2fef6SLaurent Vivier         address &= TARGET_PAGE_MASK;
62688b2fef6SLaurent Vivier         physical += address & (page_size - 1);
62788b2fef6SLaurent Vivier         tlb_set_page(cs, address, physical,
62888b2fef6SLaurent Vivier                      prot, mmu_idx, TARGET_PAGE_SIZE);
62988b2fef6SLaurent Vivier         return 0;
63088b2fef6SLaurent Vivier     }
63188b2fef6SLaurent Vivier     /* page fault */
63288b2fef6SLaurent Vivier     env->mmu.ssw = M68K_ATC_040;
63388b2fef6SLaurent Vivier     switch (size) {
63488b2fef6SLaurent Vivier     case 1:
63588b2fef6SLaurent Vivier         env->mmu.ssw |= M68K_BA_SIZE_BYTE;
63688b2fef6SLaurent Vivier         break;
63788b2fef6SLaurent Vivier     case 2:
63888b2fef6SLaurent Vivier         env->mmu.ssw |= M68K_BA_SIZE_WORD;
63988b2fef6SLaurent Vivier         break;
64088b2fef6SLaurent Vivier     case 4:
64188b2fef6SLaurent Vivier         env->mmu.ssw |= M68K_BA_SIZE_LONG;
64288b2fef6SLaurent Vivier         break;
64388b2fef6SLaurent Vivier     }
64488b2fef6SLaurent Vivier     if (access_type & ACCESS_SUPER) {
64588b2fef6SLaurent Vivier         env->mmu.ssw |= M68K_TM_040_SUPER;
64688b2fef6SLaurent Vivier     }
64788b2fef6SLaurent Vivier     if (access_type & ACCESS_CODE) {
64888b2fef6SLaurent Vivier         env->mmu.ssw |= M68K_TM_040_CODE;
64988b2fef6SLaurent Vivier     } else {
65088b2fef6SLaurent Vivier         env->mmu.ssw |= M68K_TM_040_DATA;
65188b2fef6SLaurent Vivier     }
65288b2fef6SLaurent Vivier     if (!(access_type & ACCESS_STORE)) {
65388b2fef6SLaurent Vivier         env->mmu.ssw |= M68K_RW_040;
65488b2fef6SLaurent Vivier     }
65588b2fef6SLaurent Vivier     env->mmu.ar = address;
65688b2fef6SLaurent Vivier     cs->exception_index = EXCP_ACCESS;
65788b2fef6SLaurent Vivier     return 1;
65888b2fef6SLaurent Vivier }
65988b2fef6SLaurent Vivier 
6600633879fSpbrook /* Notify CPU of a pending interrupt.  Prioritization and vectoring should
6610633879fSpbrook    be handled by the interrupt controller.  Real hardware only requests
6620633879fSpbrook    the vector when the interrupt is acknowledged by the CPU.  For
6630633879fSpbrook    simplicitly we calculate it when the interrupt is signalled.  */
664cb3fb38eSAndreas Färber void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector)
6650633879fSpbrook {
666d8ed887bSAndreas Färber     CPUState *cs = CPU(cpu);
667cb3fb38eSAndreas Färber     CPUM68KState *env = &cpu->env;
668cb3fb38eSAndreas Färber 
6690633879fSpbrook     env->pending_level = level;
6700633879fSpbrook     env->pending_vector = vector;
671d8ed887bSAndreas Färber     if (level) {
672c3affe56SAndreas Färber         cpu_interrupt(cs, CPU_INTERRUPT_HARD);
673d8ed887bSAndreas Färber     } else {
674d8ed887bSAndreas Färber         cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
675d8ed887bSAndreas Färber     }
6760633879fSpbrook }
6770633879fSpbrook 
6780633879fSpbrook #endif
679e1f3808eSpbrook 
680e1f3808eSpbrook uint32_t HELPER(bitrev)(uint32_t x)
681e1f3808eSpbrook {
682e1f3808eSpbrook     x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
683e1f3808eSpbrook     x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
684e1f3808eSpbrook     x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
685e1f3808eSpbrook     return bswap32(x);
686e1f3808eSpbrook }
687e1f3808eSpbrook 
688e1f3808eSpbrook uint32_t HELPER(ff1)(uint32_t x)
689e1f3808eSpbrook {
690e1f3808eSpbrook     int n;
691e1f3808eSpbrook     for (n = 32; x; n--)
692e1f3808eSpbrook         x >>= 1;
693e1f3808eSpbrook     return n;
694e1f3808eSpbrook }
695e1f3808eSpbrook 
696620c6cf6SRichard Henderson uint32_t HELPER(sats)(uint32_t val, uint32_t v)
697e1f3808eSpbrook {
698e1f3808eSpbrook     /* The result has the opposite sign to the original value.  */
699620c6cf6SRichard Henderson     if ((int32_t)v < 0) {
700e1f3808eSpbrook         val = (((int32_t)val) >> 31) ^ SIGNBIT;
701620c6cf6SRichard Henderson     }
702e1f3808eSpbrook     return val;
703e1f3808eSpbrook }
704e1f3808eSpbrook 
705d2f8fb8eSLaurent Vivier void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
706e1f3808eSpbrook {
707d2f8fb8eSLaurent Vivier     env->sr = sr & 0xffe0;
708d2f8fb8eSLaurent Vivier     cpu_m68k_set_ccr(env, sr);
709e1f3808eSpbrook     m68k_switch_sp(env);
710e1f3808eSpbrook }
711e1f3808eSpbrook 
712d2f8fb8eSLaurent Vivier void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
713d2f8fb8eSLaurent Vivier {
714d2f8fb8eSLaurent Vivier     cpu_m68k_set_sr(env, val);
715d2f8fb8eSLaurent Vivier }
716e1f3808eSpbrook 
717e1f3808eSpbrook /* MAC unit.  */
718e1f3808eSpbrook /* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
719e1f3808eSpbrook    take values,  others take register numbers and manipulate the contents
720e1f3808eSpbrook    in-place.  */
7212b3e3cfeSAndreas Färber void HELPER(mac_move)(CPUM68KState *env, uint32_t dest, uint32_t src)
722e1f3808eSpbrook {
723e1f3808eSpbrook     uint32_t mask;
724e1f3808eSpbrook     env->macc[dest] = env->macc[src];
725e1f3808eSpbrook     mask = MACSR_PAV0 << dest;
726e1f3808eSpbrook     if (env->macsr & (MACSR_PAV0 << src))
727e1f3808eSpbrook         env->macsr |= mask;
728e1f3808eSpbrook     else
729e1f3808eSpbrook         env->macsr &= ~mask;
730e1f3808eSpbrook }
731e1f3808eSpbrook 
7322b3e3cfeSAndreas Färber uint64_t HELPER(macmuls)(CPUM68KState *env, uint32_t op1, uint32_t op2)
733e1f3808eSpbrook {
734e1f3808eSpbrook     int64_t product;
735e1f3808eSpbrook     int64_t res;
736e1f3808eSpbrook 
737e1f3808eSpbrook     product = (uint64_t)op1 * op2;
738e1f3808eSpbrook     res = (product << 24) >> 24;
739e1f3808eSpbrook     if (res != product) {
740e1f3808eSpbrook         env->macsr |= MACSR_V;
741e1f3808eSpbrook         if (env->macsr & MACSR_OMC) {
742e1f3808eSpbrook             /* Make sure the accumulate operation overflows.  */
743e1f3808eSpbrook             if (product < 0)
744e1f3808eSpbrook                 res = ~(1ll << 50);
745e1f3808eSpbrook             else
746e1f3808eSpbrook                 res = 1ll << 50;
747e1f3808eSpbrook         }
748e1f3808eSpbrook     }
749e1f3808eSpbrook     return res;
750e1f3808eSpbrook }
751e1f3808eSpbrook 
7522b3e3cfeSAndreas Färber uint64_t HELPER(macmulu)(CPUM68KState *env, uint32_t op1, uint32_t op2)
753e1f3808eSpbrook {
754e1f3808eSpbrook     uint64_t product;
755e1f3808eSpbrook 
756e1f3808eSpbrook     product = (uint64_t)op1 * op2;
757e1f3808eSpbrook     if (product & (0xffffffull << 40)) {
758e1f3808eSpbrook         env->macsr |= MACSR_V;
759e1f3808eSpbrook         if (env->macsr & MACSR_OMC) {
760e1f3808eSpbrook             /* Make sure the accumulate operation overflows.  */
761e1f3808eSpbrook             product = 1ll << 50;
762e1f3808eSpbrook         } else {
763e1f3808eSpbrook             product &= ((1ull << 40) - 1);
764e1f3808eSpbrook         }
765e1f3808eSpbrook     }
766e1f3808eSpbrook     return product;
767e1f3808eSpbrook }
768e1f3808eSpbrook 
7692b3e3cfeSAndreas Färber uint64_t HELPER(macmulf)(CPUM68KState *env, uint32_t op1, uint32_t op2)
770e1f3808eSpbrook {
771e1f3808eSpbrook     uint64_t product;
772e1f3808eSpbrook     uint32_t remainder;
773e1f3808eSpbrook 
774e1f3808eSpbrook     product = (uint64_t)op1 * op2;
775e1f3808eSpbrook     if (env->macsr & MACSR_RT) {
776e1f3808eSpbrook         remainder = product & 0xffffff;
777e1f3808eSpbrook         product >>= 24;
778e1f3808eSpbrook         if (remainder > 0x800000)
779e1f3808eSpbrook             product++;
780e1f3808eSpbrook         else if (remainder == 0x800000)
781e1f3808eSpbrook             product += (product & 1);
782e1f3808eSpbrook     } else {
783e1f3808eSpbrook         product >>= 24;
784e1f3808eSpbrook     }
785e1f3808eSpbrook     return product;
786e1f3808eSpbrook }
787e1f3808eSpbrook 
7882b3e3cfeSAndreas Färber void HELPER(macsats)(CPUM68KState *env, uint32_t acc)
789e1f3808eSpbrook {
790e1f3808eSpbrook     int64_t tmp;
791e1f3808eSpbrook     int64_t result;
792e1f3808eSpbrook     tmp = env->macc[acc];
793e1f3808eSpbrook     result = ((tmp << 16) >> 16);
794e1f3808eSpbrook     if (result != tmp) {
795e1f3808eSpbrook         env->macsr |= MACSR_V;
796e1f3808eSpbrook     }
797e1f3808eSpbrook     if (env->macsr & MACSR_V) {
798e1f3808eSpbrook         env->macsr |= MACSR_PAV0 << acc;
799e1f3808eSpbrook         if (env->macsr & MACSR_OMC) {
800a1c7273bSStefan Weil             /* The result is saturated to 32 bits, despite overflow occurring
801e1f3808eSpbrook                at 48 bits.  Seems weird, but that's what the hardware docs
802e1f3808eSpbrook                say.  */
803e1f3808eSpbrook             result = (result >> 63) ^ 0x7fffffff;
804e1f3808eSpbrook         }
805e1f3808eSpbrook     }
806e1f3808eSpbrook     env->macc[acc] = result;
807e1f3808eSpbrook }
808e1f3808eSpbrook 
8092b3e3cfeSAndreas Färber void HELPER(macsatu)(CPUM68KState *env, uint32_t acc)
810e1f3808eSpbrook {
811e1f3808eSpbrook     uint64_t val;
812e1f3808eSpbrook 
813e1f3808eSpbrook     val = env->macc[acc];
814e1f3808eSpbrook     if (val & (0xffffull << 48)) {
815e1f3808eSpbrook         env->macsr |= MACSR_V;
816e1f3808eSpbrook     }
817e1f3808eSpbrook     if (env->macsr & MACSR_V) {
818e1f3808eSpbrook         env->macsr |= MACSR_PAV0 << acc;
819e1f3808eSpbrook         if (env->macsr & MACSR_OMC) {
820e1f3808eSpbrook             if (val > (1ull << 53))
821e1f3808eSpbrook                 val = 0;
822e1f3808eSpbrook             else
823e1f3808eSpbrook                 val = (1ull << 48) - 1;
824e1f3808eSpbrook         } else {
825e1f3808eSpbrook             val &= ((1ull << 48) - 1);
826e1f3808eSpbrook         }
827e1f3808eSpbrook     }
828e1f3808eSpbrook     env->macc[acc] = val;
829e1f3808eSpbrook }
830e1f3808eSpbrook 
8312b3e3cfeSAndreas Färber void HELPER(macsatf)(CPUM68KState *env, uint32_t acc)
832e1f3808eSpbrook {
833e1f3808eSpbrook     int64_t sum;
834e1f3808eSpbrook     int64_t result;
835e1f3808eSpbrook 
836e1f3808eSpbrook     sum = env->macc[acc];
837e1f3808eSpbrook     result = (sum << 16) >> 16;
838e1f3808eSpbrook     if (result != sum) {
839e1f3808eSpbrook         env->macsr |= MACSR_V;
840e1f3808eSpbrook     }
841e1f3808eSpbrook     if (env->macsr & MACSR_V) {
842e1f3808eSpbrook         env->macsr |= MACSR_PAV0 << acc;
843e1f3808eSpbrook         if (env->macsr & MACSR_OMC) {
844e1f3808eSpbrook             result = (result >> 63) ^ 0x7fffffffffffll;
845e1f3808eSpbrook         }
846e1f3808eSpbrook     }
847e1f3808eSpbrook     env->macc[acc] = result;
848e1f3808eSpbrook }
849e1f3808eSpbrook 
8502b3e3cfeSAndreas Färber void HELPER(mac_set_flags)(CPUM68KState *env, uint32_t acc)
851e1f3808eSpbrook {
852e1f3808eSpbrook     uint64_t val;
853e1f3808eSpbrook     val = env->macc[acc];
854c4162574SBlue Swirl     if (val == 0) {
855e1f3808eSpbrook         env->macsr |= MACSR_Z;
856c4162574SBlue Swirl     } else if (val & (1ull << 47)) {
857e1f3808eSpbrook         env->macsr |= MACSR_N;
858c4162574SBlue Swirl     }
859e1f3808eSpbrook     if (env->macsr & (MACSR_PAV0 << acc)) {
860e1f3808eSpbrook         env->macsr |= MACSR_V;
861e1f3808eSpbrook     }
862e1f3808eSpbrook     if (env->macsr & MACSR_FI) {
863e1f3808eSpbrook         val = ((int64_t)val) >> 40;
864e1f3808eSpbrook         if (val != 0 && val != -1)
865e1f3808eSpbrook             env->macsr |= MACSR_EV;
866e1f3808eSpbrook     } else if (env->macsr & MACSR_SU) {
867e1f3808eSpbrook         val = ((int64_t)val) >> 32;
868e1f3808eSpbrook         if (val != 0 && val != -1)
869e1f3808eSpbrook             env->macsr |= MACSR_EV;
870e1f3808eSpbrook     } else {
871e1f3808eSpbrook         if ((val >> 32) != 0)
872e1f3808eSpbrook             env->macsr |= MACSR_EV;
873e1f3808eSpbrook     }
874e1f3808eSpbrook }
875e1f3808eSpbrook 
876db3d7945SLaurent Vivier #define EXTSIGN(val, index) (     \
877db3d7945SLaurent Vivier     (index == 0) ? (int8_t)(val) : ((index == 1) ? (int16_t)(val) : (val)) \
878db3d7945SLaurent Vivier )
879620c6cf6SRichard Henderson 
880620c6cf6SRichard Henderson #define COMPUTE_CCR(op, x, n, z, v, c) {                                   \
881620c6cf6SRichard Henderson     switch (op) {                                                          \
882620c6cf6SRichard Henderson     case CC_OP_FLAGS:                                                      \
883620c6cf6SRichard Henderson         /* Everything in place.  */                                        \
884620c6cf6SRichard Henderson         break;                                                             \
885db3d7945SLaurent Vivier     case CC_OP_ADDB:                                                       \
886db3d7945SLaurent Vivier     case CC_OP_ADDW:                                                       \
887db3d7945SLaurent Vivier     case CC_OP_ADDL:                                                       \
888620c6cf6SRichard Henderson         res = n;                                                           \
889620c6cf6SRichard Henderson         src2 = v;                                                          \
890db3d7945SLaurent Vivier         src1 = EXTSIGN(res - src2, op - CC_OP_ADDB);                       \
891620c6cf6SRichard Henderson         c = x;                                                             \
892620c6cf6SRichard Henderson         z = n;                                                             \
893620c6cf6SRichard Henderson         v = (res ^ src1) & ~(src1 ^ src2);                                 \
894620c6cf6SRichard Henderson         break;                                                             \
895db3d7945SLaurent Vivier     case CC_OP_SUBB:                                                       \
896db3d7945SLaurent Vivier     case CC_OP_SUBW:                                                       \
897db3d7945SLaurent Vivier     case CC_OP_SUBL:                                                       \
898620c6cf6SRichard Henderson         res = n;                                                           \
899620c6cf6SRichard Henderson         src2 = v;                                                          \
900db3d7945SLaurent Vivier         src1 = EXTSIGN(res + src2, op - CC_OP_SUBB);                       \
901620c6cf6SRichard Henderson         c = x;                                                             \
902620c6cf6SRichard Henderson         z = n;                                                             \
903620c6cf6SRichard Henderson         v = (res ^ src1) & (src1 ^ src2);                                  \
904620c6cf6SRichard Henderson         break;                                                             \
905db3d7945SLaurent Vivier     case CC_OP_CMPB:                                                       \
906db3d7945SLaurent Vivier     case CC_OP_CMPW:                                                       \
907db3d7945SLaurent Vivier     case CC_OP_CMPL:                                                       \
908620c6cf6SRichard Henderson         src1 = n;                                                          \
909620c6cf6SRichard Henderson         src2 = v;                                                          \
910db3d7945SLaurent Vivier         res = EXTSIGN(src1 - src2, op - CC_OP_CMPB);                       \
911620c6cf6SRichard Henderson         n = res;                                                           \
912620c6cf6SRichard Henderson         z = res;                                                           \
913620c6cf6SRichard Henderson         c = src1 < src2;                                                   \
914620c6cf6SRichard Henderson         v = (res ^ src1) & (src1 ^ src2);                                  \
915620c6cf6SRichard Henderson         break;                                                             \
916620c6cf6SRichard Henderson     case CC_OP_LOGIC:                                                      \
917620c6cf6SRichard Henderson         c = v = 0;                                                         \
918620c6cf6SRichard Henderson         z = n;                                                             \
919620c6cf6SRichard Henderson         break;                                                             \
920620c6cf6SRichard Henderson     default:                                                               \
921620c6cf6SRichard Henderson         cpu_abort(CPU(m68k_env_get_cpu(env)), "Bad CC_OP %d", op);         \
922620c6cf6SRichard Henderson     }                                                                      \
923620c6cf6SRichard Henderson } while (0)
924620c6cf6SRichard Henderson 
925620c6cf6SRichard Henderson uint32_t cpu_m68k_get_ccr(CPUM68KState *env)
926e1f3808eSpbrook {
927620c6cf6SRichard Henderson     uint32_t x, c, n, z, v;
928620c6cf6SRichard Henderson     uint32_t res, src1, src2;
929620c6cf6SRichard Henderson 
930620c6cf6SRichard Henderson     x = env->cc_x;
931620c6cf6SRichard Henderson     n = env->cc_n;
932620c6cf6SRichard Henderson     z = env->cc_z;
933620c6cf6SRichard Henderson     v = env->cc_v;
934db3d7945SLaurent Vivier     c = env->cc_c;
935620c6cf6SRichard Henderson 
936620c6cf6SRichard Henderson     COMPUTE_CCR(env->cc_op, x, n, z, v, c);
937620c6cf6SRichard Henderson 
938620c6cf6SRichard Henderson     n = n >> 31;
939620c6cf6SRichard Henderson     z = (z == 0);
940db3d7945SLaurent Vivier     v = v >> 31;
941620c6cf6SRichard Henderson 
942620c6cf6SRichard Henderson     return x * CCF_X + n * CCF_N + z * CCF_Z + v * CCF_V + c * CCF_C;
943620c6cf6SRichard Henderson }
944620c6cf6SRichard Henderson 
945620c6cf6SRichard Henderson uint32_t HELPER(get_ccr)(CPUM68KState *env)
946620c6cf6SRichard Henderson {
947620c6cf6SRichard Henderson     return cpu_m68k_get_ccr(env);
948620c6cf6SRichard Henderson }
949620c6cf6SRichard Henderson 
950620c6cf6SRichard Henderson void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t ccr)
951620c6cf6SRichard Henderson {
952620c6cf6SRichard Henderson     env->cc_x = (ccr & CCF_X ? 1 : 0);
953620c6cf6SRichard Henderson     env->cc_n = (ccr & CCF_N ? -1 : 0);
954620c6cf6SRichard Henderson     env->cc_z = (ccr & CCF_Z ? 0 : 1);
955620c6cf6SRichard Henderson     env->cc_v = (ccr & CCF_V ? -1 : 0);
956620c6cf6SRichard Henderson     env->cc_c = (ccr & CCF_C ? 1 : 0);
957620c6cf6SRichard Henderson     env->cc_op = CC_OP_FLAGS;
958620c6cf6SRichard Henderson }
959620c6cf6SRichard Henderson 
960620c6cf6SRichard Henderson void HELPER(set_ccr)(CPUM68KState *env, uint32_t ccr)
961620c6cf6SRichard Henderson {
962620c6cf6SRichard Henderson     cpu_m68k_set_ccr(env, ccr);
963620c6cf6SRichard Henderson }
964620c6cf6SRichard Henderson 
965620c6cf6SRichard Henderson void HELPER(flush_flags)(CPUM68KState *env, uint32_t cc_op)
966620c6cf6SRichard Henderson {
967620c6cf6SRichard Henderson     uint32_t res, src1, src2;
968620c6cf6SRichard Henderson 
969620c6cf6SRichard Henderson     COMPUTE_CCR(cc_op, env->cc_x, env->cc_n, env->cc_z, env->cc_v, env->cc_c);
970620c6cf6SRichard Henderson     env->cc_op = CC_OP_FLAGS;
971e1f3808eSpbrook }
972e1f3808eSpbrook 
9732b3e3cfeSAndreas Färber uint32_t HELPER(get_macf)(CPUM68KState *env, uint64_t val)
974e1f3808eSpbrook {
975e1f3808eSpbrook     int rem;
976e1f3808eSpbrook     uint32_t result;
977e1f3808eSpbrook 
978e1f3808eSpbrook     if (env->macsr & MACSR_SU) {
979e1f3808eSpbrook         /* 16-bit rounding.  */
980e1f3808eSpbrook         rem = val & 0xffffff;
981e1f3808eSpbrook         val = (val >> 24) & 0xffffu;
982e1f3808eSpbrook         if (rem > 0x800000)
983e1f3808eSpbrook             val++;
984e1f3808eSpbrook         else if (rem == 0x800000)
985e1f3808eSpbrook             val += (val & 1);
986e1f3808eSpbrook     } else if (env->macsr & MACSR_RT) {
987e1f3808eSpbrook         /* 32-bit rounding.  */
988e1f3808eSpbrook         rem = val & 0xff;
989e1f3808eSpbrook         val >>= 8;
990e1f3808eSpbrook         if (rem > 0x80)
991e1f3808eSpbrook             val++;
992e1f3808eSpbrook         else if (rem == 0x80)
993e1f3808eSpbrook             val += (val & 1);
994e1f3808eSpbrook     } else {
995e1f3808eSpbrook         /* No rounding.  */
996e1f3808eSpbrook         val >>= 8;
997e1f3808eSpbrook     }
998e1f3808eSpbrook     if (env->macsr & MACSR_OMC) {
999e1f3808eSpbrook         /* Saturate.  */
1000e1f3808eSpbrook         if (env->macsr & MACSR_SU) {
1001e1f3808eSpbrook             if (val != (uint16_t) val) {
1002e1f3808eSpbrook                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
1003e1f3808eSpbrook             } else {
1004e1f3808eSpbrook                 result = val & 0xffff;
1005e1f3808eSpbrook             }
1006e1f3808eSpbrook         } else {
1007e1f3808eSpbrook             if (val != (uint32_t)val) {
1008e1f3808eSpbrook                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
1009e1f3808eSpbrook             } else {
1010e1f3808eSpbrook                 result = (uint32_t)val;
1011e1f3808eSpbrook             }
1012e1f3808eSpbrook         }
1013e1f3808eSpbrook     } else {
1014e1f3808eSpbrook         /* No saturation.  */
1015e1f3808eSpbrook         if (env->macsr & MACSR_SU) {
1016e1f3808eSpbrook             result = val & 0xffff;
1017e1f3808eSpbrook         } else {
1018e1f3808eSpbrook             result = (uint32_t)val;
1019e1f3808eSpbrook         }
1020e1f3808eSpbrook     }
1021e1f3808eSpbrook     return result;
1022e1f3808eSpbrook }
1023e1f3808eSpbrook 
1024e1f3808eSpbrook uint32_t HELPER(get_macs)(uint64_t val)
1025e1f3808eSpbrook {
1026e1f3808eSpbrook     if (val == (int32_t)val) {
1027e1f3808eSpbrook         return (int32_t)val;
1028e1f3808eSpbrook     } else {
1029e1f3808eSpbrook         return (val >> 61) ^ ~SIGNBIT;
1030e1f3808eSpbrook     }
1031e1f3808eSpbrook }
1032e1f3808eSpbrook 
1033e1f3808eSpbrook uint32_t HELPER(get_macu)(uint64_t val)
1034e1f3808eSpbrook {
1035e1f3808eSpbrook     if ((val >> 32) == 0) {
1036e1f3808eSpbrook         return (uint32_t)val;
1037e1f3808eSpbrook     } else {
1038e1f3808eSpbrook         return 0xffffffffu;
1039e1f3808eSpbrook     }
1040e1f3808eSpbrook }
1041e1f3808eSpbrook 
10422b3e3cfeSAndreas Färber uint32_t HELPER(get_mac_extf)(CPUM68KState *env, uint32_t acc)
1043e1f3808eSpbrook {
1044e1f3808eSpbrook     uint32_t val;
1045e1f3808eSpbrook     val = env->macc[acc] & 0x00ff;
10465ce747cfSPaolo Bonzini     val |= (env->macc[acc] >> 32) & 0xff00;
1047e1f3808eSpbrook     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
1048e1f3808eSpbrook     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
1049e1f3808eSpbrook     return val;
1050e1f3808eSpbrook }
1051e1f3808eSpbrook 
10522b3e3cfeSAndreas Färber uint32_t HELPER(get_mac_exti)(CPUM68KState *env, uint32_t acc)
1053e1f3808eSpbrook {
1054e1f3808eSpbrook     uint32_t val;
1055e1f3808eSpbrook     val = (env->macc[acc] >> 32) & 0xffff;
1056e1f3808eSpbrook     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
1057e1f3808eSpbrook     return val;
1058e1f3808eSpbrook }
1059e1f3808eSpbrook 
10602b3e3cfeSAndreas Färber void HELPER(set_mac_extf)(CPUM68KState *env, uint32_t val, uint32_t acc)
1061e1f3808eSpbrook {
1062e1f3808eSpbrook     int64_t res;
1063e1f3808eSpbrook     int32_t tmp;
1064e1f3808eSpbrook     res = env->macc[acc] & 0xffffffff00ull;
1065e1f3808eSpbrook     tmp = (int16_t)(val & 0xff00);
1066e1f3808eSpbrook     res |= ((int64_t)tmp) << 32;
1067e1f3808eSpbrook     res |= val & 0xff;
1068e1f3808eSpbrook     env->macc[acc] = res;
1069e1f3808eSpbrook     res = env->macc[acc + 1] & 0xffffffff00ull;
1070e1f3808eSpbrook     tmp = (val & 0xff000000);
1071e1f3808eSpbrook     res |= ((int64_t)tmp) << 16;
1072e1f3808eSpbrook     res |= (val >> 16) & 0xff;
1073e1f3808eSpbrook     env->macc[acc + 1] = res;
1074e1f3808eSpbrook }
1075e1f3808eSpbrook 
10762b3e3cfeSAndreas Färber void HELPER(set_mac_exts)(CPUM68KState *env, uint32_t val, uint32_t acc)
1077e1f3808eSpbrook {
1078e1f3808eSpbrook     int64_t res;
1079e1f3808eSpbrook     int32_t tmp;
1080e1f3808eSpbrook     res = (uint32_t)env->macc[acc];
1081e1f3808eSpbrook     tmp = (int16_t)val;
1082e1f3808eSpbrook     res |= ((int64_t)tmp) << 32;
1083e1f3808eSpbrook     env->macc[acc] = res;
1084e1f3808eSpbrook     res = (uint32_t)env->macc[acc + 1];
1085e1f3808eSpbrook     tmp = val & 0xffff0000;
1086e1f3808eSpbrook     res |= (int64_t)tmp << 16;
1087e1f3808eSpbrook     env->macc[acc + 1] = res;
1088e1f3808eSpbrook }
1089e1f3808eSpbrook 
10902b3e3cfeSAndreas Färber void HELPER(set_mac_extu)(CPUM68KState *env, uint32_t val, uint32_t acc)
1091e1f3808eSpbrook {
1092e1f3808eSpbrook     uint64_t res;
1093e1f3808eSpbrook     res = (uint32_t)env->macc[acc];
1094e1f3808eSpbrook     res |= ((uint64_t)(val & 0xffff)) << 32;
1095e1f3808eSpbrook     env->macc[acc] = res;
1096e1f3808eSpbrook     res = (uint32_t)env->macc[acc + 1];
1097e1f3808eSpbrook     res |= (uint64_t)(val & 0xffff0000) << 16;
1098e1f3808eSpbrook     env->macc[acc + 1] = res;
1099e1f3808eSpbrook }
11000bdb2b3bSLaurent Vivier 
11010bdb2b3bSLaurent Vivier #if defined(CONFIG_SOFTMMU)
1102*e55886c3SLaurent Vivier void HELPER(ptest)(CPUM68KState *env, uint32_t addr, uint32_t is_read)
1103*e55886c3SLaurent Vivier {
1104*e55886c3SLaurent Vivier     M68kCPU *cpu = m68k_env_get_cpu(env);
1105*e55886c3SLaurent Vivier     CPUState *cs = CPU(cpu);
1106*e55886c3SLaurent Vivier     hwaddr physical;
1107*e55886c3SLaurent Vivier     int access_type;
1108*e55886c3SLaurent Vivier     int prot;
1109*e55886c3SLaurent Vivier     int ret;
1110*e55886c3SLaurent Vivier     target_ulong page_size;
1111*e55886c3SLaurent Vivier 
1112*e55886c3SLaurent Vivier     access_type = ACCESS_PTEST;
1113*e55886c3SLaurent Vivier     if (env->dfc & 4) {
1114*e55886c3SLaurent Vivier         access_type |= ACCESS_SUPER;
1115*e55886c3SLaurent Vivier     }
1116*e55886c3SLaurent Vivier     if ((env->dfc & 3) == 2) {
1117*e55886c3SLaurent Vivier         access_type |= ACCESS_CODE;
1118*e55886c3SLaurent Vivier     }
1119*e55886c3SLaurent Vivier     if (!is_read) {
1120*e55886c3SLaurent Vivier         access_type |= ACCESS_STORE;
1121*e55886c3SLaurent Vivier     }
1122*e55886c3SLaurent Vivier 
1123*e55886c3SLaurent Vivier     env->mmu.mmusr = 0;
1124*e55886c3SLaurent Vivier     env->mmu.ssw = 0;
1125*e55886c3SLaurent Vivier     ret = get_physical_address(env, &physical, &prot, addr,
1126*e55886c3SLaurent Vivier                                access_type, &page_size);
1127*e55886c3SLaurent Vivier     if (ret == 0) {
1128*e55886c3SLaurent Vivier         addr &= TARGET_PAGE_MASK;
1129*e55886c3SLaurent Vivier         physical += addr & (page_size - 1);
1130*e55886c3SLaurent Vivier         tlb_set_page(cs, addr, physical,
1131*e55886c3SLaurent Vivier                      prot, access_type & ACCESS_SUPER ?
1132*e55886c3SLaurent Vivier                      MMU_KERNEL_IDX : MMU_USER_IDX, page_size);
1133*e55886c3SLaurent Vivier     }
1134*e55886c3SLaurent Vivier }
1135*e55886c3SLaurent Vivier 
1136*e55886c3SLaurent Vivier void HELPER(pflush)(CPUM68KState *env, uint32_t addr, uint32_t opmode)
1137*e55886c3SLaurent Vivier {
1138*e55886c3SLaurent Vivier     M68kCPU *cpu = m68k_env_get_cpu(env);
1139*e55886c3SLaurent Vivier 
1140*e55886c3SLaurent Vivier     switch (opmode) {
1141*e55886c3SLaurent Vivier     case 0: /* Flush page entry if not global */
1142*e55886c3SLaurent Vivier     case 1: /* Flush page entry */
1143*e55886c3SLaurent Vivier         tlb_flush_page(CPU(cpu), addr);
1144*e55886c3SLaurent Vivier         break;
1145*e55886c3SLaurent Vivier     case 2: /* Flush all except global entries */
1146*e55886c3SLaurent Vivier         tlb_flush(CPU(cpu));
1147*e55886c3SLaurent Vivier         break;
1148*e55886c3SLaurent Vivier     case 3: /* Flush all entries */
1149*e55886c3SLaurent Vivier         tlb_flush(CPU(cpu));
1150*e55886c3SLaurent Vivier         break;
1151*e55886c3SLaurent Vivier     }
1152*e55886c3SLaurent Vivier }
1153*e55886c3SLaurent Vivier 
11540bdb2b3bSLaurent Vivier void HELPER(reset)(CPUM68KState *env)
11550bdb2b3bSLaurent Vivier {
11560bdb2b3bSLaurent Vivier     /* FIXME: reset all except CPU */
11570bdb2b3bSLaurent Vivier }
11580bdb2b3bSLaurent Vivier #endif
1159