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

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

unix.superglobalmegacorp.com

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