Example #1
0
/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize
/// a destreg = basereg + immediate in Thumb code. Materialize the immediate
/// in a register using mov / mvn sequences or load the immediate from a
/// constpool entry.
static void emitThumbRegPlusImmInReg(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
    const DebugLoc &dl, unsigned DestReg, unsigned BaseReg, int NumBytes,
    bool CanChangeCC, const TargetInstrInfo &TII,
    const ARMBaseRegisterInfo &MRI, unsigned MIFlags = MachineInstr::NoFlags) {
  MachineFunction &MF = *MBB.getParent();
  const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>();
  bool isHigh = !isARMLowRegister(DestReg) ||
                (BaseReg != 0 && !isARMLowRegister(BaseReg));
  bool isSub = false;
  // Subtract doesn't have high register version. Load the negative value
  // if either base or dest register is a high register. Also, if do not
  // issue sub as part of the sequence if condition register is to be
  // preserved.
  if (NumBytes < 0 && !isHigh && CanChangeCC) {
    isSub = true;
    NumBytes = -NumBytes;
  }
  unsigned LdReg = DestReg;
  if (DestReg == ARM::SP)
    assert(BaseReg == ARM::SP && "Unexpected!");
  if (!isARMLowRegister(DestReg) && !MRI.isVirtualRegister(DestReg))
    LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);

  if (NumBytes <= 255 && NumBytes >= 0 && CanChangeCC) {
    BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)
        .add(t1CondCodeOp())
        .addImm(NumBytes)
        .setMIFlags(MIFlags);
  } else if (NumBytes < 0 && NumBytes >= -255 && CanChangeCC) {
    BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)
        .add(t1CondCodeOp())
        .addImm(NumBytes)
        .setMIFlags(MIFlags);
    BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)
        .add(t1CondCodeOp())
        .addReg(LdReg, RegState::Kill)
        .setMIFlags(MIFlags);
  } else if (ST.genExecuteOnly()) {
    BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm), LdReg)
      .addImm(NumBytes).setMIFlags(MIFlags);
  } else
    MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, ARMCC::AL, 0,
                          MIFlags);

  // Emit add / sub.
  int Opc = (isSub) ? ARM::tSUBrr
                    : ((isHigh || !CanChangeCC) ? ARM::tADDhirr : ARM::tADDrr);
  MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
  if (Opc != ARM::tADDhirr)
    MIB = MIB.add(t1CondCodeOp());
  if (DestReg == ARM::SP || isSub)
    MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill);
  else
    MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill);
  MIB.add(predOps(ARMCC::AL));
}
/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize
/// a destreg = basereg + immediate in Thumb code. Materialize the immediate
/// in a register using mov / mvn sequences or load the immediate from a
/// constpool entry.
static
void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB,
                              MachineBasicBlock::iterator &MBBI,
                              unsigned DestReg, unsigned BaseReg,
                              int NumBytes, bool CanChangeCC,
                              const TargetInstrInfo &TII,
                              const ARMBaseRegisterInfo& MRI,
                              DebugLoc dl) {
    MachineFunction &MF = *MBB.getParent();
    bool isHigh = !isARMLowRegister(DestReg) ||
                  (BaseReg != 0 && !isARMLowRegister(BaseReg));
    bool isSub = false;
    // Subtract doesn't have high register version. Load the negative value
    // if either base or dest register is a high register. Also, if do not
    // issue sub as part of the sequence if condition register is to be
    // preserved.
    if (NumBytes < 0 && !isHigh && CanChangeCC) {
      isSub = true;
      NumBytes = -NumBytes;
    }
    unsigned LdReg = DestReg;
    if (DestReg == ARM::SP) {
      assert(BaseReg == ARM::SP && "Unexpected!");
      LdReg = MF.getRegInfo().createVirtualRegister(ARM::tGPRRegisterClass);
    }

    if (NumBytes <= 255 && NumBytes >= 0)
      AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
        .addImm(NumBytes);
    else if (NumBytes < 0 && NumBytes >= -255) {
      AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
        .addImm(NumBytes);
      AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg))
        .addReg(LdReg, RegState::Kill);
    } else
      MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes);

    // Emit add / sub.
    int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr);
    MachineInstrBuilder MIB =
      BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
    if (Opc != ARM::tADDhirr)
      MIB = AddDefaultT1CC(MIB);
    if (DestReg == ARM::SP || isSub)
      MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill);
    else
      MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill);
    AddDefaultPred(MIB);
}