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

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
1.1.1.3   root      281: hd64180acc::sll_8(uint32 src)
                    282: {
                    283:        // bit0 に %1 が入るようだ
                    284:        // http://www.z80.info/z80sflag.htm
                    285:        CZ = (src << 1) | 1;
                    286:        return in_8(Z);
                    287: }
                    288: 
                    289: // S:* Z:* H:0 P:* N:0 C:*
                    290: uint32
1.1       root      291: hd64180acc::srl_8(uint32 src)
                    292: {
                    293:        C = src;
                    294:        Z = src >> 1;
                    295:        return in_8(Z);
                    296: }
                    297: 
                    298: //       S Z H P N C
                    299: // RLA   - - 0 - 0 * : rl_8()
                    300: // RL r  * * 0 P 0 * : in_8(rl_8())
                    301: // RLD   * * 0 P 0 - : in_8()
                    302: 
                    303: uint32
                    304: hd64180acc::rl_8(uint32 src)
                    305: {
                    306:        src <<= 1;
                    307:        if (IsC()) {
                    308:                src |= 0x01;
                    309:        }
                    310:        C = src >> 8;
                    311: 
                    312:        SetN(false);
                    313:        SetH(false);
                    314: 
                    315:        return (uint8)src;
                    316: }
                    317: 
                    318: uint32
                    319: hd64180acc::rlc_8(uint32 src)
                    320: {
                    321:        src <<= 1;
                    322:        if ((src & 0x100)) {
                    323:                src |= 0x01;
                    324:        }
                    325:        C = src >> 8;
                    326: 
                    327:        SetN(false);
                    328:        SetH(false);
                    329: 
                    330:        return (uint8)src;
                    331: }
                    332: 
                    333: uint32
                    334: hd64180acc::rr_8(uint32 src)
                    335: {
                    336:        src = (uint8)src;
                    337:        if (IsC()) {
                    338:                src |= 0x100;
                    339:        }
                    340:        C = src;
                    341:        src >>= 1;
                    342: 
                    343:        SetN(false);
                    344:        SetH(false);
                    345: 
                    346:        return (uint8)src;
                    347: }
                    348: 
                    349: uint32
                    350: hd64180acc::rrc_8(uint32 src)
                    351: {
                    352:        C = src;
                    353:        src = (uint8)src;
                    354:        src |= (C << 8);
                    355:        src >>= 1;
                    356: 
                    357:        SetN(false);
                    358:        SetH(false);
                    359: 
                    360:        return (uint8)src;
                    361: }
1.1.1.2   root      362: 
                    363: uint32
                    364: hd64180acc::daa_8(uint32 src)
                    365: {
                    366:        uint32 b;
                    367:        uint32 res;
                    368: 
                    369:        if (IsN() == false) {
                    370:                bool tmpC = IsC();      // 入力時の状態
                    371:                bool tmpH = IsH();
                    372: 
                    373:                bool resC = IsC();      // 出力用。C は入力と内部演算の和
                    374:                bool resH;                      // 出力用。H は内部演算のみの和
                    375: 
                    376:                // 下位桁
1.1.1.4 ! root      377:                uint32 al = src & 0xf;
1.1.1.2   root      378:                if (al >= 0x0a || IsH()) {
                    379:                        b = 0x06;
                    380:                } else {
                    381:                        b = 0;
                    382:                }
                    383:                src = add_8(src, b);
                    384:                resC |= IsC();
                    385:                resH  = IsH();
                    386: 
                    387:                // 上位桁
1.1.1.4 ! root      388:                uint32 ah = src >> 4;
1.1.1.2   root      389:                if (ah >= 0x0a || tmpC) {
                    390:                        b = 0x60;
                    391: 
                    392:                        // XXX 入力が 9A-9F で H=1 C=0 の時、
                    393:                        // 下位桁を補正して(6を足して) 上位桁が A になるのに、
                    394:                        // HD64180 ではこれを補正してないようだ。
                    395:                        if (0xa0 <= src && src < 0xa6 && tmpH && tmpC == false) {
                    396:                                b = 0;
                    397:                        }
                    398:                } else {
                    399:                        b = 0;
                    400: 
                    401:                        // XXX 入力が FA-FF で C=0 の時、
                    402:                        // 下位桁を補正して(6 を足して) C=1 00-05 に繰り上がるだけの
                    403:                        // はずが、HD64180 では 60 も足してしまうようだ。
                    404:                        if (IsC() && ah == 0x00 && tmpC == false) {
                    405:                                b = 0x60;
                    406:                        }
                    407:                }
                    408:                res = add_8(src, b);
                    409:                resC |= IsC();
                    410:                resH |= IsH();
                    411: 
                    412:                SetH(resH);
                    413:                SetC(resC);
                    414:        } else {
                    415:                // N==1 (減算) 側は跡形なく動作が違う。
                    416:                // 意味はさっぱり分からんけどとりあえず実機と同じ動作。
                    417: 
                    418:                bool resC = IsC();
                    419:                b = 0;
                    420:                if (IsH()) {
                    421:                        b += 0x06;
                    422:                        if (src < 0x06) {
                    423:                                resC = true;
                    424:                        }
                    425:                }
                    426:                if (IsC()) {
                    427:                        b += 0x60;
                    428:                }
                    429:                res = sub_8(src, b);
                    430: 
                    431:                SetC(resC);
                    432:        }
                    433: 
                    434:        // P/V フラグは P
                    435:        LetP(res);
                    436: 
                    437:        return res;
                    438: }

unix.superglobalmegacorp.com

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