shifts are always immediate in single data transfer

Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
2023-09-15 10:24:23 +05:30
parent 7fc6876264
commit aa96237c37

View File

@@ -3,6 +3,8 @@
#include "util/bits.hh" #include "util/bits.hh"
#include <iterator> #include <iterator>
using namespace arm;
ArmInstruction::ArmInstruction(uint32_t insn) ArmInstruction::ArmInstruction(uint32_t insn)
: condition(static_cast<Condition>(bit_range(insn, 28, 31))) { : condition(static_cast<Condition>(bit_range(insn, 28, 31))) {
// Branch and exhcange // Branch and exhcange
@@ -17,10 +19,7 @@ ArmInstruction::ArmInstruction(uint32_t insn)
uint32_t offset = bit_range(insn, 0, 23); uint32_t offset = bit_range(insn, 0, 23);
// lsh 2 and sign extend the 26 bit offset to 32 bits // lsh 2 and sign extend the 26 bit offset to 32 bits
offset <<= 2; offset = (static_cast<int32_t>(offset) << 8) >> 6;
if (get_bit(offset, 25))
offset |= 0xFC000000;
offset += 2 * ARM_INSTRUCTION_SIZE; offset += 2 * ARM_INSTRUCTION_SIZE;
@@ -72,7 +71,6 @@ ArmInstruction::ArmInstruction(uint32_t insn)
// Single data transfer // Single data transfer
} else if ((insn & 0x0C000000) == 0x04000000) { } else if ((insn & 0x0C000000) == 0x04000000) {
std::variant<uint16_t, Shift> offset; std::variant<uint16_t, Shift> offset;
uint8_t rd = bit_range(insn, 12, 15); uint8_t rd = bit_range(insn, 12, 15);
uint8_t rn = bit_range(insn, 16, 19); uint8_t rn = bit_range(insn, 16, 19);
@@ -84,15 +82,16 @@ ArmInstruction::ArmInstruction(uint32_t insn)
bool imm = get_bit(insn, 25); bool imm = get_bit(insn, 25);
if (imm) { if (imm) {
// register specified shift amounts not available in single data
// transfer (see Undefined)
uint8_t rm = bit_range(insn, 0, 3); uint8_t rm = bit_range(insn, 0, 3);
bool reg = get_bit(insn, 4);
ShiftType shift_type = ShiftType shift_type =
static_cast<ShiftType>(bit_range(insn, 5, 6)); static_cast<ShiftType>(bit_range(insn, 5, 6));
uint8_t operand = bit_range(insn, (reg ? 8 : 7), 11); uint8_t operand = bit_range(insn, 7, 11);
offset = Shift{ .rm = rm, offset = Shift{ .rm = rm,
.data = ShiftData{ .type = shift_type, .data = ShiftData{ .type = shift_type,
.immediate = !reg, .immediate = true,
.operand = operand } }; .operand = operand } };
} else { } else {
offset = static_cast<uint16_t>(bit_range(insn, 0, 11)); offset = static_cast<uint16_t>(bit_range(insn, 0, 11));
@@ -289,7 +288,7 @@ ArmInstruction::disassemble() {
}, },
[this](Branch& data) { [this](Branch& data) {
return fmt::format( return fmt::format(
"B{}{} {:#08X}", (data.link ? "L" : ""), condition, data.offset); "B{}{} 0x{:06X}", (data.link ? "L" : ""), condition, data.offset);
}, },
[this](Multiply& data) { [this](Multiply& data) {
if (data.acc) { if (data.acc) {
@@ -340,11 +339,11 @@ ArmInstruction::disassemble() {
expression = fmt::format(",#{:d}", *offset); expression = fmt::format(",#{:d}", *offset);
} }
} else if (const Shift* shift = std::get_if<Shift>(&data.offset)) { } else if (const Shift* shift = std::get_if<Shift>(&data.offset)) {
expression = fmt::format(",{}R{:d},{} {}{:d}", // Shifts are always immediate in single data transfer
expression = fmt::format(",{}R{:d},{} #{:d}",
(data.up ? '+' : '-'), (data.up ? '+' : '-'),
shift->rm, shift->rm,
shift->data.type, shift->data.type,
(shift->data.immediate ? '#' : 'R'),
shift->data.operand); shift->data.operand);
} }