From b15db82f7ce2a4b11e0cfe55b3c31cc8c4a8d89a Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 28 Dec 2020 23:20:14 -0800 Subject: 7455 New approach to disambiguating /disp32 arguments: based on opcodes rather than metadata. I interpret /disp32 as PC-relative in a short list of instructions. Otherwise it's absolute if it gets a label. There should be no reason to pass labels into /disp8 or /disp16. --- 036labels.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to '036labels.cc') diff --git a/036labels.cc b/036labels.cc index c269538a..72d11da5 100644 --- a/036labels.cc +++ b/036labels.cc @@ -224,6 +224,7 @@ void replace_labels_with_displacements(segment& code, const map const word& curr = inst.words.at(j); if (contains_key(byte_index, curr.data)) { int32_t displacement = static_cast(get(byte_index, curr.data)) - byte_index_next_instruction_starts_at; + int32_t absolute_address = code.start + get(byte_index, curr.data); if (has_argument_metadata(curr, "disp8")) { if (displacement > 0x7f || displacement < -0x7f) raise << "'" << to_string(inst) << "': label too far away for displacement " << std::hex << displacement << " to fit in 8 signed bits\n" << end(); @@ -237,9 +238,12 @@ void replace_labels_with_displacements(segment& code, const map emit_hex_bytes(new_inst, displacement, 2); } else if (has_argument_metadata(curr, "disp32")) { - emit_hex_bytes(new_inst, displacement, 4); + if (is_far_jump_or_call(new_inst)) + emit_hex_bytes(new_inst, displacement, 4); + else + emit_hex_bytes(new_inst, absolute_address, 4); } else if (has_argument_metadata(curr, "imm32")) { - emit_hex_bytes(new_inst, code.start + get(byte_index, curr.data), 4); + emit_hex_bytes(new_inst, absolute_address, 4); } } else { @@ -251,6 +255,15 @@ void replace_labels_with_displacements(segment& code, const map } } +bool is_far_jump_or_call(const line& inst) { + string first_opcode = inst.words.at(0).data; + if (first_opcode == "e8" || first_opcode == "e9") return true; + if (SIZE(inst.words) < 2) return false; + if (first_opcode != "0f") return false; + string second_opcode = inst.words.at(1).data; + return starts_with(second_opcode, "8"); +} + string data_to_string(const line& inst) { ostringstream out; for (int i = 0; i < SIZE(inst.words); ++i) { -- cgit 1.4.1-2-gfad0