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

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

unix.superglobalmegacorp.com

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