Annotation of qemu/target-m68k/op.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  *  m68k micro operations
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
                     19:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     20:  */
                     21: 
                     22: #include "exec.h"
                     23: #include "m68k-qreg.h"
                     24: 
                     25: #ifndef offsetof
                     26: #define offsetof(type, field) ((size_t) &((type *)0)->field)
                     27: #endif
                     28: 
                     29: static long qreg_offsets[] = {
                     30: #define DEFO32(name, offset) offsetof(CPUState, offset),
                     31: #define DEFR(name, reg, mode) -1,
                     32: #define DEFF64(name, offset) offsetof(CPUState, offset),
                     33:     0,
                     34: #include "qregs.def"
                     35: };
                     36: 
                     37: #define CPU_FP_STATUS env->fp_status
                     38: 
                     39: #define RAISE_EXCEPTION(n) do { \
                     40:     env->exception_index = n; \
                     41:     cpu_loop_exit(); \
                     42:     } while(0)
                     43: 
                     44: #define get_op helper_get_op
                     45: #define set_op helper_set_op
                     46: #define get_opf64 helper_get_opf64
                     47: #define set_opf64 helper_set_opf64
                     48: uint32_t
                     49: get_op(int qreg)
                     50: {
1.1.1.2 ! root       51:     if (qreg >= TARGET_NUM_QREGS) {
        !            52:         return env->qregs[qreg - TARGET_NUM_QREGS];
        !            53:     } else if (qreg == QREG_T0) {
1.1       root       54:         return T0;
                     55:     } else {
1.1.1.2 ! root       56:         return *(uint32_t *)(((long)env) + qreg_offsets[qreg]);
1.1       root       57:     }
                     58: }
                     59: 
                     60: void set_op(int qreg, uint32_t val)
                     61: {
1.1.1.2 ! root       62:     if (qreg >= TARGET_NUM_QREGS) {
        !            63:         env->qregs[qreg - TARGET_NUM_QREGS] = val;
        !            64:     } else if (qreg == QREG_T0) {
1.1       root       65:         T0 = val;
                     66:     } else {
1.1.1.2 ! root       67:         *(uint32_t *)(((long)env) + qreg_offsets[qreg]) = val;
1.1       root       68:     }
                     69: }
                     70: 
                     71: float64 get_opf64(int qreg)
                     72: {
                     73:     if (qreg < TARGET_NUM_QREGS) {
                     74:         return *(float64 *)(((long)env) + qreg_offsets[qreg]);
                     75:     } else {
                     76:         return *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS];
                     77:     }
                     78: }
                     79: 
                     80: void set_opf64(int qreg, float64 val)
                     81: {
                     82:     if (qreg < TARGET_NUM_QREGS) {
                     83:         *(float64 *)(((long)env) + qreg_offsets[qreg]) = val;
                     84:     } else {
                     85:         *(float64 *)&env->qregs[qreg - TARGET_NUM_QREGS] = val;
                     86:     }
                     87: }
                     88: 
1.1.1.2 ! root       89: #define OP(name) void OPPROTO glue(op_,name) (void)
1.1       root       90: 
                     91: OP(mov32)
                     92: {
                     93:     set_op(PARAM1, get_op(PARAM2));
                     94:     FORCE_RET();
                     95: }
                     96: 
                     97: OP(mov32_im)
                     98: {
                     99:     set_op(PARAM1, PARAM2);
                    100:     FORCE_RET();
                    101: }
                    102: 
                    103: OP(movf64)
                    104: {
                    105:     set_opf64(PARAM1, get_opf64(PARAM2));
                    106:     FORCE_RET();
                    107: }
                    108: 
                    109: OP(zerof64)
                    110: {
1.1.1.2 ! root      111:     set_opf64(PARAM1, float64_zero);
1.1       root      112:     FORCE_RET();
                    113: }
                    114: 
                    115: OP(add32)
                    116: {
                    117:     uint32_t op2 = get_op(PARAM2);
                    118:     uint32_t op3 = get_op(PARAM3);
                    119:     set_op(PARAM1, op2 + op3);
                    120:     FORCE_RET();
                    121: }
                    122: 
                    123: OP(sub32)
                    124: {
                    125:     uint32_t op2 = get_op(PARAM2);
                    126:     uint32_t op3 = get_op(PARAM3);
                    127:     set_op(PARAM1, op2 - op3);
                    128:     FORCE_RET();
                    129: }
                    130: 
                    131: OP(mul32)
                    132: {
                    133:     uint32_t op2 = get_op(PARAM2);
                    134:     uint32_t op3 = get_op(PARAM3);
                    135:     set_op(PARAM1, op2 * op3);
                    136:     FORCE_RET();
                    137: }
                    138: 
                    139: OP(not32)
                    140: {
                    141:     uint32_t arg = get_op(PARAM2);
                    142:     set_op(PARAM1, ~arg);
                    143:     FORCE_RET();
                    144: }
                    145: 
                    146: OP(neg32)
                    147: {
                    148:     uint32_t arg = get_op(PARAM2);
                    149:     set_op(PARAM1, -arg);
                    150:     FORCE_RET();
                    151: }
                    152: 
                    153: OP(bswap32)
                    154: {
                    155:     uint32_t arg = get_op(PARAM2);
                    156:     arg = (arg >> 24) | (arg << 24)
                    157:           | ((arg >> 16) & 0xff00) | ((arg << 16) & 0xff0000);
                    158:     set_op(PARAM1, arg);
                    159:     FORCE_RET();
                    160: }
                    161: 
                    162: OP(btest)
                    163: {
                    164:     uint32_t op1 = get_op(PARAM1);
                    165:     uint32_t op2 = get_op(PARAM2);
                    166:     if (op1 & op2)
                    167:         env->cc_dest &= ~CCF_Z;
                    168:     else
                    169:         env->cc_dest |= CCF_Z;
                    170:     FORCE_RET();
                    171: }
                    172: 
1.1.1.2 ! root      173: OP(ff1)
        !           174: {
        !           175:     uint32_t arg = get_op(PARAM2);
        !           176:     int n;
        !           177:     for (n = 32; arg; n--)
        !           178:         arg >>= 1;
        !           179:     set_op(PARAM1, n);
        !           180:     FORCE_RET();
        !           181: }
        !           182: 
        !           183: OP(subx_cc)
1.1       root      184: {
                    185:     uint32_t op1 = get_op(PARAM1);
                    186:     uint32_t op2 = get_op(PARAM2);
                    187:     uint32_t res;
                    188:     if (env->cc_x) {
                    189:         env->cc_x = (op1 <= op2);
                    190:         env->cc_op = CC_OP_SUBX;
                    191:         res = op1 - (op2 + 1);
                    192:     } else {
                    193:         env->cc_x = (op1 < op2);
                    194:         env->cc_op = CC_OP_SUB;
                    195:         res = op1 - op2;
                    196:     }
                    197:     set_op(PARAM1, res);
                    198:     FORCE_RET();
                    199: }
                    200: 
1.1.1.2 ! root      201: OP(addx_cc)
1.1       root      202: {
                    203:     uint32_t op1 = get_op(PARAM1);
                    204:     uint32_t op2 = get_op(PARAM2);
                    205:     uint32_t res;
                    206:     if (env->cc_x) {
                    207:         res = op1 + op2 + 1;
                    208:         env->cc_x = (res <= op2);
                    209:         env->cc_op = CC_OP_ADDX;
                    210:     } else {
                    211:         res = op1 + op2;
                    212:         env->cc_x = (res < op2);
                    213:         env->cc_op = CC_OP_ADD;
                    214:     }
                    215:     set_op(PARAM1, res);
                    216:     FORCE_RET();
                    217: }
                    218: 
                    219: /* Logic ops.  */
                    220: 
                    221: OP(and32)
                    222: {
                    223:     uint32_t op2 = get_op(PARAM2);
                    224:     uint32_t op3 = get_op(PARAM3);
                    225:     set_op(PARAM1, op2 & op3);
                    226:     FORCE_RET();
                    227: }
                    228: 
                    229: OP(or32)
                    230: {
                    231:     uint32_t op2 = get_op(PARAM2);
                    232:     uint32_t op3 = get_op(PARAM3);
                    233:     set_op(PARAM1, op2 | op3);
                    234:     FORCE_RET();
                    235: }
                    236: 
                    237: OP(xor32)
                    238: {
                    239:     uint32_t op2 = get_op(PARAM2);
                    240:     uint32_t op3 = get_op(PARAM3);
                    241:     set_op(PARAM1, op2 ^ op3);
                    242:     FORCE_RET();
                    243: }
                    244: 
                    245: /* Shifts.  */
                    246: OP(shl32)
                    247: {
                    248:     uint32_t op2 = get_op(PARAM2);
                    249:     uint32_t op3 = get_op(PARAM3);
                    250:     uint32_t result;
                    251:     result = op2 << op3;
                    252:     set_op(PARAM1, result);
                    253:     FORCE_RET();
                    254: }
                    255: 
                    256: OP(shl_cc)
                    257: {
                    258:     uint32_t op1 = get_op(PARAM1);
                    259:     uint32_t op2 = get_op(PARAM2);
                    260:     uint32_t result;
                    261:     result = op1 << op2;
                    262:     set_op(PARAM1, result);
                    263:     env->cc_x = (op1 << (op2 - 1)) & 1;
                    264:     FORCE_RET();
                    265: }
                    266: 
                    267: OP(shr32)
                    268: {
                    269:     uint32_t op2 = get_op(PARAM2);
                    270:     uint32_t op3 = get_op(PARAM3);
                    271:     uint32_t result;
                    272:     result = op2 >> op3;
                    273:     set_op(PARAM1, result);
                    274:     FORCE_RET();
                    275: }
                    276: 
                    277: OP(shr_cc)
                    278: {
                    279:     uint32_t op1 = get_op(PARAM1);
                    280:     uint32_t op2 = get_op(PARAM2);
                    281:     uint32_t result;
                    282:     result = op1 >> op2;
                    283:     set_op(PARAM1, result);
                    284:     env->cc_x = (op1 >> (op2 - 1)) & 1;
                    285:     FORCE_RET();
                    286: }
                    287: 
1.1.1.2 ! root      288: OP(sar32)
        !           289: {
        !           290:     int32_t op2 = get_op(PARAM2);
        !           291:     uint32_t op3 = get_op(PARAM3);
        !           292:     uint32_t result;
        !           293:     result = op2 >> op3;
        !           294:     set_op(PARAM1, result);
        !           295:     FORCE_RET();
        !           296: }
        !           297: 
1.1       root      298: OP(sar_cc)
                    299: {
                    300:     int32_t op1 = get_op(PARAM1);
                    301:     uint32_t op2 = get_op(PARAM2);
                    302:     uint32_t result;
                    303:     result = op1 >> op2;
                    304:     set_op(PARAM1, result);
                    305:     env->cc_x = (op1 >> (op2 - 1)) & 1;
                    306:     FORCE_RET();
                    307: }
                    308: 
                    309: /* Value extend.  */
                    310: 
                    311: OP(ext8u32)
                    312: {
                    313:     uint32_t op2 = get_op(PARAM2);
                    314:     set_op(PARAM1, (uint8_t)op2);
                    315:     FORCE_RET();
                    316: }
                    317: 
                    318: OP(ext8s32)
                    319: {
                    320:     uint32_t op2 = get_op(PARAM2);
                    321:     set_op(PARAM1, (int8_t)op2);
                    322:     FORCE_RET();
                    323: }
                    324: 
                    325: OP(ext16u32)
                    326: {
                    327:     uint32_t op2 = get_op(PARAM2);
                    328:     set_op(PARAM1, (uint16_t)op2);
                    329:     FORCE_RET();
                    330: }
                    331: 
                    332: OP(ext16s32)
                    333: {
                    334:     uint32_t op2 = get_op(PARAM2);
                    335:     set_op(PARAM1, (int16_t)op2);
                    336:     FORCE_RET();
                    337: }
                    338: 
                    339: OP(flush_flags)
                    340: {
1.1.1.2 ! root      341:     cpu_m68k_flush_flags(env, env->cc_op);
1.1       root      342:     FORCE_RET();
                    343: }
                    344: 
                    345: OP(divu)
                    346: {
                    347:     uint32_t num;
                    348:     uint32_t den;
                    349:     uint32_t quot;
                    350:     uint32_t rem;
                    351:     uint32_t flags;
1.1.1.2 ! root      352: 
1.1       root      353:     num = env->div1;
                    354:     den = env->div2;
                    355:     /* ??? This needs to make sure the throwing location is accurate.  */
                    356:     if (den == 0)
                    357:         RAISE_EXCEPTION(EXCP_DIV0);
                    358:     quot = num / den;
                    359:     rem = num % den;
                    360:     flags = 0;
                    361:     /* Avoid using a PARAM1 of zero.  This breaks dyngen because it uses
                    362:        the address of a symbol, and gcc knows symbols can't have address
                    363:        zero.  */
                    364:     if (PARAM1 == 2 && quot > 0xffff)
                    365:         flags |= CCF_V;
                    366:     if (quot == 0)
                    367:         flags |= CCF_Z;
                    368:     else if ((int32_t)quot < 0)
                    369:         flags |= CCF_N;
                    370:     env->div1 = quot;
                    371:     env->div2 = rem;
                    372:     env->cc_dest = flags;
                    373:     FORCE_RET();
                    374: }
                    375: 
                    376: OP(divs)
                    377: {
                    378:     int32_t num;
                    379:     int32_t den;
                    380:     int32_t quot;
                    381:     int32_t rem;
                    382:     int32_t flags;
1.1.1.2 ! root      383: 
1.1       root      384:     num = env->div1;
                    385:     den = env->div2;
                    386:     if (den == 0)
                    387:         RAISE_EXCEPTION(EXCP_DIV0);
                    388:     quot = num / den;
                    389:     rem = num % den;
                    390:     flags = 0;
                    391:     if (PARAM1 == 2 && quot != (int16_t)quot)
                    392:         flags |= CCF_V;
                    393:     if (quot == 0)
                    394:         flags |= CCF_Z;
                    395:     else if (quot < 0)
                    396:         flags |= CCF_N;
                    397:     env->div1 = quot;
                    398:     env->div2 = rem;
                    399:     env->cc_dest = flags;
                    400:     FORCE_RET();
                    401: }
                    402: 
1.1.1.2 ! root      403: /* Halt is special because it may be a semihosting call.  */
        !           404: OP(halt)
        !           405: {
        !           406:     RAISE_EXCEPTION(EXCP_HALT_INSN);
        !           407:     FORCE_RET();
        !           408: }
        !           409: 
        !           410: OP(stop)
        !           411: {
        !           412:     env->halted = 1;
        !           413:     RAISE_EXCEPTION(EXCP_HLT);
        !           414:     FORCE_RET();
        !           415: }
        !           416: 
1.1       root      417: OP(raise_exception)
                    418: {
                    419:     RAISE_EXCEPTION(PARAM1);
                    420:     FORCE_RET();
                    421: }
                    422: 
                    423: /* Floating point comparison sets flags differently to other instructions.  */
                    424: 
                    425: OP(sub_cmpf64)
                    426: {
                    427:     float64 src0;
                    428:     float64 src1;
                    429:     src0 = get_opf64(PARAM2);
                    430:     src1 = get_opf64(PARAM3);
                    431:     set_opf64(PARAM1, helper_sub_cmpf64(env, src0, src1));
                    432:     FORCE_RET();
                    433: }
                    434: 
                    435: OP(update_xflag_tst)
                    436: {
                    437:     uint32_t op1 = get_op(PARAM1);
                    438:     env->cc_x = op1;
                    439:     FORCE_RET();
                    440: }
                    441: 
                    442: OP(update_xflag_lt)
                    443: {
                    444:     uint32_t op1 = get_op(PARAM1);
                    445:     uint32_t op2 = get_op(PARAM2);
                    446:     env->cc_x = (op1 < op2);
                    447:     FORCE_RET();
                    448: }
                    449: 
                    450: OP(get_xflag)
                    451: {
                    452:     set_op(PARAM1, env->cc_x);
                    453:     FORCE_RET();
                    454: }
                    455: 
                    456: OP(logic_cc)
                    457: {
                    458:     uint32_t op1 = get_op(PARAM1);
                    459:     env->cc_dest = op1;
                    460:     FORCE_RET();
                    461: }
                    462: 
                    463: OP(update_cc_add)
                    464: {
                    465:     uint32_t op1 = get_op(PARAM1);
                    466:     uint32_t op2 = get_op(PARAM2);
                    467:     env->cc_dest = op1;
                    468:     env->cc_src = op2;
                    469:     FORCE_RET();
                    470: }
                    471: 
                    472: OP(fp_result)
                    473: {
                    474:     env->fp_result = get_opf64(PARAM1);
                    475:     FORCE_RET();
                    476: }
                    477: 
1.1.1.2 ! root      478: OP(set_sr)
        !           479: {
        !           480:     env->sr = get_op(PARAM1) & 0xffff;
        !           481:     m68k_switch_sp(env);
        !           482:     FORCE_RET();
        !           483: }
        !           484: 
1.1       root      485: OP(jmp)
                    486: {
                    487:     GOTO_LABEL_PARAM(1);
                    488: }
                    489: 
1.1.1.2 ! root      490: OP(set_T0_z32)
1.1       root      491: {
                    492:     uint32_t arg = get_op(PARAM1);
1.1.1.2 ! root      493:     T0 = (arg == 0);
1.1       root      494:     FORCE_RET();
                    495: }
                    496: 
1.1.1.2 ! root      497: OP(set_T0_nz32)
1.1       root      498: {
                    499:     uint32_t arg = get_op(PARAM1);
1.1.1.2 ! root      500:     T0 = (arg != 0);
1.1       root      501:     FORCE_RET();
                    502: }
                    503: 
1.1.1.2 ! root      504: OP(set_T0_s32)
1.1       root      505: {
                    506:     int32_t arg = get_op(PARAM1);
1.1.1.2 ! root      507:     T0 = (arg > 0);
1.1       root      508:     FORCE_RET();
                    509: }
                    510: 
1.1.1.2 ! root      511: OP(set_T0_ns32)
1.1       root      512: {
                    513:     int32_t arg = get_op(PARAM1);
1.1.1.2 ! root      514:     T0 = (arg >= 0);
        !           515:     FORCE_RET();
        !           516: }
        !           517: 
        !           518: OP(jmp_T0)
        !           519: {
        !           520:     if (T0)
        !           521:         GOTO_LABEL_PARAM(1);
1.1       root      522:     FORCE_RET();
                    523: }
                    524: 
                    525: void OPPROTO op_goto_tb0(void)
                    526: {
                    527:     GOTO_TB(op_goto_tb0, PARAM1, 0);
                    528: }
                    529: 
                    530: void OPPROTO op_goto_tb1(void)
                    531: {
                    532:     GOTO_TB(op_goto_tb1, PARAM1, 1);
                    533: }
                    534: 
                    535: OP(exit_tb)
                    536: {
                    537:     EXIT_TB();
                    538: }
                    539: 
                    540: 
                    541: /* Floating point.  */
                    542: OP(f64_to_i32)
                    543: {
                    544:     set_op(PARAM1, float64_to_int32(get_opf64(PARAM2), &CPU_FP_STATUS));
                    545:     FORCE_RET();
                    546: }
                    547: 
                    548: OP(f64_to_f32)
                    549: {
                    550:     union {
                    551:         float32 f;
                    552:         uint32_t i;
                    553:     } u;
                    554:     u.f = float64_to_float32(get_opf64(PARAM2), &CPU_FP_STATUS);
                    555:     set_op(PARAM1, u.i);
                    556:     FORCE_RET();
                    557: }
                    558: 
                    559: OP(i32_to_f64)
                    560: {
                    561:     set_opf64(PARAM1, int32_to_float64(get_op(PARAM2), &CPU_FP_STATUS));
                    562:     FORCE_RET();
                    563: }
                    564: 
                    565: OP(f32_to_f64)
                    566: {
                    567:     union {
                    568:         float32 f;
                    569:         uint32_t i;
                    570:     } u;
                    571:     u.i = get_op(PARAM2);
                    572:     set_opf64(PARAM1, float32_to_float64(u.f, &CPU_FP_STATUS));
                    573:     FORCE_RET();
                    574: }
                    575: 
                    576: OP(absf64)
                    577: {
                    578:     float64 op0 = get_opf64(PARAM2);
                    579:     set_opf64(PARAM1, float64_abs(op0));
                    580:     FORCE_RET();
                    581: }
                    582: 
                    583: OP(chsf64)
                    584: {
                    585:     float64 op0 = get_opf64(PARAM2);
                    586:     set_opf64(PARAM1, float64_chs(op0));
                    587:     FORCE_RET();
                    588: }
                    589: 
                    590: OP(sqrtf64)
                    591: {
                    592:     float64 op0 = get_opf64(PARAM2);
                    593:     set_opf64(PARAM1, float64_sqrt(op0, &CPU_FP_STATUS));
                    594:     FORCE_RET();
                    595: }
                    596: 
                    597: OP(addf64)
                    598: {
                    599:     float64 op0 = get_opf64(PARAM2);
                    600:     float64 op1 = get_opf64(PARAM3);
                    601:     set_opf64(PARAM1, float64_add(op0, op1, &CPU_FP_STATUS));
                    602:     FORCE_RET();
                    603: }
                    604: 
                    605: OP(subf64)
                    606: {
                    607:     float64 op0 = get_opf64(PARAM2);
                    608:     float64 op1 = get_opf64(PARAM3);
                    609:     set_opf64(PARAM1, float64_sub(op0, op1, &CPU_FP_STATUS));
                    610:     FORCE_RET();
                    611: }
                    612: 
                    613: OP(mulf64)
                    614: {
                    615:     float64 op0 = get_opf64(PARAM2);
                    616:     float64 op1 = get_opf64(PARAM3);
                    617:     set_opf64(PARAM1, float64_mul(op0, op1, &CPU_FP_STATUS));
                    618:     FORCE_RET();
                    619: }
                    620: 
                    621: OP(divf64)
                    622: {
                    623:     float64 op0 = get_opf64(PARAM2);
                    624:     float64 op1 = get_opf64(PARAM3);
                    625:     set_opf64(PARAM1, float64_div(op0, op1, &CPU_FP_STATUS));
                    626:     FORCE_RET();
                    627: }
                    628: 
                    629: OP(iround_f64)
                    630: {
                    631:     float64 op0 = get_opf64(PARAM2);
                    632:     set_opf64(PARAM1, float64_round_to_int(op0, &CPU_FP_STATUS));
                    633:     FORCE_RET();
                    634: }
                    635: 
                    636: OP(itrunc_f64)
                    637: {
                    638:     float64 op0 = get_opf64(PARAM2);
                    639:     set_opf64(PARAM1, float64_trunc_to_int(op0, &CPU_FP_STATUS));
                    640:     FORCE_RET();
                    641: }
                    642: 
                    643: OP(compare_quietf64)
                    644: {
                    645:     float64 op0 = get_opf64(PARAM2);
                    646:     float64 op1 = get_opf64(PARAM3);
                    647:     set_op(PARAM1, float64_compare_quiet(op0, op1, &CPU_FP_STATUS));
                    648:     FORCE_RET();
                    649: }
1.1.1.2 ! root      650: 
        !           651: OP(movec)
        !           652: {
        !           653:     int op1 = get_op(PARAM1);
        !           654:     uint32_t op2 = get_op(PARAM2);
        !           655:     helper_movec(env, op1, op2);
        !           656: }
        !           657: 
        !           658: /* Memory access.  */
        !           659: 
        !           660: #define MEMSUFFIX _raw
        !           661: #include "op_mem.h"
        !           662: 
        !           663: #if !defined(CONFIG_USER_ONLY)
        !           664: #define MEMSUFFIX _user
        !           665: #include "op_mem.h"
        !           666: #define MEMSUFFIX _kernel
        !           667: #include "op_mem.h"
        !           668: #endif
        !           669: 
        !           670: /* MAC unit.  */
        !           671: /* TODO: The MAC instructions use 64-bit arithmetic fairly extensively.
        !           672:    This results in fairly large ops (and sometimes other issues) on 32-bit
        !           673:    hosts.  Maybe move most of them into helpers.  */
        !           674: OP(macmuls)
        !           675: {
        !           676:     uint32_t op1 = get_op(PARAM1);
        !           677:     uint32_t op2 = get_op(PARAM2);
        !           678:     int64_t product;
        !           679:     int64_t res;
        !           680: 
        !           681:     product = (uint64_t)op1 * op2;
        !           682:     res = (product << 24) >> 24;
        !           683:     if (res != product) {
        !           684:         env->macsr |= MACSR_V;
        !           685:         if (env->macsr & MACSR_OMC) {
        !           686:             /* Make sure the accumulate operation overflows.  */
        !           687:             if (product < 0)
        !           688:                 res = ~(1ll << 50);
        !           689:             else
        !           690:                 res = 1ll << 50;
        !           691:         }
        !           692:     }
        !           693:     env->mactmp = res;
        !           694:     FORCE_RET();
        !           695: }
        !           696: 
        !           697: OP(macmulu)
        !           698: {
        !           699:     uint32_t op1 = get_op(PARAM1);
        !           700:     uint32_t op2 = get_op(PARAM2);
        !           701:     uint64_t product;
        !           702: 
        !           703:     product = (uint64_t)op1 * op2;
        !           704:     if (product & (0xffffffull << 40)) {
        !           705:         env->macsr |= MACSR_V;
        !           706:         if (env->macsr & MACSR_OMC) {
        !           707:             /* Make sure the accumulate operation overflows.  */
        !           708:             product = 1ll << 50;
        !           709:         } else {
        !           710:             product &= ((1ull << 40) - 1);
        !           711:         }
        !           712:     }
        !           713:     env->mactmp = product;
        !           714:     FORCE_RET();
        !           715: }
        !           716: 
        !           717: OP(macmulf)
        !           718: {
        !           719:     int32_t op1 = get_op(PARAM1);
        !           720:     int32_t op2 = get_op(PARAM2);
        !           721:     uint64_t product;
        !           722:     uint32_t remainder;
        !           723: 
        !           724:     product = (uint64_t)op1 * op2;
        !           725:     if (env->macsr & MACSR_RT) {
        !           726:         remainder = product & 0xffffff;
        !           727:         product >>= 24;
        !           728:         if (remainder > 0x800000)
        !           729:             product++;
        !           730:         else if (remainder == 0x800000)
        !           731:             product += (product & 1);
        !           732:     } else {
        !           733:         product >>= 24;
        !           734:     }
        !           735:     env->mactmp = product;
        !           736:     FORCE_RET();
        !           737: }
        !           738: 
        !           739: OP(macshl)
        !           740: {
        !           741:     env->mactmp <<= 1;
        !           742: }
        !           743: 
        !           744: OP(macshr)
        !           745: {
        !           746:     env->mactmp >>= 1;
        !           747: }
        !           748: 
        !           749: OP(macadd)
        !           750: {
        !           751:     int acc = PARAM1;
        !           752:     env->macc[acc] += env->mactmp;
        !           753:     FORCE_RET();
        !           754: }
        !           755: 
        !           756: OP(macsub)
        !           757: {
        !           758:     int acc = PARAM1;
        !           759:     env->macc[acc] -= env->mactmp;
        !           760:     FORCE_RET();
        !           761: }
        !           762: 
        !           763: OP(macsats)
        !           764: {
        !           765:     int acc = PARAM1;
        !           766:     int64_t sum;
        !           767:     int64_t result;
        !           768: 
        !           769:     sum = env->macc[acc];
        !           770:     result = (sum << 16) >> 16;
        !           771:     if (result != sum) {
        !           772:         env->macsr |= MACSR_V;
        !           773:     }
        !           774:     if (env->macsr & MACSR_V) {
        !           775:         env->macsr |= MACSR_PAV0 << acc;
        !           776:         if (env->macsr & MACSR_OMC) {
        !           777:             /* The result is saturated to 32 bits, despite overflow occuring
        !           778:                at 48 bits.  Seems weird, but that's what the hardware docs
        !           779:                say.  */
        !           780:             result = (result >> 63) ^ 0x7fffffff;
        !           781:         }
        !           782:     }
        !           783:     env->macc[acc] = result;
        !           784:     FORCE_RET();
        !           785: }
        !           786: 
        !           787: OP(macsatu)
        !           788: {
        !           789:     int acc = PARAM1;
        !           790:     uint64_t sum;
        !           791: 
        !           792:     sum = env->macc[acc];
        !           793:     if (sum & (0xffffull << 48)) {
        !           794:         env->macsr |= MACSR_V;
        !           795:     }
        !           796:     if (env->macsr & MACSR_V) {
        !           797:         env->macsr |= MACSR_PAV0 << acc;
        !           798:         if (env->macsr & MACSR_OMC) {
        !           799:             if (sum > (1ull << 53))
        !           800:                 sum = 0;
        !           801:             else
        !           802:                 sum = (1ull << 48) - 1;
        !           803:         } else {
        !           804:             sum &= ((1ull << 48) - 1);
        !           805:         }
        !           806:     }
        !           807:     FORCE_RET();
        !           808: }
        !           809: 
        !           810: OP(macsatf)
        !           811: {
        !           812:     int acc = PARAM1;
        !           813:     int64_t sum;
        !           814:     int64_t result;
        !           815: 
        !           816:     sum = env->macc[acc];
        !           817:     result = (sum << 16) >> 16;
        !           818:     if (result != sum) {
        !           819:         env->macsr |= MACSR_V;
        !           820:     }
        !           821:     if (env->macsr & MACSR_V) {
        !           822:         env->macsr |= MACSR_PAV0 << acc;
        !           823:         if (env->macsr & MACSR_OMC) {
        !           824:             result = (result >> 63) ^ 0x7fffffffffffll;
        !           825:         }
        !           826:     }
        !           827:     env->macc[acc] = result;
        !           828:     FORCE_RET();
        !           829: }
        !           830: 
        !           831: OP(mac_clear_flags)
        !           832: {
        !           833:     env->macsr &= ~(MACSR_V | MACSR_Z | MACSR_N | MACSR_EV);
        !           834: }
        !           835: 
        !           836: OP(mac_set_flags)
        !           837: {
        !           838:     int acc = PARAM1;
        !           839:     uint64_t val;
        !           840:     val = env->macc[acc];
        !           841:     if (val == 0)
        !           842:         env->macsr |= MACSR_Z;
        !           843:     else if (val & (1ull << 47));
        !           844:         env->macsr |= MACSR_N;
        !           845:     if (env->macsr & (MACSR_PAV0 << acc)) {
        !           846:         env->macsr |= MACSR_V;
        !           847:     }
        !           848:     if (env->macsr & MACSR_FI) {
        !           849:         val = ((int64_t)val) >> 40;
        !           850:         if (val != 0 && val != -1)
        !           851:             env->macsr |= MACSR_EV;
        !           852:     } else if (env->macsr & MACSR_SU) {
        !           853:         val = ((int64_t)val) >> 32;
        !           854:         if (val != 0 && val != -1)
        !           855:             env->macsr |= MACSR_EV;
        !           856:     } else {
        !           857:         if ((val >> 32) != 0)
        !           858:             env->macsr |= MACSR_EV;
        !           859:     }
        !           860:     FORCE_RET();
        !           861: }
        !           862: 
        !           863: OP(get_macf)
        !           864: {
        !           865:     int acc = PARAM2;
        !           866:     int64_t val;
        !           867:     int rem;
        !           868:     uint32_t result;
        !           869: 
        !           870:     val = env->macc[acc];
        !           871:     if (env->macsr & MACSR_SU) {
        !           872:         /* 16-bit rounding.  */
        !           873:         rem = val & 0xffffff;
        !           874:         val = (val >> 24) & 0xffffu;
        !           875:         if (rem > 0x800000)
        !           876:             val++;
        !           877:         else if (rem == 0x800000)
        !           878:             val += (val & 1);
        !           879:     } else if (env->macsr & MACSR_RT) {
        !           880:         /* 32-bit rounding.  */
        !           881:         rem = val & 0xff;
        !           882:         val >>= 8;
        !           883:         if (rem > 0x80)
        !           884:             val++;
        !           885:         else if (rem == 0x80)
        !           886:             val += (val & 1);
        !           887:     } else {
        !           888:         /* No rounding.  */
        !           889:         val >>= 8;
        !           890:     }
        !           891:     if (env->macsr & MACSR_OMC) {
        !           892:         /* Saturate.  */
        !           893:         if (env->macsr & MACSR_SU) {
        !           894:             if (val != (uint16_t) val) {
        !           895:                 result = ((val >> 63) ^ 0x7fff) & 0xffff;
        !           896:             } else {
        !           897:                 result = val & 0xffff;
        !           898:             }
        !           899:         } else {
        !           900:             if (val != (uint32_t)val) {
        !           901:                 result = ((uint32_t)(val >> 63) & 0x7fffffff);
        !           902:             } else {
        !           903:                 result = (uint32_t)val;
        !           904:             }
        !           905:         }
        !           906:     } else {
        !           907:         /* No saturation.  */
        !           908:         if (env->macsr & MACSR_SU) {
        !           909:             result = val & 0xffff;
        !           910:         } else {
        !           911:             result = (uint32_t)val;
        !           912:         }
        !           913:     }
        !           914:     set_op(PARAM1, result);
        !           915:     FORCE_RET();
        !           916: }
        !           917: 
        !           918: OP(get_maci)
        !           919: {
        !           920:     int acc = PARAM2;
        !           921:     set_op(PARAM1, (uint32_t)env->macc[acc]);
        !           922:     FORCE_RET();
        !           923: }
        !           924: 
        !           925: OP(get_macs)
        !           926: {
        !           927:     int acc = PARAM2;
        !           928:     int64_t val = env->macc[acc];
        !           929:     uint32_t result;
        !           930:     if (val == (int32_t)val) {
        !           931:         result = (int32_t)val;
        !           932:     } else {
        !           933:         result = (val >> 61) ^ 0x7fffffff;
        !           934:     }
        !           935:     set_op(PARAM1, result);
        !           936:     FORCE_RET();
        !           937: }
        !           938: 
        !           939: OP(get_macu)
        !           940: {
        !           941:     int acc = PARAM2;
        !           942:     uint64_t val = env->macc[acc];
        !           943:     uint32_t result;
        !           944:     if ((val >> 32) == 0) {
        !           945:         result = (uint32_t)val;
        !           946:     } else {
        !           947:         result = 0xffffffffu;
        !           948:     }
        !           949:     set_op(PARAM1, result);
        !           950:     FORCE_RET();
        !           951: }
        !           952: 
        !           953: OP(clear_mac)
        !           954: {
        !           955:     int acc = PARAM1;
        !           956: 
        !           957:     env->macc[acc] = 0;
        !           958:     env->macsr &= ~(MACSR_PAV0 << acc);
        !           959:     FORCE_RET();
        !           960: }
        !           961: 
        !           962: OP(move_mac)
        !           963: {
        !           964:     int dest = PARAM1;
        !           965:     int src = PARAM2;
        !           966:     uint32_t mask;
        !           967:     env->macc[dest] = env->macc[src];
        !           968:     mask = MACSR_PAV0 << dest;
        !           969:     if (env->macsr & (MACSR_PAV0 << src))
        !           970:         env->macsr |= mask;
        !           971:     else
        !           972:         env->macsr &= ~mask;
        !           973:     FORCE_RET();
        !           974: }
        !           975: 
        !           976: OP(get_mac_extf)
        !           977: {
        !           978:     uint32_t val;
        !           979:     int acc = PARAM2;
        !           980:     val = env->macc[acc] & 0x00ff;
        !           981:     val = (env->macc[acc] >> 32) & 0xff00;
        !           982:     val |= (env->macc[acc + 1] << 16) & 0x00ff0000;
        !           983:     val |= (env->macc[acc + 1] >> 16) & 0xff000000;
        !           984:     set_op(PARAM1, val);
        !           985:     FORCE_RET();
        !           986: }
        !           987: 
        !           988: OP(get_mac_exti)
        !           989: {
        !           990:     uint32_t val;
        !           991:     int acc = PARAM2;
        !           992:     val = (env->macc[acc] >> 32) & 0xffff;
        !           993:     val |= (env->macc[acc + 1] >> 16) & 0xffff0000;
        !           994:     set_op(PARAM1, val);
        !           995:     FORCE_RET();
        !           996: }
        !           997: 
        !           998: OP(set_macf)
        !           999: {
        !          1000:     int acc = PARAM2;
        !          1001:     int32_t val = get_op(PARAM1);
        !          1002:     env->macc[acc] = ((int64_t)val) << 8;
        !          1003:     env->macsr &= ~(MACSR_PAV0 << acc);
        !          1004:     FORCE_RET();
        !          1005: }
        !          1006: 
        !          1007: OP(set_macs)
        !          1008: {
        !          1009:     int acc = PARAM2;
        !          1010:     int32_t val = get_op(PARAM1);
        !          1011:     env->macc[acc] = val;
        !          1012:     env->macsr &= ~(MACSR_PAV0 << acc);
        !          1013:     FORCE_RET();
        !          1014: }
        !          1015: 
        !          1016: OP(set_macu)
        !          1017: {
        !          1018:     int acc = PARAM2;
        !          1019:     uint32_t val = get_op(PARAM1);
        !          1020:     env->macc[acc] = val;
        !          1021:     env->macsr &= ~(MACSR_PAV0 << acc);
        !          1022:     FORCE_RET();
        !          1023: }
        !          1024: 
        !          1025: OP(set_mac_extf)
        !          1026: {
        !          1027:     int acc = PARAM2;
        !          1028:     int32_t val = get_op(PARAM1);
        !          1029:     int64_t res;
        !          1030:     int32_t tmp;
        !          1031:     res = env->macc[acc] & 0xffffffff00ull;
        !          1032:     tmp = (int16_t)(val & 0xff00);
        !          1033:     res |= ((int64_t)tmp) << 32;
        !          1034:     res |= val & 0xff;
        !          1035:     env->macc[acc] = res;
        !          1036:     res = env->macc[acc + 1] & 0xffffffff00ull;
        !          1037:     tmp = (val & 0xff000000);
        !          1038:     res |= ((int64_t)tmp) << 16;
        !          1039:     res |= (val >> 16) & 0xff;
        !          1040:     env->macc[acc + 1] = res;
        !          1041: }
        !          1042: 
        !          1043: OP(set_mac_exts)
        !          1044: {
        !          1045:     int acc = PARAM2;
        !          1046:     int32_t val = get_op(PARAM1);
        !          1047:     int64_t res;
        !          1048:     int32_t tmp;
        !          1049:     res = (uint32_t)env->macc[acc];
        !          1050:     tmp = (int16_t)val;
        !          1051:     res |= ((int64_t)tmp) << 32;
        !          1052:     env->macc[acc] = res;
        !          1053:     res = (uint32_t)env->macc[acc + 1];
        !          1054:     tmp = val & 0xffff0000;
        !          1055:     res |= (int64_t)tmp << 16;
        !          1056:     env->macc[acc + 1] = res;
        !          1057: }
        !          1058: 
        !          1059: OP(set_mac_extu)
        !          1060: {
        !          1061:     int acc = PARAM2;
        !          1062:     int32_t val = get_op(PARAM1);
        !          1063:     uint64_t res;
        !          1064:     res = (uint32_t)env->macc[acc];
        !          1065:     res |= ((uint64_t)(val & 0xffff)) << 32;
        !          1066:     env->macc[acc] = res;
        !          1067:     res = (uint32_t)env->macc[acc + 1];
        !          1068:     res |= (uint64_t)(val & 0xffff0000) << 16;
        !          1069:     env->macc[acc + 1] = res;
        !          1070: }
        !          1071: 
        !          1072: OP(set_macsr)
        !          1073: {
        !          1074:     m68k_set_macsr(env, get_op(PARAM1));
        !          1075: }

unix.superglobalmegacorp.com

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