Annotation of nono/m88xx0/m88100.h, revision 1.1.1.1

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 [email protected]
                      4: //
                      5: 
                      6: #pragma once
                      7: 
                      8: #include "header.h"
                      9: #include "bus.h"
                     10: #include <atomic>
                     11: 
                     12: // 外部リクエストフラグ
                     13: // XXX m680x0 側にもよく似たものがあってどうしたもんか
                     14: #define CPU_REQ_TRACE          (0x00000004)    // デバッガ有効
                     15: #define CPU_REQ_PROMPT         (0x00000008)    // デバッガプロンプト
                     16: #define CPU_REQ_RELEASE                (0x00000010)    // 命令後に CPU 実行中断
                     17: #define CPU_REQ_INTR           (0x00000020)    // 命令後に割り込みチェック
                     18: 
                     19: class m88200
                     20: {
                     21:  public:
                     22:        m88200();
                     23:        virtual ~m88200();
                     24: 
                     25:  public:
                     26:        uint64 load_8(uint32 addr) {
                     27:                return vm_phys_read_8(addr);
                     28:        }
                     29:        uint64 load_16(uint32 addr) {
                     30:                return vm_phys_read_16(addr);
                     31:        }
                     32:        uint64 load_32(uint32 addr) {
                     33:                return vm_phys_read_32(addr);
                     34:        }
                     35:        uint64 store_8(uint32 addr, uint32 data) {
                     36:                return vm_phys_write_8(addr, data);
                     37:        }
                     38:        uint64 store_16(uint32 addr, uint32 data) {
                     39:                return vm_phys_write_16(addr, data);
                     40:        }
                     41:        uint64 store_32(uint32 addr, uint32 data) {
                     42:                return vm_phys_write_32(addr, data);
                     43:        }
                     44: 
                     45:        uint32 idr = 0;
                     46:        //:
                     47: };
                     48: 
                     49: // m88100 レジスタイメージを保持する構造体。
                     50: // この構造体はコピーや比較をするので、ポインタとかは置かないこと。
                     51: struct m88100reg
                     52: {
                     53:        // PID(cr0)
                     54:        static const uint32 PID_REV_MASK        = 0x0000ff00; // 0 = MC88100
                     55:        static const uint32 PID_VER_MASK        = 0x000000fe;
                     56:        static const uint32 PID_MASTER          = 0x00000001;
                     57:        // PSR(cr1)
                     58:        static const uint32 PSR_SUPER           = 0x80000000;
                     59:        static const uint32 PSR_BO_LE           = 0x40000000; // ByteOrder(Little)
                     60:        static const uint32 PSR_SER                     = 0x20000000;
                     61:        static const uint32 PSR_C                       = 0x10000000; // Carry
                     62:        static const uint32 PSR_SFD1            = 0x00000008; // SFU1 Disable
                     63:        static const uint32 PSR_MXM                     = 0x00000004; // MisalignedAccessEnable
                     64:        static const uint32 PSR_IND                     = 0x00000002; // Interrupt Disable
                     65:        static const uint32 PSR_SFRZ            = 0x00000001; // Shadow Freeze
                     66: 
                     67:        // 例外処理で使用される S*IP
                     68:        static const uint32 SIP_MASK            = 0xfffffffcU;
                     69:        static const uint32 SIP_V                       = 0x00000002;
                     70:        static const uint32 SIP_E                       = 0x00000001;
                     71: 
                     72:        // DMTn、データ例外
                     73:        static const uint32 DM_BO                       = 0x00008000;
                     74:        static const uint32 DM_DAS                      = 0x00004000;
                     75:        static const uint32 DM_DOUB1            = 0x00002000;
                     76:        static const uint32 DM_LOCK                     = 0x00001000;
                     77:        static const uint32 DM_DREG_MASK        = 0x00000f80;
                     78:        static const uint32 DM_SIGNED           = 0x00000040;
                     79:        static const uint32 DM_EN3                      = 0x00000020;
                     80:        static const uint32 DM_EN2                      = 0x00000010;
                     81:        static const uint32 DM_EN1                      = 0x00000008;
                     82:        static const uint32 DM_EN0                      = 0x00000004;
                     83:        static const uint32 DM_EN_MASK          = (DM_EN0 | DM_EN1 | DM_EN2 | DM_EN3);
                     84:        static const uint32 DM_WRITE            = 0x00000002;
                     85:        static const uint32 DM_VALID            = 0x00000001;
                     86:        // 内部識別フラグ
                     87:        static const uint32 DM_SIZE_B           = (1U << 16) | DM_EN3;
                     88:        static const uint32 DM_SIZE_H           = (1U << 17) | DM_EN3 | DM_EN2;
                     89:        static const uint32 DM_SIZE_W           = (1U << 18) | DM_EN_MASK;
                     90:        static const uint32 DM_USR                      = (1U << 20);
                     91:        static const uint32 DM_BU                       = DM_SIZE_B;
                     92:        static const uint32 DM_B                        = DM_SIZE_B | DM_SIGNED;
                     93:        static const uint32 DM_HU                       = DM_SIZE_H;
                     94:        static const uint32 DM_H                        = DM_SIZE_H | DM_SIGNED;
                     95:        static const uint32 DM_W                        = DM_SIZE_W;
                     96:        static const uint32 DM_D1                       = DM_SIZE_W | DM_DOUB1;
                     97:        static const uint32 DM_D2                       = DM_SIZE_W;
                     98: 
                     99:        // 頻繁にアクセスしそうな変数はオフセットの若いほうに持ってきておく。
                    100: 
                    101:        // 実行中の命令
                    102:        uint64 opX = 0;
                    103:        // プリフェッチ命令
                    104:        uint64 opF = 0;
                    105: 
                    106:        uint32 xip = 0;
                    107:        uint32 nip = 0;
                    108:        uint32 fip = 0;
                    109: 
                    110:        uint32 r[32] {};
                    111:        union {
                    112:                uint32 cr[21] {};
                    113:                struct {
                    114:                        uint32 pid;             // cr0
                    115:                        uint32 psr;             // cr1
                    116:                        uint32 epsr;    // cr2
                    117:                        uint32 ssbr;    // cr3
                    118:                        uint32 sxip;    // cr4
                    119:                        uint32 snip;    // cr5
                    120:                        uint32 sfip;    // cr6
                    121:                        uint32 vbr;             // cr7
                    122:                        uint32 dmt0;    // cr8
                    123:                        uint32 dmd0;    // cr9
                    124:                        uint32 dma0;    // cr10
                    125:                        uint32 dmt1;    // cr11
                    126:                        uint32 dmd1;    // cr12
                    127:                        uint32 dma1;    // cr13
                    128:                        uint32 dmt2;    // cr14
                    129:                        uint32 dmd2;    // cr15
                    130:                        uint32 dma2;    // cr16
                    131:                        uint32 sr[4];   // cr17,18,19,20
                    132:                };
                    133:        };
                    134:        union {
                    135:                uint32 fcr[11] {};
                    136:                struct {
                    137:                        uint32 fpecr;   // fcr0
                    138:                        uint32 fphs1;   // fcr1
                    139:                        uint32 fpls1;   // fcr2
                    140:                        uint32 fphs2;   // fcr3
                    141:                        uint32 fpls2;   // fcr4
                    142:                        uint32 fppt;    // fcr5
                    143:                        uint32 fprh;    // fcr6
                    144:                        uint32 fprl;    // fcr7
                    145:                        uint32 fpit;    // fcr8
                    146:                        uint32 fpsr;    // fcr62 [9]
                    147:                        uint32 fpcr;    // fcr63 [10]
                    148:                };
                    149:        };
                    150: 
                    151:        // 直近のデータアクセスアドレス
                    152:        uint32 lastaddr;
                    153: 
                    154:        // スーパーバイザ/ユーザモードなら true
                    155:        bool IsSuper()  const { return (psr & PSR_SUPER) != 0; }
                    156:        bool IsUser()   const { return (psr & PSR_SUPER) == 0; }
                    157: 
                    158:        // MXM (Misaligned Access Enable) なら true
                    159:        bool IsMXM()    const { return (psr & PSR_MXM) != 0; }
                    160: 
                    161:        // キャリーフラグが立っていれば 1 を返す
                    162:        uint32 GetCY() const { return (psr >> 28) & 1; }
                    163:        // キャリーフラグをセットする。cy は最下位ビットのみ参照する
                    164:        void SetCY(uint cy) {
                    165:                psr &= ~PSR_C;
                    166:                psr |= ((cy & 1) << 28);
                    167:        }
                    168: 
                    169:        static const char * const sipname[3];
                    170: };
                    171: 
                    172: class m88kcpu : public m88100reg
                    173: {
                    174:  public:
                    175:        m88kcpu();
                    176:        virtual ~m88kcpu();
                    177: 
                    178:  public:
                    179:        void Reset(uint32 reset_vector);
                    180:        uint32 Run(uint64 request);
                    181:        void Release();
                    182: 
                    183:        uint64 total_cycle = 0;         // 積算実行サイクル数
                    184: 
                    185:        void Interrupt();
                    186: 
                    187:  public:
                    188:        // [0] 命令バス
                    189:        // [1] データバス
                    190:        m88200 cmmu[2];
                    191: 
                    192:        uint64 fetch() {
                    193:                nip = fip;
                    194:                opF = cmmu[0].load_32(fip);
                    195:                fip += 4;
                    196:                return opF;
                    197:        }
                    198: 
                    199:        // op が>=0ならバスエラーは起きていない
                    200:        //  そのときに DELAYSLOT bit が 0 ならば通常
                    201:        //  bit32 が 1 ならば遅延スロット命令
                    202:        // op が負数ならバスエラーが起きた
                    203:        //  そのときに DELAYSLOT bit が 1 ならば通常バスエラー
                    204:        //  bit32 が 0 ならば遅延スロットでのバスエラー
                    205:        // バスエラーかどうかのチェックのほうが回数が多いため、
                    206:        // バスエラー優先にしたい。
                    207: 
                    208: 
                    209:        bool OpIsBusErr(uint64 op) const {
                    210:                return (int64)op < 0;
                    211:        }
                    212:        bool OpIsDelay(uint64 op) const {
                    213:                return (OpIsBusErr(op) ? ~op : op) & DELAYSLOT;
                    214:        }
                    215: 
                    216:        // クラス外部からの xip 取得
                    217:        uint32 Getxip() const {
                    218:                return xip;
                    219:        }
                    220: 
                    221:        enum ExceptionKind
                    222:        {
                    223:                NORMAL,
                    224:                ERROR,
                    225:                INTR,
                    226:                TRAP,
                    227:        };
                    228: 
                    229:        void Exception(int vec);
                    230:        void ExceptionCore(int vec, ExceptionKind cause);
                    231:        void ReadDataException(uint32 addr, uint32 flag);
                    232:        void WriteDataException(uint32 addr, uint32 data, uint32 flag);
                    233: 
                    234:        // FPU
                    235:        bool IsFPUEnable() { return !(psr & PSR_SFD1); }
                    236:        void fpu_unimpl();
                    237: 
                    238:        std::atomic<uint32> atomic_reqflag {}; // リクエストフラグ
                    239: 
                    240:  private:
                    241:        const uint64 DELAYSLOT = 1ULL << 62;
                    242: 
                    243:        // OpSetDelay を一つの op に対して複数回呼ばないでください
                    244:        uint64 OpSetDelay(uint64 op) const {
                    245:                return op ^ DELAYSLOT;
                    246:        }
                    247: 
                    248:        // ブランチ処理用
                    249:        void EnterBranch();
                    250:        void ExitBranch();
                    251:        void ExitDelayBranch();
                    252:        // ロードストア命令用の下処理
                    253:        bool ldst_usr(uint32 size, uint32& usr);
                    254:        uint32 ldst_scale(uint32 size);
                    255:        bool ldst_align(uint32 size, uint32& addr);
                    256: 
                    257: #define OP_PROTO(name) void __CONCAT(op_,name)()
                    258: #include "m88100ops.h"
                    259: #undef OP_PROTO
                    260: 
                    261:        void op_unimpl() {
                    262:                printf("unimplemented op XIP=%08x opX=%08x\n", xip, (uint32)opX);
                    263:        }
                    264: };
                    265: 
                    266: // とりあえず
                    267: static inline uint32
                    268: op32_to_12(uint32 op)
                    269: {
                    270:        uint32 op12 = ((op >> 20) & 0x0fc0) | ((op >> 10) & 0x003f);
                    271:        return op12;
                    272: }

unix.superglobalmegacorp.com

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