Annotation of nono/m680x0/m68030bus.cpp, revision 1.1.1.3

1.1       root        1: //
                      2: // nono
1.1.1.3 ! root        3: // Copyright (C) 2020 nono project
        !             4: // Licensed under nono-license.txt
1.1       root        5: //
1.1.1.3 ! root        6: 
1.1       root        7: // 論理アクセス
                      8: 
                      9: //
                     10: // 1回の(アラインド)物理アクセスを担当するマクロ。
                     11: // これらは続く _mmu テンプレートで使用する。
                     12: // goto を含むことに注意。gcc 拡張式(?)に注意。
1.1.1.2   root       13: // mmu_translate_* は fetch, read, write の3種だが、vm_phys_ は
1.1       root       14: // read, write しかないことに注意。物理バスに FC0 と FC1、つまりプログラム
                     15: // 空間かどうかの情報は出していないため。
                     16: //
                     17: 
                     18: #define FETCH(size) ({ \
                     19:        cpu->bus.paddr = cpu->bus.laddr;        \
                     20:        if (use_mmu && m68030_mmu_translate_fetch(cpu) == false)        \
                     21:                goto buserr;    \
1.1.1.2   root       22:        uint64 data_ = vm_phys_read_##size(cpu->bus.paddr);     \
1.1       root       23:        if ((int64)data_ < 0)   \
                     24:                goto buserr;    \
                     25:        data_;  /* これが戻り値 */        \
                     26: })
                     27: 
                     28: #define READ(size) ({  \
                     29:        cpu->bus.paddr = cpu->bus.laddr;        \
                     30:        if (use_mmu && m68030_mmu_translate_read(cpu) == false) \
                     31:                goto buserr;    \
1.1.1.2   root       32:        uint64 data_ = vm_phys_read_##size(cpu->bus.paddr);     \
1.1       root       33:        if ((int64)data_ < 0)   \
                     34:                goto buserr;    \
                     35:        data_;  /* これが戻り値 */        \
                     36: })
                     37: 
                     38: #define WRITE(size, data)      ({      \
                     39:        cpu->bus.paddr = cpu->bus.laddr;        \
                     40:        if (use_mmu && m68030_mmu_translate_write(cpu) == false)        \
                     41:                goto buserr;    \
1.1.1.2   root       42:        int64 berr_ = vm_phys_write_##size(cpu->bus.paddr, (data));     \
1.1       root       43:        if (berr_ < 0)  \
                     44:                goto buserr;    \
                     45:        0;      /* 戻り値不要だけど一応 */    \
                     46: })
                     47: 
                     48: // バスエラー時に SSW をセットする。
                     49: // m68030_*_NN_mmu() 関数の下請け。
                     50: static inline void
                     51: SET_SSW(m68kcpu *cpu, bool use_mmu, uint size)
                     52: {
                     53:        // サイズを設定
                     54:        cpu->bus.ssw &= ~SSW_SIZE_MASK;
                     55:        cpu->bus.ssw |= size;
                     56: 
                     57:        if (use_mmu) {
                     58:                // データアクセスなら再試行のため DataFault ビットをセット。
                     59:                // 命令アクセスなら RB をセット。
                     60:                if ((cpu->bus.ssw & FC_DATA)) {
                     61:                        cpu->bus.ssw |= SSW_DF;
                     62:                } else {
                     63:                        cpu->bus.ssw |= SSW_RB;
                     64:                }
                     65:        }
                     66: }
                     67: 
                     68: //
                     69: // MMU を考慮した下請けテンプレート。
                     70: // 1回分のミスアラインドありのアクセスを担当。
                     71: //
                     72: 
                     73: template<bool use_mmu> uint32
                     74: m68030_fetch_16_mmu(m68kcpu *cpu)
                     75: {
                     76:        uint64 data;
                     77: 
                     78:        data = FETCH(16);
                     79:        // XXX バスエラー時に PC をインクリメントするタイミングは?
                     80:        RegPC += 2;
                     81: 
                     82:        return data;
                     83: 
                     84:  buserr:
                     85:        SET_SSW(cpu, use_mmu, SSW_SIZE_WORD);
                     86:        throw M68K_EXCEP_BUSERR;
                     87: }
                     88: 
                     89: template<bool use_mmu> uint32
                     90: m68030_fetch_32_mmu(m68kcpu *cpu)
                     91: {
                     92:        uint64 data;
                     93: 
                     94:        if ((cpu->bus.laddr & 3) == 0) {
                     95:                data = FETCH(32);
                     96:        } else {
                     97:                uint64 h, l;
                     98: 
                     99:                h = FETCH(16);
                    100:                cpu->bus.laddr += 2;
                    101: 
                    102:                l = FETCH(16);
                    103:                data = (h << 16) | l;
                    104:        }
                    105:        // XXX バスエラー時に PC をインクリメントするタイミングは?
                    106:        RegPC += 4;
                    107:        return data;
                    108: 
                    109:  buserr:
                    110:        SET_SSW(cpu, use_mmu, SSW_SIZE_LONG);
                    111:        throw M68K_EXCEP_BUSERR;
                    112: }
                    113: 
                    114: template<bool use_mmu> uint32
                    115: m68030_read_8_mmu(m68kcpu *cpu)
                    116: {
                    117:        uint64 data;
                    118: 
                    119:        data = READ(8);
                    120: 
                    121:        if (1)
                    122:                cpulog(2, "m68030_read_8   %08X -> %02X", cpu->bus.laddr, (uint32)data);
                    123:        return data;
                    124: 
                    125:  buserr:
                    126:        SET_SSW(cpu, use_mmu, SSW_SIZE_BYTE);
                    127:        throw M68K_EXCEP_BUSERR;
                    128: }
                    129: 
                    130: template<bool use_mmu> uint32
                    131: m68030_read_16_mmu(m68kcpu *cpu)
                    132: {
                    133:        uint64 data;
                    134: 
                    135:        if ((cpu->bus.laddr & 1) == 0) {
                    136:                data = READ(16);
                    137:        } else {
                    138:                uint64 h, l;
                    139: 
                    140:                h = READ(8);
                    141:                cpu->bus.laddr += 1;
                    142: 
                    143:                l = READ(8);
                    144:                data = (h << 8) | l;
                    145:        }
                    146: 
                    147:        if (1)
                    148:                cpulog(2, "m68030_read_16  %08X -> %04X", cpu->bus.laddr, (uint32)data);
                    149:        return data;
                    150: 
                    151:  buserr:
                    152:        SET_SSW(cpu, use_mmu, SSW_SIZE_WORD);
                    153:        throw M68K_EXCEP_BUSERR;
                    154: }
                    155: 
                    156: template<bool use_mmu> uint32
                    157: m68030_read_32_mmu(m68kcpu *cpu)
                    158: {
                    159:        uint64 data;
                    160: 
                    161:        if ((cpu->bus.laddr & 3) == 0) {
                    162:                data = READ(32);
                    163:        } else if ((cpu->bus.laddr & 1) == 0) {
                    164:                uint64 h, l;
                    165: 
                    166:                h = READ(16);
                    167:                cpu->bus.laddr += 2;
                    168: 
                    169:                l = READ(16);
                    170:                data = (h << 16) | l;
                    171:        } else {
                    172:                uint64 h, m, l;
                    173: 
                    174:                h = READ(8);
                    175:                cpu->bus.laddr += 1;
                    176: 
                    177:                m = READ(16);
                    178:                cpu->bus.laddr += 2;
                    179: 
                    180:                l = READ(8);
                    181:                data = (h << 24) | (m << 8) | l;
                    182:        }
                    183: 
                    184:        if (1)
                    185:                cpulog(2, "m68030_read_32  %08X -> %08X", cpu->bus.laddr, (uint32)data);
                    186:        return data;
                    187: 
                    188:  buserr:
                    189:        SET_SSW(cpu, use_mmu, SSW_SIZE_LONG);
                    190:        throw M68K_EXCEP_BUSERR;
                    191: }
                    192: 
                    193: template<bool use_mmu> void
                    194: m68030_write_8_mmu(m68kcpu *cpu)
                    195: {
                    196:        uint32 data = cpu->bus.data;
                    197: 
                    198:        if (1)
                    199:                cpulog(2, "m68030_write_8  %08X <- %02X", cpu->bus.laddr, data);
                    200: 
                    201:        WRITE(8, data);
                    202:        return;
                    203: 
                    204:  buserr:
                    205:        SET_SSW(cpu, use_mmu, SSW_SIZE_BYTE);
                    206:        throw M68K_EXCEP_BUSERR;
                    207: }
                    208: 
                    209: template<bool use_mmu> void
                    210: m68030_write_16_mmu(m68kcpu *cpu)
                    211: {
                    212:        uint32 data = cpu->bus.data;
                    213: 
                    214:        if (1)
                    215:                cpulog(2, "m68030_write_16 %08X <- %04X", cpu->bus.laddr, data);
                    216: 
                    217:        if ((cpu->bus.laddr & 1) == 0) {
                    218:                WRITE(16, data);
                    219:        } else {
                    220:                WRITE(8, data >> 8);
                    221: 
                    222:                cpu->bus.laddr += 1;
                    223:                WRITE(8, data & 0xff);
                    224:        }
                    225:        return;
                    226: 
                    227:  buserr:
                    228:        SET_SSW(cpu, use_mmu, SSW_SIZE_WORD);
                    229:        throw M68K_EXCEP_BUSERR;
                    230: }
                    231: 
                    232: template<bool use_mmu> void
                    233: m68030_write_32_mmu(m68kcpu *cpu)
                    234: {
                    235:        uint32 data = cpu->bus.data;
                    236: 
                    237:        if (1)
                    238:                cpulog(2, "m68030_write_32 %08X <- %08X", cpu->bus.laddr, data);
                    239: 
                    240:        if ((cpu->bus.laddr & 3) == 0) {
                    241:                WRITE(32, data);
                    242:        } else if ((cpu->bus.laddr & 1) == 0) {
                    243:                WRITE(16, data >> 16);
                    244: 
                    245:                cpu->bus.laddr += 2;
                    246:                WRITE(16, data & 0xffff);
                    247:        } else {
                    248:                WRITE(8, data >> 24);
                    249: 
                    250:                cpu->bus.laddr += 1;
                    251:                WRITE(16, (data >> 8) & 0xffff);
                    252: 
                    253:                cpu->bus.laddr += 2;
                    254:                WRITE(8, data & 0xff);
                    255:        }
                    256:        return;
                    257: 
                    258:  buserr:
                    259:        SET_SSW(cpu, use_mmu, SSW_SIZE_LONG);
                    260:        throw M68K_EXCEP_BUSERR;
                    261: }
                    262: 
                    263: // m68030_{fetch,read,write}_NN() と m68030_{read,write}_NN_fc() の共通部分。
                    264: // fetch には FC 指定版はないので分ける必要は本来ないけど対称性のため。
                    265: // cpu->bus に必要な情報はセットされている。
                    266: // _bus 接尾辞はバスアクセスというより bus 構造体を使ったアクセスという感じ。
                    267: 
                    268: static inline uint32
                    269: m68030_fetch_16_bus(m68kcpu *cpu)
                    270: {
                    271:        if (cpu->mmu_enable) {
                    272:                return m68030_fetch_16_mmu<true>(cpu);
                    273:        } else {
                    274:                return m68030_fetch_16_mmu<false>(cpu);
                    275:        }
                    276: }
                    277: 
                    278: static inline uint32
                    279: m68030_fetch_32_bus(m68kcpu *cpu)
                    280: {
                    281:        if (cpu->mmu_enable) {
                    282:                return m68030_fetch_32_mmu<true>(cpu);
                    283:        } else {
                    284:                return m68030_fetch_32_mmu<false>(cpu);
                    285:        }
                    286: }
                    287: 
                    288: static uint32
                    289: m68030_read_8_bus(m68kcpu *cpu)
                    290: {
                    291: if(1)cpulog(2, "%s   $%08x", __func__, cpu->bus.laddr);
                    292:        if (cpu->mmu_enable) {
                    293:                return m68030_read_8_mmu<true>(cpu);
                    294:        } else {
                    295:                return m68030_read_8_mmu<false>(cpu);
                    296:        }
                    297: }
                    298: 
                    299: static uint32
                    300: m68030_read_16_bus(m68kcpu *cpu)
                    301: {
                    302: if(1)cpulog(2, "%s  $%08x", __func__, cpu->bus.laddr);
                    303:        if (cpu->mmu_enable) {
                    304:                return m68030_read_16_mmu<true>(cpu);
                    305:        } else {
                    306:                return m68030_read_16_mmu<false>(cpu);
                    307:        }
                    308: }
                    309: 
                    310: static uint32
                    311: m68030_read_32_bus(m68kcpu *cpu)
                    312: {
                    313: if(1)cpulog(2, "%s  $%08x", __func__, cpu->bus.laddr);
                    314:        if (cpu->mmu_enable) {
                    315:                return m68030_read_32_mmu<true>(cpu);
                    316:        } else {
                    317:                return m68030_read_32_mmu<false>(cpu);
                    318:        }
                    319: }
                    320: 
                    321: static void
                    322: m68030_write_8_bus(m68kcpu *cpu)
                    323: {
                    324: if(1)cpulog(2, "%s  $%08x", __func__, cpu->bus.laddr);
                    325:        if (cpu->mmu_enable) {
                    326:                m68030_write_8_mmu<true>(cpu);
                    327:        } else {
                    328:                m68030_write_8_mmu<false>(cpu);
                    329:        }
                    330: }
                    331: 
                    332: static void
                    333: m68030_write_16_bus(m68kcpu *cpu)
                    334: {
                    335: if(1)cpulog(2, "%s $%08x", __func__, cpu->bus.laddr);
                    336:        if (cpu->mmu_enable) {
                    337:                m68030_write_16_mmu<true>(cpu);
                    338:        } else {
                    339:                m68030_write_16_mmu<false>(cpu);
                    340:        }
                    341: }
                    342: 
                    343: static void
                    344: m68030_write_32_bus(m68kcpu *cpu)
                    345: {
                    346: if(1)cpulog(2, "%s $%08x", __func__, cpu->bus.laddr);
                    347:        if (cpu->mmu_enable) {
                    348:                m68030_write_32_mmu<true>(cpu);
                    349:        } else {
                    350:                m68030_write_32_mmu<false>(cpu);
                    351:        }
                    352: }
                    353: 
                    354: //
                    355: // CPU 内部からのメモリアクセスは常にこの8つ (またはこれを呼び出すヘルパー
                    356: // 関数) を呼ぶこと。
                    357: //     uint32 m68030_fetch_{16,32}(cpu)
                    358: //     uint32 m68030_read_{8,16,32}(cpu, laddr)
                    359: //     void   m68030_write_{8,16,32}(cpu, laddr, data)
                    360: //
                    361: 
                    362: uint32
                    363: m68030_fetch_16(m68kcpu *cpu)
                    364: {
                    365:        cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_PROG;
                    366:        cpu->bus.laddr = RegPC;
                    367:        return m68030_fetch_16_bus(cpu);
                    368: }
                    369: 
                    370: uint32
                    371: m68030_fetch_32(m68kcpu *cpu)
                    372: {
                    373:        cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_PROG;
                    374:        cpu->bus.laddr = RegPC;
                    375:        return m68030_fetch_32_bus(cpu);
                    376: }
                    377: 
                    378: uint32
                    379: m68030_read_8(m68kcpu *cpu, uint32 addr)
                    380: {
                    381:        cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_DATA;
                    382:        cpu->bus.laddr = addr;
                    383:        return m68030_read_8_bus(cpu);
                    384: }
                    385: 
                    386: uint32
                    387: m68030_read_16(m68kcpu *cpu, uint32 addr)
                    388: {
                    389:        cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_DATA;
                    390:        cpu->bus.laddr = addr;
                    391:        return m68030_read_16_bus(cpu);
                    392: }
                    393: 
                    394: uint32
                    395: m68030_read_32(m68kcpu *cpu, uint32 addr)
                    396: {
                    397:        cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_DATA;
                    398:        cpu->bus.laddr = addr;
                    399:        return m68030_read_32_bus(cpu);
                    400: }
                    401: 
                    402: void
                    403: m68030_write_8(m68kcpu *cpu, uint32 addr, uint32 data)
                    404: {
                    405:        cpu->bus.ssw = SSW_BUS_W | cpu->bus.fc2 | FC_DATA;
                    406:        cpu->bus.laddr = addr;
                    407:        cpu->bus.data = data;
                    408:        m68030_write_8_bus(cpu);
                    409: }
                    410: 
                    411: void
                    412: m68030_write_16(m68kcpu *cpu, uint32 addr, uint32 data)
                    413: {
                    414:        cpu->bus.ssw = SSW_BUS_W | cpu->bus.fc2 | FC_DATA;
                    415:        cpu->bus.laddr = addr;
                    416:        cpu->bus.data = data;
                    417:        m68030_write_16_bus(cpu);
                    418: }
                    419: 
                    420: void
                    421: m68030_write_32(m68kcpu *cpu, uint32 addr, uint32 data)
                    422: {
                    423:        cpu->bus.ssw = SSW_BUS_W | cpu->bus.fc2 | FC_DATA;
                    424:        cpu->bus.laddr = addr;
                    425:        cpu->bus.data = data;
                    426:        m68030_write_32_bus(cpu);
                    427: }
                    428: 
                    429: //
                    430: // MOVES 用の FC 指定版。
                    431: // 通常アクセスが現在の FC 空間に対してだが、
                    432: // こちらは SFC/DFC で指定された FC 空間に対してアクセスする。
                    433: //
                    434: 
                    435: uint32
                    436: m68030_read_8_fc(m68kcpu *cpu, uint32 addr)
                    437: {
                    438:        cpu->bus.ssw = SSW_BUS_R | RegSFC;
                    439:        cpu->bus.laddr = addr;
                    440:        return m68030_read_8_bus(cpu);
                    441: }
                    442: 
                    443: uint32
                    444: m68030_read_16_fc(m68kcpu *cpu, uint32 addr)
                    445: {
                    446:        cpu->bus.ssw = SSW_BUS_R | RegSFC;
                    447:        cpu->bus.laddr = addr;
                    448:        return m68030_read_16_bus(cpu);
                    449: }
                    450: 
                    451: uint32
                    452: m68030_read_32_fc(m68kcpu *cpu, uint32 addr)
                    453: {
                    454:        cpu->bus.ssw = SSW_BUS_R | RegSFC;
                    455:        cpu->bus.laddr = addr;
                    456:        return m68030_read_32_bus(cpu);
                    457: }
                    458: 
                    459: void
                    460: m68030_write_8_fc(m68kcpu *cpu, uint32 addr, uint32 data)
                    461: {
                    462:        cpu->bus.ssw = SSW_BUS_W | RegDFC;
                    463:        cpu->bus.laddr = addr;
                    464:        cpu->bus.data = data;
                    465:        m68030_write_8_bus(cpu);
                    466: }
                    467: 
                    468: void
                    469: m68030_write_16_fc(m68kcpu *cpu, uint32 addr, uint32 data)
                    470: {
                    471:        cpu->bus.ssw = SSW_BUS_W | RegDFC;
                    472:        cpu->bus.laddr = addr;
                    473:        cpu->bus.data = data;
                    474:        m68030_write_16_bus(cpu);
                    475: }
                    476: 
                    477: void
                    478: m68030_write_32_fc(m68kcpu *cpu, uint32 addr, uint32 data)
                    479: {
                    480:        cpu->bus.ssw = SSW_BUS_W | RegDFC;
                    481:        cpu->bus.laddr = addr;
                    482:        cpu->bus.data = data;
                    483:        m68030_write_32_bus(cpu);
                    484: }

unix.superglobalmegacorp.com

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