diff options
-rw-r--r-- | lib/Target/ARM/ARMAddressingModes.h | 10 | ||||
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.h | 5 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrInfo.td | 6 | ||||
-rw-r--r-- | lib/Target/ARM/ARMMCCodeEmitter.cpp | 22 | ||||
-rw-r--r-- | test/MC/ARM/simple-encoding.ll | 20 |
5 files changed, 58 insertions, 5 deletions
diff --git a/lib/Target/ARM/ARMAddressingModes.h b/lib/Target/ARM/ARMAddressingModes.h index db481005b3..7f68c81094 100644 --- a/lib/Target/ARM/ARMAddressingModes.h +++ b/lib/Target/ARM/ARMAddressingModes.h @@ -50,6 +50,16 @@ namespace ARM_AM { } } + static inline unsigned getShiftOpcEncoding(ShiftOpc Op) { + switch (Op) { + default: assert(0 && "Unknown shift opc!"); + case ARM_AM::asr: return 2; + case ARM_AM::lsl: return 0; + case ARM_AM::lsr: return 1; + case ARM_AM::ror: return 3; + } + } + static inline ShiftOpc getShiftOpcForNode(SDValue N) { switch (N.getOpcode()) { default: return ARM_AM::no_shift; diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 1c6aef1bd6..cbfd7529b1 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -160,6 +160,11 @@ namespace ARMII { //===------------------------------------------------------------------===// // Field shifts - such shifts are used to set field while generating // machine instructions. + // + // FIXME: This list will need adjusting/fixing as the MC code emitter + // takes shape and the ARMCodeEmitter.cpp bits go away. + ShiftTypeShift = 4, + M_BitShift = 5, ShiftImmShift = 5, ShiftShift = 7, diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 2fda464d64..2ed2bfac10 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -494,7 +494,13 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc, def rs : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm, iis, opc, "\t$dst, $a, $b", [(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]> { + bits<4> Rd; + bits<4> Rn; + bits<4> Rm; let Inst{25} = 0; + let Inst{3-0} = Rm; + let Inst{15-12} = Rd; + let Inst{19-16} = Rn; } } diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index fce1f3914d..ad87b386d3 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -13,6 +13,7 @@ #define DEBUG_TYPE "arm-emitter" #include "ARM.h" +#include "ARMAddressingModes.h" #include "ARMInstrInfo.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCExpr.h" @@ -139,8 +140,27 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, return; ++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. switch (Opcode) { - //FIXME: Any non-pseudos that need special handling, if there are any... + case ARM::ADDrs: + case ARM::ANDrs: + case ARM::BICrs: + case ARM::EORrs: + case ARM::ORRrs: + case ARM::SUBrs: { + // 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); diff --git a/test/MC/ARM/simple-encoding.ll b/test/MC/ARM/simple-encoding.ll index 2da4e74c89..4c23c7e7f2 100644 --- a/test/MC/ARM/simple-encoding.ll +++ b/test/MC/ARM/simple-encoding.ll @@ -8,8 +8,8 @@ define i32 @foo(i32 %a, i32 %b) nounwind ssp { entry: ; CHECK: foo -; CHECK: 0xf0,0x00,0xf0,0x07 -; CHECK: 0x1e,0xff,0x2f,0xe1 +; CHECK: trap @ encoding: [0xf0,0x00,0xf0,0x07] +; CHECK: bx lr @ encoding: [0x1e,0xff,0x2f,0xe1] tail call void @llvm.trap() ret i32 undef @@ -18,9 +18,21 @@ entry: define i32 @f2(i32 %a, i32 %b) nounwind readnone ssp { entry: ; CHECK: f2 -; CHECK: 0x00,0x00,0x81,0xe0 -; CHECK: 0x1e,0xff,0x2f,0xe1 +; CHECK: add r0, r1, r0 @ encoding: [0x00,0x00,0x81,0xe0] +; CHECK: bx lr @ encoding: [0x1e,0xff,0x2f,0xe1] %add = add nsw i32 %b, %a ret i32 %add } + + +define i32 @f3(i32 %a, i32 %b) nounwind readnone ssp { +entry: +; CHECK: f3 +; CHECK: add r0, r0, r1, lsl #3 @ encoding: [0x81,0x01,0x80,0xe0] +; CHECK: bx lr @ encoding: [0x1e,0xff,0x2f,0xe1] + %mul = shl i32 %b, 3 + %add = add nsw i32 %mul, %a + ret i32 %add +} + declare void @llvm.trap() nounwind |