Annotation of nono/vm/human68k.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2017 Y.Sugahara (moveccr)
        !             4: //
        !             5: // human68k .r .x .z console emulator
        !             6: //
        !             7: 
        !             8: #include "human68k.h"
        !             9: #include "mpu.h"
        !            10: #include "m68030bus.h"
        !            11: #include "m68030core.h"
        !            12: #include "bus.h"
        !            13: #include "iodevstream.h"
        !            14: #include "scheduler.h"
        !            15: #include "vm.h"
        !            16: #include <err.h>
        !            17: #include <fcntl.h>
        !            18: #include <sys/stat.h>
        !            19: #include <sys/mman.h>
        !            20: 
        !            21: // メモリマップ
        !            22: //
        !            23: // 0000'0000 ベクタ
        !            24: // 0000'0200 Humanエントリポイント
        !            25: // 0000'8000 FCBエリア
        !            26: // 0000'c000 コマンドライン引数
        !            27: // 0000'e000 環境変数
        !            28: // 0001'ff00 SSP 初期値
        !            29: // 0001'ff00 PSP(プロセスエントリ)
        !            30: // 0002'0000 ロードアドレス
        !            31: // 00bf'ffff RAM_END
        !            32: 
        !            33: static bool human68k_fline_callback(m68kcpu *cpu, void *arg);
        !            34: 
        !            35: // コンストラクタ
        !            36: Human68k::Human68k(const char *file, const char *arg)
        !            37: {
        !            38:        logname = "human68k";
        !            39:        devname = "Human68k";
        !            40: 
        !            41:        assert(file);
        !            42:        human68k_file = file;
        !            43:        human68k_arg = arg;
        !            44: 
        !            45:        Files[0].fd = 0;
        !            46:        Files[0].filename = strdup("|stdin");
        !            47:        Files[1].fd = 1;
        !            48:        Files[1].filename = strdup("|stdout");
        !            49:        Files[2].fd = 2;
        !            50:        Files[2].filename = strdup("|stderr");
        !            51: }
        !            52: 
        !            53: // デストラクタ
        !            54: Human68k::~Human68k()
        !            55: {
        !            56: }
        !            57: 
        !            58: bool
        !            59: Human68k::Init()
        !            60: {
        !            61:        bool r;
        !            62:        uint32 psp_base;
        !            63:        uint8 *file;
        !            64: 
        !            65:        // ショートカット用
        !            66:        ram = gRAM;
        !            67:        // Fライン命令をこちらで処理する
        !            68:        gMPU->SetFLineCallback(human68k_fline_callback, this);
        !            69: 
        !            70:        // ワークを用意 (どこでやるか)
        !            71:        // $CBC.B MPU 種別 (3:68030)
        !            72:        gRAM->Write8(0x0cbc, 3);
        !            73:        // $CBD.B FPU 有無 (0xff:あり)
        !            74:        if (gMPU->HaveFPU()) {
        !            75:                gRAM->Write8(0x0cbd, 0xff);
        !            76:        }
        !            77: 
        !            78:        putmsg(1, "arg=%s", human68k_arg);
        !            79: 
        !            80:        // 実行ファイルオープン
        !            81:        int file_fd = open(human68k_file, O_RDONLY);
        !            82:        if (file_fd == -1) {
        !            83:                warn("open %s", human68k_file);
        !            84:                return false;
        !            85:        }
        !            86: 
        !            87:        struct stat st;
        !            88:        if (fstat(file_fd, &st) != 0) {
        !            89:                warn("fstat %s", human68k_file);
        !            90:                return false;
        !            91:        }
        !            92:        uint32 file_size;
        !            93:        file_size = (uint32)st.st_size;
        !            94:        putmsg(1, "file_size=%08x", file_size);
        !            95: 
        !            96:        // mmap
        !            97:        file = (uint8 *)mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, file_fd, 0);
        !            98:        if (file == MAP_FAILED) {
        !            99:                warn("mmap");
        !           100:                return false;
        !           101:        }
        !           102: 
        !           103:        // 拡張子判別
        !           104:        if (isext(human68k_file, ".r")) {
        !           105:                r = LoadR(file, file_size);
        !           106:        } else if (isext(human68k_file, ".x")) {
        !           107:                r = LoadX(file, file_size);
        !           108:        } else if (isext(human68k_file, ".z")) {
        !           109:                r = LoadZ(file, file_size);
        !           110:        } else {
        !           111:                if (file[0] == 0x48 && file[1] == 0x55) {
        !           112:                        r = LoadX(file, file_size);
        !           113:                } else if (file[0] == 0x60 && file[1] == 0x1a) {
        !           114:                        r = LoadZ(file, file_size);
        !           115:                } else {
        !           116:                        warnx("Invalid file extension");
        !           117:                        return false;
        !           118:                }
        !           119:        }
        !           120:        if (!r) {
        !           121:                warnx("Invalid file format");
        !           122:                return false;
        !           123:        }
        !           124: 
        !           125:        munmap(file, file_size);
        !           126:        close(file_fd);
        !           127: 
        !           128:        uint32 last_addr = load_addr + load_size + bss_size;
        !           129: 
        !           130:        IODeviceStream ds(ram);
        !           131:        boot_addr = 0x200;
        !           132:        ds.Write32(0, ram_size - 4);    // 初期 SSP
        !           133:        ds.Write32(4, boot_addr);
        !           134: 
        !           135:        // TRAP #15 ベクタを書き込む。
        !           136:        ds.Write32(0xbc, 0x1000);
        !           137:        // TRAP #15 ハンドラを書き込む。
        !           138:        // エミュレータ内部命令 $f300 で処理して RTE するだけ。
        !           139:        ds.Write16(0x1000, 0xf600);     // .dw $f300
        !           140:        ds.Write16(0x1002, 0x4e73);     // rte
        !           141: 
        !           142:        // コマンドライン文字列を書き込む。LASCII 形式
        !           143:        ds.SetAddr(0xc001);
        !           144:        for (int i = 0; i < 255; i++) {
        !           145:                uint8 c = human68k_arg[i];
        !           146:                ds.Write8(c);
        !           147:                if (c == '\0') {
        !           148:                        ds.Write8(0xc000, i);
        !           149:                        break;
        !           150:                }
        !           151:        }
        !           152: 
        !           153:        // PSP (process entry) を書き込む。
        !           154:        // instructiontest.x はコマンドラインを指定するだけで動くようだ
        !           155:        // PSP はロードアドレス-256 の位置でなければならないようだ。
        !           156:        psp_base = 0x1ff00;
        !           157:        ds.SetAddr(psp_base);
        !           158: 
        !           159:        ds.Write32(-1);         // 1つ前のメモリ管理ポインタ
        !           160:        ds.Write32(-1);         // このメモリを確保したプロセスのメモリ管理ポインタ
        !           161:        ds.Write32(ram_size - 4 + 1);   // このメモリブロックの終わり+1 のアドレス
        !           162:        ds.Write32(-1);         // 次のメモリ管理ポインタ
        !           163: 
        !           164:        ds.Write32(psp_base + 0x20, 0xc000);    // コマンドライン
        !           165: 
        !           166:        ds.SetAddr(boot_addr);
        !           167:        ds.Write16(0x2c4f);             // move.l       a7,a6
        !           168:        ds.Write16(0x2e7c);             // move.l       psp_base,a7
        !           169:        ds.Write32(psp_base);
        !           170:        ds.Write16(0x4e66);             // move.l       a6,usp
        !           171:        ds.Write16(0x207c);             // move.l       psp_base,a0
        !           172:        ds.Write32(psp_base);
        !           173:        ds.Write16(0x227c);             // move.l       last_addr,a1
        !           174:        ds.Write32(last_addr);
        !           175:        ds.Write16(0x247c);             // move.l       #$c000,a2
        !           176:        ds.Write32(0xc000);
        !           177:        ds.Write16(0x267c);             // move.l       #$e000,a3
        !           178:        ds.Write32(0xe000);
        !           179:        ds.Write16(0x287c);             // move.l       exec_addr,a4
        !           180:        ds.Write32(exec_addr);
        !           181:        ds.Write16(0x2c49);             // move.l       a1,a6
        !           182:        ds.Write16(0x46fc);             // move.w       #$0700,sr
        !           183:        ds.Write16(0x0700);
        !           184:        ds.Write16(0x4eb9);             // jsr.l        exec_addr
        !           185:        ds.Write32(exec_addr);
        !           186:        ds.Write16(0xff00);             // DOS          _EXIT
        !           187: 
        !           188:        putmsg(1, "LoadFile complete");
        !           189:        return true;
        !           190: }
        !           191: 
        !           192: bool
        !           193: Human68k::LoadR(uint8 *file, uint size)
        !           194: {
        !           195:        // リロケータブルなのでどこでもいい
        !           196:        load_addr = default_load_addr;
        !           197:        load_size = size;
        !           198:        LoadMem(load_addr, &file[0], load_size);
        !           199: 
        !           200:        // R 形式はファイル先頭が実行開始位置
        !           201:        exec_addr = load_addr;
        !           202:        text_size = load_size;
        !           203:        putmsg(1, "r format");
        !           204:        return true;
        !           205: }
        !           206: 
        !           207: bool
        !           208: Human68k::LoadX(uint8 *file, uint size)
        !           209: {
        !           210:        XFileHeader *hdr = (XFileHeader *)file;
        !           211:        uint hdr_size = sizeof(*hdr);
        !           212: 
        !           213:        if (!(hdr->magic[0] == 'H' && hdr->magic[1] == 'U')) {
        !           214:                errx(EXIT_FAILURE, "invalid magic");
        !           215:        }
        !           216:        base_addr = be32toh(hdr->base_addr);
        !           217:        exec_addr = be32toh(hdr->exec_addr);
        !           218:        text_size = be32toh(hdr->text_size);
        !           219:        data_size = be32toh(hdr->data_size);
        !           220:        bss_size = be32toh(hdr->bss_size);
        !           221: 
        !           222:        uint32 reloc_size = be32toh(hdr->reloc_size);
        !           223: 
        !           224:        // 最適配置位置も可能だが今回見送り
        !           225:        load_addr = default_load_addr;
        !           226:        load_size = text_size + data_size;
        !           227:        LoadMem(load_addr, &file[hdr_size], load_size);
        !           228: 
        !           229:        // 再配置テーブルの file での位置
        !           230:        uint32 reloc_pos = hdr_size + load_size;
        !           231: 
        !           232:        // 再配置
        !           233:        IODeviceStream ds(ram);
        !           234:        uint32 offset = load_addr - base_addr;
        !           235:        uint32 reloc_end = reloc_pos + reloc_size;
        !           236:        uint32 A = load_addr;
        !           237:        uint32 B = base_addr;
        !           238:        uint32 C = A - B;
        !           239:        while (reloc_pos < reloc_end) {
        !           240:                putlog(1, "reloc_pos=%08x reloc_end=%08x", reloc_pos, reloc_end);
        !           241:                uint32 D;
        !           242:                D = be16toh(*(uint16 *)&file[reloc_pos]);
        !           243:                putlog(1, "D=%x", D);
        !           244:                reloc_pos += 2;
        !           245:                if (D == 1) {
        !           246:                        D = be32toh(*(uint32 *)&file[reloc_pos]);
        !           247:                        putlog(1, " odd, D=%x", D);
        !           248:                        reloc_pos += 4;
        !           249:                }
        !           250:                if ((D & 1) == 0) {
        !           251:                        A += D;
        !           252:                        uint32 old = ds.Read32(A);
        !           253:                        ds.Write32(A, old + C);
        !           254:                        putlog(1, " Write_L A=%x, old=%x new=%x", A, old, old + C);
        !           255:                } else {
        !           256:                        A += D - 1;
        !           257:                        uint32 old = ds.Read16(A);
        !           258:                        ds.Write16(A, old + C);
        !           259:                        putlog(1, " Write_W A=%x, old=%x new=%x", A, old, old + C);
        !           260:                }
        !           261:        }
        !           262: 
        !           263:        exec_addr += offset;
        !           264: 
        !           265:        putmsg(1, "x format, base_addr=%08x, exec_addr=%08x", base_addr, exec_addr);
        !           266: 
        !           267:        return true;
        !           268: }
        !           269: 
        !           270: 
        !           271: bool
        !           272: Human68k::LoadZ(uint8 *file, uint size)
        !           273: {
        !           274:        ZFileHeader *hdr = (ZFileHeader *)file;
        !           275:        uint32 hdr_size = sizeof(*hdr);
        !           276: 
        !           277:        if (be16toh(hdr->magic1) != 0x601a) {
        !           278:                errx(EXIT_FAILURE, "invalid magic");
        !           279:        }
        !           280:        text_size = be32toh(hdr->text_size);
        !           281:        data_size = be32toh(hdr->data_size);
        !           282:        bss_size = be32toh(hdr->bss_size);
        !           283:        base_addr = be32toh(hdr->base_addr);
        !           284:        exec_addr = base_addr;
        !           285: 
        !           286:        if (base_addr < 0x20000) {
        !           287:                errx(EXIT_FAILURE, "base, unsupported");
        !           288:        }
        !           289: 
        !           290:        load_addr = base_addr;
        !           291:        load_size = text_size + data_size;
        !           292:        LoadMem(load_addr, &file[hdr_size], load_size);
        !           293: 
        !           294:        putmsg(1, "z format, base_addr=%08x, exec_addr=%08x", base_addr, exec_addr);
        !           295:        return true;
        !           296: }
        !           297: 
        !           298: bool
        !           299: Human68k::LoadMem(uint32 addr, uint8 *src, uint size)
        !           300: {
        !           301:        if (addr + size > ram_size) {
        !           302:                errx(EXIT_FAILURE, "file too large");
        !           303:        }
        !           304: 
        !           305:        IODeviceStream ds(ram, addr);
        !           306:        for (uint32 i = 0; i < size; i++) {
        !           307:                ds.Write8(*src++);
        !           308:        }
        !           309:        return true;
        !           310: }
        !           311: 
        !           312: // file の拡張子が ext なら true を返す。ext は '.' を含む。
        !           313: bool
        !           314: Human68k::isext(const char *file, const char *ext)
        !           315: {
        !           316:        size_t len_file = strlen(file);
        !           317:        size_t len_ext = strlen(ext);
        !           318:        if (len_ext <= 0) {
        !           319:                return false;
        !           320:        }
        !           321:        if (len_file < len_ext) {
        !           322:                return false;
        !           323:        }
        !           324: 
        !           325:        return strcasecmp(&file[len_file - len_ext], ext) == 0;
        !           326: }
        !           327: 
        !           328: 
        !           329: // fileaddr: Human68k ファイル名のゲストVA
        !           330: // atr: Human68k atr
        !           331: // mode: unix open mode
        !           332: // return: Human68k fileno
        !           333: int32
        !           334: Human68k::OpenFile(uint32 fileaddr, uint16 atr, int mode)
        !           335: {
        !           336:        // XXX: unix host only
        !           337: 
        !           338:        int32 fileno;
        !           339:        Human68k::File *f = NULL;
        !           340: 
        !           341:        // 開いているエントリを検索して Human fileno を取得
        !           342:        for (int i = 0; i < FilesCount; i++) {
        !           343:                if (Files[i].fd == -1) {
        !           344:                        fileno = i;
        !           345:                        f = &Files[fileno];
        !           346:                        break;
        !           347:                }
        !           348:        }
        !           349:        if (f == NULL) {
        !           350:                return -1;
        !           351:        }
        !           352: 
        !           353:        char filename[256];
        !           354:        char *p = filename;
        !           355: 
        !           356:        // ファイル名変換
        !           357:        IODeviceStream ds(ram, fileaddr);
        !           358:        for (int i = 0; i < countof(filename) - 3; i++) {
        !           359:                uint8 c = ds.Read8();
        !           360: 
        !           361:                if (c == 0) break;
        !           362:                if (c < 32 || c >= 127 || c == 0x5c) {
        !           363:                        p += sprintf(p, "%02X", c);
        !           364:                } else {
        !           365:                        *p++ = c;
        !           366:                }
        !           367:        }
        !           368:        *p = '\0';
        !           369: 
        !           370:        putmsg(1, "OpenFile: %d %s", fileno, filename);
        !           371:        int fd = open(filename, mode, 0666);
        !           372:        if (fd == -1) {
        !           373:                warn("OpenFile.open");
        !           374:                return -1;
        !           375:        }
        !           376: 
        !           377:        f->fd = fd;
        !           378:        f->filename = strdup(filename);
        !           379: 
        !           380:        return fileno;
        !           381: }
        !           382: 
        !           383: // fileno: Human68k fileno
        !           384: int32
        !           385: Human68k::CloseFile(int32 fileno)
        !           386: {
        !           387:        Human68k::File *f;
        !           388: 
        !           389:        if (fileno <= 0 || fileno >= FilesCount) {
        !           390:                warnx("CloseFile: unopened fileno=%d", fileno);
        !           391:                return -1;
        !           392:        }
        !           393:        f = &Files[fileno];
        !           394:        putmsg(1, "CloseFile: %d %s", fileno, f->filename);
        !           395:        if (f->fd > 2) {
        !           396:                // stdin/out/err は閉じない
        !           397:                close(f->fd);
        !           398:        }
        !           399:        f->fd = -1;
        !           400:        free(f->filename);
        !           401:        return 0;
        !           402: }
        !           403: 
        !           404: // fileno: Human68k fileno
        !           405: // dataaddr: data addr (guest VA)
        !           406: // size: data length
        !           407: int32
        !           408: Human68k::WriteFile(int32 fileno, uint32 dataaddr, uint32 size)
        !           409: {
        !           410:        Human68k::File *f;
        !           411: 
        !           412:        if (fileno <= 0 || fileno >= FilesCount) {
        !           413:                warnx("WriteFile: unopened fileno=%d", fileno);
        !           414:                return -1;
        !           415:        }
        !           416: 
        !           417:        f = &Files[fileno];
        !           418:        if (f->fd < 0) {
        !           419:                return -1;
        !           420:        }
        !           421: 
        !           422:        IODeviceStream ds(ram, dataaddr);
        !           423:        uint8 *buf = new uint8[size];
        !           424:        for (int i = 0; i < size; i++) {
        !           425:                buf[i] = ds.Read8();
        !           426:        }
        !           427: 
        !           428:        int32 rv = write(f->fd, buf, size);
        !           429: 
        !           430:        delete[] buf;
        !           431:        return rv;
        !           432: }
        !           433: 
        !           434: // fileno: Human68k fileno
        !           435: // dataaddr: data addr (guest VA)
        !           436: void
        !           437: Human68k::FputsFile(int32 fileno, uint32 dataaddr)
        !           438: {
        !           439:        Human68k::File *f;
        !           440: 
        !           441:        if (fileno <= 0 || fileno >= FilesCount) {
        !           442:                return;
        !           443:        }
        !           444: 
        !           445:        f = &Files[fileno];
        !           446:        if (f->fd < 0) {
        !           447:                return;
        !           448:        }
        !           449: 
        !           450:        IODeviceStream ds(ram, dataaddr);
        !           451:        int size = 1024;
        !           452:        uint8 buf[size];
        !           453:        bool eof = false;
        !           454: 
        !           455:        do {
        !           456:                int len = 0;
        !           457:                for (int i = 0; i < size; i++) {
        !           458:                        buf[i] = ds.Read8();
        !           459:                        if (buf[i] == 0) {
        !           460:                                eof = true;
        !           461:                                break;
        !           462:                        }
        !           463:                        len++;
        !           464:                }
        !           465:                if (len > 0) {
        !           466:                        write(f->fd, buf, len);
        !           467:                }
        !           468:        } while (!eof);
        !           469: }
        !           470: 
        !           471: 
        !           472: // Human68k DOSCALL Host Emulation
        !           473: 
        !           474: void
        !           475: Human68k::IOCS(m68kcpu *cpu)
        !           476: {
        !           477:        switch (RegD(0) & 0xff) {
        !           478:         case 0x7f:     // _ONTIME
        !           479:         {
        !           480:                putmsg(1, "IOCS ONTIME");
        !           481:                uint64 t = gScheduler->GetVirtTime();
        !           482:                // nanosec to 10msec, in day
        !           483:                RegD(0) = (t / 10_msec) % 8640000;
        !           484:                // nanosec to day
        !           485:                RegD(1) = t / 86400_sec;
        !           486:                break;
        !           487:         }
        !           488:         case 0x82:     // _B_BPEEK
        !           489:         {
        !           490:                uint32 data = m68030_read_8(cpu, RegA(1));
        !           491:                RegD(0) = (RegD(0) & 0xffffff00) | data;
        !           492:                RegA(1)++;
        !           493:                break;
        !           494:         }
        !           495:         case 0xac: // _SYS_STAT (ROM1.3)
        !           496:                switch (RegD(1)) {
        !           497:                 case 0:
        !           498:                        // MPU 状態の取得
        !           499:                        RegD(0) =
        !           500:                            ((250) << 16)       // 25.0MHz
        !           501:                          | ((gMPU->HaveFPU() ? 1 : 0) << 15)   // FPU
        !           502:                          | ((0) << 14)         // MMU
        !           503:                          | ((3) << 0);         // MPU Type
        !           504:                        break;
        !           505:                 case 1:
        !           506:                        // キャッシュ状態の取得
        !           507:                        RegD(0) = 0;
        !           508:                        break;
        !           509:                 case 2:
        !           510:                        // キャッシュを SRAM の設定値に設定
        !           511:                        RegD(0) = 0;
        !           512:                        break;
        !           513:                 case 3:
        !           514:                        // キャッシュの消去
        !           515:                        RegD(0) = 0;
        !           516:                        break;
        !           517:                 case 4:
        !           518:                        // キャッシュの設定
        !           519:                        RegD(0) = 0;
        !           520:                        break;
        !           521:                 default:
        !           522:                        break;
        !           523:                }
        !           524:                break;
        !           525: 
        !           526:         default:
        !           527:                printf("Unimplemented IOCS $%02x\n", RegD(0) & 0xff);
        !           528:                exit(1);
        !           529:        }
        !           530: }
        !           531: 
        !           532: // F-Line 命令をこちらで処理する
        !           533: bool
        !           534: human68k_fline_callback(m68kcpu *cpu, void *arg)
        !           535: {
        !           536:        auto *human68k = (Human68k *)arg;
        !           537:        return human68k->FLineOp(cpu);
        !           538: }
        !           539: 
        !           540: // F-Line 命令
        !           541: bool
        !           542: Human68k::FLineOp(m68kcpu *cpu)
        !           543: {
        !           544:        switch (RegIR) {
        !           545:         case 0xf600:           // IOCS call emulation
        !           546:                IOCS(cpu);
        !           547:                break;
        !           548: 
        !           549:         case 0xff00:           // EXIT
        !           550:                putmsg(1, "DOS EXIT");
        !           551:                exit(0);
        !           552: 
        !           553:         case 0xff09:           // PRINT
        !           554:         {
        !           555:                // STDOUT
        !           556:                uint32 dataptr = m68030_read_32(cpu, RegA(7));
        !           557:                do {
        !           558:                        int c = m68030_read_8(cpu, dataptr++);
        !           559:                        if (c == 0) break;
        !           560:                        printf("%c", c);
        !           561:                } while (1);
        !           562:                RegD(0) = 0;
        !           563:                break;
        !           564:         }
        !           565: 
        !           566:         case 0xff1e:           // FPUTS
        !           567:         {
        !           568:                uint32 mesptr = m68030_read_32(cpu, RegA(7));
        !           569:                uint16 fileno = m68030_read_16(cpu, RegA(7) + 4);
        !           570:                FputsFile(fileno, mesptr);
        !           571:                break;
        !           572:         }
        !           573: 
        !           574:         case 0xff20:           // SUPER
        !           575:         {
        !           576:                uint32 data = m68030_read_32(cpu, RegA(7));
        !           577: 
        !           578:                if (data == 0) {
        !           579:                        m68030_set_sr(cpu, RegSR | 0x2000);
        !           580:                        data = RegUSP;
        !           581:                        RegD(0) = RegA(7);
        !           582:                        RegA(7) = data;
        !           583:                        putmsg(1, "SUPERVISOR MODE");
        !           584:                } else {
        !           585:                        m68030_set_sr(cpu, RegSR | 0x2000);
        !           586:                        RegA(7) = data;
        !           587:                        m68030_set_sr(cpu, RegSR & ~0x2000);
        !           588:                        putmsg(1, "USER MODE");
        !           589:                }
        !           590:                break;
        !           591:         }
        !           592: 
        !           593:         case 0xff25:           // INTVCS
        !           594:         {
        !           595:                uint16 intno = m68030_read_16(cpu, RegA(7));
        !           596:                uint32 addr = m68030_read_32(cpu, RegA(7) + 2);
        !           597: 
        !           598:                uint32 vecaddr = (intno & 0xff) * 4;
        !           599: 
        !           600:                if (intno <= 0xff) {
        !           601:                        RegD(0) = m68030_read_32(cpu, vecaddr);
        !           602:                        m68030_write_32(cpu, vecaddr, addr);
        !           603:                } else {
        !           604:                        vecaddr += 0xd000;
        !           605:                        RegD(0) = m68030_read_32(cpu, vecaddr);
        !           606:                        m68030_write_32(cpu, vecaddr, addr);
        !           607:                } 
        !           608:                break;
        !           609:         }
        !           610: 
        !           611:         case 0xff27:           // GETTIM2
        !           612:         {
        !           613:                // DUMMY
        !           614:                RegD(0) = 0;
        !           615:                break;
        !           616:         }
        !           617: 
        !           618:         case 0xff2a:           // GETDATE
        !           619:         {
        !           620:                // DUMMY
        !           621:                RegD(0) = 0;
        !           622:                break;
        !           623:         }
        !           624: 
        !           625:         case 0xff30:           // VERNUM
        !           626:         {
        !           627:                RegD(0) = 0x36380302;           // ver3.02
        !           628:                break;
        !           629:         }
        !           630: 
        !           631:         case 0xff35:           // INTVCG
        !           632:         {
        !           633:                uint16 intno = m68030_read_16(cpu, RegA(7));
        !           634: 
        !           635:                uint32 vecaddr = (intno & 0xff) * 4;
        !           636: 
        !           637:                if (intno <= 0xff) {
        !           638:                        RegD(0) = m68030_read_32(cpu, vecaddr);
        !           639:                } else {
        !           640:                        vecaddr += 0xd000;
        !           641:                        RegD(0) = m68030_read_32(cpu, vecaddr);
        !           642:                }
        !           643:                break;
        !           644:         }
        !           645: 
        !           646:         case 0xff3c:           // CREATE
        !           647:         {
        !           648:                uint32 file = m68030_read_32(cpu, RegA(7));
        !           649:                uint16 atr = m68030_read_32(cpu, RegA(7) + 4);
        !           650: 
        !           651:                int32 fileno = OpenFile(file, atr,
        !           652:                        O_CREAT | O_TRUNC | O_RDWR | O_SYNC);
        !           653:                RegD(0) = fileno;
        !           654:                break;
        !           655:         }
        !           656: 
        !           657:         case 0xff3e:           // CLOSE
        !           658:         {
        !           659:                uint16 fileno = m68030_read_16(cpu, RegA(7));
        !           660: 
        !           661:                CloseFile(fileno);
        !           662:                RegD(0) = 0;
        !           663:                break;
        !           664:         }
        !           665: 
        !           666:         case 0xff40:           // WRITE
        !           667:         {
        !           668: //             putmsg(1, "DOS _WRITE at %08x", RegPPC);
        !           669:                uint16 fileno = m68030_read_16(cpu, RegA(7));
        !           670:                uint32 dataptr = m68030_read_32(cpu, RegA(7) + 2);
        !           671:                uint32 size = m68030_read_32(cpu, RegA(7) + 6);
        !           672: //             putmsg(1, "WRITE(%d, 0x%08x, 0x%08x)\n", fileno, dataptr, size);
        !           673:                RegD(0) = WriteFile(fileno, dataptr, size);
        !           674:                break;
        !           675:         }
        !           676: 
        !           677:         case 0xff44:           // IOCTRL
        !           678:         {
        !           679:                uint32 mode = m68030_read_16(cpu, RegA(7));
        !           680:                uint32 fileno;
        !           681:                switch (mode) {
        !           682:                 case 0:
        !           683:                        fileno = m68030_read_16(cpu, RegA(7) + 2);
        !           684:                        putmsg(1, "DOS IOCTRL(mode=%d, fileno=%d)", mode, fileno);
        !           685:                        if (fileno == 0) { // STDIN
        !           686:                                RegD(0) = 0x8081; // 100u'uuuu'100u'0001;
        !           687:                                break;
        !           688:                        } else if (fileno == 1) { // STDOUT
        !           689:                                RegD(0) = 0x8082; // 100u'uuuu'100u'0010;
        !           690:                                break;
        !           691:                        } else if (fileno == 2) { // STDERR
        !           692:                                RegD(0) = 0x8081; // 100u'uuuu'100u'0001;
        !           693:                                break;
        !           694:                        } else {
        !           695:                                RegD(0) = -1;
        !           696:                        }
        !           697:                        break;
        !           698:                 default:
        !           699:                        errx(EXIT_FAILURE, "DOS IOCTRL(mode=%d) not impl.", mode);
        !           700:                }
        !           701:                break;
        !           702:         }
        !           703: 
        !           704:         case 0xff4a:           // SETBLOCK
        !           705:         {
        !           706:                uint32 memptr = m68030_read_32(cpu, RegA(7));
        !           707:                uint32 len = m68030_read_32(cpu, RegA(7) + 4);
        !           708:                putmsg(1, "DOS SETBLOCK(memptr=$%x len=$%x)", memptr, len);
        !           709:                // なにもせずに、できたという
        !           710:                RegD(0) = m68030_read_32(cpu, RegA(7) + 4);
        !           711:                break;
        !           712:         }
        !           713: 
        !           714:         case 0xff4c:           // EXIT2
        !           715:         {
        !           716:                uint32 data = m68030_read_16(cpu, RegA(7));
        !           717:                putmsg(1, "DOS EXIT2(%d)", data);
        !           718:                exit(data);
        !           719:         }
        !           720: 
        !           721:         case 0xffac:           // GETFCB
        !           722:         {
        !           723:                uint32 fileno = m68030_read_16(cpu, RegA(7));
        !           724:                putmsg(1, "DOS GETFCB(fileno=%d)", fileno);
        !           725:                if (fileno <= 4) {
        !           726:                        RegD(0) = 0x8000 + fileno * 0x60;
        !           727:                } else {
        !           728:                        RegD(0) = -1;
        !           729:                }
        !           730:                break;
        !           731:         }
        !           732: 
        !           733:         case 0xfff7:           // BUS_ERR
        !           734:         {
        !           735:                uint32 p1 = m68030_read_32(cpu, RegA(7));
        !           736:                uint32 p2 = m68030_read_32(cpu, RegA(7) + 4);
        !           737:                uint16 size = m68030_read_16(cpu, RegA(7) + 8);
        !           738:                putmsg(1, "DOS BUS_ERR(size=%d p1=$%x p2=$%x)", size, p1, p2);
        !           739: 
        !           740:                RegD(0) = -1;
        !           741:                uint32 data;
        !           742:                try {
        !           743:                        if (size == 1) {
        !           744:                                data = m68030_read_8(cpu, p1);
        !           745:                        } else if (size == 2 && ((p1 & 1) == 0)) {
        !           746:                                data = m68030_read_16(cpu, p1);
        !           747:                        } else if (size == 4 && ((p1 & 1) == 0)) {
        !           748:                                data = m68030_read_32(cpu, p1);
        !           749:                        } else {
        !           750:                                break;
        !           751:                        }
        !           752:                } catch (int cause) {
        !           753:                        if (cause == M68K_EXCEP_BUSERR) {
        !           754:                                RegD(0) = 2;
        !           755:                                break;
        !           756:                        } else {
        !           757:                                throw;
        !           758:                        }
        !           759:                }
        !           760: 
        !           761:                try {
        !           762:                        if (size == 1) {
        !           763:                                m68030_write_8(cpu, p2, data);
        !           764:                        } else if (size == 2 && ((p2 & 1) == 0)) {
        !           765:                                m68030_write_16(cpu, p2, data);
        !           766:                        } else if (size == 4 && ((p2 & 1) == 0)) {
        !           767:                                m68030_write_32(cpu, p2, data);
        !           768:                        } else {
        !           769:                                break;
        !           770:                        }
        !           771:                } catch (int cause) {
        !           772:                        if (cause == M68K_EXCEP_BUSERR) {
        !           773:                                RegD(0) = 1;
        !           774:                                break;
        !           775:                        } else {
        !           776:                                throw;
        !           777:                        }
        !           778:                }
        !           779:                RegD(0) = 0;
        !           780:                break;
        !           781:         }
        !           782: 
        !           783:         default:
        !           784:                printf("Unimplemented DOSCALL $%02x at $%08X\n", RegIR, RegPPC);
        !           785:                exit(1);
        !           786:        }
        !           787:        return true;
        !           788: }

unix.superglobalmegacorp.com

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