summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--disasm.cpp83
-rw-r--r--test.bash242
2 files changed, 198 insertions, 127 deletions
diff --git a/disasm.cpp b/disasm.cpp
index e4e776b..f5db2b5 100644
--- a/disasm.cpp
+++ b/disasm.cpp
@@ -3,6 +3,7 @@
#include "common.h"
#include <cstdio>
+#include <cstdlib>
static size_t disasm_verbatim(
char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t, const DataBuffer &)
@@ -131,15 +132,93 @@ static size_t disasm_jsr_jmp(
return disasm_verbatim(out, out_sz, instr_sz, instr, offset, code);
}
+static size_t disasm_jsr(
+ char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer & code)
+{
+ return disasm_jsr_jmp(out, out_sz, instr_sz, instr, offset, code, JsrJmp::kJsr);
+}
+
+static size_t disasm_jmp(
+ char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer & code)
+{
+ return disasm_jsr_jmp(out, out_sz, instr_sz, instr, offset, code, JsrJmp::kJmp);
+}
+
+enum class Condition {
+ kT = 0,
+ kF = 1,
+ kHI = 2,
+ kLS = 3,
+ kCC = 4,
+ kCS = 5,
+ kNE = 6,
+ kEQ = 7,
+ kVC = 8,
+ kVS = 9,
+ kPL = 10,
+ kMI = 11,
+ kGE = 12,
+ kLT = 13,
+ kGT = 14,
+ kLE = 15,
+};
+
+static inline const char *branch_instr_name_by_cond(Condition condition)
+{
+ switch (condition) {
+ case Condition::kT: return "bra"; // 60xx
+ case Condition::kF: return "bsr"; // 61xx
+ case Condition::kHI: return "bhi"; // 62xx
+ case Condition::kLS: return "bls"; // 63xx
+ case Condition::kCC: return "bcc"; // 64xx
+ case Condition::kCS: return "bcs"; // 65xx
+ case Condition::kNE: return "bne"; // 66xx
+ case Condition::kEQ: return "beq"; // 67xx
+ case Condition::kVC: return "bvc"; // 68xx
+ case Condition::kVS: return "bvs"; // 69xx
+ case Condition::kPL: return "bpl"; // 6axx
+ case Condition::kMI: return "bmi"; // 6bxx
+ case Condition::kGE: return "bge"; // 6cxx
+ case Condition::kLT: return "blt"; // 6dxx
+ case Condition::kGT: return "bgt"; // 6exx
+ case Condition::kLE: return "ble"; // 6fxx
+ }
+ return "?";
+}
+
+static size_t disasm_bra_bsr_bcc(
+ char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer & code)
+{
+ const char *mnemonic = branch_instr_name_by_cond(static_cast<Condition>((instr >> 8) & 0xf));
+ int dispmt = static_cast<int8_t>(instr & 0xff);
+ const char *size_spec = "s";
+ if (dispmt == 0) {
+ dispmt = GetI16BE(code.buffer + offset + kInstructionSizeStepBytes);
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes * 2;
+ }
+ size_spec = "w";
+ } else {
+ if (instr_sz) {
+ *instr_sz = kInstructionSizeStepBytes;
+ }
+ }
+ dispmt += kInstructionSizeStepBytes;
+ const char * const sign = dispmt >= 0 ? "+" : "";
+ return Min(out_sz, snprintf(out, out_sz, " %s%s .%s%d", mnemonic, size_spec, sign, dispmt));
+}
+
size_t m68k_disasm(
char *out, size_t out_sz, size_t *instr_sz, uint16_t instr, uint32_t offset, const DataBuffer &code)
{
if ((instr & 0xfff0) == 0x4e70) {
return disasm_mfff0_v4e70(out, out_sz, instr_sz, instr, offset, code);
} else if ((instr & 0xffc0) == 0x4e80) {
- return disasm_jsr_jmp(out, out_sz, instr_sz, instr, offset, code, JsrJmp::kJsr);
+ return disasm_jsr(out, out_sz, instr_sz, instr, offset, code);
} else if ((instr & 0xffc0) == 0x4ec0) {
- return disasm_jsr_jmp(out, out_sz, instr_sz, instr, offset, code, JsrJmp::kJmp);
+ return disasm_jmp(out, out_sz, instr_sz, instr, offset, code);
+ } else if ((instr & 0xf000) == 0x6000) {
+ return disasm_bra_bsr_bcc(out, out_sz, instr_sz, instr, offset, code);
}
return disasm_verbatim(out, out_sz, instr_sz, instr, offset, code);
}
diff --git a/test.bash b/test.bash
index 5227e64..408efc3 100644
--- a/test.bash
+++ b/test.bash
@@ -16,13 +16,14 @@ mkdir -p ${TEST_DIR}
echo "0" >${TRACE_FILE}
run_test_simple() {
- test_name=$1
- data=$2
- file_orig_bin=${TEST_DIR}/${test_name}.orig.bin
- file_asm=${TEST_DIR}/${test_name}.S
- file_as_o=${TEST_DIR}/${test_name}.as.o
- file_as_bin=${TEST_DIR}/${test_name}.as.bin
- echo -ne "Test ${test_name}... "
+ local test_name=$1
+ local test_name_sanitized=${test_name//[^a-zA-Z0-9_\-]/-}
+ local data=$2
+ local file_orig_bin=${TEST_DIR}/${test_name_sanitized}.orig.bin
+ local file_asm=${TEST_DIR}/${test_name_sanitized}.S
+ local file_as_o=${TEST_DIR}/${test_name_sanitized}.as.o
+ local file_as_bin=${TEST_DIR}/${test_name_sanitized}.as.bin
+ echo -ne "Test \"${test_name}\"... "
echo -ne "${data}" >${file_orig_bin}
./cmake-build/m68k-disasm -t ${TRACE_FILE} -o ${file_asm} ${file_orig_bin}
${AS} -o ${file_as_o} ${file_asm}
@@ -41,133 +42,124 @@ run_test_simple() {
}
run_test_iterative() {
- test_name=$1
- prefix=$2
- offset=$3
- count=$4
- step=$5
- suffix=$6
- file_orig_bin=${TEST_DIR}/${test_name}.orig.bin
- file_asm=${TEST_DIR}/${test_name}.S
- file_as_o=${TEST_DIR}/${test_name}.as.o
- file_as_bin=${TEST_DIR}/${test_name}.as.bin
+ local test_name=$1
+ local prefix=$2
+ local offset=$3
+ local count=$4
+ local step=$5
+ local suffix=$6
for i in $(seq 0 $(( step )) $(( count*step-1 )) ); do
- value=$(printf "%02x\n" $(( offset+i )))
- run_test_simple $test_name "${prefix}\x${value}${suffix}"
+ local value=$(printf "%02x" $(( offset+i )))
+ run_test_simple "${test_name}:${value}" "${prefix}\x${value}${suffix}"
done
}
-jsr_m2() {
- # 4e90..4e97
- #
- # All registers
- run_test_iterative ${FUNCNAME} "\x4e" 0x90 8 1 ""
-}
+# 60xx
+#
+run_test_simple "bras negative displacement" "\x60\xfc"
+run_test_simple "bras positive displacement" "\x60\x08"
-jsr_m5() {
- # (4ea8..4eaf) xxxx
- #
- # Zero value
- run_test_simple ${FUNCNAME} "\x4e\xa8\x00\x00"
- # Positive value, all registers
- run_test_iterative ${FUNCNAME} "\x4e" 0xa8 8 1 "\x00\x0a"
- # Negative value
- run_test_simple ${FUNCNAME} "\x4e\xa8\x80\x0f"
-}
+# 60xx (xxxx)
+#
+run_test_simple "braw negative displacement" "\x60\x00\xf8\x2e"
+run_test_simple "braw positive displacement" "\x60\x00\x03\xe6"
+run_test_simple "braw zero displacement" "\x60\x00\x00\x00"
-jsr_m6() {
- # (4eb0..4eb7) xxxx
- #
- # Positive value, Arbitrary An register
- run_test_iterative ${FUNCNAME} "\x4e" 0xb0 8 1 "\x00\x0f"
- # Negative value
- run_test_simple ${FUNCNAME} "\x4e\xb0\x00\xf0"
- # Zero displacement
- run_test_simple ${FUNCNAME} "\x4e\xb0\x00\x00"
- # Address register
- run_test_simple ${FUNCNAME} "\x4e\xb0\x80\x0a"
- # Long displacement, positive
- run_test_simple ${FUNCNAME} "\x4e\xb0\x08\x0c"
- # Long displacement, negative
- run_test_simple ${FUNCNAME} "\x4e\xb0\x08\xb0"
- # Arbitrary Xn2
- run_test_iterative ${FUNCNAME} "\x4e\xb0" 0x00 8 0x10 "\x0f"
-}
+# 61xx (xxxx)
+#
+run_test_simple "bsrs negative displacement" "\x61\x88"
+run_test_simple "bsrw positive displacement" "\x61\x00\x03\xe6"
-jsr_m7_xn0() {
- # 43b8 xxxx Word displacement
- #
- # Zero value
- run_test_simple ${FUNCNAME} "\x4e\xb8\x00\x00"
- # Positive value
- run_test_simple ${FUNCNAME} "\x4e\xb8\x00\x1f"
- # Negative value
- run_test_simple ${FUNCNAME} "\x4e\xb8\x8a\x0c"
-}
+# 6xxx
+#
+run_test_simple "bhis" "\x62\x0a"
+run_test_simple "blss" "\x63\x0a"
+run_test_simple "bccs" "\x64\x0a"
+run_test_simple "bcss" "\x65\x0a"
+run_test_simple "bnes" "\x66\x0a"
+run_test_simple "beqs" "\x67\x0a"
+run_test_simple "bvcs" "\x68\x0a"
+run_test_simple "bvss" "\x69\x0a"
+run_test_simple "bpls" "\x6a\x0a"
+run_test_simple "bmis" "\x6b\x0a"
+run_test_simple "bges" "\x6c\x0a"
+run_test_simple "blts" "\x6d\x0a"
+run_test_simple "bgts" "\x6e\x0a"
+run_test_simple "bles" "\x6f\x0a"
-jsr_m7_xn1() {
- # 43b9 xxxx Long displacement
- #
- # Zero value
- run_test_simple ${FUNCNAME} "\x4e\xb9\x00\x00\x00\x00"
- # Positive value
- run_test_simple ${FUNCNAME} "\x4e\xb9\x10\xbb\x43\x1f"
- # Negative value
- run_test_simple ${FUNCNAME} "\x4e\xb9\x80\xcc\xd9\x8a"
-}
+# 4e70
+#
+# reset
+run_test_simple "reset" "\x4e\x70"
-jsr_m7_xn2() {
- # 43ba xxxx
- #
- # Zero value
- run_test_simple ${FUNCNAME} "\x4e\xba\x00\x00"
- # Positive value
- run_test_simple ${FUNCNAME} "\x4e\xba\x00\x1f"
- # Negative value
- run_test_simple ${FUNCNAME} "\x4e\xba\x8a\x0c"
-}
+# 4e71
+#
+# nop
+run_test_simple "nop" "\x4e\x71"
-jsr_m7_xn3() {
- # 43bb xxxx
- #
- # Positive value, Arbitrary Xn register
- run_test_iterative ${FUNCNAME} "\x4e\xbb" 0x00 8 0x10 "\x1a"
- # Negative value
- run_test_simple ${FUNCNAME} "\x4e\xbb\x00\xf0"
- # Zero displacement
- run_test_simple ${FUNCNAME} "\x4e\xbb\x00\x00"
- # Address register
- run_test_simple ${FUNCNAME} "\x4e\xbb\x80\x0a"
- # Long displacement, positive
- run_test_simple ${FUNCNAME} "\x4e\xbb\x08\x0c"
- # Long displacement, negative
- run_test_simple ${FUNCNAME} "\x4e\xbb\x08\xb0"
- # Arbitrary Xn2
- run_test_iterative ${FUNCNAME} "\x4e\xbb" 0x00 8 0x10 "\x0f"
-}
+# 4e73
+#
+# rte
+run_test_simple "rte" "\x4e\x73"
-reset_nop_rte_rts_trapv_rtr() {
- # 4e7x
- #
- # reset / 4e70
- run_test_simple ${FUNCNAME} "\x4e\x70"
- # nop / 4e71
- run_test_simple ${FUNCNAME} "\x4e\x71"
- # rte / 4e73
- run_test_simple ${FUNCNAME} "\x4e\x73"
- # rts / 4e75
- run_test_simple ${FUNCNAME} "\x4e\x75"
- # trapv / 4e76
- run_test_simple ${FUNCNAME} "\x4e\x76"
- # rtr / 4e77
- run_test_simple ${FUNCNAME} "\x4e\x77"
-}
+# 4e75
+#
+# rts
+run_test_simple "rts" "\x4e\x75"
-jsr_m2
-jsr_m5
-jsr_m6
-jsr_m7_xn0
-jsr_m7_xn1
-jsr_m7_xn2
-jsr_m7_xn3
-reset_nop_rte_rts_trapv_rtr
+# 4e76
+#
+# trapv
+run_test_simple "trapv" "\x4e\x76"
+
+# 4e77
+#
+# rtr
+run_test_simple "rtr" "\x4e\x77"
+
+# 4e90..4e97
+#
+run_test_iterative "jsr M2 all An" "\x4e" 0x90 8 1 ""
+
+# (4ea8..4eaf) xxxx
+#
+run_test_simple "jsr M5 zero value" "\x4e\xa8\x00\x00"
+run_test_iterative "jsr M5 all An, positive" "\x4e" 0xa8 8 1 "\x00\x0a"
+run_test_simple "jsr M5 A0 negative" "\x4e\xa8\x80\x0f"
+
+# (4eb0..4eb7) xxxx
+#
+run_test_iterative "jsr M6 arbitrary An, positive" "\x4e" 0xb0 8 1 "\x00\x0f"
+run_test_simple "jsr M6 A0 negative" "\x4e\xb0\x00\xf0"
+run_test_simple "jsr M6 A0 zero" "\x4e\xb0\x00\x00"
+run_test_simple "jsr M6 address register" "\x4e\xb0\x80\x0a"
+run_test_simple "jsr M6 long displacement positive" "\x4e\xb0\x08\x0c"
+run_test_simple "jsr M6 long displacement negative" "\x4e\xb0\x08\xb0"
+run_test_iterative "jsr M6 arbitrary Xn2" "\x4e\xb0" 0x00 8 0x10 "\x0f"
+
+# 43b8 xxxx Word displacement
+#
+run_test_simple "jsr M7 Xn0 zero" "\x4e\xb8\x00\x00"
+run_test_simple "jsr M7 Xn0 positive" "\x4e\xb8\x00\x1f"
+run_test_simple "jsr M7 Xn0 negative" "\x4e\xb8\x8a\x0c"
+
+# 43b9 xxxx Long displacement
+#
+run_test_simple "jsr M7 X1 zero" "\x4e\xb9\x00\x00\x00\x00"
+run_test_simple "jsr M7 X1 positive" "\x4e\xb9\x10\xbb\x43\x1f"
+run_test_simple "jsr M7 X1 negative" "\x4e\xb9\x80\xcc\xd9\x8a"
+
+# 43ba xxxx
+#
+run_test_simple "jsr M7 X2 zero value" "\x4e\xba\x00\x00"
+run_test_simple "jsr M7 X2 positive value" "\x4e\xba\x00\x1f"
+run_test_simple "jsr M7 X2 negative value" "\x4e\xba\x8a\x0c"
+
+# 43bb xxxx
+#
+run_test_simple "jsr M7 X3 negative" "\x4e\xbb\x00\xf0"
+run_test_simple "jsr M7 X3 zero displacement" "\x4e\xbb\x00\x00"
+run_test_simple "jsr M7 X3 An2=A0" "\x4e\xbb\x80\x0a"
+run_test_simple "jsr M7 X3 long positive displacement" "\x4e\xbb\x08\x0c"
+run_test_simple "jsr M7 X3 long negative displacement" "\x4e\xbb\x08\xb0"
+run_test_iterative "jsr M7 X3 arbitrary Dn2" "\x4e\xbb" 0x00 8 0x10 "\x0f"