Index: llvm/lib/Target/Xtensa/CMakeLists.txt =================================================================== --- llvm/lib/Target/Xtensa/CMakeLists.txt +++ llvm/lib/Target/Xtensa/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_TARGET_DEFINITIONS Xtensa.td) tablegen(LLVM XtensaGenAsmMatcher.inc -gen-asm-matcher) +tablegen(LLVM XtensaGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM XtensaGenInstrInfo.inc -gen-instr-info) tablegen(LLVM XtensaGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM XtensaGenRegisterInfo.inc -gen-register-info) Index: llvm/lib/Target/Xtensa/LLVMBuild.txt =================================================================== --- llvm/lib/Target/Xtensa/LLVMBuild.txt +++ llvm/lib/Target/Xtensa/LLVMBuild.txt @@ -6,10 +6,11 @@ name = Xtensa parent = Target has_asmparser = 1 +has_asmprinter = 1 [component_1] type = Library name = XtensaCodeGen parent = Xtensa -required_libraries = CodeGen Core XtensaInfo Support Target +required_libraries = AsmPrinter CodeGen Core MC XtensaDesc XtensaInfo Support Target add_to_library_groups = Xtensa Index: llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt =================================================================== --- llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt +++ llvm/lib/Target/Xtensa/MCTargetDesc/CMakeLists.txt @@ -1,6 +1,7 @@ add_llvm_library(LLVMXtensaDesc XtensaAsmBackend.cpp XtensaELFObjectWriter.cpp + XtensaInstPrinter.cpp XtensaMCAsmInfo.cpp XtensaMCCodeEmitter.cpp XtensaMCTargetDesc.cpp Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h =================================================================== --- /dev/null +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.h @@ -0,0 +1,50 @@ +//===- XtensaInstPrinter.h - Convert Xtensa MCInst to asm syntax -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an Xtensa MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAINSTPRINTER_H +#define LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAINSTPRINTER_H + +#include "llvm/MC/MCInstPrinter.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { +class MCOperand; + +class XtensaInstPrinter : public MCInstPrinter { +public: + XtensaInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + + // Automatically generated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); + + // Print the given operand. + static void printOperand(const MCOperand &MO, raw_ostream &O); + + // Override MCInstPrinter. + void printRegName(raw_ostream &O, unsigned RegNo) const override; + void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, + const MCSubtargetInfo &STI) override; + +private: + // Print various types of operand. + void printOperand(const MCInst *MI, int OpNum, raw_ostream &O); + + void printImm8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); + void printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum, raw_ostream &O); +}; +} // end namespace llvm + +#endif /* LLVM_LIB_TARGET_XTENSA_MCTARGETDESC_XTENSAINSTPRINTER_H */ Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaInstPrinter.cpp @@ -0,0 +1,103 @@ +//===- XtensaInstPrinter.cpp - Convert Xtensa MCInst to asm syntax --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class prints an Xtensa MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#include "XtensaInstPrinter.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "asm-printer" + +#include "XtensaGenAsmWriter.inc" + +static void printExpr(const MCExpr *Expr, raw_ostream &OS) { + int Offset = 0; + const MCSymbolRefExpr *SRE; + + if (!(SRE = dyn_cast(Expr))) + assert(false && "Unexpected MCExpr type."); + + MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); + + switch (Kind) { + case MCSymbolRefExpr::VK_None: + break; + // TODO + default: + llvm_unreachable("Invalid kind!"); + } + + OS << SRE->getSymbol(); + + if (Offset) { + if (Offset > 0) + OS << '+'; + OS << Offset; + } + + if (Kind != MCSymbolRefExpr::VK_None) + OS << ')'; +} + +void XtensaInstPrinter::printOperand(const MCOperand &MC, raw_ostream &O) { + if (MC.isReg()) + O << getRegisterName(MC.getReg()); + else if (MC.isImm()) + O << MC.getImm(); + else if (MC.isExpr()) + printExpr(MC.getExpr(), O); + else + llvm_unreachable("Invalid operand"); +} + +void XtensaInstPrinter::printInst(const MCInst *MI, raw_ostream &O, + StringRef Annot, const MCSubtargetInfo &STI) { + printInstruction(MI, O); + printAnnotation(O, Annot); +} + +void XtensaInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { + O << getRegisterName(RegNo); +} + +void XtensaInstPrinter::printOperand(const MCInst *MI, int OpNum, + raw_ostream &O) { + printOperand(MI->getOperand(OpNum), O); +} + +void XtensaInstPrinter::printImm8_AsmOperand(const MCInst *MI, int OpNum, + raw_ostream &O) { + if (MI->getOperand(OpNum).isImm()) { + int64_t Value = MI->getOperand(OpNum).getImm(); + assert((Value >= -128 && Value <= 127) && + "Invalid argument, value must be in ranges [-128,127]"); + O << Value; + } else + printOperand(MI, OpNum, O); +} + +void XtensaInstPrinter::printImm8_sh8_AsmOperand(const MCInst *MI, int OpNum, + raw_ostream &O) { + if (MI->getOperand(OpNum).isImm()) { + int64_t Value = MI->getOperand(OpNum).getImm(); + assert((Value >= -32768 && Value <= 32512 && ((Value & 0xFF) == 0)) && + "Invalid argument, value must be multiples of 256 in range " + "[-32768,32512]"); + O << Value; + } else + printOperand(MI, OpNum, O); +} Index: llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp +++ llvm/lib/Target/Xtensa/MCTargetDesc/XtensaMCTargetDesc.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// #include "XtensaMCTargetDesc.h" +#include "XtensaInstPrinter.h" #include "XtensaMCAsmInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAsmInfo.h" @@ -23,6 +24,9 @@ #define GET_REGINFO_MC_DESC #include "XtensaGenRegisterInfo.inc" +#define GET_SUBTARGETINFO_MC_DESC +#include "XtensaGenSubtargetInfo.inc" + using namespace llvm; static MCAsmInfo *createXtensaMCAsmInfo(const MCRegisterInfo &MRI, @@ -37,12 +41,25 @@ return X; } +static MCInstPrinter *createXtensaMCInstPrinter(const Triple &TT, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) { + return new XtensaInstPrinter(MAI, MII, MRI); +} + static MCRegisterInfo *createXtensaMCRegisterInfo(const Triple &TT) { MCRegisterInfo *X = new MCRegisterInfo(); InitXtensaMCRegisterInfo(X, Xtensa::sp); return X; } +static MCSubtargetInfo * +createXtensaMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { + return createXtensaMCSubtargetInfoImpl(TT, CPU, FS); +} + extern "C" void LLVMInitializeXtensaTargetMC() { // Register the MCAsmInfo. TargetRegistry::RegisterMCAsmInfo(TheXtensaTarget, createXtensaMCAsmInfo); @@ -54,10 +71,18 @@ // Register the MCInstrInfo. TargetRegistry::RegisterMCInstrInfo(TheXtensaTarget, createXtensaMCInstrInfo); + // Register the MCInstPrinter. + TargetRegistry::RegisterMCInstPrinter(TheXtensaTarget, + createXtensaMCInstPrinter); + // Register the MCRegisterInfo. TargetRegistry::RegisterMCRegInfo(TheXtensaTarget, createXtensaMCRegisterInfo); + // Register the MCSubtargetInfo. + TargetRegistry::RegisterMCSubtargetInfo(TheXtensaTarget, + createXtensaMCSubtargetInfo); + // Register the MCAsmBackend. TargetRegistry::RegisterMCAsmBackend(TheXtensaTarget, createXtensaMCAsmBackend); Index: llvm/lib/Target/Xtensa/Xtensa.td =================================================================== --- llvm/lib/Target/Xtensa/Xtensa.td +++ llvm/lib/Target/Xtensa/Xtensa.td @@ -48,11 +48,18 @@ def XtensaAsmParser : AsmParser { let ShouldEmitMatchRegisterAltName = 1; +} + +def XtensaInstPrinter : AsmWriter +{ + string AsmWriterClassName = "InstPrinter"; + bit isMCAsmWriter = 1; } def Xtensa : Target { let InstructionSet = XtensaInstrInfo; + let AssemblyWriters = [XtensaInstPrinter]; let AssemblyParsers = [XtensaAsmParser]; } Index: llvm/test/MC/Xtensa/elf-header.s =================================================================== --- /dev/null +++ llvm/test/MC/Xtensa/elf-header.s @@ -0,0 +1,31 @@ +# RUN: llvm-mc %s -filetype=obj -triple=xtensa | llvm-readobj -h \ +# RUN: | FileCheck -check-prefix=Xtensa %s + +# Xtensa: Format: ELF32-Xtensa +# Xtensa: Arch: xtensa +# Xtensa: AddressSize: 32bit +# Xtensa: ElfHeader { +# Xtensa: Ident { +# Xtensa: Magic: (7F 45 4C 46) +# Xtensa: Class: 32-bit (0x1) +# Xtensa: DataEncoding: LittleEndian (0x1) +# Xtensa: FileVersion: 1 +# Xtensa: OS/ABI: SystemV (0x0) +# Xtensa: ABIVersion: 0 +# Xtensa: Unused: (00 00 00 00 00 00 00) +# Xtensa: } +# Xtensa: Type: Relocatable (0x1) +# Xtensa: Machine: EM_XTENSA (0x5E) +# Xtensa: Version: 1 +# Xtensa: Entry: 0x0 +# Xtensa: ProgramHeaderOffset: 0x0 +# Xtensa: SectionHeaderOffset: 0x5C +# Xtensa: Flags [ (0x0) +# Xtensa: ] +# Xtensa: HeaderSize: 52 +# Xtensa: ProgramHeaderEntrySize: 0 +# Xtensa: ProgramHeaderCount: 0 +# Xtensa: SectionHeaderEntrySize: 40 +# Xtensa: SectionHeaderCount: 4 +# Xtensa: StringTableSectionIndex: 1 +# Xtensa: } Index: llvm/test/MC/Xtensa/lit.local.cfg =================================================================== --- /dev/null +++ llvm/test/MC/Xtensa/lit.local.cfg @@ -0,0 +1,3 @@ +if not 'Xtensa' in config.root.targets: + config.unsupported = True + Index: llvm/test/MC/Xtensa/xtensa-invalid.s =================================================================== --- /dev/null +++ llvm/test/MC/Xtensa/xtensa-invalid.s @@ -0,0 +1,31 @@ +# RUN: not llvm-mc -triple xtensa < %s 2>&1 | FileCheck %s + +# Out of range immediates + +LBL0: + +# imm8 +addi a1, a2, 300 +# CHECK: error: expected immediate in range [-128, 127] + +addi a1, a2, -129 +# CHECK: error: expected immediate in range [-128, 127] + +# imm8_sh8 +addmi a1, a2, 33 +# CHECK: error: expected immediate in range [-32768, 32512], first 8 bits should be zero + +# Invalid number of operands +addi a1, a2 # CHECK: :[[@LINE]]:1: error: too few operands for instruction +addi a1, a2, 4, 4 # CHECK: :[[@LINE]]:17: error: invalid operand for instruction + +# Invalid mnemonics +aaa a10, a12 # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic + +# Invalid register names +addi a101, sp, 10 # CHECK: :[[@LINE]]:6: error: invalid operand for instruction +or r2, sp, a3 # CHECK: :[[@LINE]]:4: error: invalid operand for instruction + +# Invalid operand types +and sp, a2, 10 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction +addi sp, a1, a2 # CHECK: :[[@LINE]]:14: error: expected immediate in range [-128, 127] Index: llvm/test/MC/Xtensa/xtensa-valid.s =================================================================== --- /dev/null +++ llvm/test/MC/Xtensa/xtensa-valid.s @@ -0,0 +1,105 @@ +# RUN: llvm-mc %s -triple=xtensa -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s + + +.align 4 +LBL0: + +# CHECK-INST: abs a5, a6 +# CHECK: encoding: [0x60,0x51,0x60] + abs a5, a6 + +# CHECK-INST: add a3, a9, a4 +# CHECK: encoding: [0x40,0x39,0x80] + add a3, a9, a4 +# CHECK-INST: add a15, a9, a1 +# CHECK: encoding: [0x10,0xf9,0x80] + add a15, a9, sp + +# CHECK-INST: addi a8, a1, -128 +# CHECK: encoding: [0x82,0xc1,0x80] + addi a8, sp, -128 +# CHECK-INST: addi a8, a1, -12 +# CHECK: encoding: [0x82,0xc1,0xf4] + addi a8, a1, -12 + +# CHECK-INST: addmi a1, a2, 32512 +# CHECK: encoding: [0x12,0xd2,0x7f] + addmi a1, a2, 32512 + +# CHECK-INST: addx2 a2, a1, a5 +# CHECK: encoding: [0x50,0x21,0x90] + addx2 a2, sp, a5 +# CHECK-INST: addx4 a3, a1, a6 +# CHECK: encoding: [0x60,0x31,0xa0] + addx4 a3, sp, a6 +# CHECK-INST: addx8 a4, a1, a7 +# CHECK: encoding: [0x70,0x41,0xb0] + addx8 a4, sp, a7 + +# CHECK-INST: dsync +# CHECK: encoding: [0x30,0x20,0x00] + dsync +# CHECK-INST: esync +# CHECK: encoding: [0x20,0x20,0x00] + esync + +# CHECK-INST: extw +# CHECK: encoding: [0xd0,0x20,0x00] + extw + +# CHECK-INST: isync +# CHECK: encoding: [0x00,0x20,0x00] + isync + +# CHECK-INST: memw +# CHECK: encoding: [0xc0,0x20,0x00] + memw + +# CHECK-INST: moveqz a2, a3, a4 +# CHECK: encoding: [0x40,0x23,0x83] + moveqz a2,a3,a4 +# CHECK-INST: movgez a3, a11, a12 +# CHECK: encoding: [0xc0,0x3b,0xb3] + movgez a3,a11,a12 + +# CHECK-INST: movltz a7, a8, a9 +# CHECK: encoding: [0x90,0x78,0xa3] + movltz a7, a8, a9 +# CHECK-INST: movnez a10, a11, a12 +# CHECK: encoding: [0xc0,0xab,0x93] + movnez a10,a11, a12 + +# CHECK-INST: neg a1, a3 +# CHECK: encoding: [0x30,0x10,0x60] + neg a1, a3 + +# CHECK-INST: nop +# CHECK: encoding: [0xf0,0x20,0x00] + nop + +# CHECK-INST: or a4, a5, a6 +# CHECK: encoding: [0x60,0x45,0x20] + or a4, a5, a6 + +# CHECK-INST: rsync +# CHECK: encoding: [0x10,0x20,0x00] + rsync + +# CHECK-INST: sub a8, a2, a1 +# CHECK: encoding: [0x10,0x82,0xc0] + sub a8, a2, a1 +# CHECK-INST: subx2 a2, a1, a5 +# CHECK: encoding: [0x50,0x21,0xd0] + subx2 a2, sp, a5 +# CHECK-INST: subx4 a3, a1, a6 +# CHECK: encoding: [0x60,0x31,0xe0] + subx4 a3, sp, a6 +# CHECK-INST: subx8 a4, a1, a7 +# CHECK: encoding: [0x70,0x41,0xf0] + subx8 a4, sp, a7 + +# CHECK-INST: xor a6, a4, a5 +# CHECK: encoding: [0x50,0x64,0x30] + xor a6, a4, a5 +