Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -9371,6 +9371,12 @@ return parseDirectiveAlign(DirectiveID.getLoc()); // Use Generic on failure. else if (IDVal == ".thumb_set") parseDirectiveThumbSet(DirectiveID.getLoc()); + else if (IDVal == ".inst") + parseDirectiveInst(DirectiveID.getLoc()); + else if (IDVal == ".inst.n") + parseDirectiveInst(DirectiveID.getLoc(), 'n'); + else if (IDVal == ".inst.w") + parseDirectiveInst(DirectiveID.getLoc(), 'w'); else if (!IsMachO && !IsCOFF) { if (IDVal == ".arch") parseDirectiveArch(DirectiveID.getLoc()); @@ -9382,12 +9388,6 @@ parseDirectiveFPU(DirectiveID.getLoc()); else if (IDVal == ".fnstart") parseDirectiveFnStart(DirectiveID.getLoc()); - else if (IDVal == ".inst") - parseDirectiveInst(DirectiveID.getLoc()); - else if (IDVal == ".inst.n") - parseDirectiveInst(DirectiveID.getLoc(), 'n'); - else if (IDVal == ".inst.w") - parseDirectiveInst(DirectiveID.getLoc(), 'w'); else if (IDVal == ".object_arch") parseDirectiveObjectArch(DirectiveID.getLoc()); else if (IDVal == ".tlsdescseq") Index: lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp +++ lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp @@ -13,6 +13,8 @@ #include "ARMTargetMachine.h" #include "llvm/MC/ConstantPools.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -47,6 +49,41 @@ // reset() - Reset any state void ARMTargetStreamer::reset() {} +void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) { + unsigned Size; + char Buffer[4]; + const bool LittleEndian = getStreamer().getContext().getAsmInfo()->isLittleEndian(); + + switch (Suffix) { + case '\0': + Size = 4; + + for (unsigned II = 0, IE = Size; II != IE; II++) { + const unsigned I = LittleEndian ? (Size - II - 1) : II; + Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT); + } + + break; + case 'n': + case 'w': + Size = (Suffix == 'n' ? 2 : 4); + + // Thumb wide instructions are emitted as a pair of 16-bit words of the + // appropriate endianness. + for (unsigned II = 0, IE = Size; II != IE; II = II + 2) { + const unsigned I0 = LittleEndian ? II + 0 : II + 1; + const unsigned I1 = LittleEndian ? II + 1 : II + 0; + Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT); + Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT); + } + + break; + default: + llvm_unreachable("Invalid Suffix"); + } + getStreamer().EmitBytes(StringRef(Buffer, Size)); +} + // The remaining callbacks should be handled separately by each // streamer. void ARMTargetStreamer::emitFnStart() {} @@ -76,7 +113,6 @@ void ARMTargetStreamer::emitObjectArch(ARM::ArchKind Arch) {} void ARMTargetStreamer::emitFPU(unsigned FPU) {} void ARMTargetStreamer::finishAttributeSection() {} -void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {} void ARMTargetStreamer::AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE) {} void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {} Index: test/MC/ARM/directive-unsupported.s =================================================================== --- test/MC/ARM/directive-unsupported.s +++ test/MC/ARM/directive-unsupported.s @@ -30,24 +30,6 @@ // CHECK: .eabi_attribute 0, 0 // CHECK: ^ - .inst 0xdefe - -// CHECK: error: unknown directive -// CHECK: .inst 0xdefe -// CHECK: ^ - - .inst.n 0xdefe - -// CHECK: error: unknown directive -// CHECK: .inst.n 0xdefe -// CHECK: ^ - - .inst.w 0xdefe - -// CHECK: error: unknown directive -// CHECK: .inst.w 0xdefe -// CHECK: ^ - .object_arch armv7 // CHECK: error: unknown directive Index: test/MC/ARM/inst-directive-other.s =================================================================== --- /dev/null +++ test/MC/ARM/inst-directive-other.s @@ -0,0 +1,47 @@ +// RUN: llvm-mc %s -triple=armv7-apple-darwin -filetype=asm -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-ASM +// RUN: llvm-mc %s -triple=armv7-apple-darwin -filetype=obj -o - \ +// RUN: | llvm-objdump -triple=thumbv7 -d - | FileCheck %s --check-prefixes=CHECK-OBJ-CODE +// RUN: llvm-mc %s -triple=thumbv7-win32-gnu -filetype=asm -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-ASM +// RUN: llvm-mc %s -triple=thumbv7-win32-gnu -filetype=obj -o - \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefixes=CHECK-OBJ,CHECK-OBJ-CODE +// RUN: llvm-mc %s -triple=armv7-linux-gnueabi -filetype=asm -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-ASM +// RUN: llvm-mc %s -triple=armv7-linux-gnueabi -filetype=obj -o - \ +// RUN: | llvm-objdump -d -triple=thumbv7 - | FileCheck %s --check-prefixes=CHECK-OBJ,CHECK-OBJ-DATA + + .text + + .p2align 2 + .globl _func + .thumb +_func: + // ELF distinguishes between data and code when emitted this way, but + // MachO and COFF don't. + bx lr + .short 0x4770 + .inst.n 0x4770 + mov.w r0, #42 + .short 0xf04f, 0x002a + .inst.w 0xf04f002a + +// CHECK-ASM: .p2align 2 +// CHECK-ASM: .globl _func +// CHECK-ASM: _func: +// CHECK-ASM: bx lr +// CHECK-ASM: .short 18288 +// CHECK-ASM: .inst.n 0x4770 +// CHECK-ASM: mov.w r0, #42 +// CHECK-ASM: .short 61519 +// CHECK-ASM: .short 42 +// CHECK-ASM: .inst.w 0xf04f002a + +// CHECK-OBJ: 0: 70 47 bx lr +// CHECK-OBJ-CODE: 2: 70 47 bx lr +// CHECK-OBJ-DATA: 2: 70 47 .short 0x4770 +// CHECK-OBJ: 4: 70 47 bx lr +// CHECK-OBJ: 6: 4f f0 2a 00 mov.w r0, #42 +// CHECK-OBJ-CODE: a: 4f f0 2a 00 mov.w r0, #42 +// CHECK-OBJ-DATA: a: 4f f0 2a 00 .word 0x002af04f +// CHECK-OBJ: e: 4f f0 2a 00 mov.w r0, #42