|
|
nono 0.5.0
//
// nono
// Copyright (C) 2021 nono project
// Licensed under nono-license.txt
//
//
// Human68k?
//
#include "human_mi.h"
#include "m88100acc.h"
#include "mpu680x0.h"
#include "mpu88xx0.h"
#include "scheduler.h"
bool human_m680x0_fline_callback(MPU680x0Device *cpu, void *arg);
bool human_m88xx0_fline_callback(MPU88xx0Device *cpu, void *arg);
HumanMI::HumanMI()
: inherited(OBJ_HUMAN_MI)
{
#define SC_DEF(id, name) scTable[(id)] = &HumanMI::name
SC_DEF(0x00, DOS_EXIT);
SC_DEF(0x01, DOS_GETCHAR);
SC_DEF(0x02, DOS_PUTCHAR);
SC_DEF(0x03, DOS_COMINP);
SC_DEF(0x04, DOS_COMOUT);
SC_DEF(0x05, DOS_PRNOUT);
SC_DEF(0x06, DOS_INPOUT);
SC_DEF(0x07, DOS_INKEY);
SC_DEF(0x08, DOS_GETC);
SC_DEF(0x09, DOS_PRINT);
SC_DEF(0x0a, DOS_GETS);
SC_DEF(0x0b, DOS_KEYSNS);
SC_DEF(0x0c, DOS_KFLUSH);
SC_DEF(0x0d, DOS_FFLUSH);
SC_DEF(0x0e, DOS_CHGDRV);
SC_DEF(0x0f, DOS_DRVCTRL);
SC_DEF(0x10, DOS_CONSNS);
SC_DEF(0x11, DOS_PRNSNS);
SC_DEF(0x12, DOS_CINSNS);
SC_DEF(0x13, DOS_COUTSNS);
// $14..16 は欠番
SC_DEF(0x17, DOS_FATCHK);
SC_DEF(0x18, DOS_HENDSP);
SC_DEF(0x19, DOS_CURDRV);
SC_DEF(0x1a, DOS_GETSS);
SC_DEF(0x1b, DOS_FGETC);
SC_DEF(0x1c, DOS_FGETS);
SC_DEF(0x1d, DOS_FPUTC);
SC_DEF(0x1e, DOS_FPUTS);
SC_DEF(0x1f, DOS_ALLCLOSE);
SC_DEF(0x20, DOS_SUPER);
SC_DEF(0x21, DOS_FNCKEY);
SC_DEF(0x22, DOS_KNJCTRL);
SC_DEF(0x23, DOS_CONCTRL);
SC_DEF(0x24, DOS_KEYCTRL);
SC_DEF(0x25, DOS_INTVCS);
SC_DEF(0x26, DOS_PSPSET);
SC_DEF(0x27, DOS_GETTIM2);
SC_DEF(0x28, DOS_SETTIM2);
SC_DEF(0x29, DOS_NAMESTS);
SC_DEF(0x2a, DOS_GETDATE);
SC_DEF(0x2b, DOS_SETDATE);
SC_DEF(0x2c, DOS_GETTIME);
SC_DEF(0x2d, DOS_SETTIME);
SC_DEF(0x2e, DOS_VERIFY);
SC_DEF(0x2f, DOS_DUP0);
SC_DEF(0x30, DOS_VERNUM);
SC_DEF(0x31, DOS_KEEPPR);
SC_DEF(0x32, DOS_GETDPB);
SC_DEF(0x33, DOS_BREAKCK);
SC_DEF(0x34, DOS_DRVXCHG);
SC_DEF(0x35, DOS_INTVCG);
SC_DEF(0x36, DOS_DSKFRE);
SC_DEF(0x37, DOS_NAMECK);
// $38 は欠番
SC_DEF(0x39, DOS_MKDIR);
SC_DEF(0x3a, DOS_RMDIR);
SC_DEF(0x3b, DOS_CHDIR);
SC_DEF(0x3c, DOS_CREATE);
SC_DEF(0x3d, DOS_OPEN);
SC_DEF(0x3e, DOS_CLOSE);
SC_DEF(0x3f, DOS_READ);
SC_DEF(0x40, DOS_WRITE);
SC_DEF(0x41, DOS_DELETE);
SC_DEF(0x42, DOS_SEEK);
SC_DEF(0x43, DOS_CHMOD);
SC_DEF(0x44, DOS_IOCTRL);
SC_DEF(0x45, DOS_DUP);
SC_DEF(0x46, DOS_DUP2);
SC_DEF(0x47, DOS_CURDIR);
SC_DEF(0x48, DOS_MALLOC);
SC_DEF(0x49, DOS_MFREE);
SC_DEF(0x4a, DOS_SETBLOCK);
SC_DEF(0x4b, DOS_EXEC);
SC_DEF(0x4c, DOS_EXIT2);
SC_DEF(0x4d, DOS_WAIT);
SC_DEF(0x4e, DOS_FILES);
SC_DEF(0x4f, DOS_NFILES);
SC_DEF(0x80, DOS_SETPDB);
SC_DEF(0x81, DOS_GETPDB);
SC_DEF(0x82, DOS_SETENV);
SC_DEF(0x83, DOS_GETENV);
SC_DEF(0x84, DOS_VERIFYG);
SC_DEF(0x85, DOS_COMMON);
SC_DEF(0x86, DOS_RENAME);
SC_DEF(0x87, DOS_FILEDATE);
SC_DEF(0x88, DOS_MALLOC2);
SC_DEF(0x8a, DOS_MAKETMP);
SC_DEF(0x8b, DOS_NEWFILE);
SC_DEF(0x8c, DOS_LOCK);
// $8d..8e は欠番
SC_DEF(0x8f, DOS_ASSIGN);
SC_DEF(0xaa, DOS_FFLUSH_SET);
SC_DEF(0xab, DOS_OS_PATCH);
SC_DEF(0xac, DOS_GETFCB);
SC_DEF(0xad, DOS_S_MALLOC);
SC_DEF(0xae, DOS_S_MFREE);
SC_DEF(0xaf, DOS_S_PROCESS);
SC_DEF(0xf0, DOS_EXITVC);
SC_DEF(0xf1, DOS_CTRLVC);
SC_DEF(0xf2, DOS_ERRJVC);
SC_DEF(0xf3, DOS_DISKRED);
SC_DEF(0xf4, DOS_DISKWRT);
SC_DEF(0xf5, DOS_INDOSFLG);
SC_DEF(0xf6, DOS_SUPER_JSR);
SC_DEF(0xf7, DOS_BUS_ERR);
SC_DEF(0xf8, DOS_OPEN_PR);
SC_DEF(0xf9, DOS_KILL_PR);
SC_DEF(0xfa, DOS_GET_PR);
SC_DEF(0xfb, DOS_SUSPEND_PR);
SC_DEF(0xfc, DOS_SLEEP_PR);
SC_DEF(0xfd, DOS_SEND_PR);
SC_DEF(0xfe, DOS_TIME_PR);
SC_DEF(0xff, DOS_CHANGE_PR);
// XXX not tested
scheduler = GetScheduler();
}
HumanMI::~HumanMI()
{
}
bool
HumanMI::Dispatch()
{
if (scid < 0 || scid >= scTable.size()) {
// もともと定義されていないシステムコール。
return false;
}
auto func = scTable[scid];
if (func == nullptr) {
// もともと定義されていないシステムコール。
return false;
}
putlog(2, "calling system call $%02X", scid);
bool r = (this->*func)();
if (r == false) {
// 未実装システムコール
putlog(0, "system call $%02X (NOT IMPLEMENTED)", scid);
RequestExit(0);
return false;
}
return r;
}
// 内部関数
// 仮想マシンの中から終了させる
void
HumanMI::RequestExit(int code)
{
scheduler->Terminate();
}
// システムコールの実装
bool
HumanMI::DOS_EXIT()
{
RequestExit(0);
return true;
}
bool
HumanMI::DOS_GETCHAR()
{
int c;
c = getchar();
Result((uint32)(c & 0xff));
return true;
}
bool
HumanMI::DOS_PUTCHAR()
{
uint16 c = Pop16();
putchar(c);
Result(0);
return true;
}
bool
HumanMI::DOS_PRINT()
{
uint32 ptr = Pop32();
putlog(1, "PRINT ptr=%08x", ptr);
for (;;) {
uint64 c = Read8(ptr++);
putlog(1, "c=%d", (int)c);
if ((int64)c == -1) {
// バスエラー
// XXX どうすんの
// たぶんバスエラーハンドラにジャンプしてバスエラーハンドラが
// プロセス終了する感じ。
return false;
}
if (c == 0) {
break;
}
printf("%c", (int)c);
}
Result(0);
return true;
}
// FF40
bool
HumanMI::DOS_WRITE()
{
uint16 fileno = Pop16();
uint32 dataptr = Pop32();
uint32 size = Pop32();
putmsg(1, "WRITE(%d, 0x%08x, 0x%08x)\n", fileno, dataptr, size);
for (int i = 0; i < size; i++) {
putchar(Read8(dataptr++));
}
Result(size);
return true;
}
// FF4A
bool
HumanMI::DOS_SETBLOCK()
{
uint32 memptr = Pop32();
uint32 len = Pop32();
putmsg(1, "DOS SETBLOCK(memptr=$%x len=$%x)", memptr, len);
// なにもせずに、できたという
Result(len);
return true;
}
bool
HumanMI::DOS_EXIT2()
{
uint16 data = Pop16();
RequestExit(data);
return true;
}
// HumanMD_m680x0
bool
HumanMD_m680x0::Init()
{
mpu = GetMPU680x0Device();
mpu->SetFLineCallback(human_m680x0_fline_callback, this);
return true;
}
bool
HumanMD_m680x0::SysCallEntry()
{
uint16 ir = mpu->GetIR();
if (ir == 0xf600) {
return false;
}
scid = ir & 0xff;
sp = mpu->reg.A[7];
putlog(1, "IR=%04X sp=%08x", ir, sp);
return Dispatch();
}
uint64
HumanMD_m680x0::Pop16()
{
uint64 rv = Read16(sp);
sp += 2;
return rv;
}
uint64
HumanMD_m680x0::Pop32()
{
uint64 rv = Read32(sp);
sp += 4;
return rv;
}
uint32
HumanMD_m680x0::ReadReg(int rn)
{
assert(0 <= rn && rn < 16);
return mpu->reg.R[rn];
}
void
HumanMD_m680x0::WriteReg(int rn, uint32 data)
{
assert(0 <= rn && rn < 16);
mpu->reg.R[rn] = data;
}
void
HumanMD_m680x0::Result(uint32 data)
{
WriteReg(0, data);
}
// HumanMD_m88xx0
bool
HumanMD_m88xx0::Init()
{
auto mpu88xx0 = GetMPU88xx0Device();
mpu88xx0->SetFLineCallback(human_m88xx0_fline_callback, this);
return true;
}
bool
HumanMD_m88xx0::SysCallEntry()
{
scid = cpu->reg.opX & 0xff;
rd = m88100opf_D(cpu->reg.opX);
rs = m88100opf_S1(cpu->reg.opX);
return Dispatch();
}
uint64
HumanMD_m88xx0::Pop16()
{
uint64 rv = ReadReg(rs) & 0xffff;
rs++;
return rv;
}
uint64
HumanMD_m88xx0::Pop32()
{
uint64 rv = ReadReg(rs);
rs++;
return rv;
}
uint32
HumanMD_m88xx0::ReadReg(int rn)
{
assert(0 <= rn && rn < 32);
return cpu->reg.r[rn];
}
void
HumanMD_m88xx0::WriteReg(int rn, uint32 data)
{
assert(0 <= rn && rn < 32);
if (rn != 0) {
cpu->reg.r[rn] = data;
}
}
void
HumanMD_m88xx0::Result(uint32 data)
{
WriteReg(rd, data);
}
// CPU からのコールバックはグローバル関数宛なので
// クラス呼び出しに変換するだけを担当。
bool
human_m680x0_fline_callback(MPU680x0Device *, void *arg)
{
auto *human = (HumanMD_m680x0 *)arg;
return human->SysCallEntry();
}
bool
human_m88xx0_fline_callback(MPU88xx0Device *cpu, void *arg)
{
auto *human = (HumanMD_m88xx0 *)arg;
return human->SysCallEntry();
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.