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