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

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

unix.superglobalmegacorp.com

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