// name off bits flags
{ "fixup_arm_ldst_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_t2_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_arm_thumb_cp", 1, 8, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_movt_hi16", 0, 16, 0 },
{ "fixup_arm_movw_lo16", 0, 16, 0 },
};
unsigned &Reg, unsigned &Imm,
SmallVectorImpl<MCFixup> &Fixups) const;
+ /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate
+ /// BL branch target.
+ uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
+ /// BLX branch target.
+ uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
+ /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
+ uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
/// getBranchTargetOpValue - Return encoding info for 24-bit immediate
/// branch target.
uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
uint32_t getAddrMode3OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
+ /// getAddrModeThumbSPOpValue - Return encoding info for 'reg +/- imm12'
+ /// operand.
+ uint32_t getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
/// getAddrModeS4OpValue - Return encoding for t_addrmode_s4 operands.
uint32_t getAddrModeS4OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getAddrModeS1OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
+ /// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
+ uint32_t getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
+
/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm8' operand.
uint32_t getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
return isAdd;
}
-/// getBranchTargetOpValue - Return encoding info for 24-bit immediate
-/// branch target.
-uint32_t ARMMCCodeEmitter::
-getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const {
+/// getBranchTargetOpValue - Helper function to get the branch target operand,
+/// which is either an immediate or requires a fixup.
+static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ unsigned FixupKind,
+ SmallVectorImpl<MCFixup> &Fixups) {
const MCOperand &MO = MI.getOperand(OpIdx);
// If the destination is an immediate, we have nothing to do.
if (MO.isImm()) return MO.getImm();
- assert (MO.isExpr() && "Unexpected branch target type!");
+ assert(MO.isExpr() && "Unexpected branch target type!");
const MCExpr *Expr = MO.getExpr();
- MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_branch);
+ MCFixupKind Kind = MCFixupKind(FixupKind);
Fixups.push_back(MCFixup::Create(0, Expr, Kind));
// All of the information is in the fixup.
return 0;
}
-/// getAdrLabelOpValue - Return encoding info for 12-bit immediate
-/// ADR label target.
+/// getThumbBLTargetOpValue - Return encoding info for immediate branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl, Fixups);
+}
+
+/// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
+/// BLX branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, Fixups);
+}
+
+/// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br, Fixups);
+}
+
+/// getBranchTargetOpValue - Return encoding info for 24-bit immediate branch
+/// target.
+uint32_t ARMMCCodeEmitter::
+getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
+ if (Subtarget.isThumb2())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_branch, Fixups);
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_branch, Fixups);
+}
+
+/// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
+/// target.
uint32_t ARMMCCodeEmitter::
getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
- const MCOperand &MO = MI.getOperand(OpIdx);
- assert (MO.isExpr() && "Unexpected adr target type!");
- const MCExpr *Expr = MO.getExpr();
- MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_adr_pcrel_12);
- Fixups.push_back(MCFixup::Create(0, Expr, Kind));
- // All of the information is in the fixup.
- return 0;
+ assert(MI.getOperand(OpIdx).isExpr() && "Unexpected adr target type!");
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_adr_pcrel_12,
+ Fixups);
}
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand.
bool isAdd = true;
// If The first operand isn't a register, we have a label reference.
const MCOperand &MO = MI.getOperand(OpIdx);
- if (!MO.isReg()) {
+ const MCOperand &MO2 = MI.getOperand(OpIdx+1);
+ if (!MO.isReg() || (MO.getReg() == ARM::PC && MO2.isExpr())) {
Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC.
Imm12 = 0;
isAdd = false ; // 'U' bit is set as part of the fixup.
- assert(MO.isExpr() && "Unexpected machine operand type!");
- const MCExpr *Expr = MO.getExpr();
+ const MCExpr *Expr = 0;
+ if (!MO.isReg())
+ Expr = MO.getExpr();
+ else
+ Expr = MO2.getExpr();
+
MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_ldst_pcrel_12);
Fixups.push_back(MCFixup::Create(0, Expr, Kind));
return (Rn << 9) | Imm8 | (isAdd << 8) | (isImm << 13);
}
+/// getAddrModeThumbSPOpValue - Encode the t_addrmode_sp operands.
+uint32_t ARMMCCodeEmitter::
+getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ // [SP, #imm]
+ // {7-0} = imm8
+ const MCOperand &MO1 = MI.getOperand(OpIdx + 1);
+#if 0 // FIXME: This crashes2003-05-14-initialize-string.c
+ assert(MI.getOperand(OpIdx).getReg() == ARM::SP &&
+ "Unexpected base register!");
+#endif
+ // The immediate is already shifted for the implicit zeroes, so no change
+ // here.
+ return MO1.getImm() & 0xff;
+}
+
/// getAddrModeSOpValue - Encode the t_addrmode_s# operands.
static unsigned getAddrModeSOpValue(const MCInst &MI, unsigned OpIdx,
unsigned Scale) {
return getAddrModeSOpValue(MI, OpIdx, 1);
}
+/// getAddrModePCOpValue - Return encoding for t_addrmode_pc operands.
+uint32_t ARMMCCodeEmitter::
+getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups);
+}
+
/// getAddrMode5OpValue - Return encoding info for 'reg +/- imm10' operand.
uint32_t ARMMCCodeEmitter::
getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
assert(MO.isExpr() && "Unexpected machine operand type!");
const MCExpr *Expr = MO.getExpr();
- MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
+ MCFixupKind Kind;
+ const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
+ if (Subtarget.isThumb2())
+ Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
+ else
+ Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
Fixups.push_back(MCFixup::Create(0, Expr, Kind));
++MCNumCPRelocations;
void ARMMCCodeEmitter::
EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups) const {
+ const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
// Pseudo instructions don't get encoded.
const TargetInstrDesc &Desc = TII.get(MI.getOpcode());
uint64_t TSFlags = Desc.TSFlags;
case ARMII::Size2Bytes: Size = 2; break;
case ARMII::Size4Bytes: Size = 4; break;
}
- EmitConstant(getBinaryCodeForInstr(MI, Fixups), Size, OS);
+ uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
+ // Thumb 32-bit wide instructions need to be have the high order halfword
+ // emitted first.
+ if (Subtarget.isThumb() && Size == 4) {
+ EmitConstant(Binary >> 16, 2, OS);
+ EmitConstant(Binary & 0xffff, 2, OS);
+ } else
+ EmitConstant(Binary, Size, OS);
++MCNumEmitted; // Keep track of the # of mi's emitted.
}