shifts are always immediate in single data transfer
Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user