diff options
author | Oxore <oxore@protonmail.com> | 2023-04-20 01:53:04 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-04-20 01:58:22 +0300 |
commit | 09ea96e0d2fc82147603259c3b1bcbe30f586164 (patch) | |
tree | cb24180b066ebb0b4570693f6a61819fff673799 | |
parent | 088c90dc459841bd513cd8b0bf9c91d9af06ff41 (diff) |
Implement brief word extension for jsr (part 1)
-rw-r--r-- | main.cpp | 36 | ||||
-rw-r--r-- | test.bash | 41 |
2 files changed, 56 insertions, 21 deletions
@@ -71,7 +71,7 @@ struct DisasmNode { static size_t disasm_verbatim( char *out, size_t out_sz, uint16_t instr, uint32_t offset, const DataBuffer &) { - snprintf(out, out_sz, " .short 0x%04x | traced @%" PRIu32 "\n", instr, offset); + snprintf(out, out_sz, " .short 0x%04x | traced @%08" PRIx32 "\n", instr, offset); return kInstructionSizeStepBytes; } @@ -83,7 +83,7 @@ static size_t disasm_mfff0_v4e70( } else if (instr == 0x4e71) { snprintf(out, out_sz, " nop | %04x @%04x\n", instr, offset); } else if (instr == 0x4e72) { - snprintf(out, out_sz, " .short 0x%04x | stop (not implemented) @%" PRIu32 "\n", instr, offset); + snprintf(out, out_sz, " .short 0x%04x | stop (not implemented) @%08" PRIx32 "\n", instr, offset); } else if (instr == 0x4e73) { snprintf(out, out_sz, " rte | %04x @%04x\n", instr, offset); } else if (instr == 0x4e75) { @@ -119,36 +119,48 @@ static size_t disasm_jsr( case 1: // 4e88 .. 4e8f return disasm_verbatim(out, out_sz, instr, offset, code); case 2: // 4e90 .. 4e97 - snprintf(out, out_sz, " jsr %%a%d@ | %04x @%" PRIu32 "\n", xn, instr, offset); + snprintf(out, out_sz, " jsr %%a%d@ | %04x @%08" PRIx32 "\n", xn, instr, offset); return kInstructionSizeStepBytes; case 3: // 4e98 .. 4e9f case 4: // 4ea0 .. 4ea7 return disasm_verbatim(out, out_sz, instr, offset, code); - case 5: // 4ea8 .. 4eaf + case 5: // 4ea8 .. 4eaf, Displacement { const int16_t dispmt = GetI16BE(code.buffer + offset + kInstructionSizeStepBytes); const uint16_t dispmt_u = static_cast<uint16_t>(dispmt); snprintf( out, out_sz, - " jsr %%a%d@(%d) | %04x %04x @%" PRIu32 "\n", + " jsr %%a%d@(%d) | %04x %04x @%08" PRIx32 "\n", xn, dispmt, instr, dispmt_u, offset); return 4; } break; case 6: // 4eb0 .. 4eb7, Brief Extension Word - // TODO + { + const uint16_t briefext = GetU16BE(code.buffer + offset + kInstructionSizeStepBytes); + const int m_0d_1a = (briefext >> 15) & 1; + const int xn2 = (briefext >> 12) & 7; + const int s_0w_1l = (briefext >> 11) & 1; + const int8_t dispmt = briefext & 0xff; + snprintf( + out, out_sz, + " jsr %%a%d@(%d,%%%c%d:%c) | %04x %04x @%08" PRIx32 "\n", + xn, dispmt, m_0d_1a ? 'a' : 'd', xn2, s_0w_1l ? 'l' : 'w', instr, briefext, offset); + return 4; + } break; case 7: // 4eb0 .. 4eb7, some are with Brief Extension Word switch (xn) { - case 0: - case 1: - case 2: - case 3: + case 0: // 4eb0 + case 1: // 4eb1 + case 2: // 4eb2 + case 3: // 4eb3 + // TODO + break; case 4: case 5: case 6: - // TODO - break; + return disasm_verbatim(out, out_sz, instr, offset, code); } break; } @@ -20,13 +20,14 @@ run_test() { prefix=$2 offset=$3 count=$4 - suffix=$5 + 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 - for i in $(seq 0 $(( count-1 )) ); do - echo -ne "Test ${test_name}:$i... " + for i in $(seq 0 $(( step )) $(( count*step-1 )) ); do + echo -ne "Test ${test_name}:$(( i / step ))... " value=$(printf "%02x\n" $(( offset+i ))) echo -ne "${prefix}\x${value}${suffix}" >${file_orig_bin} ./cmake-build/m68k-disasm -t ${TRACE_FILE} -o ${file_asm} ${file_orig_bin} @@ -41,6 +42,7 @@ run_test() { break; else echo "OK" + cat ${file_asm} fi done } @@ -48,22 +50,43 @@ run_test() { jsr_m2() { # 4e90..4e97 # - run_test ${FUNCNAME} "\x4e" 0x90 8 "" + # All registers + run_test ${FUNCNAME} "\x4e" 0x90 8 1 "" } -jsr_m6() { - # (4ea8..4eaf) 0000 +jsr_m5() { + # (4ea8..4eaf) xxxx # # XXX this test fails with suffix "\x00\x00", because GNU AS makes # optimization and inserts jsr M2/"(An)" (0x4e90) version instead. Hence the # disassembler must generate ".short" alternative in such cases. But it may be # irrelevant in practice if this variant simply does not exist in the wild. # - # Positive value - run_test ${FUNCNAME} "\x4e" 0xa8 8 "\x00\x0a" + # Positive value, all registers + run_test ${FUNCNAME} "\x4e" 0xa8 8 1 "\x00\x0a" + # Negative value + run_test ${FUNCNAME} "\x4e" 0xa8 1 1 "\x80\x0f" +} + +jsr_m6() { + # (4eb0..4eb7) xxxx + # + # Positive value, Arbitrary Xn register + run_test ${FUNCNAME} "\x4e" 0xb0 8 1 "\x00\x0f" # Negative value - run_test ${FUNCNAME} "\x4e" 0xa8 8 "\x80\x0f" + run_test ${FUNCNAME} "\x4e" 0xb0 1 1 "\x00\xf0" + # Zero displacement + run_test ${FUNCNAME} "\x4e" 0xb0 1 1 "\x00\x00" + # Address register + run_test ${FUNCNAME} "\x4e" 0xb0 1 1 "\x80\x0a" + # Long displacement, positive + run_test ${FUNCNAME} "\x4e" 0xb0 1 1 "\x08\x0c" + # Long displacement, negative + run_test ${FUNCNAME} "\x4e" 0xb0 1 1 "\x08\xb0" + # Arbitrary Xn2 + run_test ${FUNCNAME} "\x4e\xb0" 0x00 8 0x10 "\x0f" } jsr_m2 +jsr_m5 jsr_m6 |