summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-05-01 20:11:36 +0300
committerOxore <oxore@protonmail.com>2023-05-01 20:11:36 +0300
commit67cd57b5e5dcf4c434e368a805f566daf829853f (patch)
tree5930c2751bd0b39091c7d6df035c68f06af42eb4
parentbecd897fe8bd4458d6c089dfcb07299a13f7b817 (diff)
Impl BTST, BCHG, BSET and BCLR
-rw-r--r--common.h8
-rw-r--r--disasm.cpp166
-rw-r--r--test.bash15
3 files changed, 133 insertions, 56 deletions
diff --git a/common.h b/common.h
index 1a99f75..fbd73de 100644
--- a/common.h
+++ b/common.h
@@ -13,19 +13,19 @@ constexpr size_t kInstructionSizeStepBytes = 2;
constexpr size_t kRomSizeBytes = 4 * 1024 * 1024;
constexpr size_t kDisasmMapSizeElements = kRomSizeBytes / kInstructionSizeStepBytes;
-constexpr size_t Min(size_t a, size_t b) { return a < b ? a : b; }
+static inline constexpr size_t Min(size_t a, size_t b) { return a < b ? a : b; }
-constexpr uint16_t GetU16BE(uint8_t *buffer)
+static inline constexpr uint16_t GetU16BE(uint8_t *buffer)
{
return (static_cast<uint16_t>(buffer[0]) << 8) | static_cast<uint16_t>(buffer[1]);
}
-constexpr int16_t GetI16BE(uint8_t *buffer)
+static inline constexpr int16_t GetI16BE(uint8_t *buffer)
{
return (static_cast<uint16_t>(buffer[0]) << 8) | static_cast<uint16_t>(buffer[1]);
}
-constexpr int32_t GetI32BE(uint8_t *buffer)
+static inline constexpr int32_t GetI32BE(uint8_t *buffer)
{
return (static_cast<uint32_t>(buffer[0]) << 24) |
(static_cast<uint32_t>(buffer[1]) << 16) |
diff --git a/disasm.cpp b/disasm.cpp
index ef53952..c75f794 100644
--- a/disasm.cpp
+++ b/disasm.cpp
@@ -131,7 +131,7 @@ struct AddrModeArg {
const int xn = addrmode & 7;
return Fetch(offset, code, m, xn, s);
}
- static constexpr AddrModeArg Fetch(
+ static inline constexpr AddrModeArg Fetch(
uint32_t offset, const DataBuffer &code, int m, int xn, char s);
int SNPrint(char *const buf, const size_t bufsz) const
{
@@ -278,7 +278,7 @@ static char suffix_from_opsize(OpSize opsize)
return 'l';
}
-size_t snprint_reg_mask(
+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;
@@ -311,7 +311,7 @@ size_t snprint_reg_mask(
}
static void disasm_verbatim(
- DisasmNode& node, uint16_t instr, const DataBuffer &, const Settings &)
+ DisasmNode &node, uint16_t instr, const DataBuffer &, const Settings &)
{
node.size = kInstructionSizeStepBytes;
snprintf(node.mnemonic, kMnemonicBufferSize, ".short");
@@ -319,7 +319,7 @@ static void disasm_verbatim(
}
static void disasm_jsr_jmp(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s, JType jsrjmp)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s, JType jsrjmp)
{
const auto a = AddrModeArg::Fetch(node.offset + kInstructionSizeStepBytes, code, instr, 'w');
switch (a.mode) {
@@ -383,7 +383,7 @@ static void disasm_jsr_jmp(
}
static void disasm_movem(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
if (node.offset + kInstructionSizeStepBytes >= code.occupied_size) {
// Not enough space for regmask
@@ -444,13 +444,13 @@ static void disasm_movem(
}
static void disasm_lea(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
return disasm_verbatim(node, instr, code, s);
}
static void disasm_chk(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
return disasm_verbatim(node, instr, code, s);
}
@@ -499,7 +499,7 @@ static inline const char *bcc_mnemonic_by_condition(Condition condition)
}
static void disasm_bra_bsr_bcc(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
Condition condition = static_cast<Condition>((instr >> 8) & 0xf);
const char *mnemonic = bcc_mnemonic_by_condition(condition);
@@ -534,34 +534,100 @@ static void disasm_bra_bsr_bcc(
return;
}
-const char *mnemonic_for_bitops(OpSize opsize)
+static inline const char *mnemonic_for_bitops(unsigned opcode)
{
- switch (opsize) {
- case OpSize::kByte: return "btst";
- case OpSize::kWord: return "bchg";
- case OpSize::kLong: return "bclr";
- case OpSize::kInvalid: return "bset";
+ switch (opcode) {
+ case 0: return "btst";
+ case 1: return "bchg";
+ case 2: return "bclr";
+ case 3: return "bset";
}
assert(false);
return "?";
}
-static void disasm_dobule_args_bitops_movep(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+static inline void disasm_movep(
+ DisasmNode &node, const uint16_t instr, const DataBuffer &code, const Settings &s)
{
- // TODO
return disasm_verbatim(node, instr, code, s);
}
-static void disasm_bitops(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+static void disasm_src_arg_bitops_movep(
+ DisasmNode &node,
+ const uint16_t instr,
+ const DataBuffer &code,
+ const Settings &s,
+ const bool has_dn_src = true)
{
- // TODO
- return disasm_verbatim(node, instr, code, s);
+ const unsigned m = (instr >> 3) & 7;
+ if ((m == 1) && has_dn_src) {
+ return disasm_movep(node, instr, code, s);
+ }
+ const unsigned dn = ((instr >> 9) & 7);
+ const unsigned xn = instr & 7;
+ // Fetch AddrMode::kDn if has_dn_src, otherwise fetch AddrMode::kImmediate
+ // byte
+ const auto src = AddrModeArg::Fetch(
+ node.offset + kInstructionSizeStepBytes,
+ code,
+ (has_dn_src) ? 0 : 7,
+ dn,
+ 'b');
+ if (src.mode == AddrMode::kInvalid) {
+ return disasm_verbatim(node, instr, code, s);
+ }
+ if (has_dn_src) {
+ assert(src.mode == AddrMode::kDn);
+ } else {
+ assert(dn == 4);
+ assert(src.mode == AddrMode::kImmediate);
+ }
+ const auto dst = AddrModeArg::Fetch(
+ node.offset + kInstructionSizeStepBytes + src.Size(), code, m, xn, 'w');
+ const unsigned opcode = (instr >> 6) & 3;
+ switch (dst.mode) {
+ case AddrMode::kInvalid:
+ return disasm_verbatim(node, instr, code, s);
+ case AddrMode::kDn:
+ break;
+ case AddrMode::kAn:
+ return disasm_verbatim(node, instr, code, s);
+ case AddrMode::kAnAddr:
+ case AddrMode::kAnAddrIncr:
+ case AddrMode::kAnAddrDecr:
+ case AddrMode::kD16AnAddr:
+ case AddrMode::kD8AnXiAddr:
+ case AddrMode::kWord:
+ case AddrMode::kLong:
+ break;
+ case AddrMode::kD16PCAddr:
+ case AddrMode::kD8PCXiAddr:
+ if (opcode != 0) {
+ // PC relative destination address argument available for BTST only
+ return disasm_verbatim(node, instr, code, s);
+ }
+ break;
+ case AddrMode::kImmediate:
+ return disasm_verbatim(node, instr, code, s);
+ }
+ char src_str[32]{};
+ char dst_str[32]{};
+ src.SNPrint(src_str, sizeof(src_str));
+ dst.SNPrint(dst_str, sizeof(dst_str));
+ const char suffix = dst.mode == AddrMode::kDn ? 'l' : 'b';
+ const char *mnemonic = mnemonic_for_bitops(opcode);
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ snprintf(node.arguments, kArgsBufferSize, "%s,%s", src_str, dst_str);
+ node.size = kInstructionSizeStepBytes + src.Size() + dst.Size();
+}
+
+static void disasm_bitops(DisasmNode &n, const uint16_t i, const DataBuffer &c, const Settings &s)
+{
+ return disasm_src_arg_bitops_movep(n, i, c, s, false);
}
static inline void disasm_logical_imm_to(
- DisasmNode& node, const char* mnemonic, const char suffix, const int16_t imm)
+ DisasmNode &node, const char* mnemonic, const char suffix, const int16_t imm)
{
const char *reg = suffix == 'b' ? "ccr" : "sr";
snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
@@ -569,7 +635,7 @@ static inline void disasm_logical_imm_to(
node.size = kInstructionSizeStepBytes * 2;
}
-const char *mnemonic_for_chunk_mf000_v1000(const unsigned opcode)
+static inline const char *mnemonic_for_chunk_mf000_v1000(const unsigned opcode)
{
switch (opcode) {
case 0: return "ori";
@@ -586,11 +652,11 @@ const char *mnemonic_for_chunk_mf000_v1000(const unsigned opcode)
}
static void chunk_mf000_v0000(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
const bool has_source_reg = (instr >> 8) & 1;
if (has_source_reg) {
- return disasm_dobule_args_bitops_movep(node, instr, code, s);
+ return disasm_src_arg_bitops_movep(node, instr, code, s);
}
const unsigned opcode = (instr >> 9) & 7;
if (opcode == 7) {
@@ -665,7 +731,7 @@ static void chunk_mf000_v0000(
}
static void disasm_move_movea(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
const int size_spec = (instr >> 12) & 3;
const char suffix = size_spec == 1 ? 'b' : (size_spec == 3 ? 'w' : 'l');
@@ -716,7 +782,7 @@ static void disasm_move_movea(
}
static void disasm_move_from_sr(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
const char suffix = 'w';
const auto dst = AddrModeArg::Fetch(
@@ -749,7 +815,7 @@ static void disasm_move_from_sr(
}
static void disasm_move_to(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s, const char* reg)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s, const char* reg)
{
const char suffix = 'w';
const auto src = AddrModeArg::Fetch(
@@ -780,7 +846,7 @@ static void disasm_move_to(
node.size = kInstructionSizeStepBytes + src.Size();
}
-const char *mnemonic_for_chunk_mf800_v4000(const unsigned opcode)
+static inline const char *mnemonic_for_chunk_mf800_v4000(const unsigned opcode)
{
switch (opcode) {
case 0: return "negx";
@@ -793,7 +859,7 @@ const char *mnemonic_for_chunk_mf800_v4000(const unsigned opcode)
}
static void chunk_mf900_v4000(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
const auto opsize = static_cast<OpSize>((instr >> 6) & 3);
const unsigned opcode = (instr >> 9) & 3;
@@ -842,15 +908,15 @@ static void chunk_mf900_v4000(
node.size = kInstructionSizeStepBytes + a.Size();
}
-static void disasm_trivial(
- DisasmNode& node, uint16_t, const DataBuffer &, const Settings &, const char* mnemonic)
+static inline void disasm_trivial(
+ DisasmNode &node, uint16_t, const DataBuffer &, const Settings &, const char* mnemonic)
{
node.size = kInstructionSizeStepBytes;
snprintf(node.mnemonic, kMnemonicBufferSize, mnemonic);
}
static inline void disasm_tas(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
const auto a = AddrModeArg::Fetch(node.offset + kInstructionSizeStepBytes, code, instr, 'w');
switch (a.mode) {
@@ -881,7 +947,7 @@ static inline void disasm_tas(
}
static void disasm_tst_tas_illegal(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
const auto opsize = static_cast<OpSize>((instr >> 6) & 3);
const int m = (instr >> 3) & 7;
@@ -922,7 +988,7 @@ static void disasm_tst_tas_illegal(
}
static void disasm_trap(
- DisasmNode& node, uint16_t instr, const DataBuffer &, const Settings &)
+ DisasmNode &node, uint16_t instr, const DataBuffer &, const Settings &)
{
const unsigned vector = instr & 0xf;
snprintf(node.mnemonic, kMnemonicBufferSize, "trap");
@@ -931,7 +997,7 @@ static void disasm_trap(
}
static void disasm_link_unlink(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
const bool unlk = (instr >> 3) & 1;
const unsigned xn = instr & 7;
@@ -968,7 +1034,7 @@ static void disasm_link_unlink(
}
static void disasm_move_usp(
- DisasmNode& node, uint16_t instr, const DataBuffer &, const Settings &)
+ DisasmNode &node, uint16_t instr, const DataBuffer &, const Settings &)
{
const unsigned xn = instr & 7;
const auto dir = static_cast<MoveDirection>((instr >> 3) & 1);
@@ -982,7 +1048,7 @@ static void disasm_move_usp(
}
static void chunk_mf000_v4000(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
if ((instr & 0xf900) == 0x4000) {
return chunk_mf900_v4000(node, instr, code, s);
@@ -1029,7 +1095,7 @@ static void chunk_mf000_v4000(
}
static void disasm_addq_subq(
- DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s, OpSize opsize)
+ DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s, OpSize opsize)
{
const char suffix = suffix_from_opsize(opsize);
const auto a = AddrModeArg::Fetch(node.offset + kInstructionSizeStepBytes, code, instr, suffix);
@@ -1093,7 +1159,7 @@ static inline const char *dbcc_mnemonic_by_condition(Condition condition)
return "?";
}
-static void disasm_dbcc(DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+static void disasm_dbcc(DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
if (node.offset + kInstructionSizeStepBytes >= code.occupied_size) {
return disasm_verbatim(node, instr, code, s);
@@ -1142,7 +1208,7 @@ static inline const char *scc_mnemonic_by_condition(Condition condition)
}
static void disasm_scc_dbcc(
- DisasmNode& node, const uint16_t instr, const DataBuffer &code, const Settings &s)
+ DisasmNode &node, const uint16_t instr, const DataBuffer &code, const Settings &s)
{
const auto a = AddrModeArg::Fetch(node.offset + kInstructionSizeStepBytes, code, instr, 'w');
switch (a.mode) {
@@ -1173,7 +1239,7 @@ static void disasm_scc_dbcc(
a.SNPrint(node.arguments, kArgsBufferSize);
}
-static void chunk_mf000_v5000(DisasmNode& n, uint16_t instr, const DataBuffer &c, const Settings &s)
+static void chunk_mf000_v5000(DisasmNode &n, uint16_t instr, const DataBuffer &c, const Settings &s)
{
const auto opsize = static_cast<OpSize>((instr >> 6) & 3);
if (opsize == OpSize::kInvalid) {
@@ -1182,7 +1248,7 @@ static void chunk_mf000_v5000(DisasmNode& n, uint16_t instr, const DataBuffer &c
return disasm_addq_subq(n, instr, c, s, opsize);
}
-static void disasm_moveq(DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+static void disasm_moveq(DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
{
if (instr & 0x100) {
// Does not exist
@@ -1201,37 +1267,37 @@ static void disasm_moveq(DisasmNode& node, uint16_t instr, const DataBuffer &cod
}
-static void chunk_mf000_v8000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
+static void chunk_mf000_v8000(DisasmNode &n, uint16_t i, const DataBuffer &c, const Settings &s)
{
return disasm_verbatim(n, i, c, s);
}
-static void chunk_mf000_v9000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
+static void chunk_mf000_v9000(DisasmNode &n, uint16_t i, const DataBuffer &c, const Settings &s)
{
return disasm_verbatim(n, i, c, s);
}
-static void chunk_mf000_vb000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
+static void chunk_mf000_vb000(DisasmNode &n, uint16_t i, const DataBuffer &c, const Settings &s)
{
return disasm_verbatim(n, i, c, s);
}
-static void chunk_mf000_vc000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
+static void chunk_mf000_vc000(DisasmNode &n, uint16_t i, const DataBuffer &c, const Settings &s)
{
return disasm_verbatim(n, i, c, s);
}
-static void chunk_mf000_vd000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
+static void chunk_mf000_vd000(DisasmNode &n, uint16_t i, const DataBuffer &c, const Settings &s)
{
return disasm_verbatim(n, i, c, s);
}
-static void chunk_mf000_ve000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
+static void chunk_mf000_ve000(DisasmNode &n, uint16_t i, const DataBuffer &c, const Settings &s)
{
return disasm_verbatim(n, i, c, s);
}
-static void m68k_disasm(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
+static void m68k_disasm(DisasmNode &n, uint16_t i, const DataBuffer &c, const Settings &s)
{
switch ((i & 0xf000) >> 12) {
case 0x0:
diff --git a/test.bash b/test.bash
index a3bff0e..90279ec 100644
--- a/test.bash
+++ b/test.bash
@@ -76,7 +76,7 @@ run_test_simple() {
cat ${file_asm}
else
echo -e "${CGREEN}OK${CRST}"
- #cat ${file_asm}
+ cat ${file_asm}
fi
}
@@ -93,7 +93,18 @@ run_test_iterative() {
done
}
-# 0xxx
+# 0xxx bitwise ops
+#
+run_test_simple "btstl immediate in Dn" "\x08\x07\x00\x06"
+run_test_simple "btstb immediate in (An)" "\x08\x17\x00\x06"
+run_test_simple "btstb immediate in (xxx).L" "\x08\x39\x00\x06\xff\x00\x00\x00"
+run_test_simple "btstb Dn in (xxx).L" "\x03\x39\xff\x00\x00\x00"
+run_test_simple "bchgb Dn in (xxx).L" "\x05\x79\xff\x00\x00\x00"
+run_test_simple "bclrb Dn in (xxx).L" "\x07\xb9\xff\x00\x00\x00"
+run_test_simple "bsetb Dn in (xxx).L" "\x09\xf9\xff\x00\x00\x00"
+run_test_expect_short "btstb large immediate in (xxx).L" "\x08\x39\x10\x21\xff\x00\x00\x00"
+
+# 0xxx immediate ops
#
run_test_simple "orib zero to CCR" "\x00\x3c\x00\x00"
run_test_simple "orib positive to CCR" "\x00\x3c\x00\x01"