Annotation of nono/vm/human68k.cpp, revision 1.1.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.