diff options
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 10 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCCodeEmitter.cpp | 55 | ||||
-rw-r--r-- | test/MC/ARM/simple-encoding.ll | 11 |
3 files changed, 54 insertions, 22 deletions
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 2ed2bfac10..3d1ddda672 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -472,10 +472,14 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc, // The register-immediate version is re-materializable. This is useful // in particular for taking the address of a local. let isReMaterializable = 1 in { - def ri : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm, - iii, opc, "\t$dst, $a, $b", - [(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]> { + def ri : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm, + iii, opc, "\t$Rd, $Rn, $imm", + [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]> { + bits<4> Rd; + bits<4> Rn; let Inst{25} = 1; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; } } def rr : AsI1<opcod, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), DPFrm, diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index ad87b386d3..27ed551113 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -39,6 +39,8 @@ public: ~ARMMCCodeEmitter() {} + unsigned getMachineSoImmOpValue(unsigned SoImm) const; + // getBinaryCodeForInstr - TableGen'erated function for getting the // binary encoding for an instruction. unsigned getBinaryCodeForInstr(const MCInst &MI) const; @@ -61,12 +63,6 @@ public: return rtn; } - static unsigned GetARMRegNum(const MCOperand &MO) { - // FIXME: getARMRegisterNumbering() is sufficient? - assert(0 && "ARMMCCodeEmitter::GetARMRegNum() not yet implemented."); - return 0; - } - void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const { OS << (char)C; ++CurByte; @@ -93,6 +89,18 @@ public: } // end anonymous namespace +unsigned ARMMCCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) const { + int SoImmVal = ARM_AM::getSOImmVal(SoImm); + assert(SoImmVal != -1 && "Not a valid so_imm value!"); + + // Encode rotate_imm. + unsigned Binary = (ARM_AM::getSOImmValRot((unsigned)SoImmVal) >> 1) + << ARMII::SoRotImmShift; + + // Encode immed_8. + Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal); + return Binary; +} MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &, TargetMachine &TM, @@ -112,12 +120,10 @@ EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind, unsigned ARMMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO) const { if (MO.isReg()) - // FIXME: Should shifted register stuff be handled as part of this? Maybe. return getARMRegisterNumbering(MO.getReg()); - else if (MO.isImm()) - // FIXME: This is insufficient. Shifted immediates and all that... (blech). + else if (MO.isImm()) { return static_cast<unsigned>(MO.getImm()); - else { + } else { #ifndef NDEBUG errs() << MO; #endif @@ -142,31 +148,42 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, ++MCNumEmitted; // Keep track of the # of mi's emitted // FIXME: TableGen doesn't deal well with operands that expand to multiple // machine instruction operands, so for now we'll fix those up here. + // Similarly, operands that are encoded as other than their literal + // values in the MI. + unsigned Value = getBinaryCodeForInstr(MI); switch (Opcode) { + default: break; + case ARM::ADDri: + case ARM::ANDri: + case ARM::BICri: + case ARM::EORri: + case ARM::ORRri: + case ARM::SUBri: + // The 's' bit. + if (MI.getOperand(5).getReg() == ARM::CPSR) + Value |= 1 << ARMII::S_BitShift; + // The shifted immediate value. + Value |= getMachineSoImmOpValue((unsigned)MI.getOperand(2).getImm()); + break; case ARM::ADDrs: case ARM::ANDrs: case ARM::BICrs: case ARM::EORrs: case ARM::ORRrs: case ARM::SUBrs: { + // The 's' bit. + if (MI.getOperand(7).getReg() == ARM::CPSR) + Value |= 1 << ARMII::S_BitShift; // The so_reg operand needs the shift ammount encoded. - unsigned Value = getBinaryCodeForInstr(MI); unsigned ShVal = MI.getOperand(4).getImm(); unsigned ShType = ARM_AM::getShiftOpcEncoding(ARM_AM::getSORegShOp(ShVal)); unsigned ShAmt = ARM_AM::getSORegOffset(ShVal); - Value |= ShType << ARMII::ShiftTypeShift; Value |= ShAmt << ARMII::ShiftShift; - - EmitConstant(Value, 4, CurByte, OS); - break; - } - default: { - unsigned Value = getBinaryCodeForInstr(MI); - EmitConstant(Value, 4, CurByte, OS); break; } } + EmitConstant(Value, 4, CurByte, OS); } // FIXME: These #defines shouldn't be necessary. Instead, tblgen should diff --git a/test/MC/ARM/simple-encoding.ll b/test/MC/ARM/simple-encoding.ll index 4c23c7e7f2..f10e934a1e 100644 --- a/test/MC/ARM/simple-encoding.ll +++ b/test/MC/ARM/simple-encoding.ll @@ -35,4 +35,15 @@ entry: ret i32 %add } +define i32 @f4(i32 %a, i32 %b) nounwind readnone ssp { +entry: +; CHECK: f4 +; CHECK: add r0, r0, #254, 28 @ encoding: [0xfe,0x0e,0x80,0xe2] +; CHECK: @ 4064 +; CHECK: bx lr @ encoding: [0x1e,0xff,0x2f,0xe1] + %add = add nsw i32 %a, 4064 + ret i32 %add +} + + declare void @llvm.trap() nounwind |