From 9d63d90de5e57ad96f467b270544443a9284eb2b Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Wed, 1 Dec 2010 19:18:46 +0000 Subject: [PATCH] Add correct encodings for STRD and LDRD, including fixup support. Additionally, update these to unified syntax. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120589 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/ELFObjectWriter.cpp | 4 +- lib/Target/ARM/ARMAsmBackend.cpp | 4 +- lib/Target/ARM/ARMCodeEmitter.cpp | 2 + lib/Target/ARM/ARMFixupKinds.h | 8 ++-- lib/Target/ARM/ARMInstrFormats.td | 9 ++++ lib/Target/ARM/ARMInstrThumb2.td | 36 +++++++-------- lib/Target/ARM/ARMMCCodeEmitter.cpp | 44 ++++++++++++++++++- .../ARM/Disassembler/ARMDisassembler.cpp | 3 -- test/CodeGen/Thumb2/thumb2-ldrd.ll | 2 +- test/MC/Disassembler/ARM/thumb-tests.txt | 2 +- 10 files changed, 78 insertions(+), 36 deletions(-) diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 641354c43cf..1bad8ebaf8a 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -409,7 +409,7 @@ namespace { case FK_PCRel_2: case FK_PCRel_4: case ARM::fixup_arm_pcrel_12: - case ARM::fixup_arm_vfp_pcrel_10: + case ARM::fixup_arm_pcrel_10: case ARM::fixup_arm_branch: return true; } @@ -1457,7 +1457,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target, switch ((unsigned)Fixup.getKind()) { default: llvm_unreachable("invalid fixup kind!"); case ARM::fixup_arm_pcrel_12: - case ARM::fixup_arm_vfp_pcrel_10: + case ARM::fixup_arm_pcrel_10: assert(0 && "Unimplemented"); break; case ARM::fixup_arm_branch: return ELF::R_ARM_CALL; break; diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp index ac0f160a9c3..0672899d7b3 100644 --- a/lib/Target/ARM/ARMAsmBackend.cpp +++ b/lib/Target/ARM/ARMAsmBackend.cpp @@ -64,7 +64,7 @@ protected: // These values don't encode the low two bits since they're always zero. // Offset by 8 just as above. return (Value - 8) >> 2; - case ARM::fixup_arm_vfp_pcrel_10: { + case ARM::fixup_arm_pcrel_10: { // Offset by 8 just as above. Value = Value - 8; bool isAdd = true; @@ -202,7 +202,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { default: llvm_unreachable("Unknown fixup kind!"); case FK_Data_4: return 4; case ARM::fixup_arm_pcrel_12: return 3; - case ARM::fixup_arm_vfp_pcrel_10: return 3; + case ARM::fixup_arm_pcrel_10: return 3; case ARM::fixup_arm_branch: return 3; } } diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 9d2edf48548..ab554f3916d 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -181,6 +181,8 @@ namespace { const { return 0; } unsigned getT2AddrModeImm8OpValue(const MachineInstr &MI, unsigned Op) const { return 0; } + unsigned getT2AddrModeImm8s4OpValue(const MachineInstr &MI, unsigned Op) + const { return 0; } unsigned getT2AddrModeImm8OffsetOpValue(const MachineInstr &MI, unsigned Op) const { return 0; } unsigned getT2AddrModeImm12OffsetOpValue(const MachineInstr &MI,unsigned Op) diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h index 33c9328b846..7f6a855d84c 100644 --- a/lib/Target/ARM/ARMFixupKinds.h +++ b/lib/Target/ARM/ARMFixupKinds.h @@ -17,10 +17,10 @@ namespace ARM { enum Fixups { // fixup_arm_pcrel_12 - 12-bit PC relative relocation for symbol addresses fixup_arm_pcrel_12 = FirstTargetFixupKind, - // fixup_arm_vfp_pcrel_10 - 10-bit PC relative relocation for symbol addresses - // used in VFP instructions where the lower 2 bits are not encoded (so it's - // encoded as an 8-bit immediate). - fixup_arm_vfp_pcrel_10, + // fixup_arm_pcrel_10 - 10-bit PC relative relocation for symbol addresses + // used in VFP and Thumb2 instructions where the lower 2 bits are not encoded + // (so it's encoded as an 8-bit immediate). + fixup_arm_pcrel_10, // fixup_arm_brnach - 24-bit PC relative relocation for direct branch // instructions. fixup_arm_branch, diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index d911fe9c61f..66234451951 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -1010,6 +1010,15 @@ class T2Ii8s4 Rt; + bits<4> Rt2; + bits<13> addr; + let Inst{15-12} = Rt{3-0}; + let Inst{11-8} = Rt2{3-0}; + let Inst{19-16} = addr{12-9}; + let Inst{23} = addr{8}; + let Inst{7-0} = addr{7-0}; } class T2sI, // t2addrmode_imm8s4 := reg +/- (imm8 << 2) def t2addrmode_imm8s4 : Operand { let PrintMethod = "printT2AddrModeImm8s4Operand"; + string EncoderMethod = "getT2AddrModeImm8s4OpValue"; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } @@ -1263,17 +1264,11 @@ defm t2LDRSH : T2I_ld<1, 0b01, "ldrsh", IIC_iLoad_bh_i, IIC_iLoad_bh_si, defm t2LDRSB : T2I_ld<1, 0b00, "ldrsb", IIC_iLoad_bh_i, IIC_iLoad_bh_si, UnOpFrag<(sextloadi8 node:$Src)>>; -let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1, - isCodeGenOnly = 1 in { // $dst doesn't exist in asmstring? +let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in { // Load doubleword -def t2LDRDi8 : T2Ii8s4<1, 0, 1, (outs rGPR:$dst1, rGPR:$dst2), +def t2LDRDi8 : T2Ii8s4<1, 0, 1, (outs rGPR:$Rt, rGPR:$Rt2), (ins t2addrmode_imm8s4:$addr), - IIC_iLoad_d_i, "ldrd", "\t$dst1, $addr", []>; -def t2LDRDpci : T2Ii8s4<1, 0, 1, (outs rGPR:$dst1, rGPR:$dst2), - (ins i32imm:$addr), IIC_iLoad_d_i, - "ldrd", "\t$dst1, $addr", []> { - let Inst{19-16} = 0b1111; // Rn -} + IIC_iLoad_d_i, "ldrd", "\t$Rt, $Rt2, $addr", []>; } // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 // zextload i1 -> zextload i8 @@ -1431,11 +1426,10 @@ defm t2STRH:T2I_st<0b01,"strh", IIC_iStore_bh_i, IIC_iStore_bh_si, BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; // Store doubleword -let mayLoad = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1, - isCodeGenOnly = 1 in // $src2 doesn't exist in asm string +let mayLoad = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs), - (ins GPR:$src1, GPR:$src2, t2addrmode_imm8s4:$addr), - IIC_iStore_d_r, "strd", "\t$src1, $addr", []>; + (ins GPR:$Rt, GPR:$Rt2, t2addrmode_imm8s4:$addr), + IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", []>; // Indexed stores def t2STR_PRE : T2Iidxst<0, 0b10, 1, (outs GPR:$base_wb), @@ -1509,21 +1503,21 @@ def t2STRHT : T2IstT<0b01, "strht", IIC_iStore_bh_i>; // ldrd / strd pre / post variants // For disassembly only. -def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs GPR:$dst1, GPR:$dst2), +def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs GPR:$Rt, GPR:$Rt2), (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru, - "ldrd", "\t$dst1, $dst2, [$base, $imm]!", []>; + "ldrd", "\t$Rt, $Rt2, [$base, $imm]!", []>; -def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs GPR:$dst1, GPR:$dst2), +def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs GPR:$Rt, GPR:$Rt2), (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru, - "ldrd", "\t$dst1, $dst2, [$base], $imm", []>; + "ldrd", "\t$Rt, $Rt2, [$base], $imm", []>; def t2STRD_PRE : T2Ii8s4<1, 1, 0, (outs), - (ins GPR:$src1, GPR:$src2, GPR:$base, t2am_imm8s4_offset:$imm), - IIC_iStore_d_ru, "strd", "\t$src1, $src2, [$base, $imm]!", []>; + (ins GPR:$Rt, GPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), + IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base, $imm]!", []>; def t2STRD_POST : T2Ii8s4<0, 1, 0, (outs), - (ins GPR:$src1, GPR:$src2, GPR:$base, t2am_imm8s4_offset:$imm), - IIC_iStore_d_ru, "strd", "\t$src1, $src2, [$base], $imm", []>; + (ins GPR:$Rt, GPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), + IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base], $imm", []>; // T2Ipl (Preload Data/Instruction) signals the memory system of possible future // data/instruction access. These are for disassembly only. diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 0000b4dfdc3..207332fba72 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -47,7 +47,7 @@ public: const static MCFixupKindInfo Infos[] = { // name offset bits flags { "fixup_arm_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, - { "fixup_arm_vfp_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_arm_movt_hi16", 0, 16, 0 }, { "fixup_arm_movw_lo16", 0, 16, 0 }, @@ -90,6 +90,12 @@ public: uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups) const; + /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2' + /// operand. + uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const; + + /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm' /// operand as needed by load/store instructions. uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx, @@ -422,6 +428,40 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx, return Binary; } +/// getT2AddrModeImm8s4OpValue - Return encoding info for +/// 'reg +/- imm8<<2' operand. +uint32_t ARMMCCodeEmitter:: +getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const { + // {17-13} = reg + // {12} = (U)nsigned (add == '1', sub == '0') + // {11-0} = imm8 + unsigned Reg, Imm8; + 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()) { + Reg = getARMRegisterNumbering(ARM::PC); // Rn is PC. + Imm8 = 0; + isAdd = false ; // 'U' bit is set as part of the fixup. + + assert(MO.isExpr() && "Unexpected machine operand type!"); + const MCExpr *Expr = MO.getExpr(); + MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10); + Fixups.push_back(MCFixup::Create(0, Expr, Kind)); + + ++MCNumCPRelocations; + } else + isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups); + + uint32_t Binary = (Imm8 >> 2) & 0xff; + // Immediate is always encoded as positive. The 'U' bit controls add vs sub. + if (isAdd) + Binary |= (1 << 9); + Binary |= (Reg << 9); + return Binary; +} + uint32_t ARMMCCodeEmitter:: getMovtImmOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups) const { @@ -613,7 +653,7 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx, assert(MO.isExpr() && "Unexpected machine operand type!"); const MCExpr *Expr = MO.getExpr(); - MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_vfp_pcrel_10); + MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_12); Fixups.push_back(MCFixup::Create(0, Expr, Kind)); ++MCNumCPRelocations; diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index d4aa03c3db2..c3d24d2d70e 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -253,9 +253,6 @@ static unsigned T2Morph2LoadLiteral(unsigned Opcode) { default: return Opcode; // Return unmorphed opcode. - case ARM::t2LDRDi8: - return ARM::t2LDRDpci; - case ARM::t2LDR_POST: case ARM::t2LDR_PRE: case ARM::t2LDRi12: case ARM::t2LDRi8: case ARM::t2LDRs: case ARM::t2LDRT: diff --git a/test/CodeGen/Thumb2/thumb2-ldrd.ll b/test/CodeGen/Thumb2/thumb2-ldrd.ll index 22d4e88ed17..a747d5f7569 100644 --- a/test/CodeGen/Thumb2/thumb2-ldrd.ll +++ b/test/CodeGen/Thumb2/thumb2-ldrd.ll @@ -4,7 +4,7 @@ define i64 @t(i64 %a) nounwind readonly { entry: -;CHECK: ldrd r2, [r2] +;CHECK: ldrd r2, r3, [r2] %0 = load i64** @b, align 4 %1 = load i64* %0, align 4 %2 = mul i64 %1, %a diff --git a/test/MC/Disassembler/ARM/thumb-tests.txt b/test/MC/Disassembler/ARM/thumb-tests.txt index 06d12fed87f..dfd80b39eff 100644 --- a/test/MC/Disassembler/ARM/thumb-tests.txt +++ b/test/MC/Disassembler/ARM/thumb-tests.txt @@ -63,7 +63,7 @@ # CHECK: ssat r0, #17, r12 0x0c 0xf3 0x10 0x00 -# CHECK: strd r0, [r7, #64] +# CHECK: strd r0, r1, [r7, #64] 0xc7 0xe9 0x10 0x01 # CHECK: sub sp, #60