|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 [email protected] ! 4: // ! 5: ! 6: #include "m88100.h" ! 7: #include "m88100excep.h" ! 8: #include "debugger.h" ! 9: #include "cvprompt.h" ! 10: #include "mpu.h" ! 11: ! 12: #define OP_DEF(name) void __CONCAT(m88kcpu::op_,name)() ! 13: #define OP_FUNC(name) __CONCAT(op_,name)() ! 14: #include "m88100ops.cpp" ! 15: ! 16: // リセット例外のようなもの? ! 17: void ! 18: m88kcpu::Reset(uint32 reset_vector) ! 19: { ! 20: // TODO: 未完成 ! 21: psr = 0x800003ff; ! 22: // SFD1 = 0; ! 23: psr &= ~PSR_SFD1; ! 24: ! 25: #if TEST_INTERRUPT ! 26: psr &= ~PSR_IND; ! 27: psr &= ~PSR_SFRZ; ! 28: #endif ! 29: ! 30: vbr = 0; ! 31: ! 32: // 実際には m88k MPU はリセット直後は 0 番地から実行を開始するので、 ! 33: // 大抵の場合システムでリセット直後は 0 番地付近に ROM を見せるように ! 34: // してあるのだと思うが、ここではその代わりに ROM のアドレスを指定して、 ! 35: // 直接そこから実行を開始することにする。 ! 36: fip = reset_vector; ! 37: nip = 0; ! 38: xip = 0; ! 39: ! 40: fetch(); ! 41: } ! 42: ! 43: // request サイクル分実行する。 ! 44: uint32 ! 45: m88kcpu::Run(uint64 request) ! 46: { ! 47: uint64 goal_cycle = total_cycle + request; ! 48: bool is_release = false; ! 49: bool is_intr = false; ! 50: ! 51: while (!is_release) { ! 52: // shift pipeline ! 53: opX = opF; ! 54: xip = nip; ! 55: ! 56: // prefetch next inst ! 57: fetch(); ! 58: ! 59: // この時点で実行しようとする命令が opX に入っている ! 60: ! 61: if (atomic_reqflag != 0) { ! 62: // 何かが起きた ! 63: ! 64: // 割り込みの認識 ! 65: // 割り込みの実行は命令実行完了後、次のプリフェッチの前 ! 66: if ((atomic_reqflag & CPU_REQ_INTR)) { ! 67: atomic_reqflag &= ~CPU_REQ_INTR; ! 68: is_intr = true; ! 69: #if TEST_INTERRUPT ! 70: atomic_reqflag |= CPU_REQ_PROMPT; ! 71: #endif ! 72: } ! 73: ! 74: if ((atomic_reqflag & CPU_REQ_TRACE)) { ! 75: // デバッガプロンプトを出すかどうかを判断する ! 76: //inst_count++; ! 77: if (debugger_check()) { ! 78: atomic_reqflag |= CPU_REQ_PROMPT; ! 79: } ! 80: } ! 81: ! 82: if ((atomic_reqflag & CPU_REQ_PROMPT)) { ! 83: // デバッガプロンプトのための実行停止 ! 84: ! 85: // プロンプト獲得を通知 ! 86: gCVPrompt->NotifyAcquire(); ! 87: ! 88: // プロンプト解放を待機 ! 89: gCVPrompt->WaitRelease(); ! 90: ! 91: // プロンプトを抜けたのでここでフラグを落とす ! 92: atomic_reqflag &= ~CPU_REQ_PROMPT; ! 93: } ! 94: ! 95: if ((atomic_reqflag & CPU_REQ_RELEASE)) { ! 96: // 中断リクエスト受信 ! 97: // この命令を実行し終わったら抜ける ! 98: atomic_reqflag &= ~CPU_REQ_RELEASE; ! 99: is_release = true; ! 100: } ! 101: } ! 102: ! 103: if (OpIsBusErr(opX)) { ! 104: // プリフェッチしていた命令がバスエラー ! 105: Exception(M88K_EXCEP_INST); ! 106: continue; ! 107: } ! 108: ! 109: uint32 op12 = op32_to_12(opX); ! 110: ! 111: switch (op12) { ! 112: #include "m88100switch.inc" ! 113: default: ! 114: __unreachable(); ! 115: } ! 116: ! 117: if (is_intr) { ! 118: is_intr = false; ! 119: if (!(psr & PSR_IND)) { ! 120: gMPU->putlog(4, "INTR take"); ! 121: ExceptionCore(M88K_EXCEP_INTERRUPT, ExceptionKind::INTR); ! 122: continue; ! 123: } else { ! 124: gMPU->putlog(4, "INTR DISABLE"); ! 125: } ! 126: } ! 127: ! 128: total_cycle++; ! 129: if (total_cycle >= goal_cycle) ! 130: break; ! 131: } ! 132: ! 133: return atomic_reqflag; ! 134: } ! 135: ! 136: // この命令後に実行を中断して VM に戻る ! 137: void ! 138: m88kcpu::Release() ! 139: { ! 140: atomic_reqflag |= CPU_REQ_RELEASE; ! 141: } ! 142: ! 143: // 通常の例外。 ! 144: // エラー、割り込み、TRAP からは使いません。 ! 145: // vec はベクタ番号。 ! 146: void ! 147: m88kcpu::Exception(int vec) ! 148: { ! 149: ExceptionCore(vec, ExceptionKind::NORMAL); ! 150: } ! 151: ! 152: // 例外処理コア部分 ! 153: // vec はベクタ番号。 ! 154: void ! 155: m88kcpu::ExceptionCore(int vec, ExceptionKind cause) ! 156: { ! 157: if (psr & PSR_SFRZ) { ! 158: if (cause != ExceptionKind::TRAP) { ! 159: gMPU->putlog(2, "SFRZ Error Exception"); ! 160: vec = M88K_EXCEP_ERROR; ! 161: cause = ExceptionKind::ERROR; ! 162: } ! 163: } else { ! 164: gMPU->putlog(2, "Exception %x", vec); ! 165: sxip = xip; ! 166: snip = nip; ! 167: sfip = fip; ! 168: ! 169: sxip |= SIP_V; ! 170: snip |= SIP_V; ! 171: // XXX:実機と異なり、fip は常にフェッチ前なので V=0 ! 172: // ^^^^ コレ自体怪しい. INTERRUPT とか。 ! 173: // でもたぶん例外ハンドラでここのビット見ないだろうなあ ! 174: ! 175: if (OpIsBusErr(opX)) { ! 176: sxip |= SIP_E; // E bit ! 177: } ! 178: if (OpIsBusErr(opF)) { ! 179: snip |= SIP_E; // E bit ! 180: } ! 181: ! 182: if (vec == M88K_EXCEP_UNIMPL_OP) { ! 183: sxip &= ~SIP_V; ! 184: } ! 185: } ! 186: ! 187: epsr = psr; ! 188: psr |= PSR_SUPER | PSR_SFD1 | PSR_IND | PSR_SFRZ; ! 189: ! 190: fip = vbr + (vec << 3); ! 191: fetch(); ! 192: if (OpIsBusErr(opF)) { ! 193: if (cause == ExceptionKind::ERROR) { ! 194: // double bus fault ! 195: // 実機は無限ループ状態 ! 196: PANIC("Infinite ERROR (double bus fault)"); ! 197: } else { ! 198: ExceptionCore(M88K_EXCEP_ERROR, ExceptionKind::ERROR); ! 199: } ! 200: } ! 201: } ! 202: ! 203: // データアクセス例外(Read) ! 204: void ! 205: m88kcpu::ReadDataException(uint32 addr, uint32 flag) ! 206: { ! 207: // ミスアラインドはこの例外より前にチェックされていて、 ! 208: // ここにはアラインドしかこない。 ! 209: dma0 = addr & ~0x3; ! 210: dmt0 = ((psr & PSR_BO_LE) ? DM_BO : 0) ! 211: | (((psr & PSR_SUPER) && !(flag & DM_USR)) ? DM_DAS : 0) ! 212: | (flag & DM_DOUB1) // ダブルワードの第1アクセスのときセット ! 213: | (flag & DM_LOCK) // xmem でセット ! 214: | (FLD_D << 7) ! 215: | (flag & DM_SIGNED) ! 216: | ((flag & DM_EN_MASK) >> (addr & 0x03)) ! 217: | 0 // DM_WRITE = 0 ! 218: | DM_VALID; ! 219: Exception(M88K_EXCEP_DATA); ! 220: } ! 221: ! 222: // データアクセス例外(Write) ! 223: void ! 224: m88kcpu::WriteDataException(uint32 addr, uint32 data, uint32 flag) ! 225: { ! 226: // ミスアラインドはこの例外より前にチェックされていて、 ! 227: // ここにはアラインドしかこない。 ! 228: dma0 = addr & ~0x3; ! 229: dmt0 = ((psr & PSR_BO_LE) ? DM_BO : 0) ! 230: | (((psr & PSR_SUPER) && !(flag & DM_USR)) ? DM_DAS : 0) ! 231: | (flag & DM_DOUB1) // ダブルワードの第1アクセスのときセット ! 232: | (flag & DM_LOCK) // xmem でセット ! 233: | (FLD_D << 7) ! 234: | (flag & DM_SIGNED) ! 235: | ((flag & DM_EN_MASK) >> (addr & 0x03)) ! 236: | DM_WRITE ! 237: | DM_VALID; ! 238: ! 239: // dmd は Byte Enable 位置に配置される ! 240: if (flag & DM_SIZE_B) { ! 241: dmd0 = data << ((3 - (addr & 0x03)) * 8); ! 242: } else if (flag & DM_SIZE_H) { ! 243: dmd0 = data << ((2 - (addr & 0x03)) * 16); ! 244: } else { ! 245: dmd0 = data; ! 246: } ! 247: Exception(M88K_EXCEP_DATA); ! 248: } ! 249: ! 250: void ! 251: m88kcpu::Interrupt() ! 252: { ! 253: atomic_reqflag |= CPU_REQ_INTR; ! 254: gMPU->putlog(4, "INTERRUPT ACK (アドレスは不正確)"); ! 255: } ! 256: ! 257: void ! 258: m88kcpu::fpu_unimpl() ! 259: { ! 260: printf("%s\n", __func__); ! 261: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.