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

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

unix.superglobalmegacorp.com

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