symbian-qemu-0.9.1-12/qemu-symbian-svp/target-m68k/helper.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  *  m68k op helpers
       
     3  *
       
     4  *  Copyright (c) 2006-2007 CodeSourcery
       
     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
       
    18  * License along with this library; if not, write to the Free Software
       
    19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    20  */
       
    21 
       
    22 #include <stdio.h>
       
    23 #include <string.h>
       
    24 
       
    25 #include "config.h"
       
    26 #include "cpu.h"
       
    27 #include "exec-all.h"
       
    28 #include "qemu-common.h"
       
    29 #include "gdbstub.h"
       
    30 
       
    31 #include "helpers.h"
       
    32 
       
    33 #define SIGNBIT (1u << 31)
       
    34 
       
    35 enum m68k_cpuid {
       
    36     M68K_CPUID_M5206,
       
    37     M68K_CPUID_M5208,
       
    38     M68K_CPUID_CFV4E,
       
    39     M68K_CPUID_ANY,
       
    40 };
       
    41 
       
    42 typedef struct m68k_def_t m68k_def_t;
       
    43 
       
    44 struct m68k_def_t {
       
    45     const char * name;
       
    46     enum m68k_cpuid id;
       
    47 };
       
    48 
       
    49 static m68k_def_t m68k_cpu_defs[] = {
       
    50     {"m5206", M68K_CPUID_M5206},
       
    51     {"m5208", M68K_CPUID_M5208},
       
    52     {"cfv4e", M68K_CPUID_CFV4E},
       
    53     {"any", M68K_CPUID_ANY},
       
    54     {NULL, 0},
       
    55 };
       
    56 
       
    57 void m68k_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
       
    58 {
       
    59     int i;
       
    60 
       
    61     (*cpu_fprintf)(f, "Available CPUs:\n");
       
    62     for (i = 0; m68k_cpu_defs[i].name; i++) {
       
    63         (*cpu_fprintf)(f, "  %s\n", m68k_cpu_defs[i].name);
       
    64     }
       
    65 }
       
    66 
       
    67 
       
    68 static int fpu_gdb_get_reg(CPUState *env, uint8_t *mem_buf, int n)
       
    69 {
       
    70     if (n < 8) {
       
    71         stfq_p(mem_buf, env->fregs[n]);
       
    72         return 8;
       
    73     }
       
    74     if (n < 11) {
       
    75         /* FP control registers (not implemented)  */
       
    76         memset(mem_buf, 0, 4);
       
    77         return 4;
       
    78     }
       
    79     return 0;
       
    80 }
       
    81 
       
    82 static int fpu_gdb_set_reg(CPUState *env, uint8_t *mem_buf, int n)
       
    83 {
       
    84     if (n < 8) {
       
    85         env->fregs[n] = ldfq_p(mem_buf);
       
    86         return 8;
       
    87     }
       
    88     if (n < 11) {
       
    89         /* FP control registers (not implemented)  */
       
    90         return 4;
       
    91     }
       
    92     return 0;
       
    93 }
       
    94 
       
    95 static void m68k_set_feature(CPUM68KState *env, int feature)
       
    96 {
       
    97     env->features |= (1u << feature);
       
    98 }
       
    99 
       
   100 static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
       
   101 {
       
   102     m68k_def_t *def;
       
   103 
       
   104     for (def = m68k_cpu_defs; def->name; def++) {
       
   105         if (strcmp(def->name, name) == 0)
       
   106             break;
       
   107     }
       
   108     if (!def->name)
       
   109         return -1;
       
   110 
       
   111     switch (def->id) {
       
   112     case M68K_CPUID_M5206:
       
   113         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
       
   114         break;
       
   115     case M68K_CPUID_M5208:
       
   116         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
       
   117         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
       
   118         m68k_set_feature(env, M68K_FEATURE_BRAL);
       
   119         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
       
   120         m68k_set_feature(env, M68K_FEATURE_USP);
       
   121         break;
       
   122     case M68K_CPUID_CFV4E:
       
   123         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
       
   124         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
       
   125         m68k_set_feature(env, M68K_FEATURE_BRAL);
       
   126         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
       
   127         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
       
   128         m68k_set_feature(env, M68K_FEATURE_USP);
       
   129         break;
       
   130     case M68K_CPUID_ANY:
       
   131         m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
       
   132         m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
       
   133         m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
       
   134         m68k_set_feature(env, M68K_FEATURE_BRAL);
       
   135         m68k_set_feature(env, M68K_FEATURE_CF_FPU);
       
   136         /* MAC and EMAC are mututally exclusive, so pick EMAC.
       
   137            It's mostly backwards compatible.  */
       
   138         m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
       
   139         m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
       
   140         m68k_set_feature(env, M68K_FEATURE_USP);
       
   141         m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
       
   142         m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
       
   143         break;
       
   144     }
       
   145 
       
   146     register_m68k_insns(env);
       
   147     if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
       
   148         gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
       
   149                                  11, "cf-fp.xml", 18);
       
   150     }
       
   151     /* TODO: Add [E]MAC registers.  */
       
   152     return 0;
       
   153 }
       
   154 
       
   155 void cpu_reset(CPUM68KState *env)
       
   156 {
       
   157     memset(env, 0, offsetof(CPUM68KState, breakpoints));
       
   158 #if !defined (CONFIG_USER_ONLY)
       
   159     env->sr = 0x2700;
       
   160 #endif
       
   161     m68k_switch_sp(env);
       
   162     /* ??? FP regs should be initialized to NaN.  */
       
   163     env->cc_op = CC_OP_FLAGS;
       
   164     /* TODO: We should set PC from the interrupt vector.  */
       
   165     env->pc = 0;
       
   166     tlb_flush(env, 1);
       
   167 }
       
   168 
       
   169 CPUM68KState *cpu_m68k_init(const char *cpu_model)
       
   170 {
       
   171     CPUM68KState *env;
       
   172     static int inited;
       
   173 
       
   174     env = qemu_mallocz(sizeof(CPUM68KState));
       
   175     if (!env)
       
   176         return NULL;
       
   177     cpu_exec_init(env);
       
   178     if (!inited) {
       
   179         inited = 1;
       
   180         m68k_tcg_init();
       
   181     }
       
   182 
       
   183     env->cpu_model_str = cpu_model;
       
   184 
       
   185     if (cpu_m68k_set_model(env, cpu_model) < 0) {
       
   186         cpu_m68k_close(env);
       
   187         return NULL;
       
   188     }
       
   189 
       
   190     cpu_reset(env);
       
   191     return env;
       
   192 }
       
   193 
       
   194 void cpu_m68k_close(CPUM68KState *env)
       
   195 {
       
   196     qemu_free(env);
       
   197 }
       
   198 
       
   199 void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
       
   200 {
       
   201     int flags;
       
   202     uint32_t src;
       
   203     uint32_t dest;
       
   204     uint32_t tmp;
       
   205 
       
   206 #define HIGHBIT 0x80000000u
       
   207 
       
   208 #define SET_NZ(x) do { \
       
   209     if ((x) == 0) \
       
   210         flags |= CCF_Z; \
       
   211     else if ((int32_t)(x) < 0) \
       
   212         flags |= CCF_N; \
       
   213     } while (0)
       
   214 
       
   215 #define SET_FLAGS_SUB(type, utype) do { \
       
   216     SET_NZ((type)dest); \
       
   217     tmp = dest + src; \
       
   218     if ((utype) tmp < (utype) src) \
       
   219         flags |= CCF_C; \
       
   220     if ((1u << (sizeof(type) * 8 - 1)) & (tmp ^ dest) & (tmp ^ src)) \
       
   221         flags |= CCF_V; \
       
   222     } while (0)
       
   223 
       
   224     flags = 0;
       
   225     src = env->cc_src;
       
   226     dest = env->cc_dest;
       
   227     switch (cc_op) {
       
   228     case CC_OP_FLAGS:
       
   229         flags = dest;
       
   230         break;
       
   231     case CC_OP_LOGIC:
       
   232         SET_NZ(dest);
       
   233         break;
       
   234     case CC_OP_ADD:
       
   235         SET_NZ(dest);
       
   236         if (dest < src)
       
   237             flags |= CCF_C;
       
   238         tmp = dest - src;
       
   239         if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
       
   240             flags |= CCF_V;
       
   241         break;
       
   242     case CC_OP_SUB:
       
   243         SET_FLAGS_SUB(int32_t, uint32_t);
       
   244         break;
       
   245     case CC_OP_CMPB:
       
   246         SET_FLAGS_SUB(int8_t, uint8_t);
       
   247         break;
       
   248     case CC_OP_CMPW:
       
   249         SET_FLAGS_SUB(int16_t, uint16_t);
       
   250         break;
       
   251     case CC_OP_ADDX:
       
   252         SET_NZ(dest);
       
   253         if (dest <= src)
       
   254             flags |= CCF_C;
       
   255         tmp = dest - src - 1;
       
   256         if (HIGHBIT & (src ^ dest) & ~(tmp ^ src))
       
   257             flags |= CCF_V;
       
   258         break;
       
   259     case CC_OP_SUBX:
       
   260         SET_NZ(dest);
       
   261         tmp = dest + src + 1;
       
   262         if (tmp <= src)
       
   263             flags |= CCF_C;
       
   264         if (HIGHBIT & (tmp ^ dest) & (tmp ^ src))
       
   265             flags |= CCF_V;
       
   266         break;
       
   267     case CC_OP_SHIFT:
       
   268         SET_NZ(dest);
       
   269         if (src)
       
   270             flags |= CCF_C;
       
   271         break;
       
   272     default:
       
   273         cpu_abort(env, "Bad CC_OP %d", cc_op);
       
   274     }
       
   275     env->cc_op = CC_OP_FLAGS;
       
   276     env->cc_dest = flags;
       
   277 }
       
   278 
       
   279 void HELPER(movec)(CPUM68KState *env, uint32_t reg, uint32_t val)
       
   280 {
       
   281     switch (reg) {
       
   282     case 0x02: /* CACR */
       
   283         env->cacr = val;
       
   284         m68k_switch_sp(env);
       
   285         break;
       
   286     case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */
       
   287         /* TODO: Implement Access Control Registers.  */
       
   288         break;
       
   289     case 0x801: /* VBR */
       
   290         env->vbr = val;
       
   291         break;
       
   292     /* TODO: Implement control registers.  */
       
   293     default:
       
   294         cpu_abort(env, "Unimplemented control register write 0x%x = 0x%x\n",
       
   295                   reg, val);
       
   296     }
       
   297 }
       
   298 
       
   299 void HELPER(set_macsr)(CPUM68KState *env, uint32_t val)
       
   300 {
       
   301     uint32_t acc;
       
   302     int8_t exthigh;
       
   303     uint8_t extlow;
       
   304     uint64_t regval;
       
   305     int i;
       
   306     if ((env->macsr ^ val) & (MACSR_FI | MACSR_SU)) {
       
   307         for (i = 0; i < 4; i++) {
       
   308             regval = env->macc[i];
       
   309             exthigh = regval >> 40;
       
   310             if (env->macsr & MACSR_FI) {
       
   311                 acc = regval >> 8;
       
   312                 extlow = regval;
       
   313             } else {
       
   314                 acc = regval;
       
   315                 extlow = regval >> 32;
       
   316             }
       
   317             if (env->macsr & MACSR_FI) {
       
   318                 regval = (((uint64_t)acc) << 8) | extlow;
       
   319                 regval |= ((int64_t)exthigh) << 40;
       
   320             } else if (env->macsr & MACSR_SU) {
       
   321                 regval = acc | (((int64_t)extlow) << 32);
       
   322                 regval |= ((int64_t)exthigh) << 40;
       
   323             } else {
       
   324                 regval = acc | (((uint64_t)extlow) << 32);
       
   325                 regval |= ((uint64_t)(uint8_t)exthigh) << 40;
       
   326             }
       
   327             env->macc[i] = regval;
       
   328         }
       
   329     }
       
   330     env->macsr = val;
       
   331 }
       
   332 
       
   333 void m68k_switch_sp(CPUM68KState *env)
       
   334 {
       
   335     int new_sp;
       
   336 
       
   337     env->sp[env->current_sp] = env->aregs[7];
       
   338     new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP)
       
   339              ? M68K_SSP : M68K_USP;
       
   340     env->aregs[7] = env->sp[new_sp];
       
   341     env->current_sp = new_sp;
       
   342 }
       
   343 
       
   344 /* MMU */
       
   345 
       
   346 /* TODO: This will need fixing once the MMU is implemented.  */
       
   347 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
       
   348 {
       
   349     return addr;
       
   350 }
       
   351 
       
   352 #if defined(CONFIG_USER_ONLY)
       
   353 
       
   354 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
       
   355                                int mmu_idx, int is_softmmu)
       
   356 {
       
   357     env->exception_index = EXCP_ACCESS;
       
   358     env->mmu.ar = address;
       
   359     return 1;
       
   360 }
       
   361 
       
   362 #else
       
   363 
       
   364 int cpu_m68k_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
       
   365                                int mmu_idx, int is_softmmu)
       
   366 {
       
   367     int prot;
       
   368 
       
   369     address &= TARGET_PAGE_MASK;
       
   370     prot = PAGE_READ | PAGE_WRITE;
       
   371     return tlb_set_page(env, address, address, prot, mmu_idx, is_softmmu);
       
   372 }
       
   373 
       
   374 /* Notify CPU of a pending interrupt.  Prioritization and vectoring should
       
   375    be handled by the interrupt controller.  Real hardware only requests
       
   376    the vector when the interrupt is acknowledged by the CPU.  For
       
   377    simplicitly we calculate it when the interrupt is signalled.  */
       
   378 void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector)
       
   379 {
       
   380     env->pending_level = level;
       
   381     env->pending_vector = vector;
       
   382     if (level)
       
   383         cpu_interrupt(env, CPU_INTERRUPT_HARD);
       
   384     else
       
   385         cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
       
   386 }
       
   387 
       
   388 #endif
       
   389 
       
   390 uint32_t HELPER(bitrev)(uint32_t x)
       
   391 {
       
   392     x = ((x >> 1) & 0x55555555u) | ((x << 1) & 0xaaaaaaaau);
       
   393     x = ((x >> 2) & 0x33333333u) | ((x << 2) & 0xccccccccu);
       
   394     x = ((x >> 4) & 0x0f0f0f0fu) | ((x << 4) & 0xf0f0f0f0u);
       
   395     return bswap32(x);
       
   396 }
       
   397 
       
   398 uint32_t HELPER(ff1)(uint32_t x)
       
   399 {
       
   400     int n;
       
   401     for (n = 32; x; n--)
       
   402         x >>= 1;
       
   403     return n;
       
   404 }
       
   405 
       
   406 uint32_t HELPER(sats)(uint32_t val, uint32_t ccr)
       
   407 {
       
   408     /* The result has the opposite sign to the original value.  */
       
   409     if (ccr & CCF_V)
       
   410         val = (((int32_t)val) >> 31) ^ SIGNBIT;
       
   411     return val;
       
   412 }
       
   413 
       
   414 uint32_t HELPER(subx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
       
   415 {
       
   416     uint32_t res;
       
   417     uint32_t old_flags;
       
   418 
       
   419     old_flags = env->cc_dest;
       
   420     if (env->cc_x) {
       
   421         env->cc_x = (op1 <= op2);
       
   422         env->cc_op = CC_OP_SUBX;
       
   423         res = op1 - (op2 + 1);
       
   424     } else {
       
   425         env->cc_x = (op1 < op2);
       
   426         env->cc_op = CC_OP_SUB;
       
   427         res = op1 - op2;
       
   428     }
       
   429     env->cc_dest = res;
       
   430     env->cc_src = op2;
       
   431     cpu_m68k_flush_flags(env, env->cc_op);
       
   432     /* !Z is sticky.  */
       
   433     env->cc_dest &= (old_flags | ~CCF_Z);
       
   434     return res;
       
   435 }
       
   436 
       
   437 uint32_t HELPER(addx_cc)(CPUState *env, uint32_t op1, uint32_t op2)
       
   438 {
       
   439     uint32_t res;
       
   440     uint32_t old_flags;
       
   441 
       
   442     old_flags = env->cc_dest;
       
   443     if (env->cc_x) {
       
   444         res = op1 + op2 + 1;
       
   445         env->cc_x = (res <= op2);
       
   446         env->cc_op = CC_OP_ADDX;
       
   447     } else {
       
   448         res = op1 + op2;
       
   449         env->cc_x = (res < op2);
       
   450         env->cc_op = CC_OP_ADD;
       
   451     }
       
   452     env->cc_dest = res;
       
   453     env->cc_src = op2;
       
   454     cpu_m68k_flush_flags(env, env->cc_op);
       
   455     /* !Z is sticky.  */
       
   456     env->cc_dest &= (old_flags | ~CCF_Z);
       
   457     return res;
       
   458 }
       
   459 
       
   460 uint32_t HELPER(xflag_lt)(uint32_t a, uint32_t b)
       
   461 {
       
   462     return a < b;
       
   463 }
       
   464 
       
   465 uint32_t HELPER(btest)(uint32_t x)
       
   466 {
       
   467     return x != 0;
       
   468 }
       
   469 
       
   470 void HELPER(set_sr)(CPUState *env, uint32_t val)
       
   471 {
       
   472     env->sr = val & 0xffff;
       
   473     m68k_switch_sp(env);
       
   474 }
       
   475 
       
   476 uint32_t HELPER(shl_cc)(CPUState *env, uint32_t val, uint32_t shift)
       
   477 {
       
   478     uint32_t result;
       
   479     uint32_t cf;
       
   480 
       
   481     shift &= 63;
       
   482     if (shift == 0) {
       
   483         result = val;
       
   484         cf = env->cc_src & CCF_C;
       
   485     } else if (shift < 32) {
       
   486         result = val << shift;
       
   487         cf = (val >> (32 - shift)) & 1;
       
   488     } else if (shift == 32) {
       
   489         result = 0;
       
   490         cf = val & 1;
       
   491     } else /* shift > 32 */ {
       
   492         result = 0;
       
   493         cf = 0;
       
   494     }
       
   495     env->cc_src = cf;
       
   496     env->cc_x = (cf != 0);
       
   497     env->cc_dest = result;
       
   498     return result;
       
   499 }
       
   500 
       
   501 uint32_t HELPER(shr_cc)(CPUState *env, uint32_t val, uint32_t shift)
       
   502 {
       
   503     uint32_t result;
       
   504     uint32_t cf;
       
   505 
       
   506     shift &= 63;
       
   507     if (shift == 0) {
       
   508         result = val;
       
   509         cf = env->cc_src & CCF_C;
       
   510     } else if (shift < 32) {
       
   511         result = val >> shift;
       
   512         cf = (val >> (shift - 1)) & 1;
       
   513     } else if (shift == 32) {
       
   514         result = 0;
       
   515         cf = val >> 31;
       
   516     } else /* shift > 32 */ {
       
   517         result = 0;
       
   518         cf = 0;
       
   519     }
       
   520     env->cc_src = cf;
       
   521     env->cc_x = (cf != 0);
       
   522     env->cc_dest = result;
       
   523     return result;
       
   524 }
       
   525 
       
   526 uint32_t HELPER(sar_cc)(CPUState *env, uint32_t val, uint32_t shift)
       
   527 {
       
   528     uint32_t result;
       
   529     uint32_t cf;
       
   530 
       
   531     shift &= 63;
       
   532     if (shift == 0) {
       
   533         result = val;
       
   534         cf = (env->cc_src & CCF_C) != 0;
       
   535     } else if (shift < 32) {
       
   536         result = (int32_t)val >> shift;
       
   537         cf = (val >> (shift - 1)) & 1;
       
   538     } else /* shift >= 32 */ {
       
   539         result = (int32_t)val >> 31;
       
   540         cf = val >> 31;
       
   541     }
       
   542     env->cc_src = cf;
       
   543     env->cc_x = cf;
       
   544     env->cc_dest = result;
       
   545     return result;
       
   546 }
       
   547 
       
   548 /* FPU helpers.  */
       
   549 uint32_t HELPER(f64_to_i32)(CPUState *env, float64 val)
       
   550 {
       
   551     return float64_to_int32(val, &env->fp_status);
       
   552 }
       
   553 
       
   554 float32 HELPER(f64_to_f32)(CPUState *env, float64 val)
       
   555 {
       
   556     return float64_to_float32(val, &env->fp_status);
       
   557 }
       
   558 
       
   559 float64 HELPER(i32_to_f64)(CPUState *env, uint32_t val)
       
   560 {
       
   561     return int32_to_float64(val, &env->fp_status);
       
   562 }
       
   563 
       
   564 float64 HELPER(f32_to_f64)(CPUState *env, float32 val)
       
   565 {
       
   566     return float32_to_float64(val, &env->fp_status);
       
   567 }
       
   568 
       
   569 float64 HELPER(iround_f64)(CPUState *env, float64 val)
       
   570 {
       
   571     return float64_round_to_int(val, &env->fp_status);
       
   572 }
       
   573 
       
   574 float64 HELPER(itrunc_f64)(CPUState *env, float64 val)
       
   575 {
       
   576     return float64_trunc_to_int(val, &env->fp_status);
       
   577 }
       
   578 
       
   579 float64 HELPER(sqrt_f64)(CPUState *env, float64 val)
       
   580 {
       
   581     return float64_sqrt(val, &env->fp_status);
       
   582 }
       
   583 
       
   584 float64 HELPER(abs_f64)(float64 val)
       
   585 {
       
   586     return float64_abs(val);
       
   587 }
       
   588 
       
   589 float64 HELPER(chs_f64)(float64 val)
       
   590 {
       
   591     return float64_chs(val);
       
   592 }
       
   593 
       
   594 float64 HELPER(add_f64)(CPUState *env, float64 a, float64 b)
       
   595 {
       
   596     return float64_add(a, b, &env->fp_status);
       
   597 }
       
   598 
       
   599 float64 HELPER(sub_f64)(CPUState *env, float64 a, float64 b)
       
   600 {
       
   601     return float64_sub(a, b, &env->fp_status);
       
   602 }
       
   603 
       
   604 float64 HELPER(mul_f64)(CPUState *env, float64 a, float64 b)
       
   605 {
       
   606     return float64_mul(a, b, &env->fp_status);
       
   607 }
       
   608 
       
   609 float64 HELPER(div_f64)(CPUState *env, float64 a, float64 b)
       
   610 {
       
   611     return float64_div(a, b, &env->fp_status);
       
   612 }
       
   613 
       
   614 float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
       
   615 {
       
   616     /* ??? This may incorrectly raise exceptions.  */
       
   617     /* ??? Should flush denormals to zero.  */
       
   618     float64 res;
       
   619     res = float64_sub(a, b, &env->fp_status);
       
   620     if (float64_is_nan(res)) {
       
   621         /* +/-inf compares equal against itself, but sub returns nan.  */
       
   622         if (!float64_is_nan(a)
       
   623             && !float64_is_nan(b)) {
       
   624             res = float64_zero;
       
   625             if (float64_lt_quiet(a, res, &env->fp_status))
       
   626                 res = float64_chs(res);
       
   627         }
       
   628     }
       
   629     return res;
       
   630 }
       
   631 
       
   632 uint32_t HELPER(compare_f64)(CPUState *env, float64 val)
       
   633 {
       
   634     return float64_compare_quiet(val, float64_zero, &env->fp_status);
       
   635 }
       
   636 
       
   637 /* MAC unit.  */
       
   638 /* FIXME: The MAC unit implementation is a bit of a mess.  Some helpers
       
   639    take values,  others take register numbers and manipulate the contents
       
   640    in-place.  */
       
   641 void HELPER(mac_move)(CPUState *env, uint32_t dest, uint32_t src)
       
   642 {
       
   643     uint32_t mask;
       
   644     env->macc[dest] = env->macc[src];
       
   645     mask = MACSR_PAV0 << dest;
       
   646     if (env->macsr & (MACSR_PAV0 << src))
       
   647         env->macsr |= mask;
       
   648     else
       
   649         env->macsr &= ~mask;
       
   650 }
       
   651 
       
   652 uint64_t HELPER(macmuls)(CPUState *env, uint32_t op1, uint32_t op2)
       
   653 {
       
   654     int64_t product;
       
   655     int64_t res;
       
   656 
       
   657     product = (uint64_t)op1 * op2;
       
   658     res = (product << 24) >> 24;
       
   659     if (res != product) {
       
   660         env->macsr |= MACSR_V;
       
   661         if (env->macsr & MACSR_OMC) {
       
   662             /* Make sure the accumulate operation overflows.  */
       
   663             if (product < 0)
       
   664                 res = ~(1ll << 50);
       
   665             else
       
   666                 res = 1ll << 50;
       
   667         }
       
   668     }
       
   669     return res;
       
   670 }
       
   671 
       
   672 uint64_t HELPER(macmulu)(CPUState *env, uint32_t op1, uint32_t op2)
       
   673 {
       
   674     uint64_t product;
       
   675 
       
   676     product = (uint64_t)op1 * op2;
       
   677     if (product & (0xffffffull << 40)) {
       
   678         env->macsr |= MACSR_V;
       
   679         if (env->macsr & MACSR_OMC) {
       
   680             /* Make sure the accumulate operation overflows.  */
       
   681             product = 1ll << 50;
       
   682         } else {
       
   683             product &= ((1ull << 40) - 1);
       
   684         }
       
   685     }
       
   686     return product;
       
   687 }
       
   688 
       
   689 uint64_t HELPER(macmulf)(CPUState *env, uint32_t op1, uint32_t op2)
       
   690 {
       
   691     uint64_t product;
       
   692     uint32_t remainder;
       
   693 
       
   694     product = (uint64_t)op1 * op2;
       
   695     if (env->macsr & MACSR_RT) {
       
   696         remainder = product & 0xffffff;
       
   697         product >>= 24;
       
   698         if (remainder > 0x800000)
       
   699             product++;
       
   700         else if (remainder == 0x800000)
       
   701             product += (product & 1);
       
   702     } else {
       
   703         product >>= 24;
       
   704     }
       
   705     return product;
       
   706 }
       
   707 
       
   708 void HELPER(macsats)(CPUState *env, uint32_t acc)
       
   709 {
       
   710     int64_t tmp;
       
   711     int64_t result;
       
   712     tmp = env->macc[acc];
       
   713     result = ((tmp << 16) >> 16);
       
   714     if (result != tmp) {
       
   715         env->macsr |= MACSR_V;
       
   716     }
       
   717     if (env->macsr & MACSR_V) {
       
   718         env->macsr |= MACSR_PAV0 << acc;
       
   719         if (env->macsr & MACSR_OMC) {
       
   720             /* The result is saturated to 32 bits, despite overflow occuring
       
   721                at 48 bits.  Seems weird, but that's what the hardware docs
       
   722                say.  */
       
   723             result = (result >> 63) ^ 0x7fffffff;
       
   724         }
       
   725     }
       
   726     env->macc[acc] = result;
       
   727 }
       
   728 
       
   729 void HELPER(macsatu)(CPUState *env, uint32_t acc)
       
   730 {
       
   731     uint64_t val;
       
   732 
       
   733     val = env->macc[acc];
       
   734     if (val & (0xffffull << 48)) {
       
   735         env->macsr |= MACSR_V;
       
   736     }
       
   737     if (env->macsr & MACSR_V) {
       
   738         env->macsr |= MACSR_PAV0 << acc;
       
   739         if (env->macsr & MACSR_OMC) {
       
   740             if (val > (1ull << 53))
       
   741                 val = 0;
       
   742             else
       
   743                 val = (1ull << 48) - 1;
       
   744         } else {
       
   745             val &= ((1ull << 48) - 1);
       
   746         }
       
   747     }
       
   748     env->macc[acc] = val;
       
   749 }
       
   750 
       
   751 void HELPER(macsatf)(CPUState *env, uint32_t acc)
       
   752 {
       
   753     int64_t sum;
       
   754     int64_t result;
       
   755 
       
   756     sum = env->macc[acc];
       
   757     result = (sum << 16) >> 16;
       
   758     if (result != sum) {
       
   759         env->macsr |= MACSR_V;
       
   760     }
       
   761     if (env->macsr & MACSR_V) {
       
   762         env->macsr |= MACSR_PAV0 << acc;
       
   763         if (env->macsr & MACSR_OMC) {
       
   764             result = (result >> 63) ^ 0x7fffffffffffll;
       
   765         }
       
   766     }
       
   767     env->macc[acc] = result;
       
   768 }
       
   769 
       
   770 void HELPER(mac_set_flags)(CPUState *env, uint32_t acc)
       
   771 {
       
   772     uint64_t val;
       
   773     val = env->macc[acc];
       
   774     if (val == 0)
       
   775         env->macsr |= MACSR_Z;
       
   776     else if (val & (1ull << 47));
       
   777         env->macsr |= MACSR_N;
       
   778     if (env->macsr & (MACSR_PAV0 << acc)) {
       
   779         env->macsr |= MACSR_V;
       
   780     }
       
   781     if (env->macsr & MACSR_FI) {
       
   782         val = ((int64_t)val) >> 40;
       
   783         if (val != 0 && val != -1)
       
   784             env->macsr |= MACSR_EV;
       
   785     } else if (env->macsr & MACSR_SU) {
       
   786         val = ((int64_t)val) >> 32;
       
   787         if (val != 0 && val != -1)
       
   788             env->macsr |= MACSR_EV;
       
   789     } else {
       
   790         if ((val >> 32) != 0)
       
   791             env->macsr |= MACSR_EV;
       
   792     }
       
   793 }
       
   794 
       
   795 void HELPER(flush_flags)(CPUState *env, uint32_t cc_op)
       
   796 {
       
   797     cpu_m68k_flush_flags(env, cc_op);
       
   798 }
       
   799 
       
   800 uint32_t HELPER(get_macf)(CPUState *env, uint64_t val)
       
   801 {
       
   802     int rem;
       
   803     uint32_t result;
       
   804 
       
   805     if (env->macsr & MACSR_SU) {
       
   806         /* 16-bit rounding.  */
       
   807         rem = val & 0xffffff;
       
   808         val = (val >> 24) & 0xffffu;
       
   809         if (rem > 0x800000)
       
   810             val++;
       
   811         else if (rem == 0x800000)
       
   812             val += (val & 1);
       
   813     } else if (env->macsr & MACSR_RT) {
       
   814         /* 32-bit rounding.  */
       
   815         rem = val & 0xff;
       
   816         val >>= 8;
       
   817         if (rem > 0x80)
       
   818             val++;
       
   819         else if (rem == 0x80)
       
   820             val += (val & 1);
       
   821     } else {
       
   822         /* No rounding.  */
       
   823         val >>= 8;
       
   824     }
       
   825     if (env->macsr & MACSR_OMC) {
       
   826         /* Saturate.  */
       
   827         if (env->macsr & MACSR_SU) {
       
   828             if (val != (uint16_t) val) {
       
   829                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
       
   830             } else {
       
   831                 result = val & 0xffff;
       
   832             }
       
   833         } else {
       
   834             if (val != (uint32_t)val) {
       
   835                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
       
   836             } else {
       
   837                 result = (uint32_t)val;
       
   838             }
       
   839         }
       
   840     } else {
       
   841         /* No saturation.  */
       
   842         if (env->macsr & MACSR_SU) {
       
   843             result = val & 0xffff;
       
   844         } else {
       
   845             result = (uint32_t)val;
       
   846         }
       
   847     }
       
   848     return result;
       
   849 }
       
   850 
       
   851 uint32_t HELPER(get_macs)(uint64_t val)
       
   852 {
       
   853     if (val == (int32_t)val) {
       
   854         return (int32_t)val;
       
   855     } else {
       
   856         return (val >> 61) ^ ~SIGNBIT;
       
   857     }
       
   858 }
       
   859 
       
   860 uint32_t HELPER(get_macu)(uint64_t val)
       
   861 {
       
   862     if ((val >> 32) == 0) {
       
   863         return (uint32_t)val;
       
   864     } else {
       
   865         return 0xffffffffu;
       
   866     }
       
   867 }
       
   868 
       
   869 uint32_t HELPER(get_mac_extf)(CPUState *env, uint32_t acc)
       
   870 {
       
   871     uint32_t val;
       
   872     val = env->macc[acc] & 0x00ff;
       
   873     val = (env->macc[acc] >> 32) & 0xff00;
       
   874     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
       
   875     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
       
   876     return val;
       
   877 }
       
   878 
       
   879 uint32_t HELPER(get_mac_exti)(CPUState *env, uint32_t acc)
       
   880 {
       
   881     uint32_t val;
       
   882     val = (env->macc[acc] >> 32) & 0xffff;
       
   883     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
       
   884     return val;
       
   885 }
       
   886 
       
   887 void HELPER(set_mac_extf)(CPUState *env, uint32_t val, uint32_t acc)
       
   888 {
       
   889     int64_t res;
       
   890     int32_t tmp;
       
   891     res = env->macc[acc] & 0xffffffff00ull;
       
   892     tmp = (int16_t)(val & 0xff00);
       
   893     res |= ((int64_t)tmp) << 32;
       
   894     res |= val & 0xff;
       
   895     env->macc[acc] = res;
       
   896     res = env->macc[acc + 1] & 0xffffffff00ull;
       
   897     tmp = (val & 0xff000000);
       
   898     res |= ((int64_t)tmp) << 16;
       
   899     res |= (val >> 16) & 0xff;
       
   900     env->macc[acc + 1] = res;
       
   901 }
       
   902 
       
   903 void HELPER(set_mac_exts)(CPUState *env, uint32_t val, uint32_t acc)
       
   904 {
       
   905     int64_t res;
       
   906     int32_t tmp;
       
   907     res = (uint32_t)env->macc[acc];
       
   908     tmp = (int16_t)val;
       
   909     res |= ((int64_t)tmp) << 32;
       
   910     env->macc[acc] = res;
       
   911     res = (uint32_t)env->macc[acc + 1];
       
   912     tmp = val & 0xffff0000;
       
   913     res |= (int64_t)tmp << 16;
       
   914     env->macc[acc + 1] = res;
       
   915 }
       
   916 
       
   917 void HELPER(set_mac_extu)(CPUState *env, uint32_t val, uint32_t acc)
       
   918 {
       
   919     uint64_t res;
       
   920     res = (uint32_t)env->macc[acc];
       
   921     res |= ((uint64_t)(val & 0xffff)) << 32;
       
   922     env->macc[acc] = res;
       
   923     res = (uint32_t)env->macc[acc + 1];
       
   924     res |= (uint64_t)(val & 0xffff0000) << 16;
       
   925     env->macc[acc + 1] = res;
       
   926 }