|
|
nono 1.7.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
//
// デバッガのメモリアクセスヘルパー(?)
//
#include "debugger_memory.h"
#include "debugger_private.h"
#include "mainbus.h"
// コンストラクタ
DebuggerMemoryStream::DebuggerMemoryStream(const DebuggerMD *md_,
busaddr laddr_)
{
md = md_;
assert(md);
laddr = laddr_;
paddr = laddr.Addr();
bus = md->GetBus();
lcol = md->GetLASize() / 4;
pcol = md->GetPASize() / 4;
translate = false;
if (laddr.IsPhysical() == false) {
if (md->MMUEnabled()) {
translate = true;
// FormatAddr() なしで Fetch/Peek を実行した場合でも、初回に
// アドレス変換を起こさせるため。SetNBreakpoint() で使う。
pageover = true;
}
}
}
// 現在のアドレスを表示用に整形して str に代入する。
// アドレス変換でバスエラーが起きたら false を返す。
bool
DebuggerMemoryStream::FormatAddr(std::string& str)
{
// ここは pageover に関係なく必ずアドレス変換を行う。
// (その結果必ず pageover = false になる)
if (translate) {
// laddr は論理アドレスなのでアドレス変換する
busaddr tmp = md->TranslateAddr(laddr);
pageover = false;
// laddr は常に表示
str = strhex(laddr.Addr(), lcol);
if (tmp.IsBusErr()) {
// アドレス変換の結果バスエラーなら false で帰る
str += ":BusErr";
return false;
}
paddr = tmp.Addr();
if (paddr == laddr.Addr()) {
// PA==VA
str += "=PA";
} else {
// PA!=VA
if (tmp.IsTableSearched()) {
// 本当はテーブルサーチをしてから確定するはずのアドレスなので
str += '?';
} else {
str += ':';
}
str += strhex(paddr, pcol);
str += ':';
}
} else {
// laddr は物理アドレスなのでそのまま
paddr = laddr.Addr();
str = strhex(paddr, pcol);
str += ':';
}
return true;
}
// アドレスを進める(戻す)。
void
DebuggerMemoryStream::Offset(int n)
{
ResetAddr(laddr.Addr() + n);
}
// アドレスをリセットする。
// (他のパラメータは維持するので、1ワード戻るとかそういう時用)
void
DebuggerMemoryStream::ResetAddr(uint32 newaddr)
{
laddr.ChangeAddr(newaddr);
pageover = true;
}
// 前回のアクセスでページ境界をまたいだかも知れない場合は再変換。
#define PRECHECK() do { \
if (__predict_false(pageover)) { \
busaddr tmp = md->TranslateAddr(laddr); \
if (__predict_false(tmp.IsBusErr())) { \
return (uint64)-2; \
} \
paddr = tmp.Addr(); \
pageover = false; \
} \
} while (0)
// 論理アドレスがページ境界をまたいだかどうか。
// m68k はページサイズが 256バイト..32KB まで可変だが、いつ変わるか
// 分からないページサイズマスクを取得することを考えたら、多少の無駄
// を承知で常に 256 バイトおきにチェックするほうがマシかもしれない。
#define POSTCHECK() do { \
if (__predict_false(translate && (paddr & 0xff) == 0)) { \
pageover = true; \
} \
} while (0)
// laddr から指定バイト数を右詰めで読み込むが、アドレスは進めない。
uint64
DebuggerMemoryStream::Peek(int bytes)
{
uint64 data;
PRECHECK();
data = 0;
for (int i = 0; i < bytes; i++) {
busdata bd = bus->Peek1(paddr + i);
if (__predict_false(bd.IsBusErr())) {
return bd;
}
data = (data << 8) | bd.Data();
}
return data;
}
// laddr から指定バイト数を右詰めで読み込んで、アドレスを進める。
uint64
DebuggerMemoryStream::Read(int bytes)
{
uint64 data;
data = Peek(bytes);
laddr += bytes;
paddr += bytes;
POSTCHECK();
return data;
}
// laddr から1バイト読み込んで、アドレスを進める。
uint64
DebuggerMemoryStream::Read1()
{
uint64 data;
PRECHECK();
data = bus->Peek1(paddr);
++laddr;
++paddr;
POSTCHECK();
return data;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.