File:  [Isaki's NoNo m68k/m88k emulator] / nono / debugger / debugger_memory.cpp
Revision 1.1.1.7 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:58 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
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;
}

unix.superglobalmegacorp.com

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