|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2022 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // ! 8: // NEWS の ROM エミュレーション (-X のみ対応) ! 9: // ! 10: ! 11: #include "romemu_news.h" ! 12: #include "mainram.h" ! 13: #include "memorystream.h" ! 14: #include "mpu680x0.h" ! 15: #include "newsfb.h" ! 16: ! 17: // コンストラクタ ! 18: NewsROMEmuDevice::NewsROMEmuDevice() ! 19: : inherited(OBJ_PROM) ! 20: { ! 21: // 適当 ! 22: uint devlen = 4096; ! 23: imagebuf.reset(new uint8 [devlen]); ! 24: memset(&imagebuf[0], 0, devlen); ! 25: mem = &imagebuf[0]; ! 26: ! 27: mask = devlen - 1; ! 28: } ! 29: ! 30: // デストラクタ ! 31: NewsROMEmuDevice::~NewsROMEmuDevice() ! 32: { ! 33: } ! 34: ! 35: // 初期化 ! 36: bool ! 37: NewsROMEmuDevice::Init() ! 38: { ! 39: if (inherited::Init() == false) { ! 40: return false; ! 41: } ! 42: ! 43: mainram = GetMainRAMDevice(); ! 44: ! 45: MemoryStreamBE ms(imagebuf.get()); ! 46: ms.Write32(0x00000400); // +00: リセットベクタ SP ! 47: ms.Write32(0xf8000400); // +04: リセットベクタ PC ! 48: // ベクタ ! 49: for (int i = 2; i < 256; i++) { ! 50: ms.Write32(0); ! 51: } ! 52: ms.SetOffset(32 * 4); ! 53: ms.Write32(0xf8000500); // Trap#0 で ROM のサービスコール ! 54: ! 55: // リセット時に実行する命令 ! 56: ms.SetOffset(0x400); ! 57: ms.Write16(0x2039); // move.l (ROMIO_INIT),d0 ! 58: ms.Write32(ROMIO_INIT); ! 59: ms.Write16(0x2040); // move.l d0,a0 ; ジャンプ先を a0 にセット ! 60: ms.Write16(0x4ed0); // jmp (a0) ; ジャンプ ! 61: ! 62: // ROM サービスコール ! 63: ms.SetOffset(0x500); ! 64: ms.Write16(0x0c80); // cmpi.l #3,d0 ! 65: ms.Write32(0x00000003); // ! 66: ms.Write16(0x6708); // beq @f ! 67: ms.Write16(0x2039); // move.l (ROMIO_SYS),d0 ! 68: ms.Write32(ROMIO_SYS); // ! 69: ms.Write16(0x4e73); // rte ! 70: //@@: ; Read は対応してないので ! 71: ms.Write32(0x4e722500); // stop #0x2500 ; STOP しつつ ! 72: ms.Write16(0x60fa); // bra @b ; 無限ループ。 ! 73: ms.Write16(0x4e73); // rte ! 74: ! 75: return true; ! 76: } ! 77: ! 78: void ! 79: NewsROMEmuDevice::ResetHard(bool poweron) ! 80: { ! 81: // 起動時に RAM にリセットベクタを書き込んでおく。(手抜き) ! 82: for (int i = 0; i < 8; i++) { ! 83: mainram->Write8(i, imagebuf[i]); ! 84: } ! 85: } ! 86: ! 87: uint64 ! 88: NewsROMEmuDevice::Read32(uint32 addr) ! 89: { ! 90: switch (addr) { ! 91: case ROMIO_INIT: ! 92: return ROM_Init(); ! 93: ! 94: case ROMIO_SYS: ! 95: return ROM_Sys(); ! 96: ! 97: default: ! 98: break; ! 99: } ! 100: ! 101: return inherited::Read32(addr); ! 102: } ! 103: ! 104: uint32 ! 105: NewsROMEmuDevice::ROM_Init() ! 106: { ! 107: LoadInfo info; ! 108: ! 109: // -X file ! 110: if (gMainApp.exec_file) { ! 111: // ホストのファイルを読み込んでエントリポイントアドレスを ! 112: // この Read アクセスの読み出し値として返す。 ! 113: // エラーがあればエラーメッセージは呼び出し先側で表示してある。 ! 114: info.path = gMainApp.exec_file; ! 115: if (mainram->LoadFromFile(&info) == false) { ! 116: // XXX どうすべ ! 117: PANIC("** Couldn't load specified host program.\n"); ! 118: return -1; ! 119: } ! 120: putmsg(1, "Host program loaded. Entry point = $%08x\n", info.entry); ! 121: } ! 122: ! 123: // ROMCONS のために VBR を設定 ! 124: m68kreg& reg = GetMPU680x0Device()->reg; ! 125: reg.vbr = 0xf8000000; ! 126: ! 127: // %d2 には MARK_END (たぶん最後の番地) ! 128: // %d4 にメモリサイズ。 ! 129: // %d5 には読み込んだファイル名の先頭番地? ! 130: // %d6 に bootdev、NetBSD/news68k の場合は ! 131: // bootdev = $MCxUHPTT ! 132: // || |||++ Type? (SD=0) ! 133: // || ||+-- Partition? ! 134: // || |+--- Host: 機種? (NEWS1700 は 0) ! 135: // || +---- Unit? ! 136: // |+------ Controller? ! 137: // +------- magic ($5) ! 138: // 下位28ビット(7桁) は ROM から渡されるようだ。 ! 139: // %d7 は boothowto。 ! 140: reg.D[2] = info.sym; ! 141: reg.D[4] = mainram->GetSize(); ! 142: reg.D[6] = 0x50000000; ! 143: reg.D[7] = 0; ! 144: ! 145: return info.entry; ! 146: } ! 147: ! 148: uint32 ! 149: NewsROMEmuDevice::ROM_Sys() ! 150: { ! 151: auto mpu680x0 = GetMPU680x0Device(); ! 152: m68kreg& reg = mpu680x0->reg; ! 153: auto newsfb = GetNewsfbDevice(); ! 154: ! 155: if (reg.D[0] == SYS_write) { ! 156: uint32 a6 = reg.A[6]; ! 157: uint32 fd = mpu680x0->Read32(a6 + 8); ! 158: uint32 buf = mpu680x0->Read32(a6 + 12); ! 159: uint32 len = mpu680x0->Read32(a6 + 16); ! 160: ! 161: for (int i = 0; i < len; i++) { ! 162: uint64 ch = mpu680x0->Read8(buf++); ! 163: if ((int64)ch < 0) { ! 164: // XXX ? ! 165: return 0; ! 166: } ! 167: if (ch == '\r') { ! 168: continue; ! 169: } ! 170: newsfb->Putc(ch); ! 171: } ! 172: (void)fd; ! 173: return len; ! 174: } ! 175: ! 176: VMPANIC("Unknown service call $%02x", reg.D[0]); ! 177: return 0; ! 178: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.