From fdc5756981286ac904a7b0d623ff823044207b48 Mon Sep 17 00:00:00 2001 From: Oxore Date: Tue, 9 May 2023 18:03:00 +0300 Subject: Migrate MOVEM to new Arg struct --- disasm.cpp | 78 ++++++++++++++++++++++++++++++-------------------------------- disasm.h | 14 +++++++++-- 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/disasm.cpp b/disasm.cpp index dd63e47..9c54e69 100644 --- a/disasm.cpp +++ b/disasm.cpp @@ -167,38 +167,6 @@ static char suffix_from_opsize(OpSize opsize) return 'w'; } -static inline size_t snprint_reg_mask( - char *const buf, const size_t bufsz, const uint32_t regmask_arg, const bool predecrement) -{ - const uint32_t regmask = regmask_arg & 0xffff; - size_t written = 0; - bool first_printed = 0; - size_t span = 0; - // 17-th bit used to close the span with 0 value unconditionaly - for (int i = 0; i < 17; i++) { - const uint32_t mask = 1 << (predecrement ? (15 - i) : i); - const bool hit = regmask & mask; - const bool span_open = hit && span == 0; - const bool span_closed = !hit && span > 1; - const int printable_i = i - (span_closed ? 1 : 0); - const int id = printable_i % 8; - const char regtype = (printable_i >= 8) ? 'a' : 'd'; - if (span_open || span_closed) { - const char *const delimiter = span_open ? (first_printed ? "/" : "") : "-"; - const size_t remaining = bufsz - written; - const int ret = snprintf(buf + written, remaining, "%s%%%c%d", delimiter, regtype, id); - assert(ret > 0); - assert(static_cast(ret) >= strlen("%d0")); - assert(static_cast(ret) <= strlen("-%d0")); - written += Min(remaining, ret); - first_printed = true; - } - span = hit ? span + 1 : 0; - } - assert(written < bufsz); // Output must not be truncated - return written; -} - static size_t disasm_verbatim( DisasmNode &node, uint16_t instr, const DataBuffer &) { @@ -342,16 +310,14 @@ static size_t disasm_ext_movem( case AddrMode::kImmediate: // 4ebc / 4efc return disasm_verbatim(node, instr, code); } - const char suffix = suffix_from_opsize(opsize); - snprintf(node.mnemonic, kMnemonicBufferSize, "movem%c", suffix); - char regmask_str[48]{}; - char addrmodearg_str[32]{}; - snprint_reg_mask(regmask_str, sizeof(regmask_str), regmask, a.mode == AddrMode::kAnAddrDecr); - a.SNPrint(addrmodearg_str, sizeof(addrmodearg_str)); + node.size_spec = ToSizeSpec(opsize); + node.opcode = OpCode::kMOVEM; if (dir == MoveDirection::kMemoryToRegister) { - snprintf(node.arguments, kArgsBufferSize, "%s,%s", addrmodearg_str, regmask_str); + node.arg1 = Arg::FromAddrModeArg(a); + node.arg2 = (a.mode == AddrMode::kAnAddrDecr) ? Arg::RegMaskPredecrement(regmask) : Arg::RegMask(regmask); } else { - snprintf(node.arguments, kArgsBufferSize, "%s,%s", regmask_str, addrmodearg_str); + node.arg1 = (a.mode == AddrMode::kAnAddrDecr) ? Arg::RegMaskPredecrement(regmask) : Arg::RegMask(regmask); + node.arg2 = Arg::FromAddrModeArg(a); } return node.size = kInstructionSizeStepBytes * 2 + a.Size(); } @@ -2007,6 +1973,38 @@ static char SizeSpecChar(RegKind k) return 'w'; } +static inline size_t snprint_reg_mask( + char *const buf, const size_t bufsz, const uint32_t regmask_arg, const bool predecrement) +{ + const uint32_t regmask = regmask_arg & 0xffff; + size_t written = 0; + bool first_printed = 0; + size_t span = 0; + // 17-th bit used to close the span with 0 value unconditionaly + for (int i = 0; i < 17; i++) { + const uint32_t mask = 1 << (predecrement ? (15 - i) : i); + const bool hit = regmask & mask; + const bool span_open = hit && span == 0; + const bool span_closed = !hit && span > 1; + const int printable_i = i - (span_closed ? 1 : 0); + const int id = printable_i % 8; + const char regtype = (printable_i >= 8) ? 'a' : 'd'; + if (span_open || span_closed) { + const char *const delimiter = span_open ? (first_printed ? "/" : "") : "-"; + const size_t remaining = bufsz - written; + const int ret = snprintf(buf + written, remaining, "%s%%%c%d", delimiter, regtype, id); + assert(ret > 0); + assert(static_cast(ret) >= strlen("%d0")); + assert(static_cast(ret) <= strlen("-%d0")); + written += Min(remaining, ret); + first_printed = true; + } + span = hit ? span + 1 : 0; + } + assert(written < bufsz); // Output must not be truncated + return written; +} + int Arg::SNPrint(char *buf, size_t bufsz, const Settings &) const { switch (type) { diff --git a/disasm.h b/disasm.h index 69a73b8..2dcff2f 100644 --- a/disasm.h +++ b/disasm.h @@ -315,6 +315,16 @@ struct Arg { a.uword = instr; return a; } + static constexpr Self RegMask(const uint16_t regmask) { + Arg a{ArgType::kRegMask, 0}; + a.uword = regmask; + return a; + } + static constexpr Self RegMaskPredecrement(const uint16_t regmask) { + Arg a{ArgType::kRegMaskPredecrement, 0}; + a.uword = regmask; + return a; + } private: static constexpr Self addrModeXn(const ArgType type, const uint8_t xn) { Arg a{type, 0}; @@ -381,9 +391,9 @@ public: case AddrMode::kAnAddr: return addrModeXn(ArgType::kAnAddr, arg.xn); case AddrMode::kAnAddrIncr: - return addrModeXn(ArgType::kAnAddrDecr, arg.xn); - case AddrMode::kAnAddrDecr: return addrModeXn(ArgType::kAnAddrIncr, arg.xn); + case AddrMode::kAnAddrDecr: + return addrModeXn(ArgType::kAnAddrDecr, arg.xn); case AddrMode::kD16AnAddr: return addrModeD16AnAddr(D16AnPCAddr{arg.xn, static_cast(arg.value)}); case AddrMode::kD8AnXiAddr: -- cgit v1.2.3