Annotation of nono/vm/bankram.cpp, revision 1.1.1.3

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2023 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // Nereid バンクメモリ
                      9: //
                     10: 
                     11: // バンクメモリはロングワード単位でホストバイトオーダ配置なので、
                     12: // バイトアクセス、ワードアクセス時は HLB(), HLW() マクロを使用のこと。
                     13: 
                     14: #include "bankram.h"
                     15: #include "config.h"
                     16: 
                     17: // コンストラクタ
1.1.1.3 ! root       18: BankRAMDevice::BankRAMDevice(uint objid_, int ram_size_MB)
1.1       root       19:        : inherited(objid_)
                     20: {
                     21:        // ram_size_MB は正数のみ。負数は親側で処理する。
                     22:        assert(ram_size_MB >= 0);
                     23: 
                     24:        ram_size = ram_size_MB * 1024 * 1024;
                     25:        // 初期化は Init() で行う
                     26: }
                     27: 
                     28: // デストラクタ
                     29: BankRAMDevice::~BankRAMDevice()
                     30: {
                     31: }
                     32: 
                     33: // 初期化
                     34: bool
                     35: BankRAMDevice::Init()
                     36: {
                     37:        if (inherited::Init() == false) {
                     38:                return false;
                     39:        }
                     40: 
                     41:        ram.reset(new uint8[ram_size]);
                     42: 
                     43:        return true;
                     44: }
                     45: 
                     46: // 電源オン/リセット
                     47: void
                     48: BankRAMDevice::ResetHard(bool poweron)
                     49: {
                     50:        if (poweron) {
                     51:                // ノイズで埋めたいがとりあえず。
                     52:                memset(&ram[0], 0, ram_size);
                     53:        }
                     54: 
                     55:        // リセットでクリアされる。
                     56:        SetPage(0);
1.1.1.2   root       57: 
1.1.1.3 ! root       58:        memset(&accstat_read[0],  0, AccStat::BANKLEN);
        !            59:        memset(&accstat_write[0], 0, AccStat::BANKLEN);
1.1       root       60: }
                     61: 
                     62: inline uint32
                     63: BankRAMDevice::Decoder(uint32 addr) const
                     64: {
                     65:        return pageaddr + (addr & 0xffff);
                     66: }
                     67: 
1.1.1.2   root       68: busdata
1.1.1.3 ! root       69: BankRAMDevice::Read(busaddr addr)
1.1       root       70: {
1.1.1.3 ! root       71:        uint32 offset = Decoder(addr.Addr());
        !            72:        busdata data;
1.1       root       73: 
1.1.1.3 ! root       74:        accstat_read[offset >> AccStat::SHIFT] = AccStat::READ;
1.1       root       75: 
1.1.1.3 ! root       76:        data  = *(uint32 *)&ram[offset & ~3U];
        !            77:        putlog(4, "$%06x ($%06x) -> $%08x", addr.Addr(), offset, data.Data());
        !            78:        data |= busdata::Wait(1);
        !            79:        data |= BusData::Size4;
1.1       root       80:        return data;
                     81: }
                     82: 
1.1.1.2   root       83: busdata
1.1.1.3 ! root       84: BankRAMDevice::Write(busaddr addr, uint32 data)
1.1       root       85: {
1.1.1.3 ! root       86:        uint32 offset = Decoder(addr.Addr());
        !            87:        uint32 reqsize = addr.GetSize();
        !            88:        uint32 datasize = std::min(4 - (offset & 3U), reqsize);
        !            89: 
        !            90:        accstat_write[offset >> AccStat::SHIFT] = AccStat::WRITE;
        !            91: 
        !            92:        if (datasize == 4) {
        !            93:                putlog(3, "$%06x ($%06x) <- $%08x", addr.Addr(), offset, data);
        !            94:                *(uint32 *)&ram[offset] = data;
        !            95:        } else if (datasize == 1) {
        !            96:                data >>= (reqsize - datasize) * 8;
        !            97:                putlog(3, "$%06x ($%06x) <- $%02x", addr.Addr(), offset, data);
        !            98:                ram[HLB(offset)] = data;
        !            99:        } else {
        !           100:                data >>= (reqsize - datasize) * 8;
        !           101:                putlog(3, "$%06x ($%06x) <- $%0*x", addr.Addr(), offset,
        !           102:                        datasize * 2, data);
        !           103:                for (int i = datasize - 1; i >= 0; i--) {
        !           104:                        ram[HLB(offset + i)] = data;
        !           105:                        data >>= 8;
        !           106:                }
        !           107:        }
1.1       root      108: 
1.1.1.3 ! root      109:        busdata r = busdata::Wait(1);
        !           110:        r |= BusData::Size4;
        !           111:        return r;
1.1       root      112: }
                    113: 
1.1.1.2   root      114: busdata
1.1.1.3 ! root      115: BankRAMDevice::Peek1(uint32 addr)
1.1       root      116: {
                    117:        uint32 offset = Decoder(addr);
                    118:        return ram[HLB(offset)];
                    119: }
                    120: 
1.1.1.2   root      121: bool
1.1.1.3 ! root      122: BankRAMDevice::Poke1(uint32 addr, uint32 data)
1.1       root      123: {
                    124:        if ((int32)data >= 0) {
                    125:                uint32 offset = Decoder(addr);
                    126:                ram[HLB(offset)] = data;
                    127:        }
1.1.1.2   root      128:        return true;
1.1       root      129: }
                    130: 
                    131: void
                    132: BankRAMDevice::SetPage(uint32 page_)
                    133: {
                    134:        page = page_;
                    135:        // XXX 4MB の時の折返し確認
                    136:        pageaddr = (page << 16) & (ram_size - 1);
                    137: 
                    138:        putlog(2, "Page <- $%02x", page);
                    139: }
1.1.1.2   root      140: 
                    141: void
                    142: BankRAMDevice::FetchAccStat(uint8 *acc)
                    143: {
1.1.1.3 ! root      144:        // 要素が8バイトと分かっていればこれだけで済む。
        !           145:        static_assert(AccStat::BANKLEN == 8, "");
        !           146: 
1.1.1.2   root      147:        // R|W をマージしながらコピー。
1.1.1.3 ! root      148:        uint64 tmp;
        !           149:        tmp  = *(uint64 *)&accstat_read[0];
        !           150:        tmp |= *(uint64 *)&accstat_write[0];
        !           151:        *(uint64 *)acc = tmp;
1.1.1.2   root      152: 
                    153:        // 読んだのでリセット。
1.1.1.3 ! root      154:        memset(&accstat_read[0],  0, AccStat::BANKLEN);
        !           155:        memset(&accstat_write[0], 0, AccStat::BANKLEN);
1.1.1.2   root      156: }

unix.superglobalmegacorp.com

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