11static constexpr char sign(uint8_t a)
13 return (a & 128) ?
'-' :
'+';
16static constexpr int abs(uint8_t a)
18 return (a & 128) ? (256 - a) : a;
23 strAppend(output,
'#', hex_string<4>(addr));
28 if (bin.empty())
return {};
32 if (bin.size() < 2)
return {};
34 if (
t > bin.
size())
return {};
38unsigned dasm(std::span<const uint8_t> opcode, uint16_t pc, std::string& dest,
41 const char* r =
nullptr;
43 auto [s, i] = [&]() -> std::pair<const char*, unsigned> {
51 r = (opcode[0] == 0xDD) ?
"ix" :
"iy";
52 if (opcode[1] != 0xCB) {
62 for (
int j = 0; s[j]; ++j) {
66 static_cast<uint16_t
>(opcode[i])));
70 appendAddr(dest, uint16_t(pc + 2 +
static_cast<int8_t
>(opcode[i])));
75 appendAddr(dest, opcode[i] + opcode[i + 1] * 256);
79 strAppend(dest,
'(', r, sign(opcode[i]),
'#',
80 hex_string<2>(abs(opcode[i])),
')');
84 strAppend(dest, r, sign(opcode[2]),
'#', hex_string<2>(abs(opcode[2])));
94 strAppend(dest, ((k == 0) ?
' ' :
','),
'#', hex_string<2>(opcode[k]));
110 std::span<uint8_t, 4> buffer, EmuTime::param time)
113 buffer[idx++] = interface.
peekMem(addr, time);
116 buffer[idx++] = interface.
peekMem(addr + 1, time);
120 for (; idx < len; ++idx) {
121 buffer[idx] = interface.
peekMem(addr + idx, time);
123 return buffer.subspan(0, len);
127 std::string& dest, EmuTime::param time,
131 dasm(opcodes, pc, dest, appendAddr);
132 return narrow_cast<unsigned>(opcodes.size());
138 auto op0 = interface.peekMem(pc, time);
142 auto op1 = interface.peekMem(pc + 1, time);
150static std::pair<uint16_t, unsigned> findGuaranteedBoundary(
const MSXCPUInterface& interface, uint16_t addr, EmuTime::param time)
156 std::array<unsigned, 4>
length;
157 for (
auto i :
xrange(4)) {
168 if ((length[1] == 1) && (length[2] <= 2) && (length[3] <= 3)) {
183static std::pair<uint16_t, unsigned> instructionBoundaryAndLength(
184 const MSXCPUInterface& interface, uint16_t addr, EmuTime::param time)
187 auto [candidate, len] = findGuaranteedBoundary(interface, addr, time);
190 if ((candidate + len) > addr)
return {candidate, len};
199 auto [result, len] = instructionBoundaryAndLength(interface, addr, time);
204 EmuTime::param time,
int n)
206 auto start = uint16_t(std::max(0,
int(addr - 4 * n)));
207 auto [tmp, len] = instructionBoundaryAndLength(interface, start, time);
209 std::vector<uint16_t> addresses;
210 while ((tmp + len) <= addr) {
211 addresses.push_back(tmp);
215 addresses.push_back(tmp);
217 return addresses[std::max(0, narrow<int>(addresses.size()) - 1 - n)];
byte peekMem(word address, EmuTime::param time) const
Peek memory location.
T length(const vecN< N, T > &x)
This file implemented 3 utility functions:
const std::array< const char *, 256 > mnemonic_xx
std::span< uint8_t > fetchInstruction(const MSXCPUInterface &interface, uint16_t addr, std::span< uint8_t, 4 > buffer, EmuTime::param time)
const std::array< const char *, 256 > mnemonic_ed
std::optional< unsigned > instructionLength(std::span< const uint8_t > bin)
Calculate the length of the instruction at the given address.
const std::array< const char *, 256 > mnemonic_xx_cb
const std::array< const char *, 256 > mnemonic_cb
const std::array< uint8_t, std::size_t(3) *256 > instr_len_tab
const std::array< const char *, 256 > mnemonic_main
uint16_t instructionBoundary(const MSXCPUInterface &interface, uint16_t addr, EmuTime::param time)
This is only an heuristic to display instructions in a debugger disassembly view.
uint16_t nInstructionsBefore(const MSXCPUInterface &interface, uint16_t addr, EmuTime::param time, int n)
Get the start address of the 'n'th instruction before the instruction containing the byte at the give...
void appendAddrAsHex(std::string &output, uint16_t addr)
unsigned dasm(std::span< const uint8_t > opcode, uint16_t pc, std::string &dest, function_ref< void(std::string &, uint16_t)> appendAddr)
Disassemble.
void strAppend(std::string &result, Ts &&...ts)
constexpr auto xrange(T e)