Annotation of qemu/target-m68k/helper.c, revision 1.1.1.5

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.