|
|
nono 1.2.0
// vi:set ts=4:
//
// nono
// Copyright (C) 2024 nono project
// Licensed under nono-license.txt
//
#include "runx.h"
int
iocscall(pid_t pid, struct reg *reg)
{
uint32 callno = (RegD(0) & 0xff);
DEBUG(2, "iocscall $%02x", callno);
// IOCS コールは TRAP 命令なので、ここに来た時点で TRAP 命令実行後。
// RegPC の1ワード手前が TRAP #15 のはずで、
// そのもう1ワード手前は大抵 moveq.l #nn,d0 だが、違う可能性はある。
// TRAP 命令のもう1ワード手前からの2ワードを取得して、
// moveq.l #nn,d0; trap #15 の組み合わせならここを IOCS コールの
// アドレスとする。
// そうでなければ、仕方ないので trap #15 の番地だけを指す。
// (前の命令が1ワード命令とは限らない)
uint32 pc = RegPC - 4;
uint32 inst = readmem4(pc);
if ((inst & 0xff00ffff) != 0x70004e4f) {
pc += 2;
}
int have_fpu = 1; // XXX
switch (callno) {
case 0x80: // _B_INTVCS
{
uint32 num = RegD(1);
uint32 newaddr = RegA(1);
uint32 oldaddr;
if (num < 0x100) {
// 例外ベクタ。
oldaddr = readmem4(num * 4);
writemem4(num * 4, newaddr);
TRACE(pc, "IOCS _B_INTVCS(#$%04x, $%06x) -> $%06x",
num, newaddr, oldaddr);
} else {
// 未対応。
TRACE(pc, "IOCS _B_INTVCS(#$%04x, $%06x) Not supported",
num, newaddr);
}
break;
}
case 0x82: // _B_BPEEK
{
uint32 addr = RegA(1);
uint32 data = readmem1(addr);
TRACE(pc, "IOCS _B_BPEEK($%06x) -> $%02x", addr, data);
RegD(0) = (RegD(0) & 0xffffff00) | data;
RegA(1)++;
break;
}
case 0xac: // _SYS_STAT (ROM1.3)
TRACE(pc, "IOCS _SYS_STAT(%u)", RegD(1));
switch (RegD(1)) {
case 0:
// MPU 状態の取得。
RegD(0) =
(250 << 16) // 25.0MHz
| (have_fpu << 15) // FPU
| (0 << 14) // MMU
| (3 << 0); // MPU Type
break;
case 1:
// キャッシュ状態の取得。
RegD(0) = 0;
break;
case 2:
// キャッシュを SRAM の設定値に設定。
RegD(0) = 0;
break;
case 3:
// キャッシュの消去。
RegD(0) = 0;
break;
case 4:
// キャッシュの設定。
RegD(0) = 0;
break;
default:
break;
}
break;
default:
warnx("%06x: Unknown IOCS call $%02x", RegPC, callno);
break;
}
return 0;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.