mirror of
https://github.com/mikage-emu/mikage-dev.git
synced 2025-01-09 06:50:59 +01:00
498 lines
22 KiB
C++
498 lines
22 KiB
C++
#include "thumb.hpp"
|
|
|
|
#include <framework/exceptions.hpp>
|
|
|
|
namespace ARM {
|
|
|
|
DecodedThumbInstr DecodeThumb(ARM::ThumbInstr instr) {
|
|
if (instr.opcode_upper5 == 0b00000) {
|
|
// LSL (1) - Logical Shift Left
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = ((0b1110'0001'1011'0000ul) << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.immed_mid_5 } << 7)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b00010) {
|
|
// ASR (1) - Arithmetic Shift Right
|
|
ARM::ARMInstr arm_instr;
|
|
// arm_instr.raw = (0b1110'0001'1011'0000ul << 16)
|
|
// | (uint32_t { instr.idx_rd_low } << 12)
|
|
// | (uint32_t { instr.immed_mid_5 } << 7)
|
|
// | (0b100ul << 3)
|
|
// | instr.idx_rm;
|
|
arm_instr.raw = (0b1110'0001'1011'0000ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.immed_mid_5 } << 7)
|
|
| (0b100ul << 4)
|
|
| instr.idx_rm;
|
|
// arm_instr.raw = (0b1110'0001'1011'0000'0000'1111'1010'0000ul); // shift_imm = 31, shift = 1
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0000'00) {
|
|
// AND
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0000'0001ul << 20)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0001'01) {
|
|
// ADC
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0000'1011ul << 20)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0001110) {
|
|
// ADD (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0010'1001ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.immed_mid_5_lower3;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b00110) {
|
|
// ADD (2)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0010'1001ul << 20)
|
|
| (uint32_t { instr.idx_rd_high } << 16)
|
|
| (uint32_t { instr.idx_rd_high } << 12)
|
|
| instr.immed_low_8;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0001100) {
|
|
// ADD (3)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0000'1001ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper8 == 0b01000100) {
|
|
// ADD (4)
|
|
ARM::ARMInstr arm_instr;
|
|
auto idx_rd = uint32_t { instr.idx_rd_low } | (uint32_t { instr.idx_rd_upperbit } << 3);
|
|
auto idx_rm = uint32_t { instr.idx_rm } | (uint32_t { instr.idx_rm_upperbit } << 3);
|
|
arm_instr.raw = (0b1110'0000'1000ul << 20)
|
|
| (idx_rd << 16)
|
|
| (idx_rd << 12)
|
|
| idx_rm;
|
|
auto ret = DecodedThumbInstr { arm_instr }.SetMayReadPC();
|
|
if (idx_rd == 15) {
|
|
ret.SetMayModifyPC();
|
|
}
|
|
return ret;
|
|
// } else if (instr.opcode_upper5 == 0b10100) {
|
|
// // ADD (5)
|
|
// ARM::ARMInstr arm_instr;
|
|
// arm_instr.raw = (0b1110'0010'1000'1111ul << 16)
|
|
// | (uint32_t { instr.idx_rd_high } << 12)
|
|
// | (0b1111ul << 8)
|
|
// | instr.immed_low_8;
|
|
// return DecodedThumbInstr { arm_instr }.SetMayReadPC();
|
|
} else if (instr.opcode_upper5 == 0b10101) {
|
|
// ADD (6)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0010'1000'1101ul << 16)
|
|
| (uint32_t { instr.idx_rd_high } << 12)
|
|
| (0b1111ul << 8)
|
|
| instr.immed_low_8;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper9 == 0b1011'0000'0) {
|
|
// ADD (7)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110001010001101110111110ul << 7)
|
|
| instr.immed_low_7;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0011'10) {
|
|
// BIC
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b111000011101ul << 20)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0010'00) {
|
|
// TST
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b111000010001ul << 20)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0001'111) {
|
|
// SUB (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b111000100101ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.immed_mid_5_lower3;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b00111) {
|
|
// SUB (2)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0010'0101ul << 20)
|
|
| (uint32_t { instr.idx_rd_high } << 16)
|
|
| (uint32_t { instr.idx_rd_high } << 12)
|
|
| instr.immed_low_8;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0001'101) {
|
|
// SUB (3)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0000'0101ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper9 == 0b1011'0000'1) {
|
|
// SUB (4)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0010'0100'1101'1101'1111'0ul << 7)
|
|
| instr.immed_low_7;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0001'10) {
|
|
// SBC
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0000'1101ul << 20)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0011'00) {
|
|
// ORR
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1001ul << 20)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0000'01) {
|
|
// EOR
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0000'0011ul << 20)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b00100) {
|
|
// MOV (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0011'1011'0000ul << 16)
|
|
| (uint32_t { instr.idx_rd_high } << 12)
|
|
| instr.immed_low_8;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper8 == 0b0100'0110) {
|
|
// MOV (3)
|
|
ARM::ARMInstr arm_instr;
|
|
auto idx_rd = uint32_t { instr.idx_rd_low } | (uint32_t { instr.idx_rd_upperbit } << 3);
|
|
auto idx_rm = uint32_t { instr.idx_rm } | (uint32_t { instr.idx_rm_upperbit } << 3);
|
|
arm_instr.raw = (0b1110'0001'1010ul << 20)
|
|
| (idx_rd << 12)
|
|
| idx_rm;
|
|
auto ret = DecodedThumbInstr { arm_instr }.SetMayReadPC();
|
|
if (idx_rd == 15) {
|
|
ret.SetMayModifyPC();
|
|
}
|
|
return ret;
|
|
} else if (instr.opcode_upper10 == 0b0100'0011'11) {
|
|
// MVN
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1111'0000ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b00000) {
|
|
// LSL (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1011'0000ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.immed_mid_5 } << 7)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0000'10) {
|
|
// LSL (2)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1011'0000ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.idx_rm } << 8)
|
|
| 0b1'0000
|
|
| instr.idx_rd_low;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b00001) {
|
|
// LSR (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1011'0000ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.immed_mid_5 } << 7)
|
|
| 0b10'0000
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0000'11) {
|
|
// LSR (2)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1011'0000ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.idx_rm } << 8)
|
|
| 0b11'0000
|
|
| instr.idx_rd_low;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0010'01) {
|
|
// NEG
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0010'0111ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12);
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0011'01) {
|
|
// MUL
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0000'0001ul << 20)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 8)
|
|
| (0b1001ul << 4)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b1011'1010'00) {
|
|
// REV
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0110'1011'1111ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (0b1111'0011ul << 4)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0001'11) {
|
|
// ROR
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1011'0000ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.idx_rm } << 8)
|
|
| (0b0111ul << 4)
|
|
| instr.idx_rd_low;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b1011'0010'01) {
|
|
// SXTB
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0110'1010'1111ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (0b0111ul << 4)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b1011'0010'00) {
|
|
// SXTH
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0110'1011'1111ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (0b0111ul << 4)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b1011'0010'10) {
|
|
// UXTH
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0110'1111'1111ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (0b0111ul << 4)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b1011'0010'11) {
|
|
// UXTB
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0110'1110'1111ul << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (0b0111ul << 4)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b11001) {
|
|
// LDMIA
|
|
ARM::ARMInstr arm_instr;
|
|
uint32_t has_rd = (instr.register_list >> instr.idx_rd_high) & 1;
|
|
arm_instr.raw = (0b1110'1000'1001ul << 20)
|
|
| (uint32_t { !has_rd } << 21)
|
|
| (uint32_t { instr.idx_rd_high } << 16)
|
|
| instr.register_list;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b01101) {
|
|
// LDR (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0101'1001ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.immed_mid_5 } << 2);
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0101'100) {
|
|
// LDR (2)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0111'1001ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b10011) {
|
|
// LDR (4)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0101'1001'1101ul << 16)
|
|
| (uint32_t { instr.idx_rd_high } << 12)
|
|
| (uint32_t { instr.immed_low_8 } << 2);
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b01111) {
|
|
// LDRB (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0101'1101ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.immed_mid_5;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0101110) {
|
|
// LDRB (2)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0111'1101ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0101011) {
|
|
// LDRSB
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1001ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (0b1101ul << 4)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0101111) {
|
|
// LDRSH
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1001ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (0b1111ul << 4)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b10001) {
|
|
// LDRH (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1101ul<< 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.immed_mid_5_upper2 } << 8)
|
|
| (0b1011ul << 4)
|
|
| (uint32_t { instr.immed_mid_5_lower3 } << 1);
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0101'101) {
|
|
// LDRH (2)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1001ul<< 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (0b1011ul << 4)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b00101) {
|
|
// CMP (1) - Compare
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0011'0101ul << 20)
|
|
| (uint32_t { instr.idx_rd_high } << 16)
|
|
| (instr.immed_low_8);
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper10 == 0b0100'0010'10) {
|
|
// CMP (2) - Compare
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b111000010101ul << 20)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper8 == 0b0100'0101) {
|
|
// CMP (3) - Compare
|
|
ARM::ARMInstr arm_instr;
|
|
if (!instr.idx_rd_upperbit && !instr.idx_rm_upperbit) {
|
|
throw Mikage::Exceptions::Invalid("Unpredictable configuration");
|
|
}
|
|
if (instr.idx_rm_upperbit && instr.idx_rm == 7) {
|
|
throw Mikage::Exceptions::Invalid("Unpredictable configuration");
|
|
}
|
|
if (instr.idx_rd_upperbit && instr.idx_rd_low == 7) {
|
|
throw Mikage::Exceptions::NotImplemented("Cannot use PC for this instruction, yet");
|
|
}
|
|
arm_instr.raw = (0b111000010101ul << 20)
|
|
| (uint32_t { instr.idx_rd_upperbit } << 19)
|
|
| (uint32_t { instr.idx_rd_low } << 16)
|
|
| (uint32_t { instr.idx_rm_upperbit } << 3)
|
|
| instr.idx_rm;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b11000) {
|
|
// STMIA
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'1000'1010ul << 20)
|
|
| (uint32_t { instr.idx_rd_high } << 16)
|
|
| instr.register_list;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b01100) {
|
|
// STR (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0101'1000ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.immed_mid_5 } << 2);
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0101000) {
|
|
// STR (2)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0111'1000ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b10010) {
|
|
// STR (3)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0101'1000'1101ul << 16)
|
|
| (uint32_t { instr.idx_rd_high } << 12)
|
|
| (uint32_t { instr.immed_low_8 } << 2);
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b01110) {
|
|
// STRB (1)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0101'1100ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.immed_mid_5;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0101'010) {
|
|
// STRB (2)
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0111'1100ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper5 == 0b10000) {
|
|
// STRH (1) - Store Register Halfword
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1100ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (uint32_t { instr.immed_mid_5_upper2 } << 8)
|
|
| (0b1011 << 4)
|
|
| (uint32_t { instr.immed_mid_5_lower3 } << 1);
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b0101001) {
|
|
// STRH (2) - Store Register Halfword
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'0001'1000ul << 20)
|
|
| (uint32_t { instr.idx_rm } << 16)
|
|
| (uint32_t { instr.idx_rd_low } << 12)
|
|
| (0b1011 << 4)
|
|
| instr.idx_rn;
|
|
return { arm_instr };
|
|
} else if (instr.opcode_upper7 == 0b1011'010) {
|
|
// PUSH - Push Multiple Registers
|
|
ARM::ARMInstr arm_instr;
|
|
arm_instr.raw = (0b1110'1001'0010'1101ul << 16)
|
|
| ((uint32_t { instr.raw } & 0x100) << 6) // bit8 denotes whether to push LR
|
|
| instr.register_list;
|
|
return { arm_instr };
|
|
} else {
|
|
// Instruction has no ARM equivalent, let the caller handle it manually
|
|
return { };
|
|
}
|
|
}
|
|
|
|
} // namespace ARM
|