diff options
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMCodeEmitter.cpp | 233 | 
1 files changed, 175 insertions, 58 deletions
diff --git a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp index 6066671ff37..74dab5f1484 100644 --- a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp @@ -54,9 +54,9 @@ namespace {      }      void emitInstruction(const MachineInstr &MI); -    unsigned getBinaryCodeForInstr(const MachineInstr &MI);      int getMachineOpValue(const MachineInstr &MI, unsigned OpIndex);      unsigned getBaseOpcodeFor(const TargetInstrDescriptor *TID); +    unsigned getBinaryCodeForInstr(const MachineInstr &MI);      void emitGlobalAddressForCall(GlobalValue *GV, bool DoesntNeedStub);      void emitExternalSymbolAddress(const char *ES, unsigned Reloc); @@ -64,6 +64,8 @@ namespace {                                int Disp = 0, unsigned PCAdj = 0 );      void emitJumpTableAddress(unsigned JTI, unsigned Reloc,                                unsigned PCAdj = 0); +    void emitGlobalConstant(const Constant *CV); +    void emitMachineBasicBlock(MachineBasicBlock *BB);    private:      int getShiftOp(const MachineOperand &MO); @@ -100,10 +102,13 @@ bool Emitter::runOnMachineFunction(MachineFunction &MF) {    return false;  } +/// getBaseOpcodeFor - Return the opcode value  unsigned Emitter::getBaseOpcodeFor(const TargetInstrDescriptor *TID) {    return (TID->TSFlags & ARMII::OpcodeMask) >> ARMII::OpcodeShift;  } +/// getShiftOp - Verify which is the shift opcode (bit[6:5]) of the +/// machine operand.  int Emitter::getShiftOp(const MachineOperand &MO) {    unsigned ShiftOp = 0x0;    switch(ARM_AM::getAM2ShiftOpc(MO.getImmedValue())) { @@ -133,20 +138,18 @@ int Emitter::getMachineOpValue(const MachineInstr &MI, unsigned OpIndex) {      rv = ARMRegisterInfo::getRegisterNumbering(MO.getReg());    } else if (MO.isImmediate()) {      rv = MO.getImmedValue(); -  } else if (MO.isGlobalAddress() || MO.isExternalSymbol() || -             MO.isConstantPoolIndex() || MO.isJumpTableIndex()) { - -    if (MO.isGlobalAddress()) { -      emitGlobalAddressForCall(MO.getGlobal(), true); -    } else if (MO.isExternalSymbol()) { -      emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_relative); -    } else if (MO.isConstantPoolIndex()) { -      emitConstPoolAddress(MO.getConstantPoolIndex(), ARM::reloc_arm_relative); -    } else if (MO.isJumpTableIndex()) { -      emitJumpTableAddress(MO.getJumpTableIndex(), ARM::reloc_arm_relative); -    } - +  } else if (MO.isGlobalAddress()) { +    emitGlobalAddressForCall(MO.getGlobal(), false); +  } else if (MO.isExternalSymbol()) { +    emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_relative); +  } else if (MO.isConstantPoolIndex()) { +    emitConstPoolAddress(MO.getConstantPoolIndex(), ARM::reloc_arm_relative); +  } else if (MO.isJumpTableIndex()) { +    emitJumpTableAddress(MO.getJumpTableIndex(), ARM::reloc_arm_relative); +  } else if (MO.isMachineBasicBlock()) { +    emitMachineBasicBlock(MO.getMachineBasicBlock());    } +    return rv;  } @@ -186,7 +189,11 @@ void Emitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc,                                                      Reloc, JTI, PCAdj));  } - +/// emitMachineBasicBlock - Emit the specified address basic block. +void Emitter::emitMachineBasicBlock(MachineBasicBlock *BB) { +  MCE.addRelocation(MachineRelocation::getBB(MCE.getCurrentPCOffset(), +                                      ARM::reloc_arm_branch, BB)); +}  void Emitter::emitInstruction(const MachineInstr &MI) {    NumEmitted++;  // Keep track of the # of mi's emitted @@ -196,6 +203,7 @@ void Emitter::emitInstruction(const MachineInstr &MI) {  unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {    const TargetInstrDescriptor *Desc = MI.getInstrDescriptor();    const unsigned opcode = MI.getOpcode(); +  // initial instruction mask    unsigned Value = 0xE0000000;    unsigned op; @@ -204,10 +212,11 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {      switch(Desc->TSFlags & ARMII::FormMask) {      default: {        assert(0 && "Unknown instruction subtype!"); +      // treat special instruction CLZ        if(opcode == ARM::CLZ) {          // set first operand          op = getMachineOpValue(MI,0); -        Value |= op << 12; +        Value |= op << ARMII::RegRdShift;          // set second operand          op = getMachineOpValue(MI,1); @@ -215,9 +224,51 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {        }        break;      } +    case ARMII::MulSMLAW: +    case ARMII::MulSMULW: +      // set bit W(21) +      Value |= 1 << 21; +    case ARMII::MulSMLA: +    case ARMII::MulSMUL: { +      // set bit W(21) +      Value |= 1 << 24; + +      // set opcode (bit[7:4]). For more information, see ARM-ARM page A3-31 +      // SMLA<x><y>  - 1yx0 +      // SMLAW<y>    - 1y00 +      // SMULW<y>    - 1y10 +      // SMUL<x><y>  - 1yx0 +      unsigned char BaseOpcode = getBaseOpcodeFor(Desc); +      Value |= BaseOpcode << 4; + +      unsigned Format = (Desc->TSFlags & ARMII::FormMask); +      if (Format == ARMII::MulSMUL) +        Value |= 1 << 22; + +      // set first operand +      op = getMachineOpValue(MI,0); +      Value |= op << ARMII::RegRnShift; + +      // set second operand +      op = getMachineOpValue(MI,1); +      Value |= op; + +      // set third operand +      op = getMachineOpValue(MI,2); +      Value |= op << ARMII::RegRsShift; + +      // instructions SMLA and SMLAW have a fourth operand +      if (Format != ARMII::MulSMULW && Format != ARMII::MulSMUL) { +        op = getMachineOpValue(MI,3); +        Value |= op << ARMII::RegRdShift; +      } + +      break; +    }      case ARMII::MulFrm: { +      // bit[7:4] is always 9        Value |= 9 << 4; - +      // set opcode (bit[23:20])        unsigned char BaseOpcode = getBaseOpcodeFor(Desc);        Value |= BaseOpcode << 20; @@ -226,40 +277,53 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {        // set first operand        op = getMachineOpValue(MI,0); -      Value |= op << (isMUL || isMLA ? 16 : 12); +      Value |= op << (isMUL || isMLA ? ARMII::RegRnShift : ARMII::RegRdShift);        // set second operand        op = getMachineOpValue(MI,1); -      Value |= op << (isMUL || isMLA ? 0 : 16); +      Value |= op << (isMUL || isMLA ? 0 : ARMII::RegRnShift);        // set third operand        op = getMachineOpValue(MI,2); -      Value |= op << (isMUL || isMLA ? 8 : 0); +      Value |= op << (isMUL || isMLA ? ARMII::RegRsShift : 0); +      // multiply instructions (except MUL), have a fourth operand        if (!isMUL) {          op = getMachineOpValue(MI,3); -        Value |= op << (isMLA ? 12 : 8); +        Value |= op << (isMLA ? ARMII::RegRdShift : ARMII::RegRsShift);        }        break;      }      case ARMII::Branch: { +      // set opcode (bit[27:24])        unsigned BaseOpcode = getBaseOpcodeFor(Desc);        Value |= BaseOpcode << 24; +      // set signed_immed_24 field        op = getMachineOpValue(MI,0);        Value |= op; +      // if it is a conditional branch, set cond field +      if (opcode == ARM::Bcc) { +        op = getMachineOpValue(MI,1); +        Value &= 0x0FFFFFFF; // clear conditional field +        Value |= op << 28;   // set conditional field +      } +        break;      }      case ARMII::BranchMisc: { +      // set opcode (bit[7:4])        unsigned char BaseOpcode = getBaseOpcodeFor(Desc);        Value |= BaseOpcode << 4; +      // set bit[27:24] to 1, set bit[23:20] to 2 and set bit[19:8] to 0xFFF        Value |= 0x12fff << 8;        if (opcode == ARM::BX_RET) -        op = 0xe; +        op = 0xe; // the return register is LR        else  +        // otherwise, set the return register          op = getMachineOpValue(MI,0);        Value |= op; @@ -272,12 +336,15 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {      break;    }    case ARMII::AddrMode1: { +    // set opcode (bit[24:21]) of data-processing instructions      unsigned char BaseOpcode = getBaseOpcodeFor(Desc);      Value |= BaseOpcode << 21; +    // treat 3 special instructions: MOVsra_flag, MOVsrl_flag and +    // MOVrx.      unsigned Format = (Desc->TSFlags & ARMII::FormMask);      if (Format == ARMII::DPRdMisc) { -      Value |= getMachineOpValue(MI,0) << 12; +      Value |= getMachineOpValue(MI,0) << ARMII::RegRdShift;        Value |= getMachineOpValue(MI,1);        switch(opcode) {        case ARM::MOVsra_flag: { @@ -298,20 +365,26 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {        break;      } -    bool IsDataProcessing3 = false; - -    if (Format == ARMII::DPRImS || Format == ARMII::DPRRegS || -        Format == ARMII::DPRSoRegS) { -      Value |= 1 << 20; -      IsDataProcessing3 = true; -    } - +    // Data processing operand instructions has 3 possible encodings (for more +    // information, see ARM-ARM page A3-10): +    // 1. <instr> <Rd>,<shifter_operand> +    // 2. <instr> <Rn>,<shifter_operand> +    // 3. <instr> <Rd>,<Rn>,<shifter_operand>      bool IsDataProcessing1 = Format == ARMII::DPRdIm    ||                               Format == ARMII::DPRdReg   ||                               Format == ARMII::DPRdSoReg;      bool IsDataProcessing2 = Format == ARMII::DPRnIm    ||                               Format == ARMII::DPRnReg   ||                               Format == ARMII::DPRnSoReg; +    bool IsDataProcessing3 = false; + +    // set bit S(20) +    if (Format == ARMII::DPRImS || Format == ARMII::DPRRegS || +        Format == ARMII::DPRSoRegS || IsDataProcessing2) { +      Value |= 1 << ARMII::S_BitShift; +      IsDataProcessing3 = !IsDataProcessing2; +    } +      IsDataProcessing3 = Format == ARMII::DPRIm     ||                          Format == ARMII::DPRReg    ||                          Format == ARMII::DPRSoReg  || @@ -320,22 +393,24 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {      // set first operand      op = getMachineOpValue(MI,0);      if (IsDataProcessing1 || IsDataProcessing3) { -      Value |= op << 12; +      Value |= op << ARMII::RegRdShift;      } else if (IsDataProcessing2) { -      Value |= op << 16; +      Value |= op << ARMII::RegRnShift;      } +    // set second operand of data processing #3 instructions      if (IsDataProcessing3) {        op = getMachineOpValue(MI,1); -      Value |= op << 16; +      Value |= op << ARMII::RegRnShift;      }      unsigned OperandIndex = IsDataProcessing3 ? 2 : 1; -    // set shift operand      switch (Format) {      case ARMII::DPRdIm: case ARMII::DPRnIm:      case ARMII::DPRIm:  case ARMII::DPRImS: { -      Value |= 1 << 25; +      // set bit I(25) to identify this is the immediate form of <shifter_op> +      Value |= 1 << ARMII::I_BitShift; +      // set immed_8 field        const MachineOperand &MO = MI.getOperand(OperandIndex);        op = ARM_AM::getSOImmVal(MO.getImmedValue());        Value |= op; @@ -344,6 +419,7 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {      }      case ARMII::DPRdReg: case ARMII::DPRnReg:      case ARMII::DPRReg:  case ARMII::DPRRegS: { +      // set last operand (register Rm)        op = getMachineOpValue(MI,OperandIndex);        Value |= op; @@ -351,12 +427,20 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {      }      case ARMII::DPRdSoReg: case ARMII::DPRnSoReg:      case ARMII::DPRSoReg:  case ARMII::DPRSoRegS: { +      // set last operand (register Rm)        op = getMachineOpValue(MI,OperandIndex);        Value |= op;        const MachineOperand &MO1 = MI.getOperand(OperandIndex + 1);        const MachineOperand &MO2 = MI.getOperand(OperandIndex + 2); +      // identify it the instr is in immed or register shifts encoding        bool IsShiftByRegister = MO1.getReg() > 0; +      // set shift operand (bit[6:4]). +      // ASR - 101 if it is in register shifts encoding; 100, otherwise. +      // LSL - 001 if it is in register shifts encoding; 000, otherwise. +      // LSR - 011 if it is in register shifts encoding; 010, otherwise. +      // ROR - 111 if it is in register shifts encoding; 110, otherwise. +      // RRX - 110 and bit[11:7] clear.        switch(ARM_AM::getSORegShOp(MO2.getImmedValue())) {          default: assert(0 && "Unknown shift opc!");          case ARM_AM::asr: { @@ -390,13 +474,16 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {            break;          }        } +      // set the field related to shift operations (except rrx).        if(ARM_AM::getSORegShOp(MO2.getImmedValue()) != ARM_AM::rrx)          if(IsShiftByRegister) { +          // set the value of bit[11:8] (register Rs).            assert(MRegisterInfo::isPhysicalRegister(MO1.getReg()));            op = ARMRegisterInfo::getRegisterNumbering(MO1.getReg());            assert(ARM_AM::getSORegOffset(MO2.getImm()) == 0); -          Value |= op << 8; +          Value |= op << ARMII::RegRsShift;          } else { +          // set the value of bit [11:7] (shift_immed field).            op = ARM_AM::getSORegOffset(MO2.getImm());            Value |= op << 7;          } @@ -409,83 +496,107 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {      break;    }    case ARMII::AddrMode2: { +    // bit 26 is always 1      Value |= 1 << 26;      unsigned Index = (Desc->TSFlags & ARMII::IndexModeMask); +    // if the instruction uses offset addressing or pre-indexed addressing, +    // set bit P(24) to 1      if (Index == ARMII::IndexModePre || Index == 0) -      Value |= 1 << 24; +      Value |= 1 << ARMII::IndexShift; +    // if the instruction uses post-indexed addressing, set bit W(21) to 1      if (Index == ARMII::IndexModePre)        Value |= 1 << 21;      unsigned Format = (Desc->TSFlags & ARMII::FormMask); +    // If it is a load instruction (except LDRD), set bit L(20) to 1      if (Format == ARMII::LdFrm) -      Value |= 1 << 20; +      Value |= 1 << ARMII::L_BitShift; +    // set bit B(22)      unsigned BitByte = getBaseOpcodeFor(Desc);      Value |= BitByte << 22;      // set first operand      op = getMachineOpValue(MI,0); -    Value |= op << 12; +    Value |= op << ARMII::RegRdShift; -    // addressing mode +    // set second operand      op = getMachineOpValue(MI,1); -    Value |= op << 16; +    Value |= op << ARMII::RegRnShift;      const MachineOperand &MO2 = MI.getOperand(2);      const MachineOperand &MO3 = MI.getOperand(3); -    Value |= (ARM_AM::getAM2Op(MO3.getImm()) == ARM_AM::add ? 1 : 0) << 23; +    // set bit U(23) according to signal of immed value (positive or negative) +    Value |= (ARM_AM::getAM2Op(MO3.getImm()) == ARM_AM::add ? 1 : 0) << +                                                ARMII::U_BitShift;      if (!MO2.getReg()) { // is immediate        if (ARM_AM::getAM2Offset(MO3.getImm())) +        // set the value of offset_12 field          Value |= ARM_AM::getAM2Offset(MO3.getImm());        break;      } -    Value |= 1 << 25; +    // set bit I(25), because this is not in immediate enconding. +    Value |= 1 << ARMII::I_BitShift;      assert(MRegisterInfo::isPhysicalRegister(MO2.getReg())); +    // set bit[3:0] to the corresponding Rm register      Value |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg()); +    // if this instr is in scaled register offset/index instruction, set +    // shift_immed(bit[11:7]) and shift(bit[6:5]) fields.      if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) {        unsigned ShiftOp = getShiftOp(MO3); -      Value |= ShiftOp << 5; -      Value |= ShImm << 7; +      Value |= ShiftOp << 5; // shift +      Value |= ShImm << 7;   // shift_immed      }      break;    }    case ARMII::AddrMode3: { +      unsigned Index = (Desc->TSFlags & ARMII::IndexModeMask); +    // if the instruction uses offset addressing or pre-indexed addressing, +    // set bit P(24) to 1      if (Index == ARMII::IndexModePre || Index == 0) -      Value |= 1 << 24; +      Value |= 1 << ARMII::IndexShift;      unsigned Format = (Desc->TSFlags & ARMII::FormMask); -    if (Format == ARMII::LdFrm) -      Value |= 1 << 20; +    // If it is a load instruction (except LDRD), set bit L(20) to 1 +    if (Format == ARMII::LdFrm && opcode != ARM::LDRD) +      Value |= 1 << ARMII::L_BitShift; +    // bit[7:4] is the opcode of this instruction class (bits S and H).      unsigned char BaseOpcode = getBaseOpcodeFor(Desc);      Value |= BaseOpcode << 4;      // set first operand      op = getMachineOpValue(MI,0); -    Value |= op << 12; +    Value |= op << ARMII::RegRdShift; -    // addressing mode +    // set second operand      op = getMachineOpValue(MI,1); -    Value |= op << 16; +    Value |= op << ARMII::RegRnShift;      const MachineOperand &MO2 = MI.getOperand(2);      const MachineOperand &MO3 = MI.getOperand(3); -    Value |= (ARM_AM::getAM2Op(MO3.getImm()) == ARM_AM::add ? 1 : 0) << 23; +    // set bit U(23) according to signal of immed value (positive or negative) +    Value |= (ARM_AM::getAM2Op(MO3.getImm()) == ARM_AM::add ? 1 : 0) << +                                                ARMII::U_BitShift; +    // if this instr is in register offset/index encoding, set bit[3:0] +    // to the corresponding Rm register.      if (MO2.getReg()) {        Value |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg());        break;      } +    // if this instr is in immediate offset/index encoding, set bit 22 to 1      if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm())) {        Value |= 1 << 22; +      // set operands        Value |= (ImmOffs >> 4) << 8; // immedH        Value |= (ImmOffs & ~0xF); // immedL      } @@ -493,30 +604,36 @@ unsigned Emitter::getBinaryCodeForInstr(const MachineInstr &MI) {      break;    }    case ARMII::AddrMode4: { +    // bit 27 is always 1      Value |= 1 << 27;      unsigned Format = (Desc->TSFlags & ARMII::FormMask); +    // if it is a load instr, set bit L(20) to 1      if (Format == ARMII::LdFrm) -      Value |= 1 << 20; +      Value |= 1 << ARMII::L_BitShift;      unsigned OpIndex = 0;      // set first operand      op = getMachineOpValue(MI,OpIndex); -    Value |= op << 16; +    Value |= op << ARMII::RegRnShift; -    // set addressing mode +    // set addressing mode by modifying bits U(23) and P(24) +    // IA - Increment after  - bit U = 1 and bit P = 0 +    // IB - Increment before - bit U = 1 and bit P = 1 +    // DA - Decrement after  - bit U = 0 and bit P = 0 +    // DB - Decrement before - bit U = 0 and bit P = 1      const MachineOperand &MO = MI.getOperand(OpIndex + 1);      ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO.getImm());      switch(Mode) {      default: assert(0 && "Unknown addressing sub-mode!");      case ARM_AM::ia: Value |= 0x1 << 23; break; -    case ARM_AM::ib: Value |= 0x2 << 23; break; +    case ARM_AM::ib: Value |= 0x3 << 23; break;      case ARM_AM::da: break;      case ARM_AM::db: Value |= 0x1 << 24; break;      } -    // set flag W +    // set bit W(21)      if (ARM_AM::getAM4WBFlag(MO.getImm()))        Value |= 0x1 << 21;  | 

