Annotation of nono/hd64180/hd64180acc.cpp, revision 1.1.1.2

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2022 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // HD64180 演算部分
                      9: //
                     10: 
                     11: #include "hd64180acc.h"
                     12: 
                     13: /*static*/ inline uint32
                     14: hd64180acc::vflag_add(uint32 dst, uint32 src, uint32 res)
                     15: {
                     16:        return (src ^ res) & (dst ^ res);
                     17: }
                     18: 
                     19: /*static*/ inline uint32
                     20: hd64180acc::vflag_sub(uint32 dst, uint32 src, uint32 res)
                     21: {
                     22:        return (src ^ dst) & (dst ^ res);
                     23: }
                     24: 
                     25: /*static*/ inline uint32
                     26: hd64180acc::hflag_add(uint32 dst, uint32 src)
                     27: {
                     28:        return (dst & 0x0f) + (src & 0x0f);
                     29: }
                     30: 
                     31: /*static*/ inline uint32
                     32: hd64180acc::hflag_sub(uint32 dst, uint32 src)
                     33: {
                     34:        return (dst & 0x0f) - (src & 0x0f);
                     35: }
                     36: 
                     37: // LD A,I、LD A,R 命令のフラグ変化。
                     38: // S:* Z:* H:0 P/V:IEF2 N:0 C:-
                     39: uint32
                     40: hd64180acc::ld_ir8(uint32 src)
                     41: {
                     42:        // P/V (IEF2) は呼び出し側で行う。
                     43: 
                     44:        S = Z = src;
                     45:        SetH(false);
                     46:        SetN(false);
                     47:        return Z;
                     48: }
                     49: 
                     50: // save_c が true なら C を変更しない。
                     51: // S:* Z:* H:* V:* N:0 C:*/-
                     52: uint32
                     53: hd64180acc::add_8(uint32 dst, uint32 src, bool save_c)
                     54: {
                     55:        if (save_c) {
                     56:                Z = dst + src;
                     57:        } else {
                     58:                CZ = dst + src;
                     59:        }
                     60:        S = Z;
                     61:        H = hflag_add(dst, src);
                     62:        LetV(vflag_add(dst, src, Z));
                     63:        SetN(false);
                     64: 
                     65:        return (uint8)Z;
                     66: }
                     67: 
                     68: // save_c が true なら C を変更しない。
                     69: // S:* Z:* H:* V:* N:0 C:*/-
                     70: uint32
                     71: hd64180acc::sub_8(uint32 dst, uint32 src, bool save_c)
                     72: {
                     73:        if (save_c) {
                     74:                Z = dst - src;
                     75:        } else {
                     76:                CZ = dst - src;
                     77:        }
                     78:        S = Z;
                     79:        H = hflag_sub(dst, src);
                     80:        LetV(vflag_sub(dst, src, Z));
                     81:        SetN(true);
                     82: 
                     83:        return (uint8)Z;
                     84: }
                     85: 
                     86: // S:* Z:* H:* V:* N:0 C:*
                     87: uint32
                     88: hd64180acc::adc_8(uint32 dst, uint32 src)
                     89: {
                     90:        uint32 cin = IsC() ? 1 : 0;
                     91:        uint32 res = dst + src + cin;
                     92: 
                     93:        CZ = res;
                     94:        S = res;
                     95:        LetV(vflag_add(dst, src, res));
                     96:        H  = hflag_add(dst, src);
                     97:        H |= hflag_add(H, cin);
                     98:        SetN(false);
                     99: 
                    100:        return Z;
                    101: }
                    102: 
                    103: // S:* Z:* H:* V:* N:0 C:*
                    104: uint32
                    105: hd64180acc::sbc_8(uint32 dst, uint32 src)
                    106: {
                    107:        uint32 cin = IsC() ? 1 : 0;
                    108:        uint32 res = dst - src - cin;
                    109: 
                    110:        CZ = res;
                    111:        S = res;
                    112:        LetV(vflag_sub(dst, src, res));
                    113:        H  = hflag_sub(dst, src);
                    114:        H |= hflag_sub(H, cin);
                    115:        SetN(true);
                    116: 
                    117:        return Z;
                    118: }
                    119: 
                    120: // S:- Z:- H:X PV:- N:0 C:*
                    121: uint32
                    122: hd64180acc::add_16(uint32 dst, uint32 src)
                    123: {
                    124:        uint32 res = dst + src;
                    125:        C = res >> 16;
                    126:        SetN(false);
                    127:        // XXX H は不定
                    128: 
                    129:        return res;
                    130: }
                    131: 
                    132: // S:* Z:* H:X V:* N:0 C:*
                    133: uint32
                    134: hd64180acc::adc_16(uint32 dst, uint32 src)
                    135: {
                    136:        // V のために2回に分けて計算しないといけない?
                    137:        uint32 res = dst + src;
                    138:        uint32 v = vflag_add(dst, src, res);
                    139: 
                    140:        dst = res;
                    141:        src = IsC() ? 1 : 0;
                    142:        res = dst + src;
                    143:        v |= vflag_add(dst, src, res);
                    144: 
                    145:        LetV((uint32)(v >> 8));
                    146: 
                    147:        // C, S, Z は 16bit が対象でいい?
                    148:        C = res >> 16;
                    149:        S = res >> 8;
                    150:        Z = res | S;
                    151: 
                    152:        SetN(false);
                    153: 
                    154:        // XXX H は本当は不定
                    155: 
                    156:        return res;
                    157: }
                    158: 
                    159: // S:* Z:* H:X V:* N:1 C:*
                    160: uint32
                    161: hd64180acc::sbc_16(uint32 dst, uint32 src)
                    162: {
                    163:        // V のために2回に分けて計算しないといけない?
                    164:        uint32 res = dst - src;
                    165:        uint32 v = vflag_sub(dst, src, res);
                    166: 
                    167:        dst = res;
                    168:        src = IsC() ? 1 : 0;
                    169:        res = dst - src;
                    170:        v |= vflag_sub(dst, src, res);
                    171: 
                    172:        LetV((uint32)(v >> 8));
                    173: 
                    174:        // C, S, Z は 16bit が対象でいい?
                    175:        C = res >> 16;
                    176:        S = res >> 8;
                    177:        Z = res | S;
                    178: 
                    179:        SetN(true);
                    180: 
                    181:        // XXX H は本当は不定
                    182: 
                    183:        return res;
                    184: }
                    185: 
                    186: // BIT 命令
                    187: // S:X Z:* H:1 PV:X N:0 C:-
                    188: void
                    189: hd64180acc::bit_8(uint b, uint32 src)
                    190: {
                    191:        Z = src & (1U << b);
                    192:        SetH(true);
                    193:        SetN(false);
                    194:        // XXX S, P(V) は本当は不定
                    195: }
                    196: 
                    197: // IN A,(n) 命令のフラグ変化。他からも色々呼ばれる。
                    198: // S:* Z:* H:0 P:* N:0 C:-
                    199: uint32
                    200: hd64180acc::in_8(uint32 src)
                    201: {
                    202:        S = Z = src;
                    203:        SetN(false);
                    204:        SetH(false);
                    205:        LetP(Z);
                    206:        return Z;
                    207: }
                    208: 
                    209: // OTIM/OTDM 命令のフラグ変化。
                    210: // 戻り値は演算後の B レジスタの値。
                    211: // HD64180.pdf p.110
                    212: // S:* Z:* H:* P:* N:* C:*
                    213: uint32
                    214: hd64180acc::outm_8(uint32 src, uint32 breg)
                    215: {
                    216:        CZ = breg - 1;
                    217:        S = Z;
                    218:        H = hflag_sub(breg, 1);
                    219:        LetP(Z);                        // 減算後の B のパリティ
                    220:        N = (src & 0x80);       // (HL) の MSB
                    221: 
                    222:        return Z;
                    223: }
                    224: 
                    225: // S:* Z:* H:1 P:* N:0 C:0
                    226: uint32
                    227: hd64180acc::and_8(uint32 dst, uint32 src)
                    228: {
                    229:        uint32 res;
                    230:        SetC(false);
                    231:        res = in_8(dst & src);
                    232:        SetH(true);                     // これだけ H はセット
                    233:        return res;
                    234: }
                    235: 
                    236: // S:* Z:* H:0 P:* N:0 C:0
                    237: uint32
                    238: hd64180acc::or_8(uint32 dst, uint32 src)
                    239: {
                    240:        SetC(false);
                    241:        return in_8(dst | src);
                    242: }
                    243: 
                    244: // S:* Z:* H:0 P:* N:0 C:0
                    245: uint32
                    246: hd64180acc::xor_8(uint32 dst, uint32 src)
                    247: {
                    248:        SetC(false);
                    249:        return in_8(dst ^ src);
                    250: }
                    251: 
                    252: // S:* Z:* H:1 P:* N:0 C:0
                    253: void
                    254: hd64180acc::tst_8(uint32 dst, uint32 src)
                    255: {
                    256:        in_8(dst & src);
                    257:        SetH(true);
                    258:        SetC(false);
                    259: }
                    260: 
                    261: // S:* Z:* H:0 P:* N:0 C:*
                    262: uint32
                    263: hd64180acc::sla_8(uint32 src)
                    264: {
                    265:        CZ = src << 1;
                    266:        return in_8(Z);
                    267: }
                    268: 
                    269: // S:* Z:* H:0 P:* N:0 C:*
                    270: uint32
                    271: hd64180acc::sra_8(uint32 src)
                    272: {
                    273:        C = src;
                    274:        Z = (src >> 1);
                    275:        Z |= src & 0x80;
                    276:        return in_8(Z);
                    277: }
                    278: 
                    279: // S:* Z:* H:0 P:* N:0 C:*
                    280: uint32
                    281: hd64180acc::srl_8(uint32 src)
                    282: {
                    283:        C = src;
                    284:        Z = src >> 1;
                    285:        return in_8(Z);
                    286: }
                    287: 
                    288: //       S Z H P N C
                    289: // RLA   - - 0 - 0 * : rl_8()
                    290: // RL r  * * 0 P 0 * : in_8(rl_8())
                    291: // RLD   * * 0 P 0 - : in_8()
                    292: 
                    293: uint32
                    294: hd64180acc::rl_8(uint32 src)
                    295: {
                    296:        src <<= 1;
                    297:        if (IsC()) {
                    298:                src |= 0x01;
                    299:        }
                    300:        C = src >> 8;
                    301: 
                    302:        SetN(false);
                    303:        SetH(false);
                    304: 
                    305:        return (uint8)src;
                    306: }
                    307: 
                    308: uint32
                    309: hd64180acc::rlc_8(uint32 src)
                    310: {
                    311:        src <<= 1;
                    312:        if ((src & 0x100)) {
                    313:                src |= 0x01;
                    314:        }
                    315:        C = src >> 8;
                    316: 
                    317:        SetN(false);
                    318:        SetH(false);
                    319: 
                    320:        return (uint8)src;
                    321: }
                    322: 
                    323: uint32
                    324: hd64180acc::rr_8(uint32 src)
                    325: {
                    326:        src = (uint8)src;
                    327:        if (IsC()) {
                    328:                src |= 0x100;
                    329:        }
                    330:        C = src;
                    331:        src >>= 1;
                    332: 
                    333:        SetN(false);
                    334:        SetH(false);
                    335: 
                    336:        return (uint8)src;
                    337: }
                    338: 
                    339: uint32
                    340: hd64180acc::rrc_8(uint32 src)
                    341: {
                    342:        C = src;
                    343:        src = (uint8)src;
                    344:        src |= (C << 8);
                    345:        src >>= 1;
                    346: 
                    347:        SetN(false);
                    348:        SetH(false);
                    349: 
                    350:        return (uint8)src;
                    351: }
1.1.1.2 ! root      352: 
        !           353: uint32
        !           354: hd64180acc::daa_8(uint32 src)
        !           355: {
        !           356:        uint32 ah;
        !           357:        uint32 al;
        !           358:        uint32 b;
        !           359:        uint32 res;
        !           360: 
        !           361:        if (IsN() == false) {
        !           362:                bool tmpC = IsC();      // 入力時の状態
        !           363:                bool tmpH = IsH();
        !           364: 
        !           365:                bool resC = IsC();      // 出力用。C は入力と内部演算の和
        !           366:                bool resH;                      // 出力用。H は内部演算のみの和
        !           367: 
        !           368:                // 下位桁
        !           369:                ah = src >> 4;
        !           370:                al = src & 0xf;
        !           371:                if (al >= 0x0a || IsH()) {
        !           372:                        b = 0x06;
        !           373:                } else {
        !           374:                        b = 0;
        !           375:                }
        !           376:                src = add_8(src, b);
        !           377:                resC |= IsC();
        !           378:                resH  = IsH();
        !           379: 
        !           380:                // 上位桁
        !           381:                ah = src >> 4;
        !           382:                al = src & 0xf;
        !           383:                if (ah >= 0x0a || tmpC) {
        !           384:                        b = 0x60;
        !           385: 
        !           386:                        // XXX 入力が 9A-9F で H=1 C=0 の時、
        !           387:                        // 下位桁を補正して(6を足して) 上位桁が A になるのに、
        !           388:                        // HD64180 ではこれを補正してないようだ。
        !           389:                        if (0xa0 <= src && src < 0xa6 && tmpH && tmpC == false) {
        !           390:                                b = 0;
        !           391:                        }
        !           392:                } else {
        !           393:                        b = 0;
        !           394: 
        !           395:                        // XXX 入力が FA-FF で C=0 の時、
        !           396:                        // 下位桁を補正して(6 を足して) C=1 00-05 に繰り上がるだけの
        !           397:                        // はずが、HD64180 では 60 も足してしまうようだ。
        !           398:                        if (IsC() && ah == 0x00 && tmpC == false) {
        !           399:                                b = 0x60;
        !           400:                        }
        !           401:                }
        !           402:                res = add_8(src, b);
        !           403:                resC |= IsC();
        !           404:                resH |= IsH();
        !           405: 
        !           406:                SetH(resH);
        !           407:                SetC(resC);
        !           408:        } else {
        !           409:                // N==1 (減算) 側は跡形なく動作が違う。
        !           410:                // 意味はさっぱり分からんけどとりあえず実機と同じ動作。
        !           411: 
        !           412:                bool resC = IsC();
        !           413:                b = 0;
        !           414:                if (IsH()) {
        !           415:                        b += 0x06;
        !           416:                        if (src < 0x06) {
        !           417:                                resC = true;
        !           418:                        }
        !           419:                }
        !           420:                if (IsC()) {
        !           421:                        b += 0x60;
        !           422:                }
        !           423:                res = sub_8(src, b);
        !           424: 
        !           425:                SetC(resC);
        !           426:        }
        !           427: 
        !           428:        // P/V フラグは P
        !           429:        LetP(res);
        !           430: 
        !           431:        return res;
        !           432: }

unix.superglobalmegacorp.com

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