diff options
author | Oxore <oxore@protonmail.com> | 2023-04-22 21:12:19 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-04-22 21:12:19 +0300 |
commit | 0f95d73515e01fce82155f4f054df90f4dd1d048 (patch) | |
tree | 4cf350607351f4b9d5c3ed1b1b8b357c27206fd6 | |
parent | b0cab09b630b9093777febbad4cbd9003255fc85 (diff) |
Impl bsr, bra and bcc, refactor tests
-rw-r--r-- | disasm.cpp | 83 | ||||
-rw-r--r-- | test.bash | 242 |
2 files changed, 198 insertions, 127 deletions
@@ -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); } @@ -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" |