Annotation of nono/m680x0/m680x0acc.cpp, revision 1.1.1.2

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: #include "mpu680x0.h"
                      8: #include "m680x0acc.h"
                      9: 
                     10: /*static*/ inline uint32
                     11: m680x0ACC::vflag_add_8(uint32 src, uint32 dst, uint32 res)
                     12: {
                     13:        return vflag_add_32(src, dst, res) << 24;
                     14: }
                     15: 
                     16: /*static*/ inline uint32
                     17: m680x0ACC::vflag_add_16(uint32 src, uint32 dst, uint32 res)
                     18: {
                     19:        return vflag_add_32(src, dst, res) << 16;
                     20: }
                     21: 
                     22: /*static*/ inline uint32
                     23: m680x0ACC::vflag_add_32(uint32 src, uint32 dst, uint32 res)
                     24: {
                     25:        return (src ^ res) & (dst ^ res);
                     26: }
                     27: 
                     28: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
                     29: // src, dst の上位ビットはクリアしておくこと。
                     30: // 戻り値の上位ビットはクリアされている。
                     31: uint32
                     32: m680x0ACC::add_8(uint32 src, uint32 dst)
                     33: {
                     34:        Z = dst + src;
                     35:        C = Z >> 8;
                     36:        X = C;
                     37:        N = Z << 24;
                     38:        Z &= 0xff;
                     39:        V = vflag_add_8(src, dst, Z);
                     40:        return Z;
                     41: }
                     42: 
                     43: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
                     44: // src, dst の上位ビットはクリアしておくこと。
                     45: // 戻り値の上位ビットはクリアされている。
                     46: uint32
                     47: m680x0ACC::add_16(uint32 src, uint32 dst)
                     48: {
                     49:        Z = dst + src;
                     50:        C = Z >> 16;
                     51:        X = C;
                     52:        N = Z << 16;
                     53:        Z &= 0xffff;
                     54:        V = vflag_add_16(src, dst, Z);
                     55:        return Z;
                     56: }
                     57: 
                     58: // src + dst を計算し、XNZVC フラグをセットして結果を返す。
                     59: uint32
                     60: m680x0ACC::add_32(uint32 src, uint32 dst)
                     61: {
                     62:        CZ = (uint64)dst + (uint64)src;
                     63:        X = C;
                     64:        V = vflag_add_32(src, dst, Z);
                     65:        N = Z;
                     66:        return Z;
                     67: }
                     68: 
                     69: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
                     70: // src, dst の上位ビットはクリアしておくこと。
                     71: // 戻り値の上位ビットはクリアされている。
                     72: uint32
                     73: m680x0ACC::addx_8(uint32 src, uint32 dst)
                     74: {
                     75:        uint32 res = dst + src + (IsX() ? 1 : 0);
                     76:        C = res >> 8;
                     77:        X = C;
                     78:        N = res << 24;
                     79:        // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
                     80:        if (N != 0) {
                     81:                Z = N;
                     82:        }
                     83:        V = vflag_add_8(src, dst, res);
                     84:        return res & 0xff;
                     85: }
                     86: 
                     87: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
                     88: // src, dst の上位ビットはクリアしておくこと。
                     89: // 戻り値の上位ビットはクリアされている。
                     90: uint32
                     91: m680x0ACC::addx_16(uint32 src, uint32 dst)
                     92: {
                     93:        uint32 res = dst + src + (IsX() ? 1 : 0);
                     94:        C = res >> 16;
                     95:        X = C;
                     96:        N = res << 16;
                     97:        // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
                     98:        if (N != 0) {
                     99:                Z = N;
                    100:        }
                    101:        V = vflag_add_16(src, dst, res);
                    102:        return res & 0xffff;
                    103: }
                    104: 
                    105: // src + dst + X を計算し、XNZVC フラグをセットして結果を返す。
                    106: uint32
                    107: m680x0ACC::addx_32(uint32 src, uint32 dst)
                    108: {
                    109:        uint64 res = (uint64)dst + (uint64)src + (IsX() ? 1 : 0);
                    110:        C = res >> 32;
                    111:        X = C;
                    112:        N = res;
                    113:        // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
                    114:        if (N != 0) {
                    115:                Z = N;
                    116:        }
                    117:        V = vflag_add_32(src, dst, res);
                    118:        return res;
                    119: }
                    120: 
                    121: 
                    122: /*static*/ inline uint32
                    123: m680x0ACC::vflag_sub_8(uint32 src, uint32 dst, uint32 res)
                    124: {
                    125:        return vflag_sub_32(src, dst, res) << 24;
                    126: }
                    127: 
                    128: /*static*/ inline uint32
                    129: m680x0ACC::vflag_sub_16(uint32 src, uint32 dst, uint32 res)
                    130: {
                    131:        return vflag_sub_32(src, dst, res) << 16;
                    132: }
                    133: 
                    134: /*static*/ inline uint32
                    135: m680x0ACC::vflag_sub_32(uint32 src, uint32 dst, uint32 res)
                    136: {
                    137:        return (src ^ dst) & (dst ^ res);
                    138: }
                    139: 
                    140: // dst - src を計算し、NZVC フラグをセットして結果を返す。
                    141: // src, dst の上位ビットはクリアしておくこと。
                    142: // 戻り値の上位ビットはクリアされている。
                    143: uint32
                    144: m680x0ACC::cmp_8(uint32 src, uint32 dst)
                    145: {
                    146:        Z = dst - src;
                    147:        C = Z >> 8;
                    148:        N = Z << 24;
                    149:        Z &= 0xff;
                    150:        V = vflag_sub_8(src, dst, Z);
                    151:        return Z;
                    152: }
                    153: 
                    154: // dst - src を計算し、NZVC フラグをセットして結果を返す。
                    155: // src, dst の上位ビットはクリアしておくこと。
                    156: // 戻り値の上位ビットはクリアされている。
                    157: uint32
                    158: m680x0ACC::cmp_16(uint32 src, uint32 dst)
                    159: {
                    160:        Z = dst - src;
                    161:        C = Z >> 16;
                    162:        N = Z << 16;
                    163:        Z &= 0xffff;
                    164:        V = vflag_sub_16(src, dst, Z);
                    165:        return Z;
                    166: }
                    167: 
                    168: // dst - src を計算し、NZVC フラグをセットして結果を返す。
                    169: uint32
                    170: m680x0ACC::cmp_32(uint32 src, uint32 dst)
                    171: {
                    172:        CZ = (uint64)dst - (uint64)src;
                    173:        N = Z;
                    174:        V = vflag_sub_32(src, dst, Z);
                    175:        return Z;
                    176: }
                    177: 
                    178: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
                    179: // src, dst の上位ビットはクリアしておくこと。
                    180: // 戻り値の上位ビットはクリアされている。
                    181: uint32
                    182: m680x0ACC::sub_8(uint32 src, uint32 dst)
                    183: {
                    184:        uint32 res = cmp_8(src, dst);
                    185:        X = C;
                    186:        return res;
                    187: }
                    188: 
                    189: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
                    190: // src, dst の上位ビットはクリアしておくこと。
                    191: // 戻り値の上位ビットはクリアされている。
                    192: uint32
                    193: m680x0ACC::sub_16(uint32 src, uint32 dst)
                    194: {
                    195:        uint32 res = cmp_16(src, dst);
                    196:        X = C;
                    197:        return res;
                    198: }
                    199: 
                    200: // dst - src を計算し、XNZVC フラグをセットして結果を返す。
                    201: uint32
                    202: m680x0ACC::sub_32(uint32 src, uint32 dst)
                    203: {
                    204:        uint32 res = cmp_32(src, dst);
                    205:        X = C;
                    206:        return res;
                    207: }
                    208: 
                    209: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
                    210: // src, dst の上位ビットはクリアしておくこと。
                    211: // 戻り値 res の上位ビットはクリアされている。
                    212: uint32
                    213: m680x0ACC::subx_8(uint32 src, uint32 dst)
                    214: {
                    215:        uint32 res = dst - src - (IsX() ? 1 : 0);
                    216:        C = res >> 8;
                    217:        X = C;
                    218:        N = res << 24;
                    219:        // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
                    220:        if (N != 0) {
                    221:                Z = N;
                    222:        }
                    223:        V = vflag_sub_8(src, dst, res);
                    224:        return res & 0xff;
                    225: }
                    226: 
                    227: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
                    228: // src, dst の上位ビットはクリアしておくこと。
                    229: // 戻り値 res の上位ビットはクリアされている。
                    230: uint32
                    231: m680x0ACC::subx_16(uint32 src, uint32 dst)
                    232: {
                    233:        uint32 res = dst - src - (IsX() ? 1 : 0);
                    234:        C = res >> 16;
                    235:        X = C;
                    236:        N = res << 16;
                    237:        // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
                    238:        if (N != 0) {
                    239:                Z = N;
                    240:        }
                    241:        V = vflag_sub_16(src, dst, res);
                    242:        return res & 0xffff;
                    243: }
                    244: 
                    245: // src - dst - X を計算し、XNZVC フラグをセットして結果を返す。
                    246: uint32
                    247: m680x0ACC::subx_32(uint32 src, uint32 dst)
                    248: {
                    249:        uint64 res = (uint64)dst - (uint64)src - (IsX() ? 1 : 0);
                    250:        C = res >> 32;
                    251:        X = C;
                    252:        N = res;
                    253:        // 結果がゼロでなければ Z をクリア、結果がゼロなら Z は何もしない
                    254:        if (N != 0) {
                    255:                Z = N;
                    256:        }
                    257:        V = vflag_sub_32(src, dst, res);
                    258:        return res;
                    259: }
                    260: 
                    261: // src(u16) * dst(u16) を計算し、NZVC フラグをセットして結果(u32)を返す。
                    262: // src, dst の上位ビットはクリアしておくこと。
                    263: uint32
                    264: m680x0ACC::mulu_16(uint32 src, uint32 dst)
                    265: {
                    266:        uint32 res = src * dst;
                    267:        // 16x16->32 ではオーバーフローは起きないので move でよい
                    268:        move_32(res);
                    269:        return res;
                    270: }
                    271: 
                    272: // src(s16) * dst(s16) を計算し、NZVC フラグをセットして結果(u32)を返す。
                    273: // src, dst の上位ビットはクリアしておくこと。
                    274: uint32
                    275: m680x0ACC::muls_16(uint32 src, uint32 dst)
                    276: {
                    277:        int32 res = (int32)(int16)src * (int32)(int16)dst;
                    278:        // 16x16->32 ではオーバーフローは起きないので move でよい
                    279:        move_32(res);
                    280:        return res;
                    281: }
                    282: 
                    283: // src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
                    284: uint32
                    285: m680x0ACC::mulu_32(uint32 src, uint32 dst)
                    286: {
                    287:        uint64 res = (uint64)src * (uint64)dst;
                    288:        Z = res;
                    289:        N = res;
                    290:        C = 0;
                    291:        if (res > 0xffffffffUL) {
                    292:                V = V_BIT;
                    293:        } else {
                    294:                V = 0;
                    295:        }
                    296:        return (uint32)res;
                    297: }
                    298: 
                    299: // src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(32bit)を返す。
                    300: uint32
                    301: m680x0ACC::muls_32(uint32 src, uint32 dst)
                    302: {
                    303:        int64 res = (int64)(int32)src * (int64)(int32)dst;
                    304:        Z = res;
                    305:        N = res;
                    306:        C = 0;
                    307:        // V フラグは64ビット演算結果の上位32ビットが
                    308:        // 下位32ビットの符号拡張になっていなかった場合に立つ。
                    309:        // つまり符号付き整数で 32bit 表現と 64bit 表現が一致していなければ立つ。
                    310:        int32 tmp = res;
                    311:        if (res != tmp) {
                    312:                V = V_BIT;
                    313:        } else {
                    314:                V = 0;
                    315:        }
                    316:        return (uint32)res;
                    317: }
                    318: 
                    319: // src(u32) * dst(u32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
                    320: uint64
                    321: m680x0ACC::mulu_64(uint32 src, uint32 dst)
                    322: {
                    323:        uint64 res = (uint64)src * (uint64)dst;
                    324:        N = res >> 32;
                    325:        Z = N | res;
                    326:        V = 0;
                    327:        C = 0;
                    328:        return res;
                    329: }
                    330: 
                    331: // src(s32) * dst(s32) を計算し、NZVC フラグをセットして結果(64bit)を返す。
                    332: uint64
                    333: m680x0ACC::muls_64(uint32 src, uint32 dst)
                    334: {
                    335:        int64 res = (int64)(int32)src * (int64)(int32)dst;
                    336:        N = res >> 32;
                    337:        Z = N | res;
                    338:        V = 0;
                    339:        C = 0;
                    340:        return res;
                    341: }
                    342: 
                    343: void
                    344: m680x0ACC::btst(uint32 data, int n)
                    345: {
1.1.1.2 ! root      346:        Z = data & (1U << n);
1.1       root      347: }
                    348: 
                    349: uint32
                    350: m680x0ACC::bchg(uint32 data, int n)
                    351: {
1.1.1.2 ! root      352:        Z = data & (1U << n);
        !           353:        data ^= (1U << n);
1.1       root      354:        return data;
                    355: }
                    356: 
                    357: uint32
                    358: m680x0ACC::bclr(uint32 data, int n)
                    359: {
1.1.1.2 ! root      360:        Z = data & (1U << n);
        !           361:        data &= ~(1U << n);
1.1       root      362:        return data;
                    363: }
                    364: 
                    365: uint32
                    366: m680x0ACC::bset(uint32 data, int n)
                    367: {
1.1.1.2 ! root      368:        Z = data & (1U << n);
        !           369:        data |= (1U << n);
1.1       root      370:        return data;
                    371: }
                    372: 
                    373: 
                    374: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
                    375: // count は 0..63。data の上位はクリアしておくこと。
                    376: uint32
                    377: m680x0ACC::asl_8(uint32 data, int count)
                    378: {
                    379:        if (count == 0) {
                    380:                move_8(data);
                    381:                return data;
                    382:        }
                    383:        int64 tmps = (int64)(int8)data;
                    384:        if (count > 8) count = 9;
                    385:        uint64 tmp = (uint64)tmps << count;
                    386:        X = C = tmp >> 8;
                    387:        N = tmp << 24;
                    388:        Z = N;
                    389:        // 送り出された全てのビットが元の MSB と一致すれば V=0
                    390:        SetV(((int64)tmp >> 7) != (tmps >> 8));
                    391:        return tmp & 0xff;
                    392: }
                    393: 
                    394: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
                    395: // count は 0..63。data の上位はクリアしておくこと。
                    396: uint32
                    397: m680x0ACC::asl_16(uint32 data, int count)
                    398: {
                    399:        if (count == 0) {
                    400:                move_16(data);
                    401:                return data;
                    402:        }
                    403:        int64 tmps = (int64)(int16)data;
                    404:        if (count > 16) count = 17;
                    405:        uint64 tmp = (uint64)tmps << count;
                    406:        X = C = tmp >> 16;
                    407:        N = tmp << 16;
                    408:        Z = N;
                    409:        // 送り出された全てのビットが元の MSB と一致すれば V=0
                    410:        SetV(((int64)tmp >> 15) != (tmps >> 16));
                    411:        return tmp & 0xffff;
                    412: }
                    413: 
                    414: // data を count ビット算術左シフトし、XNZVC フラグを反映して結果を返す。
                    415: // count は 0..63
                    416: uint32
                    417: m680x0ACC::asl_32(uint32 data, int count)
                    418: {
                    419:        if (count == 0) {
                    420:                move_32(data);
                    421:                return data;
                    422:        }
                    423:        int64 tmps = (int64)(int32)data;
                    424:        if (count > 32) count = 33;
                    425:        uint64 tmp = (uint64)tmps << count;
                    426:        X = C = tmp >> 32;
                    427:        N = Z = tmp;
                    428:        // 送り出された全てのビットが元の MSB と一致すれば V=0
                    429:        SetV(((int64)tmp >> 31) != (tmps >> 32));
                    430:        return tmp;
                    431: }
                    432: 
                    433: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
                    434: // count は 0..63。data の上位はクリアしておくこと。
                    435: uint32
                    436: m680x0ACC::lsl_8(uint32 data, int count)
                    437: {
                    438:        if (count == 0) {
                    439:                move_8(data);
                    440:                return data;
                    441:        }
                    442:        uint64 tmp = (uint64)data << count;
                    443:        X = C = tmp >> 8;
                    444:        N = tmp << 24;
                    445:        Z = tmp & 0xff;
                    446:        V = 0;
                    447:        return Z;
                    448: }
                    449: 
                    450: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
                    451: // count は 0..63。data の上位はクリアしておくこと。
                    452: uint32
                    453: m680x0ACC::lsl_16(uint32 data, int count)
                    454: {
                    455:        if (count == 0) {
                    456:                move_16(data);
                    457:                return data;
                    458:        }
                    459:        uint64 tmp = (uint64)data << count;
                    460:        X = C = tmp >> 16;
                    461:        N = tmp << 16;
                    462:        Z = tmp & 0xffff;
                    463:        V = 0;
                    464:        return Z;
                    465: }
                    466: 
                    467: // data を count ビット左シフトし、NZVC フラグを反映して結果を返す。
                    468: // count は 0..63
                    469: uint32
                    470: m680x0ACC::lsl_32(uint32 data, int count)
                    471: {
                    472:        if (count == 0) {
                    473:                move_32(data);
                    474:                return data;
                    475:        }
                    476:        uint64 tmp = (uint64)data << count;
                    477:        X = C = tmp >> 32;
                    478:        N = tmp;
                    479:        Z = tmp;
                    480:        V = 0;
                    481:        return Z;
                    482: }
                    483: 
                    484: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
                    485: // count は 0..63
                    486: uint32
                    487: m680x0ACC::roxl_8(uint32 data, int count)
                    488: {
                    489:        count %= 9;
                    490:        if (count == 0) {
                    491:                Z = data;
                    492:                N = data << 24;
                    493:                V = 0;
                    494:                C = X;
                    495:                return Z;
                    496:        }
                    497:        uint32 xbit = X & 1;
                    498:        Z = (data << count) | (data >> (9 - count)) | (xbit << (count - 1));
                    499:        C = X = Z >> 8;
                    500:        Z &= 0xff;
                    501:        N = Z << 24;
                    502:        V = 0;
                    503:        return Z;
                    504: }
                    505: 
                    506: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
                    507: // count は 0..63
                    508: uint32
                    509: m680x0ACC::roxl_16(uint32 data, int count)
                    510: {
                    511:        count %= 17;
                    512:        if (count == 0) {
                    513:                Z = data;
                    514:                N = data << 16;
                    515:                V = 0;
                    516:                C = X;
                    517:                return Z;
                    518:        }
                    519:        uint32 xbit = X & 1;
                    520:        Z = (data << count) | (data >> (17 - count)) | (xbit << (count - 1));
                    521:        C = X = Z >> 16;
                    522:        Z &= 0xffff;
                    523:        N = Z << 16;
                    524:        V = 0;
                    525:        return Z;
                    526: }
                    527: 
                    528: // data:X を count ビット左ローテートし、XNZVC フラグを反映して結果を返す。
                    529: // count は 0..63
                    530: uint32
                    531: m680x0ACC::roxl_32(uint32 data, int count)
                    532: {
                    533:        count %= 33;
                    534:        if (count == 0) {
                    535:                Z = data;
                    536:                N = data;
                    537:                V = 0;
                    538:                C = X;
                    539:                return Z;
                    540:        }
                    541:        // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
                    542:        uint64 data64 = data;
                    543:        uint32 xbit = X & 1;
                    544:        Z = (data64 << count) | (data64 >> (33 - count)) | (xbit << (count - 1));
                    545:        C = X = data64 >> (32 - count);
                    546:        N = Z;
                    547:        V = 0;
                    548:        return Z;
                    549: }
                    550: 
                    551: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
                    552: // count は 0..63。data の上位はクリアしておくこと
                    553: uint32
                    554: m680x0ACC::rol_8(uint32 data, int count)
                    555: {
                    556:        if (count == 0) {
                    557:                move_8(data);
                    558:                return data;
                    559:        }
                    560: 
                    561:        count %= 8;
                    562:        int count2 = (8 - count) % 8;
                    563:        uint8 tmp = (data << count) | (data >> count2);
                    564:        Z = tmp;
                    565:        N = (uint32)tmp << 24;
                    566:        C = data >> count2;
                    567:        V = 0;
                    568:        return Z;
                    569: }
                    570: 
                    571: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
                    572: // count は 0..63。data の上位はクリアしておくこと
                    573: uint32
                    574: m680x0ACC::rol_16(uint32 data, int count)
                    575: {
                    576:        if (count == 0) {
                    577:                move_16(data);
                    578:                return data;
                    579:        }
                    580: 
                    581:        count %= 16;
                    582:        int count2 = (16 - count) % 16;
                    583:        uint16 tmp = (data << count) | (data >> count2);
                    584:        Z = tmp;
                    585:        N = (uint32)tmp << 16;
                    586:        C = data >> count2;
                    587:        V = 0;
                    588:        return Z;
                    589: }
                    590: 
                    591: // data を count ビット左ローテートし、NZVC フラグを反映して結果を返す。
                    592: // count は 0..63
                    593: uint32
                    594: m680x0ACC::rol_32(uint32 data, int count)
                    595: {
                    596:        if (count == 0) {
                    597:                move_32(data);
                    598:                return data;
                    599:        }
                    600: 
                    601:        count %= 32;
                    602:        int count2 = (32 - count) % 32;
                    603:        uint64 data64 = (uint64)data;
                    604:        uint64 tmp = (data << count) | (data >> count2);
                    605:        Z = tmp;
                    606:        N = Z;
                    607:        C = data64 >> count2;
                    608:        V = 0;
                    609:        return Z;
                    610: }
                    611: 
                    612: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
                    613: // count は 0..64。data の上位はクリアしておくこと。
                    614: uint32
                    615: m680x0ACC::asr_8(uint32 data, int count)
                    616: {
                    617:        if (count == 0) {
                    618:                move_8(data);
                    619:                return data;
                    620:        }
                    621:        if (count > 8) {
                    622:                if ((int8)data < 0) {
                    623:                        data = 0xff;
                    624:                } else {
                    625:                        data = 0;
                    626:                }
                    627:                X = C = Z = data;
                    628:                N = data << 24;
                    629:                V = 0;
                    630:                return data;
                    631:        }
                    632:        // data >>> count の結果が tmp の上位32ビット中の下位8ビットに入る
                    633:        uint64 tmp = (uint64)(int64)(int8)data << (32 - count);
                    634:        X = C = tmp >> 31;
                    635:        N = tmp >> 8;
                    636:        Z = (tmp >> 32) & 0xff;
                    637:        V = 0;
                    638:        return Z;
                    639: }
                    640: 
                    641: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
                    642: // count は 0..64。data の上位はクリアしておくこと。
                    643: uint32
                    644: m680x0ACC::asr_16(uint32 data, int count)
                    645: {
                    646:        if (count == 0) {
                    647:                move_16(data);
                    648:                return data;
                    649:        }
                    650:        if (count > 16) {
                    651:                if ((int16)data < 0) {
                    652:                        data = 0xffff;
                    653:                } else {
                    654:                        data = 0;
                    655:                }
                    656:                X = C = Z = data;
                    657:                N = data << 16;
                    658:                V = 0;
                    659:                return data;
                    660:        }
                    661:        // data >>> count の結果が tmp の上位32ビット中の下位16ビットに入る
                    662:        uint64 tmp = (uint64)(int64)(int16)data << (32 - count);
                    663:        X = C = tmp >> 31;
                    664:        N = tmp >> 16;
                    665:        Z = (tmp >> 32) & 0xffff;
                    666:        V = 0;
                    667:        return Z;
                    668: }
                    669: 
                    670: // data を count ビット算術右シフトし、XNZVC フラグを反映して結果を返す。
                    671: // count は 0..64
                    672: uint32
                    673: m680x0ACC::asr_32(uint32 data, int count)
                    674: {
                    675:        if (count == 0) {
                    676:                move_32(data);
                    677:                return data;
                    678:        }
                    679:        if (count > 32) {
                    680:                if ((int32)data < 0) {
                    681:                        data = 0xffffffff;
                    682:                } else {
                    683:                        data = 0;
                    684:                }
                    685:                X = C = Z = data;
                    686:                N = data;
                    687:                V = 0;
                    688:                return data;
                    689:        }
                    690:        // data >>> count の結果が tmp の上位32ビットに入る
                    691:        uint64 tmp = (uint64)(int64)(int32)data << (32 - count);
                    692:        X = C = tmp >> 31;
                    693:        Z = N = tmp >> 32;
                    694:        V = 0;
                    695:        return Z;
                    696: }
                    697: 
                    698: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
                    699: // count は 0..63
                    700: uint32
                    701: m680x0ACC::lsr_8(uint32 data, int count)
                    702: {
                    703:        if (count == 0) {
                    704:                move_8(data);
                    705:                return data;
                    706:        }
                    707:        if (count > 8) {
                    708:                X = C = 0;
                    709:                move_8(0);
                    710:                return 0;
                    711:        }
                    712:        // data >> count の結果が tmp の上位32ビットに入る
                    713:        uint64 tmp = (uint64)data << (32 - count);
                    714:        X = C = tmp >> 31;
                    715:        N = tmp >> 8;
                    716:        Z = (tmp >> 32) & 0xff;
                    717:        V = 0;
                    718:        return Z;
                    719: }
                    720: 
                    721: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
                    722: // count は 0..63
                    723: uint32
                    724: m680x0ACC::lsr_16(uint32 data, int count)
                    725: {
                    726:        if (count == 0) {
                    727:                move_16(data);
                    728:                return data;
                    729:        }
                    730:        if (count > 16) {
                    731:                X = C = 0;
                    732:                move_16(0);
                    733:                return 0;
                    734:        }
                    735:        // data >> count の結果が tmp の上位32ビットに入る
                    736:        uint64 tmp = (uint64)data << (32 - count);
                    737:        X = C = tmp >> 31;
                    738:        N = tmp >> 16;
                    739:        Z = (tmp >> 32) & 0xffff;
                    740:        V = 0;
                    741:        return Z;
                    742: }
                    743: 
                    744: // data を count ビット論理右シフトし、XNZVC フラグを反映して結果を返す。
                    745: // count は 0..63
                    746: uint32
                    747: m680x0ACC::lsr_32(uint32 data, int count)
                    748: {
                    749:        if (count == 0) {
                    750:                move_32(data);
                    751:                return data;
                    752:        }
                    753:        if (count > 32) {
                    754:                X = C = 0;
                    755:                move_32(0);
                    756:                return 0;
                    757:        }
                    758:        // data >> count の結果が tmp の上位32ビットに入る
                    759:        uint64 tmp = (uint64)data << (32 - count);
                    760:        X = C = tmp >> 31;
                    761:        Z = N = tmp >> 32;
                    762:        V = 0;
                    763:        return Z;
                    764: }
                    765: 
                    766: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
                    767: // count は 0..63
                    768: uint32
                    769: m680x0ACC::roxr_8(uint32 data, int count)
                    770: {
                    771:        count %= 9;
                    772:        if (count == 0) {
                    773:                Z = data;
                    774:                N = data << 24;
                    775:                V = 0;
                    776:                C = X;
                    777:                return Z;
                    778:        }
1.1.1.2 ! root      779:        uint32 rot = data & ((1U << (count - 1)) - 1);
1.1       root      780:        uint32 xbit = X & 1;
                    781:        Z = (data >> count) | (rot << (9 - count)) | (xbit << (8 - count));
                    782:        C = X = data >> (count - 1);
                    783:        N = Z << 24;
                    784:        V = 0;
                    785:        return Z;
                    786: }
                    787: 
                    788: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
                    789: // count は 0..63
                    790: uint32
                    791: m680x0ACC::roxr_16(uint32 data, int count)
                    792: {
                    793:        count %= 17;
                    794:        if (count == 0) {
                    795:                Z = data;
                    796:                N = data << 16;
                    797:                V = 0;
                    798:                C = X;
                    799:                return Z;
                    800:        }
1.1.1.2 ! root      801:        uint32 rot = data & ((1U << (count - 1)) - 1);
1.1       root      802:        uint32 xbit = X & 1;
                    803:        Z = (data >> count) | (rot << (17 - count)) | (xbit << (16 - count));
                    804:        C = X = data >> (count - 1);
                    805:        N = Z << 16;
                    806:        V = 0;
                    807:        return Z;
                    808: }
                    809: 
                    810: // data:C を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
                    811: // count は 0..63
                    812: uint32
                    813: m680x0ACC::roxr_32(uint32 data, int count)
                    814: {
                    815:        count %= 33;
                    816:        if (count == 0) {
                    817:                Z = data;
                    818:                N = data;
                    819:                V = 0;
                    820:                C = X;
                    821:                return Z;
                    822:        }
                    823:        // 32bit値の 32ビットシフトは未定義動作なので 64bit値を使用
                    824:        uint64 data64 = data;
1.1.1.2 ! root      825:        uint64 rot = data64 & ((1U << (count - 1)) - 1);
1.1       root      826:        uint32 xbit = X & 1;
                    827:        Z = (data64 >> count) | (rot << (33 - count)) | (xbit << (32 - count));
                    828:        C = X = data64 >> (count - 1);
                    829:        N = Z;
                    830:        V = 0;
                    831:        return Z;
                    832: }
                    833: 
                    834: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
                    835: // count は 0..63
                    836: uint32
                    837: m680x0ACC::ror_8(uint32 data, int count)
                    838: {
                    839:        if (count == 0) {
                    840:                move_8(data);
                    841:                return data;
                    842:        }
                    843: 
                    844:        count %= 8;
                    845:        uint8 tmp = (data >> count) | (data << (8 - count));
                    846:        Z = tmp;
                    847:        N = (uint32)tmp << 24;
                    848:        // 7 0 1 2 3 4 5 6
                    849:        C = data >> ((count + 7) % 8);
                    850:        V = 0;
                    851:        return tmp;
                    852: }
                    853: 
                    854: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
                    855: // count は 0..63
                    856: uint32
                    857: m680x0ACC::ror_16(uint32 data, int count)
                    858: {
                    859:        if (count == 0) {
                    860:                move_16(data);
                    861:                return data;
                    862:        }
                    863: 
                    864:        count %= 16;
                    865:        uint16 tmp = (data >> count) | (data << (16 - count));
                    866:        Z = tmp;
                    867:        N = (uint32)tmp << 16;
                    868:        C = data >> ((count + 15) % 16);
                    869:        V = 0;
                    870:        return tmp;
                    871: }
                    872: 
                    873: // data を count ビット右ローテートし、NZVC フラグを反映して結果を返す。
                    874: // count は 0..63
                    875: uint32
                    876: m680x0ACC::ror_32(uint32 data, int count)
                    877: {
                    878:        if (count == 0) {
                    879:                move_32(data);
                    880:                return data;
                    881:        }
                    882: 
                    883:        count %= 32;
                    884:        uint64 data64 = (uint64)data;
                    885:        uint64 tmp = (data >> count) | (data << (32 - count));
                    886:        Z = tmp;
                    887:        N = tmp;
                    888:        C = data64 >> ((count + 31) % 32);
                    889:        V = 0;
                    890:        return tmp;
                    891: }
                    892: 
                    893: void
                    894: m680x0ACC::chk2cmp2_32(uint32 compare, uint32 lower, uint32 upper)
                    895: {
                    896:        // 実機の実行結果をじっと睨んだ結果、このロジックで
                    897:        // cmp2 は実行していると考えられる。
                    898:        // オペランド順はフラグに影響する。
                    899:        // なぜ 68k のデザイナが順序を入れ替えたのかは不明。
                    900:        // なんかの都合があったんだろうな...
                    901: 
                    902:        // この cmp は通常の if で代替できるけど、
                    903:        // あえて MPU 内部の動作をエミュレート。
                    904:        cmp_32(lower, upper);
                    905: 
                    906:        if (CondCS()) {
                    907:                cmp_32(compare, upper);
                    908:                if (CondEQ()) {
                    909:                        // break
                    910:                } else if (CondCS()) {
                    911:                        cmp_32(lower, compare);
                    912:                } else {
                    913:                        cmp_32(compare, lower);
                    914:                }
                    915:        } else {
                    916:                cmp_32(lower, compare);
                    917:                if (CondEQ()) {
                    918:                        // break
                    919:                } else if (CondCS()) {
                    920:                        // break
                    921:                } else {
                    922:                        cmp_32(compare, upper);
                    923:                }
                    924:        }
                    925: }
                    926: 
                    927: // src_10 + dst_10 + X を計算し、XNZVC フラグをセットして結果を返す。
                    928: // src, dst の上位ビットはクリアしておくこと。
                    929: // 戻り値の上位ビットはクリアされている。
                    930: uint32
                    931: m680x0ACC::abcd_8(uint32 src, uint32 dst)
                    932: {
                    933:        uint32 res;
                    934:        uint32 tmp;
                    935:        uint32 adj;
                    936:        uint32 low;
                    937:        uint32 cbit;
                    938: 
                    939:        adj = 0;
                    940:        cbit = 0;
                    941: 
                    942:        // X フラグは LSB なので直接足してよい
                    943:        tmp = src + dst + (X & X_BIT);
                    944: 
                    945:        low = (src & 0x0f) + (dst & 0x0f) + (X & X_BIT);
                    946:        if (low > 0x09) {
                    947:                adj = 0x06;
                    948:        }
                    949: 
                    950:        if (tmp > 0x99) {
                    951:                adj += 0x60;
                    952:                cbit = C_BIT;
                    953:        }
                    954: 
                    955:        res = tmp + adj;
                    956:        cbit |= res >> 8;
                    957:        X = C = cbit;
                    958: 
                    959:        res &= 0xff;
                    960:        Z |= res;
                    961: 
                    962:        // V フラグは不定だが 68030 では常にクリア
                    963:        V = 0;
                    964:        // N フラグは不定だが 68030 実機合わせ
                    965:        N = res << 24;
                    966: 
                    967:        return res;
                    968: }
                    969: 
                    970: // src_10 - dst_10 - X を計算し、XNZVC フラグをセットして結果を返す。
                    971: // src, dst の上位ビットはクリアしておくこと。
                    972: // 戻り値の上位ビットはクリアされている。
                    973: uint32
                    974: m680x0ACC::sbcd_8(uint32 src, uint32 dst)
                    975: {
                    976:        uint32 res;
                    977:        int32 tmp;
                    978:        int32 adj;
                    979:        int32 low;
                    980:        uint32 cbit;
                    981: 
                    982:        adj = 0;
                    983:        cbit = 0;
                    984: 
                    985:        // X フラグは LSB なので直接引いてよい
                    986:        tmp = dst - src - (X & X_BIT);
                    987: 
                    988:        low = (dst & 0x0f) - (src & 0x0f) - (X & X_BIT);
                    989:        if (low < 0) {
                    990:                adj = 0x06;
                    991:        }
                    992: 
                    993:        if (tmp < 0) {
                    994:                adj += 0x60;
                    995:                cbit = C_BIT;
                    996:        }
                    997: 
                    998:        res = tmp - adj;
                    999:        cbit |= res >> 8;
                   1000:        X = C = cbit;
                   1001: 
                   1002:        res &= 0xff;
                   1003:        Z |= res;
                   1004: 
                   1005:        // V フラグは不定だが 68030 では常にクリア
                   1006:        V = 0;
                   1007:        // N フラグは不定だが 68030 実機合わせ
                   1008:        N = res << 24;
                   1009: 
                   1010:        return res;
                   1011: }

unix.superglobalmegacorp.com

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