Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -180,6 +180,7 @@ set(LLVM_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) set(LLVM_ALL_TARGETS + AAP AArch64 AMDGPU ARM Index: autoconf/configure.ac =================================================================== --- autoconf/configure.ac +++ autoconf/configure.ac @@ -439,6 +439,7 @@ nvptx-*) llvm_cv_target_arch="NVPTX" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;; wasm*-*) llvm_cv_target_arch="WebAssembly" ;; + aap-*) llvm_cv_target_arch="AAP" ;; *) llvm_cv_target_arch="Unknown" ;; esac]) @@ -475,6 +476,7 @@ hexagon-*) host_arch="Hexagon" ;; s390x-*) host_arch="SystemZ" ;; wasm*-*) host_arch="WebAssembly" ;; + aap-*) host_arch="AAP" ;; *) host_arch="Unknown" ;; esac @@ -808,6 +810,7 @@ NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;; SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;; WebAssembly) AC_SUBST(TARGET_HAS_JIT,0) ;; + AAP) AC_SUBST(TARGET_HAS_JIT,0) ;; *) AC_SUBST(TARGET_HAS_JIT,0) ;; esac fi @@ -1093,7 +1096,7 @@ fi dnl List all possible targets -ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ AMDGPU BPF" +ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ AMDGPU BPF AAP" AC_SUBST(ALL_TARGETS,$ALL_TARGETS) dnl Allow specific targets to be specified for building (or not) @@ -1101,7 +1104,7 @@ AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets], [Build specific host targets: all or target1,target2,... Valid targets are: host, x86, x86_64, sparc, powerpc, arm64, arm, aarch64, mips, hexagon, - xcore, msp430, nvptx, systemz, r600, bpf, wasm, and cpp (default=all)]),, + xcore, msp430, nvptx, systemz, r600, bpf, asm, wasm, and cpp (default=all)]),, enableval=all) if test "$enableval" = host-only ; then enableval=host @@ -1130,6 +1133,7 @@ systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;; r600) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;; + aap) TARGETS_TO_BUILD="AAP $TARGETS_TO_BUILD" ;; wasm) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;; host) case "$llvm_cv_target_arch" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -1144,6 +1148,7 @@ Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; + AAP) TARGETS_TO_BUILD="AAP $TARGETS_TO_BUILD" ;; WebAssembly) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;; *) AC_MSG_ERROR([Can not set target to build]) ;; esac ;; Index: bindings/python/llvm/disassembler.py =================================================================== --- bindings/python/llvm/disassembler.py +++ bindings/python/llvm/disassembler.py @@ -36,7 +36,7 @@ _initialized = False -_targets = ['AArch64', 'ARM', 'Hexagon', 'MSP430', 'Mips', 'NVPTX', 'PowerPC', 'R600', 'Sparc', 'SystemZ', 'X86', 'XCore'] +_targets = ['AArch64', 'ARM', 'Hexagon', 'MSP430', 'Mips', 'NVPTX', 'PowerPC', 'R600', 'Sparc', 'SystemZ', 'AAP', 'X86', 'XCore'] def _ensure_initialized(): global _initialized if not _initialized: Index: cmake/config-ix.cmake =================================================================== --- cmake/config-ix.cmake +++ cmake/config-ix.cmake @@ -361,6 +361,8 @@ set(LLVM_NATIVE_ARCH WebAssembly) elseif (LLVM_NATIVE_ARCH MATCHES "wasm64") set(LLVM_NATIVE_ARCH WebAssembly) +elseif (LLVM_NATIVE_ARCH MATCHES "aap") + set(LLVM_NATIVE_ARCH AAP) else () message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}") endif () Index: configure =================================================================== --- configure +++ configure @@ -1464,7 +1464,7 @@ target1,target2,... Valid targets are: host, x86, x86_64, sparc, powerpc, arm64, arm, aarch64, mips, hexagon, xcore, msp430, nvptx, systemz, r600, bpf, - wasm, and cpp (default=all) + aap, wasm, and cpp (default=all) --enable-experimental-targets Build experimental host targets: disable or target1,target2,... (default=disable) @@ -4196,6 +4196,7 @@ nvptx-*) llvm_cv_target_arch="NVPTX" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;; wasm*-*) llvm_cv_target_arch="WebAssembly" ;; + aap-*) llvm_cv_target_arch="AAP" ;; *) llvm_cv_target_arch="Unknown" ;; esac fi @@ -4233,6 +4234,7 @@ hexagon-*) host_arch="Hexagon" ;; s390x-*) host_arch="SystemZ" ;; wasm*-*) host_arch="WebAssembly" ;; + aap-*) host_arch="AAP" ;; *) host_arch="Unknown" ;; esac @@ -5162,6 +5164,8 @@ ;; WebAssembly) TARGET_HAS_JIT=0 ;; + AAP) TARGET_HAS_JIT=0 + ;; *) TARGET_HAS_JIT=0 ;; esac @@ -5620,7 +5624,7 @@ fi -ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ AMDGPU BPF" +ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ AMDGPU BPF AAP" ALL_TARGETS=$ALL_TARGETS @@ -5660,6 +5664,7 @@ amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;; r600) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;; wasm) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;; + aap) TARGETS_TO_BUILD="AAP $TARGETS_TO_BUILD" ;; host) case "$llvm_cv_target_arch" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -5674,6 +5679,7 @@ NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; WebAssembly) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;; + AAP) TARGETS_TO_BUILD="AAP $TARGETS_TO_BUILD" ;; *) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5 echo "$as_me: error: Can not set target to build" >&2;} { (exit 1); exit 1; }; } ;; Index: include/llvm/ADT/Triple.h =================================================================== --- include/llvm/ADT/Triple.h +++ include/llvm/ADT/Triple.h @@ -87,7 +87,8 @@ shave, // SHAVE: Movidius vector VLIW processors wasm32, // WebAssembly with 32-bit pointers wasm64, // WebAssembly with 64-bit pointers - LastArchType = wasm64 + aap, // AAP architecture + LastArchType = aap }; enum SubArchType { NoSubArch, Index: include/llvm/Object/ELFObjectFile.h =================================================================== --- include/llvm/Object/ELFObjectFile.h +++ include/llvm/Object/ELFObjectFile.h @@ -838,6 +838,8 @@ case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: return "ELF32-sparc"; + case ELF::EM_AAP: + return "ELF32-aap"; default: return "ELF32-unknown"; } @@ -902,6 +904,9 @@ case ELF::EM_SPARCV9: return Triple::sparcv9; + case ELF::EM_AAP: + return Triple::aap; + default: return Triple::UnknownArch; } Index: include/llvm/Support/ELF.h =================================================================== --- include/llvm/Support/ELF.h +++ include/llvm/Support/ELF.h @@ -309,7 +309,8 @@ EM_COOL = 217, // iCelero CoolEngine EM_NORC = 218, // Nanoradio Optimized RISC EM_CSR_KALIMBA = 219, // CSR Kalimba architecture family - EM_AMDGPU = 224 // AMD GPU architecture + EM_AMDGPU = 224, // AMD GPU architecture + EM_AAP = 0x5343 // AAP }; // Object file classes. @@ -565,6 +566,11 @@ #include "ELFRelocs/Sparc.def" }; +// ELF Relocation type for AAP. +enum { +#include "ELFRelocs/AAP.def" +}; + #undef ELF_RELOC // Section header. Index: include/llvm/Support/ELFRelocs/AAP.def =================================================================== --- /dev/null +++ include/llvm/Support/ELFRelocs/AAP.def @@ -0,0 +1,24 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_AAP_NONE, 0x00) +ELF_RELOC(R_AAP_8, 0x01) +ELF_RELOC(R_AAP_16, 0x02) +ELF_RELOC(R_AAP_32, 0x03) +ELF_RELOC(R_AAP_64, 0x04) +ELF_RELOC(R_AAP_BR16, 0x05) +ELF_RELOC(R_AAP_BR32, 0x06) +ELF_RELOC(R_AAP_BRCC16, 0x07) +ELF_RELOC(R_AAP_BRCC32, 0x08) +ELF_RELOC(R_AAP_BAL16, 0x09) +ELF_RELOC(R_AAP_BAL32, 0x0a) +ELF_RELOC(R_AAP_ABS3_SHORT, 0x0b) +ELF_RELOC(R_AAP_ABS6_SHORT, 0x0c) +ELF_RELOC(R_AAP_ABS6, 0x0d) +ELF_RELOC(R_AAP_ABS9, 0x0e) +ELF_RELOC(R_AAP_ABS10, 0x0f) +ELF_RELOC(R_AAP_OFF10, 0x10) +ELF_RELOC(R_AAP_ABS12, 0x11) +ELF_RELOC(R_AAP_ABS16, 0x12) Index: include/llvm/module.modulemap =================================================================== --- include/llvm/module.modulemap +++ include/llvm/module.modulemap @@ -199,6 +199,7 @@ // These are intended for textual inclusion. textual header "Support/Dwarf.def" + textual header "Support/ELFRelocs/AAP.def" textual header "Support/ELFRelocs/AArch64.def" textual header "Support/ELFRelocs/ARM.def" textual header "Support/ELFRelocs/Hexagon.def" Index: lib/Object/ELF.cpp =================================================================== --- lib/Object/ELF.cpp +++ lib/Object/ELF.cpp @@ -39,6 +39,13 @@ break; } break; + case ELF::EM_AAP: + switch (Type) { +#include "llvm/Support/ELFRelocs/AAP.def" + default: + break; + } + break; case ELF::EM_AARCH64: switch (Type) { #include "llvm/Support/ELFRelocs/AArch64.def" Index: lib/Object/ELFYAML.cpp =================================================================== --- lib/Object/ELFYAML.cpp +++ lib/Object/ELFYAML.cpp @@ -475,6 +475,9 @@ case ELF::EM_ARM: #include "llvm/Support/ELFRelocs/ARM.def" break; + case ELF::EM_AAP: +#include "llvm/Support/ELFRelocs/AAP.def" + break; default: llvm_unreachable("Unsupported architecture"); } Index: lib/Support/Triple.cpp =================================================================== --- lib/Support/Triple.cpp +++ lib/Support/Triple.cpp @@ -62,6 +62,7 @@ case shave: return "shave"; case wasm32: return "wasm32"; case wasm64: return "wasm64"; + case aap: return "aap"; } llvm_unreachable("Invalid ArchType!"); @@ -126,6 +127,7 @@ case shave: return "shave"; case wasm32: case wasm64: return "wasm"; + case aap: return "aap"; } } @@ -263,6 +265,7 @@ .Case("shave", shave) .Case("wasm32", wasm32) .Case("wasm64", wasm64) + .Case("aap", aap) .Default(UnknownArch); } @@ -370,6 +373,7 @@ .Case("shave", Triple::shave) .Case("wasm32", Triple::wasm32) .Case("wasm64", Triple::wasm64) + .Case("aap", Triple::aap) .Default(Triple::UnknownArch); } @@ -1003,6 +1007,7 @@ return 0; case llvm::Triple::msp430: + case llvm::Triple::aap: return 16; case llvm::Triple::arm: @@ -1074,6 +1079,7 @@ case Triple::bpfel: case Triple::bpfeb: case Triple::msp430: + case Triple::aap: case Triple::systemz: case Triple::ppc64le: T.setArch(UnknownArch); @@ -1135,6 +1141,7 @@ case Triple::xcore: case Triple::sparcel: case Triple::shave: + case Triple::aap: T.setArch(UnknownArch); break; @@ -1196,6 +1203,7 @@ case Triple::spir: case Triple::wasm32: case Triple::wasm64: + case Triple::aap: case Triple::x86: case Triple::x86_64: case Triple::xcore: @@ -1274,6 +1282,7 @@ case Triple::thumb: case Triple::wasm32: case Triple::wasm64: + case Triple::aap: case Triple::x86: case Triple::x86_64: case Triple::xcore: Index: lib/Target/AAP/AAP.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAP.h @@ -0,0 +1,43 @@ +//===-- AAP.h - Top-level interface for AAP representation ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in the LLVM +// AAP back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_AAP_H +#define TARGET_AAP_H + +#include "MCTargetDesc/AAPMCTargetDesc.h" +#include "llvm/Target/TargetMachine.h" + +namespace AAPCC { +// AAP specific condition codes +enum CondCode { + COND_EQ = 0, + COND_NE = 1, + COND_LTS = 2, + COND_GTS = 3, + COND_LTU = 4, + COND_GTU = 5, + COND_INVALID = -1 +}; +} // end namespace AAP + +namespace llvm { +extern Target TheAAPTarget; +class AAPTargetMachine; + +FunctionPass *createAAPISelDag(AAPTargetMachine &TM, + CodeGenOpt::Level OptLevel); + +} // end namespace llvm + +#endif Index: lib/Target/AAP/AAP.td =================================================================== --- /dev/null +++ lib/Target/AAP/AAP.td @@ -0,0 +1,47 @@ +//===- AAP.td - Describe the AAP Target Machine ------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces which we are implementing +//===----------------------------------------------------------------------===// + +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// AAP Subtarget features. +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// AAP processors supported. +//===----------------------------------------------------------------------===// + +class Proc Features> + : Processor; + +def : Proc<"generic", []>; + + +//===----------------------------------------------------------------------===// +// Register File, Calling Conv, Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "AAPRegisterInfo.td" +include "AAPCallingConv.td" +include "AAPInstrFormats.td" +include "AAPInstrInfo.td" + +def AAPInstrInfo : InstrInfo; + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def AAP : Target { + let InstructionSet = AAPInstrInfo; +} Index: lib/Target/AAP/AAPAsmPrinter.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPAsmPrinter.cpp @@ -0,0 +1,115 @@ +//===-- AAPAsmPrinter.cpp - AAP LLVM assembly writer ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to the AAP assembly language. +// +//===----------------------------------------------------------------------===// + +#include "AAP.h" +#include "InstPrinter/AAPInstPrinter.h" +#include "AAPInstrInfo.h" +#include "AAPMCInstLower.h" +#include "AAPTargetMachine.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "asm-printer" + +namespace { +class AAPAsmPrinter : public AsmPrinter { +public: + AAPAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)) {} + + const char *getPassName() const override { return "AAP Assembly Printer"; } + + void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, + const char *Modifier = nullptr); + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) override; + + void EmitInstruction(const MachineInstr *MI) override; +}; +} // end of anonymous namespace + +void AAPAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, + raw_ostream &O, const char *Modifier) { + const MachineOperand &MO = MI->getOperand(OpNum); + switch (MO.getType()) { + default: + llvm_unreachable("Not implemented yet!"); + case MachineOperand::MO_Register: + O << '$' << AAPInstPrinter::getRegisterName(MO.getReg()); + return; + case MachineOperand::MO_Immediate: + O << MO.getImm(); + return; + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(); + return; + case MachineOperand::MO_GlobalAddress: { + bool isMemOp = Modifier && !strcmp(Modifier, "mem"); + uint64_t Offset = MO.getOffset(); + + // If the global address expression is a part of displacement field with a + // register base, we should not emit any prefix symbol here, e.g. + // mov.w &foo, r1 + // vs + // mov.w glb(r1), r2 + // Otherwise (!) msp430-as will silently miscompile the output :( + O << (isMemOp ? '&' : '#'); + if (Offset) + O << '(' << Offset << '+'; + + O << *getSymbol(MO.getGlobal()); + + if (Offset) + O << ')'; + + return; + } + } +} + +bool AAPAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode, raw_ostream &O) { + printOperand(MI, OpNo, O); + return false; +} + +void AAPAsmPrinter::EmitInstruction(const MachineInstr *MI) { + AAPMCInstLower MCInstLowering(OutContext, *this); + + MCInst TmpInst; + MCInstLowering.Lower(MI, TmpInst); + EmitToStreamer(*OutStreamer, TmpInst); +} + +// Force static initialization. +extern "C" void LLVMInitializeAAPAsmPrinter() { + RegisterAsmPrinter X(TheAAPTarget); +} Index: lib/Target/AAP/AAPCallingConv.td =================================================================== --- /dev/null +++ lib/Target/AAP/AAPCallingConv.td @@ -0,0 +1,38 @@ +//===- AAPCallingConv.td - Calling Conventions for AAP -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the AAP architectures. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Return Value Calling Conventions +//===----------------------------------------------------------------------===// + +def RetCC_AAP : CallingConv<[ + CCIfType<[i16], CCAssignToReg<[R3, R4, R5, R6, R7]>> +]>; + +//===----------------------------------------------------------------------===// +// Argument Calling Conventions +//===----------------------------------------------------------------------===// + +def CC_AAP : CallingConv<[ + // Promote i8 args to i16 + CCIfType<[i8], CCPromoteToType>, + + // All arguments get passed into registers if there is space. + CCIfType<[i16], CCAssignToReg<[R3, R4, R5, R6]>>, + + // Alternatively they are added to the stack. + CCAssignToStack<2, 2> +]>; + +def CSR : CalleeSavedRegs<(add R20, R21, R22, R23, R24, R25, R26, R27, R28, + R29, R30, R31)>; Index: lib/Target/AAP/AAPFrameLowering.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAPFrameLowering.h @@ -0,0 +1,53 @@ +//===-- AAPFrameLowering.h - Frame info for AAP Target ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the AAP implementation of the TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#ifndef AAPFRAMELOWERING_H +#define AAPFRAMELOWERING_H + +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +class AAPSubtarget; + +class AAPFrameLowering : public TargetFrameLowering { +public: + AAPFrameLowering(); + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const override; + bool + restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const override; + + void + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; + + bool hasFP(const MachineFunction &MF) const override; + + void processFunctionBeforeFrameFinalized( + MachineFunction &MF, RegScavenger *RS = nullptr) const override; +}; +} + +#endif Index: lib/Target/AAP/AAPFrameLowering.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPFrameLowering.cpp @@ -0,0 +1,186 @@ +//===-- AAPFrameLowering.cpp - Frame info for AAP Target ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the AAP implementation of the TargetFrameLowering class. +// +//===----------------------------------------------------------------------===// + +#include "AAPFrameLowering.h" +#include "AAP.h" +#include "AAPInstrInfo.h" +#include "AAPMachineFunctionInfo.h" +#include "AAPSubtarget.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// AAPFrameLowering: +//===----------------------------------------------------------------------===// + +AAPFrameLowering::AAPFrameLowering() + : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 2, 0, 2) {} + +bool AAPFrameLowering::hasFP(const MachineFunction &MF) const { + return MF.getTarget().Options.DisableFramePointerElim(MF) || + MF.getFrameInfo()->hasVarSizedObjects(); +} + +void AAPFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + MachineFrameInfo *MFrameInfo = MF.getFrameInfo(); + AAPMachineFunctionInfo *MFuncInfo = MF.getInfo(); + const AAPInstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + + auto MBBI = MBB.begin(); + DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); + + // Get the number of bytes to allocate from the FrameInfo + const uint64_t StackSize = MFrameInfo->getStackSize(); + + assert(!hasFP(MF) && "Frame pointer unsupported!"); + + uint64_t NumBytes = StackSize - MFuncInfo->getCalleeSavedFrameSize(); + const unsigned SP = AAPRegisterInfo::getStackPtrRegister(); + + // Adjust the stack pointer if there is a stack to allocate + if (NumBytes) { + const uint64_t Addend = NumBytes % 1023; + const uint64_t NumChunks = NumBytes / 1023; + + for (uint64_t i = 0; i < NumChunks; ++i) { + BuildMI(MBB, MBBI, DL, TII.get(AAP::SUB_i10), SP) + .addReg(SP) + .addImm(1023); + } + if (Addend) { + BuildMI(MBB, MBBI, DL, TII.get(AAP::SUB_i10), SP) + .addReg(SP) + .addImm(Addend); + } + } +} + +void AAPFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + const MachineFrameInfo *MFrameInfo = MF.getFrameInfo(); + AAPMachineFunctionInfo *MFuncInfo = MF.getInfo(); + const AAPInstrInfo &TII = + *static_cast(MF.getSubtarget().getInstrInfo()); + + auto MBBI = MBB.getLastNonDebugInstr(); + DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); + + unsigned RetOpcode = MBBI->getOpcode(); + assert(RetOpcode == AAP::JMP && + "Epilogue can only be inserted in returning blocks"); + + // Number of bytes to dealloc from FrameInfo + const uint64_t StackSize = MFrameInfo->getStackSize(); + uint64_t NumBytes = StackSize - MFuncInfo->getCalleeSavedFrameSize(); + + const unsigned SP = AAPRegisterInfo::getStackPtrRegister(); + + assert(!hasFP(MF) && "Frame pointer unsupported!"); + + if (NumBytes) { + // otherwise adjust by adding back the frame size + const uint64_t Addend = NumBytes % 1023; + const uint64_t NumChunks = NumBytes / 1023; + + for (uint64_t i = 0; i < NumChunks; ++i) { + BuildMI(MBB, MBBI, DL, TII.get(AAP::ADD_i10), SP) + .addReg(SP) + .addImm(1023); + } + if (Addend) { + BuildMI(MBB, MBBI, DL, TII.get(AAP::ADD_i10), SP) + .addReg(SP) + .addImm(Addend); + } + } +} + +bool AAPFrameLowering::spillCalleeSavedRegisters( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) { + return false; + } + + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + AAPMachineFunctionInfo *MFuncInfo = MF.getInfo(); + + DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); + + // Each spilled register is 2 bytes less adjustment to SP + MFuncInfo->setCalleeSavedFrameSize(CSI.size() * 2); + + for (unsigned i = CSI.size(); i != 0; --i) { + unsigned Reg = CSI[i - 1].getReg(); + + // Add Callee-saved register as live-in. It's killed by the spill + const unsigned SP = AAPRegisterInfo::getStackPtrRegister(); + MBB.addLiveIn(Reg); + BuildMI(MBB, MI, DL, TII.get(AAP::STW_predec)) + .addReg(SP) + .addImm(0) + .addReg(Reg, RegState::Kill); + } + return true; +} + +bool AAPFrameLowering::restoreCalleeSavedRegisters( + MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const std::vector &CSI, + const TargetRegisterInfo *TRI) const { + if (CSI.empty()) { + return false; + } + + MachineFunction &MF = *MBB.getParent(); + const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + + DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); + + for (unsigned i = 0; i != CSI.size(); ++i) { + unsigned Reg = CSI[i].getReg(); + + const unsigned SP = AAPRegisterInfo::getStackPtrRegister(); + BuildMI(MBB, MI, DL, TII.get(AAP::LDW_postinc), Reg) + .addReg(SP) + .addImm(0); + } + return true; +} + +// This function eliminates ADJCALLSTACKDOWN, +// ADJCALLSTACKUP pseudo instructions +void AAPFrameLowering::eliminateCallFramePseudoInstr( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + assert(!hasFP(MF) && "Frame pointer unsupported!"); + MBB.erase(I); +} + +void AAPFrameLowering::processFunctionBeforeFrameFinalized( + MachineFunction &MF, RegScavenger *RS) const {} Index: lib/Target/AAP/AAPISelDAGToDAG.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPISelDAGToDAG.cpp @@ -0,0 +1,198 @@ +//===-- AAPISelDAGToDAG.cpp - A dag to dag inst selector for AAP ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the AAP target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "AAP-isel" +#include "AAP.h" +#include "AAPMachineFunctionInfo.h" +#include "AAPRegisterInfo.h" +#include "AAPSubtarget.h" +#include "AAPTargetMachine.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// AAPDAGToDAGISel - AAP specific code to select AAP machine +// instructions for SelectionDAG operations. +//===----------------------------------------------------------------------===// +namespace { + +class AAPDAGToDAGISel : public SelectionDAGISel { + + /// TM - Keep a reference to AAPTargetMachine. + AAPTargetMachine &TM; + +public: + AAPDAGToDAGISel(AAPTargetMachine &tm, CodeGenOpt::Level OptLevel) + : SelectionDAGISel(tm), TM(tm) {} + + // Pass Name + virtual const char *getPassName() const { + return "AAP DAG->DAG Pattern Instruction Selection"; + } + +// Include the pieces autogenerated from the target description. +#include "AAPGenDAGISel.inc" + +private: + /// getTargetMachine - Return a reference to the TargetMachine, casted + /// to the target-specific type. + const AAPTargetMachine &getTargetMachine() { + return static_cast(TM); + } + + SDNode *Select(SDNode *N); + + // Complex Pattern for address selection. + bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset); + bool SelectAddr_MO3(SDValue Addr, SDValue &Base, SDValue &Offset); + bool SelectAddr_MO10(SDValue Addr, SDValue &Base, SDValue &Offset); +}; +} // end anonymous namespace + +/// Select instructions not customized! Used for +/// expanded, promoted and normal instructions +SDNode *AAPDAGToDAGISel::Select(SDNode *Node) { + unsigned Opcode = Node->getOpcode(); + SDLoc dl(Node); + + // Dump information about the Node being selected + DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); + + // If we have a custom node, we already have selected! + if (Node->isMachineOpcode()) { + DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); + return NULL; + } + + /// + // Instruction Selection not handled by the auto-generated + // tablegen selection should be handled here. + /// + switch (Opcode) { + case ISD::FrameIndex: { + assert(Node->getValueType(0) == MVT::i16); + + int FI = cast(Node)->getIndex(); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16); + + // Handle single use + return CurDAG->getMachineNode(AAP::LEA, dl, MVT::i16, TFI, + CurDAG->getTargetConstant(0, dl, MVT::i16)); + } + default: + break; + } + + // Select the default instruction + SDNode *ResNode = SelectCode(Node); + + DEBUG(errs() << "=> "); + if (ResNode == NULL || ResNode == Node) + DEBUG(Node->dump(CurDAG)); + else + DEBUG(ResNode->dump(CurDAG)); + DEBUG(errs() << "\n"); + return ResNode; +} + +static bool isImm3(int64_t Imm) { return (Imm >= 0 && Imm <= 7); } +static bool isOff10(int64_t Imm) { return (Imm >= -512 && Imm <= 511); } + +bool AAPDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { + // if Address is FI, get the TargetFrameIndex + if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { + SDLoc dl(FIN); + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16); + Offset = CurDAG->getTargetConstant(0, dl, MVT::i16); + return true; + } + + if ((Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress)) { + return false; + } + + // Addresses of the form FI+const or FI|const + if (CurDAG->isBaseWithConstantOffset(Addr)) { + ConstantSDNode *CN = dyn_cast(Addr.getOperand(1)); + SDLoc dl(CN); + + if (isInt<16>(CN->getSExtValue())) { + // If the first operand is a FI, get the TargetFI Node + if (FrameIndexSDNode *FIN = + dyn_cast(Addr.getOperand(0))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16); + } else { + Base = Addr.getOperand(0); + } + + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), dl, MVT::i16); + return true; + } + } + return false; +} + +bool AAPDAGToDAGISel::SelectAddr_MO3(SDValue Addr, SDValue &Base, + SDValue &Offset) { + SDValue B, O; + bool ret = SelectAddr(Addr, B, O); + if (ret && isa(O)) { + int64_t c = dyn_cast(O)->getSExtValue(); + if (isImm3(c)) { + Base = B; + Offset = O; + return true; + } + } + return false; +} +bool AAPDAGToDAGISel::SelectAddr_MO10(SDValue Addr, SDValue &Base, + SDValue &Offset) { + SDValue B, O; + bool ret = SelectAddr(Addr, B, O); + if (ret && isa(O)) { + int64_t c = dyn_cast(O)->getSExtValue(); + if (isOff10(c)) { + Base = B; + Offset = O; + return true; + } + } + return false; +} + +/// createAAPISelDag - This pass converts a legalized DAG into a +/// AAP-specific DAG, ready for instruction scheduling. +FunctionPass *llvm::createAAPISelDag(AAPTargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new AAPDAGToDAGISel(TM, OptLevel); +} Index: lib/Target/AAP/AAPISelLowering.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAPISelLowering.h @@ -0,0 +1,132 @@ +//===-- AAPISelLowering.h - AAP DAG Lowering Interface ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interfaces that AAP uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef AAPISELLOWERING_H +#define AAPISELLOWERING_H + +#include "AAP.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLowering.h" + +namespace llvm { + +// Forward delcarations +class AAPSubtarget; +class AAPTargetMachine; + +namespace AAPISD { +enum NodeType { + // Start the numbering where the builtin ops and target ops leave off. + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + /// Return with a flag operand. Operand 0 is the chain. + RET_FLAG, + + /// CALL - A node to wrap calls. + CALL, + + /// Wrapper - A wrapper node for TargetConstantPool, TargetExternalSymbol, + /// and TargetGlobalAddress. + Wrapper, + + /// BR_CC - Custom brcc node, where the condition code is an AAP + /// specific value + BR_CC, + + /// SELECT_CC - Custom selectcc node, where the condition code is an + /// AAP specific value + SELECT_CC +}; +} + +//===--------------------------------------------------------------------===// +// TargetLowering Implementation +//===--------------------------------------------------------------------===// +class AAPTargetLowering : public TargetLowering { +public: + explicit AAPTargetLowering(const TargetMachine &TM, const AAPSubtarget &STI); + + /// LowerOperation - Provide custom lowering hooks for some operations. + SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; + + /// ReplaceNodeResults - Replace the results of node with an illegal result + /// type with new values built out of custom code. + /// + // void ReplaceNodeResults(SDNode *N, SmallVectorImpl&Results, + // SelectionDAG &DAG) const override; + + /// getTargetNodeName - This method returns the name of a target specific + // DAG node. + const char *getTargetNodeName(unsigned Opcode) const override; + + /// Custom lowering + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; + + MachineBasicBlock * + EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB) const override; + +private: + MachineBasicBlock *emitBrCC(MachineInstr *MI, MachineBasicBlock *MBB) const; + MachineBasicBlock *emitSelectCC(MachineInstr *MI, + MachineBasicBlock *MBB) const; + + SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, SDLoc dl, + SelectionDAG &DAG, + SmallVectorImpl &InVals) const; + + SDValue LowerCCCArguments(SDValue Chain, CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl &Ins, SDLoc dl, + SelectionDAG &DAG, + SmallVectorImpl &InVals) const; + + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, SDLoc dl, + SelectionDAG &DAG, + SmallVectorImpl &InVals) const; + + SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl &Ins, + SDLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const override; + SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, + SmallVectorImpl &InVals) const override; + + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, SDLoc dl, + SelectionDAG &DAG) const override; + + TargetLowering::ConstraintType + getConstraintType(const StringRef Constraint) const override; + + std::pair + getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + StringRef Constraint, + MVT VT) const override; +}; +} + +#endif Index: lib/Target/AAP/AAPISelLowering.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPISelLowering.cpp @@ -0,0 +1,900 @@ +//===-- AAPISelLowering.cpp - AAP DAG Lowering Implementation ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AAPTargetLowering class. +// +//===----------------------------------------------------------------------===// + +#include "AAPISelLowering.h" +#include "AAP.h" +#include "AAPMachineFunctionInfo.h" +#include "AAPSubtarget.h" +#include "AAPTargetMachine.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalAlias.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "aap-lower" + +AAPTargetLowering::AAPTargetLowering(const TargetMachine &TM, + const AAPSubtarget &STI) + : TargetLowering(TM) { + + // Set up the register classes. + addRegisterClass(MVT::i16, &AAP::GR8RegClass); + addRegisterClass(MVT::i16, &AAP::GR64RegClass); + computeRegisterProperties(STI.getRegisterInfo()); + + setStackPointerRegisterToSaveRestore(AAP::R1); + setBooleanContents(ZeroOrOneBooleanContent); + setBooleanVectorContents(ZeroOrOneBooleanContent); + + // We have post-incremented loads / stores. + // setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal); + // setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal); + + // Only basic load with zero extension i8 -> i16 is supported + // Note: EXTLOAD promotion will trigger an assertion + setLoadExtAction(ISD::EXTLOAD, MVT::i8, MVT::i1, Promote); + setLoadExtAction(ISD::EXTLOAD, MVT::i16, MVT::i1, Promote); + + setLoadExtAction(ISD::ZEXTLOAD, MVT::i8, MVT::i1, Expand); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, MVT::i1, Expand); + + setLoadExtAction(ISD::SEXTLOAD, MVT::i8, MVT::i1, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i16, MVT::i1, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i16, MVT::i8, Expand); + + + setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); + + // Handle conditionals via brcc and selectcc + setOperationAction(ISD::BRCOND, MVT::i8, Expand); + setOperationAction(ISD::BRCOND, MVT::i16, Expand); + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + + setOperationAction(ISD::SELECT, MVT::i8, Expand); + setOperationAction(ISD::SELECT, MVT::i16, Expand); + setOperationAction(ISD::SELECT, MVT::Other, Expand); + + setOperationAction(ISD::SETCC, MVT::i8, Expand); + setOperationAction(ISD::SETCC, MVT::i16, Expand); + setOperationAction(ISD::SETCC, MVT::Other, Expand); + + setOperationAction(ISD::SELECT_CC, MVT::i8, Promote); + setOperationAction(ISD::SELECT_CC, MVT::i16, Custom); + setOperationAction(ISD::BR_CC, MVT::i8, Promote); + setOperationAction(ISD::BR_CC, MVT::i16, Custom); + + // Currently no support for indirect branches + setOperationAction(ISD::BRIND, MVT::Other, Expand); + + // No support for jump tables + setOperationAction(ISD::JumpTable, MVT::i8, Expand); + setOperationAction(ISD::JumpTable, MVT::i16, Expand); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + + // vaarg + setOperationAction(ISD::VASTART, MVT::Other, Custom); + setOperationAction(ISD::VAARG, MVT::Other, Expand); + setOperationAction(ISD::VAEND, MVT::Other, Expand); + setOperationAction(ISD::VACOPY, MVT::Other, Expand); + + // ALU operations unsupported by the architecture + setOperationAction(ISD::SDIV, MVT::i8, Expand); + setOperationAction(ISD::SDIV, MVT::i16, Expand); + setOperationAction(ISD::UDIV, MVT::i8, Expand); + setOperationAction(ISD::UDIV, MVT::i16, Expand); + setOperationAction(ISD::UREM, MVT::i8, Expand); + setOperationAction(ISD::UREM, MVT::i16, Expand); + setOperationAction(ISD::SREM, MVT::i8, Expand); + setOperationAction(ISD::SREM, MVT::i16, Expand); + setOperationAction(ISD::SDIVREM, MVT::i8, Expand); + setOperationAction(ISD::SDIVREM, MVT::i16, Expand); + setOperationAction(ISD::UDIVREM, MVT::i8, Expand); + setOperationAction(ISD::UDIVREM, MVT::i16, Expand); + + setOperationAction(ISD::MUL, MVT::i8, Expand); + setOperationAction(ISD::MUL, MVT::i16, Expand); + setOperationAction(ISD::MULHS, MVT::i8, Expand); + setOperationAction(ISD::MULHS, MVT::i16, Expand); + setOperationAction(ISD::MULHU, MVT::i8, Expand); + setOperationAction(ISD::MULHU, MVT::i16, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand); + + // Use ADDE/SUBE + setOperationAction(ISD::SUBC, MVT::i8, Expand); + setOperationAction(ISD::SUBC, MVT::i16, Expand); + + setOperationAction(ISD::ROTL, MVT::i8, Expand); + setOperationAction(ISD::ROTL, MVT::i16, Expand); + setOperationAction(ISD::ROTR, MVT::i8, Expand); + setOperationAction(ISD::ROTR, MVT::i16, Expand); + + setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand); + setOperationAction(ISD::SHL_PARTS, MVT::i16, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i16, Expand); + + setOperationAction(ISD::BSWAP, MVT::i8, Expand); + setOperationAction(ISD::BSWAP, MVT::i16, Expand); + + setOperationAction(ISD::CTTZ, MVT::i8, Expand); + setOperationAction(ISD::CTTZ, MVT::i16, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i8, Expand); + setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i16, Expand); + setOperationAction(ISD::CTLZ, MVT::i8, Expand); + setOperationAction(ISD::CTLZ, MVT::i16, Expand); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i8, Expand); + setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i16, Expand); + setOperationAction(ISD::CTPOP, MVT::i8, Expand); + setOperationAction(ISD::CTPOP, MVT::i16, Expand); + + + setMinFunctionAlignment(1); + setPrefFunctionAlignment(2); +} + +SDValue AAPTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { + switch (Op.getOpcode()) { + case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::BR_CC: return LowerBR_CC(Op, DAG); + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + case ISD::VASTART: return LowerVASTART(Op, DAG); + } + llvm_unreachable("unimplemented operand"); +} + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "AAPGenCallingConv.inc" + +/// For each argument in a function store the number of pieces it is composed +/// of. +template +static void ParseFunctionArgs(const SmallVectorImpl &Args, + SmallVectorImpl &Out) { + unsigned CurrentArgIndex = ~0U; + for (unsigned i = 0, e = Args.size(); i != e; i++) { + if (CurrentArgIndex == Args[i].OrigArgIndex) { + Out.back()++; + } else { + Out.push_back(1); + CurrentArgIndex++; + } + } +} + +SDValue AAPTargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, SDLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + + switch (CallConv) { + default: + llvm_unreachable("Unsupported calling convention"); + case CallingConv::C: + case CallingConv::Fast: + return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals); + } +} + +SDValue AAPTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, + SmallVectorImpl &InVals) const { + SelectionDAG &DAG = CLI.DAG; + SDLoc &dl = CLI.DL; + SmallVectorImpl &Outs = CLI.Outs; + SmallVectorImpl &OutVals = CLI.OutVals; + SmallVectorImpl &Ins = CLI.Ins; + SDValue Chain = CLI.Chain; + SDValue Callee = CLI.Callee; + bool &isTailCall = CLI.IsTailCall; + CallingConv::ID CallConv = CLI.CallConv; + bool isVarArg = CLI.IsVarArg; + + // AAP target does not yet support tail call optimization. + isTailCall = false; + + switch (CallConv) { + default: + llvm_unreachable("Unsupported calling convention"); + case CallingConv::Fast: + case CallingConv::C: + return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall, Outs, + OutVals, Ins, dl, DAG, InVals); + } +} + +/// LowerCCCArguments - transform physical registers into virtual registers and +/// generate load operations for arguments places on the stack. +SDValue AAPTargetLowering::LowerCCCArguments( + SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, SDLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + AAPMachineFunctionInfo *FuncInfo = MF.getInfo(); + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext()); + CCInfo.AnalyzeFormalArguments(Ins, CC_AAP); + + // Create frame index for the start of the first vararg value + if (isVarArg) { + unsigned Offset = CCInfo.getNextStackOffset(); + FuncInfo->setVarArgsFrameIndex(MFI->CreateFixedObject(1, Offset, true)); + } + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + if (VA.isRegLoc()) { + // Arguments passed in registers + EVT RegVT = VA.getLocVT(); + switch (RegVT.getSimpleVT().SimpleTy) { + default: { +#ifndef NDEBUG + errs() << "LowerFormalArguments Unhandled argument type: " + << RegVT.getSimpleVT().SimpleTy << "\n"; +#endif + llvm_unreachable(0); + } + case MVT::i16: + unsigned VReg = RegInfo.createVirtualRegister(&AAP::GR64RegClass); + RegInfo.addLiveIn(VA.getLocReg(), VReg); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); + + // If this is an 8-bit value, it is really passed promoted to 16 + // bits. Insert an assert[sz]ext to capture this, then truncate to the + // right size. + if (VA.getLocInfo() == CCValAssign::SExt) + ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + else if (VA.getLocInfo() == CCValAssign::ZExt) + ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + + if (VA.getLocInfo() != CCValAssign::Full) + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + + InVals.push_back(ArgValue); + } + } else { + // Sanity check + assert(VA.isMemLoc()); + + SDValue InVal; + ISD::ArgFlagsTy Flags = Ins[i].Flags; + + if (Flags.isByVal()) { + int FI = MFI->CreateFixedObject(Flags.getByValSize(), + VA.getLocMemOffset(), true); + InVal = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); + } else { + // Load the argument to a virtual register + unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8; + if (ObjSize > 2) { + errs() << "LowerFormalArguments Unhandled argument type: " + << EVT(VA.getLocVT()).getEVTString() << "\n"; + } + // Create the frame index object for this incoming parameter... + int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); + + // Create the SelectionDAG nodes corresponding to a load + // from this parameter + SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); + InVal = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, + MachinePointerInfo::getFixedStack(MF, FI), + false, false, + false, 0); + } + + InVals.push_back(InVal); + } + } + + return Chain; +} + +SDValue +AAPTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + SDLoc dl, SelectionDAG &DAG) const { + + // CCValAssign - represent the assignment of the return value to a location + SmallVector RVLocs; + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, + *DAG.getContext()); + + // Analize return values. + CCInfo.AnalyzeReturn(Outs, RetCC_AAP); + + SDValue Flag; + SmallVector RetOps(1, Chain); + + // Add the link register as the first operand + RetOps.push_back( + DAG.getRegister(AAPRegisterInfo::getLinkRegister(), MVT::i16)); + + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag); + + // Guarantee that all emitted copies are stuck together, + // avoiding something bad. + Flag = Chain.getValue(1); + RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); + } + + RetOps[0] = Chain; // Update chain. + + // Add the flag if we have it. + if (Flag.getNode()) + RetOps.push_back(Flag); + + return DAG.getNode(AAPISD::RET_FLAG, dl, {MVT::Other, MVT::i16}, RetOps); +} + +/// LowerCCCCallTo - functions arguments are copied from virtual regs to +/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. +SDValue AAPTargetLowering::LowerCCCCallTo( + SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, + bool isTailCall, const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, SDLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + const DataLayout& DL = DAG.getDataLayout(); + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, + *DAG.getContext()); + + CCInfo.AnalyzeCallOperands(Outs, CC_AAP); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + + Chain = DAG.getCALLSEQ_START( + Chain, DAG.getConstant(NumBytes, dl, getPointerTy(DL), true), dl); + + SmallVector, 4> RegsToPass; + SmallVector MemOpChains; + SDValue StackPtr; + + // Walk the register/memloc assignments, inserting copies/loads. + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + SDValue Arg = OutVals[i]; + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: + llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: + break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); + break; + } + + // Arguments that can be passed on register must be kept at RegsToPass + // vector + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + assert(VA.isMemLoc()); + + if (StackPtr.getNode() == 0) + StackPtr = DAG.getCopyFromReg(Chain, dl, + AAPRegisterInfo::getStackPtrRegister(), + getPointerTy(DL)); + + SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(DL), StackPtr, + DAG.getIntPtrConstant( + VA.getLocMemOffset(), dl)); + + SDValue MemOp; + ISD::ArgFlagsTy Flags = Outs[i].Flags; + + if (Flags.isByVal()) { + SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i16); + MemOp = DAG.getMemcpy( + Chain, dl, PtrOff, Arg, SizeNode, Flags.getByValAlign(), + /*isVolatile*/ false, + /*AlwaysInline*/ true, + /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo()); + } else { + MemOp = DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo(), + false, false, 0); + } + + MemOpChains.push_back(MemOp); + } + } + + // Transform all store nodes into one single node because all store nodes are + // independent of each other. + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); + + // Build a sequence of copy-to-reg nodes chained together with token chain and + // flag operands which copy the outgoing args into registers. The InFlag in + // necessary since all emitted instructions must be stuck together. + SDValue InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // If the callee is a GlobalAddress node (quite common, every direct call is) + // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. + // Likewise ExternalSymbol -> TargetExternalSymbol. + if (GlobalAddressSDNode *G = dyn_cast(Callee)) + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i16); + else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) + Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i16); + + // Returns a chain & a flag for retval copy to use. + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + SmallVector Ops; + // Add the link register as a return + Ops.push_back(Chain); + Ops.push_back(Callee); + Ops.push_back(DAG.getRegister(AAPRegisterInfo::getLinkRegister(), MVT::i16)); + + + // Add argument registers to the end of the list so that they are + // known live into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + + if (InFlag.getNode()) + Ops.push_back(InFlag); + + Chain = DAG.getNode(AAPISD::CALL, dl, NodeTys, Ops); + InFlag = Chain.getValue(1); + + // Create the CALLSEQ_END node. + Chain = + DAG.getCALLSEQ_END(Chain, + DAG.getConstant(NumBytes, dl, getPointerTy(DL), true), + DAG.getConstant(0, dl, getPointerTy(DL), true), + InFlag, dl); + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG, + InVals); +} + +/// LowerCallResult - Lower the result values of a call into the +/// appropriate copies out of appropriate physical registers. +/// +SDValue AAPTargetLowering::LowerCallResult( + SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, SDLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + + // Assign locations to each value returned by this call. + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, + *DAG.getContext()); + + CCInfo.AnalyzeCallResult(Ins, RetCC_AAP); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), + RVLocs[i].getValVT(), InFlag) + .getValue(1); + InFlag = Chain.getValue(2); + InVals.push_back(Chain.getValue(0)); + } + + return Chain; +} + +// Get the AAP specific condition code for a given CondCode DAG node. +// The first element of the pair is a bool dictating whether the returned +// condition code requires the operands to be swapped. +// The second element of the pair is the equivalent AAP condition code +static std::pair getAAPCondCode(ISD::CondCode CC) { + AAPCC::CondCode TargetCC; + bool shouldSwapOps; + + switch (CC) { + // These have a direct equivalent + case ISD::SETEQ: + TargetCC = AAPCC::COND_EQ; + break; + case ISD::SETNE: + TargetCC = AAPCC::COND_NE; + break; + case ISD::SETLT: + TargetCC = AAPCC::COND_LTS; + break; + case ISD::SETGT: + TargetCC = AAPCC::COND_GTS; + break; + case ISD::SETULT: + TargetCC = AAPCC::COND_LTU; + break; + case ISD::SETUGT: + TargetCC = AAPCC::COND_GTU; + break; + + // These require lhs/rhs to be swapped, therefore the condition returned + // is inverted + case ISD::SETLE: + TargetCC = AAPCC::COND_GTS; + break; + case ISD::SETGE: + TargetCC = AAPCC::COND_LTS; + break; + case ISD::SETULE: + TargetCC = AAPCC::COND_GTU; + break; + case ISD::SETUGE: + TargetCC = AAPCC::COND_LTU; + break; + default: + llvm_unreachable("Unknown condition for brcc lowering"); + } + + shouldSwapOps = (CC == ISD::SETLE) || (CC == ISD::SETGE) || + (CC == ISD::SETULE) || (CC == ISD::SETUGE); + + return std::make_pair(shouldSwapOps, TargetCC); +} + +// Map the generic BR_CC instruction to a specific branch instruction based +// on the provided AAP condition code +static unsigned getBranchOpForCondition(int branchOp, AAPCC::CondCode CC) { + assert(branchOp == AAP::BR_CC || branchOp == AAP::BR_CC); + + if (branchOp == AAP::BR_CC) { + switch (CC) { + case AAPCC::COND_EQ: + branchOp = AAP::BEQ_; + break; + case AAPCC::COND_NE: + branchOp = AAP::BNE_; + break; + case AAPCC::COND_LTS: + branchOp = AAP::BLTS_; + break; + case AAPCC::COND_GTS: + branchOp = AAP::BGTS_; + break; + case AAPCC::COND_LTU: + branchOp = AAP::BLTU_; + break; + case AAPCC::COND_GTU: + branchOp = AAP::BGTU_; + break; + default: + llvm_unreachable("Unknown condition code!"); + } + } else { + switch (CC) { + case AAPCC::COND_EQ: + branchOp = AAP::BEQ_; + break; + case AAPCC::COND_NE: + branchOp = AAP::BNE_; + break; + case AAPCC::COND_LTS: + branchOp = AAP::BLTS_; + break; + case AAPCC::COND_GTS: + branchOp = AAP::BGTS_; + break; + case AAPCC::COND_LTU: + branchOp = AAP::BLTU_; + break; + case AAPCC::COND_GTU: + branchOp = AAP::BGTU_; + break; + default: + llvm_unreachable("Unknown condition code!"); + } + } + return branchOp; +} + +SDValue AAPTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { + SDLoc dl(Op); + SDValue Chain = Op.getOperand(0); + ISD::CondCode CC = cast(Op.getOperand(1))->get(); + SDValue LHS = Op.getOperand(2); + SDValue RHS = Op.getOperand(3); + SDValue BranchTarget = Op.getOperand(4); + + // get equivalent AAP condition code, swap operands if necessary + std::pair CCPair = getAAPCondCode(CC); + bool SwapOperands = CCPair.first; + AAPCC::CondCode TargetCC = CCPair.second; + + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(DAG.getConstant(TargetCC, dl, MVT::i16)); + if (!SwapOperands) { + Ops.push_back(LHS); + Ops.push_back(RHS); + } else { + Ops.push_back(RHS); + Ops.push_back(LHS); + } + Ops.push_back(BranchTarget); + return DAG.getNode(AAPISD::BR_CC, dl, Op.getValueType(), Ops); +} + +SDValue AAPTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { + SDLoc dl(Op); + + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + SDValue TrueValue = Op.getOperand(2); + SDValue FalseValue = Op.getOperand(3); + ISD::CondCode CC = cast(Op.getOperand(4))->get(); + + // get equivalent AAP condition code, swap operands if necessary + std::pair CCPair = getAAPCondCode(CC); + bool SwapOperands = CCPair.first; + AAPCC::CondCode TargetCC = CCPair.second; + + SmallVector Ops; + if (!SwapOperands) { + Ops.push_back(LHS); + Ops.push_back(RHS); + } else { + Ops.push_back(RHS); + Ops.push_back(LHS); + } + Ops.push_back(TrueValue); + Ops.push_back(FalseValue); + Ops.push_back(DAG.getConstant(TargetCC, dl, MVT::i16)); + return DAG.getNode(AAPISD::SELECT_CC, dl, Op.getValueType(), Ops); +} + +SDValue AAPTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { + MachineFunction &MF = DAG.getMachineFunction(); + AAPMachineFunctionInfo *MFI = MF.getInfo(); + const DataLayout& DL = DAG.getDataLayout(); + + // Frame index of first vaarg argument + SDValue FrameIndex = DAG.getFrameIndex(MFI->getVarArgsFrameIndex(), + getPointerTy(DL)); + const Value *Src = cast(Op.getOperand(2))->getValue(); + + // Create a store of the frame index to the location operand + return DAG.getStore(Op.getOperand(0), SDLoc(Op), FrameIndex, + Op.getOperand(1), MachinePointerInfo(Src), + false, false, 0); +} + +SDValue AAPTargetLowering::LowerGlobalAddress(SDValue Op, + SelectionDAG &DAG) const { + const DataLayout DL = DAG.getDataLayout(); + const GlobalValue *GV = cast(Op)->getGlobal(); + int64_t Offset = cast(Op)->getOffset(); + + // Create the TargetGlobalAddress node, folding in the constant offset. + SDValue Result = + DAG.getTargetGlobalAddress(GV, SDLoc(Op), getPointerTy(DL), Offset); + return DAG.getNode(AAPISD::Wrapper, SDLoc(Op), getPointerTy(DL), Result); +} + + +//===----------------------------------------------------------------------===// +// AAP Inline Assembly Support +//===----------------------------------------------------------------------===// + +/// getConstraintType - Given a constraint letter, return the type of +/// constraint it is for this target +TargetLowering::ConstraintType +AAPTargetLowering::getConstraintType(StringRef Constraint) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: + break; + case 'r': + return C_RegisterClass; + } + } + return TargetLowering::getConstraintType(Constraint); +} + +std::pair +AAPTargetLowering:: +getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + StringRef Constraint, + MVT VT) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: + break; + case 'r': + // General purpose registers + return std::make_pair(0U, &AAP::GR64RegClass); + } + } + return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); +} + + +MachineBasicBlock * +AAPTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB) const { + switch (MI->getOpcode()) { + case AAP::BR_CC: + case AAP::BR_CC_short: + return emitBrCC(MI, MBB); + case AAP::SELECT_CC: + return emitSelectCC(MI, MBB); + default: + llvm_unreachable("Unexpected instruction for custom insertion"); + } +} + +MachineBasicBlock *AAPTargetLowering::emitBrCC(MachineInstr *MI, + MachineBasicBlock *MBB) const { + const TargetInstrInfo *TII = MBB->getParent()->getSubtarget().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + AAPCC::CondCode CC = (AAPCC::CondCode)MI->getOperand(0).getImm(); + + unsigned lhsReg = MI->getOperand(1).getReg(); + unsigned rhsReg = MI->getOperand(2).getReg(); + MachineBasicBlock *targetMBB = MI->getOperand(3).getMBB(); + + unsigned branchOp = getBranchOpForCondition(MI->getOpcode(), CC); + BuildMI(*MBB, MI, dl, TII->get(branchOp)) + .addMBB(targetMBB) + .addReg(lhsReg) + .addReg(rhsReg); + + MI->eraseFromParent(); + return MBB; +} + +MachineBasicBlock * +AAPTargetLowering::emitSelectCC(MachineInstr *MI, + MachineBasicBlock *MBB) const { + const TargetInstrInfo *TII = MBB->getParent()->getSubtarget().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + + // insert a diamond control flow pattern to handle the select + const BasicBlock *llvmBB = MBB->getBasicBlock(); + MachineFunction::iterator It = MBB; + ++It; + + MachineBasicBlock *entryMBB = MBB; + MachineFunction *MF = MBB->getParent(); + MachineBasicBlock *trueValueMBB = MF->CreateMachineBasicBlock(llvmBB); + MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(llvmBB); + MF->insert(It, trueValueMBB); + MF->insert(It, sinkMBB); + + // Transfer remainder of entryBB to sinkMBB + sinkMBB->splice(sinkMBB->begin(), entryMBB, + std::next(MachineBasicBlock::iterator(MI)), entryMBB->end()); + sinkMBB->transferSuccessorsAndUpdatePHIs(entryMBB); + + // Add true value and fallthrough blocks as successors + entryMBB->addSuccessor(trueValueMBB); + entryMBB->addSuccessor(sinkMBB); + + // Choose the branch instruction to use based on the condition code + // For now, always use the long instructions + AAPCC::CondCode CC = (AAPCC::CondCode)MI->getOperand(5).getImm(); + unsigned branchOp; + switch (CC) { + case AAPCC::COND_EQ: + branchOp = AAP::BEQ_; + break; + case AAPCC::COND_NE: + branchOp = AAP::BNE_; + break; + case AAPCC::COND_LTS: + branchOp = AAP::BLTS_; + break; + case AAPCC::COND_GTS: + branchOp = AAP::BGTS_; + break; + case AAPCC::COND_LTU: + branchOp = AAP::BLTU_; + break; + case AAPCC::COND_GTU: + branchOp = AAP::BGTU_; + break; + default: + llvm_unreachable("Unknown condition code!"); + } + + unsigned inReg = MI->getOperand(0).getReg(); + unsigned lhsReg = MI->getOperand(1).getReg(); + unsigned rhsReg = MI->getOperand(2).getReg(); + BuildMI(entryMBB, dl, TII->get(branchOp)) + .addMBB(trueValueMBB) + .addReg(lhsReg) + .addReg(rhsReg); + + trueValueMBB->addSuccessor(sinkMBB); + + unsigned trueValueReg = MI->getOperand(3).getReg(); + unsigned falseValueReg = MI->getOperand(4).getReg(); + BuildMI(*sinkMBB, sinkMBB->begin(), dl, TII->get(AAP::PHI), inReg) + .addReg(trueValueReg) + .addMBB(trueValueMBB) + .addReg(falseValueReg) + .addMBB(entryMBB); + + MI->eraseFromParent(); + return sinkMBB; +} + +const char *AAPTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + default: + return nullptr; + case AAPISD::RET_FLAG: + return "AAPISD::RET_FLAG"; + case AAPISD::CALL: + return "AAPISD::CALL"; + case AAPISD::Wrapper: + return "AAPISD::Wrapper"; + case AAPISD::SELECT_CC: + return "AAPISD::SELECT_CC"; + } +} Index: lib/Target/AAP/AAPInstrFormats.td =================================================================== --- /dev/null +++ lib/Target/AAP/AAPInstrFormats.td @@ -0,0 +1,295 @@ +//===- AAPInstrFormats.td - AAP Instruction Formats ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// Instruction Format Superclasses +//===----------------------------------------------------------------------===// + +class InstAAP_base opclass, dag outs, dag ins, + string asmstr, list pattern> + : Instruction { + let Namespace = "AAP"; + + dag OutOperandList = outs; + dag InOperandList = ins; + let AsmString = asmstr; + let Pattern = pattern; + + let Size = 4; + field bits<32> Inst; + field bits<32> SoftFail = 0; + + let Inst{31} = 0; + let Inst{15} = 1; + let Inst{14-13} = opclass{1-0}; + let Inst{30-29} = opclass{3-2}; +} + + +class InstAAP opclass, bits<8> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_base { + let Inst{12-9} = opcode{3-0}; + let Inst{28-25} = opcode{7-4}; +} + + +class InstAAP_short opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : Instruction { + let Namespace = "AAP"; + + dag OutOperandList = outs; + dag InOperandList = ins; + let AsmString = asmstr; + let Pattern = pattern; + + let Size = 2; + field bits<16> Inst; + field bits<16> SoftFail = 0; + + let Inst{15} = 0; + let Inst{14-13} = opclass; + let Inst{12-9} = opcode; +} + + +//===----------------------------------------------------------------------===// +// Instruction Formats +//===----------------------------------------------------------------------===// + +class Inst_rrr opclass, bits<8> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP { + bits<6> rD; + bits<6> rA; + bits<6> rB; + let Inst{8-6} = rD{2-0}; + let Inst{24-22} = rD{5-3}; + let Inst{5-3} = rA{2-0}; + let Inst{21-19} = rA{5-3}; + let Inst{2-0} = rB{2-0}; + let Inst{18-16} = rB{5-3}; +} +class Inst_rrr_short opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_short { + bits<3> rD; + bits<3> rA; + bits<3> rB; + let Inst{8-6} = rD; + let Inst{5-3} = rA; + let Inst{2-0} = rB; +} + + +class Inst_rr opclass, bits<8> opcode, dag outs, dag ins, + string asmstr, list pattern> + : Inst_rrr { + let rB = 0; +} +class Inst_rr_short opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : Inst_rrr_short { + let rB = 0; +} + + +class Inst_r opclass, bits<8> opcode, dag outs, dag ins, + string asmstr, list pattern> + : Inst_rr { + let rA = 0; +} +class Inst_r_short opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : Inst_rr_short { + let rA = 0; +} + + +class Inst_rr_i6 opclass, bits<8> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP { + bits<6> rD; + bits<6> rA; + bits<6> imm; + let Inst{8-6} = rD{2-0}; + let Inst{24-22} = rD{5-3}; + let Inst{5-3} = rA{2-0}; + let Inst{21-19} = rA{5-3}; + let Inst{2-0} = imm{2-0}; + let Inst{18-16} = imm{5-3}; +} +class Inst_rr_i3_short opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_short { + bits<3> rD; + bits<3> rA; + bits<3> imm; + let Inst{8-6} = rD; + let Inst{5-3} = rA; + let Inst{2-0} = imm; +} + + +class Inst_rr_i9 opclass, bits<5> opcode, dag outs, dag ins, + string asmstr, listpattern> + : InstAAP_base { + bits<6> rD; + bits<6> rA; + bits<9> imm; + + let Inst{12-9} = opcode{3-0}; // Define low bits of the opcode field + let Inst{25} = opcode{4}; + + let Inst{8-6} = rD{2-0}; + let Inst{24-22} = rD{5-3}; + let Inst{5-3} = rA{2-0}; + let Inst{21-19} = rA{5-3}; + let Inst{2-0} = imm{2-0}; + let Inst{18-16} = imm{5-3}; + let Inst{28-26} = imm{8-6}; // Immediate reuses high bits of opcode field +} +class Inst_rr_i10 opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_base { + bits<6> rD; + bits<6> rA; + bits<10> imm; + + let Inst{12-9} = opcode; // Define low bits of the opcode field + + let Inst{8-6} = rD{2-0}; + let Inst{24-22} = rD{5-3}; + let Inst{5-3} = rA{2-0}; + let Inst{21-19} = rA{5-3}; + let Inst{2-0} = imm{2-0}; + let Inst{18-16} = imm{5-3}; + let Inst{28-25} = imm{9-6}; // Immediate reuses high bits of opcode field +} + + +class Inst_r_i12 opclass, bits<8> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP { + bits<6> rD; + bits<12> imm; + + let Inst{8-6} = rD{2-0}; + let Inst{24-22} = rD{5-3}; + let Inst{5-0} = imm{5-0}; + let Inst{21-16} = imm{11-6}; +} +class Inst_r_i6_short opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_short { + bits<3> rD; + bits<6> imm; + let Inst{8-6} = rD; + let Inst{5-0} = imm; +} + + +class Inst_r_i16 opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_base { + bits<6> rD; + bits<16> imm; + + let Inst{12-9} = opcode; // Define low bits of the opcode field + + let Inst{8-6} = rD{2-0}; + let Inst{24-22} = rD{5-3}; + let Inst{5-0} = imm{5-0}; + let Inst{21-16} = imm{11-6}; + let Inst{28-25} = imm{15-12}; // Imm reuses high bits of opcode field +} + + +class Inst_i18 opclass, bits<8> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP { + bits<18> imm; + let Inst{8-0} = imm{8-0}; + let Inst{24-16} = imm{17-9}; +} +class Inst_i9_short opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_short { + bits<9> imm; + let Inst{8-0} = imm; +} + + +class Inst_i16_r opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_base { + bits<16> imm; + bits<6> rA; + + let Inst{12-9} = opcode; // Define low bits of opcode field + + let Inst{2-0} = imm{2-0}; + let Inst{8-6} = imm{5-3}; + let Inst{18-16} = imm{8-6}; + let Inst{28-22} = imm{15-9}; // Reuse opcode high bits + + let Inst{5-3} = rA{2-0}; + let Inst{21-19} = rA{5-3}; +} +class Inst_i6_r_short opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_short { + bits<6> imm; + bits<3> rA; + let Inst{2-0} = imm{2-0}; + let Inst{8-6} = imm{5-3}; + let Inst{5-3} = rA{2-0}; +} + + +class Inst_i10_rr opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_base { + bits<10> imm; + bits<6> rA; + bits<6> rB; + + let Inst{12-9} = opcode; // Define low bits of opcode field + + let Inst{8-6} = imm{2-0}; + let Inst{28-22} = imm{9-3}; // Reuse top bits of opcode field + let Inst{5-3} = rA{2-0}; + let Inst{21-19} = rA{5-3}; + let Inst{2-0} = rB{2-0}; + let Inst{18-16} = rB{5-3}; +} +class Inst_i3_rr_short opclass, bits<4> opcode, dag outs, dag ins, + string asmstr, list pattern> + : InstAAP_short { + bits<3> imm; + bits<3> rA; + bits<3> rB; + let Inst{8-6} = imm; + let Inst{5-3} = rA; + let Inst{2-0} = rB; +} + + +//===----------------------------------------------------------------------===// +// Pseudo Instruction +//===----------------------------------------------------------------------===// + +let isCodeGenOnly = 1 in { +class Pseudo pattern> + : InstAAP<0x0, 0x0, outs, ins, asmstr, pattern> { + let Inst{31-0} = 0; +} +} Index: lib/Target/AAP/AAPInstrInfo.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAPInstrInfo.h @@ -0,0 +1,79 @@ +//===-- AAPInstrInfo.h - AAP Instruction Information ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the AAP implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef AAPINSTRINFO_H +#define AAPINSTRINFO_H + +#include "AAPRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" + +#define GET_INSTRINFO_HEADER +#include "AAPGenInstrInfo.inc" + +namespace llvm { + +class AAPSubtarget; + +class AAPInstrInfo : public AAPGenInstrInfo { + const AAPRegisterInfo TRI; + virtual void anchor(); + +public: + AAPInstrInfo(AAPSubtarget &STI); + + const TargetRegisterInfo &getRegisterInfo() const { return TRI; } + + unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const override; + + /// isStoreToStackSlot - If the specified machine instruction is a direct + /// store to a stack slot, return the virtual or physical register number of + /// the source reg along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than storing to the stack slot. + unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const override; + + bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const override; + + unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + ArrayRef Cond, + DebugLoc DL) const override; + + unsigned RemoveBranch(MachineBasicBlock &MBB) const override; + + void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + DebugLoc DL, unsigned DestReg, unsigned SrcReg, + bool KillSrc) const override; + + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, unsigned SrcReg, + bool isKill, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const override; + + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, unsigned DestReg, + int FrameIndex, const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const override; + + bool + ReverseBranchCondition(SmallVectorImpl &Cond) const override; +}; +} + +#endif Index: lib/Target/AAP/AAPInstrInfo.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPInstrInfo.cpp @@ -0,0 +1,152 @@ +//===-- AAPInstrInfo.cpp - AAP Instruction Information ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the AAP implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "AAPInstrInfo.h" +#include "AAP.h" +#include "AAPMachineFunctionInfo.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define GET_INSTRINFO_CTOR_DTOR +#include "AAPGenInstrInfo.inc" + +// Pin the vtable to this file. +void AAPInstrInfo::anchor() {} + +AAPInstrInfo::AAPInstrInfo(AAPSubtarget &STI) + : AAPGenInstrInfo(AAP::ADJCALLSTACKDOWN, AAP::ADJCALLSTACKUP), TRI() {} + +/// isLoadFromStackSlot - If the specified machine instruction is a direct +/// load from a stack slot, return the virtual or physical register number of +/// the destination along with the FrameIndex of the loaded stack slot. If +/// not, return 0. This predicate must return 0 if the instruction has +/// any side effects other than loading from the stack slot. +unsigned AAPInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + return 0; +} + +/// isStoreToStackSlot - If the specified machine instruction is a direct +/// store to a stack slot, return the virtual or physical register number of +/// the source reg along with the FrameIndex of the loaded stack slot. If +/// not, return 0. This predicate must return 0 if the instruction has +/// any side effects other than storing to the stack slot. +unsigned AAPInstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { + return 0; +} + +//===----------------------------------------------------------------------===// +// Branch Analysis +//===----------------------------------------------------------------------===// + +bool AAPInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + return true; +} + +unsigned AAPInstrInfo::InsertBranch(MachineBasicBlock &MBB, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + ArrayRef Cond, + DebugLoc DL) const { + return 0; +} + +unsigned AAPInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { return 0; } + +void AAPInstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, DebugLoc DL, + unsigned DestReg, unsigned SrcReg, + bool KillSrc) const { + assert(AAP::GR64RegClass.contains(DestReg) && + AAP::GR64RegClass.contains(DestReg) && + "Impossible register-register copy"); + + // FIXME: If possible with short insn, build that instead + BuildMI(MBB, I, DL, get(AAP::MOV_r), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); +} + +void AAPInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, bool isKill, + int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFrameInfo = *MF.getFrameInfo(); + + DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); + + MachineMemOperand *MMO = MF.getMachineMemOperand( + MachinePointerInfo::getFixedStack(MF, FrameIdx), + MachineMemOperand::MOStore, + MFrameInfo.getObjectSize(FrameIdx), + MFrameInfo.getObjectAlignment(FrameIdx)); + + assert((RC == &AAP::GR8RegClass || RC == &AAP::GR64RegClass) && + "Unknown register class to store to stack slot"); + + BuildMI(MBB, MI, DL, get(AAP::STW)) + .addFrameIndex(FrameIdx) + .addImm(0) + .addReg(SrcReg, getKillRegState(isKill)) + .addMemOperand(MMO); +} + +void AAPInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DstReg, int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + MachineFunction &MF = *MBB.getParent(); + MachineFrameInfo &MFrameInfo = *MF.getFrameInfo(); + + DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc(); + + MachineMemOperand *MMO = MF.getMachineMemOperand( + MachinePointerInfo::getFixedStack(MF, FrameIdx), + MachineMemOperand::MOLoad, + MFrameInfo.getObjectSize(FrameIdx), + MFrameInfo.getObjectAlignment(FrameIdx)); + + assert((RC == &AAP::GR8RegClass || RC == &AAP::GR64RegClass) && + "Unknown register class to store to stack slot"); + + BuildMI(MBB, MI, DL, get(AAP::LDW), DstReg) + .addFrameIndex(FrameIdx) + .addImm(0) + .addMemOperand(MMO); +} + +/// ReverseBranchCondition - Return the inverse opcode of the +/// specified Branch instruction. +bool AAPInstrInfo::ReverseBranchCondition( + SmallVectorImpl &Cond) const { + return false; +} Index: lib/Target/AAP/AAPInstrInfo.td =================================================================== --- /dev/null +++ lib/Target/AAP/AAPInstrInfo.td @@ -0,0 +1,608 @@ +//===-- AAPInstrInfo.td - Target Description for AAP Target ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the AAP instructions in TableGen format. +// +//===----------------------------------------------------------------------===// + +// Call +def sdt_call : SDTypeProfile<0, -1, [SDTCisVT<1, iPTR>, SDTCisVT<1, i16>]>; +def sdt_ret : SDTypeProfile<0, 1, [SDTCisVT<0, i16>]>; +def callflag : SDNode<"AAPISD::CALL", sdt_call, + [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>; +def retflag : SDNode<"AAPISD::RET_FLAG", sdt_ret, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +def sdt_callseqstart : SDCallSeqStart<[SDTCisVT<0, i16>]>; +def sdt_callseqend : SDCallSeqEnd<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; +def callseq_start : SDNode<"ISD::CALLSEQ_START", sdt_callseqstart, + [SDNPHasChain, SDNPOutGlue]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", sdt_callseqend, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; +def sdt_wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, + SDTCisPtrTy<0>]>; +def aapwrapper : SDNode<"AAPISD::Wrapper", sdt_wrapper>; + +def sdt_selectcc : SDTypeProfile<1, 5, [SDTCisSameAs<0, 3>, + SDTCisSameAs<1, 2>, + SDTCisSameAs<3, 4>, + SDTCisVT<5, i16>]>; +def sdt_brcc : SDTypeProfile<0, 4, [SDTCisVT<0, i16>, + SDTCisSameAs<1, 2>, + SDTCisVT<3, OtherVT>]>; +def AAPselectcc : SDNode<"AAPISD::SELECT_CC", sdt_selectcc>; +def AAPbrcc : SDNode<"AAPISD::BR_CC", sdt_brcc, + [SDNPHasChain]>; + + +// Branch Operands +def brtarget : Operand { + let PrintMethod = "printPCRelImmOperand"; + let EncoderMethod = "encodePCRelImmOperand"; +} + + +// Immediate operands. Smaller operands are subclasses of larger ones so they +// are correctly prioritized when disassembling. +// +// Currently we have no custom 'signed' immediates, but it will likely +// be needed in the future to handle branches properly. +// +// A constant immediate is an immediate which cannot be an expression, only +// a constant value. +let RenderMethod = "addImmOperands" in { + def imm16AsmOperand : AsmOperandClass { + let Name = "Imm16"; let SuperClasses = [ImmAsmOperand]; + } + def imm12AsmOperand : AsmOperandClass { + let Name = "Imm12"; let SuperClasses = [imm16AsmOperand]; + } + def off10AsmOperand : AsmOperandClass { + let Name = "Off10"; let SuperClasses = [ImmAsmOperand]; + } + def imm10AsmOperand : AsmOperandClass { + let Name = "Imm10"; let SuperClasses = [imm12AsmOperand]; + } + def imm9AsmOperand : AsmOperandClass { + let Name = "Imm9"; let SuperClasses = [imm10AsmOperand]; + } + def const6AsmOperand : AsmOperandClass { + let Name = "Const6"; let SuperClasses = [imm9AsmOperand]; + } + def imm6AsmOperand : AsmOperandClass { + let Name = "Imm6"; let SuperClasses = [const6AsmOperand]; + } + def const3AsmOperand : AsmOperandClass { + let Name = "Const3"; let SuperClasses = [imm6AsmOperand]; + } +} + +// A constant immediate cannot be an expression, only an absolute value +def const3 : Operand, ImmLeaf= 0 && Imm <= 7; +}]> { + let EncoderMethod = "encodeImm3"; + let ParserMatchClass = const3AsmOperand; +} +def imm6 : Operand, ImmLeaf= 0 && Imm <= 63; +}]> { + let EncoderMethod = "encodeImm6"; + let ParserMatchClass = imm6AsmOperand; +} +def const6 : Operand, ImmLeaf= 0 && Imm <= 63; +}]> { + let EncoderMethod = "encodeImm6"; + let ParserMatchClass = const6AsmOperand; +} +def imm9 : Operand, ImmLeaf= 0 && Imm <= 511; +}]> { + let EncoderMethod = "encodeImm9"; + let ParserMatchClass = imm9AsmOperand; +} +def imm10 : Operand, ImmLeaf= 0 && Imm <= 1023; +}]> { + let EncoderMethod = "encodeImm10"; + let ParserMatchClass = imm10AsmOperand; +} +def off10 : Operand, ImmLeaf= -512 && Imm <= 511; +}]> { + let EncoderMethod = "encodeOff10"; + let ParserMatchClass = off10AsmOperand; +} +def imm12 : Operand, ImmLeaf= 0 && Imm <= 4095; +}]> { + let EncoderMethod = "encodeImm12"; + let ParserMatchClass = imm12AsmOperand; +} +def imm16 : Operand, ImmLeaf= -32768 && Imm <= 65535; +}]> { + let EncoderMethod = "encodeImm16"; + let ParserMatchClass = imm16AsmOperand; +} + + +// Memory offsets consist of a 3 or 10 bit offset and a register operand +def addr_MO3 : ComplexPattern; +def addr_MO10 : ComplexPattern; + + +// Memsrc operand encodings consist of a 16-bit immediate field in the low +// bits, and a 3 or 6 bit register field in the high bits. The encoding +// is exactly the same for predecrement and postincrement address mode. +def memsrc10AsmOperand : AsmOperandClass { + let Name = "MemSrc10"; +} +def memsrc10PostIncAsmOperand : AsmOperandClass { + let Name = "MemSrc10PostInc"; +} +def memsrc10PreDecAsmOperand : AsmOperandClass { + let Name = "MemSrc10PreDec"; +} + +// short memsrc operands subclass the longer ones, as this means they will +// be prioritized when matching assembly. +def memsrc3AsmOperand : AsmOperandClass { + let Name = "MemSrc3"; + let SuperClasses = [memsrc10AsmOperand]; +} +def memsrc3PostIncAsmOperand : AsmOperandClass { + let Name = "MemSrc3PostInc"; + let SuperClasses = [memsrc10PostIncAsmOperand]; +} +def memsrc3PreDecAsmOperand : AsmOperandClass { + let Name = "MemSrc3PreDec"; + let SuperClasses = [memsrc10PreDecAsmOperand]; +} + +let EncoderMethod = "encodeMemSrcOperand", + DecoderMethod = "decodeMemSrcOperand" in { + def memsrc10 : Operand { + let PrintMethod = "printMemSrcOperand"; + let ParserMatchClass = memsrc10AsmOperand; + let MIOperandInfo = (ops GR64, off10); + } + def memsrc10_postinc : Operand { + let PrintMethod = "printMemSrcPostIncOperand"; + let ParserMatchClass = memsrc10PostIncAsmOperand; + let MIOperandInfo = (ops GR64, off10); + } + def memsrc10_predec : Operand { + let PrintMethod = "printMemSrcPreDecOperand"; + let ParserMatchClass = memsrc10PreDecAsmOperand; + let MIOperandInfo = (ops GR64, off10); + } + def memsrc3 : Operand { + let PrintMethod = "printMemSrcOperand"; + let ParserMatchClass = memsrc3AsmOperand; + let MIOperandInfo = (ops GR8, const3); + } + def memsrc3_postinc : Operand { + let PrintMethod = "printMemSrcPostIncOperand"; + let ParserMatchClass = memsrc3PostIncAsmOperand; + let MIOperandInfo = (ops GR8, const3); + } + def memsrc3_predec : Operand { + let PrintMethod = "printMemSrcPreDecOperand"; + let ParserMatchClass = memsrc3PreDecAsmOperand; + let MIOperandInfo = (ops GR8, const3); + } +} + + +//===----------------------------------------------------------------------===// +// MOV Operations +//===----------------------------------------------------------------------===// + +def MOV_r : Inst_rr + <0x0, 0x9, (outs GR64:$rD), (ins GR64:$rA), "mov\t$rD, $rA", []>; + +let AddedComplexity = 123 in { + def MOV_r_short : Inst_rr_short + <0x0, 0x9, (outs GR8:$rD), (ins GR8:$rA), "mov\t$rD, $rA", []>; +} + +def MOV_i16 : Inst_r_i16 + <0x0, 0xf, (outs GR64:$rD), (ins imm16:$imm), "mov\t$rD, $imm", + [(set GR64:$rD, (i16 imm16:$imm))]>; + +let AddedComplexity = 123 in { + def MOV_i6_short : Inst_r_i6_short + <0x0, 0xf, (outs GR8:$rD), (ins const6:$imm), "mov\t$rD, $imm", + [(set GR8:$rD, (i16 const6:$imm))]>; +} + + +//===----------------------------------------------------------------------===// +// ALU/Logical Operations +//===----------------------------------------------------------------------===// + +def NOP : Inst_r_i12 + <0x0, 0x0, (outs), (ins GR64:$rD, imm12:$imm), "nop\t$rD, $imm", []>; + +let AddedComplexity = 123 in { + def NOP_short : Inst_r_i6_short + <0x0, 0x0, (outs), (ins GR8:$rD, const6:$imm), "nop\t$rD, $imm", []>; +} + + +// ALU ops with register operands +multiclass ALU_r opcode, string opname, SDNode OpNode> { + def _r : Inst_rrr + <0x0, opcode, (outs GR64:$rD), (ins GR64:$rA, GR64:$rB), + !strconcat(opname, "\t$rD, $rA, $rB"), + [(set GR64:$rD, (OpNode GR64:$rA, GR64:$rB))]>; + + let AddedComplexity = 123 in { + def _r_short : Inst_rrr_short + <0x0, opcode{3-0}, (outs GR8:$rD), (ins GR8:$rA, GR8:$rB), + !strconcat(opname, "\t$rD, $rA, $rB"), + [(set GR8:$rD, (OpNode GR8:$rA, GR8:$rB))]>; + } +} + + +let isCommutable = 1 in { +let Defs = [PSW] in + defm ADD : ALU_r<0x1, "add", add>; +defm AND : ALU_r<0x3, "and", and>; +defm OR : ALU_r<0x4, "or", or>; +defm XOR : ALU_r<0x5, "xor", xor>; +} + +let Defs = [PSW] in + defm SUB : ALU_r<0x2, "sub", sub>; +defm ASR : ALU_r<0x6, "asr", sra>; +defm LSL : ALU_r<0x7, "lsl", shl>; +defm LSR : ALU_r<0x8, "lsr", srl>; + + +let Uses = [PSW], Defs = [PSW] in { +def ADDC_r : Inst_rrr + <0x0, 0x11, (outs GR64:$rD), (ins GR64:$rA, GR64:$rB), + "addc\t$rD, $rA, $rB", + [(set GR64:$rD, (adde GR64:$rA, GR64:$rB))]>; + +def SUBC_r : Inst_rrr + <0x0, 0x12, (outs GR64:$rD), (ins GR64:$rA, GR64:$rB), + "subc\t$rD, $rA, $rD", + [(set GR64:$rD, (sube GR64:$rA, GR64:$rB))]>; +} + + +// ALU ops with immediates +let Defs = [PSW] in { + +// LEA Pseudo operation, expanded to ADD_i10 or SUB_i10 during frame index +// elimination depending on the sign of the immediate. +def LEA : Pseudo<(outs GR64:$rD), (ins GR64:$rA, imm16:$imm), "#LEA", []>; + +def ADD_i10 : Inst_rr_i10 + <0x0, 0xa, (outs GR64:$rD), (ins GR64:$rA, imm10:$imm), + "add\t$rD, $rA, $imm", + [(set GR64:$rD, (add GR64:$rA, (i16 imm10:$imm)))]>; + +let AddedComplexity = 123 in { + def ADD_i3_short : Inst_rr_i3_short + <0x0, 0xa, (outs GR8:$rD), (ins GR8:$rA, const3:$imm), + "add\t$rD, $rA, $imm", + [(set GR8:$rD, (add GR8:$rA, (i16 const3:$imm)))]>; +} + +def SUB_i10 : Inst_rr_i10 + <0x0, 0xb, (outs GR64:$rD), (ins GR64:$rA, imm10:$imm), + "sub\t$rD, $rA, $imm", + [(set GR64:$rD, (sub GR64:$rA, (i16 imm10:$imm)))]>; + +let AddedComplexity = 123 in { + def SUB_i3_short : Inst_rr_i3_short + <0x0, 0xb, (outs GR8:$rD), (ins GR8:$rA, const3:$imm), + "sub\t$rD, $rA, $imm", + [(set GR8:$rD, (sub GR8:$rA, (i16 const3:$imm)))]>; +} + +} // end of Defs + + +multiclass SHIFT_i opcode, string opname, SDNode OpNode> { + def _i6 : Inst_rr_i6 + <0x0, opcode, (outs GR64:$rD), (ins GR64:$rA, imm6:$imm), + !strconcat(opname, "\t$rD, $rA, $imm"), + [(set GR64:$rD, (OpNode GR64:$rA, (i16 imm6:$imm)))]>; + + let AddedComplexity = 123 in { + def _i3_short : Inst_rr_i3_short + <0x0, opcode{3-0}, (outs GR8:$rD), (ins GR8:$rA, const3:$imm), + !strconcat(opname, "\t$rD, $rA, $imm"), + [(set GR8:$rD, (OpNode GR8:$rA, (i16 const3:$imm)))]>; + } +} +defm ASR : SHIFT_i<0xc, "asr", sra>; +defm LSL : SHIFT_i<0xd, "lsl", shl>; +defm LSR : SHIFT_i<0xe, "lsr", srl>; + + +// Logical operations with immediate +class LOG_i9 opcode, string opname, SDNode OpNode> + : Inst_rr_i9 + <0x0, opcode, (outs GR64:$rD), (ins GR64:$rA, imm9:$imm), + !strconcat(opname, "\t$rD, $rA, $imm"), + [(set GR64:$rD, (OpNode GR64:$rA, (i16 imm9:$imm)))]>; + +def AND_i9 : LOG_i9<0x13, "and", and>; +def OR_i9 : LOG_i9<0x14, "or", or>; +def XOR_i9 : LOG_i9<0x15, "xor", xor>; + + +//===----------------------------------------------------------------------===// +// Load/Store Operations +//===----------------------------------------------------------------------===// + +// TODO: It may be better for the LOAD/STORE classes to be in the formats .td +// TODO: There's quite a lot of duplication here as the Load/Store classes +// end up defining a lot of the fields themselves. + +class LOAD opcode, string opname, dag outs, dag ins> + : InstAAP + <0x1, opcode, outs, ins, !strconcat(opname, "\t$rD, [$src]"), []> { + bits<6> rD; + bits<22> src; // 6-bit reg field, 16 bit imm field + + let Inst{8-6} = rD{2-0}; + let Inst{24-22} = rD{5-3}; + + let Inst{5-3} = src{18-16}; + let Inst{21-19} = src{21-19}; + let Inst{2-0} = src{2-0}; + let Inst{18-16} = src{5-3}; + let Inst{28-25} = src{9-6}; // reuse second word opcode field for offset +} + +class LOAD_short opcode, string opname, dag outs, dag ins> + : InstAAP_short + <0x1, opcode, outs, ins, !strconcat(opname, "\t$rD, [$src]"), []> { + bits<3> rD; + bits<19> src; // 3-bit reg field, 16 bit imm field + + let Inst{8-6} = rD; + let Inst{5-3} = src{18-16}; + let Inst{2-0} = src{2-0}; +} + +class STORE opcode, string opname, dag outs, dag ins> + : InstAAP + <0x1, opcode, outs, ins, !strconcat(opname, "\t[$dst], $rA"), []> { + bits<22> dst; // 6-bit reg field, 16 bit imm field + bits<6> rA; + + let Inst{8-6} = dst{18-16}; + let Inst{24-22} = dst{21-19}; + let Inst{2-0} = dst{2-0}; + let Inst{18-16} = dst{5-3}; + let Inst{28-25} = dst{9-6}; // reuse second word opcode field for offset + + let Inst{5-3} = rA{2-0}; + let Inst{21-19} = rA{5-3}; +} + +class STORE_short opcode, string opname, dag outs, dag ins> + : InstAAP_short + <0x1, opcode, outs, ins, !strconcat(opname, "\t[$dst], $rA"), []> { + bits<19> dst; // 3-bit reg field, 16 bit imm field + bits<3> rA; + + let Inst{8-6} = dst{18-16}; + let Inst{2-0} = dst{2-0}; + let Inst{5-3} = rA; +} + + +// Short instructions use the memsrc3 operand type, which uses a different +// fixup when encoding and a different matching class when parsing assembly. +let mayLoad = 1 in { +def LDB : LOAD<0x0, "ldb", (outs GR64:$rD), (ins memsrc10:$src)>; +def LDW : LOAD<0x4, "ldw", (outs GR64:$rD), (ins memsrc10:$src)>; +def LDB_postinc : LOAD<0x1, "ldb", (outs GR64:$rD), (ins memsrc10_postinc:$src)>; +def LDW_postinc : LOAD<0x5, "ldw", (outs GR64:$rD), (ins memsrc10_postinc:$src)>; +def LDB_predec : LOAD<0x2, "ldb", (outs GR64:$rD), (ins memsrc10_predec:$src)>; +def LDW_predec : LOAD<0x6, "ldw", (outs GR64:$rD), (ins memsrc10_predec:$src)>; + +def LDB_short : LOAD_short<0x0, "ldb", (outs GR8:$rD), (ins memsrc3:$src)>; +def LDW_short : LOAD_short<0x4, "ldw", (outs GR8:$rD), (ins memsrc3:$src)>; +def LDB_postinc_short : LOAD_short<0x1, "ldb", (outs GR8:$rD), (ins memsrc3_postinc:$src)>; +def LDW_postinc_short : LOAD_short<0x5, "ldw", (outs GR8:$rD), (ins memsrc3_postinc:$src)>; +def LDB_predec_short : LOAD_short<0x2, "ldb", (outs GR8:$rD), (ins memsrc3_predec:$src)>; +def LDW_predec_short : LOAD_short<0x6, "ldw", (outs GR8:$rD), (ins memsrc3_predec:$src)>; +} // end of mayLoad + +// Load patterns +def : Pat<(i16 (zextloadi8 GR64:$src)), (LDB GR64:$src, (i16 0))>; +def : Pat<(i16 (zextloadi8 addr_MO10:$src)), (LDB addr_MO10:$src)>; + +def : Pat<(i16 (extloadi8 GR64:$src)), (LDB GR64:$src, (i16 0))>; +def : Pat<(i16 (extloadi8 addr_MO10:$src)), (LDB addr_MO10:$src)>; + +def : Pat<(i16 (load GR64:$src)), (LDW GR64:$src, (i16 0))>; +def : Pat<(i16 (load addr_MO10:$src)), (LDW addr_MO10:$src)>; + +// Short load patterns +let AddedComplexity = 123 in { + def : Pat<(i16 (zextloadi8 GR8:$src)), (LDB_short GR8:$src, (i16 0))>; + def : Pat<(i16 (zextloadi8 addr_MO3:$src)), (LDB_short addr_MO3:$src)>; + + def : Pat<(i16 (extloadi8 GR8:$src)), (LDB GR8:$src, (i16 0))>; + def : Pat<(i16 (extloadi8 addr_MO3:$src)), (LDB_short addr_MO3:$src)>; + + def : Pat<(i16 (load GR8:$src)), (LDW GR8:$src, (i16 0))>; + def : Pat<(i16 (load addr_MO3:$src)), (LDW addr_MO3:$src)>; +} + +let mayStore = 1 in { +def STB : STORE<0x8, "stb", (outs), (ins memsrc10:$dst, GR64:$rA)>; +def STW : STORE<0xc, "stw", (outs), (ins memsrc10:$dst, GR64:$rA)>; +def STB_postinc : STORE<0x9, "stb", (outs), (ins memsrc10_postinc:$dst, GR64:$rA)>; +def STW_postinc : STORE<0xd, "stw", (outs), (ins memsrc10_postinc:$dst, GR64:$rA)>; +def STB_predec : STORE<0xa, "stb", (outs), (ins memsrc10_predec:$dst, GR64:$rA)>; +def STW_predec : STORE<0xe, "stw", (outs), (ins memsrc10_predec:$dst, GR64:$rA)>; + +def STB_short : STORE_short<0x8, "stb", (outs), (ins memsrc3:$dst, GR8:$rA)>; +def STW_short : STORE_short<0xc, "stw", (outs), (ins memsrc3:$dst, GR8:$rA)>; +def STB_postinc_short : STORE_short<0x9, "stb", (outs), (ins memsrc3_postinc:$dst, GR8:$rA)>; +def STW_postinc_short : STORE_short<0xd, "stw", (outs), (ins memsrc3_postinc:$dst, GR8:$rA)>; +def STB_predec_short : STORE_short<0xa, "stb", (outs), (ins memsrc3_predec:$dst, GR8:$rA)>; +def STW_predec_short : STORE_short<0xe, "stw", (outs), (ins memsrc3_predec:$dst, GR8:$rA)>; +} // end of mayStore + +// Store patterns +def : Pat<(truncstorei8 GR64:$src, GR64:$dst), (STB GR64:$dst, (i16 0), GR64:$src)>; +def : Pat<(truncstorei8 GR64:$src, addr_MO10:$dst), (STB addr_MO10:$dst, GR64:$src)>; + +def : Pat<(store GR64:$src, GR64:$dst), (STW GR64:$dst, (i16 0), GR64:$src)>; +def : Pat<(store GR64:$src, addr_MO10:$dst), (STW addr_MO10:$dst, GR64:$src)>; + +// Short store patterns +let AddedComplexity = 123 in { + def : Pat<(truncstorei8 GR8:$src, GR8:$dst), (STB GR8:$dst, (i16 0), GR8:$src)>; + def : Pat<(truncstorei8 GR8:$src, addr_MO3:$dst), (STB addr_MO3:$dst, GR8:$src)>; + + def : Pat<(store GR8:$src, GR8:$dst), (STW GR8:$dst, (i16 0), GR8:$src)>; + def : Pat<(store GR8:$src, addr_MO10:$dst), (STW addr_MO3:$dst, GR8:$src)>; +} + + +//===----------------------------------------------------------------------===// +// Branch Operations +//===----------------------------------------------------------------------===// + +multiclass BRCC cc, string opname> { + def _ : Inst_i10_rr + <0x2, cc, (outs), (ins brtarget:$imm, GR64:$rA, GR64:$rB), + !strconcat(opname, "\t$imm, $rA, $rB"), []>; + + // Don't assemble short branch instructions + let isCodeGenOnly = 1 in { + def _short : Inst_i3_rr_short + <0x2, cc, (outs), (ins brtarget:$imm, GR8:$rA, GR8:$rB), + !strconcat(opname, "\t$imm, $rA, $rB"), []>; + } +} + +let isBranch = 1, isTerminator = 1, isBarrier = 1 in { + defm BEQ : BRCC<0x2, "beq">; + defm BNE : BRCC<0x3, "bne">; + defm BLTS : BRCC<0x4, "blts">; + defm BGTS : BRCC<0x5, "bgts">; + defm BLTU : BRCC<0x6, "bltu">; + defm BGTU : BRCC<0x7, "bgtu">; + + def BRA : Inst_i18 + <0x2, 0x0, (outs), (ins brtarget:$imm), "bra\t$imm", [(br bb:$imm)]>; + + // Don't assemble short branch instructions + let isCodeGenOnly = 1 in { + def BRA_short : Inst_i9_short + <0x2, 0x0, (outs), (ins brtarget:$imm), "bra\t$imm", []>; + } +} + +// Implements the BR_CC DAG node. Expanded into one of the above branches. +let isBranch = 1, isTerminator = 1, isBarrier = 1, usesCustomInserter = 1 in { + def BR_CC : Pseudo + <(outs), (ins i16imm:$cc, GR64:$lhs, GR64:$rhs, brtarget:$target), + "#BR_CC", [(AAPbrcc imm:$cc, GR64:$lhs, GR64:$rhs, bb:$target)]>; + + def BR_CC_short : Pseudo + <(outs), (ins i16imm:$cc, GR8:$lhs, GR8:$rhs, brtarget:$target), + "#BR_CC_short", []>; +} + +// Implements the SELECT_CC DAG node. Expanded into a branch sequence +let usesCustomInserter = 1 in { + def SELECT_CC : Pseudo + <(outs GR64:$dst), + (ins GR64:$lhs, GR64:$rhs, GR64:$T, GR64:$F, i16imm:$cc), + "#SELECT_CC", + [(set GR64:$dst, + (AAPselectcc GR64:$lhs, GR64:$rhs, GR64:$T, GR64:$F, imm:$cc))]>; +} + + +//===----------------------------------------------------------------------===// +// Calls and returns +//===----------------------------------------------------------------------===// +//FIXME: Mark as clobbering all non-callee saved regs +//TODO: Add other conditional branches +let isCall = 1, + Uses = [R1], + Defs = [R0, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, + R13, R14, R15, R16, R17, R18, R19] in { + +let isCodeGenOnly = 1 in { + def BAL_short : Inst_i6_r_short + <0x2, 0x1, (outs), (ins i16imm:$imm, GR8:$rA), "bal\t$imm, $rA", []>; +} + +def BAL : Inst_i16_r + <0x2, 0x1, (outs), (ins i16imm:$imm, GR64:$rA), "bal\t$imm, $rA", []>; + +def JAL_short : Inst_rr_short + <0x2, 0x9, (outs), (ins GR8:$rD, GR64:$rA), "jal\t$rD, $rA", []>; + +def JAL : Inst_rr + <0x2, 0x9, (outs), (ins GR64:$rD, GR64:$rA), "jal\t$rD, $rA", []>; +} + +// Calls are encoded as a branch through the link register +def : Pat<(callflag (i16 imm:$imm), GR64:$rA), (BAL imm:$imm, GR64:$rA)>; + + +let isReturn = 1, isTerminator = 1, isBarrier = 1 in { +def JMP : Inst_r<0x2, 0x8, (outs), (ins GR64:$rD), "jmp\t$rD", []>; + +def JMP_short : Inst_r_short<0x2, 0x8, (outs), (ins GR8:$rD), "jmp\t$rD", []>; +} + + +// Indirect calls are a jump through a register +def : Pat<(callflag GR64:$rD, GR64:$rA), (JAL GR64:$rD, GR64:$rA)>; + + +// Returns are encoded as a jump through the link register +def : Pat<(retflag GR64:$rD), (JMP GR64:$rD)>; + + +// Stack adjustment +let Defs = [R1], Uses = [R1] in { +def ADJCALLSTACKDOWN : Pseudo + <(outs), (ins i16imm:$amt), "#ADJCALLSTACKDOWN", + [(callseq_start timm:$amt)]>; + +def ADJCALLSTACKUP : Pseudo + <(outs), (ins i16imm:$amt1, i16imm:$amt2), "#ADJCALLSTACKUP", + [(callseq_end timm:$amt1, timm:$amt2)]>; +} + +// Call patterns +def : Pat<(callflag (i16 tglobaladdr:$dst), GR64:$rA), (BAL tglobaladdr:$dst, GR64:$rA)>; +def : Pat<(callflag (i16 texternalsym:$dst), GR64:$rA), (BAL texternalsym:$dst, GR64:$rA)>; + + +//===----------------------------------------------------------------------===// +// Peephole Patterns +//===----------------------------------------------------------------------===// +def : Pat<(addc GR64:$src1, GR64:$src2), (ADD_r GR64:$src1, GR64:$src2)>; + +def : Pat<(i16 (aapwrapper tglobaladdr:$dst)), (MOV_i16 tglobaladdr:$dst)>; +def : Pat<(i16 (aapwrapper texternalsym:$dst)), (MOV_i16 texternalsym:$dst)>; +def : Pat<(i16 (aapwrapper tblockaddress:$dst)), (MOV_i16 tblockaddress:$dst)>; Index: lib/Target/AAP/AAPMCInstLower.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAPMCInstLower.h @@ -0,0 +1,47 @@ +//===-- AAPMCInstLower.h - Lower MachineInstr to MCInst ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AAP_AAPMCINSTLOWER_H +#define LLVM_LIB_TARGET_AAP_AAPMCINSTLOWER_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { +class AsmPrinter; +class MCContext; +class MCInst; +class MCOperand; +class MCSymbol; +class MachineInstr; +class MachineModuleInfoMachO; +class MachineOperand; + +/// AAPMCInstLower - This class is used to lower an MachineInstr +/// into an MCInst. +class LLVM_LIBRARY_VISIBILITY AAPMCInstLower { + MCContext &Ctx; + + AsmPrinter &Printer; + +public: + AAPMCInstLower(MCContext &ctx, AsmPrinter &printer) + : Ctx(ctx), Printer(printer) {} + void Lower(const MachineInstr *MI, MCInst &OutMI) const; + + MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const; + + MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const; + MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const; + MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const; + MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const; + MCSymbol *GetBlockAddressSymbol(const MachineOperand &MO) const; +}; +} + +#endif Index: lib/Target/AAP/AAPMCInstLower.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPMCInstLower.cpp @@ -0,0 +1,168 @@ +//===-- AAPMCInstLower.cpp - Convert AAP MachineInstr to an MCInst --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to lower AAP MachineInstrs to their corresponding +// MCInst records. +// +//===----------------------------------------------------------------------===// + +#include "AAPMCInstLower.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; + +MCSymbol * +AAPMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case 0: + break; + } + + return Printer.getSymbol(MO.getGlobal()); +} + +MCSymbol * +AAPMCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case 0: + break; + } + + return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); +} + +MCSymbol *AAPMCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const { + const DataLayout &DL = Printer.getDataLayout(); + SmallString<256> Name; + raw_svector_ostream(Name) << DL.getPrivateGlobalPrefix() << "JTI" + << Printer.getFunctionNumber() << '_' + << MO.getIndex(); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case 0: + break; + } + + // Create a symbol for the name. + return Ctx.getOrCreateSymbol(Name); +} + +MCSymbol * +AAPMCInstLower::GetConstantPoolIndexSymbol(const MachineOperand &MO) const { + const DataLayout &DL = Printer.getDataLayout(); + SmallString<256> Name; + raw_svector_ostream(Name) << DL.getPrivateGlobalPrefix() << "CPI" + << Printer.getFunctionNumber() << '_' + << MO.getIndex(); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case 0: + break; + } + + // Create a symbol for the name. + return Ctx.getOrCreateSymbol(Name); +} + +MCSymbol * +AAPMCInstLower::GetBlockAddressSymbol(const MachineOperand &MO) const { + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case 0: + break; + } + + return Printer.GetBlockAddressSymbol(MO.getBlockAddress()); +} + +MCOperand AAPMCInstLower::LowerSymbolOperand(const MachineOperand &MO, + MCSymbol *Sym) const { + // FIXME: We would like an efficient form for this, so we don't have to do a + // lot of extra uniquing. + const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx); + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case 0: + break; + } + + if (!MO.isJTI() && MO.getOffset()) + Expr = MCBinaryExpr::createAdd( + Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); + return MCOperand::createExpr(Expr); +} + +void AAPMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(MI->getOpcode()); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + + MCOperand MCOp; + switch (MO.getType()) { + default: + MI->dump(); + llvm_unreachable("unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) + continue; + MCOp = MCOperand::createReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::createImm(MO.getImm()); + break; + case MachineOperand::MO_MachineBasicBlock: + MCOp = MCOperand::createExpr( + MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); + break; + case MachineOperand::MO_GlobalAddress: + MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); + break; + case MachineOperand::MO_ExternalSymbol: + MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); + break; + case MachineOperand::MO_JumpTableIndex: + MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO)); + break; + case MachineOperand::MO_ConstantPoolIndex: + MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO)); + break; + case MachineOperand::MO_BlockAddress: + MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(MO)); + break; + case MachineOperand::MO_RegisterMask: + continue; + } + + OutMI.addOperand(MCOp); + } +} Index: lib/Target/AAP/AAPMachineFunctionInfo.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAPMachineFunctionInfo.h @@ -0,0 +1,65 @@ +//===- AAPMachineFuctionInfo.h - AAP machine func info -----------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares AAP-specific per-machine-function information. +// +//===----------------------------------------------------------------------===// + +#ifndef AAPMACHINEFUNCTIONINFO_H +#define AAPMACHINEFUNCTIONINFO_H +#include "AAPRegisterInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +namespace llvm { + +/// AAPMachineFunctionInfo - This class is derived from MachineFunction and +/// contains private AAP target-specific information for each MachineFunction. +class AAPMachineFunctionInfo : public MachineFunctionInfo { + virtual void anchor(); + + MachineFunction &MF; + + /// CalleeSavedFrameSize - Size of the callee-saved register portion of the + /// stack frame in bytes + unsigned CalleeSavedFrameSize; + + /// SRetReturnReg - AAP ABI require that sret lowering includes + /// returning the value of the returned struct in a register. This field + /// holds the virtual register into which the sret argument is passed. + unsigned SRetReturnReg; + + /// GlobalBaseReg - keeps track of the virtual register initialized for + /// use as the global base register. This is used for PIC in some PIC + /// relocation models. + unsigned GlobalBaseReg; + + /// VarArgsFrameIndex - FrameIndex for start of varargs area. + int VarArgsFrameIndex; + +public: + AAPMachineFunctionInfo(MachineFunction &MF) + : MF(MF), CalleeSavedFrameSize(0), SRetReturnReg(0), GlobalBaseReg(0), + VarArgsFrameIndex(0) {} + + unsigned getCalleeSavedFrameSize() { return CalleeSavedFrameSize; } + void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; } + + unsigned getSRetReturnReg() const { return SRetReturnReg; } + void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } + + unsigned getGlobalBaseReg(); + + int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } + void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } +}; + +} // End llvm namespace + +#endif Index: lib/Target/AAP/AAPMachineFunctionInfo.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPMachineFunctionInfo.cpp @@ -0,0 +1,23 @@ +//===-- AAPMachineFuctionInfo.cpp - AAP machine function info -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AAPMachineFunctionInfo.h" + +using namespace llvm; + +void AAPMachineFunctionInfo::anchor() {} + +unsigned AAPMachineFunctionInfo::getGlobalBaseReg() { + // Return if it has already been initialized. + if (GlobalBaseReg) + return GlobalBaseReg; + + return GlobalBaseReg = + MF.getRegInfo().createVirtualRegister(&AAP::GR64RegClass); +} Index: lib/Target/AAP/AAPRegisterInfo.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAPRegisterInfo.h @@ -0,0 +1,51 @@ +//===-- AAPRegisterInfo.h - AAP Register Information Impl -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the AAP implementation of the MRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef AAPREGISTERINFO_H +#define AAPREGISTERINFO_H + +#include "llvm/Target/TargetRegisterInfo.h" + +#define GET_REGINFO_HEADER +#include "AAPGenRegisterInfo.inc" + +namespace llvm { + +class TargetInstrInfo; + +struct AAPRegisterInfo : public AAPGenRegisterInfo { +public: + AAPRegisterInfo(); + + const MCPhysReg * + getCalleeSavedRegs(const MachineFunction *MF = nullptr) const override; + + BitVector getReservedRegs(const MachineFunction &MF) const override; + + bool requiresRegisterScavenging(const MachineFunction &MF) const override; + + void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, + unsigned FIOperandNum, + RegScavenger *RS = nullptr) const override; + + // Debug information queries. + unsigned getFrameRegister(const MachineFunction &MF) const override; + + static unsigned getLinkRegister(); + static unsigned getStackPtrRegister(); + static unsigned getFramePtrRegister(); +}; + +} // end namespace llvm + +#endif Index: lib/Target/AAP/AAPRegisterInfo.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPRegisterInfo.cpp @@ -0,0 +1,128 @@ +//===-- AAPRegisterInfo.cpp - AAP Register Information ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the AAP implementation of the TargetRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#include "AAPRegisterInfo.h" +#include "AAP.h" +#include "AAPSubtarget.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" + +using namespace llvm; + +#define GET_REGINFO_TARGET_DESC +#include "AAPGenRegisterInfo.inc" +#include "llvm/CodeGen/MachineFunction.h" + +AAPRegisterInfo::AAPRegisterInfo() : AAPGenRegisterInfo(getLinkRegister()) {} + +const uint16_t * +AAPRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + return CSR_SaveList; +} + +BitVector AAPRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + + Reserved.set(getLinkRegister()); + Reserved.set(getStackPtrRegister()); + if (TFI->hasFP(MF)) { + Reserved.set(getFramePtrRegister()); + } + + // Restrict the size of the register set + for (unsigned i = AAP::R16; i <= AAP::R63; i++) { + Reserved.set(i); + } + return Reserved; +} + +bool AAPRegisterInfo::requiresRegisterScavenging( + const MachineFunction &MF) const { + return false; +} + +void AAPRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBI, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { + MachineInstr &MI = *MBBI; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + + DebugLoc DL = MI.getDebugLoc(); + + unsigned i = 0; + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && + "Instr does not have a Frame Index operand!"); + } + + int FrameIdx = MI.getOperand(i).getIndex(); + unsigned BaseReg = getFrameRegister(MF); + + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIdx); + if (!TFI->hasFP(MF)) { + Offset += MF.getFrameInfo()->getStackSize(); + } + + // fold imm into offset + Offset += MI.getOperand(i + 1).getImm(); + + // If the MachineInstr is an LEA, expand it to an ADD_i10 or SUB_i10 here + if (MI.getOpcode() == AAP::LEA) { + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + unsigned DstReg = MI.getOperand(0).getReg(); + + assert(((Offset >= -1023) || (Offset <= 1023)) && + "Currently LEA immediates must be in the range [-1023, 1023]"); + + if (Offset > 0) { + BuildMI(MBB, &MI, DL, TII->get(AAP::ADD_i10), DstReg) + .addReg(BaseReg) + .addImm(Offset); + } + else if (Offset < 0) { + BuildMI(MBB, &MI, DL, TII->get(AAP::SUB_i10), DstReg) + .addReg(BaseReg) + .addImm(-Offset); + } + else { + BuildMI(MBB, &MI, DL, TII->get(AAP::MOV_r), DstReg).addReg(BaseReg); + } + MI.eraseFromParent(); + } + else { + MI.getOperand(i).ChangeToRegister(BaseReg, false); + MI.getOperand(i + 1).ChangeToImmediate(Offset); + } +} + +unsigned AAPRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + + return TFI->hasFP(MF) ? getFramePtrRegister() : getStackPtrRegister(); +} + + +unsigned AAPRegisterInfo::getLinkRegister() { + return AAP::R0; +} +unsigned AAPRegisterInfo::getStackPtrRegister() { + return AAP::R1; +} +unsigned AAPRegisterInfo::getFramePtrRegister() { + return AAP::R2; +} Index: lib/Target/AAP/AAPRegisterInfo.td =================================================================== --- /dev/null +++ lib/Target/AAP/AAPRegisterInfo.td @@ -0,0 +1,42 @@ +//===- AAPRegisterInfo.td - AAP Register defs ------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Declarations that describe the AAP register file +//===----------------------------------------------------------------------===// + +class AAPReg : Register { + field bits<5> Num; + let Namespace = "AAP"; +} + +// Registers are identified with 5-bit ID numbers. +// Ri - 16-bit integer registers +class Ri num, string n> : AAPReg { + let Num = num; + let HWEncoding{4-0} = num; +} + +foreach I = 0-63 in +def R#I : Ri, DwarfRegNum<[I]>; + +// PSW holds the carry flag +def PSW : AAPReg<"psw">, DwarfRegNum<[64]>; + + +// Register classes. +def GR8 : RegisterClass<"AAP", [i16], 16, + (add R0, R1, R2, R3, R4, R5, R6, R7)>; + +def GR64 : RegisterClass<"AAP", [i16], 16, + (add R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, + R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, + R26, R27, R28, R29, R30, R31, R32, R33, R34, R35, R36, R37, R38, + R39, R40, R41, R42, R43, R44, R45, R46, R47, R48, R49, R50, R51, + R52, R53, R54, R55, R56, R57, R58, R59, R60, R61, R62, R63)>; Index: lib/Target/AAP/AAPSelectionDAGInfo.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAPSelectionDAGInfo.h @@ -0,0 +1,30 @@ +//===-- AAPSelectionDAGInfo.h - AAP SelectionDAG Info -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the AAP subclass for TargetSelectionDAGInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef AAPSELECTIONDAGINFO_H +#define AAPSELECTIONDAGINFO_H + +#include "llvm/Target/TargetSelectionDAGInfo.h" + +namespace llvm { + +class AAPTargetMachine; + +class AAPSelectionDAGInfo : public TargetSelectionDAGInfo { +public: + explicit AAPSelectionDAGInfo(); + ~AAPSelectionDAGInfo(); +}; +} + +#endif Index: lib/Target/AAP/AAPSelectionDAGInfo.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPSelectionDAGInfo.cpp @@ -0,0 +1,21 @@ +//===-- AAPSelectionDAGInfo.cpp - AAP SelectionDAG Info -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AAPSelectionDAGInfo class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "AAP-selectiondag-info" +#include "AAPTargetMachine.h" +using namespace llvm; + +AAPSelectionDAGInfo::AAPSelectionDAGInfo() + : TargetSelectionDAGInfo() {} + +AAPSelectionDAGInfo::~AAPSelectionDAGInfo() {} Index: lib/Target/AAP/AAPSubtarget.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAPSubtarget.h @@ -0,0 +1,67 @@ +//===-- AAPSubtarget.h - Define Subtarget for the AAP -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the AAP specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef AAP_SUBTARGET_H +#define AAP_SUBTARGET_H + +#include "AAPFrameLowering.h" +#include "AAPISelLowering.h" +#include "AAPInstrInfo.h" +#include "AAPSelectionDAGInfo.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" +#include + +#define GET_SUBTARGETINFO_HEADER +#include "AAPGenSubtargetInfo.inc" + +namespace llvm { +class StringRef; + +class AAPSubtarget : public AAPGenSubtargetInfo { + virtual void anchor(); + AAPInstrInfo InstrInfo; + AAPFrameLowering FrameLowering; + AAPTargetLowering TLInfo; + AAPSelectionDAGInfo TSInfo; + +public: + /// This constructor initializes the data members to match that + /// of the specified triple. + /// + AAPSubtarget(const Triple &TT, const std::string &CPU, + const std::string &FS, const TargetMachine &TM); + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + + const AAPInstrInfo *getInstrInfo() const override { return &InstrInfo; } + const AAPFrameLowering *getFrameLowering() const override { + return &FrameLowering; + } + const AAPTargetLowering *getTargetLowering() const override { + return &TLInfo; + } + const AAPSelectionDAGInfo *getSelectionDAGInfo() const override { + return &TSInfo; + } + const TargetRegisterInfo *getRegisterInfo() const override { + return &InstrInfo.getRegisterInfo(); + } +}; +} // End llvm namespace + +#endif Index: lib/Target/AAP/AAPSubtarget.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPSubtarget.cpp @@ -0,0 +1,32 @@ +//===-- AAPSubtarget.cpp - AAP Subtarget Information ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the AAP specific subclass of TargetSubtargetInfo. +// +//===----------------------------------------------------------------------===// + +#include "AAPSubtarget.h" +#include "AAP.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "aap-subtarget" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "AAPGenSubtargetInfo.inc" + +void AAPSubtarget::anchor() {} + +AAPSubtarget::AAPSubtarget(const Triple &TT, const std::string &CPU, + const std::string &FS, const TargetMachine &TM) + : AAPGenSubtargetInfo(TT, CPU, FS), InstrInfo(*this), FrameLowering(), + TLInfo(TM, *this), TSInfo() {} Index: lib/Target/AAP/AAPTargetMachine.h =================================================================== --- /dev/null +++ lib/Target/AAP/AAPTargetMachine.h @@ -0,0 +1,47 @@ +//===-- AAPTargetMachine.h - Define TargetMachine for AAP --------- C++ ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the AAP specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#ifndef AAP_TARGETMACHINE_H +#define AAP_TARGETMACHINE_H + +#include "AAPSubtarget.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + +class AAPTargetMachine : public LLVMTargetMachine { + std::unique_ptr TLOF; + AAPSubtarget Subtarget; + +public: + AAPTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, + const TargetOptions &Options, Reloc::Model RM, + CodeModel::Model CM, CodeGenOpt::Level OL); + ~AAPTargetMachine() override; + + const AAPSubtarget *getSubtargetImpl(const Function &F) const override { + return &Subtarget; + } + + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; + + TargetLoweringObjectFile *getObjFileLowering() const override { + return TLOF.get(); + } +}; // AAPTargetMachine + +} // end namespace llvm + +#endif Index: lib/Target/AAP/AAPTargetMachine.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AAPTargetMachine.cpp @@ -0,0 +1,62 @@ +//===-- AAPTargetMachine.cpp - Define TargetMachine for AAP ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements the info about AAP target spec. +// +//===----------------------------------------------------------------------===// + +#include "AAP.h" +#include "AAPTargetMachine.h" +#include "llvm/ADT/Triple.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Support/TargetRegistry.h" +using namespace llvm; + +extern "C" void LLVMInitializeAAPTarget() { + // Register the target + RegisterTargetMachine X(TheAAPTarget); +} + +AAPTargetMachine::AAPTargetMachine(const Target &T, const Triple &TT, StringRef CPU, + StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) + : LLVMTargetMachine(T, "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-n16", TT, CPU, FS, Options, RM, CM, + OL), + TLOF(make_unique()), + Subtarget(TT, CPU, FS, *this) { + initAsmInfo(); +} + +AAPTargetMachine::~AAPTargetMachine() {} + +namespace { +/// AAP Code Generator Pass Configuration Options. +class AAPPassConfig : public TargetPassConfig { +public: + AAPPassConfig(AAPTargetMachine *TM, PassManagerBase &PM) + : TargetPassConfig(TM, PM) {} + + AAPTargetMachine &getAAPTargetMachine() const { + return getTM(); + } + + virtual bool addInstSelector(); +}; +} // namespace + +TargetPassConfig *AAPTargetMachine::createPassConfig(PassManagerBase &PM) { + return new AAPPassConfig(this, PM); +} + +bool AAPPassConfig::addInstSelector() { + addPass(createAAPISelDag(getAAPTargetMachine(), getOptLevel())); + return false; +} Index: lib/Target/AAP/AsmParser/AAPAsmParser.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/AsmParser/AAPAsmParser.cpp @@ -0,0 +1,588 @@ +//===-- AAPAsmParser.cpp - Parse AAP assembly to MCInst instructions ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AAP.h" +#include "MCTargetDesc/AAPMCTargetDesc.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +namespace { +struct AAPOperand; + +class AAPAsmParser : public MCTargetAsmParser { + MCAsmParser &Parser; + const MCRegisterInfo *MRI; + + MCAsmParser &getParser() const { return Parser; } + MCAsmLexer &getLexer() const { return Parser.getLexer(); } + MCSubtargetInfo &STI; + + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, MCStreamer &Out, + uint64_t &ErrorInfo, + bool matchingInlineAsm) override; + + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); + + std::unique_ptr ParseRegister(unsigned &RegNo); + std::unique_ptr ParseImmediate(); + std::unique_ptr ParseMemSrc(); + + bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands) override; + + bool ParseDirective(AsmToken DirectiveID); + + bool ParseOperand(OperandVector &Operands); + +// Auto-generated instruction matching functions +#define GET_ASSEMBLER_HEADER +#include "AAPGenAsmMatcher.inc" + +public: + AAPAsmParser(MCSubtargetInfo &sti, MCAsmParser &_Parser, + const MCInstrInfo &MII, const MCTargetOptions &Options) + : MCTargetAsmParser(Options), Parser(_Parser), STI(sti) { + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + + // Cache the machine register info for later + MRI = Parser.getContext().getRegisterInfo(); + } + + unsigned checkTargetMatchPredicate(MCInst &Inst) override { + // Check instructions with memsrc operands here, as they cannot be + // checked through the instruction match classes. + + // If this is a short load/store instruction, then we must check that + // its register operands are all in the GR8 reg class. + const MCRegisterClass& MRC = MRI->getRegClass(AAP::GR8RegClassID); + + switch (Inst.getOpcode()) { + default: + return Match_Success; + case AAP::LDB_short: + case AAP::LDW_short: + case AAP::LDB_postinc_short: + case AAP::LDW_postinc_short: + case AAP::LDB_predec_short: + case AAP::LDW_predec_short: + case AAP::STB_short: + case AAP::STW_short: + case AAP::STB_postinc_short: + case AAP::STW_postinc_short: + case AAP::STB_predec_short: + case AAP::STW_predec_short: + break; + } + + for (MCInst::iterator I = Inst.begin(); I != Inst.end(); ++I) { + if (I->isReg() && !MRC.contains(I->getReg())) { + return Match_InvalidOperand; + } + } + return Match_Success; + } +}; + +/// AAPOperand - Instances of this class represented a parsed machine +/// instruction +struct AAPOperand : public MCParsedAsmOperand { + + enum KindTy { Token, Register, Immediate, MemSrc } Kind; + + SMLoc StartLoc, EndLoc; + union { + struct { + const char *Data; + unsigned Length; + } Tok; + struct { + unsigned RegNum; + } Reg; + struct { + const MCExpr *Val; + } Imm; + struct { + bool WithPreDec; + unsigned RegNum; + bool WithPostInc; + const MCExpr *Offset; + } Mem; + }; + + AAPOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} + +public: + AAPOperand(const AAPOperand &o) : MCParsedAsmOperand() { + Kind = o.Kind; + StartLoc = o.StartLoc; + EndLoc = o.EndLoc; + switch (Kind) { + case Register: + Reg = o.Reg; + break; + case Immediate: + Imm = o.Imm; + break; + case Token: + Tok = o.Tok; + break; + case MemSrc: + Mem = o.Mem; + } + } + + /// getStartLoc - Gets location of the first token of this operand + SMLoc getStartLoc() const { return StartLoc; } + + /// getEndLoc - Gets location of the last token of this operand + SMLoc getEndLoc() const { return EndLoc; } + + unsigned getReg() const { + assert(Kind == Register && "Invalid type access!"); + return Reg.RegNum; + } + + const MCExpr *getImm() const { + assert(Kind == Immediate && "Invalid type access!"); + return Imm.Val; + } + + StringRef getToken() const { + assert(Kind == Token && "Invalid type access!"); + return StringRef(Tok.Data, Tok.Length); + } + + unsigned getMemSrcReg() const { + assert(Kind == MemSrc && "Invalid type access!"); + return Mem.RegNum; + } + + const MCExpr *getMemSrcImm() const { + assert(Kind == MemSrc && "Invalid type access!"); + return Mem.Offset; + } + + + // If an MCExpr is a constant immediate, check whether it is in the provided + // inclusive range. If we are checking for an immediate, then arbitrary + // expressions are also allowed. + static bool isImmInRange(const MCExpr* Imm, int64_t Min, int64_t Max) { + if (Imm->getKind() != MCExpr::Constant) { + return true; // allow arbitrary expressions + } + int64_t Res; + Imm->evaluateAsAbsolute(Res); + return (Res >= Min) && (Res <= Max); + } + + static bool isConstInRange(const MCExpr* Imm, int64_t Min, int64_t Max) { + if (Imm->getKind() != MCExpr::Constant) { + return false; // only allow constants + } + int64_t Res; + Imm->evaluateAsAbsolute(Res); + return (Res >= Min) && (Res <= Max); + } + + static bool isConst3(const MCExpr* I) { return isConstInRange(I, 0, 7); } + static bool isConst6(const MCExpr* I) { return isConstInRange(I, 0, 63); } + static bool isImm6(const MCExpr* I) { return isImmInRange(I, 0, 63); } + static bool isImm9(const MCExpr* I) { return isImmInRange(I, 0, 511); } + static bool isImm10(const MCExpr* I) { return isImmInRange(I, 0, 1023); } + static bool isImm12(const MCExpr* I) { return isImmInRange(I, 0, 4095); } + static bool isImm16(const MCExpr* I) { return isImmInRange(I, -32768, 65535); } + static bool isOff10(const MCExpr* I) { return isImmInRange(I, -512, 511); } + + + // Functions for testing operand type + bool isReg() const { return Kind == Register; } + bool isImm() const { return Kind == Immediate; } + + bool isConst3() const { return isImm() && isConst3(getImm()); } + bool isConst6() const { return isImm() && isConst6(getImm()); } + bool isImm6() const { return isImm() && isImm6(getImm()); } + bool isImm9() const { return isImm() && isImm9(getImm()); } + bool isImm10() const { return isImm() && isImm10(getImm()); } + bool isImm12() const { return isImm() && isImm12(getImm()); } + bool isImm16() const { return isImm() && isImm16(getImm()); } + bool isOff10() const { return isImm() && isOff10(getImm()); } + + bool isToken() const { return Kind == Token; } + bool isMem() const { return false; } + + // Check that the immediate fits in an imm6 + bool isMemSrc10() const { + if (Kind != MemSrc || Mem.WithPreDec || Mem.WithPostInc) { return false; } + // AAPAsmParser::checkTargetMatchPredicate checks that the register is + // is in the GR64 class + return isOff10(getMemSrcImm()); + } + bool isMemSrc10PostInc() const { + if (Kind != MemSrc) { return false; } + if (Mem.WithPreDec) { return false; } + if (!Mem.WithPostInc) { return false; } + // AAPAsmParser::checkTargetMatchPredicate checks that the register is + // is in the GR64 class + return isOff10(getMemSrcImm()); + } + bool isMemSrc10PreDec() const { + if (Kind != MemSrc) { return false; } + if (!Mem.WithPreDec) { return false; } + if (Mem.WithPostInc) { return false; } + // AAPAsmParser::checkTargetMatchPredicate checks that the register is + // is in the GR64 class + return isOff10(getMemSrcImm()); + } + + // Check that the immediate fits in an const3. A memsrc3 operand may only + // have a constant in its immediate field. + bool isMemSrc3() const { + if (Kind != MemSrc || Mem.WithPreDec || Mem.WithPostInc) { return false; } + // AAPAsmParser::checkTargetMatchPredicate checks that the register is + // is in the GR8 class + return isConst3(getMemSrcImm()); + } + bool isMemSrc3PostInc() const { + if (Kind != MemSrc) { return false; } + if (Mem.WithPreDec) { return false; } + if (!Mem.WithPostInc) { return false; } + // AAPAsmParser::checkTargetMatchPredicate checks that the register is + // is in the GR8 class + return isConst3(getMemSrcImm()); + } + bool isMemSrc3PreDec() const { + if (Kind != MemSrc) { return false; } + if (!Mem.WithPreDec) { return false; } + if (Mem.WithPostInc) { return false; } + // AAPAsmParser::checkTargetMatchPredicate checks that the register is + // is in the GR8 class + return isConst3(getMemSrcImm()); + } + + void addExpr(MCInst &Inst, const MCExpr *Expr) const { + // Add as immediates where possible. Null MCExpr = 0 + if (Expr == 0) + Inst.addOperand(MCOperand::createImm(0)); + else if (const MCConstantExpr *CE = dyn_cast(Expr)) + Inst.addOperand(MCOperand::createImm(CE->getValue())); + else + Inst.addOperand(MCOperand::createExpr(Expr)); + } + + void addRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getReg())); + } + + void addImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + + void addMemSrcOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getMemSrcReg())); + addExpr(Inst, getMemSrcImm()); + } + void addMemSrc10Operands(MCInst &Inst, unsigned N) const { + addMemSrcOperands(Inst, N); + } + void addMemSrc10PostIncOperands(MCInst &Inst, unsigned N) const { + addMemSrcOperands(Inst, N); + } + void addMemSrc10PreDecOperands(MCInst &Inst, unsigned N) const { + addMemSrcOperands(Inst, N); + } + void addMemSrc3Operands(MCInst &Inst, unsigned N) const { + addMemSrcOperands(Inst, N); + } + void addMemSrc3PostIncOperands(MCInst &Inst, unsigned N) const { + addMemSrcOperands(Inst, N); + } + void addMemSrc3PreDecOperands(MCInst &Inst, unsigned N) const { + addMemSrcOperands(Inst, N); + } + + // FIXME: Implement this + void print(raw_ostream &OS) const {} + + static std::unique_ptr CreateToken(StringRef Str, SMLoc S) { + auto Op = make_unique(Token); + Op->Tok.Data = Str.data(); + Op->Tok.Length = Str.size(); + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } + + static std::unique_ptr CreateReg(unsigned RegNo, SMLoc S, + SMLoc E) { + auto Op = make_unique(Register); + Op->Reg.RegNum = RegNo; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static std::unique_ptr CreateImm(const MCExpr *Val, SMLoc S, + SMLoc E) { + auto Op = make_unique(Immediate); + Op->Imm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static std::unique_ptr + CreateMemSrc(unsigned RegNo, const MCExpr *Offset, + bool WithPreDec, bool WithPostInc, SMLoc S, SMLoc E) { + auto Op = make_unique(MemSrc); + Op->Mem.WithPreDec = WithPreDec; + Op->Mem.RegNum = RegNo; + Op->Mem.WithPostInc = WithPostInc; + Op->Mem.Offset = Offset; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } +}; +} // end anonymous namespace. + +// Auto-generated by TableGen +static unsigned MatchRegisterName(StringRef Name); +static const char *getSubtargetFeatureName(uint64_t Val); + +bool AAPAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, + MCStreamer &Out, uint64_t &ErrorInfo, + bool matchingInlineAsm) { + MCInst Inst; + SMLoc ErrorLoc; + + switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, matchingInlineAsm)) { + default: + break; + case Match_Success: + Out.EmitInstruction(Inst, STI); + return false; + case Match_MissingFeature: { + assert(ErrorInfo && "Unknown missing feature!"); + std::string Msg = "Use of this instruction requires:"; + unsigned Mask = 1; + for (unsigned i = 0; i < (sizeof(ErrorInfo) * 8 - 1); ++i) { + if (ErrorInfo & Mask) { + Msg += " "; + Msg += getSubtargetFeatureName(ErrorInfo & Mask); + } + Mask <<= 1; + } + return Error(IDLoc, Msg); + } + case Match_MnemonicFail: + return Error(IDLoc, "Unrecognized instruction mnemonic"); + case Match_InvalidOperand: + ErrorLoc = IDLoc; + if (ErrorInfo != ~0U) { + if (ErrorInfo >= Operands.size()) + return Error(IDLoc, "Too few operands for instruction"); + + ErrorLoc = ((AAPOperand &)*Operands[ErrorInfo]).getStartLoc(); + if (ErrorLoc == SMLoc()) + ErrorLoc = IDLoc; + } + return Error(IDLoc, "Invalid operand for instruction"); + } + + llvm_unreachable("Unknown match type detected!"); +} + +bool AAPAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) { + return (ParseRegister(RegNo) == nullptr); +} + +std::unique_ptr AAPAsmParser::ParseRegister(unsigned &RegNo) { + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + + // Registers have '$' prefix + if (getLexer().getKind() != AsmToken::Dollar) { + return nullptr; + } + getLexer().Lex(); + + switch (getLexer().getKind()) { + default: + return nullptr; + case AsmToken::Identifier: + std::string lowerCaseStr = getLexer().getTok().getString().lower(); + + RegNo = MatchRegisterName(lowerCaseStr); + if (RegNo == 0) { + return nullptr; + } + getLexer().Lex(); + return AAPOperand::CreateReg(RegNo, S, E); + } +} + +std::unique_ptr AAPAsmParser::ParseImmediate() { + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + + const MCExpr *EVal; + if (!getParser().parseExpression(EVal, E)) { + return AAPOperand::CreateImm(EVal, S, E); + } + return nullptr; +} + +std::unique_ptr AAPAsmParser::ParseMemSrc() { + SMLoc S = Parser.getTok().getLoc(); + SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + + bool WithPreDec = false; + bool WithPostInc = false; + + // First check for a '-', signifying a predecrement + if (getLexer().getKind() == AsmToken::Minus) { + getLexer().Lex(); + WithPreDec = true; + } + + unsigned RegNo; + std::unique_ptr RegOp = ParseRegister(RegNo); + if (!RegOp) { + Error(Parser.getTok().getLoc(), "Missing register in memsrc operand"); + return nullptr; + } + RegNo = RegOp->getReg(); + + // Check for a '+' signifying a post increment + if (getLexer().getKind() == AsmToken::Plus) { + getLexer().Lex(); + WithPostInc = true; + } + + if (!getLexer().is(AsmToken::Comma)) { + Error(Parser.getTok().getLoc(), "Missing ',' separator in memsrc operand"); + return nullptr; + } + Parser.Lex(); + + std::unique_ptr ImmOp = ParseImmediate(); + if (!ImmOp) { + Error(Parser.getTok().getLoc(), "Missing immediate in memsrc operand"); + return nullptr; + } + const MCExpr *ImmVal = ImmOp->getImm(); + + return AAPOperand::CreateMemSrc(RegNo, ImmVal, WithPreDec, WithPostInc, S, E); +} + +/// Looks at a token type and creates the relevant operand +/// from this information, adding to Operands. +/// If operand was parsed, returns false, else true. +bool AAPAsmParser::ParseOperand(OperandVector &Operands) { + std::unique_ptr Op = nullptr; + + // Attempt to parse token as register + unsigned RegNo; + Op = ParseRegister(RegNo); + if (Op) { + Operands.push_back(std::move(Op)); + return false; + } + + // If we see a '[', that implies a memsrc follows + if (getLexer().getKind() == AsmToken::LBrac) { + SMLoc S = Parser.getTok().getLoc(); + Operands.push_back(AAPOperand::CreateToken("[", S)); + Parser.Lex(); // Eat '[' + + Op = ParseMemSrc(); + + if (Op) { + Operands.push_back(std::move(Op)); + + S = Parser.getTok().getLoc(); + if (getLexer().getKind() == AsmToken::RBrac) { + Operands.push_back(AAPOperand::CreateToken("]", S)); + Parser.Lex(); // Eat ']' + } else { + Error(S, "Missing closing brace for memsrc operand"); + return true; + } + return false; + } + } + + // Attempt to parse token as an immediate + Op = ParseImmediate(); + if (Op) { + Operands.push_back(std::move(Op)); + return false; + } + + // Finally we have exhausted all options and must declare defeat. + Error(Parser.getTok().getLoc(), "Unknown operand"); + return true; +} + +bool AAPAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands) { + // First operand is token for instruction + Operands.push_back(AAPOperand::CreateToken(Name, NameLoc)); + + // If there are no more operands, then finish + if (getLexer().is(AsmToken::EndOfStatement)) + return false; + + // Parse first operand + if (ParseOperand(Operands)) + return true; + + // Parse until end of statement, consuming commas between operands + while (getLexer().isNot(AsmToken::EndOfStatement) && + getLexer().is(AsmToken::Comma)) { + // Consume comma token + getLexer().Lex(); + + // Parse next operand + if (ParseOperand(Operands)) + return true; + } + + // consume end of statement + return false; +} + +bool AAPAsmParser::ParseDirective(AsmToken DirectiveID) { return true; } + +extern "C" void LLVMInitializeAAPAsmParser() { + RegisterMCAsmParser X(TheAAPTarget); +} + +#define GET_REGISTER_MATCHER +#define GET_MATCHER_IMPLEMENTATION +#define GET_SUBTARGET_FEATURE_NAME +#include "AAPGenAsmMatcher.inc" Index: lib/Target/AAP/AsmParser/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/AAP/AsmParser/CMakeLists.txt @@ -0,0 +1,5 @@ +add_llvm_library(LLVMAAPAsmParser + AAPAsmParser.cpp + ) + +add_dependencies(LLVMAAPAsmParser AAPCommonTableGen) Index: lib/Target/AAP/AsmParser/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/AAP/AsmParser/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/AAP/AsmParser/LLVMBuild.txt ----------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = AAPAsmParser +parent = AAP +required_libraries = MC MCParser Support AAPDesc AAPInfo +add_to_library_groups = AAP Index: lib/Target/AAP/AsmParser/Makefile =================================================================== --- /dev/null +++ lib/Target/AAP/AsmParser/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/AAP/AsmParser/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMAAPAsmParser + +# Hack: we need to include 'main' AAP target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common Index: lib/Target/AAP/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/AAP/CMakeLists.txt @@ -0,0 +1,32 @@ +set(LLVM_TARGET_DEFINITIONS AAP.td) + +tablegen(LLVM AAPGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM AAPGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM AAPGenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM AAPGenMCCodeEmitter.inc -gen-emitter) +tablegen(LLVM AAPGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM AAPGenAsmMatcher.inc -gen-asm-matcher) +tablegen(LLVM AAPGenDAGISel.inc -gen-dag-isel) +tablegen(LLVM AAPGenSubtargetInfo.inc -gen-subtarget) +tablegen(LLVM AAPGenCallingConv.inc -gen-callingconv) +add_public_tablegen_target(AAPCommonTableGen) + +add_llvm_target(AAPCodeGen + AAPFrameLowering.cpp + AAPInstrInfo.cpp + AAPISelDAGToDAG.cpp + AAPISelLowering.cpp + AAPMachineFunctionInfo.cpp + AAPRegisterInfo.cpp + AAPSelectionDAGInfo.cpp + AAPSubtarget.cpp + AAPTargetMachine.cpp + AAPAsmPrinter.cpp + AAPMCInstLower.cpp + ) + +add_subdirectory(Disassembler) +add_subdirectory(InstPrinter) +add_subdirectory(MCTargetDesc) +add_subdirectory(TargetInfo) +add_subdirectory(AsmParser) Index: lib/Target/AAP/Disassembler/AAPDisassembler.h =================================================================== --- /dev/null +++ lib/Target/AAP/Disassembler/AAPDisassembler.h @@ -0,0 +1,36 @@ +//===-- AAPDisassembler.h - AAP Disassembler ----------------------*- C++ -*--// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef AAPDISASSEMBLER_H +#define AAPDISASSEMBLER_H + +#include "llvm/MC/MCDisassembler.h" + +// Pull DecodeStatus and its enum values into the global namespace. +typedef llvm::MCDisassembler::DecodeStatus DecodeStatus; + +namespace llvm { +class MCInst; +class MemoryObject; +class raw_ostream; + +class AAPDisassembler : public MCDisassembler { + +public: + AAPDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) + : MCDisassembler(STI, Ctx) {} + + DecodeStatus getInstruction(MCInst &instr, uint64_t &size, + ArrayRef Bytes, uint64_t address, + raw_ostream &vStream, + raw_ostream &cStream) const override; +}; +} // namespace llvm + +#endif Index: lib/Target/AAP/Disassembler/AAPDisassembler.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/Disassembler/AAPDisassembler.cpp @@ -0,0 +1,134 @@ +//===-- AAPDisassembler.cpp - Disassembler for AAP ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the AAP Disassembler. +// +//===----------------------------------------------------------------------===// + +#include "AAP.h" +#include "AAPDisassembler.h" +#include "AAPRegisterInfo.h" +#include "AAPSubtarget.h" +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemoryObject.h" +#include "llvm/Support/TargetRegistry.h" + +#define DEBUG_TYPE "AAP-disassembler" + +using namespace llvm; + +typedef MCDisassembler::DecodeStatus DecodeStatus; + +namespace llvm { +extern Target TheAAPTarget; +} + +static MCDisassembler *createAAPDisassembler(const Target &T, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new AAPDisassembler(STI, Ctx); +} + +extern "C" void LLVMInitializeAAPDisassembler() { + // Register the disassembler + TargetRegistry::RegisterMCDisassembler(TheAAPTarget, createAAPDisassembler); +} + +// Forward declare because the autogenerated code will reference this. +// Definition is further down. +DecodeStatus DecodeGR8RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +DecodeStatus DecodeGR64RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); + +DecodeStatus decodeMemSrcOperand(MCInst &Inst, unsigned Operand, + uint64_t Address, const void *Decoder); + +#include "AAPGenDisassemblerTables.inc" + +DecodeStatus AAPDisassembler::getInstruction(MCInst &MI, uint64_t &Size, + ArrayRef Bytes, + uint64_t Address, raw_ostream &os, + raw_ostream &cs) const { + uint32_t Insn; + DecodeStatus Result; + + // First try a 16-bit instruction + Insn = (Bytes[1] << 8) | (Bytes[0] << 0); + + // Next try generic 16-bit instructions + Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = 2; + return Result; + } + + // Finally try a 32-bit instruction + Insn = + (Bytes[3] << 24) | (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0); + + // Call auto-generated decoder function + Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = 4; + return Result; + } + + // In case of invalid decode, assume it was a short instruction + Size = 2; + return MCDisassembler::Fail; +} + +static const unsigned AAPRegs8[] = {AAP::R0, AAP::R1, AAP::R2, AAP::R3, + AAP::R4, AAP::R5, AAP::R6, AAP::R7}; +static const unsigned AAPRegs64[] = { + AAP::R0, AAP::R1, AAP::R2, AAP::R3, AAP::R4, AAP::R5, AAP::R6, + AAP::R7, AAP::R8, AAP::R9, AAP::R10, AAP::R11, AAP::R12, AAP::R13, + AAP::R14, AAP::R15, AAP::R16, AAP::R17, AAP::R18, AAP::R19, AAP::R20, + AAP::R21, AAP::R22, AAP::R23, AAP::R24, AAP::R25, AAP::R26, AAP::R27, + AAP::R28, AAP::R29, AAP::R30, AAP::R31, AAP::R32, AAP::R33, AAP::R34, + AAP::R35, AAP::R36, AAP::R37, AAP::R38, AAP::R39, AAP::R40, AAP::R41, + AAP::R42, AAP::R43, AAP::R44, AAP::R45, AAP::R46, AAP::R47, AAP::R48, + AAP::R49, AAP::R50, AAP::R51, AAP::R52, AAP::R53, AAP::R54, AAP::R55, + AAP::R56, AAP::R57, AAP::R58, AAP::R59, AAP::R60, AAP::R61, AAP::R62, + AAP::R63}; + +template +static DecodeStatus decodeRegisterClass(MCInst &Inst, uint64_t RegNo, + const unsigned(&Regs)[N]) { + if (RegNo >= N) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::createReg(Regs[RegNo])); + return MCDisassembler::Success; +} + +DecodeStatus DecodeGR8RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, AAPRegs8); +} +DecodeStatus DecodeGR64RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + return decodeRegisterClass(Inst, RegNo, AAPRegs64); +} +DecodeStatus decodeMemSrcOperand(MCInst &Inst, unsigned Operand, + uint64_t Address, const void *Decoder) { + unsigned Reg = (Operand >> 16) && 0x3f; + unsigned Offset = Operand & 0xffff; + + if (decodeRegisterClass(Inst, Reg, AAPRegs64) == MCDisassembler::Fail) { + return MCDisassembler::Fail; + } + + Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset))); + return MCDisassembler::Success; +} Index: lib/Target/AAP/Disassembler/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/AAP/Disassembler/CMakeLists.txt @@ -0,0 +1,7 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMAAPDisassembler + AAPDisassembler.cpp + ) + +add_dependencies(LLVMAAPDisassembler AAPCommonTableGen) Index: lib/Target/AAP/Disassembler/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/AAP/Disassembler/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/AAP/Disassembler/LLVMBuild.txt --------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = AAPDisassembler +parent = AAP +required_libraries = Support AAPInfo MCDisassembler AAPDesc +add_to_library_groups = AAP Index: lib/Target/AAP/Disassembler/Makefile =================================================================== --- /dev/null +++ lib/Target/AAP/Disassembler/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/AAP/Disassembler/Makefile ----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMAAPDisassembler + +# Hack: we need to include 'main' AAP target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common Index: lib/Target/AAP/InstPrinter/AAPInstPrinter.h =================================================================== --- /dev/null +++ lib/Target/AAP/InstPrinter/AAPInstPrinter.h @@ -0,0 +1,57 @@ +//= AAPInstPrinter.h - Convert AAP MCInst to assembly 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 a AAP MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AAP_INSTPRINTER_AAPINSTPRINTER_H +#define LLVM_LIB_TARGET_AAP_INSTPRINTER_AAPINSTPRINTER_H + +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { +class MCOperand; + +class AAPInstPrinter : public MCInstPrinter { +public: + AAPInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + + void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, + const MCSubtargetInfo &STI) override; + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo); + + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = nullptr); + + void printPCRelImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = nullptr); + + void printMemSrcOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = nullptr, + bool WithPreDec = false, bool WithPostInc = false); + + void printMemSrcPostIncOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = nullptr); + + void printMemSrcPreDecOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = nullptr); + + +private: + void printRegister(unsigned RegNo, raw_ostream &O) const; +}; +} + +#endif Index: lib/Target/AAP/InstPrinter/AAPInstPrinter.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/InstPrinter/AAPInstPrinter.cpp @@ -0,0 +1,107 @@ +//===-- AAPInstPrinter.cpp - Convert AAP MCInst to assembly 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 AAP MCInst to a .s file. +// +//===----------------------------------------------------------------------===// + +#include "AAPInstPrinter.h" +#include "AAP.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +#define DEBUG_TYPE "asm-printer" + +// Include the auto-generated portion of the assembly writer. +#include "AAPGenAsmWriter.inc" + +void AAPInstPrinter::printInst(const MCInst *MI, raw_ostream &O, + StringRef Annot, const MCSubtargetInfo &STI) { + printInstruction(MI, O); + printAnnotation(O, Annot); +} + + +void AAPInstPrinter::printRegister(unsigned RegNo, raw_ostream &O) const { + O << '$' << getRegisterName(RegNo); +} + +void AAPInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, const char *Modifier) { + assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported"); + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isReg()) { + printRegister(Op.getReg(), O); + } else if (Op.isImm()) { + O << Op.getImm(); + } else { + assert(Op.isExpr() && "unknown operand kind in printOperand"); + O << *Op.getExpr(); + } +} + +void AAPInstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, + const char *Modifier) { + const MCOperand &Op = MI->getOperand(OpNo); + if (Op.isImm()) { + O << Op.getImm(); + } else { + assert(Op.isExpr() && "unknown pcrel immediate operand"); + O << *Op.getExpr(); + } +} + + +void AAPInstPrinter:: +printMemSrcOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier, bool WithPreDec, bool WithPostInc) { + const MCOperand &Base = MI->getOperand(OpNo); + const MCOperand &Offset = MI->getOperand(OpNo + 1); + + if (WithPreDec) { + O << '-'; + } + + // Print register base field + if (Base.getReg()) { + printRegister(Base.getReg(), O); + } + + if (WithPostInc) { + O << '+'; + } + + O << ", "; + if (Offset.isImm()) { + O << Offset.getImm(); + } + else if (Offset.isExpr()) { + O << *Offset.getExpr(); + } + else { + llvm_unreachable("Expected immediate/expression in offset field"); + } +} + +void AAPInstPrinter:: +printMemSrcPostIncOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier) { + printMemSrcOperand(MI, OpNo, O, Modifier, false, true); +} + +void AAPInstPrinter:: +printMemSrcPreDecOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier) { + printMemSrcOperand(MI, OpNo, O, Modifier, true, false); +} Index: lib/Target/AAP/InstPrinter/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/AAP/InstPrinter/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMAAPAsmPrinter + AAPInstPrinter.cpp + ) Index: lib/Target/AAP/InstPrinter/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/AAP/InstPrinter/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/AAP/InstPrinter/LLVMBuild.txt ---------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = AAPAsmPrinter +parent = AAP +required_libraries = MC Support +add_to_library_groups = AAP Index: lib/Target/AAP/InstPrinter/Makefile =================================================================== --- /dev/null +++ lib/Target/AAP/InstPrinter/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/AAP/AsmPrinter/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMAAPAsmPrinter + +# Hack: we need to include 'main' AAP target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common Index: lib/Target/AAP/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/AAP/LLVMBuild.txt @@ -0,0 +1,34 @@ +;===- ./lib/Target/AAP/LLVMBuild.txt -------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[common] +subdirectories = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo + +[component_0] +type = TargetGroup +name = AAP +parent = Target +has_asmprinter = 1 +has_asmparser = 1 +has_diassembler = 1 + +[component_1] +type = Library +name = AAPCodeGen +parent = AAP +required_libraries = CodeGen Core Support Target SelectionDAG TransformUtils AAPInfo AsmPrinter AAPAsmPrinter AAPDesc MC +add_to_library_groups = AAP Index: lib/Target/AAP/MCTargetDesc/AAPAsmBackend.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/AAPAsmBackend.cpp @@ -0,0 +1,204 @@ +//===-- AAPAsmBackend.cpp - AAP Assembler Backend -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AAPMCTargetDesc.h" +#include "MCTargetDesc/AAPFixupKinds.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCObjectWriter.h" + +using namespace llvm; + +namespace { + +class AAPAsmBackend : public MCAsmBackend { +public: + AAPAsmBackend(Target const &T) {} + + unsigned getNumFixupKinds() const override { return 15; } + + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { + const static MCFixupKindInfo Infos[AAP::NumTargetFixupKinds] = { + // We tell LLVM that branches are not PC relative to prevent it from + // resolving them, these are more complex fields which we instead want + // populate in the linker. + + // This table *must* be in the order that the fixup_* kinds are defined + // in + // AAPFixupKinds.h. + // + // Name offset size flags + {"fixup_AAP_NONE", 0, 16, 0}, + {"fixup_AAP_BR16", 0, 9, 0}, + {"fixup_AAP_BR32", 0, 9, 0}, + {"fixup_AAP_BRCC16", 6, 3, 0}, + {"fixup_AAP_BRCC32", 6, 3, 0}, + {"fixup_AAP_BAL16", 0, 3, 0}, + {"fixup_AAP_BAL32", 0, 3, 0}, + {"fixup_AAP_ABS3_SHORT", 0, 3, 0}, + {"fixup_AAP_ABS6_SHORT", 0, 6, 0}, + {"fixup_AAP_ABS6", 0, 3, 0}, + {"fixup_AAP_ABS9", 0, 3, 0}, + {"fixup_AAP_ABS10", 0, 3, 0}, + {"fixup_AAP_OFF10", 0, 3, 0}, + {"fixup_AAP_ABS12", 0, 6, 0}, + {"fixup_AAP_ABS16", 0, 6, 0} + }; + + if (Kind < FirstTargetFixupKind) + return MCAsmBackend::getFixupKindInfo(Kind); + + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && + "Invalid kind!"); + return Infos[Kind - FirstTargetFixupKind]; + } + + void applyFixup(MCFixup const &Fixup, char *Data, unsigned DataSize, + uint64_t Value, bool IsPCRel) const override { + return; + } + + bool mayNeedRelaxation(MCInst const &Inst) const override { + switch (Inst.getOpcode()) { + case AAP::NOP_short: + case AAP::ADD_i3_short: + case AAP::SUB_i3_short: + case AAP::ASR_i3_short: + case AAP::LSL_i3_short: + case AAP::LSR_i3_short: + case AAP::MOV_i6_short: + case AAP::LDB_short: + case AAP::LDW_short: + case AAP::LDB_postinc_short: + case AAP::LDW_postinc_short: + case AAP::LDB_predec_short: + case AAP::LDW_predec_short: + case AAP::STB_short: + case AAP::STW_short: + case AAP::STB_postinc_short: + case AAP::STW_postinc_short: + case AAP::STB_predec_short: + case AAP::STW_predec_short: + case AAP::BRA_short: + case AAP::BAL_short: + case AAP::BEQ_short: + case AAP::BNE_short: + case AAP::BLTS_short: + case AAP::BGTS_short: + case AAP::BLTU_short: + case AAP::BGTU_short: + // Currently, these instructions should not generate fixups so they do + // not need to be relaxed. + return false; + default: + return false; + } + } + + bool fixupNeedsRelaxation(MCFixup const &Fixup, uint64_t Value, + MCRelaxableFragment const *DF, + MCAsmLayout const &Layout) const override { + // All instructions with short fixups should be relaxed + switch((unsigned)Fixup.getKind()) { + case AAP::fixup_AAP_BR16: + case AAP::fixup_AAP_BRCC16: + case AAP::fixup_AAP_BAL16: + case AAP::fixup_AAP_ABS3_SHORT: + case AAP::fixup_AAP_ABS6_SHORT: + // At the moment, we should never generate or parse short instructions + // with these fixups. + llvm_unreachable("Cannot relax short instruction fixups!"); + return false; + default: + return false; + } + } + + + // Get the equivalent + static unsigned getRelaxedOpcode(unsigned Opcode) { + switch (Opcode) { + case AAP::NOP_short: return AAP::NOP; + case AAP::ADD_i3_short: return AAP::ADD_i10; + case AAP::SUB_i3_short: return AAP::SUB_i10; + case AAP::ASR_i3_short: return AAP::ASR_i6; + case AAP::LSL_i3_short: return AAP::LSL_i6; + case AAP::LSR_i3_short: return AAP::LSR_i6; + case AAP::MOV_i6_short: return AAP::MOV_i16; + case AAP::LDB_short: return AAP::LDB; + case AAP::LDW_short: return AAP::LDW; + case AAP::LDB_postinc_short: return AAP::LDB_postinc; + case AAP::LDW_postinc_short: return AAP::LDW_postinc; + case AAP::LDB_predec_short: return AAP::LDB_predec; + case AAP::LDW_predec_short: return AAP::LDW_predec; + case AAP::STB_short: return AAP::STB; + case AAP::STW_short: return AAP::STW; + case AAP::STB_postinc_short: return AAP::STB_postinc; + case AAP::STW_postinc_short: return AAP::STW_postinc; + case AAP::STB_predec_short: return AAP::STB_predec; + case AAP::STW_predec_short: return AAP::STW_predec; + case AAP::BRA_short: return AAP::BRA; + case AAP::BAL_short: return AAP::BAL; + case AAP::BEQ_short: return AAP::BEQ_; + case AAP::BNE_short: return AAP::BNE_; + case AAP::BLTS_short: return AAP::BLTS_; + case AAP::BGTS_short: return AAP::BGTS_; + case AAP::BLTU_short: return AAP::BLTU_; + case AAP::BGTU_short: return AAP::BGTU_; + default: + llvm_unreachable("Unknown opcode for relaxation!"); + } + return 0; + } + + void relaxInstruction(MCInst const &Inst, MCInst &Res) const override { + // The only instructions which should require relaxation are short + // instructions with fixups, and at the moment these instructions should + // not be selected or parsed + llvm_unreachable("Unexpected short instruction with fixup"); + } + + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override { + if ((Count % 2) != 0) { + return false; + } + + // 0x0000 corresponds to nop $r0, 0 + for (uint64_t i = 0; i < Count; i += 2) { + OW->write16(0x0000); + } + return true; + } +}; +} // end anonymous namespace + +namespace { +class ELFAAPAsmBackend : public AAPAsmBackend { + uint8_t OSABI; + +public: + ELFAAPAsmBackend(Target const &T, uint8_t OSABI) + : AAPAsmBackend(T), OSABI(OSABI) {} + + MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { + StringRef CPU("Default"); + return createAAPELFObjectWriter(OS, OSABI, CPU); + } +}; +} // end anonymous namespace + +namespace llvm { +MCAsmBackend *createAAPAsmBackend(Target const &T, MCRegisterInfo const &MRI, + const Triple &TT, StringRef CPU) { + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(Triple(TT).getOS()); + return new ELFAAPAsmBackend(T, OSABI); +} +} Index: lib/Target/AAP/MCTargetDesc/AAPELFObjectWriter.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/AAPELFObjectWriter.cpp @@ -0,0 +1,82 @@ +//===-- AAPELFObjectWriter.cpp - AAP Target Descriptions ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AAP.h" +#include "MCTargetDesc/AAPFixupKinds.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "aap-elfwriter" + +using namespace llvm; + +namespace { + +class AAPELFObjectWriter : public MCELFObjectTargetWriter { +private: + StringRef CPU; + +public: + AAPELFObjectWriter(uint8_t OSABI, StringRef C); + + virtual unsigned GetRelocType(MCValue const &Target, MCFixup const &Fixup, + bool IsPCRel) const override; +}; +} + +AAPELFObjectWriter::AAPELFObjectWriter(uint8_t OSABI, StringRef C) + : MCELFObjectTargetWriter(/*Is64bit*/ false, OSABI, ELF::EM_AAP, + /*HasRelocationAddend*/ true), + CPU(C) {} + +unsigned AAPELFObjectWriter::GetRelocType(MCValue const & /*Target*/, + MCFixup const &Fixup, + bool IsPCRel) const { + llvm::MCFixupKind Kind = Fixup.getKind(); + + switch ((unsigned)Kind) { + case AAP::fixup_AAP_NONE: return ELF::R_AAP_NONE; + case AAP::fixup_AAP_BR32: return ELF::R_AAP_BR32; + case AAP::fixup_AAP_BRCC32: return ELF::R_AAP_BRCC32; + case AAP::fixup_AAP_BAL32: return ELF::R_AAP_BAL32; + + case AAP::fixup_AAP_ABS6: return ELF::R_AAP_ABS6; + case AAP::fixup_AAP_ABS9: return ELF::R_AAP_ABS9; + case AAP::fixup_AAP_ABS10: return ELF::R_AAP_ABS10; + case AAP::fixup_AAP_OFF10: return ELF::R_AAP_OFF10; + case AAP::fixup_AAP_ABS12: return ELF::R_AAP_ABS12; + case AAP::fixup_AAP_ABS16: return ELF::R_AAP_ABS16; + + case FK_Data_1: return ELF::R_AAP_8; + case FK_Data_2: return ELF::R_AAP_16; + case FK_Data_4: return ELF::R_AAP_32; + case FK_Data_8: return ELF::R_AAP_64; + + // Instrs with these fixups should never be generated or parsed, so for now + // we should not be emitting relocations for them. + case AAP::fixup_AAP_BR16: + case AAP::fixup_AAP_BRCC16: + case AAP::fixup_AAP_BAL16: + case AAP::fixup_AAP_ABS3_SHORT: + case AAP::fixup_AAP_ABS6_SHORT: + llvm_unreachable("Cannot emit relocations for short instruction fixups!"); + default: + llvm_unreachable("Unimplemented fixup kind!"); + } + return ELF::R_AAP_NONE; +} + +MCObjectWriter *llvm::createAAPELFObjectWriter(raw_pwrite_stream &OS, + uint8_t OSABI, + StringRef CPU) { + MCELFObjectTargetWriter *MOTW = new AAPELFObjectWriter(OSABI, CPU); + return createELFObjectWriter(MOTW, OS, /*IsLittleEndian*/ true); +} Index: lib/Target/AAP/MCTargetDesc/AAPFixupKinds.h =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/AAPFixupKinds.h @@ -0,0 +1,58 @@ +//===-- AAPFixupKinds.h - AAP Specific Fixup Entries ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_AAP_AAPFIXUPKINDS_H +#define LLVM_AAP_AAPFIXUPKINDS_H + +#include "llvm/MC/MCFixup.h" + +namespace llvm { +namespace AAP { +// Although most of the current fixup types reflect a unique relocation +// one can have multiple fixup types for a given relocation and thus need +// to be uniquely named. +// +// This table *must* be in the save order of +// MCFixupKindInfo Infos[AAP::NumTargetFixupKinds] +// in AAPAsmBackend.cpp. +// +enum Fixups { + // Results in R_AAP_NONE + fixup_AAP_NONE = FirstTargetFixupKind, + + // Fixup for resolving branches to other basic blocks + fixup_AAP_BR16, + fixup_AAP_BR32, + + // Fixup for resolving conditional branches to other basic blocks + fixup_AAP_BRCC16, + fixup_AAP_BRCC32, + + // Branch and link fixups + fixup_AAP_BAL16, + fixup_AAP_BAL32, + + // Fixup for absolute values + fixup_AAP_ABS3_SHORT, + fixup_AAP_ABS6_SHORT, + + fixup_AAP_ABS6, + fixup_AAP_ABS9, + fixup_AAP_ABS10, + fixup_AAP_OFF10, + fixup_AAP_ABS12, + fixup_AAP_ABS16, + + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind +}; +} // end namespace AAP +} // end namespace llvm + +#endif Index: lib/Target/AAP/MCTargetDesc/AAPMCAsmInfo.h =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/AAPMCAsmInfo.h @@ -0,0 +1,32 @@ +//===-- AAPMCAsmInfo.h - AAP asm properties --------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the AAPMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AAP_MCTARGETDESC_AAPMCASMINFO_H +#define LLVM_LIB_TARGET_AAP_MCTARGETDESC_AAPMCASMINFO_H + +#include "llvm/MC/MCAsmInfoELF.h" +#include "llvm/ADT/Triple.h" + +namespace llvm { +class StringRef; + +class AAPMCAsmInfo : public MCAsmInfoELF { + void anchor() override; + +public: + explicit AAPMCAsmInfo(const Triple &TT); +}; + +} // namespace llvm + +#endif Index: lib/Target/AAP/MCTargetDesc/AAPMCAsmInfo.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/AAPMCAsmInfo.cpp @@ -0,0 +1,26 @@ +//===-- AAPMCAsmInfo.cpp - AAP asm properties -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the AAPMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "AAPMCAsmInfo.h" +#include "llvm/ADT/Triple.h" + +using namespace llvm; + +void AAPMCAsmInfo::anchor() {} + +AAPMCAsmInfo::AAPMCAsmInfo(const llvm::Triple &TT) { + PointerSize = CalleeSaveStackSlotSize = 2; + CommentString = ";"; + SupportsDebugInformation = true; + UsesELFSectionDirectiveForBSS = true; +} Index: lib/Target/AAP/MCTargetDesc/AAPMCCodeEmitter.h =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/AAPMCCodeEmitter.h @@ -0,0 +1,85 @@ +//===-- AAPMCCodeEmitter.h - AAP Code Emitter -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// Definition for classes that emit AAP machine code from MCInsts +/// +//===----------------------------------------------------------------------===// + +#ifndef AAPMCCODEEMITTER_H +#define AAPMCCODEEMITTER_H + +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class AAPMCCodeEmitter : public MCCodeEmitter { + MCContext &MCtx; + MCInstrInfo const &MCII; + +public: + AAPMCCodeEmitter(MCInstrInfo const &aMII, MCContext &aMCT); + + MCSubtargetInfo const &getSubtargetInfo() const; + + void encodeInstruction(MCInst const &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const override; + + unsigned encodePCRelImmOperand(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned encodeMemSrcOperand(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const; + + unsigned encodeImm3(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const; + unsigned encodeImm6(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const; + unsigned encodeImm9(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const; + unsigned encodeImm10(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const; + unsigned encodeImm12(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const; + unsigned encodeImm16(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const; + + // TableGen'erated function for getting the + // binary encoding for an instruction. + uint64_t getBinaryCodeForInstr(MCInst const &MI, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const; + + /// Return binary encoding of operand. + unsigned getMachineOpValue(MCInst const &MI, MCOperand const &MO, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const; + +private: + AAPMCCodeEmitter(AAPMCCodeEmitter const &) = delete; + void operator=(AAPMCCodeEmitter const &) = delete; +}; // class AAPMCCodeEmitter + +} // namespace llvm + +#endif /* AAPMCCODEEMITTER_H */ Index: lib/Target/AAP/MCTargetDesc/AAPMCCodeEmitter.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/AAPMCCodeEmitter.cpp @@ -0,0 +1,313 @@ +//===-- AAPMCCodeEmitter.cpp - AAP Target Descriptions --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AAP.h" +#include "MCTargetDesc/AAPFixupKinds.h" +#include "MCTargetDesc/AAPMCCodeEmitter.h" +#include "MCTargetDesc/AAPMCTargetDesc.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "aap-codemitter" + +using namespace llvm; +using namespace AAP; + +STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); + +namespace { +void emitLittleEndian(uint64_t Encoding, raw_ostream &OS, unsigned sz) { + while (sz > 0) { + OS << static_cast(Encoding & 0xff); + Encoding = Encoding >> 8; + sz--; + } +} +} + +AAPMCCodeEmitter::AAPMCCodeEmitter(MCInstrInfo const &MII, MCContext &Context) + : MCtx(Context), MCII(MII) {} + +void AAPMCCodeEmitter::encodeInstruction(MCInst const &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const { + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); + emitLittleEndian(Binary, OS, Desc.getSize()); + ++MCNumEmitted; +} + +unsigned AAPMCCodeEmitter::getMachineOpValue(MCInst const &MI, + MCOperand const &MO, + SmallVectorImpl &Fixups, + MCSubtargetInfo const &STI) const { + if (MO.isReg()) + return MCtx.getRegisterInfo()->getEncodingValue(MO.getReg()); + if (MO.isImm()) + return static_cast(MO.getImm()); + + // MO must be an expression + assert(MO.isExpr()); + + const MCExpr *Expr = MO.getExpr(); + MCExpr::ExprKind Kind = Expr->getKind(); + + if (Kind == MCExpr::Binary) { + Expr = static_cast(Expr)->getLHS(); + Kind = Expr->getKind(); + } + + assert(Kind == MCExpr::SymbolRef); + + AAP::Fixups FixupKind = AAP::Fixups(0); + const unsigned Opcode = MI.getOpcode(); + if (Opcode == AAP::BAL) { + FixupKind = AAP::fixup_AAP_BAL32; + } + else if (Opcode == AAP::BAL_short) { + FixupKind = AAP::fixup_AAP_BAL16; + } + else { + llvm_unreachable("Unknown fixup kind!"); + } + + // Push fixup, encoding 0 as the current operand + Fixups.push_back( + MCFixup::create(0, MO.getExpr(), MCFixupKind(FixupKind), MI.getLoc())); + return 0; +} + +MCCodeEmitter *llvm::createAAPMCCodeEmitter(MCInstrInfo const &MII, + MCRegisterInfo const &MRI, + MCContext &Context) { + return new AAPMCCodeEmitter(MII, Context); +} + + +// TODO: Better way than using LUTs? +static const unsigned BRCCOpcodes[] = { + AAP::BEQ_, AAP::BNE_, + AAP::BLTS_, AAP::BGTS_, + AAP::BLTU_, AAP::BGTU_, + + AAP::BEQ_short, AAP::BNE_short, + AAP::BLTS_short, AAP::BGTS_short, + AAP::BLTU_short, AAP::BGTU_short +}; +static const unsigned LoadStoreOpcodes[] = { + AAP::LDB, AAP::LDW, //AAP::LDD, + AAP::LDB_postinc, AAP::LDW_postinc, //AAP::LDD_postinc, + AAP::LDB_predec, AAP::LDW_predec, //AAP::LDD_predec, + + AAP::STB, AAP::STW, //AAP::STD, + AAP::STB_postinc, AAP::STW_postinc, //AAP::STD_postinc, + AAP::STB_predec, AAP::STW_predec, //AAP::STD_predec, + + AAP::LDB_short, AAP::LDW_short, + AAP::LDB_postinc_short, AAP::LDW_postinc_short, + AAP::LDB_predec_short, AAP::LDW_predec_short, + + AAP::STB_short, AAP::STW_short, + AAP::STB_postinc_short, AAP::STW_postinc_short, + AAP::STB_predec_short, AAP::STW_predec_short, +}; + +static bool findOpcode(unsigned Op, ArrayRef Opcodes) { + for (auto It = Opcodes.begin(); It != Opcodes.end(); It++) { + if (Op == *It) { + return true; + } + } + return false; +} + + +unsigned +AAPMCCodeEmitter::encodePCRelImmOperand(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(Op); + if (MO.isReg() || MO.isImm()) { + return getMachineOpValue(MI, MO, Fixups, STI); + } + + const unsigned Opcode = MI.getOpcode(); + AAP::Fixups FixupKind; + switch (Opcode) { + case AAP::BRA: + FixupKind = AAP::fixup_AAP_BR32; + break; + case AAP::BRA_short: + FixupKind = AAP::fixup_AAP_BR16; + break; + case AAP::BAL: + FixupKind = AAP::fixup_AAP_BAL32; + break; + case AAP::BAL_short: + FixupKind = AAP::fixup_AAP_BAL16; + break; + default: + if (findOpcode(Opcode, BRCCOpcodes)) { + const MCInstrDesc& Desc = MCII.get(Opcode); + if (Desc.getSize() == 4) { + FixupKind = AAP::fixup_AAP_BRCC32; + } + else { + FixupKind = AAP::fixup_AAP_BRCC16; + } + } + } + Fixups.push_back(MCFixup::create(0, MO.getExpr(), (MCFixupKind)FixupKind)); + return 0; +} + +unsigned +AAPMCCodeEmitter::encodeMemSrcOperand(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + unsigned encoding; + + // Map register number to its encoding, encode in upper 16 bits + const MCOperand RegOp = MI.getOperand(Op); + assert(RegOp.isReg() && "First operand is not a register!"); + + unsigned Reg = MCtx.getRegisterInfo()->getEncodingValue(RegOp.getReg()); + encoding = (Reg & 0xffff) << 16; + + // Immediates map directly to their encoding, map into lower 16 bits + MCOperand ImmOp = MI.getOperand(Op + 1); + if (ImmOp.isImm()) { + encoding |= static_cast(ImmOp.getImm()) & 0xffff; + return encoding; + } + + // Not an immediate, check for an expression and store as fixup to be + // resolved later + assert(ImmOp.isExpr() && "Second memsrc op not an immediate or expression!"); + + AAP::Fixups FixupKind; + const unsigned Opcode = MI.getOpcode(); + if (findOpcode(Opcode, LoadStoreOpcodes)) { + // Fixup to emit depends on whether we're encoding a memsrc for a + // short or normal length instruction + const MCInstrDesc& Desc = MCII.get(Opcode); + FixupKind = + (Desc.getSize() == 4) ? AAP::fixup_AAP_OFF10 : AAP::fixup_AAP_ABS3_SHORT; + } + else { + llvm_unreachable("Unknown opcode!"); + } + Fixups.push_back(MCFixup::create(0, ImmOp.getExpr(), MCFixupKind(FixupKind))); + return encoding; +} + +unsigned +AAPMCCodeEmitter::encodeImm3(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand MO = MI.getOperand(Op); + if (MO.isImm()) { + return static_cast(MO.getImm()); + } + + assert(MO.isExpr()); + AAP::Fixups FixupKind = AAP::fixup_AAP_ABS3_SHORT; + Fixups.push_back(MCFixup::create(0, MO.getExpr(), MCFixupKind(FixupKind))); + return 0; +} + +unsigned +AAPMCCodeEmitter::encodeImm6(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand MO = MI.getOperand(Op); + if (MO.isImm()) { + return static_cast(MO.getImm()); + } + + assert(MO.isExpr()); + + const MCInstrDesc& Desc = MCII.get(MI.getOpcode()); + AAP::Fixups FixupKind = + (Desc.getSize() == 4) ? AAP::fixup_AAP_ABS6 : AAP::fixup_AAP_ABS6_SHORT; + Fixups.push_back(MCFixup::create(0, MO.getExpr(), MCFixupKind(FixupKind))); + return 0; +} + +unsigned +AAPMCCodeEmitter::encodeImm9(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand MO = MI.getOperand(Op); + if (MO.isImm()) { + return static_cast(MO.getImm()); + } + + assert(MO.isExpr()); + AAP::Fixups FixupKind = AAP::fixup_AAP_ABS9; + Fixups.push_back(MCFixup::create(0, MO.getExpr(), MCFixupKind(FixupKind))); + return 0; +} + +unsigned +AAPMCCodeEmitter::encodeImm10(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand MO = MI.getOperand(Op); + if (MO.isImm()) { + return static_cast(MO.getImm()); + } + + assert(MO.isExpr()); + AAP::Fixups FixupKind = AAP::fixup_AAP_ABS10; + Fixups.push_back(MCFixup::create(0, MO.getExpr(), MCFixupKind(FixupKind))); + return 0; +} + +unsigned +AAPMCCodeEmitter::encodeImm12(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand MO = MI.getOperand(Op); + if (MO.isImm()) { + return static_cast(MO.getImm()); + } + + assert(MO.isExpr()); + AAP::Fixups FixupKind = AAP::fixup_AAP_ABS12; + Fixups.push_back(MCFixup::create(0, MO.getExpr(), MCFixupKind(FixupKind))); + return 0; +} + +unsigned +AAPMCCodeEmitter::encodeImm16(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand MO = MI.getOperand(Op); + if (MO.isImm()) { + return static_cast(MO.getImm()); + } + + assert(MO.isExpr()); + AAP::Fixups FixupKind = AAP::fixup_AAP_ABS16; + Fixups.push_back(MCFixup::create(0, MO.getExpr(), MCFixupKind(FixupKind))); + return 0; +} + + +#include "AAPGenMCCodeEmitter.inc" Index: lib/Target/AAP/MCTargetDesc/AAPMCTargetDesc.h =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/AAPMCTargetDesc.h @@ -0,0 +1,57 @@ +//===-- AAPMCTargetDesc.h - AAP Target Descriptions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides AAP specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AAP_MCTARGETDESC_AAPMCTARGETDESC_H +#define LLVM_LIB_TARGET_AAP_MCTARGETDESC_AAPMCTARGETDESC_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; +class MCObjectWriter; +class MCRegisterInfo; +class StringRef; +class Target; +class Triple; +class raw_pwrite_stream; + +extern Target TheAAPTarget; + +MCCodeEmitter *createAAPMCCodeEmitter(MCInstrInfo const &MCII, + MCRegisterInfo const &MRI, + MCContext &Context); + +MCAsmBackend *createAAPAsmBackend(Target const &T, MCRegisterInfo const &MRI, + const Triple &TT, StringRef CPU); + +MCObjectWriter *createAAPELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, + StringRef CPU); + +} // End llvm namespace + +// Defines symbolic names for AAP registers. +// This defines a mapping from register name to register number. +#define GET_REGINFO_ENUM +#include "AAPGenRegisterInfo.inc" + +// Defines symbolic names for the AAP instructions. +#define GET_INSTRINFO_ENUM +#include "AAPGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_ENUM +#include "AAPGenSubtargetInfo.inc" + +#endif Index: lib/Target/AAP/MCTargetDesc/AAPMCTargetDesc.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/AAPMCTargetDesc.cpp @@ -0,0 +1,96 @@ +//===-- AAPMCTargetDesc.cpp - AAP Target Descriptions ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides AAP specific target descriptions. +// +//===----------------------------------------------------------------------===// + +#include "AAPMCTargetDesc.h" +#include "InstPrinter/AAPInstPrinter.h" +#include "AAPRegisterInfo.h" +#include "AAPMCAsmInfo.h" +#include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define GET_INSTRINFO_MC_DESC +#include "AAPGenInstrInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "AAPGenSubtargetInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "AAPGenRegisterInfo.inc" + +static MCInstrInfo *createAAPMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitAAPMCInstrInfo(X); + return X; +} + +static MCRegisterInfo *createAAPMCRegisterInfo(const Triple &TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + InitAAPMCRegisterInfo(X, AAP::R0); + return X; +} + +static MCSubtargetInfo *createAAPMCSubtargetInfo(const Triple &TT, + StringRef CPU, + StringRef FS) { + return createAAPMCSubtargetInfoImpl(TT, CPU, FS); +} + +static MCCodeGenInfo *createAAPMCCodeGenInfo(const Triple &TT, Reloc::Model RM, + CodeModel::Model CM, + CodeGenOpt::Level OL) { + MCCodeGenInfo *X = new MCCodeGenInfo(); + X->initMCCodeGenInfo(RM, CM, OL); + return X; +} + +static MCInstPrinter *createAAPMCInstPrinter(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) { + if (SyntaxVariant == 0) + return new AAPInstPrinter(MAI, MII, MRI); + return nullptr; +} + +extern "C" void LLVMInitializeAAPTargetMC() { + // Register the MC asm info. + RegisterMCAsmInfo X(TheAAPTarget); + + // Register the MC codegen info. + TargetRegistry::RegisterMCCodeGenInfo(TheAAPTarget, createAAPMCCodeGenInfo); + + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(TheAAPTarget, createAAPMCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(TheAAPTarget, createAAPMCRegisterInfo); + + // Register the MC Code Emitter + TargetRegistry::RegisterMCCodeEmitter(TheAAPTarget, createAAPMCCodeEmitter); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(TheAAPTarget, + createAAPMCSubtargetInfo); + + // Register the MCInstPrinter. + TargetRegistry::RegisterMCInstPrinter(TheAAPTarget, createAAPMCInstPrinter); + + // Register the asm backend + TargetRegistry::RegisterMCAsmBackend(TheAAPTarget, createAAPAsmBackend); +} Index: lib/Target/AAP/MCTargetDesc/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMAAPDesc + AAPAsmBackend.cpp + AAPELFObjectWriter.cpp + AAPMCAsmInfo.cpp + AAPMCCodeEmitter.cpp + AAPMCTargetDesc.cpp + ) Index: lib/Target/AAP/MCTargetDesc/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/AAP/MCTargetDesc/LLVMBuild.txt --------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = AAPDesc +parent = AAP +required_libraries = MC Support AAPAsmPrinter AAPInfo +add_to_library_groups = AAP Index: lib/Target/AAP/MCTargetDesc/Makefile =================================================================== --- /dev/null +++ lib/Target/AAP/MCTargetDesc/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/AAP/TargetDesc/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMAAPDesc + +# Hack: we need to include 'main' target directory to grab private headers +CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common Index: lib/Target/AAP/Makefile =================================================================== --- /dev/null +++ lib/Target/AAP/Makefile @@ -0,0 +1,27 @@ +##===- lib/Target/AAP/Makefile ---------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMAAPCodeGen +TARGET = AAP + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = AAPGenRegisterInfo.inc \ + AAPGenInstrInfo.inc \ + AAPGenAsmWriter.inc \ + AAPGenAsmMatcher.inc \ + AAPGenDAGISel.inc \ + AAPGenDisassemblerTables.inc \ + AAPGenSubtargetInfo.inc + AAPGenCallingConv.inc \ + AAPGenMCCodeEmitter.inc + +DIRS = AsmParser Disassembler InstPrinter MCTargetDesc TargetInfo + +include $(LEVEL)/Makefile.common Index: lib/Target/AAP/TargetInfo/AAPTargetInfo.cpp =================================================================== --- /dev/null +++ lib/Target/AAP/TargetInfo/AAPTargetInfo.cpp @@ -0,0 +1,19 @@ +//===-- AAPTargetInfo.cpp - AAP Target Implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AAP.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/TargetRegistry.h" +using namespace llvm; + +Target llvm::TheAAPTarget; + +extern "C" void LLVMInitializeAAPTargetInfo() { + RegisterTarget X(TheAAPTarget, "aap", "AAP [experimental]"); +} Index: lib/Target/AAP/TargetInfo/CMakeLists.txt =================================================================== --- /dev/null +++ lib/Target/AAP/TargetInfo/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMAAPInfo + AAPTargetInfo.cpp + ) Index: lib/Target/AAP/TargetInfo/LLVMBuild.txt =================================================================== --- /dev/null +++ lib/Target/AAP/TargetInfo/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/Target/AAP/TargetInfo/LLVMBuild.txt ----------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = AAPInfo +parent = AAP +required_libraries = Support +add_to_library_groups = AAP Index: lib/Target/AAP/TargetInfo/Makefile =================================================================== --- /dev/null +++ lib/Target/AAP/TargetInfo/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/AAP/TargetInfo/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMAAPInfo + +# Hack: we need to include 'main' target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common Index: lib/Target/LLVMBuild.txt =================================================================== --- lib/Target/LLVMBuild.txt +++ lib/Target/LLVMBuild.txt @@ -19,6 +19,7 @@ ; will typically require only insertion of a line. [common] subdirectories = + AAP AMDGPU ARM AArch64 Index: test/CodeGen/AAP/add-sub.ll =================================================================== --- /dev/null +++ test/CodeGen/AAP/add-sub.ll @@ -0,0 +1,82 @@ +; RUN: llc -asm-show-inst -march=aap < %s | FileCheck %s + + +; Simple tests of basic word size add/sub operations + + +; ADD + +define i16 @add_short_imm(i16 %x) { +entry: +;CHECK: add_short_imm: +;CHECK: add ${{r[0-9]+}}, ${{r[0-9]+}}, 3 {{.*ADD_i3_short}} + %0 = add i16 %x, 3 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +; TODO: ADD_r is selected instead of ADD_i10 +define i16 @add_imm(i16 %x) { +entry: +;CHECK: add_imm: +;CHECK: add ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*ADD_r(_short)?}} + %0 = add i16 %x, 123 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @add_big_imm(i16 %x) { +entry: +;CHECK: add_big_imm: +;CHECK: mov ${{r[0-9]+}}, 21345 +;CHECK: add ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*ADD_r(_short)?}} + %0 = add i16 %x, 21345 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @add_reg(i16 %x, i16 %y) { +entry: +;CHECK: add_reg: +;CHECK: add ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*ADD_r(_short)?}} + %0 = add i16 %x, %y + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + + +; SUB + +; TODO: ADD_r is selected instead of SUB_i3_short +define i16 @sub_short_imm(i16 %x) { +entry: +;CHECK: sub_short_imm: +;CHECK: mov ${{r[0-9]+}}, -3 +;CHECK: add ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*ADD_r(_short)?}} + %0 = sub i16 %x, 3 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +; TODO: ADD_r is selected instead of SUB_i10 +define i16 @sub_imm(i16 %x) { +entry: +;CHECK: sub_imm: +;CHECK: mov ${{r[0-9]+}}, -252 +;CHECK: add ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*ADD_r(_short)?}} + %0 = sub i16 %x, 252 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +; TODO: ADD_r is selected instead of SUB_r +define i16 @sub_big_imm(i16 %x) { +entry: +;CHECK: sub_big_imm: +;CHECK: mov ${{r[0-9]+}}, -12345 +;CHECK: add ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*ADD_r(_short)?}} + %0 = sub i16 %x, 12345 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @sub_reg(i16 %x, i16 %y) { +entry: +;CHECK: sub_reg: +;CHECK: sub ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*SUB_r(_short)?}} + %0 = sub i16 %x, %y + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} Index: test/CodeGen/AAP/load.ll =================================================================== --- /dev/null +++ test/CodeGen/AAP/load.ll @@ -0,0 +1,69 @@ +; RUN: llc -asm-show-inst -march=aap < %s | FileCheck %s + + +; Check the correctness of various simple load operations. + + +@a = external global i16 +@b = external global i16 + +@c = external global i8 +@d = external global i8 + + +define i8 @ldb_global() { +entry: +;CHECK: ldb_global: +;CHECK: mov $[[REG1:r[0-9]+]], c {{.*MOV_i16}} +;CHECK: ldb ${{r[0-9]+}}, [$[[REG1]], 0] {{.*LDB(_short)?}} + %0 = load i8, i8* @c, align 1 + ret i8 %0 ;CHECK: jmp {{.*JMP}} +} + +define i8 @ldb_imm() { +entry: +;CHECK: ldb_imm: +;CHECK: mov $[[REG1:r[0-9]+]], 123 {{.*MOV_i16}} +;CHECK: ldb ${{r[0-9]+}}, [$[[REG1]], 0] {{.*LDB(_short)?}} + %0 = inttoptr i16 123 to i8* + %1 = load i8, i8* %0, align 1 + ret i8 %1 ;CHECK: jmp {{.*JMP}} +} + +define i8 @ldb_reg(i8* %x) { +entry: +;CHECK: ldb_reg: +;CHECK: ldb ${{r[0-9]+}}, [${{r[0-9]+}}, 0] {{.*LDB(_short)?}} + %0 = load i8, i8* %x, align 1 + ret i8 %0 ;CHECK: jmp {{.*JMP}} +} + + + + +define i16 @ldw_global() { +entry: +;CHECK: ldw_global: +;CHECK: mov $[[REG1:r[0-9]+]], a {{.*MOV_i16}} +;CHECK: ldw ${{r[0-9]+}}, [$[[REG1]], 0] {{.*LDW(_short)?}} + %0 = load i16, i16* @a, align 2 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @ldw_imm() { +entry: +;CHECK: ldw_imm: +;CHECK: mov $[[REG1:r[0-9]+]], 123 {{.*MOV_i16}} +;CHECK: ldw ${{r[0-9]+}}, [$[[REG1]], 0] {{.*LDW(_short)?}} + %0 = inttoptr i16 123 to i16* + %1 = load i16, i16* %0, align 2 + ret i16 %1 ;CHECK: jmp {{.*JMP}} +} + +define i16 @ldw_reg(i16* %x) { +entry: +;CHECK: ldw_reg: +;CHECK: ldw ${{r[0-9]+}}, [${{r[0-9]+}}, 0] {{.*LDW(_short)?}} + %0 = load i16, i16* %x, align 2 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} Index: test/CodeGen/AAP/logical.ll =================================================================== --- /dev/null +++ test/CodeGen/AAP/logical.ll @@ -0,0 +1,67 @@ +; RUN: llc -asm-show-inst -march=aap < %s | FileCheck %s + + +; Simple tests of basic word size logical operations + + +; AND + +; TODO: AND_r selected instead of AND_i9 +define i16 @and_imm(i16 %x) { +entry: +;CHECK: and_imm: +;CHECK: and ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*AND_r(_short)?}} + %0 = and i16 %x, 3 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @and_big_imm(i16 %x) { +entry: +;CHECK: and_big_imm: +;CHECK: mov ${{r[0-9]+}}, 19283 {{.*MOV_i16}} +;CHECK: and ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*AND_r(_short)?}} + %0 = and i16 %x, 19283 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + + +; OR + +; TODO: OR_r selected instead of OR_i9 +define i16 @or_imm(i16 %x) { +entry: +;CHECK: or_imm: +;CHECK: or ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*OR_r(_short)?}} + %0 = or i16 %x, 3 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @or_big_imm(i16 %x) { +entry: +;CHECK: or_big_imm: +;CHECK: mov ${{r[0-9]+}}, 19283 {{.*MOV_i16}} +;CHECK: or ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*OR_r(_short)?}} + %0 = or i16 %x, 19283 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + + +; XOR + +; TODO: XOR_r selected instead of XOR_i9 +define i16 @xor_imm(i16 %x) { +entry: +;CHECK: xor_imm: +;CHECK: xor ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*XOR_r(_short)?}} + %0 = xor i16 %x, 3 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @xor_big_imm(i16 %x) { +entry: +;CHECK: xor_big_imm: +;CHECK: mov ${{r[0-9]+}}, 19283 {{.*MOV_i16}} +;CHECK: xor ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*XOR_r(_short)?}} + %0 = xor i16 %x, 19283 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} Index: test/CodeGen/AAP/shift.ll =================================================================== --- /dev/null +++ test/CodeGen/AAP/shift.ll @@ -0,0 +1,88 @@ +; RUN: llc -asm-show-inst -march=aap < %s | FileCheck %s + + +; Simple tests of basic word size shift operations + + +; ASR + +define i16 @asr_small_imm(i16 %x) { +entry: +;CHECK: asr_small_imm: +;CHECK: asr ${{r[0-9]+}}, ${{r[0-9]+}}, 3 {{.*ASR_i3_short}} + %0 = ashr i16 %x, 3 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +; TODO: ASR_r is selected in preference to ASR_i9 +define i16 @asr_imm(i16 %x) { +entry: +;CHECK: asr_imm: +;CHECK: asr ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*ASR_r(_short)?}} + %0 = ashr i16 %x, 14 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @asr_reg(i16 %x, i16 %y) { +entry: +;CHECK: asr_reg: +;CHECK: asr ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*ASR_r(_short)?}} + %0 = ashr i16 %x, %y + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + + +; LSL + +define i16 @lsl_small_imm(i16 %x) { +entry: +;CHECK: lsl_small_imm: +;CHECK: lsl ${{r[0-9]+}}, ${{r[0-9]+}}, 3 {{.*LSL_i3_short}} + %0 = shl i16 %x, 3 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +; TODO: LSL_r is selected in preference to LSL_i9 +define i16 @lsl_imm(i16 %x) { +entry: +;CHECK: lsl_imm: +;CHECK: lsl ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*LSL_r(_short)?}} + %0 = shl i16 %x, 14 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @lsl_reg(i16 %x, i16 %y) { +entry: +;CHECK: lsl_reg: +;CHECK: lsl ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*LSL_r(_short)?}} + %0 = shl i16 %x, %y + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + + +; LSR + +define i16 @lsr_small_imm(i16 %x) { +entry: +;CHECK: lsr_small_imm: +;CHECK: lsr ${{r[0-9]+}}, ${{r[0-9]+}}, 3 {{.*LSR_i3_short}} + %0 = lshr i16 %x, 3 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +; TODO: LSL_r is selected in preference to LSL_i9 +define i16 @lsr_imm(i16 %x) { +entry: +;CHECK: lsr_imm: +;CHECK: lsr ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*LSR_r(_short)?}} + %0 = lshr i16 %x, 14 + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} + +define i16 @lsr_reg(i16 %x, i16 %y) { +entry: +;CHECK: lsr_reg: +;CHECK: lsr ${{r[0-9]+}}, ${{r[0-9]+}}, ${{r[0-9]+}} {{.*LSR_r(_short)?}} + %0 = lshr i16 %x, %y + ret i16 %0 ;CHECK: jmp {{.*JMP}} +} Index: test/CodeGen/AAP/store.ll =================================================================== --- /dev/null +++ test/CodeGen/AAP/store.ll @@ -0,0 +1,195 @@ +; RUN: llc -asm-show-inst -march=aap < %s | FileCheck %s + + +; Check the correctness of various simple store operations. + + +@a = external global i16 +@b = external global i16 + +@c = external global i8 +@d = external global i8 + + +define void @stb_global_global() { +entry: +;CHECK: stb_global_global: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], c {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], d {{.*MOV_i16}} +;CHECK: stb [$[[REG1]], 0], $[[REG2]] {{.*STB(_short)?}} + %0 = ptrtoint i8* @d to i8 + store i8 %0, i8* @c, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stb_global_imm() { +entry: +;CHECK: stb_global_imm: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], c {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], 123 {{.*MOV_i16}} +;CHECK: stb [$[[REG1]], 0], $[[REG2]] {{.*STB(_short)?}} + store i8 123, i8* @c, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stb_global_reg(i8 %x) { +entry: +;CHECK: stb_global_reg: +;CHECK: mov $[[REG1:r[0-9]+]], c {{.*MOV_i16}} +;CHECK: stb [$[[REG1]], 0], ${{r[0-9]+}} {{.*STB(_short)?}} + store i8 %x, i8* @c, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stb_imm_global() { +entry: +;CHECK: stb_imm_global: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], 345 {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], c {{.*MOV_i16}} +;CHECK: stb [$[[REG1]], 0], $[[REG2]] {{.*STB(_short)?}} + %0 = inttoptr i16 345 to i8* + %1 = ptrtoint i8* @c to i8 + store i8 %1, i8* %0, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stb_imm_imm() { +entry: +;CHECK: stb_imm_imm: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], 456 {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], 123 {{.*MOV_i16}} +;CHECK: stb [$[[REG1]], 0], $[[REG2]] {{.*STB(_short)?}} + %0 = inttoptr i16 456 to i8* + store i8 123, i8* %0, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stb_imm_reg(i8 %x) { +entry: +;CHECK: stb_imm_reg: +;CHECK: mov $[[REG1:r[0-9]+]], 345 {{.*MOV_i16}} +;CHECK: stb [$[[REG1]], 0], ${{r[0-9]+}} {{.*STB(_short)?}} + %0 = inttoptr i16 345 to i8* + store i8 %x, i8* %0, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stb_reg_global(i8 *%x) { +entry: +;CHECK: stb_reg_global: +;CHECK: mov $[[REG1:r[0-9]+]], c {{.*MOV_i16}} +;CHECK: stb [${{r[0-9]+}}, 0], $[[REG1]] {{.*STB(_short)?}} + %0 = ptrtoint i8* @c to i8 + store i8 %0, i8* %x, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stb_reg_imm(i8* %x) { +entry: +;CHECK: stb_reg_imm: +;CHECK: mov $[[REG1:r[0-9]+]], 123 {{.*MOV_i16}} +;CHECK: stb [${{r[0-9]+}}, 0], $[[REG1]] {{.*STB(_short)?}} + store i8 123, i8* %x, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stb_reg_reg(i8* %x, i8 %y) { +entry: +;CHECK: stb_reg_reg: +;CHECK: stb [${{r[0-9]+}}, 0], ${{r[0-9]+}} {{.*STB(_short)?}} + store i8 %y, i8* %x, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + + + + +define void @stw_global_global() { +entry: +;CHECK: stw_global_global: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], a {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], b {{.*MOV_i16}} +;CHECK: stw [$[[REG1]], 0], $[[REG2]] {{.*STW(_short)?}} + %0 = ptrtoint i16* @b to i16 + store i16 %0, i16* @a, align 2 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stw_global_imm() { +entry: +;CHECK: stw_global_imm: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], a {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], 123 {{.*MOV_i16}} +;CHECK: stw [$[[REG1]], 0], $[[REG2]] {{.*STW(_short)?}} + store i16 123, i16* @a, align 2 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stw_global_reg(i16 %x) { +entry: +;CHECK: stw_global_reg: +;CHECK: mov $[[REG1:r[0-9]+]], a {{.*MOV_i16}} +;CHECK: stw [$[[REG1]], 0], ${{r[0-9]+}} {{.*STW(_short)?}} + store i16 %x, i16* @a, align 2 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stw_imm_global() { +entry: +;CHECK: stw_imm_global: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], 345 {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], a {{.*MOV_i16}} +;CHECK: stw [$[[REG1]], 0], $[[REG2]] {{.*STW(_short)?}} + %0 = inttoptr i16 345 to i16* + %1 = ptrtoint i16* @a to i16 + store i16 %1, i16* %0, align 2 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stw_imm_imm() { +entry: +;CHECK: stw_imm_imm: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], 456 {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], 123 {{.*MOV_i16}} +;CHECK: stw [$[[REG1]], 0], $[[REG2]] {{.*STW(_short)?}} + %0 = inttoptr i16 456 to i16* + store i16 123, i16* %0, align 2 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stw_imm_reg(i16 %x) { +entry: +;CHECK: stw_imm_reg: +;CHECK: mov $[[REG1:r[0-9]+]], 345 {{.*MOV_i16}} +;CHECK: stw [$[[REG1]], 0], ${{r[0-9]+}} {{.*STW(_short)?}} + %0 = inttoptr i16 345 to i16* + store i16 %x, i16* %0, align 2 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stw_reg_global(i16 *%x) { +entry: +;CHECK: stw_reg_global: +;CHECK: mov $[[REG1:r[0-9]+]], a {{.*MOV_i16}} +;CHECK: stw [${{r[0-9]+}}, 0], $[[REG1]] {{.*STW(_short)?}} + %0 = ptrtoint i16* @a to i16 + store i16 %0, i16* %x, align 2 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stw_reg_imm(i16* %x) { +entry: +;CHECK: stw_reg_imm: +;CHECK: mov $[[REG1:r[0-9]+]], 123 {{.*MOV_i16}} +;CHECK: stw [${{r[0-9]+}}, 0], $[[REG1]] {{.*STW(_short)?}} + store i16 123, i16* %x, align 2 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @stw_reg_reg(i16* %x, i16 %y) { +entry: +;CHECK: stw_reg_reg: +;CHECK: stw [${{r[0-9]+}}, 0], ${{r[0-9]+}} {{.*STW(_short)?}} + store i16 %y, i16* %x, align 2 + ret void ;CHECK: jmp {{.*JMP}} +} Index: test/CodeGen/AAP/truncstore.ll =================================================================== --- /dev/null +++ test/CodeGen/AAP/truncstore.ll @@ -0,0 +1,108 @@ +; RUN: llc -asm-show-inst -march=aap < %s | FileCheck %s + + +; Check the correctness of truncstore operations in codegen. + + +@c = external global i8 +@d = external global i8 + + +define void @truncstore_i16_i8_global_global() { +entry: +;CHECK: truncstore_i16_i8_global_global: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], c {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], d {{.*MOV_i16}} +;CHECK: stb [$[[REG2]], 0], $[[REG1]] {{.*STB(_short)?}} + %0 = ptrtoint i8* @c to i16 + %1 = trunc i16 %0 to i8 + store i8 %1, i8* @d, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @truncstore_i16_i8_global_imm() { +entry: +;CHECK: truncstore_i16_i8_global_imm: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], 210 {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], c {{.*MOV_i16}} +;CHECK: stb [$[[REG2]], 0], $[[REG1]] {{.*STB(_short)?}} + %0 = trunc i16 1234 to i8 + store i8 %0, i8* @c, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @truncstore_i16_i8_global_reg(i16 %x) { +entry: +;CHECK: truncstore_i16_i8_global_reg: +;CHECK: mov $[[REG2:r[0-9]+]], c {{.*MOV_i16}} +;CHECK: stb [$[[REG2]], 0], ${{r[0-9]+}} {{.*STB(_short)?}} + %0 = trunc i16 %x to i8 + store i8 %0, i8* @c, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @truncstore_i16_i8_imm_global() { +entry: +;CHECK: truncstore_i16_i8_imm_global: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], c {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], 1234 {{.*MOV_i16}} +;CHECK: stb [$[[REG2]], 0], $[[REG1]] {{.*STB(_short)?}} + %0 = ptrtoint i8* @c to i16 + %1 = trunc i16 %0 to i8 + %2 = inttoptr i16 1234 to i8* + store i8 %1, i8* %2, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @truncstore_i16_i8_imm_imm() { +entry: +;CHECK: truncstore_i16_i8_imm_imm: +;CHECK-DAG: mov $[[REG1:r[0-9]+]], 215 {{.*MOV_i16}} +;CHECK-DAG: mov $[[REG2:r[0-9]+]], 1234 {{.*MOV_i16}} +;CHECK: stb [$[[REG2]], 0], $[[REG1]] {{.*STB(_short)?}} + %0 = trunc i16 4567 to i8 + %1 = inttoptr i16 1234 to i8* + store i8 %0, i8* %1, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @truncstore_i16_i8_imm_reg(i16 %x) { +entry: +;CHECK: truncstore_i16_i8_imm_reg: +;CHECK: mov $[[REG1:r[0-9]+]], 1234 {{.*MOV_i16}} +;CHECK: stb [$[[REG1]], 0], ${{r[0-9]+}} {{.*STB(_short)?}} + %0 = trunc i16 %x to i8 + %1 = inttoptr i16 1234 to i8* + store i8 %0, i8* %1, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @truncstore_i16_i8_reg_global(i8* %x) { +entry: +;CHECK: truncstore_i16_i8_reg_global: +;CHECK: mov $[[REG1:r[0-9]+]], c {{.*MOV_i16}} +;CHECK: stb [${{r[0-9]+}}, 0], $[[REG1]] {{.*STB(_short)?}} + %0 = ptrtoint i8* @c to i16 + %1 = trunc i16 %0 to i8 + store i8 %1, i8* %x, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @truncstore_i16_i8_reg_imm(i8* %x) { +entry: +;CHECK: truncstore_i16_i8_reg_imm: +;CHECK: mov $[[REG1:r[0-9]+]], 215 {{.*MOV_i16}} +;CHECK: stb [${{r[0-9]+}}, 0], $[[REG1]] {{.*STB(_short)?}} + %0 = trunc i16 4567 to i8 + store i8 %0, i8* %x, align 1 + ret void ;CHECK: jmp {{.*JMP}} +} + +define void @truncstore_i16_i8_reg_reg(i8* %x, i16 %y) { +entry: +;CHECK: truncstore_i16_i8_reg_reg: +;CHECK: stb [${{r[0-9]+}}, 0], ${{r[0-9]+}} {{.*STB(_short)?}} + %0 = trunc i16 %y to i8 + store i8 %0, i8* %x, align 1 + ret void ;CHECK: jmp {{.*JMP}} +}