mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[lanai] Add Lanai backend.
Add the Lanai backend to lib/Target. General Lanai backend discussion on llvm-dev thread "[RFC] Lanai backend" (http://lists.llvm.org/pipermail/llvm-dev/2016-February/095118.html). Differential Revision: http://reviews.llvm.org/D17011 llvm-svn: 264578
This commit is contained in:
parent
d84de52bea
commit
9af311f3de
@ -142,6 +142,10 @@ N: Krzysztof Parzyszek
|
||||
E: kparzysz@codeaurora.org
|
||||
D: Hexagon Backend
|
||||
|
||||
N: Jacques Pienaar
|
||||
E: jpienaar@google.com
|
||||
D: Lanai Backend
|
||||
|
||||
N: Paul Robinson
|
||||
E: paul_robinson@playstation.sony.com
|
||||
D: Sony PlayStation®4 support
|
||||
|
@ -194,6 +194,7 @@ ScalarEnumerationTraits<ELFYAML::ELF_EM>::enumeration(IO &IO,
|
||||
ECase(EM_78KOR)
|
||||
ECase(EM_56800EX)
|
||||
ECase(EM_AMDGPU)
|
||||
ECase(EM_LANAI)
|
||||
#undef ECase
|
||||
}
|
||||
|
||||
@ -527,6 +528,9 @@ void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration(
|
||||
case ELF::EM_ARM:
|
||||
#include "llvm/Support/ELFRelocs/ARM.def"
|
||||
break;
|
||||
case ELF::EM_LANAI:
|
||||
#include "llvm/Support/ELFRelocs/Lanai.def"
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unsupported architecture");
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ subdirectories =
|
||||
AVR
|
||||
BPF
|
||||
CppBackend
|
||||
Lanai
|
||||
Hexagon
|
||||
MSP430
|
||||
NVPTX
|
||||
|
7
lib/Target/Lanai/AsmParser/CMakeLists.txt
Normal file
7
lib/Target/Lanai/AsmParser/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
|
||||
|
||||
add_llvm_library(LLVMLanaiAsmParser
|
||||
LanaiAsmParser.cpp
|
||||
)
|
||||
|
||||
add_dependencies( LLVMLanaiAsmParser LanaiCommonTableGen )
|
23
lib/Target/Lanai/AsmParser/LLVMBuild.txt
Normal file
23
lib/Target/Lanai/AsmParser/LLVMBuild.txt
Normal file
@ -0,0 +1,23 @@
|
||||
;===- ./lib/Target/Lanai/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 = LanaiAsmParser
|
||||
parent = Lanai
|
||||
required_libraries = MC MCParser Support LanaiMCTargetDesc LanaiInfo
|
||||
add_to_library_groups = Lanai
|
1162
lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
Normal file
1162
lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
36
lib/Target/Lanai/CMakeLists.txt
Normal file
36
lib/Target/Lanai/CMakeLists.txt
Normal file
@ -0,0 +1,36 @@
|
||||
set(LLVM_TARGET_DEFINITIONS Lanai.td)
|
||||
|
||||
tablegen(LLVM LanaiGenAsmMatcher.inc -gen-asm-matcher)
|
||||
tablegen(LLVM LanaiGenAsmWriter.inc -gen-asm-writer)
|
||||
tablegen(LLVM LanaiGenCallingConv.inc -gen-callingconv)
|
||||
tablegen(LLVM LanaiGenDAGISel.inc -gen-dag-isel)
|
||||
tablegen(LLVM LanaiGenDisassemblerTables.inc -gen-disassembler)
|
||||
tablegen(LLVM LanaiGenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM LanaiGenMCCodeEmitter.inc -gen-emitter)
|
||||
tablegen(LLVM LanaiGenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM LanaiGenSubtargetInfo.inc -gen-subtarget)
|
||||
add_public_tablegen_target(LanaiCommonTableGen)
|
||||
|
||||
add_llvm_target(LanaiCodeGen
|
||||
LanaiAsmPrinter.cpp
|
||||
LanaiDelaySlotFiller.cpp
|
||||
LanaiFrameLowering.cpp
|
||||
LanaiInstrInfo.cpp
|
||||
LanaiISelDAGToDAG.cpp
|
||||
LanaiISelLowering.cpp
|
||||
LanaiMachineFunctionInfo.cpp
|
||||
LanaiMCInstLower.cpp
|
||||
LanaiMemAluCombiner.cpp
|
||||
LanaiRegisterInfo.cpp
|
||||
LanaiSelectionDAGInfo.cpp
|
||||
LanaiSetflagAluCombiner.cpp
|
||||
LanaiSubtarget.cpp
|
||||
LanaiTargetMachine.cpp
|
||||
LanaiTargetObjectFile.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(AsmParser)
|
||||
add_subdirectory(TargetInfo)
|
||||
add_subdirectory(MCTargetDesc)
|
||||
add_subdirectory(InstPrinter)
|
||||
add_subdirectory(Disassembler)
|
3
lib/Target/Lanai/Disassembler/CMakeLists.txt
Normal file
3
lib/Target/Lanai/Disassembler/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
add_llvm_library(LLVMLanaiDisassembler
|
||||
LanaiDisassembler.cpp
|
||||
)
|
23
lib/Target/Lanai/Disassembler/LLVMBuild.txt
Normal file
23
lib/Target/Lanai/Disassembler/LLVMBuild.txt
Normal file
@ -0,0 +1,23 @@
|
||||
;===-- ./lib/Target/Lanai/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 = LanaiDisassembler
|
||||
parent = Lanai
|
||||
required_libraries = LanaiMCTargetDesc LanaiInfo MC MCDisassembler Support
|
||||
add_to_library_groups = Lanai
|
228
lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
Normal file
228
lib/Target/Lanai/Disassembler/LanaiDisassembler.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
//===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- 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 Lanai Disassembler.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiDisassembler.h"
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiSubtarget.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"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
typedef MCDisassembler::DecodeStatus DecodeStatus;
|
||||
|
||||
namespace llvm {
|
||||
extern Target TheLanaiTarget;
|
||||
}
|
||||
|
||||
static MCDisassembler *createLanaiDisassembler(const Target &T,
|
||||
const MCSubtargetInfo &STI,
|
||||
MCContext &Ctx) {
|
||||
return new LanaiDisassembler(STI, Ctx);
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeLanaiDisassembler() {
|
||||
// Register the disassembler
|
||||
TargetRegistry::RegisterMCDisassembler(TheLanaiTarget,
|
||||
createLanaiDisassembler);
|
||||
}
|
||||
|
||||
LanaiDisassembler::LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
|
||||
: MCDisassembler(STI, Ctx) {}
|
||||
|
||||
// Forward declare because the autogenerated code will reference this.
|
||||
// Definition is further down.
|
||||
DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
|
||||
uint64_t Address, const void *Decoder);
|
||||
|
||||
static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
|
||||
static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
|
||||
static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
|
||||
static DecodeStatus decodeBranch(MCInst &Inst, unsigned Insn, uint64_t Address,
|
||||
const void *Decoder);
|
||||
|
||||
static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder);
|
||||
|
||||
#include "LanaiGenDisassemblerTables.inc"
|
||||
|
||||
static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||
uint64_t &Size, uint32_t &Insn) {
|
||||
// We want to read exactly 4 bytes of data.
|
||||
if (Bytes.size() < 4) {
|
||||
Size = 0;
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
|
||||
// Encoded as big-endian 32-bit word in the stream.
|
||||
Insn =
|
||||
(Bytes[0] << 24) | (Bytes[1] << 16) | (Bytes[2] << 8) | (Bytes[3] << 0);
|
||||
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static void PostOperandDecodeAdjust(MCInst &Instr, uint32_t Insn) {
|
||||
unsigned AluOp = LPAC::ADD;
|
||||
// Fix up for pre and post operations.
|
||||
int PqShift = -1;
|
||||
if (isRMOpcode(Instr.getOpcode()))
|
||||
PqShift = 16;
|
||||
else if (isSPLSOpcode(Instr.getOpcode()))
|
||||
PqShift = 10;
|
||||
else if (isRRMOpcode(Instr.getOpcode())) {
|
||||
PqShift = 16;
|
||||
// Determine RRM ALU op.
|
||||
AluOp = (Insn >> 8) & 0x7;
|
||||
if (AluOp == 7)
|
||||
// Handle JJJJJ
|
||||
// 0b10000 or 0b11000
|
||||
AluOp |= 0x20 | (((Insn >> 3) & 0xf) << 1);
|
||||
}
|
||||
|
||||
if (PqShift != -1) {
|
||||
unsigned PQ = (Insn >> PqShift) & 0x3;
|
||||
switch (PQ) {
|
||||
case 0x0:
|
||||
if (Instr.getOperand(2).isReg()) {
|
||||
Instr.getOperand(2).setReg(Lanai::R0);
|
||||
}
|
||||
if (Instr.getOperand(2).isImm())
|
||||
Instr.getOperand(2).setImm(0);
|
||||
break;
|
||||
case 0x1:
|
||||
AluOp = LPAC::makePostOp(AluOp);
|
||||
break;
|
||||
case 0x2:
|
||||
break;
|
||||
case 0x3:
|
||||
AluOp = LPAC::makePreOp(AluOp);
|
||||
break;
|
||||
}
|
||||
Instr.addOperand(MCOperand::createImm(AluOp));
|
||||
}
|
||||
}
|
||||
|
||||
DecodeStatus LanaiDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
|
||||
ArrayRef<uint8_t> Bytes,
|
||||
uint64_t Address,
|
||||
raw_ostream &VStream,
|
||||
raw_ostream &CStream) const {
|
||||
uint32_t Insn;
|
||||
|
||||
DecodeStatus Result = readInstruction32(Bytes, Address, Size, Insn);
|
||||
|
||||
if (Result == MCDisassembler::Fail)
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
// Call auto-generated decoder function
|
||||
Result =
|
||||
decodeInstruction(DecoderTableLanai32, Instr, Insn, Address, this, STI);
|
||||
|
||||
if (Result != MCDisassembler::Fail) {
|
||||
PostOperandDecodeAdjust(Instr, Insn);
|
||||
Size = 4;
|
||||
return Result;
|
||||
}
|
||||
|
||||
return MCDisassembler::Fail;
|
||||
}
|
||||
|
||||
static const unsigned GPRDecoderTable[] = {
|
||||
Lanai::R0, Lanai::R1, Lanai::PC, Lanai::R3, Lanai::SP, Lanai::FP,
|
||||
Lanai::R6, Lanai::R7, Lanai::RV, Lanai::R9, Lanai::RR1, Lanai::RR2,
|
||||
Lanai::R12, Lanai::R13, Lanai::R14, Lanai::RCA, Lanai::R16, Lanai::R17,
|
||||
Lanai::R18, Lanai::R19, Lanai::R20, Lanai::R21, Lanai::R22, Lanai::R23,
|
||||
Lanai::R24, Lanai::R25, Lanai::R26, Lanai::R27, Lanai::R28, Lanai::R29,
|
||||
Lanai::R30, Lanai::R31};
|
||||
|
||||
DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
if (RegNo > 31)
|
||||
return MCDisassembler::Fail;
|
||||
|
||||
unsigned Reg = GPRDecoderTable[RegNo];
|
||||
Inst.addOperand(MCOperand::createReg(Reg));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static DecodeStatus decodeRiMemoryValue(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
// RI memory values encoded using 23 bits:
|
||||
// 5 bit register, 16 bit constant
|
||||
unsigned Register = (Insn >> 18) & 0x1f;
|
||||
Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
|
||||
unsigned Offset = (Insn & 0xffff);
|
||||
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
|
||||
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static DecodeStatus decodeRrMemoryValue(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
// RR memory values encoded using 20 bits:
|
||||
// 5 bit register, 5 bit register, 2 bit PQ, 3 bit ALU operator, 5 bit JJJJJ
|
||||
unsigned Register = (Insn >> 15) & 0x1f;
|
||||
Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
|
||||
Register = (Insn >> 10) & 0x1f;
|
||||
Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
|
||||
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static DecodeStatus decodeSplsValue(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
// RI memory values encoded using 17 bits:
|
||||
// 5 bit register, 10 bit constant
|
||||
unsigned Register = (Insn >> 12) & 0x1f;
|
||||
Inst.addOperand(MCOperand::createReg(GPRDecoderTable[Register]));
|
||||
unsigned Offset = (Insn & 0x3ff);
|
||||
Inst.addOperand(MCOperand::createImm(SignExtend32<10>(Offset)));
|
||||
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static bool tryAddingSymbolicOperand(int64_t Value, bool IsBranch,
|
||||
uint64_t Address, uint64_t Offset,
|
||||
uint64_t Width, MCInst &MI,
|
||||
const void *Decoder) {
|
||||
const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder);
|
||||
return Dis->tryAddingSymbolicOperand(MI, Value, Address, IsBranch, Offset,
|
||||
Width);
|
||||
}
|
||||
|
||||
static DecodeStatus decodeBranch(MCInst &MI, unsigned Insn, uint64_t Address,
|
||||
const void *Decoder) {
|
||||
if (!tryAddingSymbolicOperand(Insn + Address, false, Address, 2, 23, MI,
|
||||
Decoder))
|
||||
MI.addOperand(MCOperand::createImm(Insn));
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
static DecodeStatus decodeShiftImm(MCInst &Inst, unsigned Insn,
|
||||
uint64_t Address, const void *Decoder) {
|
||||
unsigned Offset = (Insn & 0xffff);
|
||||
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Offset)));
|
||||
|
||||
return MCDisassembler::Success;
|
||||
}
|
41
lib/Target/Lanai/Disassembler/LanaiDisassembler.h
Normal file
41
lib/Target/Lanai/Disassembler/LanaiDisassembler.h
Normal file
@ -0,0 +1,41 @@
|
||||
//===- LanaiDisassembler.cpp - Disassembler for Lanai -----------*- 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 Lanai Disassembler.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_DISASSEMBLER_LANAIDISASSEMBLER_H
|
||||
#define LLVM_LIB_TARGET_LANAI_DISASSEMBLER_LANAIDISASSEMBLER_H
|
||||
|
||||
#define DEBUG_TYPE "lanai-disassembler"
|
||||
|
||||
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCInst;
|
||||
class raw_ostream;
|
||||
|
||||
class LanaiDisassembler : public MCDisassembler {
|
||||
public:
|
||||
LanaiDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx);
|
||||
|
||||
~LanaiDisassembler() override {}
|
||||
|
||||
// getInstruction - See MCDisassembler.
|
||||
MCDisassembler::DecodeStatus
|
||||
getInstruction(MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes,
|
||||
uint64_t Address, raw_ostream &VStream,
|
||||
raw_ostream &CStream) const override;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_DISASSEMBLER_LANAIDISASSEMBLER_H
|
3
lib/Target/Lanai/InstPrinter/CMakeLists.txt
Normal file
3
lib/Target/Lanai/InstPrinter/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
add_llvm_library(LLVMLanaiInstPrinter
|
||||
LanaiInstPrinter.cpp
|
||||
)
|
23
lib/Target/Lanai/InstPrinter/LLVMBuild.txt
Normal file
23
lib/Target/Lanai/InstPrinter/LLVMBuild.txt
Normal file
@ -0,0 +1,23 @@
|
||||
;===-- ./lib/Target/Lanai/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 = LanaiInstPrinter
|
||||
parent = Lanai
|
||||
required_libraries = LanaiInfo MC Support
|
||||
add_to_library_groups = Lanai
|
309
lib/Target/Lanai/InstPrinter/LanaiInstPrinter.cpp
Normal file
309
lib/Target/Lanai/InstPrinter/LanaiInstPrinter.cpp
Normal file
@ -0,0 +1,309 @@
|
||||
//===-- LanaiInstPrinter.cpp - Convert Lanai MCInst to asm syntax ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints an Lanai MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiInstPrinter.h"
|
||||
#include "MCTargetDesc/LanaiMCExpr.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCSymbol.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.
|
||||
#define PRINT_ALIAS_INSTR
|
||||
#include "LanaiGenAsmWriter.inc"
|
||||
|
||||
void LanaiInstPrinter::printRegName(raw_ostream &Ostream,
|
||||
unsigned RegNo) const {
|
||||
Ostream << StringRef(getRegisterName(RegNo)).lower();
|
||||
}
|
||||
|
||||
bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &Ostream,
|
||||
StringRef Alias, unsigned OpNo0,
|
||||
unsigned OpNo1) {
|
||||
Ostream << "\t" << Alias << " ";
|
||||
printOperand(MI, OpNo0, Ostream);
|
||||
Ostream << ", ";
|
||||
printOperand(MI, OpNo1, Ostream);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool usesGivenOffset(const MCInst *MI, int AddOffset) {
|
||||
unsigned AluCode = MI->getOperand(3).getImm();
|
||||
return LPAC::encodeLanaiAluCode(AluCode) == LPAC::ADD &&
|
||||
(MI->getOperand(2).getImm() == AddOffset ||
|
||||
MI->getOperand(2).getImm() == -AddOffset);
|
||||
}
|
||||
|
||||
static bool isPreIncrementForm(const MCInst *MI, int AddOffset) {
|
||||
unsigned AluCode = MI->getOperand(3).getImm();
|
||||
return LPAC::isPreOp(AluCode) && usesGivenOffset(MI, AddOffset);
|
||||
}
|
||||
|
||||
static bool isPostIncrementForm(const MCInst *MI, int AddOffset) {
|
||||
unsigned AluCode = MI->getOperand(3).getImm();
|
||||
return LPAC::isPostOp(AluCode) && usesGivenOffset(MI, AddOffset);
|
||||
}
|
||||
|
||||
static StringRef decIncOperator(const MCInst *MI) {
|
||||
if (MI->getOperand(2).getImm() < 0)
|
||||
return "--";
|
||||
return "++";
|
||||
}
|
||||
|
||||
bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
|
||||
raw_ostream &Ostream,
|
||||
StringRef Opcode,
|
||||
int AddOffset) {
|
||||
if (isPreIncrementForm(MI, AddOffset)) {
|
||||
Ostream << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
|
||||
<< getRegisterName(MI->getOperand(1).getReg()) << "], %"
|
||||
<< getRegisterName(MI->getOperand(0).getReg());
|
||||
return true;
|
||||
}
|
||||
if (isPostIncrementForm(MI, AddOffset)) {
|
||||
Ostream << "\t" << Opcode << "\t[%"
|
||||
<< getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
|
||||
<< "], %" << getRegisterName(MI->getOperand(0).getReg());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
|
||||
raw_ostream &Ostream,
|
||||
StringRef Opcode,
|
||||
int AddOffset) {
|
||||
if (isPreIncrementForm(MI, AddOffset)) {
|
||||
Ostream << "\t" << Opcode << "\t%"
|
||||
<< getRegisterName(MI->getOperand(0).getReg()) << ", ["
|
||||
<< decIncOperator(MI) << "%"
|
||||
<< getRegisterName(MI->getOperand(1).getReg()) << "]";
|
||||
return true;
|
||||
}
|
||||
if (isPostIncrementForm(MI, AddOffset)) {
|
||||
Ostream << "\t" << Opcode << "\t%"
|
||||
<< getRegisterName(MI->getOperand(0).getReg()) << ", [%"
|
||||
<< getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
|
||||
<< "]";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &Ostream) {
|
||||
switch (MI->getOpcode()) {
|
||||
case Lanai::LDW_RI:
|
||||
// ld 4[*%rN], %rX => ld [++imm], %rX
|
||||
// ld -4[*%rN], %rX => ld [--imm], %rX
|
||||
// ld 4[%rN*], %rX => ld [imm++], %rX
|
||||
// ld -4[%rN*], %rX => ld [imm--], %rX
|
||||
return printMemoryLoadIncrement(MI, Ostream, "ld", 4);
|
||||
case Lanai::LDHs_RI:
|
||||
return printMemoryLoadIncrement(MI, Ostream, "ld.h", 2);
|
||||
case Lanai::LDHz_RI:
|
||||
return printMemoryLoadIncrement(MI, Ostream, "uld.h", 2);
|
||||
case Lanai::LDBs_RI:
|
||||
return printMemoryLoadIncrement(MI, Ostream, "ld.b", 1);
|
||||
case Lanai::LDBz_RI:
|
||||
return printMemoryLoadIncrement(MI, Ostream, "uld.b", 1);
|
||||
case Lanai::SW_RI:
|
||||
// st %rX, 4[*%rN] => st %rX, [++imm]
|
||||
// st %rX, -4[*%rN] => st %rX, [--imm]
|
||||
// st %rX, 4[%rN*] => st %rX, [imm++]
|
||||
// st %rX, -4[%rN*] => st %rX, [imm--]
|
||||
return printMemoryStoreIncrement(MI, Ostream, "st", 4);
|
||||
case Lanai::STH_RI:
|
||||
return printMemoryStoreIncrement(MI, Ostream, "st.h", 2);
|
||||
case Lanai::STB_RI:
|
||||
return printMemoryStoreIncrement(MI, Ostream, "st.b", 1);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &Ostream,
|
||||
StringRef Annotation,
|
||||
const MCSubtargetInfo &STI) {
|
||||
if (!printAlias(MI, Ostream) && !printAliasInstr(MI, Ostream))
|
||||
printInstruction(MI, Ostream);
|
||||
printAnnotation(Ostream, Annotation);
|
||||
}
|
||||
|
||||
static void printExpr(const MCAsmInfo &MAI, const MCExpr &Expr,
|
||||
raw_ostream &Ostream) {
|
||||
const MCExpr *SRE;
|
||||
|
||||
if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(&Expr))
|
||||
SRE = dyn_cast<LanaiMCExpr>(BE->getLHS());
|
||||
else if (isa<LanaiMCExpr>(&Expr)) {
|
||||
SRE = dyn_cast<LanaiMCExpr>(&Expr);
|
||||
} else {
|
||||
SRE = dyn_cast<MCSymbolRefExpr>(&Expr);
|
||||
}
|
||||
assert(SRE && "Unexpected MCExpr type.");
|
||||
|
||||
SRE->print(Ostream, &MAI);
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &Ostream,
|
||||
const char *Modifier) {
|
||||
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
if (Op.isReg())
|
||||
Ostream << "%" << getRegisterName(Op.getReg());
|
||||
else if (Op.isImm())
|
||||
Ostream << formatHex(Op.getImm());
|
||||
else {
|
||||
assert(Op.isExpr() && "Expected an expression");
|
||||
printExpr(MAI, *Op.getExpr(), Ostream);
|
||||
}
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &Ostream) {
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
if (Op.isImm()) {
|
||||
Ostream << '[' << formatHex(Op.getImm()) << ']';
|
||||
} else {
|
||||
// Symbolic operand will be lowered to immediate value by linker
|
||||
assert(Op.isExpr() && "Expected an expression");
|
||||
Ostream << '[';
|
||||
printExpr(MAI, *Op.getExpr(), Ostream);
|
||||
Ostream << ']';
|
||||
}
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &Ostream) {
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
if (Op.isImm()) {
|
||||
Ostream << formatHex(Op.getImm() << 16);
|
||||
} else {
|
||||
// Symbolic operand will be lowered to immediate value by linker
|
||||
assert(Op.isExpr() && "Expected an expression");
|
||||
printExpr(MAI, *Op.getExpr(), Ostream);
|
||||
}
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &Ostream) {
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
if (Op.isImm()) {
|
||||
Ostream << formatHex((Op.getImm() << 16) | 0xffff);
|
||||
} else {
|
||||
// Symbolic operand will be lowered to immediate value by linker
|
||||
assert(Op.isExpr() && "Expected an expression");
|
||||
printExpr(MAI, *Op.getExpr(), Ostream);
|
||||
}
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &Ostream) {
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
if (Op.isImm()) {
|
||||
Ostream << formatHex(0xffff0000 | Op.getImm());
|
||||
} else {
|
||||
// Symbolic operand will be lowered to immediate value by linker
|
||||
assert(Op.isExpr() && "Expected an expression");
|
||||
printExpr(MAI, *Op.getExpr(), Ostream);
|
||||
}
|
||||
}
|
||||
|
||||
static void printMemoryBaseRegister(raw_ostream &Ostream, const unsigned AluCode,
|
||||
const MCOperand &RegOp) {
|
||||
assert(RegOp.isReg() && "Register operand expected");
|
||||
Ostream << "[";
|
||||
if (LPAC::isPreOp(AluCode))
|
||||
Ostream << "*";
|
||||
Ostream << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
|
||||
if (LPAC::isPostOp(AluCode))
|
||||
Ostream << "*";
|
||||
Ostream << "]";
|
||||
}
|
||||
|
||||
template <unsigned SizeInBits>
|
||||
static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
|
||||
const MCOperand &OffsetOp,
|
||||
raw_ostream &Ostream) {
|
||||
assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
|
||||
if (OffsetOp.isImm()) {
|
||||
assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
|
||||
Ostream << OffsetOp.getImm();
|
||||
} else
|
||||
printExpr(MAI, *OffsetOp.getExpr(), Ostream);
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
|
||||
raw_ostream &Ostream,
|
||||
const char *Modifier) {
|
||||
const MCOperand &RegOp = MI->getOperand(OpNo);
|
||||
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
|
||||
const MCOperand &AluOp = MI->getOperand(OpNo + 2);
|
||||
const unsigned AluCode = AluOp.getImm();
|
||||
|
||||
// Offset
|
||||
printMemoryImmediateOffset<16>(MAI, OffsetOp, Ostream);
|
||||
|
||||
// Register
|
||||
printMemoryBaseRegister(Ostream, AluCode, RegOp);
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
|
||||
raw_ostream &Ostream,
|
||||
const char *Modifier) {
|
||||
const MCOperand &RegOp = MI->getOperand(OpNo);
|
||||
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
|
||||
const MCOperand &AluOp = MI->getOperand(OpNo + 2);
|
||||
const unsigned AluCode = AluOp.getImm();
|
||||
assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
|
||||
|
||||
// [ Base OP Offset ]
|
||||
Ostream << "[";
|
||||
if (LPAC::isPreOp(AluCode))
|
||||
Ostream << "*";
|
||||
Ostream << "%" << getRegisterName(RegOp.getReg());
|
||||
if (LPAC::isPostOp(AluCode))
|
||||
Ostream << "*";
|
||||
Ostream << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
|
||||
Ostream << "%" << getRegisterName(OffsetOp.getReg());
|
||||
Ostream << "]";
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
|
||||
raw_ostream &Ostream,
|
||||
const char *Modifier) {
|
||||
const MCOperand &RegOp = MI->getOperand(OpNo);
|
||||
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
|
||||
const MCOperand &AluOp = MI->getOperand(OpNo + 2);
|
||||
const unsigned AluCode = AluOp.getImm();
|
||||
|
||||
// Offset
|
||||
printMemoryImmediateOffset<10>(MAI, OffsetOp, Ostream);
|
||||
|
||||
// Register
|
||||
printMemoryBaseRegister(Ostream, AluCode, RegOp);
|
||||
}
|
||||
|
||||
void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
|
||||
raw_ostream &Ostream) {
|
||||
const int CC = static_cast<const int>(MI->getOperand(OpNo).getImm());
|
||||
Ostream << lanaiCondCodeToString(static_cast<LPCC::CondCode>(CC));
|
||||
}
|
64
lib/Target/Lanai/InstPrinter/LanaiInstPrinter.h
Normal file
64
lib/Target/Lanai/InstPrinter/LanaiInstPrinter.h
Normal file
@ -0,0 +1,64 @@
|
||||
//= LanaiInstPrinter.h - Convert Lanai MCInst to asm syntax -------*- C++ -*--//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints a Lanai MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_INSTPRINTER_LANAIINSTPRINTER_H
|
||||
#define LLVM_LIB_TARGET_LANAI_INSTPRINTER_LANAIINSTPRINTER_H
|
||||
|
||||
#include "llvm/MC/MCInstPrinter.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCOperand;
|
||||
|
||||
class LanaiInstPrinter : public MCInstPrinter {
|
||||
public:
|
||||
LanaiInstPrinter(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;
|
||||
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
|
||||
const char *Modifier = 0);
|
||||
void printMemRiOperand(const MCInst *MI, int OpNo, raw_ostream &O,
|
||||
const char *Modifier = 0);
|
||||
void printMemRrOperand(const MCInst *MI, int OpNo, raw_ostream &O,
|
||||
const char *Modifier = 0);
|
||||
void printMemSplsOperand(const MCInst *MI, int OpNo, raw_ostream &O,
|
||||
const char *Modifier = 0);
|
||||
void printCCOperand(const MCInst *MI, int OpNo, raw_ostream &O);
|
||||
void printAluOperand(const MCInst *MI, int OpNo, raw_ostream &O);
|
||||
void printHi16ImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||
void printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||
void printLo16AndImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||
void printMemImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||
|
||||
// Autogenerated by tblgen.
|
||||
void printInstruction(const MCInst *MI, raw_ostream &O);
|
||||
bool printAliasInstr(const MCInst *MI, raw_ostream &OS);
|
||||
void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
|
||||
unsigned PrintMethodIdx, raw_ostream &O);
|
||||
static const char *getRegisterName(unsigned RegNo);
|
||||
void printRegName(raw_ostream &OS, unsigned RegNo) const override;
|
||||
|
||||
private:
|
||||
bool printAlias(const MCInst *MI, raw_ostream &Ostream);
|
||||
bool printInst(const MCInst *MI, raw_ostream &Ostream, StringRef Alias,
|
||||
unsigned OpNo0, unsigned OpnNo1);
|
||||
bool printMemoryLoadIncrement(const MCInst *MI, raw_ostream &Ostream,
|
||||
StringRef Opcode, int AddOffset);
|
||||
bool printMemoryStoreIncrement(const MCInst *MI, raw_ostream &Ostream,
|
||||
StringRef Opcode, int AddOffset);
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_INSTPRINTER_LANAIINSTPRINTER_H
|
45
lib/Target/Lanai/LLVMBuild.txt
Normal file
45
lib/Target/Lanai/LLVMBuild.txt
Normal file
@ -0,0 +1,45 @@
|
||||
;===- ./lib/Target/Lanai/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 = Lanai
|
||||
parent = Target
|
||||
has_asmprinter = 1
|
||||
|
||||
[component_1]
|
||||
type = Library
|
||||
name = LanaiCodeGen
|
||||
parent = Lanai
|
||||
required_libraries =
|
||||
Analysis
|
||||
AsmPrinter
|
||||
CodeGen
|
||||
Core
|
||||
LanaiAsmParser
|
||||
LanaiMCTargetDesc
|
||||
LanaiInfo
|
||||
LanaiInstPrinter
|
||||
MC
|
||||
SelectionDAG
|
||||
Support
|
||||
Target
|
||||
TransformUtils
|
||||
add_to_library_groups = Lanai
|
51
lib/Target/Lanai/Lanai.h
Normal file
51
lib/Target/Lanai/Lanai.h
Normal file
@ -0,0 +1,51 @@
|
||||
//===-- Lanai.h - Top-level interface for Lanai 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
|
||||
// Lanai back-end.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAI_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAI_H
|
||||
|
||||
#include "LanaiAluCode.h"
|
||||
#include "LanaiCondCode.h"
|
||||
#include "MCTargetDesc/LanaiBaseInfo.h"
|
||||
#include "MCTargetDesc/LanaiMCTargetDesc.h"
|
||||
#include "llvm/CodeGen/ISDOpcodes.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
class LanaiTargetMachine;
|
||||
class MachineFunctionPass;
|
||||
class TargetMachine;
|
||||
class formatted_raw_ostream;
|
||||
|
||||
// createLanaiISelDag - This pass converts a legalized DAG into a
|
||||
// Lanai-specific DAG, ready for instruction scheduling.
|
||||
FunctionPass *createLanaiISelDag(LanaiTargetMachine &TM);
|
||||
|
||||
// createLanaiDelaySlotFillerPass - This pass fills delay slots
|
||||
// with useful instructions or nop's
|
||||
FunctionPass *createLanaiDelaySlotFillerPass(const LanaiTargetMachine &TM);
|
||||
|
||||
// createLanaiMemAluCombinerPass - This pass combines loads/stores and
|
||||
// arithmetic operations.
|
||||
FunctionPass *createLanaiMemAluCombinerPass();
|
||||
|
||||
// createLanaiSetflagAluCombinerPass - This pass combines SET_FLAG and ALU
|
||||
// operations.
|
||||
FunctionPass *createLanaiSetflagAluCombinerPass();
|
||||
|
||||
extern Target TheLanaiTarget;
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAI_H
|
47
lib/Target/Lanai/Lanai.td
Normal file
47
lib/Target/Lanai/Lanai.td
Normal file
@ -0,0 +1,47 @@
|
||||
//===- Lanai.td - Describe the Lanai 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"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register File, Calling Conv, Instruction Descriptions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "LanaiSchedule.td"
|
||||
include "LanaiRegisterInfo.td"
|
||||
include "LanaiCallingConv.td"
|
||||
include "LanaiInstrInfo.td"
|
||||
|
||||
def LanaiInstrInfo : InstrInfo;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Lanai processors supported.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def : ProcessorModel<"generic", LanaiSchedModel, []>;
|
||||
def : ProcessorModel<"v11", LanaiSchedModel, []>;
|
||||
|
||||
def LanaiInstPrinter : AsmWriter {
|
||||
string AsmWriterClassName = "InstPrinter";
|
||||
bit isMCAsmWriter = 1;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declare the target which we are implementing
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def Lanai : Target {
|
||||
// Pull in Instruction Info:
|
||||
let InstructionSet = LanaiInstrInfo;
|
||||
let AssemblyWriters = [LanaiInstPrinter];
|
||||
}
|
148
lib/Target/Lanai/LanaiAluCode.h
Normal file
148
lib/Target/Lanai/LanaiAluCode.h
Normal file
@ -0,0 +1,148 @@
|
||||
//===-- LanaiAluCode.h - ALU operator encoding ----------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The encoding for ALU operators used in RM and RRM operands
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAIALUCODE_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAIALUCODE_H
|
||||
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/CodeGen/ISDOpcodes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace LPAC {
|
||||
enum AluCode {
|
||||
ADD = 0x00,
|
||||
ADDC = 0x01,
|
||||
SUB = 0x02,
|
||||
SUBB = 0x03,
|
||||
AND = 0x04,
|
||||
OR = 0x05,
|
||||
XOR = 0x06,
|
||||
SPECIAL = 0x07,
|
||||
|
||||
// Shift instructions are treated as SPECIAL when encoding the machine
|
||||
// instruction, but kept distinct until lowering. The constant values are
|
||||
// chosen to ease lowering.
|
||||
SHL = 0x17,
|
||||
SRL = 0x27,
|
||||
SRA = 0x37,
|
||||
|
||||
// Indicates an unknown/unsupported operator
|
||||
UNKNOWN = 0xFF,
|
||||
};
|
||||
|
||||
// Bits indicating post- and pre-operators should be tested and set using Is*
|
||||
// and Make* utility functions
|
||||
constexpr int Lanai_PRE_OP = 0x40;
|
||||
constexpr int Lanai_POST_OP = 0x80;
|
||||
|
||||
inline static unsigned encodeLanaiAluCode(unsigned AluOp) {
|
||||
unsigned const OP_ENCODING_MASK = 0x07;
|
||||
return AluOp & OP_ENCODING_MASK;
|
||||
}
|
||||
|
||||
inline static unsigned getAluOp(unsigned AluOp) {
|
||||
unsigned const ALU_MASK = 0x3F;
|
||||
return AluOp & ALU_MASK;
|
||||
}
|
||||
|
||||
inline static bool isPreOp(unsigned AluOp) { return AluOp & Lanai_PRE_OP; }
|
||||
|
||||
inline static bool isPostOp(unsigned AluOp) { return AluOp & Lanai_POST_OP; }
|
||||
|
||||
inline static unsigned makePreOp(unsigned AluOp) {
|
||||
assert(!isPostOp(AluOp) && "Operator can't be a post- and pre-op");
|
||||
return AluOp | Lanai_PRE_OP;
|
||||
}
|
||||
|
||||
inline static unsigned makePostOp(unsigned AluOp) {
|
||||
assert(!isPreOp(AluOp) && "Operator can't be a post- and pre-op");
|
||||
return AluOp | Lanai_POST_OP;
|
||||
}
|
||||
|
||||
inline static bool modifiesOp(unsigned AluOp) {
|
||||
return isPreOp(AluOp) | isPostOp(AluOp);
|
||||
}
|
||||
|
||||
inline static const char *lanaiAluCodeToString(unsigned AluOp) {
|
||||
switch (getAluOp(AluOp)) {
|
||||
case ADD:
|
||||
return "add";
|
||||
case ADDC:
|
||||
return "addc";
|
||||
case SUB:
|
||||
return "sub";
|
||||
case SUBB:
|
||||
return "subb";
|
||||
case AND:
|
||||
return "and";
|
||||
case OR:
|
||||
return "or";
|
||||
case XOR:
|
||||
return "xor";
|
||||
case SHL:
|
||||
return "sh";
|
||||
case SRL:
|
||||
return "sh";
|
||||
case SRA:
|
||||
return "sha";
|
||||
default:
|
||||
llvm_unreachable("Invalid ALU code.");
|
||||
}
|
||||
}
|
||||
|
||||
inline static AluCode stringToLanaiAluCode(StringRef S) {
|
||||
return StringSwitch<AluCode>(S)
|
||||
.Case("add", ADD)
|
||||
.Case("addc", ADDC)
|
||||
.Case("sub", SUB)
|
||||
.Case("subb", SUBB)
|
||||
.Case("and", AND)
|
||||
.Case("or", OR)
|
||||
.Case("xor", XOR)
|
||||
.Case("sh", SHL)
|
||||
.Case("srl", SRL)
|
||||
.Case("sha", SRA)
|
||||
.Default(UNKNOWN);
|
||||
}
|
||||
|
||||
inline static AluCode isdToLanaiAluCode(ISD::NodeType Node_type) {
|
||||
switch (Node_type) {
|
||||
case ISD::ADD:
|
||||
return AluCode::ADD;
|
||||
case ISD::ADDE:
|
||||
return AluCode::ADDC;
|
||||
case ISD::SUB:
|
||||
return AluCode::SUB;
|
||||
case ISD::SUBE:
|
||||
return AluCode::SUBB;
|
||||
case ISD::AND:
|
||||
return AluCode::AND;
|
||||
case ISD::OR:
|
||||
return AluCode::OR;
|
||||
case ISD::XOR:
|
||||
return AluCode::XOR;
|
||||
case ISD::SHL:
|
||||
return AluCode::SHL;
|
||||
case ISD::SRL:
|
||||
return AluCode::SRL;
|
||||
case ISD::SRA:
|
||||
return AluCode::SRA;
|
||||
default:
|
||||
return AluCode::UNKNOWN;
|
||||
}
|
||||
}
|
||||
} // namespace LPAC
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAIALUCODE_H
|
252
lib/Target/Lanai/LanaiAsmPrinter.cpp
Normal file
252
lib/Target/Lanai/LanaiAsmPrinter.cpp
Normal file
@ -0,0 +1,252 @@
|
||||
//===-- LanaiAsmPrinter.cpp - Lanai 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 Lanai assembly language.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "InstPrinter/LanaiInstPrinter.h"
|
||||
#include "LanaiInstrInfo.h"
|
||||
#include "LanaiMCInstLower.h"
|
||||
#include "LanaiTargetMachine.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/MCInstBuilder.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class LanaiAsmPrinter : public AsmPrinter {
|
||||
public:
|
||||
explicit LanaiAsmPrinter(TargetMachine &TM,
|
||||
std::unique_ptr<MCStreamer> Streamer)
|
||||
: AsmPrinter(TM, std::move(Streamer)) {}
|
||||
|
||||
const char *getPassName() const override { return "Lanai Assembly Printer"; }
|
||||
|
||||
void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
|
||||
const char *Modifier = 0);
|
||||
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O) override;
|
||||
void EmitInstruction(const MachineInstr *MI) override;
|
||||
bool isBlockOnlyReachableByFallthrough(
|
||||
const MachineBasicBlock *MBB) const override;
|
||||
|
||||
private:
|
||||
void customEmitInstruction(const MachineInstr *MI);
|
||||
void emitCallInstruction(const MachineInstr *MI);
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
void LanaiAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O, const char *Modifier) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNum);
|
||||
unsigned TF = MO.getTargetFlags();
|
||||
|
||||
switch (MO.getType()) {
|
||||
case MachineOperand::MO_Register:
|
||||
O << LanaiInstPrinter::getRegisterName(MO.getReg());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_Immediate:
|
||||
O << MO.getImm();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
O << *MO.getMBB()->getSymbol();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
if (TF == LanaiII::MO_PLT)
|
||||
O << "plt(" << *getSymbol(MO.getGlobal()) << ")";
|
||||
else
|
||||
O << *getSymbol(MO.getGlobal());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_BlockAddress: {
|
||||
MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
|
||||
O << BA->getName();
|
||||
break;
|
||||
}
|
||||
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
if (TF == LanaiII::MO_PLT)
|
||||
O << "plt(" << *GetExternalSymbolSymbol(MO.getSymbolName()) << ")";
|
||||
else
|
||||
O << *GetExternalSymbolSymbol(MO.getSymbolName());
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_JumpTableIndex:
|
||||
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
|
||||
<< MO.getIndex();
|
||||
break;
|
||||
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
|
||||
<< MO.getIndex();
|
||||
return;
|
||||
|
||||
default:
|
||||
llvm_unreachable("<unknown operand type>");
|
||||
}
|
||||
}
|
||||
|
||||
// PrintAsmOperand - Print out an operand for an inline asm expression.
|
||||
//
|
||||
bool LanaiAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant,
|
||||
const char *ExtraCode, raw_ostream &O) {
|
||||
// Does this asm operand have a single letter operand modifier?
|
||||
if (ExtraCode && ExtraCode[0]) {
|
||||
if (ExtraCode[1])
|
||||
return true; // Unknown modifier.
|
||||
|
||||
switch (ExtraCode[0]) {
|
||||
// The highest-numbered register of a pair.
|
||||
case 'H': {
|
||||
if (OpNo == 0)
|
||||
return true;
|
||||
const MachineOperand &FlagsOP = MI->getOperand(OpNo - 1);
|
||||
if (!FlagsOP.isImm())
|
||||
return true;
|
||||
unsigned Flags = FlagsOP.getImm();
|
||||
unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
|
||||
if (NumVals != 2)
|
||||
return true;
|
||||
unsigned RegOp = OpNo + 1;
|
||||
if (RegOp >= MI->getNumOperands())
|
||||
return true;
|
||||
const MachineOperand &MO = MI->getOperand(RegOp);
|
||||
if (!MO.isReg())
|
||||
return true;
|
||||
unsigned Reg = MO.getReg();
|
||||
O << LanaiInstPrinter::getRegisterName(Reg);
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return true; // Unknown modifier.
|
||||
}
|
||||
}
|
||||
printOperand(MI, OpNo, O);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
void LanaiAsmPrinter::emitCallInstruction(const MachineInstr *MI) {
|
||||
assert((MI->getOpcode() == Lanai::CALL || MI->getOpcode() == Lanai::CALLR) &&
|
||||
"Unsupported call function");
|
||||
|
||||
LanaiMCInstLower MCInstLowering(OutContext, *Mang, *this);
|
||||
MCSubtargetInfo STI = getSubtargetInfo();
|
||||
// Insert save rca instruction immediately before the call.
|
||||
// TODO: We should generate a pc-relative mov instruction here instead
|
||||
// of pc + 16 (should be mov .+16 %rca).
|
||||
OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_I_LO)
|
||||
.addReg(Lanai::RCA)
|
||||
.addReg(Lanai::PC)
|
||||
.addImm(16),
|
||||
STI);
|
||||
|
||||
// Push rca onto the stack.
|
||||
// st %rca, [--%sp]
|
||||
OutStreamer->EmitInstruction(MCInstBuilder(Lanai::SW_RI)
|
||||
.addReg(Lanai::RCA)
|
||||
.addReg(Lanai::SP)
|
||||
.addImm(-4)
|
||||
.addImm(LPAC::makePreOp(LPAC::ADD)),
|
||||
STI);
|
||||
|
||||
// Lower the call instruction.
|
||||
if (MI->getOpcode() == Lanai::CALL) {
|
||||
MCInst TmpInst;
|
||||
MCInstLowering.Lower(MI, TmpInst);
|
||||
TmpInst.setOpcode(Lanai::BT);
|
||||
OutStreamer->EmitInstruction(TmpInst, STI);
|
||||
} else {
|
||||
OutStreamer->EmitInstruction(MCInstBuilder(Lanai::ADD_R)
|
||||
.addReg(Lanai::PC)
|
||||
.addReg(MI->getOperand(0).getReg())
|
||||
.addReg(Lanai::R0)
|
||||
.addImm(LPCC::ICC_T),
|
||||
STI);
|
||||
}
|
||||
}
|
||||
|
||||
void LanaiAsmPrinter::customEmitInstruction(const MachineInstr *MI) {
|
||||
LanaiMCInstLower MCInstLowering(OutContext, *Mang, *this);
|
||||
MCSubtargetInfo STI = getSubtargetInfo();
|
||||
MCInst TmpInst;
|
||||
MCInstLowering.Lower(MI, TmpInst);
|
||||
OutStreamer->EmitInstruction(TmpInst, STI);
|
||||
}
|
||||
|
||||
void LanaiAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MachineBasicBlock::const_instr_iterator I = MI->getIterator();
|
||||
MachineBasicBlock::const_instr_iterator E = MI->getParent()->instr_end();
|
||||
|
||||
do {
|
||||
if (I->isCall()) {
|
||||
emitCallInstruction(&*I);
|
||||
continue;
|
||||
}
|
||||
|
||||
customEmitInstruction(&*I);
|
||||
} while ((++I != E) && I->isInsideBundle());
|
||||
}
|
||||
|
||||
// isBlockOnlyReachableByFallthough - Return true if the basic block has
|
||||
// exactly one predecessor and the control transfer mechanism between
|
||||
// the predecessor and this block is a fall-through.
|
||||
// FIXME: could the overridden cases be handled in AnalyzeBranch?
|
||||
bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough(
|
||||
const MachineBasicBlock *MBB) const {
|
||||
// The predecessor has to be immediately before this block.
|
||||
const MachineBasicBlock *Pred = *MBB->pred_begin();
|
||||
|
||||
// If the predecessor is a switch statement, assume a jump table
|
||||
// implementation, so it is not a fall through.
|
||||
if (const BasicBlock *B = Pred->getBasicBlock())
|
||||
if (isa<SwitchInst>(B->getTerminator()))
|
||||
return false;
|
||||
|
||||
// Check default implementation
|
||||
if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB))
|
||||
return false;
|
||||
|
||||
// Otherwise, check the last instruction.
|
||||
// Check if the last terminator is an unconditional branch.
|
||||
MachineBasicBlock::const_iterator I = Pred->end();
|
||||
while (I != Pred->begin() && !(--I)->isTerminator()) {
|
||||
}
|
||||
|
||||
return !I->isBarrier();
|
||||
}
|
||||
|
||||
// Force static initialization.
|
||||
extern "C" void LLVMInitializeLanaiAsmPrinter() {
|
||||
RegisterAsmPrinter<LanaiAsmPrinter> X(TheLanaiTarget);
|
||||
}
|
50
lib/Target/Lanai/LanaiCallingConv.td
Normal file
50
lib/Target/Lanai/LanaiCallingConv.td
Normal file
@ -0,0 +1,50 @@
|
||||
//===- LanaiCallingConv.td - Calling Conventions Lanai -------*- 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 Lanai architectures.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Return Value Calling Conventions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Lanai 32-bit C Calling convention.
|
||||
def CC_Lanai32 : CallingConv<[
|
||||
// Promote i8/i16 args to i32
|
||||
CCIfType<[i8, i16], CCPromoteToType<i32>>,
|
||||
|
||||
// Put argument in registers if marked 'inreg' and not a vararg call.
|
||||
CCIfNotVarArg<CCIfInReg<CCIfType<[i32],
|
||||
CCAssignToReg<[R6, R7, R18, R19]>>>>,
|
||||
|
||||
// Otherwise they are assigned to the stack in 4-byte aligned units.
|
||||
CCAssignToStack<4, 4>
|
||||
]>;
|
||||
|
||||
// Lanai 32-bit Fast Calling convention.
|
||||
def CC_Lanai32_Fast : CallingConv<[
|
||||
// Promote i8/i16 args to i32
|
||||
CCIfType<[ i8, i16 ], CCPromoteToType<i32>>,
|
||||
|
||||
// Put arguments in registers.
|
||||
CCIfNotVarArg<CCIfType<[i32], CCAssignToReg<[ R6, R7, R18, R19 ]>>>,
|
||||
|
||||
// Otherwise they are assigned to the stack in 4-byte aligned units.
|
||||
CCAssignToStack<4, 4>
|
||||
]>;
|
||||
|
||||
// Lanai 32-bit C return-value convention.
|
||||
def RetCC_Lanai32 : CallingConv<[
|
||||
// Specify two registers to allow returning 64-bit results that have already
|
||||
// been lowered to 2 32-bit values.
|
||||
CCIfType<[i32], CCAssignToReg<[RV, R9]>>
|
||||
]>;
|
||||
|
||||
def CSR: CalleeSavedRegs<(add)>;
|
100
lib/Target/Lanai/LanaiCondCode.h
Normal file
100
lib/Target/Lanai/LanaiCondCode.h
Normal file
@ -0,0 +1,100 @@
|
||||
// The encoding used for conditional codes used in BR instructions
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAICONDCODE_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAICONDCODE_H
|
||||
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace LPCC {
|
||||
enum CondCode {
|
||||
ICC_T = 0, // true
|
||||
ICC_F = 1, // false
|
||||
ICC_HI = 2, // high
|
||||
ICC_UGT = 2, // unsigned greater than
|
||||
ICC_LS = 3, // low or same
|
||||
ICC_ULE = 3, // unsigned less than or equal
|
||||
ICC_CC = 4, // carry cleared
|
||||
ICC_ULT = 4, // unsigned less than
|
||||
ICC_CS = 5, // carry set
|
||||
ICC_UGE = 5, // unsigned greater than or equal
|
||||
ICC_NE = 6, // not equal
|
||||
ICC_EQ = 7, // equal
|
||||
ICC_VC = 8, // oVerflow cleared
|
||||
ICC_VS = 9, // oVerflow set
|
||||
ICC_PL = 10, // plus
|
||||
ICC_MI = 11, // minus
|
||||
ICC_GE = 12, // greater than or equal
|
||||
ICC_LT = 13, // less than
|
||||
ICC_GT = 14, // greater than
|
||||
ICC_LE = 15, // less than or equal
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
inline static StringRef lanaiCondCodeToString(LPCC::CondCode CC) {
|
||||
switch (CC) {
|
||||
case LPCC::ICC_T:
|
||||
return "t"; // true
|
||||
case LPCC::ICC_F:
|
||||
return "f"; // false
|
||||
case LPCC::ICC_NE:
|
||||
return "ne"; // not equal
|
||||
case LPCC::ICC_EQ:
|
||||
return "eq"; // equal
|
||||
case LPCC::ICC_VC:
|
||||
return "vc"; // oVerflow cleared
|
||||
case LPCC::ICC_VS:
|
||||
return "vs"; // oVerflow set
|
||||
case LPCC::ICC_PL:
|
||||
return "pl"; // plus
|
||||
case LPCC::ICC_MI:
|
||||
return "mi"; // minus
|
||||
case LPCC::ICC_GE:
|
||||
return "ge"; // greater than or equal
|
||||
case LPCC::ICC_LT:
|
||||
return "lt"; // less than
|
||||
case LPCC::ICC_GT:
|
||||
return "gt"; // greater than
|
||||
case LPCC::ICC_LE:
|
||||
return "le"; // less than or equal
|
||||
case LPCC::ICC_UGT:
|
||||
return "ugt"; // high | unsigned greater than
|
||||
case LPCC::ICC_ULE:
|
||||
return "ule"; // low or same | unsigned less or equal
|
||||
case LPCC::ICC_ULT:
|
||||
return "ult"; // carry cleared | unsigned less than
|
||||
case LPCC::ICC_UGE:
|
||||
return "uge"; // carry set | unsigned than or equal
|
||||
default:
|
||||
llvm_unreachable("Invalid cond code");
|
||||
}
|
||||
}
|
||||
|
||||
inline static CondCode suffixToLanaiCondCode(StringRef S) {
|
||||
return StringSwitch<CondCode>(S)
|
||||
.EndsWith("f", LPCC::ICC_F)
|
||||
.EndsWith("hi", LPCC::ICC_HI)
|
||||
.EndsWith("ugt", LPCC::ICC_UGT)
|
||||
.EndsWith("ls", LPCC::ICC_LS)
|
||||
.EndsWith("ule", LPCC::ICC_ULE)
|
||||
.EndsWith("cc", LPCC::ICC_CC)
|
||||
.EndsWith("ult", LPCC::ICC_ULT)
|
||||
.EndsWith("cs", LPCC::ICC_CS)
|
||||
.EndsWith("uge", LPCC::ICC_UGE)
|
||||
.EndsWith("ne", LPCC::ICC_NE)
|
||||
.EndsWith("eq", LPCC::ICC_EQ)
|
||||
.EndsWith("vc", LPCC::ICC_VC)
|
||||
.EndsWith("vs", LPCC::ICC_VS)
|
||||
.EndsWith("pl", LPCC::ICC_PL)
|
||||
.EndsWith("mi", LPCC::ICC_MI)
|
||||
.EndsWith("ge", LPCC::ICC_GE)
|
||||
.EndsWith("lt", LPCC::ICC_LT)
|
||||
.EndsWith("gt", LPCC::ICC_GT)
|
||||
.EndsWith("le", LPCC::ICC_LE)
|
||||
.EndsWith("t", LPCC::ICC_T) // Has to be after others with suffix t
|
||||
.Default(LPCC::UNKNOWN);
|
||||
}
|
||||
} // namespace LPCC
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAICONDCODE_H
|
250
lib/Target/Lanai/LanaiDelaySlotFiller.cpp
Normal file
250
lib/Target/Lanai/LanaiDelaySlotFiller.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
//===-- LanaiDelaySlotFiller.cpp - Lanai delay slot filler ----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Simple pass to fills delay slots with useful instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiTargetMachine.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "delay-slot-filler"
|
||||
|
||||
STATISTIC(FilledSlots, "Number of delay slots filled");
|
||||
|
||||
static cl::opt<bool>
|
||||
NopDelaySlotFiller("lanai-nop-delay-filler", cl::init(false),
|
||||
cl::desc("Fill Lanai delay slots with NOPs."),
|
||||
cl::Hidden);
|
||||
|
||||
namespace {
|
||||
struct Filler : public MachineFunctionPass {
|
||||
// Target machine description which we query for reg. names, data
|
||||
// layout, etc.
|
||||
const TargetInstrInfo *TII;
|
||||
const TargetRegisterInfo *TRI;
|
||||
MachineBasicBlock::instr_iterator LastFiller;
|
||||
|
||||
static char ID;
|
||||
explicit Filler() : MachineFunctionPass(ID) {}
|
||||
|
||||
const char *getPassName() const override { return "Lanai Delay Slot Filler"; }
|
||||
|
||||
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF) override {
|
||||
const LanaiSubtarget &Subtarget = MF.getSubtarget<LanaiSubtarget>();
|
||||
TII = Subtarget.getInstrInfo();
|
||||
TRI = Subtarget.getRegisterInfo();
|
||||
|
||||
bool Changed = false;
|
||||
for (MachineFunction::iterator FI = MF.begin(), FE = MF.end(); FI != FE;
|
||||
++FI)
|
||||
Changed |= runOnMachineBasicBlock(*FI);
|
||||
return Changed;
|
||||
}
|
||||
|
||||
void insertDefsUses(MachineBasicBlock::instr_iterator MI,
|
||||
SmallSet<unsigned, 32> &RegDefs,
|
||||
SmallSet<unsigned, 32> &RegUses);
|
||||
|
||||
bool isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg);
|
||||
|
||||
bool delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
|
||||
bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
|
||||
SmallSet<unsigned, 32> &RegUses);
|
||||
|
||||
bool findDelayInstr(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::instr_iterator Slot,
|
||||
MachineBasicBlock::instr_iterator &Filler);
|
||||
};
|
||||
char Filler::ID = 0;
|
||||
} // end of anonymous namespace
|
||||
|
||||
// createLanaiDelaySlotFillerPass - Returns a pass that fills in delay
|
||||
// slots in Lanai MachineFunctions
|
||||
FunctionPass *
|
||||
llvm::createLanaiDelaySlotFillerPass(const LanaiTargetMachine &tm) {
|
||||
return new Filler();
|
||||
}
|
||||
|
||||
// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
|
||||
// There is one or two delay slot per delayed instruction.
|
||||
bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
|
||||
bool Changed = false;
|
||||
LastFiller = MBB.instr_end();
|
||||
|
||||
for (MachineBasicBlock::instr_iterator I = MBB.instr_begin();
|
||||
I != MBB.instr_end(); ++I) {
|
||||
if (I->getDesc().hasDelaySlot()) {
|
||||
MachineBasicBlock::instr_iterator InstrWithSlot = I;
|
||||
MachineBasicBlock::instr_iterator J = I;
|
||||
|
||||
// Treat RET specially as it is only instruction with 2 delay slots
|
||||
// generated while all others generated have 1 delay slot.
|
||||
if (I->getOpcode() == Lanai::RET) {
|
||||
// RET is generated as part of epilogue generation and hence we know
|
||||
// what the two instructions preceding it are and that it is safe to
|
||||
// insert RET above them.
|
||||
MachineBasicBlock::reverse_instr_iterator RI(I);
|
||||
assert(RI->getOpcode() == Lanai::LDW_RI && RI->getOperand(0).isReg() &&
|
||||
RI->getOperand(0).getReg() == Lanai::FP &&
|
||||
RI->getOperand(1).isReg() &&
|
||||
RI->getOperand(1).getReg() == Lanai::FP &&
|
||||
RI->getOperand(2).isImm() && RI->getOperand(2).getImm() == -8);
|
||||
++RI;
|
||||
assert(RI->getOpcode() == Lanai::ADD_I_LO &&
|
||||
RI->getOperand(0).isReg() &&
|
||||
RI->getOperand(0).getReg() == Lanai::SP &&
|
||||
RI->getOperand(1).isReg() &&
|
||||
RI->getOperand(1).getReg() == Lanai::FP);
|
||||
++RI;
|
||||
MachineBasicBlock::instr_iterator FI(RI.base());
|
||||
MBB.splice(std::next(I), &MBB, FI, I);
|
||||
FilledSlots += 2;
|
||||
} else {
|
||||
if (!NopDelaySlotFiller && findDelayInstr(MBB, I, J)) {
|
||||
MBB.splice(std::next(I), &MBB, J);
|
||||
} else {
|
||||
BuildMI(MBB, std::next(I), DebugLoc(), TII->get(Lanai::NOP));
|
||||
}
|
||||
++FilledSlots;
|
||||
}
|
||||
|
||||
Changed = true;
|
||||
// Record the filler instruction that filled the delay slot.
|
||||
// The instruction after it will be visited in the next iteration.
|
||||
LastFiller = ++I;
|
||||
|
||||
// Bundle the delay slot filler to InstrWithSlot so that the machine
|
||||
// verifier doesn't expect this instruction to be a terminator.
|
||||
MIBundleBuilder(MBB, InstrWithSlot, std::next(LastFiller));
|
||||
}
|
||||
}
|
||||
return Changed;
|
||||
}
|
||||
|
||||
bool Filler::findDelayInstr(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::instr_iterator Slot,
|
||||
MachineBasicBlock::instr_iterator &Filler) {
|
||||
SmallSet<unsigned, 32> RegDefs;
|
||||
SmallSet<unsigned, 32> RegUses;
|
||||
|
||||
insertDefsUses(Slot, RegDefs, RegUses);
|
||||
|
||||
bool SawLoad = false;
|
||||
bool SawStore = false;
|
||||
|
||||
for (MachineBasicBlock::reverse_instr_iterator I(Slot); I != MBB.instr_rend();
|
||||
++I) {
|
||||
// skip debug value
|
||||
if (I->isDebugValue())
|
||||
continue;
|
||||
|
||||
// Convert to forward iterator.
|
||||
MachineBasicBlock::instr_iterator FI(std::next(I).base());
|
||||
|
||||
if (I->hasUnmodeledSideEffects() || I->isInlineAsm() || I->isLabel() ||
|
||||
FI == LastFiller || I->isPseudo())
|
||||
break;
|
||||
|
||||
if (delayHasHazard(FI, SawLoad, SawStore, RegDefs, RegUses)) {
|
||||
insertDefsUses(FI, RegDefs, RegUses);
|
||||
continue;
|
||||
}
|
||||
Filler = FI;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Filler::delayHasHazard(MachineBasicBlock::instr_iterator MI, bool &SawLoad,
|
||||
bool &SawStore, SmallSet<unsigned, 32> &RegDefs,
|
||||
SmallSet<unsigned, 32> &RegUses) {
|
||||
if (MI->isImplicitDef() || MI->isKill())
|
||||
return true;
|
||||
|
||||
// Loads or stores cannot be moved past a store to the delay slot
|
||||
// and stores cannot be moved past a load.
|
||||
if (MI->mayLoad()) {
|
||||
if (SawStore)
|
||||
return true;
|
||||
SawLoad = true;
|
||||
}
|
||||
|
||||
if (MI->mayStore()) {
|
||||
if (SawStore)
|
||||
return true;
|
||||
SawStore = true;
|
||||
if (SawLoad)
|
||||
return true;
|
||||
}
|
||||
|
||||
assert((!MI->isCall() && !MI->isReturn()) &&
|
||||
"Cannot put calls or returns in delay slot.");
|
||||
|
||||
for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
|
||||
const MachineOperand &MO = MI->getOperand(I);
|
||||
unsigned Reg;
|
||||
|
||||
if (!MO.isReg() || !(Reg = MO.getReg()))
|
||||
continue; // skip
|
||||
|
||||
if (MO.isDef()) {
|
||||
// check whether Reg is defined or used before delay slot.
|
||||
if (isRegInSet(RegDefs, Reg) || isRegInSet(RegUses, Reg))
|
||||
return true;
|
||||
}
|
||||
if (MO.isUse()) {
|
||||
// check whether Reg is defined before delay slot.
|
||||
if (isRegInSet(RegDefs, Reg))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert Defs and Uses of MI into the sets RegDefs and RegUses.
|
||||
void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI,
|
||||
SmallSet<unsigned, 32> &RegDefs,
|
||||
SmallSet<unsigned, 32> &RegUses) {
|
||||
// If MI is a call or return, just examine the explicit non-variadic operands.
|
||||
MCInstrDesc MCID = MI->getDesc();
|
||||
unsigned E = MI->isCall() || MI->isReturn() ? MCID.getNumOperands()
|
||||
: MI->getNumOperands();
|
||||
for (unsigned I = 0; I != E; ++I) {
|
||||
const MachineOperand &MO = MI->getOperand(I);
|
||||
unsigned Reg;
|
||||
|
||||
if (!MO.isReg() || !(Reg = MO.getReg()))
|
||||
continue;
|
||||
|
||||
if (MO.isDef())
|
||||
RegDefs.insert(Reg);
|
||||
else if (MO.isUse())
|
||||
RegUses.insert(Reg);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the Reg or its alias is in the RegSet.
|
||||
bool Filler::isRegInSet(SmallSet<unsigned, 32> &RegSet, unsigned Reg) {
|
||||
// Check Reg and all aliased Registers.
|
||||
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
|
||||
if (RegSet.count(*AI))
|
||||
return true;
|
||||
return false;
|
||||
}
|
220
lib/Target/Lanai/LanaiFrameLowering.cpp
Normal file
220
lib/Target/Lanai/LanaiFrameLowering.cpp
Normal file
@ -0,0 +1,220 @@
|
||||
//===-- LanaiFrameLowering.cpp - Lanai Frame 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 Lanai implementation of TargetFrameLowering class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiFrameLowering.h"
|
||||
|
||||
#include "LanaiInstrInfo.h"
|
||||
#include "LanaiMachineFunctionInfo.h"
|
||||
#include "LanaiSubtarget.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// Determines the size of the frame and maximum call frame size.
|
||||
void LanaiFrameLowering::determineFrameLayout(MachineFunction &MF) const {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const LanaiRegisterInfo *LRI = STI.getRegisterInfo();
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo.
|
||||
unsigned FrameSize = MFI->getStackSize();
|
||||
|
||||
// Get the alignment.
|
||||
unsigned StackAlign = LRI->needsStackRealignment(MF) ? MFI->getMaxAlignment()
|
||||
: getStackAlignment();
|
||||
|
||||
// Get the maximum call frame size of all the calls.
|
||||
unsigned MaxCallFrameSize = MFI->getMaxCallFrameSize();
|
||||
|
||||
// If we have dynamic alloca then MaxCallFrameSize needs to be aligned so
|
||||
// that allocations will be aligned.
|
||||
if (MFI->hasVarSizedObjects())
|
||||
MaxCallFrameSize = alignTo(MaxCallFrameSize, StackAlign);
|
||||
|
||||
// Update maximum call frame size.
|
||||
MFI->setMaxCallFrameSize(MaxCallFrameSize);
|
||||
|
||||
// Include call frame size in total.
|
||||
if (!(hasReservedCallFrame(MF) && MFI->adjustsStack()))
|
||||
FrameSize += MaxCallFrameSize;
|
||||
|
||||
// Make sure the frame is aligned.
|
||||
FrameSize = alignTo(FrameSize, StackAlign);
|
||||
|
||||
// Update frame info.
|
||||
MFI->setStackSize(FrameSize);
|
||||
}
|
||||
|
||||
// Iterates through each basic block in a machine function and replaces
|
||||
// ADJDYNALLOC pseudo instructions with a Lanai:ADDI with the
|
||||
// maximum call frame size as the immediate.
|
||||
void LanaiFrameLowering::replaceAdjDynAllocPseudo(MachineFunction &MF) const {
|
||||
const LanaiInstrInfo &LII =
|
||||
*static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
|
||||
unsigned MaxCallFrameSize = MF.getFrameInfo()->getMaxCallFrameSize();
|
||||
|
||||
for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E;
|
||||
++MBB) {
|
||||
MachineBasicBlock::iterator MBBI = MBB->begin();
|
||||
while (MBBI != MBB->end()) {
|
||||
MachineInstr *MI = MBBI++;
|
||||
if (MI->getOpcode() == Lanai::ADJDYNALLOC) {
|
||||
DebugLoc DL = MI->getDebugLoc();
|
||||
unsigned Dst = MI->getOperand(0).getReg();
|
||||
unsigned Src = MI->getOperand(1).getReg();
|
||||
|
||||
BuildMI(*MBB, MI, DL, LII.get(Lanai::ADD_I_LO), Dst)
|
||||
.addReg(Src)
|
||||
.addImm(MaxCallFrameSize);
|
||||
MI->eraseFromParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the following sequence for function entry:
|
||||
// st %fp,-4[*%sp] !push old FP
|
||||
// add %sp,8,%fp !generate new FP
|
||||
// sub %sp,0x4,%sp !allocate stack space (as needed)
|
||||
void LanaiFrameLowering::emitPrologue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {
|
||||
assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
|
||||
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const LanaiInstrInfo &LII =
|
||||
*static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
|
||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||
|
||||
// Debug location must be unknown since the first debug location is used
|
||||
// to determine the end of the prologue.
|
||||
DebugLoc DL;
|
||||
|
||||
// Determine the correct frame layout
|
||||
determineFrameLayout(MF);
|
||||
|
||||
// FIXME: This appears to be overallocating. Needs investigation.
|
||||
// Get the number of bytes to allocate from the FrameInfo.
|
||||
unsigned StackSize = MFI->getStackSize();
|
||||
|
||||
// Push old FP
|
||||
// st %fp,-4[*%sp]
|
||||
BuildMI(MBB, MBBI, DL, LII.get(Lanai::SW_RI))
|
||||
.addReg(Lanai::FP)
|
||||
.addReg(Lanai::SP)
|
||||
.addImm(-4)
|
||||
.addImm(LPAC::makePreOp(LPAC::ADD))
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
|
||||
// Generate new FP
|
||||
// add %sp,8,%fp
|
||||
BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::FP)
|
||||
.addReg(Lanai::SP)
|
||||
.addImm(8)
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
|
||||
// Allocate space on the stack if needed
|
||||
// sub %sp,StackSize,%sp
|
||||
if (StackSize != 0) {
|
||||
BuildMI(MBB, MBBI, DL, LII.get(Lanai::SUB_I_LO), Lanai::SP)
|
||||
.addReg(Lanai::SP)
|
||||
.addImm(StackSize)
|
||||
.setMIFlag(MachineInstr::FrameSetup);
|
||||
}
|
||||
|
||||
// Replace ADJDYNANALLOC
|
||||
if (MFI->hasVarSizedObjects())
|
||||
replaceAdjDynAllocPseudo(MF);
|
||||
}
|
||||
|
||||
void LanaiFrameLowering::eliminateCallFramePseudoInstr(
|
||||
MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const {
|
||||
// Discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions.
|
||||
MBB.erase(I);
|
||||
}
|
||||
|
||||
// The function epilogue should not depend on the current stack pointer!
|
||||
// It should use the frame pointer only. This is mandatory because
|
||||
// of alloca; we also take advantage of it to omit stack adjustments
|
||||
// before returning.
|
||||
//
|
||||
// Note that when we go to restore the preserved register values we must
|
||||
// not try to address their slots by using offsets from the stack pointer.
|
||||
// That's because the stack pointer may have been moved during the function
|
||||
// execution due to a call to alloca(). Rather, we must restore all
|
||||
// preserved registers via offsets from the frame pointer value.
|
||||
//
|
||||
// Note also that when the current frame is being "popped" (by adjusting
|
||||
// the value of the stack pointer) on function exit, we must (for the
|
||||
// sake of alloca) set the new value of the stack pointer based upon
|
||||
// the current value of the frame pointer. We can't just add what we
|
||||
// believe to be the (static) frame size to the stack pointer because
|
||||
// if we did that, and alloca() had been called during this function,
|
||||
// we would end up returning *without* having fully deallocated all of
|
||||
// the space grabbed by alloca. If that happened, and a function
|
||||
// containing one or more alloca() calls was called over and over again,
|
||||
// then the stack would grow without limit!
|
||||
//
|
||||
// RET is lowered to
|
||||
// ld -4[%fp],%pc # modify %pc (two delay slots)
|
||||
// as the return address is in the stack frame and mov to pc is allowed.
|
||||
// emitEpilogue emits
|
||||
// mov %fp,%sp # restore the stack pointer
|
||||
// ld -8[%fp],%fp # restore the caller's frame pointer
|
||||
// before RET and the delay slot filler will move RET such that these
|
||||
// instructions execute in the delay slots of the load to PC.
|
||||
void LanaiFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {
|
||||
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||
const LanaiInstrInfo &LII =
|
||||
*static_cast<const LanaiInstrInfo *>(STI.getInstrInfo());
|
||||
DebugLoc DL = MBBI->getDebugLoc();
|
||||
|
||||
// Restore the stack pointer using the callee's frame pointer value.
|
||||
BuildMI(MBB, MBBI, DL, LII.get(Lanai::ADD_I_LO), Lanai::SP)
|
||||
.addReg(Lanai::FP)
|
||||
.addImm(0);
|
||||
|
||||
// Restore the frame pointer from the stack.
|
||||
BuildMI(MBB, MBBI, DL, LII.get(Lanai::LDW_RI), Lanai::FP)
|
||||
.addReg(Lanai::FP)
|
||||
.addImm(-8)
|
||||
.addImm(LPAC::ADD);
|
||||
}
|
||||
|
||||
void LanaiFrameLowering::determineCalleeSaves(MachineFunction &MF,
|
||||
BitVector &SavedRegs,
|
||||
RegScavenger *RS) const {
|
||||
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
|
||||
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const LanaiRegisterInfo *LRI =
|
||||
static_cast<const LanaiRegisterInfo *>(STI.getRegisterInfo());
|
||||
int Offset = -4;
|
||||
|
||||
// Reserve 4 bytes for the saved RCA
|
||||
MFI->CreateFixedObject(4, Offset, true);
|
||||
Offset -= 4;
|
||||
|
||||
// Reserve 4 bytes for the saved FP
|
||||
MFI->CreateFixedObject(4, Offset, true);
|
||||
Offset -= 4;
|
||||
|
||||
if (LRI->hasBasePointer(MF)) {
|
||||
MFI->CreateFixedObject(4, Offset, true);
|
||||
SavedRegs.reset(LRI->getBaseRegister());
|
||||
}
|
||||
}
|
57
lib/Target/Lanai/LanaiFrameLowering.h
Normal file
57
lib/Target/Lanai/LanaiFrameLowering.h
Normal file
@ -0,0 +1,57 @@
|
||||
//===-- LanaiFrameLowering.h - Define frame lowering for Lanai --*- C++-*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class implements Lanai-specific bits of TargetFrameLowering class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAIFRAMELOWERING_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAIFRAMELOWERING_H
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BitVector;
|
||||
class LanaiSubtarget;
|
||||
|
||||
class LanaiFrameLowering : public TargetFrameLowering {
|
||||
private:
|
||||
void determineFrameLayout(MachineFunction &MF) const;
|
||||
void replaceAdjDynAllocPseudo(MachineFunction &MF) const;
|
||||
|
||||
protected:
|
||||
const LanaiSubtarget &STI;
|
||||
|
||||
public:
|
||||
explicit LanaiFrameLowering(const LanaiSubtarget &Subtarget)
|
||||
: TargetFrameLowering(StackGrowsDown,
|
||||
/*StackAlignment=*/8,
|
||||
/*LocalAreaOffset=*/0),
|
||||
STI(Subtarget) {}
|
||||
|
||||
// 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;
|
||||
|
||||
void
|
||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const override;
|
||||
|
||||
bool hasFP(const MachineFunction &MF) const override { return true; }
|
||||
|
||||
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
|
||||
RegScavenger *RS = nullptr) const override;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAIFRAMELOWERING_H
|
325
lib/Target/Lanai/LanaiISelDAGToDAG.cpp
Normal file
325
lib/Target/Lanai/LanaiISelDAGToDAG.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
//===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===//
|
||||
//
|
||||
// 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 Lanai target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiMachineFunctionInfo.h"
|
||||
#include "LanaiRegisterInfo.h"
|
||||
#include "LanaiSubtarget.h"
|
||||
#include "LanaiTargetMachine.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;
|
||||
|
||||
#define DEBUG_TYPE "lanai-isel"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Selector Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// LanaiDAGToDAGISel - Lanai specific code to select Lanai machine
|
||||
// instructions for SelectionDAG operations.
|
||||
//===----------------------------------------------------------------------===//
|
||||
namespace {
|
||||
|
||||
class LanaiDAGToDAGISel : public SelectionDAGISel {
|
||||
public:
|
||||
explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine)
|
||||
: SelectionDAGISel(TargetMachine) {}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF) override {
|
||||
return SelectionDAGISel::runOnMachineFunction(MF);
|
||||
}
|
||||
|
||||
// Pass Name
|
||||
const char *getPassName() const override {
|
||||
return "Lanai DAG->DAG Pattern Instruction Selection";
|
||||
}
|
||||
|
||||
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
|
||||
std::vector<SDValue> &OutOps) override;
|
||||
|
||||
private:
|
||||
// Include the pieces autogenerated from the target description.
|
||||
#include "LanaiGenDAGISel.inc"
|
||||
|
||||
// Instruction Selection not handled by the auto-generated tablgen
|
||||
SDNode *Select(SDNode *N) override;
|
||||
|
||||
// Support functions for the opcodes of Instruction Selection
|
||||
// not handled by the auto-generated tablgen
|
||||
SDNode *selectFrameIndex(SDNode *N);
|
||||
|
||||
// Complex Pattern for address selection.
|
||||
bool selectAddrRi(SDValue Addr, SDValue &Base, SDValue &Offset,
|
||||
SDValue &AluOp);
|
||||
bool selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, SDValue &AluOp);
|
||||
bool selectAddrSls(SDValue Addr, SDValue &Offset);
|
||||
bool selectAddrSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
|
||||
SDValue &AluOp);
|
||||
|
||||
// getI32Imm - Return a target constant with the specified value, of type i32.
|
||||
inline SDValue getI32Imm(unsigned Imm, SDLoc DL) {
|
||||
return CurDAG->getTargetConstant(Imm, DL, MVT::i32);
|
||||
}
|
||||
|
||||
private:
|
||||
bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
|
||||
SDValue &AluOp, bool RiMode);
|
||||
};
|
||||
|
||||
bool canBeRepresentedAsSls(const ConstantSDNode &CN) {
|
||||
// Fits in 21-bit signed immediate and two low-order bits are zero.
|
||||
return isInt<21>(CN.getSExtValue()) && ((CN.getSExtValue() & 0x3) == 0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Helper functions for ComplexPattern used on LanaiInstrInfo
|
||||
// Used on Lanai Load/Store instructions.
|
||||
bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) {
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
|
||||
SDLoc DL(Addr);
|
||||
// Loading from a constant address.
|
||||
if (canBeRepresentedAsSls(*CN)) {
|
||||
int32_t Imm = CN->getSExtValue();
|
||||
Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (Addr.getOpcode() == ISD::OR &&
|
||||
Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) {
|
||||
Offset = Addr.getOperand(1).getOperand(0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base,
|
||||
SDValue &Offset, SDValue &AluOp,
|
||||
bool RiMode) {
|
||||
SDLoc DL(Addr);
|
||||
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
|
||||
if (RiMode) {
|
||||
// Fits in 16-bit signed immediate.
|
||||
if (isInt<16>(CN->getSExtValue())) {
|
||||
int16_t Imm = CN->getSExtValue();
|
||||
Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
|
||||
Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
|
||||
AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
// Allow SLS to match if the constant doesn't fit in 16 bits but can be
|
||||
// represented as an SLS.
|
||||
if (canBeRepresentedAsSls(*CN))
|
||||
return false;
|
||||
} else {
|
||||
// Fits in 10-bit signed immediate.
|
||||
if (isInt<10>(CN->getSExtValue())) {
|
||||
int16_t Imm = CN->getSExtValue();
|
||||
Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
|
||||
Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
|
||||
AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if Address is FI, get the TargetFrameIndex.
|
||||
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
|
||||
Base = CurDAG->getTargetFrameIndex(
|
||||
FIN->getIndex(),
|
||||
getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
|
||||
Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
|
||||
AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip direct calls
|
||||
if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
|
||||
Addr.getOpcode() == ISD::TargetGlobalAddress))
|
||||
return false;
|
||||
|
||||
// Address of the form imm + reg
|
||||
ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
|
||||
if (AluOperator == ISD::ADD) {
|
||||
AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
|
||||
// Addresses of the form FI+const
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
|
||||
if ((RiMode && isInt<16>(CN->getSExtValue())) ||
|
||||
(!RiMode && isInt<10>(CN->getSExtValue()))) {
|
||||
// If the first operand is a FI, get the TargetFI Node
|
||||
if (FrameIndexSDNode *FIN =
|
||||
dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
|
||||
Base = CurDAG->getTargetFrameIndex(
|
||||
FIN->getIndex(),
|
||||
getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
|
||||
} else {
|
||||
Base = Addr.getOperand(0);
|
||||
}
|
||||
|
||||
Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Let SLS match SMALL instead of RI.
|
||||
if (AluOperator == ISD::OR && RiMode &&
|
||||
Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
|
||||
return false;
|
||||
|
||||
Base = Addr;
|
||||
Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
|
||||
AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base,
|
||||
SDValue &Offset, SDValue &AluOp) {
|
||||
return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RImode=*/true);
|
||||
}
|
||||
|
||||
bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base,
|
||||
SDValue &Offset, SDValue &AluOp) {
|
||||
return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false);
|
||||
}
|
||||
|
||||
bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2,
|
||||
SDValue &AluOp) {
|
||||
// if Address is FI, get the TargetFrameIndex.
|
||||
if (Addr.getOpcode() == ISD::FrameIndex)
|
||||
return false;
|
||||
|
||||
// Skip direct calls
|
||||
if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
|
||||
Addr.getOpcode() == ISD::TargetGlobalAddress))
|
||||
return false;
|
||||
|
||||
// Address of the form OP + OP
|
||||
ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
|
||||
LPAC::AluCode AluCode = LPAC::isdToLanaiAluCode(AluOperator);
|
||||
if (AluCode != LPAC::UNKNOWN) {
|
||||
// Skip addresses of the form FI OP const
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
|
||||
if (isInt<16>(CN->getSExtValue()))
|
||||
return false;
|
||||
|
||||
// Skip addresses with hi/lo operands
|
||||
if (Addr.getOperand(0).getOpcode() == LanaiISD::HI ||
|
||||
Addr.getOperand(0).getOpcode() == LanaiISD::LO ||
|
||||
Addr.getOperand(0).getOpcode() == LanaiISD::SMALL ||
|
||||
Addr.getOperand(1).getOpcode() == LanaiISD::HI ||
|
||||
Addr.getOperand(1).getOpcode() == LanaiISD::LO ||
|
||||
Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
|
||||
return false;
|
||||
|
||||
// Addresses of the form register OP register
|
||||
R1 = Addr.getOperand(0);
|
||||
R2 = Addr.getOperand(1);
|
||||
AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip addresses with zero offset
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand(
|
||||
const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
|
||||
SDValue Op0, Op1, AluOp;
|
||||
switch (ConstraintCode) {
|
||||
default:
|
||||
return true;
|
||||
case InlineAsm::Constraint_m: // memory
|
||||
if (!selectAddrRr(Op, Op0, Op1, AluOp) &&
|
||||
!selectAddrRi(Op, Op0, Op1, AluOp))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
OutOps.push_back(Op0);
|
||||
OutOps.push_back(Op1);
|
||||
OutOps.push_back(AluOp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Select instructions not customized! Used for
|
||||
// expanded, promoted and normal instructions
|
||||
SDNode *LanaiDAGToDAGISel::Select(SDNode *Node) {
|
||||
unsigned Opcode = Node->getOpcode();
|
||||
|
||||
// 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.
|
||||
SDNode *ResNode = nullptr;
|
||||
switch (Opcode) {
|
||||
case ISD::FrameIndex:
|
||||
ResNode = selectFrameIndex(Node);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Select the default instruction
|
||||
if (ResNode == nullptr)
|
||||
ResNode = SelectCode(Node);
|
||||
|
||||
DEBUG(errs() << "=> ");
|
||||
if (ResNode == NULL || ResNode == Node)
|
||||
DEBUG(Node->dump(CurDAG));
|
||||
else
|
||||
DEBUG(ResNode->dump(CurDAG));
|
||||
DEBUG(errs() << "\n");
|
||||
return ResNode;
|
||||
}
|
||||
|
||||
SDNode *LanaiDAGToDAGISel::selectFrameIndex(SDNode *Node) {
|
||||
SDLoc DL(Node);
|
||||
SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i32);
|
||||
int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
|
||||
EVT VT = Node->getValueType(0);
|
||||
SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
|
||||
unsigned Opc = Lanai::ADD_I_LO;
|
||||
if (Node->hasOneUse())
|
||||
return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, Imm);
|
||||
return CurDAG->getMachineNode(Opc, DL, VT, TFI, Imm);
|
||||
}
|
||||
|
||||
// createLanaiISelDag - This pass converts a legalized DAG into a
|
||||
// Lanai-specific DAG, ready for instruction scheduling.
|
||||
FunctionPass *llvm::createLanaiISelDag(LanaiTargetMachine &TM) {
|
||||
return new LanaiDAGToDAGISel(TM);
|
||||
}
|
1207
lib/Target/Lanai/LanaiISelLowering.cpp
Normal file
1207
lib/Target/Lanai/LanaiISelLowering.cpp
Normal file
File diff suppressed because it is too large
Load Diff
144
lib/Target/Lanai/LanaiISelLowering.h
Normal file
144
lib/Target/Lanai/LanaiISelLowering.h
Normal file
@ -0,0 +1,144 @@
|
||||
//===-- LanaiISelLowering.h - Lanai 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 Lanai uses to lower LLVM code into a
|
||||
// selection DAG.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAIISELLOWERING_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAIISELLOWERING_H
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiRegisterInfo.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace LanaiISD {
|
||||
enum {
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
||||
|
||||
ADJDYNALLOC,
|
||||
|
||||
// Return with a flag operand. Operand 0 is the chain operand.
|
||||
RET_FLAG,
|
||||
|
||||
// CALL - These operations represent an abstract call instruction, which
|
||||
// includes a bunch of information.
|
||||
CALL,
|
||||
|
||||
// SELECT_CC - Operand 0 and operand 1 are selection variable, operand 3
|
||||
// is condition code and operand 4 is flag operand.
|
||||
SELECT_CC,
|
||||
|
||||
// SETCC - Store the conditional to a register
|
||||
SETCC,
|
||||
|
||||
// SET_FLAG - Set flag compare
|
||||
SET_FLAG,
|
||||
|
||||
// BR_CC - Used to glue together a conditional branch and comparison
|
||||
BR_CC,
|
||||
|
||||
// Wrapper - A wrapper node for TargetConstantPool, TargetExternalSymbol,
|
||||
// and TargetGlobalAddress.
|
||||
Wrapper,
|
||||
|
||||
// Get the Higher/Lower 16 bits from a 32-bit immediate
|
||||
HI,
|
||||
LO,
|
||||
|
||||
// Small 21-bit immediate in global memory
|
||||
SMALL
|
||||
};
|
||||
} // namespace LanaiISD
|
||||
|
||||
class LanaiSubtarget;
|
||||
|
||||
class LanaiTargetLowering : public TargetLowering {
|
||||
public:
|
||||
LanaiTargetLowering(const TargetMachine &TM, const LanaiSubtarget &STI);
|
||||
|
||||
// LowerOperation - Provide custom lowering hooks for some operations.
|
||||
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
|
||||
|
||||
// getTargetNodeName - This method returns the name of a target specific
|
||||
// DAG node.
|
||||
const char *getTargetNodeName(unsigned Opcode) const override;
|
||||
|
||||
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerCTTZ(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerCTLZ(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerCTTZ_ZERO_UNDEF(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
unsigned getRegisterByName(const char *RegName, EVT VT,
|
||||
SelectionDAG &DAG) const override;
|
||||
std::pair<unsigned, const TargetRegisterClass *>
|
||||
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
|
||||
StringRef Constraint, MVT VT) const override;
|
||||
ConstraintWeight
|
||||
getSingleConstraintMatchWeight(AsmOperandInfo &Info,
|
||||
const char *Constraint) const override;
|
||||
void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,
|
||||
std::vector<SDValue> &Ops,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
private:
|
||||
SDValue LowerCCCCallTo(SDValue Chain, SDValue Callee,
|
||||
CallingConv::ID CallConv, bool IsVarArg,
|
||||
bool IsTailCall,
|
||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
const SmallVectorImpl<SDValue> &OutVals,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl,
|
||||
SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals) const;
|
||||
|
||||
SDValue LowerCCCArguments(SDValue Chain, CallingConv::ID CallConv,
|
||||
bool IsVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL,
|
||||
SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals) const;
|
||||
|
||||
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||
CallingConv::ID CallConv, bool IsVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL,
|
||||
SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals) const;
|
||||
|
||||
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
SmallVectorImpl<SDValue> &InVals) const override;
|
||||
|
||||
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
|
||||
bool IsVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
SDLoc DL, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals) const override;
|
||||
|
||||
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
|
||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
const SmallVectorImpl<SDValue> &OutVals, SDLoc DL,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
const LanaiRegisterInfo *TRI;
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAIISELLOWERING_H
|
561
lib/Target/Lanai/LanaiInstrFormats.td
Normal file
561
lib/Target/Lanai/LanaiInstrFormats.td
Normal file
@ -0,0 +1,561 @@
|
||||
//===- LanaiInstrFormats.td - Lanai Instruction Formats ----*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class InstLanai<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: Instruction {
|
||||
field bits<32> Inst;
|
||||
field bits<32> SoftFail = 0;
|
||||
let Size = 4;
|
||||
|
||||
let Namespace = "Lanai";
|
||||
let DecoderNamespace = "Lanai";
|
||||
|
||||
bits<4> Opcode;
|
||||
let Inst{31 - 28} = Opcode;
|
||||
|
||||
dag OutOperandList = outs;
|
||||
dag InOperandList = ins;
|
||||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Register Immediate (RI)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |0.A.A.A| . . . . | . . . . |F.H| . . . . . . . . . . . . . . . |
|
||||
// -----------------------------------------------------------------
|
||||
// opcode Rd Rs1 constant (16)
|
||||
//
|
||||
// Action:
|
||||
// Rd <- Rs1 op constant
|
||||
//
|
||||
// Except for shift instructions, `H' determines whether the constant
|
||||
// is in the high (1) or low (0) word. The other halfword is 0x0000,
|
||||
// except for the `AND' instruction (`AAA' = 100), for which the other
|
||||
// halfword is 0xFFFF, and shifts (`AAA' = 111), for which the constant is
|
||||
// sign extended.
|
||||
//
|
||||
// `F' determines whether the instruction modifies (1) or does not
|
||||
// modify (0) the program flags.
|
||||
//
|
||||
// `AAA' specifies the operation: `add' (000), `addc' (001), `sub'
|
||||
// (010), `subb' (011), `and' (100), `or' (101), `xor' (110), or `shift'
|
||||
// (111). For the shift, `H' specifies a logical (0) or arithmetic (1)
|
||||
// shift. The amount and direction of the shift are determined by the
|
||||
// sign extended constant interpreted as a two's complement number. The
|
||||
// shift operation is defined only for the range of:
|
||||
// 31 ... 0 -1 ... -31
|
||||
// \ / \ /
|
||||
// left right
|
||||
// shift shift
|
||||
//
|
||||
// If and only if the `F' bit is 1, RI instructions modify the
|
||||
// condition bits, `Z' (Zero), `N' (Negative), `V' (oVerflow), and `C'
|
||||
// (Carry), according to the result. If the flags are updated, they are
|
||||
// updated as follows:
|
||||
// `Z'
|
||||
// is set if the result is zero and cleared otherwise.
|
||||
//
|
||||
// `N'
|
||||
// is set to the most significant bit of the result.
|
||||
//
|
||||
// `V'
|
||||
// For arithmetic instructions (`add', `addc', `sub', `subb') `V' is
|
||||
// set if the sign (most significant) bits of the input operands are
|
||||
// the same but different from the sign bit of the result and cleared
|
||||
// otherwise. For other RI instructions, `V' is cleared.
|
||||
//
|
||||
// `C'
|
||||
// For arithmetic instructions, `C' is set/cleared if there is/is_not
|
||||
// a carry generated out of the most significant when performing the
|
||||
// twos-complement addition (`sub(a,b) == a + ~b + 1', `subb(a,b) ==
|
||||
// a + ~b + `C''). For left shifts, `C' is set to the least
|
||||
// significant bit discarded by the shift operation. For all other
|
||||
// operations, `C' is cleared.
|
||||
//
|
||||
// A Jump is accomplished by `Rd' being `pc', and it has one shadow.
|
||||
//
|
||||
// The all-0s word is the instruction `R0 <- R0 + 0', which is a no-op.
|
||||
class InstRI<bits<3> op, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern>, Sched<[WriteALU]> {
|
||||
let Itinerary = IIC_ALU;
|
||||
bits<5> Rd;
|
||||
bits<5> Rs1;
|
||||
bit F;
|
||||
bit H;
|
||||
bits<16> imm16;
|
||||
|
||||
let Opcode{3} = 0;
|
||||
let Opcode{2 - 0} = op;
|
||||
let Inst{27 - 23} = Rd;
|
||||
let Inst{22 - 18} = Rs1;
|
||||
let Inst{17} = F;
|
||||
let Inst{16} = H;
|
||||
let Inst{15 - 0} = imm16;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Register Register (RR)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.1.0.0| . . . . | . . . . |F.I| . . . . |B.B.B|J.J.J.J.J|D.D.D|
|
||||
// -----------------------------------------------------------------
|
||||
// opcode Rd Rs1 Rs2 \ operation /
|
||||
//
|
||||
// Action:
|
||||
// `Rd <- Rs1 op Rs2' iff condition DDDI is true.
|
||||
//
|
||||
// `DDDI' is as described for the BR instruction.
|
||||
//
|
||||
// `F' determines whether the instruction modifies (1) or does not
|
||||
// modify (0) the program flags.
|
||||
//
|
||||
// `BBB' determines the operation: `add' (000), `addc' (001), `sub'
|
||||
// (010), `subb' (011), `and' (100), `or' (101), `xor' (110), or "special"
|
||||
// (111). The `JJJJJ' field is irrelevant except for special.
|
||||
//
|
||||
// `JJJJJ' determines which special operation is performed. `10---'
|
||||
// is a logical shift, and `11---' is an arithmetic shift, and ‘00000` is
|
||||
// the SELECT operation. The amount and direction of the shift are
|
||||
// determined by the contents of `Rs2' interpreted as a two's complement
|
||||
// number (in the same way as shifts in the Register-Immediate
|
||||
// instructions in *Note RI::). For the SELECT operation, Rd gets Rs1 if
|
||||
// condition DDDI is true, Rs2 otherwise. All other `JJJJJ' combinations
|
||||
// are reserved for instructions that may be defined in the future.
|
||||
//
|
||||
// If the `F' bit is 1, RR instructions modify the condition bits, `Z'
|
||||
// (Zero), `N' (Negative), `V' (oVerflow), and `C' (Carry), according to
|
||||
// the result. All RR instructions modify the `Z', `N', and `V' flags.
|
||||
// Except for arithmetic instructions (`add', `addc', `sub', `subb'), `V'
|
||||
// is cleared. Only arithmetic instructions and shifts modify `C'. Right
|
||||
// shifts clear C.
|
||||
//
|
||||
// DDDI is as described in the table for the BR instruction and only used for
|
||||
// the select instruction.
|
||||
//
|
||||
// A Jump is accomplished by `Rd' being `pc', and it has one shadow.
|
||||
class InstRR<bits<3> op, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern>, Sched<[WriteALU]> {
|
||||
let Itinerary = IIC_ALU;
|
||||
bits<5> Rd;
|
||||
bits<5> Rs1;
|
||||
bits<5> Rs2;
|
||||
bit F;
|
||||
bits<4> DDDI;
|
||||
bits<5> JJJJJ;
|
||||
|
||||
let Opcode = 0b1100;
|
||||
let Inst{27 - 23} = Rd;
|
||||
let Inst{22 - 18} = Rs1;
|
||||
let Inst{17} = F;
|
||||
let Inst{16} = DDDI{0};
|
||||
let Inst{15 - 11} = Rs2;
|
||||
let Inst{10 - 8} = op;
|
||||
let Inst{7 - 3} = JJJJJ;
|
||||
let Inst{2 - 0} = DDDI{3 - 1};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Register Memory (RM)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.0.0.S| . . . . | . . . . |P.Q| . . . . . . . . . . . . . . . |
|
||||
// -----------------------------------------------------------------
|
||||
// opcode Rd Rs1 constant (16)
|
||||
//
|
||||
// Action:
|
||||
// Rd <- Memory(ea) (Load) see below for the
|
||||
// Memory(ea) <- Rd (Store) definition of ea.
|
||||
//
|
||||
// `S' determines whether the instruction is a Load (0) or a Store (1).
|
||||
// Loads appear in Rd one cycle after this instruction executes. If the
|
||||
// following instruction reads Rd, that instruction will be delayed by 1
|
||||
// clock cycle.
|
||||
//
|
||||
// PQ operation
|
||||
// -- ------------------------------------------
|
||||
// 00 ea = Rs1
|
||||
// 01 ea = Rs1, Rs1 <- Rs1 + constant
|
||||
// 10 ea = Rs1 + constant
|
||||
// 11 ea = Rs1 + constant, Rs1 <- Rs1 + constant
|
||||
//
|
||||
// The constant is sign-extended for this instruction.
|
||||
//
|
||||
// A Jump is accomplished by `Rd' being `pc', and it has *two* delay slots.
|
||||
class InstRM<bit S, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern> {
|
||||
bits<5> Rd;
|
||||
bits<5> Rs1;
|
||||
bit P;
|
||||
bit Q;
|
||||
bits<16> imm16;
|
||||
// Dummy variables to allow multiclass definition of RM and RRM
|
||||
bits<2> YL;
|
||||
bit E;
|
||||
|
||||
let Opcode{3 - 1} = 0b100;
|
||||
let Opcode{0} = S;
|
||||
let Inst{27 - 23} = Rd;
|
||||
let Inst{22 - 18} = Rs1;
|
||||
let Inst{17} = P;
|
||||
let Inst{16} = Q;
|
||||
let Inst{15 - 0} = imm16;
|
||||
|
||||
let PostEncoderMethod = "adjustPqBitsRmAndRrm";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Register Register Memory (RRM)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.0.1.S| . . . . | . . . . |P.Q| . . . . |B.B.B|J.J.J.J.J|Y.L.E|
|
||||
// -----------------------------------------------------------------
|
||||
// opcode Rd Rs1 Rs2 \ operation /
|
||||
//
|
||||
// Action:
|
||||
// Rd <- Memory(ea) (Load) see below for the
|
||||
// Memory(ea) <- Rd (Store) definition of ea.
|
||||
//
|
||||
// The RRM instruction is identical to the RM (*note RM::.) instruction
|
||||
// except that:
|
||||
//
|
||||
// 1. `Rs1 + constant' is replaced with `Rs1 op Rs2', where `op' is
|
||||
// determined in the same way as in the RR instruction (*note RR::.)
|
||||
// and
|
||||
//
|
||||
// 2. part-word memory accesses are allowed as specified below.
|
||||
//
|
||||
// If `BBB' != 111 (i.e.: For all but shift operations):
|
||||
// If `YLE' = 01- => fuLl-word memory access
|
||||
// If `YLE' = 00- => half-word memory access
|
||||
// If `YLE' = 10- => bYte memory access
|
||||
// If `YLE' = --1 => loads are zEro extended
|
||||
// If `YLE' = --0 => loads are sign extended
|
||||
//
|
||||
// If `BBB' = 111 (For shift operations):
|
||||
// fullword memory access are performed.
|
||||
//
|
||||
// All part-word loads write the least significant part of the
|
||||
// destination register with the higher-order bits zero- or sign-extended.
|
||||
// All part-word stores store the least significant part-word of the
|
||||
// source register in the destination memory location.
|
||||
//
|
||||
// A Jump is accomplished by `Rd' being `pc', and it has *two* delay slots.
|
||||
class InstRRM<bit S, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern> {
|
||||
bits<5> Rd;
|
||||
bits<5> Rs1;
|
||||
bits<5> Rs2;
|
||||
bit P;
|
||||
bit Q;
|
||||
bits<3> BBB;
|
||||
bits<5> JJJJJ;
|
||||
bits<2> YL;
|
||||
bit E;
|
||||
|
||||
let Opcode{3 - 1} = 0b101;
|
||||
let Opcode{0} = S;
|
||||
let Inst{27 - 23} = Rd;
|
||||
let Inst{22 - 18} = Rs1;
|
||||
let Inst{17} = P;
|
||||
let Inst{16} = Q;
|
||||
let Inst{15 - 11} = Rs2;
|
||||
let Inst{10 - 8} = BBB;
|
||||
let Inst{7 - 3} = JJJJJ;
|
||||
let Inst{2 - 1} = YL;
|
||||
let Inst{0} = E;
|
||||
|
||||
let PostEncoderMethod = "adjustPqBitsRmAndRrm";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Conditional Branch (BR)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.1.1.0|D.D.D| . . . . . . . . . . . . . . . . . . . . . . |0.I|
|
||||
// -----------------------------------------------------------------
|
||||
// opcode condition constant (23)
|
||||
//
|
||||
// Action:
|
||||
// if (condition) { `pc' <- 4*(zero-extended constant) }
|
||||
//
|
||||
// The BR instruction is an absolute branch.
|
||||
// The constant is scaled as shown by its position in the instruction word such
|
||||
// that it specifies word-aligned addresses in the range [0,2^25-4]
|
||||
//
|
||||
// The `DDDI' field selects the condition that causes the branch to be taken.
|
||||
// (the `I' (Invert sense) bit inverts the sense of the condition):
|
||||
//
|
||||
// DDDI logical function [code, used for...]
|
||||
// ---- -------------------------------------- ------------------------
|
||||
// 0000 1 [T, true]
|
||||
// 0001 0 [F, false]
|
||||
// 0010 C AND Z' [HI, high]
|
||||
// 0011 C' OR Z [LS, low or same]
|
||||
// 0100 C' [CC, carry cleared]
|
||||
// 0101 C [CS, carry set]
|
||||
// 0110 Z' [NE, not equal]
|
||||
// 0111 Z [EQ, equal]
|
||||
// 1000 V' [VC, oVerflow cleared]
|
||||
// 1001 V [VS, oVerflow set]
|
||||
// 1010 N' [PL, plus]
|
||||
// 1011 N [MI, minus]
|
||||
// 1100 (N AND V) OR (N' AND V') [GE, greater than or equal]
|
||||
// 1101 (N AND V') OR (N' AND V) [LT, less than]
|
||||
// 1110 (N AND V AND Z') OR (N' AND V' AND Z') [GT, greater than]
|
||||
// 1111 (Z) OR (N AND V') OR (N' AND V) [LE, less than or equal]
|
||||
//
|
||||
// If the branch is not taken, the BR instruction is a no-op. If the branch is
|
||||
// taken, the processor starts executing instructions at the branch target
|
||||
// address *after* the processor has executed one more instruction. That is,
|
||||
// the branch has one “branch delay slot”. Be very careful if you find yourself
|
||||
// wanting to put a branch in a branch delays slot!
|
||||
class InstBR<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern> {
|
||||
let Itinerary = IIC_ALU;
|
||||
bits<25> addr;
|
||||
bits<4> DDDI;
|
||||
|
||||
let Opcode = 0b1110;
|
||||
let Inst{27 - 25} = DDDI{3 - 1};
|
||||
let Inst{24 - 0} = addr;
|
||||
// These instructions overwrite the last two address bits (which are assumed
|
||||
// and ensured to be 0).
|
||||
let Inst{1} = 0;
|
||||
let Inst{0} = DDDI{0};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Conditional Branch Relative (BRR)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.1.1.0|D.D.D|1|-| . . . . |-.-| . . . . . . . . . . . . . |1.I|
|
||||
// -----------------------------------------------------------------
|
||||
// opcode condition Rs1 constant (14)
|
||||
// Action:
|
||||
// if (condition) { ‘pc’ <- Rs1 + 4*sign-extended constant) }
|
||||
//
|
||||
// BRR behaves like BR, except the branch target address is a 16-bit PC relative
|
||||
// offset.
|
||||
class InstBRR<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern> {
|
||||
bits<4> DDDI;
|
||||
bits<5> Rs1;
|
||||
bits<16> imm16;
|
||||
|
||||
let Opcode = 0b1110;
|
||||
let Inst{27 - 25} = DDDI{3 - 1};
|
||||
let Inst{24} = 1;
|
||||
let Inst{22 - 18} = Rs1;
|
||||
let Inst{17 - 16} = 0;
|
||||
let Inst{15 - 0} = imm16;
|
||||
// Overwrite last two bits which have to be zero
|
||||
let Inst{1} = 1;
|
||||
let Inst{0} = DDDI{0};
|
||||
|
||||
// Set don't cares to zero
|
||||
let Inst{23} = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Conditional Set (SCC)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.1.1.0|D.D.D|0.-| . . . . |-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-|1.I|
|
||||
// -----------------------------------------------------------------
|
||||
// opcode condition Rs1
|
||||
//
|
||||
// Action:
|
||||
// Rs1 <- logical function result
|
||||
//
|
||||
// SCC sets dst_reg to the boolean result of computing the logical function
|
||||
// specified by DDDI, as described in the table for the BR instruction.
|
||||
class InstSCC<dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern> {
|
||||
let Itinerary = IIC_ALU;
|
||||
bits<5> Rs1; // dst_reg in documentation
|
||||
bits<4> DDDI;
|
||||
|
||||
let Opcode = 0b1110;
|
||||
let Inst{27 - 25} = DDDI{3 - 1};
|
||||
let Inst{24} = 0;
|
||||
let Inst{22 - 18} = Rs1;
|
||||
let Inst{1} = 1;
|
||||
let Inst{0} = DDDI{0};
|
||||
|
||||
// Set don't cares to zero
|
||||
let Inst{23} = 0;
|
||||
let Inst{17 - 2} = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Special Load/Store (SLS)
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.1.1.1| . . . . | . . . . |0.S| . . . . . . . . . . . . . . . |
|
||||
// -----------------------------------------------------------------
|
||||
// opcode Rd addr 5msb's address 16 lsb's
|
||||
//
|
||||
// Action:
|
||||
// If S = 0 (LOAD): Rd <- Memory(address);
|
||||
// If S = 1 (STORE): Memory(address) <- Rd
|
||||
//
|
||||
// The timing is the same as for RM (*note RM::.) and RRM (*note
|
||||
// RRM::.) instructions. The two low-order bits of the 21-bit address are
|
||||
// ignored. The address is zero extended. Fullword memory accesses are
|
||||
// performed.
|
||||
class InstSLS<bit S, dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern> {
|
||||
bits<5> Rd;
|
||||
bits<5> msb;
|
||||
bits<16> lsb;
|
||||
|
||||
let Opcode = 0b1111;
|
||||
let Inst{27 - 23} = Rd;
|
||||
let Inst{22 - 18} = msb;
|
||||
let Inst{17} = 0;
|
||||
let Inst{16} = S;
|
||||
let Inst{15 - 0} = lsb;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Special Load Immediate (SLI)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.1.1.1| . . . . | . . . . |1.0| . . . . . . . . . . . . . . . |
|
||||
// -----------------------------------------------------------------
|
||||
// opcode Rd const 5msb's constant 16 lsb's
|
||||
//
|
||||
// Action:
|
||||
// Rd <- constant
|
||||
//
|
||||
// The 21-bit constant is zero-extended. The timing is the same as the
|
||||
// RM instruction (*note RM::.).
|
||||
class InstSLI<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern> {
|
||||
bits<5> Rd;
|
||||
bits<5> msb;
|
||||
bits<16> lsb;
|
||||
|
||||
let Opcode = 0b1111;
|
||||
let Inst{27 - 23} = Rd;
|
||||
let Inst{22 - 18} = msb;
|
||||
let Inst{17} = 1;
|
||||
let Inst{16} = 0;
|
||||
let Inst{15 - 0} = lsb;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Special Part-Word Load/Store (SPLS)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.1.1.1| . . . . | . . . . |1.1.0.Y.S.E.P.Q| . . . . . . . . . |
|
||||
// -----------------------------------------------------------------
|
||||
// opcode Rd Rs1 constant (10)
|
||||
//
|
||||
// Action:
|
||||
// If `YS' = 11 (bYte Store):
|
||||
// Memory(ea) <- (least significant byte of Rr)
|
||||
// If `YS' = 01 (halfword Store):
|
||||
// Memory(ea) <- (least significant half-word of Rr)
|
||||
// If `YS' = 10 (bYte load): Rr <- Memory(ea)
|
||||
// If `YS' = 00 (halfword load): Rr <- Memory(ea)
|
||||
// [Note: here ea is determined as in the the RM instruction. ]
|
||||
// If `SE' = 01 then the value is zEro extended
|
||||
// before being loaded into Rd.
|
||||
// If `SE' = 00 then the value is sign extended
|
||||
// before being loaded into Rd.
|
||||
//
|
||||
// `P' and `Q' are used to determine `ea' as in the RM instruction. The
|
||||
// constant is sign extended. The timing is the same as the RM and RRM
|
||||
// instructions. *Note RM:: and *Note RRM::.
|
||||
//
|
||||
// All part-word loads write the part-word into the least significant
|
||||
// part of the destination register, with the higher-order bits zero- or
|
||||
// sign-extended. All part-word stores store the least significant
|
||||
// part-word of the source register into the destination memory location.
|
||||
class InstSPLS<dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern> {
|
||||
bits<5> Rd;
|
||||
bits<5> Rs1;
|
||||
bits<5> msb;
|
||||
bit Y;
|
||||
bit S;
|
||||
bit E;
|
||||
bit P;
|
||||
bit Q;
|
||||
bits<10> imm10;
|
||||
|
||||
let Opcode = 0b1111;
|
||||
let Inst{27 - 23} = Rd;
|
||||
let Inst{22 - 18} = Rs1;
|
||||
let Inst{17 - 15} = 0b110;
|
||||
let Inst{14} = Y;
|
||||
let Inst{13} = S;
|
||||
let Inst{12} = E;
|
||||
let Inst{11} = P;
|
||||
let Inst{10} = Q;
|
||||
let Inst{9 - 0} = imm10;
|
||||
|
||||
let PostEncoderMethod = "adjustPqBitsSpls";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Special instructions (popc, leadz, trailz)
|
||||
//------------------------------------------------------------------------------
|
||||
// Encoding:
|
||||
// -----------------------------------------------------------------
|
||||
// |1.1.0.1| Rd | Rs1 |F.-| . . . . | . . | . . . . | OP |
|
||||
// -----------------------------------------------------------------
|
||||
// opcode Rd Rs1
|
||||
// Action:
|
||||
// Rd <- Perform action encoded in OP on Rs1
|
||||
// OP is one of:
|
||||
// 0b001 POPC Population count;
|
||||
// 0b010 LEADZ Count number of leading zeros;
|
||||
// 0b011 TRAILZ Count number of trailing zeros;
|
||||
class InstSpecial<bits<3> op, dag outs, dag ins, string asmstr,
|
||||
list<dag> pattern> : InstLanai<outs, ins, asmstr,
|
||||
pattern>, Sched<[WriteALU]> {
|
||||
let Itinerary = IIC_ALU;
|
||||
bit F;
|
||||
bits<5> Rd;
|
||||
bits<5> Rs1;
|
||||
|
||||
let Opcode = 0b1101;
|
||||
let Inst{27 - 23} = Rd;
|
||||
let Inst{22 - 18} = Rs1;
|
||||
let Inst{17} = F;
|
||||
let Inst{16 - 3} = 0;
|
||||
let Inst{2 - 0} = op;
|
||||
}
|
||||
|
||||
// Pseudo instructions
|
||||
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstLanai<outs, ins, asmstr, pattern> {
|
||||
let Inst{15 - 0} = 0;
|
||||
let isPseudo = 1;
|
||||
}
|
324
lib/Target/Lanai/LanaiInstrInfo.cpp
Normal file
324
lib/Target/Lanai/LanaiInstrInfo.cpp
Normal file
@ -0,0 +1,324 @@
|
||||
//===-- LanaiInstrInfo.cpp - Lanai 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 Lanai implementation of the TargetInstrInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiInstrInfo.h"
|
||||
#include "LanaiMachineFunctionInfo.h"
|
||||
#include "LanaiTargetMachine.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
#define GET_INSTRINFO_CTOR_DTOR
|
||||
#include "LanaiGenInstrInfo.inc"
|
||||
|
||||
namespace llvm {
|
||||
LanaiInstrInfo::LanaiInstrInfo()
|
||||
: LanaiGenInstrInfo(Lanai::ADJCALLSTACKDOWN, Lanai::ADJCALLSTACKUP),
|
||||
RegisterInfo() {}
|
||||
|
||||
void LanaiInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator Position,
|
||||
DebugLoc DL, unsigned DestinationRegister,
|
||||
unsigned SourceRegister,
|
||||
bool KillSource) const {
|
||||
if (!Lanai::GPRRegClass.contains(DestinationRegister, SourceRegister)) {
|
||||
llvm_unreachable("Impossible reg-to-reg copy");
|
||||
}
|
||||
|
||||
BuildMI(MBB, Position, DL, get(Lanai::OR_I_LO), DestinationRegister)
|
||||
.addReg(SourceRegister, getKillRegState(KillSource))
|
||||
.addImm(0);
|
||||
}
|
||||
|
||||
void LanaiInstrInfo::storeRegToStackSlot(
|
||||
MachineBasicBlock &MBB, MachineBasicBlock::iterator Position,
|
||||
unsigned SourceRegister, bool IsKill, int FrameIndex,
|
||||
const TargetRegisterClass *RegisterClass,
|
||||
const TargetRegisterInfo *RegisterInfo) const {
|
||||
DebugLoc DL;
|
||||
if (Position != MBB.end()) {
|
||||
DL = Position->getDebugLoc();
|
||||
}
|
||||
|
||||
if (!Lanai::GPRRegClass.hasSubClassEq(RegisterClass)) {
|
||||
llvm_unreachable("Can't store this register to stack slot");
|
||||
}
|
||||
BuildMI(MBB, Position, DL, get(Lanai::SW_RI))
|
||||
.addReg(SourceRegister, getKillRegState(IsKill))
|
||||
.addFrameIndex(FrameIndex)
|
||||
.addImm(0)
|
||||
.addImm(LPAC::ADD);
|
||||
}
|
||||
|
||||
void LanaiInstrInfo::loadRegFromStackSlot(
|
||||
MachineBasicBlock &MBB, MachineBasicBlock::iterator Position,
|
||||
unsigned DestinationRegister, int FrameIndex,
|
||||
const TargetRegisterClass *RegisterClass,
|
||||
const TargetRegisterInfo *RegisterInfo) const {
|
||||
DebugLoc DL;
|
||||
if (Position != MBB.end()) {
|
||||
DL = Position->getDebugLoc();
|
||||
}
|
||||
|
||||
if (!Lanai::GPRRegClass.hasSubClassEq(RegisterClass)) {
|
||||
llvm_unreachable("Can't load this register from stack slot");
|
||||
}
|
||||
BuildMI(MBB, Position, DL, get(Lanai::LDW_RI), DestinationRegister)
|
||||
.addFrameIndex(FrameIndex)
|
||||
.addImm(0)
|
||||
.addImm(LPAC::ADD);
|
||||
}
|
||||
|
||||
bool LanaiInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
static LPCC::CondCode GetOppositeBranchCondition(LPCC::CondCode CC) {
|
||||
switch (CC) {
|
||||
case LPCC::ICC_T: // true
|
||||
return LPCC::ICC_F;
|
||||
case LPCC::ICC_F: // false
|
||||
return LPCC::ICC_T;
|
||||
case LPCC::ICC_HI: // high
|
||||
return LPCC::ICC_LS;
|
||||
case LPCC::ICC_LS: // low or same
|
||||
return LPCC::ICC_HI;
|
||||
case LPCC::ICC_CC: // carry cleared
|
||||
return LPCC::ICC_CS;
|
||||
case LPCC::ICC_CS: // carry set
|
||||
return LPCC::ICC_CC;
|
||||
case LPCC::ICC_NE: // not equal
|
||||
return LPCC::ICC_EQ;
|
||||
case LPCC::ICC_EQ: // equal
|
||||
return LPCC::ICC_NE;
|
||||
case LPCC::ICC_VC: // oVerflow cleared
|
||||
return LPCC::ICC_VS;
|
||||
case LPCC::ICC_VS: // oVerflow set
|
||||
return LPCC::ICC_VC;
|
||||
case LPCC::ICC_PL: // plus (note: 0 is "minus" too here)
|
||||
return LPCC::ICC_MI;
|
||||
case LPCC::ICC_MI: // minus
|
||||
return LPCC::ICC_PL;
|
||||
case LPCC::ICC_GE: // greater than or equal
|
||||
return LPCC::ICC_LT;
|
||||
case LPCC::ICC_LT: // less than
|
||||
return LPCC::ICC_GE;
|
||||
case LPCC::ICC_GT: // greater than
|
||||
return LPCC::ICC_LE;
|
||||
case LPCC::ICC_LE: // less than or equal
|
||||
return LPCC::ICC_GT;
|
||||
default:
|
||||
llvm_unreachable("Invalid condtional code");
|
||||
}
|
||||
}
|
||||
|
||||
// The AnalyzeBranch function is used to examine conditional instructions and
|
||||
// remove unnecessary instructions. This method is used by BranchFolder and
|
||||
// IfConverter machine function passes to improve the CFG.
|
||||
// - TrueBlock is set to the destination if condition evaluates true (it is the
|
||||
// nullptr if the destination is the fall-through branch);
|
||||
// - FalseBlock is set to the destination if condition evaluates to false (it
|
||||
// is the nullptr if the branch is unconditional);
|
||||
// - condition is populated with machine operands needed to generate the branch
|
||||
// to insert in InsertBranch;
|
||||
// Returns: false if branch could successfully be analyzed.
|
||||
bool LanaiInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock *&TrueBlock,
|
||||
MachineBasicBlock *&FalseBlock,
|
||||
SmallVectorImpl<MachineOperand> &Condition,
|
||||
bool AllowModify) const {
|
||||
// Iterator to current instruction being considered.
|
||||
MachineBasicBlock::iterator Instruction = MBB.end();
|
||||
|
||||
// Start from the bottom of the block and work up, examining the
|
||||
// terminator instructions.
|
||||
while (Instruction != MBB.begin()) {
|
||||
--Instruction;
|
||||
|
||||
// Skip over debug values.
|
||||
if (Instruction->isDebugValue())
|
||||
continue;
|
||||
|
||||
// Working from the bottom, when we see a non-terminator
|
||||
// instruction, we're done.
|
||||
if (!isUnpredicatedTerminator(*Instruction))
|
||||
break;
|
||||
|
||||
// A terminator that isn't a branch can't easily be handled
|
||||
// by this analysis.
|
||||
if (!Instruction->isBranch())
|
||||
return true;
|
||||
|
||||
// Handle unconditional branches.
|
||||
if (Instruction->getOpcode() == Lanai::BT) {
|
||||
if (!AllowModify) {
|
||||
TrueBlock = Instruction->getOperand(0).getMBB();
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the block has any instructions after a branch, delete them.
|
||||
while (std::next(Instruction) != MBB.end()) {
|
||||
std::next(Instruction)->eraseFromParent();
|
||||
}
|
||||
|
||||
Condition.clear();
|
||||
FalseBlock = nullptr;
|
||||
|
||||
// Delete the jump if it's equivalent to a fall-through.
|
||||
if (MBB.isLayoutSuccessor(Instruction->getOperand(0).getMBB())) {
|
||||
TrueBlock = nullptr;
|
||||
Instruction->eraseFromParent();
|
||||
Instruction = MBB.end();
|
||||
continue;
|
||||
}
|
||||
|
||||
// TrueBlock is used to indicate the unconditional destination.
|
||||
TrueBlock = Instruction->getOperand(0).getMBB();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle conditional branches
|
||||
unsigned Opcode = Instruction->getOpcode();
|
||||
if (Opcode != Lanai::BRCC)
|
||||
return true; // Unknown opcode.
|
||||
|
||||
// Multiple conditional branches are not handled here so only proceed if
|
||||
// there are no conditions enqueued.
|
||||
if (Condition.empty()) {
|
||||
LPCC::CondCode BranchCond =
|
||||
static_cast<LPCC::CondCode>(Instruction->getOperand(1).getImm());
|
||||
|
||||
// TrueBlock is the target of the previously seen unconditional branch.
|
||||
FalseBlock = TrueBlock;
|
||||
TrueBlock = Instruction->getOperand(0).getMBB();
|
||||
Condition.push_back(MachineOperand::CreateImm(BranchCond));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Multiple conditional branches are not handled.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return false indicating branch successfully analyzed.
|
||||
return false;
|
||||
}
|
||||
|
||||
// ReverseBranchCondition - Reverses the branch condition of the specified
|
||||
// condition list, returning false on success and true if it cannot be
|
||||
// reversed.
|
||||
bool LanaiInstrInfo::ReverseBranchCondition(
|
||||
SmallVectorImpl<llvm::MachineOperand> &Condition) const {
|
||||
assert((Condition.size() == 1) &&
|
||||
"Lanai branch conditions should have one component.");
|
||||
|
||||
LPCC::CondCode BranchCond =
|
||||
static_cast<LPCC::CondCode>(Condition[0].getImm());
|
||||
Condition[0].setImm(GetOppositeBranchCondition(BranchCond));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Insert the branch with condition specified in condition and given targets
|
||||
// (TrueBlock and FalseBlock). This function returns the number of machine
|
||||
// instructions inserted.
|
||||
unsigned LanaiInstrInfo::InsertBranch(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock *TrueBlock,
|
||||
MachineBasicBlock *FalseBlock,
|
||||
ArrayRef<MachineOperand> Condition,
|
||||
DebugLoc DL) const {
|
||||
// Shouldn't be a fall through.
|
||||
assert(TrueBlock && "InsertBranch must not be told to insert a fallthrough");
|
||||
|
||||
// If condition is empty then an unconditional branch is being inserted.
|
||||
if (Condition.empty()) {
|
||||
assert(!FalseBlock && "Unconditional branch with multiple successors!");
|
||||
BuildMI(&MBB, DL, get(Lanai::BT)).addMBB(TrueBlock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Else a conditional branch is inserted.
|
||||
assert((Condition.size() == 1) &&
|
||||
"Lanai branch conditions should have one component.");
|
||||
unsigned ConditionalCode = Condition[0].getImm();
|
||||
BuildMI(&MBB, DL, get(Lanai::BRCC)).addMBB(TrueBlock).addImm(ConditionalCode);
|
||||
|
||||
// If no false block, then false behavior is fall through and no branch needs
|
||||
// to be inserted.
|
||||
if (!FalseBlock)
|
||||
return 1;
|
||||
|
||||
BuildMI(&MBB, DL, get(Lanai::BT)).addMBB(FalseBlock);
|
||||
return 2;
|
||||
}
|
||||
|
||||
unsigned LanaiInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
|
||||
MachineBasicBlock::iterator Instruction = MBB.end();
|
||||
unsigned Count = 0;
|
||||
|
||||
while (Instruction != MBB.begin()) {
|
||||
--Instruction;
|
||||
if (Instruction->isDebugValue())
|
||||
continue;
|
||||
if (Instruction->getOpcode() != Lanai::BT &&
|
||||
Instruction->getOpcode() != Lanai::BRCC) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove the branch.
|
||||
Instruction->eraseFromParent();
|
||||
Instruction = MBB.end();
|
||||
++Count;
|
||||
}
|
||||
|
||||
return Count;
|
||||
}
|
||||
|
||||
unsigned LanaiInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const {
|
||||
if (MI->getOpcode() == Lanai::LDW_RI)
|
||||
if (MI->getOperand(1).isFI() && MI->getOperand(2).isImm() &&
|
||||
MI->getOperand(2).getImm() == 0) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned LanaiInstrInfo::isLoadFromStackSlotPostFE(const MachineInstr *MI,
|
||||
int &FrameIndex) const {
|
||||
if (MI->getOpcode() == Lanai::LDW_RI) {
|
||||
unsigned Reg;
|
||||
if ((Reg = isLoadFromStackSlot(MI, FrameIndex)))
|
||||
return Reg;
|
||||
// Check for post-frame index elimination operations
|
||||
const MachineMemOperand *Dummy;
|
||||
return hasLoadFromStackSlot(MI, Dummy, FrameIndex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned LanaiInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const {
|
||||
if (MI->getOpcode() == Lanai::SW_RI)
|
||||
if (MI->getOperand(0).isFI() && MI->getOperand(1).isImm() &&
|
||||
MI->getOperand(1).getImm() == 0) {
|
||||
FrameIndex = MI->getOperand(0).getIndex();
|
||||
return MI->getOperand(2).getReg();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // namespace llvm
|
126
lib/Target/Lanai/LanaiInstrInfo.h
Normal file
126
lib/Target/Lanai/LanaiInstrInfo.h
Normal file
@ -0,0 +1,126 @@
|
||||
//===- LanaiInstrInfo.h - Lanai 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 Lanai implementation of the TargetInstrInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAIINSTRINFO_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAIINSTRINFO_H
|
||||
|
||||
#include "LanaiRegisterInfo.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
|
||||
#define GET_INSTRINFO_HEADER
|
||||
#include "LanaiGenInstrInfo.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LanaiInstrInfo : public LanaiGenInstrInfo {
|
||||
const LanaiRegisterInfo RegisterInfo;
|
||||
|
||||
public:
|
||||
LanaiInstrInfo();
|
||||
|
||||
// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
||||
// such, whenever a client has an instance of instruction info, it should
|
||||
// always be able to get register info as well (through this method).
|
||||
virtual const LanaiRegisterInfo &getRegisterInfo() const {
|
||||
return RegisterInfo;
|
||||
}
|
||||
|
||||
unsigned isLoadFromStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const override;
|
||||
|
||||
unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI,
|
||||
int &FrameIndex) const override;
|
||||
|
||||
unsigned isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const override;
|
||||
|
||||
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator Position,
|
||||
DebugLoc DL, unsigned DestinationRegister,
|
||||
unsigned SourceRegister, bool KillSource) const override;
|
||||
|
||||
void
|
||||
storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator Position,
|
||||
unsigned SourceRegister, bool IsKill, int FrameIndex,
|
||||
const TargetRegisterClass *RegisterClass,
|
||||
const TargetRegisterInfo *RegisterInfo) const override;
|
||||
|
||||
void
|
||||
loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator Position,
|
||||
unsigned DestinationRegister, int FrameIndex,
|
||||
const TargetRegisterClass *RegisterClass,
|
||||
const TargetRegisterInfo *RegisterInfo) const override;
|
||||
|
||||
bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override;
|
||||
|
||||
bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TrueBlock,
|
||||
MachineBasicBlock *&FalseBlock,
|
||||
SmallVectorImpl<MachineOperand> &Condition,
|
||||
bool AllowModify) const override;
|
||||
|
||||
unsigned RemoveBranch(MachineBasicBlock &MBB) const override;
|
||||
|
||||
bool ReverseBranchCondition(
|
||||
SmallVectorImpl<MachineOperand> &Condition) const override;
|
||||
|
||||
unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TrueBlock,
|
||||
MachineBasicBlock *FalseBlock,
|
||||
ArrayRef<MachineOperand> Condition,
|
||||
DebugLoc DL) const override;
|
||||
};
|
||||
|
||||
static inline bool isSPLSOpcode(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Lanai::LDBs_RI:
|
||||
case Lanai::LDBz_RI:
|
||||
case Lanai::LDHs_RI:
|
||||
case Lanai::LDHz_RI:
|
||||
case Lanai::STB_RI:
|
||||
case Lanai::STH_RI:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool isRMOpcode(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Lanai::LDW_RI:
|
||||
case Lanai::SW_RI:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool isRRMOpcode(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Lanai::LDBs_RR:
|
||||
case Lanai::LDBz_RR:
|
||||
case Lanai::LDHs_RR:
|
||||
case Lanai::LDHz_RR:
|
||||
case Lanai::LDWz_RR:
|
||||
case Lanai::LDW_RR:
|
||||
case Lanai::STB_RR:
|
||||
case Lanai::STH_RR:
|
||||
case Lanai::SW_RR:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAIINSTRINFO_H
|
881
lib/Target/Lanai/LanaiInstrInfo.td
Normal file
881
lib/Target/Lanai/LanaiInstrInfo.td
Normal file
@ -0,0 +1,881 @@
|
||||
//===-- LanaiInstrInfo.td - Target Description for Lanai 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 Lanai instructions in TableGen format.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction format superclass
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "LanaiInstrFormats.td"
|
||||
|
||||
// -------------------------------------------------- //
|
||||
// Instruction Operands and Patterns
|
||||
// -------------------------------------------------- //
|
||||
|
||||
// These are target-independent nodes, but have target-specific formats.
|
||||
def SDT_LanaiCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
|
||||
def SDT_LanaiCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>,
|
||||
SDTCisVT<1, i32>]>;
|
||||
def SDT_LanaiCall : SDTypeProfile<0, -1, [SDTCisVT<0, i32>]>;
|
||||
def SDT_LanaiSetFlag : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
|
||||
def SDT_LanaiSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
|
||||
SDTCisSameAs<1, 2>]>;
|
||||
def SDT_LanaiSetCC : SDTypeProfile<1, 1, [SDTCisVT<0, i32>,
|
||||
SDTCisVT<1, i32>]>;
|
||||
def SDT_LanaiBrCC : SDTypeProfile<0, 2, [SDTCisVT<0, OtherVT>,
|
||||
SDTCisVT<1, i32>]>;
|
||||
def SDT_LanaiAdjDynAlloc : SDTypeProfile<1, 1, [SDTCisVT<0, i32>,
|
||||
SDTCisVT<1, i32>]>;
|
||||
|
||||
def Call : SDNode<"LanaiISD::CALL", SDT_LanaiCall,
|
||||
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
|
||||
SDNPVariadic]>;
|
||||
def RetFlag : SDNode<"LanaiISD::RET_FLAG", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
|
||||
def CallSeqStart : SDNode<"ISD::CALLSEQ_START", SDT_LanaiCallSeqStart,
|
||||
[SDNPHasChain, SDNPOutGlue]>;
|
||||
def CallSeqEnd : SDNode<"ISD::CALLSEQ_END", SDT_LanaiCallSeqEnd,
|
||||
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
|
||||
def LanaiSetFlag : SDNode<"LanaiISD::SET_FLAG", SDT_LanaiSetFlag,
|
||||
[SDNPOutGlue]>;
|
||||
def LanaiBrCC : SDNode<"LanaiISD::BR_CC", SDT_LanaiBrCC,
|
||||
[SDNPHasChain, SDNPInGlue]>;
|
||||
def LanaiSelectCC : SDNode<"LanaiISD::SELECT_CC", SDT_LanaiSelectCC,
|
||||
[SDNPInGlue]>;
|
||||
def LanaiSetCC : SDNode<"LanaiISD::SETCC", SDT_LanaiSetCC,
|
||||
[SDNPInGlue]>;
|
||||
def LanaiHi : SDNode<"LanaiISD::HI", SDTIntUnaryOp>;
|
||||
def LanaiLo : SDNode<"LanaiISD::LO", SDTIntUnaryOp>;
|
||||
def LanaiSmall : SDNode<"LanaiISD::SMALL", SDTIntUnaryOp>;
|
||||
def LanaiAdjDynAlloc : SDNode<"LanaiISD::ADJDYNALLOC", SDT_LanaiAdjDynAlloc>;
|
||||
|
||||
// Extract bits 0-15 (low-end) of an immediate value.
|
||||
def LO16 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((uint64_t)N->getZExtValue() & 0xffff,
|
||||
SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
// Extract bits 16-31 (high-end) of an immediate value.
|
||||
// Transformation function: shift the immediate value down into the low bits.
|
||||
def HI16 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((uint64_t)N->getZExtValue() >> 16, SDLoc(N),
|
||||
MVT::i32);
|
||||
}]>;
|
||||
|
||||
def NEG : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def LO21 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant((uint64_t)N->getZExtValue() & 0x1fffff,
|
||||
SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
// Branch targets
|
||||
def BrTargetAsmOperand : AsmOperandClass {
|
||||
let Name = "BrTarget";
|
||||
}
|
||||
def BrTarget : Operand<OtherVT> {
|
||||
let ParserMatchClass = BrTargetAsmOperand;
|
||||
let EncoderMethod = "getBranchTargetOpValue";
|
||||
let DecoderMethod = "decodeBranch";
|
||||
}
|
||||
|
||||
def CallTargetAsmOperand : AsmOperandClass {
|
||||
let Name = "CallTarget";
|
||||
}
|
||||
def CallTarget : Operand<i32> {
|
||||
let ParserMatchClass = CallTargetAsmOperand;
|
||||
let EncoderMethod = "getBranchTargetOpValue";
|
||||
let DecoderMethod = "decodeBranch";
|
||||
}
|
||||
|
||||
def ImmShiftAsmOperand : AsmOperandClass { let Name = "ImmShift"; }
|
||||
def immShift : Operand<i32>, PatLeaf<(imm), [{
|
||||
int Imm = N->getSExtValue();
|
||||
return Imm >= -31 && Imm <= 31;}]> {
|
||||
let ParserMatchClass = ImmShiftAsmOperand;
|
||||
let DecoderMethod = "decodeShiftImm";
|
||||
}
|
||||
|
||||
def Imm10AsmOperand : AsmOperandClass { let Name = "Imm10"; }
|
||||
def imm10 : Operand<i32>, PatLeaf<(imm), [{
|
||||
return isInt<10>(N->getSExtValue()); }]> {
|
||||
let ParserMatchClass = Imm10AsmOperand;
|
||||
}
|
||||
|
||||
def immZExt21 : PatLeaf<(imm),
|
||||
[{return isUInt<21>(N->getZExtValue()); }], LO21>;
|
||||
|
||||
def LoImm16AsmOperand : AsmOperandClass { let Name = "LoImm16"; }
|
||||
def i32lo16z : Operand<i32>, PatLeaf<(i32 imm), [{
|
||||
// i32lo16 predicate - true if the 32-bit immediate has only rightmost 16
|
||||
// bits set.
|
||||
return ((N->getZExtValue() & 0xFFFFUL) == N->getZExtValue());}], LO16> {
|
||||
let ParserMatchClass = LoImm16AsmOperand;
|
||||
}
|
||||
def i32neg16 : Operand<i32>, PatLeaf<(i32 imm), [{
|
||||
// i32neg16 predicate - true if the 32-bit immediate is negative and can
|
||||
// be represented by a 16 bit integer.
|
||||
int Imm = N->getSExtValue();
|
||||
return (Imm < 0) && (isInt<16>(Imm));}], LO16> {
|
||||
let ParserMatchClass = LoImm16AsmOperand;
|
||||
}
|
||||
def i32lo16s : Operand<i32>, PatLeaf<(i32 imm), [{
|
||||
// i32lo16 predicate - true if the 32-bit immediate has only rightmost 16
|
||||
// bits set.
|
||||
return ((N->getSExtValue() & 0xFFFFUL) == N->getSExtValue());}], LO16> {
|
||||
let ParserMatchClass = LoImm16AsmOperand;
|
||||
}
|
||||
|
||||
def LoImm16AndAsmOperand : AsmOperandClass { let Name = "LoImm16And"; }
|
||||
def i32lo16and : Operand<i32>, PatLeaf<(i32 imm), [{
|
||||
// i32lo16 predicate - true if the 32-bit immediate has the rightmost 16
|
||||
// bits set and the leftmost 16 bits 1's.
|
||||
return (N->getZExtValue() >= 0xFFFF0000UL);}], LO16> {
|
||||
let ParserMatchClass = LoImm16AndAsmOperand;
|
||||
let PrintMethod = "printLo16AndImmOperand";
|
||||
}
|
||||
|
||||
def HiImm16AsmOperand : AsmOperandClass { let Name = "HiImm16"; }
|
||||
def i32hi16 : Operand<i32>, PatLeaf<(i32 imm), [{
|
||||
// i32hi16 predicate - true if the 32-bit immediate has only leftmost 16
|
||||
// bits set.
|
||||
return ((N->getZExtValue() & 0xFFFF0000UL) == N->getZExtValue());}], HI16> {
|
||||
let ParserMatchClass = HiImm16AsmOperand;
|
||||
let PrintMethod = "printHi16ImmOperand";
|
||||
}
|
||||
|
||||
def HiImm16AndAsmOperand : AsmOperandClass { let Name = "HiImm16And"; }
|
||||
def i32hi16and : Operand<i32>, PatLeaf<(i32 imm), [{
|
||||
// i32lo16 predicate - true if the 32-bit immediate has the leftmost 16
|
||||
// bits set and the rightmost 16 bits 1's.
|
||||
return ((N->getZExtValue() & 0xFFFFUL) == 0xFFFFUL);}], HI16> {
|
||||
let ParserMatchClass = HiImm16AndAsmOperand;
|
||||
let PrintMethod = "printHi16AndImmOperand";
|
||||
}
|
||||
|
||||
def LoImm21AsmOperand : AsmOperandClass { let Name = "LoImm21"; }
|
||||
def i32lo21 : Operand<i32>, PatLeaf<(i32 imm), [{
|
||||
// i32lo21 predicate - true if the 32-bit immediate has only rightmost 21
|
||||
// bits set.
|
||||
return ((N->getZExtValue() & 0x1FFFFFUL) == N->getZExtValue());}], LO21> {
|
||||
let ParserMatchClass = LoImm21AsmOperand;
|
||||
}
|
||||
|
||||
def AluOp : Operand<i32> {
|
||||
let PrintMethod = "printAluOperand";
|
||||
}
|
||||
|
||||
// Addressing modes.
|
||||
def ADDRrr : ComplexPattern<i32, 3, "selectAddrRr", [], []>;
|
||||
def ADDRri : ComplexPattern<i32, 3, "selectAddrRi", [frameindex], []>;
|
||||
def ADDRsls : ComplexPattern<i32, 1, "selectAddrSls", [frameindex], []>;
|
||||
def ADDRspls : ComplexPattern<i32, 3, "selectAddrSpls", [frameindex], []>;
|
||||
|
||||
// Address operands
|
||||
def MemRegImmAsmOperand : AsmOperandClass {
|
||||
let Name = "MemRegImm";
|
||||
let ParserMethod = "parseMemoryOperand";
|
||||
}
|
||||
def MEMri : Operand<i32> {
|
||||
let DecoderMethod = "decodeRiMemoryValue";
|
||||
let EncoderMethod = "getRiMemoryOpValue";
|
||||
let MIOperandInfo = (ops GPR:$base, i32lo16s:$offset, AluOp:$Opcode);
|
||||
let ParserMatchClass = MemRegImmAsmOperand;
|
||||
let PrintMethod = "printMemRiOperand";
|
||||
}
|
||||
|
||||
def MemRegRegAsmOperand : AsmOperandClass {
|
||||
let Name = "MemRegReg";
|
||||
let ParserMethod = "parseMemoryOperand";
|
||||
}
|
||||
def MEMrr : Operand<i32> {
|
||||
let DecoderMethod = "decodeRrMemoryValue";
|
||||
let EncoderMethod = "getRrMemoryOpValue";
|
||||
let MIOperandInfo = (ops GPR:$Op1, GPR:$Op2, AluOp:$Opcode);
|
||||
let ParserMatchClass = MemRegRegAsmOperand;
|
||||
let PrintMethod = "printMemRrOperand";
|
||||
}
|
||||
|
||||
def MemImmAsmOperand : AsmOperandClass {
|
||||
let Name = "MemImm";
|
||||
let ParserMethod = "parseMemoryOperand";
|
||||
}
|
||||
def MEMi : Operand<i32> {
|
||||
let MIOperandInfo = (ops i32lo21:$offset);
|
||||
let ParserMatchClass = MemImmAsmOperand;
|
||||
let PrintMethod = "printMemImmOperand";
|
||||
}
|
||||
|
||||
def MemSplsAsmOperand : AsmOperandClass {
|
||||
let Name = "MemSpls";
|
||||
let ParserMethod = "parseMemoryOperand";
|
||||
}
|
||||
def MEMspls : Operand<i32> {
|
||||
let DecoderMethod = "decodeSplsValue";
|
||||
let EncoderMethod = "getSplsOpValue";
|
||||
let MIOperandInfo = (ops GPR:$base, imm10:$offset, AluOp:$Opcode);
|
||||
let ParserMatchClass = MemSplsAsmOperand;
|
||||
let PrintMethod = "printMemSplsOperand";
|
||||
}
|
||||
|
||||
def CCOp : Operand<i32> {
|
||||
let PrintMethod = "printCCOperand";
|
||||
}
|
||||
|
||||
let hasSideEffects = 0, Inst = 0x00000001 in
|
||||
def NOP : InstLanai<(outs), (ins), "nop", []>;
|
||||
|
||||
// Special NOPs to change logging level in vlanai.
|
||||
let hasSideEffects = 0, Inst = 0x00000002 in
|
||||
def LOG0 : InstLanai<(outs), (ins), "log_0", []>;
|
||||
let hasSideEffects = 0, Inst = 0x00000003 in
|
||||
def LOG1 : InstLanai<(outs), (ins), "log_1", []>;
|
||||
let hasSideEffects = 0, Inst = 0x00000004 in
|
||||
def LOG2 : InstLanai<(outs), (ins), "log_2", []>;
|
||||
let hasSideEffects = 0, Inst = 0x00000005 in
|
||||
def LOG3 : InstLanai<(outs), (ins), "log_3", []>;
|
||||
let hasSideEffects = 0, Inst = 0x00000006 in
|
||||
def LOG4 : InstLanai<(outs), (ins), "log_4", []>;
|
||||
|
||||
// Map an SPLS instruction onto itself. All other instructions will be mapped
|
||||
// onto -1. Used to identify SPLS instructions.
|
||||
def splsIdempotent : InstrMapping {
|
||||
let FilterClass = "InstSPLS";
|
||||
let RowFields = ["AsmString"];
|
||||
let ColFields = ["PostEncoderMethod"];
|
||||
let KeyCol = ["adjustPqBitsSpls"];
|
||||
let ValueCols = [["adjustPqBitsSpls"]];
|
||||
}
|
||||
|
||||
// -------------------------------------------------- //
|
||||
// ALU instructions
|
||||
// -------------------------------------------------- //
|
||||
multiclass ALUbase<bits<3> subOp, string AsmStr, SDNode OpNode,
|
||||
PatLeaf LoExt, PatLeaf HiExt,
|
||||
list<dag> loPattern, list<dag> hiPattern> {
|
||||
// Register Immediate
|
||||
let H = 0 in
|
||||
def LO : InstRI<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, LoExt:$imm16),
|
||||
!strconcat(AsmStr, "\t$Rs1, $imm16, $Rd"),
|
||||
loPattern>;
|
||||
let H = 1 in
|
||||
def HI : InstRI<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, HiExt:$imm16),
|
||||
!strconcat(AsmStr, "\t$Rs1, $imm16, $Rd"),
|
||||
hiPattern>;
|
||||
|
||||
}
|
||||
|
||||
multiclass ALUarith<bits<3> subOp, string AsmStr, SDNode OpNode,
|
||||
PatLeaf LoExt, PatLeaf HiExt> {
|
||||
defm I_ : ALUbase<subOp, AsmStr, OpNode, LoExt, HiExt, [], []>;
|
||||
|
||||
// Register Register
|
||||
let JJJJJ = 0, DDDI = 0 in
|
||||
def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2),
|
||||
!strconcat(AsmStr, "\t$Rs1, $Rs2, $Rd"),
|
||||
[(set GPR:$Rd, (OpNode GPR:$Rs1, GPR:$Rs2))]>;
|
||||
// RR Conditional
|
||||
let JJJJJ = 0, Uses = [SR] in
|
||||
def R_CC : InstRR<subOp, (outs GPR:$Rd),
|
||||
(ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI),
|
||||
!strconcat(AsmStr, ".$DDDI\t$Rs1, $Rs2, $Rd"),
|
||||
[]>;
|
||||
}
|
||||
|
||||
multiclass ALUlogic<bits<3> subOp, string AsmStr, SDNode OpNode,
|
||||
PatLeaf LoExt, PatLeaf HiExt> {
|
||||
defm I_ : ALUbase<subOp, AsmStr, OpNode, LoExt, HiExt,
|
||||
[(set GPR:$Rd, (OpNode GPR:$Rs1, LoExt:$imm16))],
|
||||
[(set GPR:$Rd, (OpNode GPR:$Rs1, HiExt:$imm16))]>;
|
||||
|
||||
// Register Register
|
||||
let JJJJJ = 0, DDDI = 0 in
|
||||
def R : InstRR<subOp, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2),
|
||||
!strconcat(AsmStr, "\t$Rs1, $Rs2, $Rd"),
|
||||
[(set GPR:$Rd, (OpNode GPR:$Rs1, GPR:$Rs2))]>;
|
||||
// RR Conditional
|
||||
let JJJJJ = 0, Uses = [SR] in
|
||||
def R_CC : InstRR<subOp, (outs GPR:$Rd),
|
||||
(ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI),
|
||||
!strconcat(AsmStr, ".$DDDI\t$Rs1, $Rs2, $Rd"),
|
||||
[]>;
|
||||
}
|
||||
|
||||
// Non flag setting ALU operations
|
||||
let isAsCheapAsAMove = 1, F = 0 in {
|
||||
let isCommutable = 1 in {
|
||||
defm ADD_ : ALUarith<0b000, "add", add, i32lo16s, i32hi16>;
|
||||
}
|
||||
defm SUB_ : ALUarith<0b010, "sub", sub, i32lo16s, i32hi16>;
|
||||
let isCommutable = 1 in {
|
||||
defm AND_ : ALUlogic<0b100, "and", and, i32lo16and, i32hi16and>;
|
||||
defm OR_ : ALUlogic<0b101, "or", or, i32lo16z, i32hi16>;
|
||||
defm XOR_ : ALUlogic<0b110, "xor", xor, i32lo16s, i32hi16>;
|
||||
}
|
||||
}
|
||||
|
||||
def : Pat<(add GPR:$Rs1, i32lo16z:$imm),
|
||||
(ADD_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
||||
|
||||
def : Pat<(sub GPR:$Rs1, i32lo16z:$imm),
|
||||
(SUB_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
||||
|
||||
def : Pat<(add GPR:$Rs1, i32hi16:$imm),
|
||||
(ADD_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
||||
|
||||
def : Pat<(sub GPR:$Rs1, i32hi16:$imm),
|
||||
(SUB_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
||||
|
||||
def : Pat<(i32 i32lo16and:$imm), (AND_I_LO (i32 R1), i32lo16and:$imm)>;
|
||||
def : Pat<(i32 i32hi16and:$imm), (AND_I_HI (i32 R1), i32hi16and:$imm)>;
|
||||
|
||||
// Change add/sub with negative number to sub/add
|
||||
def : Pat<(add GPR:$Rs1, i32neg16:$imm),
|
||||
(SUB_I_LO GPR:$Rs1, (NEG $imm))>;
|
||||
def : Pat<(sub GPR:$Rs1, i32neg16:$imm),
|
||||
(ADD_I_LO GPR:$Rs1, (NEG $imm))>;
|
||||
|
||||
// Flag (incl. carry) setting addition and subtraction
|
||||
let F = 1, Defs = [SR] in {
|
||||
defm ADD_F_ : ALUarith<0b000, "add.f", addc, i32lo16s, i32hi16>;
|
||||
defm SUB_F_ : ALUarith<0b010, "sub.f", subc, i32lo16s, i32hi16>;
|
||||
}
|
||||
|
||||
def : Pat<(addc GPR:$Rs1, i32lo16z:$imm),
|
||||
(ADD_F_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
||||
|
||||
def : Pat<(subc GPR:$Rs1, i32lo16z:$imm),
|
||||
(SUB_F_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
||||
|
||||
def : Pat<(addc GPR:$Rs1, i32hi16:$imm),
|
||||
(ADD_F_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
||||
|
||||
def : Pat<(subc GPR:$Rs1, i32hi16:$imm),
|
||||
(SUB_F_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
||||
|
||||
// Carry using addition and subtraction
|
||||
let F = 0, Uses = [SR] in {
|
||||
defm ADDC_ : ALUarith<0b001, "addc", adde, i32lo16s, i32hi16>;
|
||||
defm SUBB_ : ALUarith<0b011, "subb", sube, i32lo16s, i32hi16>;
|
||||
}
|
||||
|
||||
def : Pat<(adde GPR:$Rs1, i32lo16z:$imm),
|
||||
(ADDC_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
||||
|
||||
def : Pat<(sube GPR:$Rs1, i32lo16z:$imm),
|
||||
(SUBB_I_LO GPR:$Rs1, i32lo16z:$imm)>;
|
||||
|
||||
def : Pat<(adde GPR:$Rs1, i32hi16:$imm),
|
||||
(ADDC_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
||||
|
||||
def : Pat<(sube GPR:$Rs1, i32hi16:$imm),
|
||||
(SUBB_I_HI GPR:$Rs1, i32hi16:$imm)>;
|
||||
|
||||
// Flag setting ALU operations
|
||||
let isAsCheapAsAMove = 1, F = 1, Defs = [SR] in {
|
||||
defm ADDC_F_ : ALUarith<0b001, "addc.f", adde, i32lo16s, i32hi16>;
|
||||
defm SUBB_F_ : ALUarith<0b011, "subb.f", sube, i32lo16s, i32hi16>;
|
||||
let isCommutable = 1 in {
|
||||
defm AND_F_ : ALUlogic<0b100, "and.f", and, i32lo16and, i32hi16and>;
|
||||
defm OR_F_ : ALUlogic<0b101, "or.f", or, i32lo16z, i32hi16>;
|
||||
defm XOR_F_ : ALUlogic<0b110, "xor.f", xor, i32lo16s, i32hi16>;
|
||||
}
|
||||
}
|
||||
|
||||
def : InstAlias<"mov $src, $dst", (ADD_R GPR:$dst, GPR:$src, R0)>;
|
||||
|
||||
let isAsCheapAsAMove = 1, Rs1 = R0.Num, isCodeGenOnly = 1, H = 1, F = 0,
|
||||
isReMaterializable = 1 in
|
||||
def MOVHI : InstRI<0b000, (outs GPR:$Rd), (ins i32hi16:$imm16),
|
||||
"mov\t$imm16, $Rd",
|
||||
[(set GPR:$Rd, i32hi16:$imm16)]>;
|
||||
|
||||
def : InstAlias<"mov $imm16, $dst", (ADD_I_LO GPR:$dst, R0, i32lo16s:$imm16)>;
|
||||
def : InstAlias<"mov $imm16, $dst", (ADD_I_HI GPR:$dst, R0, i32hi16:$imm16)>;
|
||||
def : InstAlias<"mov $imm16, $dst",
|
||||
(AND_I_LO GPR:$dst, R1, i32lo16and:$imm16)>;
|
||||
def : InstAlias<"mov $imm16, $dst",
|
||||
(AND_I_HI GPR:$dst, R1, i32hi16and:$imm16)>;
|
||||
|
||||
// Shift instructions
|
||||
class ShiftRI<string AsmStr, list<dag> Pattern>
|
||||
: InstRI<0b111, (outs GPR:$Rd), (ins GPR:$Rs1, immShift:$imm16),
|
||||
!strconcat(AsmStr, "\t$Rs1, $imm16, $Rd"), Pattern> {
|
||||
let isReMaterializable = 1;
|
||||
}
|
||||
|
||||
let F = 0 in {
|
||||
let H = 0 in
|
||||
def SL_I : ShiftRI<"sh", [(set GPR:$Rd, (shl GPR:$Rs1, immShift:$imm16))]>;
|
||||
let H = 1 in
|
||||
def SA_I : ShiftRI<"sha", []>;
|
||||
}
|
||||
def : Pat<(srl GPR:$Rs1, immShift:$imm), (SL_I GPR:$Rs1, (NEG $imm))>;
|
||||
def : Pat<(sra GPR:$Rs1, immShift:$imm), (SA_I GPR:$Rs1, (NEG $imm))>;
|
||||
|
||||
let F = 1, Defs = [SR] in {
|
||||
let H = 0 in
|
||||
def SL_F_I : ShiftRI<"sh.f", []>;
|
||||
let H = 1 in
|
||||
def SA_F_I : ShiftRI<"sha.f", []>;
|
||||
}
|
||||
|
||||
class ShiftRR<string AsmStr, list<dag> Pattern>
|
||||
: InstRR<0b111, (outs GPR:$Rd), (ins GPR:$Rs1, GPR:$Rs2), AsmStr, Pattern> {
|
||||
let DDDI = 0;
|
||||
}
|
||||
|
||||
let F = 0 in {
|
||||
let JJJJJ = 0b10000 in
|
||||
def SHL_R : ShiftRR<"sh\t$Rs1, $Rs2, $Rd",
|
||||
[(set GPR:$Rd, (shl GPR:$Rs1, GPR:$Rs2))]>;
|
||||
let isCodeGenOnly = 1 in {
|
||||
let JJJJJ = 0b10000 in
|
||||
def SRL_R : ShiftRR<"sh\t$Rs1, $Rs2, $Rd", []>;
|
||||
}
|
||||
let JJJJJ = 0b11000 in
|
||||
def SRA_R : ShiftRR<"sha\t$Rs1, $Rs2, $Rd", []>;
|
||||
}
|
||||
|
||||
let F = 1, Defs = [SR] in {
|
||||
let JJJJJ = 0b10000 in
|
||||
def SHL_F_R : ShiftRR<"sh.f\t$Rs1, $Rs2, $Rd", []>;
|
||||
let isCodeGenOnly = 1 in {
|
||||
let JJJJJ = 0b10000 in
|
||||
def SRL_F_R : ShiftRR<"sh.f\t$Rs1, $Rs2, $Rd", []>;
|
||||
}
|
||||
let JJJJJ = 0b11000 in
|
||||
def SRA_F_R : ShiftRR<"sha.f\t$Rs1, $Rs2, $Rd", []>;
|
||||
}
|
||||
|
||||
// Expand shift-right operations
|
||||
def : Pat<(srl GPR:$Rs1, GPR:$Rs2),
|
||||
(SRL_R GPR:$Rs1, (SUB_R R0, GPR:$Rs2))>;
|
||||
def : Pat<(sra GPR:$Rs1, GPR:$Rs2),
|
||||
(SRA_R GPR:$Rs1, (SUB_R R0, GPR:$Rs2))>;
|
||||
|
||||
// -------------------------------------------------- //
|
||||
// LOAD instructions
|
||||
// -------------------------------------------------- //
|
||||
|
||||
class LoadRR<string OpcString, PatFrag OpNode, ValueType Ty>
|
||||
: InstRRM<0b0, (outs GPR:$Rd), (ins MEMrr:$src),
|
||||
!strconcat(OpcString, "\t$src, $Rd"),
|
||||
[(set (Ty GPR:$Rd), (OpNode ADDRrr:$src))]>,
|
||||
Sched<[WriteLD]> {
|
||||
bits<20> src;
|
||||
|
||||
let Rs1 = src{19-15};
|
||||
let Rs2 = src{14-10};
|
||||
let P = src{9};
|
||||
let Q = src{8};
|
||||
let BBB = src{7-5};
|
||||
let JJJJJ = src{4-0};
|
||||
}
|
||||
|
||||
class LoadRI<string OpcString, PatFrag OpNode, ValueType Ty>
|
||||
: InstRM<0b0, (outs GPR:$Rd), (ins MEMri:$src),
|
||||
!strconcat(OpcString, "\t$src, $Rd"),
|
||||
[(set (Ty GPR:$Rd), (OpNode ADDRri:$src))]>,
|
||||
Sched<[WriteLD]> {
|
||||
bits<23> src;
|
||||
|
||||
let Itinerary = IIC_LD;
|
||||
let Rs1 = src{22-18};
|
||||
let P = src{17};
|
||||
let Q = src{16};
|
||||
let imm16 = src{15-0};
|
||||
let isReMaterializable = 1;
|
||||
}
|
||||
|
||||
let E = 0 in {
|
||||
let YL = 0b01 in {
|
||||
// uld is used here and ld in the alias as the alias is printed out first if
|
||||
// an alias exist
|
||||
def LDW_RI : LoadRI<"uld", load, i32>;
|
||||
def LDW_RR : LoadRR<"ld", load, i32>;
|
||||
}
|
||||
}
|
||||
|
||||
def : InstAlias<"ld $src, $dst", (LDW_RI GPR:$dst, MEMri:$src)>;
|
||||
|
||||
let E = 1 in {
|
||||
let YL = 0b01 in {
|
||||
def LDWz_RR : LoadRR<"uld", zextloadi32, i32>;
|
||||
}
|
||||
}
|
||||
|
||||
let E = 1 in {
|
||||
let YL = 0b00 in
|
||||
def LDHz_RR : LoadRR<"uld.h", zextloadi16, i32>;
|
||||
let YL = 0b10 in
|
||||
def LDBz_RR : LoadRR<"uld.b", zextloadi8, i32>;
|
||||
}
|
||||
|
||||
let E = 0 in {
|
||||
let YL = 0b00 in
|
||||
def LDHs_RR : LoadRR<"ld.h", sextloadi16, i32>;
|
||||
let YL = 0b10 in
|
||||
def LDBs_RR : LoadRR<"ld.b", sextloadi8, i32>;
|
||||
}
|
||||
|
||||
def LDADDR : InstSLS<0x0, (outs GPR:$Rd), (ins MEMi:$src),
|
||||
"ld\t$src, $Rd",
|
||||
[(set (i32 GPR:$Rd), (load ADDRsls:$src))]>,
|
||||
Sched<[WriteLD]> {
|
||||
bits<21> src;
|
||||
|
||||
let Itinerary = IIC_LD;
|
||||
let msb = src{20-16};
|
||||
let lsb = src{15-0};
|
||||
let isReMaterializable = 1;
|
||||
}
|
||||
|
||||
class LoadSPLS<string asmstring, PatFrag opNode>
|
||||
: InstSPLS<(outs GPR:$Rd), (ins MEMspls:$src),
|
||||
!strconcat(asmstring, "\t$src, $Rd"),
|
||||
[(set (i32 GPR:$Rd), (opNode ADDRspls:$src))]>,
|
||||
Sched<[WriteLD]> {
|
||||
bits<17> src;
|
||||
let Itinerary = IIC_LD;
|
||||
let Rs1 = src{16-12};
|
||||
let P = src{11};
|
||||
let Q = src{10};
|
||||
let imm10 = src{9-0};
|
||||
}
|
||||
|
||||
let Y = 0, S = 0, E = 1 in
|
||||
def LDHz_RI : LoadSPLS<"uld.h", zextloadi16>;
|
||||
|
||||
let Y = 0, S = 0, E = 0 in
|
||||
def LDHs_RI : LoadSPLS<"ld.h", sextloadi16>;
|
||||
|
||||
let Y = 1, S = 0, E = 1 in
|
||||
def LDBz_RI : LoadSPLS<"uld.b", zextloadi8>;
|
||||
|
||||
let Y = 1, S = 0, E = 0 in
|
||||
def LDBs_RI : LoadSPLS<"ld.b", sextloadi8>;
|
||||
|
||||
def SLI : InstSLI<(outs GPR:$Rd), (ins i32lo21:$imm),
|
||||
"mov\t$imm, $Rd",
|
||||
[(set GPR:$Rd, i32lo21:$imm)]> {
|
||||
bits<21> imm;
|
||||
|
||||
let Itinerary = IIC_LD;
|
||||
let msb = imm{20-16};
|
||||
let lsb = imm{15-0};
|
||||
let isReMaterializable = 1;
|
||||
}
|
||||
|
||||
// -------------------------------------------------- //
|
||||
// STORE instructions
|
||||
// -------------------------------------------------- //
|
||||
|
||||
class StoreRR<string OpcString, PatFrag OpNode, ValueType Ty>
|
||||
: InstRRM<0b1, (outs), (ins GPR:$Rd, MEMrr:$dst),
|
||||
!strconcat(OpcString, "\t$Rd, $dst"),
|
||||
[(OpNode (Ty GPR:$Rd), ADDRrr:$dst)]>,
|
||||
Sched<[WriteST]> {
|
||||
bits<20> dst;
|
||||
|
||||
let Itinerary = IIC_ST;
|
||||
let Rs1 = dst{19-15};
|
||||
let Rs2 = dst{14-10};
|
||||
let P = dst{9};
|
||||
let Q = dst{8};
|
||||
let BBB = dst{7-5};
|
||||
let JJJJJ = dst{4-0};
|
||||
}
|
||||
|
||||
class StoreRI<string OpcString, PatFrag OpNode, ValueType Ty>
|
||||
: InstRM<0b1, (outs), (ins GPR:$Rd, MEMri:$dst),
|
||||
!strconcat(OpcString, "\t$Rd, $dst"),
|
||||
[(OpNode (Ty GPR:$Rd), ADDRri:$dst)]>,
|
||||
Sched<[WriteST]> {
|
||||
bits<23> dst;
|
||||
|
||||
let Itinerary = IIC_ST;
|
||||
let Rs1 = dst{22-18};
|
||||
let P = dst{17};
|
||||
let Q = dst{16};
|
||||
let imm16 = dst{15-0};
|
||||
}
|
||||
|
||||
let YL = 0b01, E = 0 in {
|
||||
def SW_RR : StoreRR<"st", store, i32>;
|
||||
def SW_RI : StoreRI<"st", store, i32>;
|
||||
}
|
||||
|
||||
let E = 0 in {
|
||||
let YL = 0b00 in
|
||||
def STH_RR : StoreRR<"st.h", truncstorei16, i32>;
|
||||
let YL = 0b10 in
|
||||
def STB_RR : StoreRR<"st.b", truncstorei8, i32>;
|
||||
}
|
||||
|
||||
def STADDR : InstSLS<0x1, (outs), (ins GPR:$Rd, MEMi:$dst),
|
||||
"st\t$Rd, $dst",
|
||||
[(store (i32 GPR:$Rd), ADDRsls:$dst)]>,
|
||||
Sched<[WriteST]> {
|
||||
bits<21> dst;
|
||||
|
||||
let Itinerary = IIC_ST;
|
||||
let msb = dst{20-16};
|
||||
let lsb = dst{15-0};
|
||||
}
|
||||
|
||||
class StoreSPLS<string asmstring, PatFrag opNode>
|
||||
: InstSPLS<(outs), (ins GPR:$Rd, MEMspls:$dst),
|
||||
!strconcat(asmstring, "\t$Rd, $dst"),
|
||||
[(opNode (i32 GPR:$Rd), ADDRspls:$dst)]>,
|
||||
Sched<[WriteST]> {
|
||||
bits<17> dst;
|
||||
|
||||
let Itinerary = IIC_ST;
|
||||
let Rs1 = dst{16-12};
|
||||
let P = dst{11};
|
||||
let Q = dst{10};
|
||||
let imm10 = dst{9-0};
|
||||
}
|
||||
|
||||
let Y = 0, S = 1, E = 0 in
|
||||
def STH_RI : StoreSPLS<"st.h", truncstorei16>;
|
||||
|
||||
let Y = 1, S = 1, E = 0 in
|
||||
def STB_RI : StoreSPLS<"st.b", truncstorei8>;
|
||||
|
||||
// -------------------------------------------------- //
|
||||
// BRANCH instructions
|
||||
// -------------------------------------------------- //
|
||||
|
||||
let isBranch = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1 in {
|
||||
def BT : InstBR<(outs), (ins BrTarget:$addr),
|
||||
"bt\t$addr",
|
||||
[(br bb:$addr)]> {
|
||||
let DDDI = 0b0000;
|
||||
}
|
||||
let Uses = [SR] in
|
||||
def BRCC : InstBR<(outs), (ins BrTarget:$addr, CCOp:$DDDI),
|
||||
"b$DDDI\t$addr",
|
||||
[(LanaiBrCC bb:$addr, imm:$DDDI)]>;
|
||||
|
||||
let isIndirectBranch = 1 in {
|
||||
def JR : InstRR<0b101, (outs), (ins GPR:$Rs2), "bt\t$Rs2",
|
||||
[(brind GPR:$Rs2)]> {
|
||||
let Rs1 = R0.Num;
|
||||
let Rd = R2.Num;
|
||||
let F = 0;
|
||||
let JJJJJ = 0;
|
||||
let DDDI = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------- //
|
||||
// Condition/SF instructions
|
||||
// -------------------------------------------------- //
|
||||
|
||||
// Instructions to set flags used in lowering comparisons.
|
||||
multiclass SF<bits<3> op2Val, string AsmStr> {
|
||||
let F = 1, Rd = R0.Num, JJJJJ = 0, Defs = [SR], DDDI = 0 in
|
||||
def _RR : InstRR<op2Val, (outs), (ins GPR:$Rs1, GPR:$Rs2),
|
||||
!strconcat(AsmStr, "\t$Rs1, $Rs2, %r0"),
|
||||
[(LanaiSetFlag (i32 GPR:$Rs1), (i32 GPR:$Rs2))]>;
|
||||
let F = 1, Rd = R0.Num, H = 0, Defs = [SR] in
|
||||
def _RI : InstRI<op2Val, (outs), (ins GPR:$Rs1, i32lo16s:$imm16),
|
||||
!strconcat(AsmStr, "\t$Rs1, $imm16, %r0"),
|
||||
[(LanaiSetFlag (i32 GPR:$Rs1), i32lo16s:$imm16)]>;
|
||||
}
|
||||
let isCodeGenOnly = 1 in {
|
||||
defm SFSUB_F : SF<0b010, "sub.f">;
|
||||
}
|
||||
|
||||
// Jump and link
|
||||
let isCall = 1, hasDelaySlot = 1, isCodeGenOnly = 1, Uses = [SP],
|
||||
Defs = [RCA] in {
|
||||
def CALL : Pseudo<(outs), (ins CallTarget:$addr), "", []>;
|
||||
def CALLR : Pseudo<(outs), (ins GPR:$Rs1), "", [(Call GPR:$Rs1)]>;
|
||||
}
|
||||
|
||||
let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1,
|
||||
Uses = [RCA] in {
|
||||
def RET : InstRM<0b0, (outs), (ins),
|
||||
"ld\t-4[%fp], %pc ! return",
|
||||
[(RetFlag)]> {
|
||||
let Rd = PC.Num;
|
||||
let Rs1 = FP.Num;
|
||||
let P = 1;
|
||||
let Q = 0;
|
||||
let imm16 = -4;
|
||||
|
||||
// Post encoding is not needed for RET.
|
||||
let PostEncoderMethod = "";
|
||||
}
|
||||
}
|
||||
|
||||
// ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into
|
||||
// a stack adjustment and the codegen must know that they may modify the stack
|
||||
// pointer before prolog-epilog rewriting occurs.
|
||||
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
||||
// sub / add which can clobber SP.
|
||||
let Defs = [SP], Uses = [SP] in {
|
||||
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt),
|
||||
"#ADJCALLSTACKDOWN $amt",
|
||||
[(CallSeqStart timm:$amt)]>;
|
||||
def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
|
||||
"#ADJCALLSTACKUP $amt1 $amt2",
|
||||
[(CallSeqEnd timm:$amt1, timm:$amt2)]>;
|
||||
}
|
||||
|
||||
let Defs = [SP], Uses = [SP] in {
|
||||
def ADJDYNALLOC : Pseudo<(outs GPR:$dst), (ins GPR:$src),
|
||||
"#ADJDYNALLOC $dst $src",
|
||||
[(set GPR:$dst, (LanaiAdjDynAlloc GPR:$src))]>;
|
||||
}
|
||||
|
||||
let Uses = [SR] in {
|
||||
def SCC : InstSCC<(outs GPR:$Rs1), (ins CCOp:$DDDI),
|
||||
"s$DDDI\t$Rs1",
|
||||
[(set (i32 GPR:$Rs1), (LanaiSetCC imm:$DDDI))]>;
|
||||
}
|
||||
|
||||
// SCC's output is already 1-bit so and'ing with 1 is redundant.
|
||||
def : Pat<(and (LanaiSetCC imm:$DDDI), 1), (SCC imm:$DDDI)>;
|
||||
|
||||
// Select with hardware support
|
||||
let Uses = [SR], isSelect = 1 in {
|
||||
def SELECT : InstRR<0b111, (outs GPR:$Rd),
|
||||
(ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI),
|
||||
"sel.$DDDI $Rs1, $Rs2, $Rd",
|
||||
[(set (i32 GPR:$Rd),
|
||||
(LanaiSelectCC (i32 GPR:$Rs1), (i32 GPR:$Rs2),
|
||||
(imm:$DDDI)))]> {
|
||||
let JJJJJ = 0;
|
||||
let F = 0;
|
||||
}
|
||||
}
|
||||
|
||||
let isBranch = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1,
|
||||
isIndirectBranch = 1, Uses = [SR] in {
|
||||
def BRIND_CC : InstRR<0b101, (outs), (ins GPR:$Rs1, CCOp:$DDDI),
|
||||
"b$DDDI\t$Rs1", []> {
|
||||
let F = 0;
|
||||
let JJJJJ = 0;
|
||||
let Rd = PC.Num;
|
||||
let Rs2 = R0.Num;
|
||||
}
|
||||
|
||||
def BRIND_CCA : InstRR<0b101, (outs), (ins GPR:$Rs1, GPR:$Rs2, CCOp:$DDDI),
|
||||
"b${DDDI}\t$Rs1 add $Rs2", []> {
|
||||
let F = 0;
|
||||
let Rd = PC.Num;
|
||||
let JJJJJ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This only considers the case where BROFF is an immediate and not where
|
||||
// it is a register. Add support for register relative branching.
|
||||
let isBranch = 1, isBarrier = 1, isTerminator = 1, hasDelaySlot = 1, Rs1 = 0,
|
||||
Uses = [SR] in
|
||||
def BRR : InstBRR<(outs), (ins i16imm:$imm16, CCOp:$DDDI),
|
||||
"b${DDDI}.r\t$imm16", []>;
|
||||
|
||||
let F = 0 in {
|
||||
// Population Count (POPC)
|
||||
def POPC: InstSpecial<0b001, (outs GPR:$Rd), (ins GPR:$Rs1),
|
||||
"popc\t$Rs1, $Rd",
|
||||
[(set GPR:$Rd, (ctpop GPR:$Rs1))]>;
|
||||
|
||||
// Count Leading Zeros (LEADZ)
|
||||
def LEADZ: InstSpecial<0b010, (outs GPR:$Rd), (ins GPR:$Rs1),
|
||||
"leadz\t$Rs1, $Rd", [(set GPR:$Rd, (ctlz GPR:$Rs1))]>;
|
||||
let isCodeGenOnly = 1 in
|
||||
def LEADZUNDEF: InstSpecial<0b010, (outs GPR:$Rd), (ins GPR:$Rs1),
|
||||
"leadz\t$Rs1, $Rd",
|
||||
[(set GPR:$Rd, (ctlz_zero_undef GPR:$Rs1))]>;
|
||||
|
||||
// Count Trailing Zeros (TRAILZ)
|
||||
def TRAILZ : InstSpecial<0b011, (outs GPR:$Rd), (ins GPR:$Rs1),
|
||||
"trailz\t$Rs1, $Rd",
|
||||
[(set GPR:$Rd, (cttz GPR:$Rs1))]>;
|
||||
let isCodeGenOnly = 1 in
|
||||
def TRAILZUNDEF : InstSpecial<0b011, (outs GPR:$Rd), (ins GPR:$Rs1),
|
||||
"trailz\t$Rs1, $Rd",
|
||||
[(set GPR:$Rd,
|
||||
(cttz_zero_undef GPR:$Rs1))]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Non-Instruction Patterns
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// signed 16-bit immediate
|
||||
def : Pat<(i32 i32lo16s:$imm), (MOVHI imm:$imm)>;
|
||||
|
||||
// i32 0 and R0 can be used interchangeably.
|
||||
def : Pat<(i32 0), (i32 R0)>;
|
||||
// i32 -1 and R1 can be used interchangeably.
|
||||
def : Pat<(i32 -1), (i32 R1)>;
|
||||
|
||||
// unsigned 16-bit immediate
|
||||
def : Pat<(i32 i32lo16z:$imm), (OR_I_LO (i32 R0), imm:$imm)>;
|
||||
|
||||
// arbitrary immediate
|
||||
def : Pat<(i32 imm:$imm), (OR_I_LO (MOVHI (HI16 imm:$imm)), (LO16 imm:$imm))>;
|
||||
|
||||
// Calls
|
||||
def : Pat<(Call tglobaladdr:$dst), (CALL tglobaladdr:$dst)>;
|
||||
def : Pat<(Call texternalsym:$dst), (CALL texternalsym:$dst)>;
|
||||
|
||||
// Loads
|
||||
def : Pat<(extloadi8 ADDRspls:$src), (i32 (LDBz_RI ADDRspls:$src))>;
|
||||
def : Pat<(extloadi16 ADDRspls:$src), (i32 (LDHz_RI ADDRspls:$src))>;
|
||||
|
||||
// GlobalAddress, ExternalSymbol, Jumptable, ConstantPool
|
||||
def : Pat<(LanaiHi tglobaladdr:$dst), (MOVHI tglobaladdr:$dst)>;
|
||||
def : Pat<(LanaiLo tglobaladdr:$dst), (OR_I_LO (i32 R0), tglobaladdr:$dst)>;
|
||||
def : Pat<(LanaiSmall tglobaladdr:$dst), (SLI tglobaladdr:$dst)>;
|
||||
def : Pat<(LanaiHi texternalsym:$dst), (MOVHI texternalsym:$dst)>;
|
||||
def : Pat<(LanaiLo texternalsym:$dst), (OR_I_LO (i32 R0), texternalsym:$dst)>;
|
||||
def : Pat<(LanaiSmall texternalsym:$dst), (SLI texternalsym:$dst)>;
|
||||
def : Pat<(LanaiHi tblockaddress:$dst), (MOVHI tblockaddress:$dst)>;
|
||||
def : Pat<(LanaiLo tblockaddress:$dst), (OR_I_LO (i32 R0), tblockaddress:$dst)>;
|
||||
def : Pat<(LanaiSmall tblockaddress:$dst), (SLI tblockaddress:$dst)>;
|
||||
def : Pat<(LanaiHi tjumptable:$dst), (MOVHI tjumptable:$dst)>;
|
||||
def : Pat<(LanaiLo tjumptable:$dst), (OR_I_LO (i32 R0), tjumptable:$dst)>;
|
||||
def : Pat<(LanaiSmall tjumptable:$dst), (SLI tjumptable:$dst)>;
|
||||
def : Pat<(LanaiHi tconstpool:$dst), (MOVHI tconstpool:$dst)>;
|
||||
def : Pat<(LanaiLo tconstpool:$dst), (OR_I_LO (i32 R0), tconstpool:$dst)>;
|
||||
def : Pat<(LanaiSmall tconstpool:$dst), (SLI tconstpool:$dst)>;
|
||||
|
||||
def : Pat<(or GPR:$hi, (LanaiLo tglobaladdr:$lo)),
|
||||
(OR_I_LO GPR:$hi, tglobaladdr:$lo)>;
|
||||
def : Pat<(or R0, (LanaiSmall tglobaladdr:$small)),
|
||||
(SLI tglobaladdr:$small)>;
|
||||
def : Pat<(or GPR:$hi, (LanaiLo texternalsym:$lo)),
|
||||
(OR_I_LO GPR:$hi, texternalsym:$lo)>;
|
||||
def : Pat<(or R0, (LanaiSmall texternalsym:$small)),
|
||||
(SLI texternalsym:$small)>;
|
||||
def : Pat<(or GPR:$hi, (LanaiLo tblockaddress:$lo)),
|
||||
(OR_I_LO GPR:$hi, tblockaddress:$lo)>;
|
||||
def : Pat<(or R0, (LanaiSmall tblockaddress:$small)),
|
||||
(SLI tblockaddress:$small)>;
|
||||
def : Pat<(or GPR:$hi, (LanaiLo tjumptable:$lo)),
|
||||
(OR_I_LO GPR:$hi, tjumptable:$lo)>;
|
||||
def : Pat<(or R0, (LanaiSmall tjumptable:$small)),
|
||||
(SLI tjumptable:$small)>;
|
||||
def : Pat<(or GPR:$hi, (LanaiLo tconstpool:$lo)),
|
||||
(OR_I_LO GPR:$hi, tconstpool:$lo)>;
|
||||
def : Pat<(or R0, (LanaiSmall tconstpool:$small)),
|
||||
(SLI tconstpool:$small)>;
|
139
lib/Target/Lanai/LanaiMCInstLower.cpp
Normal file
139
lib/Target/Lanai/LanaiMCInstLower.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
//=-- LanaiMCInstLower.cpp - Convert Lanai 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 Lanai MachineInstrs to their corresponding
|
||||
// MCInst records.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiMCInstLower.h"
|
||||
|
||||
#include "MCTargetDesc/LanaiBaseInfo.h"
|
||||
#include "MCTargetDesc/LanaiMCExpr.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/IR/Constants.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"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MCSymbol *
|
||||
LanaiMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
|
||||
return Printer.getSymbol(MO.getGlobal());
|
||||
}
|
||||
|
||||
MCSymbol *
|
||||
LanaiMCInstLower::GetBlockAddressSymbol(const MachineOperand &MO) const {
|
||||
return Printer.GetBlockAddressSymbol(MO.getBlockAddress());
|
||||
}
|
||||
|
||||
MCSymbol *
|
||||
LanaiMCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
|
||||
return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
|
||||
}
|
||||
|
||||
MCSymbol *LanaiMCInstLower::GetJumpTableSymbol(const MachineOperand &MO) const {
|
||||
SmallString<256> Name;
|
||||
raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI"
|
||||
<< Printer.getFunctionNumber() << '_'
|
||||
<< MO.getIndex();
|
||||
// Create a symbol for the name.
|
||||
return Ctx.getOrCreateSymbol(Name.str());
|
||||
}
|
||||
|
||||
MCSymbol *
|
||||
LanaiMCInstLower::GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
|
||||
SmallString<256> Name;
|
||||
raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI"
|
||||
<< Printer.getFunctionNumber() << '_'
|
||||
<< MO.getIndex();
|
||||
// Create a symbol for the name.
|
||||
return Ctx.getOrCreateSymbol(Name.str());
|
||||
}
|
||||
|
||||
MCOperand LanaiMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
|
||||
MCSymbol *Sym) const {
|
||||
LanaiMCExpr::VariantKind Kind;
|
||||
|
||||
switch (MO.getTargetFlags()) {
|
||||
case LanaiII::MO_NO_FLAG:
|
||||
Kind = LanaiMCExpr::VK_Lanai_None;
|
||||
break;
|
||||
case LanaiII::MO_ABS_HI:
|
||||
Kind = LanaiMCExpr::VK_Lanai_ABS_HI;
|
||||
break;
|
||||
case LanaiII::MO_ABS_LO:
|
||||
Kind = LanaiMCExpr::VK_Lanai_ABS_LO;
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unknown target flag on GV operand");
|
||||
}
|
||||
|
||||
const MCSymbolRefExpr *Symbol = MCSymbolRefExpr::create(Sym, Ctx);
|
||||
const MCExpr *Expr = LanaiMCExpr::create(Kind, Symbol, Ctx);
|
||||
if (!MO.isJTI() && MO.getOffset())
|
||||
Expr = MCBinaryExpr::createAdd(
|
||||
Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
|
||||
return MCOperand::createExpr(Expr);
|
||||
}
|
||||
|
||||
void LanaiMCInstLower::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()) {
|
||||
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_RegisterMask:
|
||||
continue;
|
||||
case MachineOperand::MO_GlobalAddress:
|
||||
MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
|
||||
break;
|
||||
case MachineOperand::MO_BlockAddress:
|
||||
MCOp = LowerSymbolOperand(MO, GetBlockAddressSymbol(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;
|
||||
default:
|
||||
MI->dump();
|
||||
llvm_unreachable("unknown operand type");
|
||||
}
|
||||
|
||||
OutMI.addOperand(MCOp);
|
||||
}
|
||||
}
|
48
lib/Target/Lanai/LanaiMCInstLower.h
Normal file
48
lib/Target/Lanai/LanaiMCInstLower.h
Normal file
@ -0,0 +1,48 @@
|
||||
//===-- LanaiMCInstLower.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_LANAI_LANAIMCINSTLOWER_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAIMCINSTLOWER_H
|
||||
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
class AsmPrinter;
|
||||
class MCContext;
|
||||
class MCInst;
|
||||
class MCOperand;
|
||||
class MCSymbol;
|
||||
class MachineInstr;
|
||||
class MachineModuleInfoMachO;
|
||||
class MachineOperand;
|
||||
class Mangler;
|
||||
|
||||
// LanaiMCInstLower - This class is used to lower an MachineInstr
|
||||
// into an MCInst.
|
||||
class LLVM_LIBRARY_VISIBILITY LanaiMCInstLower {
|
||||
MCContext &Ctx;
|
||||
|
||||
AsmPrinter &Printer;
|
||||
|
||||
public:
|
||||
LanaiMCInstLower(MCContext &CTX, Mangler &Mang, AsmPrinter &AP)
|
||||
: Ctx(CTX), Printer(AP) {}
|
||||
void Lower(const MachineInstr *MI, MCInst &OutMI) const;
|
||||
|
||||
MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const;
|
||||
|
||||
MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
|
||||
MCSymbol *GetBlockAddressSymbol(const MachineOperand &MO) const;
|
||||
MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
|
||||
MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const;
|
||||
MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const;
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAIMCINSTLOWER_H
|
23
lib/Target/Lanai/LanaiMachineFunctionInfo.cpp
Normal file
23
lib/Target/Lanai/LanaiMachineFunctionInfo.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
//===-- LanaiMachineFuctionInfo.cpp - Lanai 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 "LanaiMachineFunctionInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void LanaiMachineFunctionInfo::anchor() {}
|
||||
|
||||
unsigned LanaiMachineFunctionInfo::getGlobalBaseReg() {
|
||||
// Return if it has already been initialized.
|
||||
if (GlobalBaseReg)
|
||||
return GlobalBaseReg;
|
||||
|
||||
return GlobalBaseReg =
|
||||
MF.getRegInfo().createVirtualRegister(&Lanai::GPRRegClass);
|
||||
}
|
58
lib/Target/Lanai/LanaiMachineFunctionInfo.h
Normal file
58
lib/Target/Lanai/LanaiMachineFunctionInfo.h
Normal file
@ -0,0 +1,58 @@
|
||||
//===- LanaiMachineFuctionInfo.h - Lanai 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 Lanai-specific per-machine-function information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAIMACHINEFUNCTIONINFO_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAIMACHINEFUNCTIONINFO_H
|
||||
|
||||
#include "LanaiRegisterInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// LanaiMachineFunctionInfo - This class is derived from MachineFunction and
|
||||
// contains private Lanai target-specific information for each MachineFunction.
|
||||
class LanaiMachineFunctionInfo : public MachineFunctionInfo {
|
||||
virtual void anchor();
|
||||
|
||||
MachineFunction &MF;
|
||||
|
||||
// SRetReturnReg - Lanai 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:
|
||||
explicit LanaiMachineFunctionInfo(MachineFunction &MF)
|
||||
: MF(MF), SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0) {}
|
||||
|
||||
unsigned getSRetReturnReg() const { return SRetReturnReg; }
|
||||
void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
|
||||
|
||||
unsigned getGlobalBaseReg();
|
||||
|
||||
int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
|
||||
void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAIMACHINEFUNCTIONINFO_H
|
414
lib/Target/Lanai/LanaiMemAluCombiner.cpp
Normal file
414
lib/Target/Lanai/LanaiMemAluCombiner.cpp
Normal file
@ -0,0 +1,414 @@
|
||||
//===-- LanaiMemAluCombiner.cpp - Pass to combine memory & ALU operations -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Simple pass to combine memory and ALU operations
|
||||
//
|
||||
// The Lanai ISA supports instructions where a load/store modifies the base
|
||||
// register used in the load/store operation. This pass finds suitable
|
||||
// load/store and ALU instructions and combines them into one instruction.
|
||||
//
|
||||
// For example,
|
||||
// ld [ %r6 -- ], %r12
|
||||
// is a supported instruction that is not currently generated by the instruction
|
||||
// selection pass of this backend. This pass generates these instructions by
|
||||
// merging
|
||||
// add %r6, -4, %r6
|
||||
// followed by
|
||||
// ld [ %r6 ], %r12
|
||||
// in the same machine basic block into one machine instruction.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiTargetMachine.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define GET_INSTRMAP_INFO
|
||||
#include "LanaiGenInstrInfo.inc"
|
||||
|
||||
#define DEBUG_TYPE "lanai-mem-alu-combiner"
|
||||
|
||||
STATISTIC(NumLdStAluCombined, "Number of memory and ALU instructions combined");
|
||||
|
||||
static llvm::cl::opt<bool> DisableMemAluCombiner(
|
||||
"disable-lanai-mem-alu-combiner", llvm::cl::init(false),
|
||||
llvm::cl::desc("Do not combine ALU and memory operators"),
|
||||
llvm::cl::Hidden);
|
||||
|
||||
namespace llvm {
|
||||
void initializeLanaiMemAluCombinerPass(PassRegistry &);
|
||||
} // namespace llvm
|
||||
|
||||
namespace {
|
||||
typedef MachineBasicBlock::iterator MbbIterator;
|
||||
typedef MachineFunction::iterator MfIterator;
|
||||
|
||||
class LanaiMemAluCombiner : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
explicit LanaiMemAluCombiner() : MachineFunctionPass(ID) {
|
||||
initializeLanaiMemAluCombinerPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
const char *getPassName() const override {
|
||||
return "Lanai load / store optimization pass";
|
||||
}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &F) override;
|
||||
|
||||
private:
|
||||
MbbIterator findClosestSuitableAluInstr(MachineBasicBlock *BB,
|
||||
const MbbIterator &MemInstr,
|
||||
bool Decrement);
|
||||
void insertMergedInstruction(MachineBasicBlock *BB,
|
||||
const MbbIterator &MemInstr,
|
||||
const MbbIterator &AluInstr, bool Before);
|
||||
bool combineMemAluInBasicBlock(MachineBasicBlock *BB);
|
||||
|
||||
// Target machine description which we query for register names, data
|
||||
// layout, etc.
|
||||
const TargetInstrInfo *TII;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
char LanaiMemAluCombiner::ID = 0;
|
||||
|
||||
INITIALIZE_PASS(LanaiMemAluCombiner, DEBUG_TYPE,
|
||||
"Lanai memory ALU combiner pass", false, false);
|
||||
|
||||
namespace {
|
||||
bool isSpls(uint16_t Opcode) { return Lanai::splsIdempotent(Opcode) == Opcode; }
|
||||
|
||||
// Determine the opcode for the merged instruction created by considering the
|
||||
// old memory operation's opcode and whether the merged opcode will have an
|
||||
// immediate offset.
|
||||
unsigned mergedOpcode(unsigned OldOpcode, bool ImmediateOffset) {
|
||||
switch (OldOpcode) {
|
||||
case Lanai::LDW_RI:
|
||||
case Lanai::LDW_RR:
|
||||
if (ImmediateOffset)
|
||||
return Lanai::LDW_RI;
|
||||
return Lanai::LDW_RR;
|
||||
case Lanai::LDHs_RI:
|
||||
case Lanai::LDHs_RR:
|
||||
if (ImmediateOffset)
|
||||
return Lanai::LDHs_RI;
|
||||
return Lanai::LDHs_RR;
|
||||
case Lanai::LDHz_RI:
|
||||
case Lanai::LDHz_RR:
|
||||
if (ImmediateOffset)
|
||||
return Lanai::LDHz_RI;
|
||||
return Lanai::LDHz_RR;
|
||||
case Lanai::LDBs_RI:
|
||||
case Lanai::LDBs_RR:
|
||||
if (ImmediateOffset)
|
||||
return Lanai::LDBs_RI;
|
||||
return Lanai::LDBs_RR;
|
||||
case Lanai::LDBz_RI:
|
||||
case Lanai::LDBz_RR:
|
||||
if (ImmediateOffset)
|
||||
return Lanai::LDBz_RI;
|
||||
return Lanai::LDBz_RR;
|
||||
case Lanai::SW_RI:
|
||||
case Lanai::SW_RR:
|
||||
if (ImmediateOffset)
|
||||
return Lanai::SW_RI;
|
||||
return Lanai::SW_RR;
|
||||
case Lanai::STB_RI:
|
||||
case Lanai::STB_RR:
|
||||
if (ImmediateOffset)
|
||||
return Lanai::STB_RI;
|
||||
return Lanai::STB_RR;
|
||||
case Lanai::STH_RI:
|
||||
case Lanai::STH_RR:
|
||||
if (ImmediateOffset)
|
||||
return Lanai::STH_RI;
|
||||
return Lanai::STH_RR;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the machine instruction has non-volatile memory operands of the type
|
||||
// supported for combining with ALU instructions.
|
||||
bool isNonVolatileMemoryOp(const MachineInstr &MI) {
|
||||
if (!MI.hasOneMemOperand())
|
||||
return false;
|
||||
|
||||
// Determine if the machine instruction is a supported memory operation by
|
||||
// testing if the computed merge opcode is a valid memory operation opcode.
|
||||
if (mergedOpcode(MI.getOpcode(), false) == 0)
|
||||
return false;
|
||||
|
||||
const MachineMemOperand *MemOperand = *MI.memoperands_begin();
|
||||
|
||||
// Don't move volatile memory accesses
|
||||
if (MemOperand->isVolatile())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test to see if two machine operands are of the same type. This test is less
|
||||
// strict than the MachineOperand::isIdenticalTo function.
|
||||
bool isSameOperand(const MachineOperand &Op1, const MachineOperand &Op2) {
|
||||
if (Op1.getType() != Op2.getType())
|
||||
return false;
|
||||
|
||||
switch (Op1.getType()) {
|
||||
case MachineOperand::MO_Register:
|
||||
return Op1.getReg() == Op2.getReg();
|
||||
case MachineOperand::MO_Immediate:
|
||||
return Op1.getImm() == Op2.getImm();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool isZeroOperand(const MachineOperand &Op) {
|
||||
return ((Op.isReg() && Op.getReg() == Lanai::R0) ||
|
||||
(Op.isImm() && Op.getImm() == 0));
|
||||
}
|
||||
|
||||
// Determines whether a register is used by an instruction.
|
||||
bool InstrUsesReg(const MbbIterator &Instr, const MachineOperand *Reg) {
|
||||
for (MachineInstr::const_mop_iterator Mop = Instr->operands_begin();
|
||||
Mop != Instr->operands_end(); ++Mop) {
|
||||
if (isSameOperand(*Mop, *Reg))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Converts between machine opcode and AluCode.
|
||||
// Flag using/modifying ALU operations should not be considered for merging and
|
||||
// are omitted from this list.
|
||||
LPAC::AluCode mergedAluCode(unsigned AluOpcode) {
|
||||
switch (AluOpcode) {
|
||||
case Lanai::ADD_I_LO:
|
||||
case Lanai::ADD_R:
|
||||
return LPAC::ADD;
|
||||
case Lanai::SUB_I_LO:
|
||||
case Lanai::SUB_R:
|
||||
return LPAC::SUB;
|
||||
case Lanai::AND_I_LO:
|
||||
case Lanai::AND_R:
|
||||
return LPAC::AND;
|
||||
case Lanai::OR_I_LO:
|
||||
case Lanai::OR_R:
|
||||
return LPAC::OR;
|
||||
case Lanai::XOR_I_LO:
|
||||
case Lanai::XOR_R:
|
||||
return LPAC::XOR;
|
||||
case Lanai::SHL_R:
|
||||
return LPAC::SHL;
|
||||
case Lanai::SRL_R:
|
||||
return LPAC::SRL;
|
||||
case Lanai::SRA_R:
|
||||
return LPAC::SRA;
|
||||
case Lanai::SA_I:
|
||||
case Lanai::SL_I:
|
||||
default:
|
||||
return LPAC::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert a new combined memory and ALU operation instruction.
|
||||
//
|
||||
// This function builds a new machine instruction using the MachineInstrBuilder
|
||||
// class and inserts it before the memory instruction.
|
||||
void LanaiMemAluCombiner::insertMergedInstruction(MachineBasicBlock *BB,
|
||||
const MbbIterator &MemInstr,
|
||||
const MbbIterator &AluInstr,
|
||||
bool Before) {
|
||||
// Insert new combined load/store + alu operation
|
||||
MachineOperand Dest = MemInstr->getOperand(0);
|
||||
MachineOperand Base = MemInstr->getOperand(1);
|
||||
MachineOperand MemOffset = MemInstr->getOperand(2);
|
||||
MachineOperand AluOffset = AluInstr->getOperand(2);
|
||||
|
||||
// Abort if ALU offset is not a register or immediate
|
||||
assert((AluOffset.isReg() || AluOffset.isImm()) &&
|
||||
"Unsupported operand type in merge");
|
||||
|
||||
// Determined merged instructions opcode and ALU code
|
||||
LPAC::AluCode AluOpcode = mergedAluCode(AluInstr->getOpcode());
|
||||
unsigned NewOpc = mergedOpcode(MemInstr->getOpcode(), AluOffset.isImm());
|
||||
|
||||
assert(AluOpcode != LPAC::UNKNOWN && "Unknown ALU code in merging");
|
||||
assert(NewOpc != 0 && "Unknown merged node opcode");
|
||||
|
||||
// Build and insert new machine instruction
|
||||
MachineInstrBuilder InstrBuilder =
|
||||
BuildMI(*BB, MemInstr, MemInstr->getDebugLoc(), TII->get(NewOpc));
|
||||
InstrBuilder.addReg(Dest.getReg(), getDefRegState(true));
|
||||
InstrBuilder.addReg(Base.getReg(), getKillRegState(true));
|
||||
|
||||
// Add offset to machine instruction
|
||||
if (AluOffset.isReg())
|
||||
InstrBuilder.addReg(AluOffset.getReg());
|
||||
else if (AluOffset.isImm())
|
||||
InstrBuilder.addImm(AluOffset.getImm());
|
||||
else
|
||||
llvm_unreachable("Unsupported ld/st ALU merge.");
|
||||
|
||||
// Create a pre-op if the ALU operation preceded the memory operation or the
|
||||
// MemOffset is non-zero (i.e. the memory value should be adjusted before
|
||||
// accessing it), else create a post-op.
|
||||
if (Before || !isZeroOperand(MemOffset))
|
||||
InstrBuilder.addImm(LPAC::makePreOp(AluOpcode));
|
||||
else
|
||||
InstrBuilder.addImm(LPAC::makePostOp(AluOpcode));
|
||||
|
||||
// Transfer memory operands.
|
||||
InstrBuilder->setMemRefs(MemInstr->memoperands_begin(),
|
||||
MemInstr->memoperands_end());
|
||||
}
|
||||
|
||||
// Function determines if ALU operation (in alu_iter) can be combined with
|
||||
// a load/store with base and offset.
|
||||
bool isSuitableAluInstr(bool IsSpls, const MbbIterator &AluIter,
|
||||
const MachineOperand &Base,
|
||||
const MachineOperand &Offset) {
|
||||
// ALU operations have 3 operands
|
||||
if (AluIter->getNumOperands() != 3)
|
||||
return false;
|
||||
|
||||
MachineOperand &Dest = AluIter->getOperand(0);
|
||||
MachineOperand &Op1 = AluIter->getOperand(1);
|
||||
MachineOperand &Op2 = AluIter->getOperand(2);
|
||||
|
||||
// Only match instructions using the base register as destination and with the
|
||||
// base and first operand equal
|
||||
if (!isSameOperand(Dest, Base) || !isSameOperand(Dest, Op1))
|
||||
return false;
|
||||
|
||||
if (Op2.isImm()) {
|
||||
// It is not a match if the 2nd operand in the ALU operation is an
|
||||
// immediate but the ALU operation is not an addition.
|
||||
if (AluIter->getOpcode() != Lanai::ADD_I_LO)
|
||||
return false;
|
||||
|
||||
if (Offset.isReg() && Offset.getReg() == Lanai::R0)
|
||||
return true;
|
||||
|
||||
if (Offset.isImm() &&
|
||||
((Offset.getImm() == 0 &&
|
||||
// Check that the Op2 would fit in the immediate field of the
|
||||
// memory operation.
|
||||
((IsSpls && isInt<10>(Op2.getImm())) ||
|
||||
(!IsSpls && isInt<16>(Op2.getImm())))) ||
|
||||
Offset.getImm() == Op2.getImm()))
|
||||
return true;
|
||||
} else if (Op2.isReg()) {
|
||||
// The Offset and 2nd operand are both registers and equal
|
||||
if (Offset.isReg() && Op2.getReg() == Offset.getReg())
|
||||
return true;
|
||||
} else
|
||||
// Only consider operations with register or immediate values
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MbbIterator LanaiMemAluCombiner::findClosestSuitableAluInstr(
|
||||
MachineBasicBlock *BB, const MbbIterator &MemInstr, const bool Decrement) {
|
||||
MachineOperand *Base = &MemInstr->getOperand(1);
|
||||
MachineOperand *Offset = &MemInstr->getOperand(2);
|
||||
bool IsSpls = isSpls(MemInstr->getOpcode());
|
||||
|
||||
MbbIterator First = MemInstr;
|
||||
MbbIterator Last = Decrement ? BB->begin() : BB->end();
|
||||
|
||||
while (First != Last) {
|
||||
Decrement ? --First : ++First;
|
||||
|
||||
// Skip over debug instructions
|
||||
if (First->isDebugValue())
|
||||
continue;
|
||||
|
||||
if (isSuitableAluInstr(IsSpls, First, *Base, *Offset)) {
|
||||
return First;
|
||||
}
|
||||
|
||||
// Usage of the base register of a form not suitable for merging
|
||||
if (First != Last && InstrUsesReg(First, Base)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return MemInstr;
|
||||
}
|
||||
|
||||
bool LanaiMemAluCombiner::combineMemAluInBasicBlock(MachineBasicBlock *BB) {
|
||||
bool Modified = false;
|
||||
|
||||
MbbIterator MBBIter = BB->begin(), End = BB->end();
|
||||
while (MBBIter != End) {
|
||||
bool IsMemOp = isNonVolatileMemoryOp(*MBBIter);
|
||||
|
||||
if (IsMemOp) {
|
||||
MachineOperand AluOperand = MBBIter->getOperand(3);
|
||||
unsigned int DestReg = MBBIter->getOperand(0).getReg(),
|
||||
BaseReg = MBBIter->getOperand(1).getReg();
|
||||
assert(AluOperand.isImm() && "Unexpected memory operator type");
|
||||
LPAC::AluCode AluOpcode = static_cast<LPAC::AluCode>(AluOperand.getImm());
|
||||
|
||||
// Skip memory operations that already modify the base register or if
|
||||
// the destination and base register are the same
|
||||
if (!LPAC::modifiesOp(AluOpcode) && DestReg != BaseReg) {
|
||||
for (int Inc = 0; Inc <= 1; ++Inc) {
|
||||
MbbIterator AluIter =
|
||||
findClosestSuitableAluInstr(BB, MBBIter, Inc == 0);
|
||||
if (AluIter != MBBIter) {
|
||||
insertMergedInstruction(BB, MBBIter, AluIter, Inc == 0);
|
||||
|
||||
++NumLdStAluCombined;
|
||||
Modified = true;
|
||||
|
||||
// Erase the matching ALU instruction
|
||||
BB->erase(AluIter);
|
||||
// Erase old load/store instruction
|
||||
BB->erase(MBBIter++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (MBBIter == End)
|
||||
break;
|
||||
++MBBIter;
|
||||
}
|
||||
|
||||
return Modified;
|
||||
}
|
||||
|
||||
// Driver function that iterates over the machine basic building blocks of a
|
||||
// machine function
|
||||
bool LanaiMemAluCombiner::runOnMachineFunction(MachineFunction &MF) {
|
||||
if (DisableMemAluCombiner)
|
||||
return false;
|
||||
|
||||
TII = MF.getSubtarget<LanaiSubtarget>().getInstrInfo();
|
||||
bool Modified = false;
|
||||
for (MfIterator MFI = MF.begin(); MFI != MF.end(); ++MFI) {
|
||||
Modified |= combineMemAluInBasicBlock(&*MFI);
|
||||
}
|
||||
return Modified;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
FunctionPass *llvm::createLanaiMemAluCombinerPass() {
|
||||
return new LanaiMemAluCombiner();
|
||||
}
|
282
lib/Target/Lanai/LanaiRegisterInfo.cpp
Normal file
282
lib/Target/Lanai/LanaiRegisterInfo.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
//===-- LanaiRegisterInfo.cpp - Lanai 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 Lanai implementation of the TargetRegisterInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiRegisterInfo.h"
|
||||
#include "LanaiSubtarget.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
|
||||
#define GET_REGINFO_TARGET_DESC
|
||||
#include "LanaiGenRegisterInfo.inc"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
LanaiRegisterInfo::LanaiRegisterInfo()
|
||||
: LanaiGenRegisterInfo(Lanai::RCA) {}
|
||||
|
||||
const uint16_t *
|
||||
LanaiRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
return CSR_SaveList;
|
||||
}
|
||||
|
||||
BitVector LanaiRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
BitVector Reserved(getNumRegs());
|
||||
|
||||
Reserved.set(Lanai::R0);
|
||||
Reserved.set(Lanai::R1);
|
||||
Reserved.set(Lanai::PC);
|
||||
Reserved.set(Lanai::R2);
|
||||
Reserved.set(Lanai::SP);
|
||||
Reserved.set(Lanai::R4);
|
||||
Reserved.set(Lanai::FP);
|
||||
Reserved.set(Lanai::R5);
|
||||
Reserved.set(Lanai::RR1);
|
||||
Reserved.set(Lanai::R10);
|
||||
Reserved.set(Lanai::RR2);
|
||||
Reserved.set(Lanai::R11);
|
||||
Reserved.set(Lanai::RCA);
|
||||
Reserved.set(Lanai::R15);
|
||||
if (hasBasePointer(MF))
|
||||
Reserved.set(getBaseRegister());
|
||||
return Reserved;
|
||||
}
|
||||
|
||||
bool LanaiRegisterInfo::requiresRegisterScavenging(
|
||||
const MachineFunction &MF) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LanaiRegisterInfo::trackLivenessAfterRegAlloc(
|
||||
const MachineFunction &MF) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool isALUArithLoOpcode(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Lanai::ADD_I_LO:
|
||||
case Lanai::SUB_I_LO:
|
||||
case Lanai::ADD_F_I_LO:
|
||||
case Lanai::SUB_F_I_LO:
|
||||
case Lanai::ADDC_I_LO:
|
||||
case Lanai::SUBB_I_LO:
|
||||
case Lanai::ADDC_F_I_LO:
|
||||
case Lanai::SUBB_F_I_LO:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned getOppositeALULoOpcode(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Lanai::ADD_I_LO:
|
||||
return Lanai::SUB_I_LO;
|
||||
case Lanai::SUB_I_LO:
|
||||
return Lanai::ADD_I_LO;
|
||||
case Lanai::ADD_F_I_LO:
|
||||
return Lanai::SUB_F_I_LO;
|
||||
case Lanai::SUB_F_I_LO:
|
||||
return Lanai::ADD_F_I_LO;
|
||||
case Lanai::ADDC_I_LO:
|
||||
return Lanai::SUBB_I_LO;
|
||||
case Lanai::SUBB_I_LO:
|
||||
return Lanai::ADDC_I_LO;
|
||||
case Lanai::ADDC_F_I_LO:
|
||||
return Lanai::SUBB_F_I_LO;
|
||||
case Lanai::SUBB_F_I_LO:
|
||||
return Lanai::ADDC_F_I_LO;
|
||||
default:
|
||||
llvm_unreachable("Invalid ALU lo opcode");
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned getRRMOpcodeVariant(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Lanai::LDBs_RI:
|
||||
return Lanai::LDBs_RR;
|
||||
case Lanai::LDBz_RI:
|
||||
return Lanai::LDBz_RR;
|
||||
case Lanai::LDHs_RI:
|
||||
return Lanai::LDHs_RR;
|
||||
case Lanai::LDHz_RI:
|
||||
return Lanai::LDHz_RR;
|
||||
case Lanai::LDW_RI:
|
||||
return Lanai::LDW_RR;
|
||||
case Lanai::STB_RI:
|
||||
return Lanai::STB_RR;
|
||||
case Lanai::STH_RI:
|
||||
return Lanai::STH_RR;
|
||||
case Lanai::SW_RI:
|
||||
return Lanai::SW_RR;
|
||||
default:
|
||||
llvm_unreachable("Opcode has no RRM variant");
|
||||
}
|
||||
}
|
||||
|
||||
void LanaiRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, unsigned FIOperandNum,
|
||||
RegScavenger *RS) const {
|
||||
assert(SPAdj == 0 && "Unexpected");
|
||||
|
||||
MachineInstr &MI = *II;
|
||||
MachineFunction &MF = *MI.getParent()->getParent();
|
||||
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
|
||||
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
||||
bool HasFP = TFI->hasFP(MF);
|
||||
DebugLoc DL = MI.getDebugLoc();
|
||||
|
||||
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
|
||||
|
||||
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
|
||||
MI.getOperand(FIOperandNum + 1).getImm();
|
||||
|
||||
// Addressable stack objects are addressed using neg. offsets from fp
|
||||
// or pos. offsets from sp/basepointer
|
||||
if (!HasFP || (needsStackRealignment(MF) && FrameIndex >= 0))
|
||||
Offset += MF.getFrameInfo()->getStackSize();
|
||||
|
||||
unsigned FrameReg = getFrameRegister(MF);
|
||||
if (FrameIndex >= 0) {
|
||||
if (hasBasePointer(MF))
|
||||
FrameReg = getBaseRegister();
|
||||
else if (needsStackRealignment(MF))
|
||||
FrameReg = Lanai::SP;
|
||||
}
|
||||
|
||||
// Replace frame index with a frame pointer reference.
|
||||
// If the offset is small enough to fit in the immediate field, directly
|
||||
// encode it.
|
||||
// Otherwise scavenge a register and encode it into a MOVHI, OR_I_LO sequence.
|
||||
if ((isSPLSOpcode(MI.getOpcode()) && !isInt<10>(Offset)) ||
|
||||
!isInt<16>(Offset)) {
|
||||
assert(RS && "Register scavenging must be on");
|
||||
unsigned Reg = RS->FindUnusedReg(&Lanai::GPRRegClass);
|
||||
if (!Reg)
|
||||
Reg = RS->scavengeRegister(&Lanai::GPRRegClass, II, SPAdj);
|
||||
assert(Reg && "Register scavenger failed");
|
||||
|
||||
bool HasNegOffset = false;
|
||||
// ALU ops have unsigned immediate values. If the Offset is negative, we
|
||||
// negate it here and reverse the opcode later.
|
||||
if (Offset < 0) {
|
||||
HasNegOffset = true;
|
||||
Offset = -Offset;
|
||||
}
|
||||
|
||||
if (!isInt<16>(Offset)) {
|
||||
// Reg = hi(offset) | lo(offset)
|
||||
BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::MOVHI), Reg)
|
||||
.addImm(static_cast<uint32_t>(Offset) >> 16);
|
||||
BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::OR_I_LO), Reg)
|
||||
.addReg(Reg)
|
||||
.addImm(Offset & 0xffffU);
|
||||
} else {
|
||||
// Reg = mov(offset)
|
||||
BuildMI(*MI.getParent(), II, DL, TII->get(Lanai::ADD_I_LO), Reg)
|
||||
.addImm(0)
|
||||
.addImm(Offset);
|
||||
}
|
||||
// Reg = FrameReg OP Reg
|
||||
if (MI.getOpcode() == Lanai::ADD_I_LO) {
|
||||
if (HasNegOffset)
|
||||
MI.setDesc(TII->get(Lanai::SUB_R));
|
||||
else
|
||||
MI.setDesc(TII->get(Lanai::ADD_R));
|
||||
} else if (isSPLSOpcode(MI.getOpcode()) || isRMOpcode(MI.getOpcode())) {
|
||||
MI.setDesc(TII->get(getRRMOpcodeVariant(MI.getOpcode())));
|
||||
if (HasNegOffset) {
|
||||
// Change the ALU op (operand 3) from LPAC::ADD (the default) to
|
||||
// LPAC::SUB with the already negated offset.
|
||||
assert((MI.getOperand(3).getImm() == LPAC::ADD) &&
|
||||
"Unexpected ALU op in RRM instruction");
|
||||
MI.getOperand(3).setImm(LPAC::SUB);
|
||||
}
|
||||
} else
|
||||
llvm_unreachable("Unexpected opcode in frame index operation");
|
||||
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
|
||||
MI.getOperand(FIOperandNum + 1)
|
||||
.ChangeToRegister(Reg, /*isDef=*/false, /*isImp=*/false,
|
||||
/*isKill=*/true);
|
||||
return;
|
||||
}
|
||||
|
||||
// ALU arithmetic ops take unsigned immediates. If the offset is negative,
|
||||
// we replace the instruction with one that inverts the opcode and negates
|
||||
// the immediate.
|
||||
if ((Offset < 0) && isALUArithLoOpcode(MI.getOpcode())) {
|
||||
unsigned NewOpcode = getOppositeALULoOpcode(MI.getOpcode());
|
||||
// We know this is an ALU op, so we know the operands are as follows:
|
||||
// 0: destination register
|
||||
// 1: source register (frame register)
|
||||
// 2: immediate
|
||||
BuildMI(*MI.getParent(), II, DL, TII->get(NewOpcode),
|
||||
MI.getOperand(0).getReg())
|
||||
.addReg(FrameReg)
|
||||
.addImm(-Offset);
|
||||
MI.eraseFromParent();
|
||||
} else {
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, /*isDef=*/false);
|
||||
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
|
||||
}
|
||||
}
|
||||
|
||||
bool LanaiRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
// When we need stack realignment and there are dynamic allocas, we can't
|
||||
// reference off of the stack pointer, so we reserve a base pointer.
|
||||
if (needsStackRealignment(MF) && MFI->hasVarSizedObjects())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned LanaiRegisterInfo::getRARegister() const { return Lanai::RCA; }
|
||||
|
||||
unsigned LanaiRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
return Lanai::FP;
|
||||
}
|
||||
|
||||
unsigned LanaiRegisterInfo::getBaseRegister() const { return Lanai::R14; }
|
||||
|
||||
bool LanaiRegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
if (!TargetRegisterInfo::canRealignStack(MF))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned LanaiRegisterInfo::getEHExceptionRegister() const {
|
||||
llvm_unreachable("no exception support");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned LanaiRegisterInfo::getEHHandlerRegister() const {
|
||||
llvm_unreachable("no exception support");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint32_t *
|
||||
LanaiRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
|
||||
CallingConv::ID CC) const {
|
||||
return CSR_RegMask;
|
||||
}
|
63
lib/Target/Lanai/LanaiRegisterInfo.h
Normal file
63
lib/Target/Lanai/LanaiRegisterInfo.h
Normal file
@ -0,0 +1,63 @@
|
||||
//===- LanaiRegisterInfo.h - Lanai 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 Lanai implementation of the TargetRegisterInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAIREGISTERINFO_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAIREGISTERINFO_H
|
||||
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
|
||||
#define GET_REGINFO_HEADER
|
||||
#include "LanaiGenRegisterInfo.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class TargetInstrInfo;
|
||||
class Type;
|
||||
|
||||
struct LanaiRegisterInfo : public LanaiGenRegisterInfo {
|
||||
LanaiRegisterInfo();
|
||||
|
||||
const uint32_t *getCallPreservedMask(const MachineFunction &MF,
|
||||
CallingConv::ID) const override;
|
||||
|
||||
// Code Generation virtual methods.
|
||||
const uint16_t *
|
||||
getCalleeSavedRegs(const MachineFunction *MF = 0) const override;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const override;
|
||||
|
||||
bool requiresRegisterScavenging(const MachineFunction &MF) const override;
|
||||
|
||||
bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override;
|
||||
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
unsigned FIOperandNum,
|
||||
RegScavenger *RS = NULL) const override;
|
||||
|
||||
bool canRealignStack(const MachineFunction &MF) const override;
|
||||
|
||||
// Debug information queries.
|
||||
unsigned getRARegister() const;
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const override;
|
||||
unsigned getBaseRegister() const;
|
||||
bool hasBasePointer(const MachineFunction &MF) const;
|
||||
|
||||
// Exception handling queries.
|
||||
unsigned getEHExceptionRegister() const;
|
||||
unsigned getEHHandlerRegister() const;
|
||||
int getDwarfRegNum(unsigned RegNum, bool IsEH) const;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAIREGISTERINFO_H
|
64
lib/Target/Lanai/LanaiRegisterInfo.td
Normal file
64
lib/Target/Lanai/LanaiRegisterInfo.td
Normal file
@ -0,0 +1,64 @@
|
||||
//===- LanaiRegisterInfo.td - Lanai 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 Lanai register file
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Registers are identified with 5-bit ID numbers.
|
||||
class LanaiReg<bits<5> num, string n, list<Register> subregs = [],
|
||||
list<string> altNames = []> : Register<n, altNames> {
|
||||
field bits<5> Num;
|
||||
let Num = num;
|
||||
let Namespace = "Lanai";
|
||||
let SubRegs = subregs;
|
||||
}
|
||||
|
||||
let Namespace = "Lanai" in {
|
||||
def sub_32 : SubRegIndex<32>;
|
||||
}
|
||||
|
||||
// Integer registers
|
||||
foreach i = 0-31 in {
|
||||
def R#i : LanaiReg<i, "r"#i>, DwarfRegNum<[i]>;
|
||||
}
|
||||
|
||||
// Register aliases
|
||||
let SubRegIndices = [sub_32] in {
|
||||
def PC : LanaiReg< 2, "pc", [R2]>, DwarfRegAlias<R2>;
|
||||
def SP : LanaiReg< 4, "sp", [R4]>, DwarfRegAlias<R4>;
|
||||
def FP : LanaiReg< 5, "fp", [R5]>, DwarfRegAlias<R5>;
|
||||
def RV : LanaiReg< 8, "rv", [R8]>, DwarfRegAlias<R8>;
|
||||
def RR1 : LanaiReg<10, "rr1", [R10]>, DwarfRegAlias<R10>;
|
||||
def RR2 : LanaiReg<11, "rr2", [R11]>, DwarfRegAlias<R11>;
|
||||
def RCA : LanaiReg<15, "rca", [R15]>, DwarfRegAlias<R15>;
|
||||
}
|
||||
|
||||
// Define a status register to capture the dependencies between the set flag
|
||||
// and setcc instructions
|
||||
def SR : LanaiReg< 0, "sw">;
|
||||
|
||||
// Register classes.
|
||||
def GPR : RegisterClass<"Lanai", [i32], 32,
|
||||
(add R3, R9, R12, R13, R14, R16, R17,
|
||||
(sequence "R%i", 20, 31),
|
||||
R6, R7, R18, R19, // registers for passing arguments
|
||||
R15, RCA, // register for constant addresses
|
||||
R10, RR1, R11, RR2, // programmer controlled registers
|
||||
R8, RV, // return value
|
||||
R5, FP, // frame pointer
|
||||
R4, SP, // stack pointer
|
||||
R2, PC, // program counter
|
||||
R1, // all 1s (0xffffffff)
|
||||
R0 // constant 0
|
||||
)>;
|
||||
|
||||
// Condition code register class
|
||||
def CCR : RegisterClass<"Lanai", [i32], 32, (add SR)> {
|
||||
let CopyCost = -1; // Don't allow copying of status registers
|
||||
let isAllocatable = 0;
|
||||
}
|
66
lib/Target/Lanai/LanaiSchedule.td
Normal file
66
lib/Target/Lanai/LanaiSchedule.td
Normal file
@ -0,0 +1,66 @@
|
||||
//=-LanaiSchedule.td - Lanai Scheduling Definitions --*- tablegen -*-=========//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def ALU_FU : FuncUnit;
|
||||
def LDST_FU : FuncUnit;
|
||||
|
||||
def IIC_ALU : InstrItinClass;
|
||||
def IIC_LD : InstrItinClass;
|
||||
def IIC_ST : InstrItinClass;
|
||||
|
||||
def LanaiItinerary : ProcessorItineraries<[ALU_FU, LDST_FU],[],[
|
||||
InstrItinData<IIC_LD, [InstrStage<1, [LDST_FU]>]>,
|
||||
InstrItinData<IIC_ST, [InstrStage<1, [LDST_FU]>]>,
|
||||
InstrItinData<IIC_ALU, [InstrStage<1, [ALU_FU]>]>
|
||||
]>;
|
||||
|
||||
def LanaiSchedModel : SchedMachineModel {
|
||||
// Cycles for loads to access the cache [default = -1]
|
||||
let LoadLatency = 2;
|
||||
|
||||
// Max micro-ops that can be buffered for optimized loop dispatch/execution.
|
||||
// [default = -1]
|
||||
let LoopMicroOpBufferSize = 0;
|
||||
|
||||
// Allow scheduler to assign default model to any unrecognized opcodes.
|
||||
// [default = 1]
|
||||
let CompleteModel = 0;
|
||||
|
||||
// Max micro-ops that may be scheduled per cycle. [default = 1]
|
||||
let IssueWidth = 1;
|
||||
|
||||
// Determines which instructions are allowed in a group. 1 is an inorder
|
||||
// CPU with variable latencies. [default = -1]
|
||||
let MinLatency = 1;
|
||||
|
||||
// Extra cycles for a mispredicted branch. [default = -1]
|
||||
let MispredictPenalty = 10;
|
||||
|
||||
// Enable Post RegAlloc Scheduler pass. [default = 0]
|
||||
let PostRAScheduler = 0;
|
||||
|
||||
// Max micro-ops that can be buffered. [default = -1]
|
||||
let MicroOpBufferSize = 0;
|
||||
|
||||
// Per-cycle resources tables. [default = NoItineraries]
|
||||
let Itineraries = LanaiItinerary;
|
||||
}
|
||||
|
||||
def ALU : ProcResource<1> { let BufferSize = 0; }
|
||||
def LdSt : ProcResource<1> { let BufferSize = 0; }
|
||||
|
||||
def WriteLD : SchedWrite;
|
||||
def WriteST : SchedWrite;
|
||||
def WriteALU : SchedWrite;
|
||||
|
||||
let SchedModel = LanaiSchedModel in {
|
||||
def : WriteRes<WriteLD, [LdSt]> { let Latency = 2; }
|
||||
def : WriteRes<WriteST, [LdSt]> { let Latency = 2; }
|
||||
def : WriteRes<WriteALU, [ALU]> { let Latency = 1; }
|
||||
}
|
33
lib/Target/Lanai/LanaiSelectionDAGInfo.cpp
Normal file
33
lib/Target/Lanai/LanaiSelectionDAGInfo.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
//===-- LanaiSelectionDAGInfo.cpp - Lanai 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 LanaiSelectionDAGInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiSelectionDAGInfo.h"
|
||||
|
||||
#include "LanaiTargetMachine.h"
|
||||
|
||||
#define DEBUG_TYPE "lanai-selectiondag-info"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
SDValue LanaiSelectionDAGInfo::EmitTargetCodeForMemcpy(
|
||||
SelectionDAG &DAG, SDLoc dl, SDValue Chain, SDValue Dst, SDValue Src,
|
||||
SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline,
|
||||
MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
|
||||
ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
|
||||
if (!ConstantSize)
|
||||
return SDValue();
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
} // namespace llvm
|
36
lib/Target/Lanai/LanaiSelectionDAGInfo.h
Normal file
36
lib/Target/Lanai/LanaiSelectionDAGInfo.h
Normal file
@ -0,0 +1,36 @@
|
||||
//===-- LanaiSelectionDAGInfo.h - Lanai 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 Lanai subclass for TargetSelectionDAGInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAISELECTIONDAGINFO_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAISELECTIONDAGINFO_H
|
||||
|
||||
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LanaiSelectionDAGInfo : public SelectionDAGTargetInfo {
|
||||
public:
|
||||
LanaiSelectionDAGInfo() = default;
|
||||
|
||||
SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl, SDValue Chain,
|
||||
SDValue Dst, SDValue Src, SDValue Size,
|
||||
unsigned Align, bool isVolatile,
|
||||
bool AlwaysInline,
|
||||
MachinePointerInfo DstPtrInfo,
|
||||
MachinePointerInfo SrcPtrInfo) const override;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAISELECTIONDAGINFO_H
|
327
lib/Target/Lanai/LanaiSetflagAluCombiner.cpp
Normal file
327
lib/Target/Lanai/LanaiSetflagAluCombiner.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
//===-- LanaiSetflagAluCombiner.cpp - Pass to combine set flag & ALU ops --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiTargetMachine.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "lanai-setflag-alu-combiner"
|
||||
|
||||
STATISTIC(NumSetflagAluCombined,
|
||||
"Number of SET_FLAG and ALU instructions combined");
|
||||
|
||||
static llvm::cl::opt<bool> DisableSetflagAluCombiner(
|
||||
"disable-lanai-setflag-alu-combiner", llvm::cl::init(false),
|
||||
llvm::cl::desc("Do not combine SET_FLAG and ALU operators"),
|
||||
llvm::cl::Hidden);
|
||||
|
||||
namespace llvm {
|
||||
void initializeLanaiSetflagAluCombinerPass(PassRegistry &);
|
||||
} // namespace llvm
|
||||
|
||||
namespace {
|
||||
typedef MachineBasicBlock::iterator MbbIterator;
|
||||
typedef MachineFunction::iterator MfIterator;
|
||||
|
||||
class LanaiSetflagAluCombiner : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
LanaiSetflagAluCombiner() : MachineFunctionPass(ID) {
|
||||
initializeLanaiSetflagAluCombinerPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
const char *getPassName() const override {
|
||||
return "Lanai SET_FLAG ALU combiner pass";
|
||||
}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &F) override;
|
||||
|
||||
private:
|
||||
bool CombineSetflagAluInBasicBlock(MachineFunction *MF,
|
||||
MachineBasicBlock *BB);
|
||||
};
|
||||
} // namespace
|
||||
|
||||
char LanaiSetflagAluCombiner::ID = 0;
|
||||
|
||||
INITIALIZE_PASS(LanaiSetflagAluCombiner, DEBUG_TYPE,
|
||||
"Lanai SET_FLAG ALU combiner pass", false, false);
|
||||
|
||||
namespace {
|
||||
|
||||
const unsigned kInvalid = -1;
|
||||
|
||||
static unsigned flagSettingOpcodeVariant(unsigned OldOpcode) {
|
||||
switch (OldOpcode) {
|
||||
case Lanai::ADD_I_HI:
|
||||
return Lanai::ADD_F_I_HI;
|
||||
case Lanai::ADD_I_LO:
|
||||
return Lanai::ADD_F_I_LO;
|
||||
case Lanai::ADD_R:
|
||||
return Lanai::ADD_F_R;
|
||||
case Lanai::ADD_R_CC:
|
||||
return Lanai::ADD_F_R_CC;
|
||||
case Lanai::ADDC_I_HI:
|
||||
return Lanai::ADDC_F_I_HI;
|
||||
case Lanai::ADDC_I_LO:
|
||||
return Lanai::ADDC_F_I_LO;
|
||||
case Lanai::ADDC_R:
|
||||
return Lanai::ADDC_F_R;
|
||||
case Lanai::ADDC_R_CC:
|
||||
return Lanai::ADDC_F_R_CC;
|
||||
case Lanai::AND_I_HI:
|
||||
return Lanai::AND_F_I_HI;
|
||||
case Lanai::AND_I_LO:
|
||||
return Lanai::AND_F_I_LO;
|
||||
case Lanai::AND_R:
|
||||
return Lanai::AND_F_R;
|
||||
case Lanai::AND_R_CC:
|
||||
return Lanai::AND_F_R_CC;
|
||||
case Lanai::OR_I_HI:
|
||||
return Lanai::OR_F_I_HI;
|
||||
case Lanai::OR_I_LO:
|
||||
return Lanai::OR_F_I_LO;
|
||||
case Lanai::OR_R:
|
||||
return Lanai::OR_F_R;
|
||||
case Lanai::OR_R_CC:
|
||||
return Lanai::OR_F_R_CC;
|
||||
case Lanai::SL_I:
|
||||
return Lanai::SL_F_I;
|
||||
case Lanai::SRL_R:
|
||||
return Lanai::SRL_F_R;
|
||||
case Lanai::SA_I:
|
||||
return Lanai::SA_F_I;
|
||||
case Lanai::SRA_R:
|
||||
return Lanai::SRA_F_R;
|
||||
case Lanai::SUB_I_HI:
|
||||
return Lanai::SUB_F_I_HI;
|
||||
case Lanai::SUB_I_LO:
|
||||
return Lanai::SUB_F_I_LO;
|
||||
case Lanai::SUB_R:
|
||||
return Lanai::SUB_F_R;
|
||||
case Lanai::SUB_R_CC:
|
||||
return Lanai::SUB_F_R_CC;
|
||||
case Lanai::SUBB_I_HI:
|
||||
return Lanai::SUBB_F_I_HI;
|
||||
case Lanai::SUBB_I_LO:
|
||||
return Lanai::SUBB_F_I_LO;
|
||||
case Lanai::SUBB_R:
|
||||
return Lanai::SUBB_F_R;
|
||||
case Lanai::SUBB_R_CC:
|
||||
return Lanai::SUBB_F_R_CC;
|
||||
case Lanai::XOR_I_HI:
|
||||
return Lanai::XOR_F_I_HI;
|
||||
case Lanai::XOR_I_LO:
|
||||
return Lanai::XOR_F_I_LO;
|
||||
case Lanai::XOR_R:
|
||||
return Lanai::XOR_F_R;
|
||||
case Lanai::XOR_R_CC:
|
||||
return Lanai::XOR_F_R_CC;
|
||||
default:
|
||||
return kInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns whether opcode corresponds to instruction that sets flags.
|
||||
static bool isFlagSettingInstruction(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Lanai::ADDC_F_I_HI:
|
||||
case Lanai::ADDC_F_I_LO:
|
||||
case Lanai::ADDC_F_R:
|
||||
case Lanai::ADDC_F_R_CC:
|
||||
case Lanai::ADD_F_I_HI:
|
||||
case Lanai::ADD_F_I_LO:
|
||||
case Lanai::ADD_F_R:
|
||||
case Lanai::ADD_F_R_CC:
|
||||
case Lanai::AND_F_I_HI:
|
||||
case Lanai::AND_F_I_LO:
|
||||
case Lanai::AND_F_R:
|
||||
case Lanai::AND_F_R_CC:
|
||||
case Lanai::OR_F_I_HI:
|
||||
case Lanai::OR_F_I_LO:
|
||||
case Lanai::OR_F_R:
|
||||
case Lanai::OR_F_R_CC:
|
||||
case Lanai::SFSUB_F_RI:
|
||||
case Lanai::SFSUB_F_RR:
|
||||
case Lanai::SA_F_I:
|
||||
case Lanai::SL_F_I:
|
||||
case Lanai::SHL_F_R:
|
||||
case Lanai::SRA_F_R:
|
||||
case Lanai::SRL_F_R:
|
||||
case Lanai::SUBB_F_I_HI:
|
||||
case Lanai::SUBB_F_I_LO:
|
||||
case Lanai::SUBB_F_R:
|
||||
case Lanai::SUBB_F_R_CC:
|
||||
case Lanai::SUB_F_I_HI:
|
||||
case Lanai::SUB_F_I_LO:
|
||||
case Lanai::SUB_F_R:
|
||||
case Lanai::SUB_F_R_CC:
|
||||
case Lanai::XOR_F_I_HI:
|
||||
case Lanai::XOR_F_I_LO:
|
||||
case Lanai::XOR_F_R:
|
||||
case Lanai::XOR_F_R_CC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the Conditional Code operand for a given instruction kind. For
|
||||
// example, operand at index 1 of a BRIND_CC instruction is the conditional code
|
||||
// (eq, ne, etc.). Returns -1 if the instruction does not have a conditional
|
||||
// code.
|
||||
static int getCCOperandPosition(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Lanai::BRIND_CC:
|
||||
case Lanai::BRIND_CCA:
|
||||
case Lanai::BRR:
|
||||
case Lanai::BRCC:
|
||||
case Lanai::SCC:
|
||||
return 1;
|
||||
case Lanai::SELECT:
|
||||
case Lanai::ADDC_F_R_CC:
|
||||
case Lanai::ADDC_R_CC:
|
||||
case Lanai::ADD_F_R_CC:
|
||||
case Lanai::ADD_R_CC:
|
||||
case Lanai::AND_F_R_CC:
|
||||
case Lanai::AND_R_CC:
|
||||
case Lanai::OR_F_R_CC:
|
||||
case Lanai::OR_R_CC:
|
||||
case Lanai::SUBB_F_R_CC:
|
||||
case Lanai::SUBB_R_CC:
|
||||
case Lanai::SUB_F_R_CC:
|
||||
case Lanai::SUB_R_CC:
|
||||
case Lanai::XOR_F_R_CC:
|
||||
case Lanai::XOR_R_CC:
|
||||
return 3;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if instruction is a lowered SET_FLAG instruction with 0/R0 as
|
||||
// the first operand and whose conditional code is such that it can be merged
|
||||
// (i.e., EQ, NE, PL and MI).
|
||||
static bool isSuitableSetflag(MbbIterator Instruction, MbbIterator End) {
|
||||
unsigned Opcode = Instruction->getOpcode();
|
||||
if (Opcode == Lanai::SFSUB_F_RI || Opcode == Lanai::SFSUB_F_RR) {
|
||||
const MachineOperand &Operand = Instruction->getOperand(1);
|
||||
if (Operand.isReg() && Operand.getReg() != Lanai::R0)
|
||||
return false;
|
||||
if (Operand.isImm() && Operand.getImm() != 0)
|
||||
return false;
|
||||
|
||||
MbbIterator SCCUserIter = Instruction;
|
||||
while (SCCUserIter != End) {
|
||||
++SCCUserIter;
|
||||
// Early exit when encountering flag setting instruction.
|
||||
if (isFlagSettingInstruction(SCCUserIter->getOpcode()))
|
||||
break;
|
||||
int CCIndex = getCCOperandPosition(SCCUserIter->getOpcode());
|
||||
if (CCIndex != -1) {
|
||||
LPCC::CondCode CC = static_cast<LPCC::CondCode>(
|
||||
SCCUserIter->getOperand(CCIndex).getImm());
|
||||
if (CC != LPCC::ICC_EQ && CC != LPCC::ICC_NE && CC != LPCC::ICC_PL &&
|
||||
CC != LPCC::ICC_MI)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Combines a SET_FLAG instruction comparing a register with 0 and an ALU
|
||||
// operation that sets the same register used in the comparison into a single
|
||||
// flag setting ALU instruction (both instructions combined are removed and new
|
||||
// flag setting ALU operation inserted where ALU instruction was).
|
||||
bool LanaiSetflagAluCombiner::CombineSetflagAluInBasicBlock(
|
||||
MachineFunction *MF, MachineBasicBlock *BB) {
|
||||
bool Modified = false;
|
||||
const TargetInstrInfo *TII =
|
||||
MF->getSubtarget<LanaiSubtarget>().getInstrInfo();
|
||||
|
||||
MbbIterator SetflagIter = BB->begin();
|
||||
MbbIterator End = BB->end();
|
||||
MbbIterator Begin = BB->begin();
|
||||
while (SetflagIter != End) {
|
||||
bool Replaced = false;
|
||||
if (isSuitableSetflag(SetflagIter, End)) {
|
||||
MbbIterator AluIter = SetflagIter;
|
||||
while (AluIter != Begin) {
|
||||
--AluIter;
|
||||
// Skip debug instructions. Debug instructions don't affect codegen.
|
||||
if (AluIter->isDebugValue()) {
|
||||
continue;
|
||||
}
|
||||
// Early exit when encountering flag setting instruction.
|
||||
if (isFlagSettingInstruction(AluIter->getOpcode())) {
|
||||
break;
|
||||
}
|
||||
// Check that output of AluIter is equal to input of SetflagIter.
|
||||
if (AluIter->getNumOperands() > 1 && AluIter->getOperand(0).isReg() &&
|
||||
(AluIter->getOperand(0).getReg() ==
|
||||
SetflagIter->getOperand(0).getReg())) {
|
||||
unsigned NewOpc = flagSettingOpcodeVariant(AluIter->getOpcode());
|
||||
if (NewOpc == kInvalid)
|
||||
break;
|
||||
|
||||
// Change the ALU instruction to the flag setting variant.
|
||||
AluIter->setDesc(TII->get(NewOpc));
|
||||
AluIter->addImplicitDefUseOperands(*MF);
|
||||
|
||||
Replaced = true;
|
||||
++NumSetflagAluCombined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Erase the setflag instruction if merged.
|
||||
if (Replaced) {
|
||||
BB->erase(SetflagIter++);
|
||||
}
|
||||
}
|
||||
|
||||
Modified |= Replaced;
|
||||
if (SetflagIter == End)
|
||||
break;
|
||||
if (!Replaced)
|
||||
++SetflagIter;
|
||||
}
|
||||
|
||||
return Modified;
|
||||
}
|
||||
|
||||
// Driver function that iterates over the machine basic building blocks of a
|
||||
// machine function
|
||||
bool LanaiSetflagAluCombiner::runOnMachineFunction(MachineFunction &MF) {
|
||||
if (DisableSetflagAluCombiner)
|
||||
return false;
|
||||
|
||||
bool Modified = false;
|
||||
MfIterator End = MF.end();
|
||||
for (MfIterator MFI = MF.begin(); MFI != End; ++MFI) {
|
||||
Modified |= CombineSetflagAluInBasicBlock(&MF, &*MFI);
|
||||
}
|
||||
return Modified;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
FunctionPass *llvm::createLanaiSetflagAluCombinerPass() {
|
||||
return new LanaiSetflagAluCombiner();
|
||||
}
|
48
lib/Target/Lanai/LanaiSubtarget.cpp
Normal file
48
lib/Target/Lanai/LanaiSubtarget.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
//===- LanaiSubtarget.cpp - Lanai Subtarget 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 implements the Lanai specific subclass of TargetSubtarget.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiSubtarget.h"
|
||||
|
||||
#include "Lanai.h"
|
||||
|
||||
#define DEBUG_TYPE "lanai-subtarget"
|
||||
|
||||
#define GET_SUBTARGETINFO_TARGET_DESC
|
||||
#define GET_SUBTARGETINFO_CTOR
|
||||
#include "LanaiGenSubtargetInfo.inc"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void LanaiSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
|
||||
std::string CPUName = CPU;
|
||||
if (CPUName.empty())
|
||||
CPUName = "generic";
|
||||
|
||||
ParseSubtargetFeatures(CPUName, FS);
|
||||
}
|
||||
|
||||
LanaiSubtarget &LanaiSubtarget::initializeSubtargetDependencies(StringRef CPU,
|
||||
StringRef FS) {
|
||||
initSubtargetFeatures(CPU, FS);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LanaiSubtarget::LanaiSubtarget(const Triple &TargetTriple, StringRef Cpu,
|
||||
StringRef FeatureString, const TargetMachine &TM,
|
||||
const TargetOptions &Options,
|
||||
Reloc::Model RelocationModel,
|
||||
CodeModel::Model CodeModel,
|
||||
CodeGenOpt::Level OptLevel)
|
||||
: LanaiGenSubtargetInfo(TargetTriple, Cpu, FeatureString),
|
||||
FrameLowering(initializeSubtargetDependencies(Cpu, FeatureString)),
|
||||
InstrInfo(), TLInfo(TM, *this), TSInfo() {}
|
76
lib/Target/Lanai/LanaiSubtarget.h
Normal file
76
lib/Target/Lanai/LanaiSubtarget.h
Normal file
@ -0,0 +1,76 @@
|
||||
//=====-- LanaiSubtarget.h - Define Subtarget for the Lanai -----*- 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 Lanai specific subclass of TargetSubtarget.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAISUBTARGET_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAISUBTARGET_H
|
||||
|
||||
#include "LanaiFrameLowering.h"
|
||||
#include "LanaiISelLowering.h"
|
||||
#include "LanaiInstrInfo.h"
|
||||
#include "LanaiSelectionDAGInfo.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetSubtargetInfo.h"
|
||||
|
||||
#define GET_SUBTARGETINFO_HEADER
|
||||
#include "LanaiGenSubtargetInfo.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LanaiSubtarget : public LanaiGenSubtargetInfo {
|
||||
public:
|
||||
// This constructor initializes the data members to match that
|
||||
// of the specified triple.
|
||||
LanaiSubtarget(const Triple &TargetTriple, StringRef Cpu,
|
||||
StringRef FeatureString, const TargetMachine &TM,
|
||||
const TargetOptions &Options, Reloc::Model RelocationModel,
|
||||
CodeModel::Model CodeModel, CodeGenOpt::Level OptLevel);
|
||||
|
||||
// ParseSubtargetFeatures - Parses features string setting specified
|
||||
// subtarget options. Definition of function is auto generated by tblgen.
|
||||
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
|
||||
|
||||
LanaiSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
|
||||
|
||||
void initSubtargetFeatures(StringRef CPU, StringRef FS);
|
||||
|
||||
bool enableMachineScheduler() const override { return true; }
|
||||
|
||||
const LanaiInstrInfo *getInstrInfo() const override { return &InstrInfo; }
|
||||
|
||||
const TargetFrameLowering *getFrameLowering() const override {
|
||||
return &FrameLowering;
|
||||
}
|
||||
|
||||
const LanaiRegisterInfo *getRegisterInfo() const override {
|
||||
return &InstrInfo.getRegisterInfo();
|
||||
}
|
||||
|
||||
const LanaiTargetLowering *getTargetLowering() const override {
|
||||
return &TLInfo;
|
||||
}
|
||||
|
||||
const LanaiSelectionDAGInfo *getSelectionDAGInfo() const override {
|
||||
return &TSInfo;
|
||||
}
|
||||
|
||||
private:
|
||||
LanaiFrameLowering FrameLowering;
|
||||
LanaiInstrInfo InstrInfo;
|
||||
LanaiTargetLowering TLInfo;
|
||||
LanaiSelectionDAGInfo TSInfo;
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAISUBTARGET_H
|
110
lib/Target/Lanai/LanaiTargetMachine.cpp
Normal file
110
lib/Target/Lanai/LanaiTargetMachine.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
//===-- LanaiTargetMachine.cpp - Define TargetMachine for Lanai ---------===//
|
||||
//
|
||||
// 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 Lanai target spec.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiTargetMachine.h"
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiTargetObjectFile.h"
|
||||
#include "LanaiTargetTransformInfo.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
void initializeLanaiMemAluCombinerPass(PassRegistry &);
|
||||
void initializeLanaiSetflagAluCombinerPass(PassRegistry &);
|
||||
} // namespace llvm
|
||||
|
||||
extern "C" void LLVMInitializeLanaiTarget() {
|
||||
// Register the target.
|
||||
RegisterTargetMachine<LanaiTargetMachine> registered_target(TheLanaiTarget);
|
||||
}
|
||||
|
||||
static std::string computeDataLayout(const Triple &TT) {
|
||||
// Data layout (keep in sync with clang/lib/Basic/Targets.cpp)
|
||||
return "E" // Big endian
|
||||
"-m:e" // ELF name manging
|
||||
"-p:32:32" // 32-bit pointers, 32 bit aligned
|
||||
"-i64:64" // 64 bit integers, 64 bit aligned
|
||||
"-a:0:32" // 32 bit alignment of objects of aggregate type
|
||||
"-n32" // 32 bit native integer width
|
||||
"-S64"; // 64 bit natural stack alignment
|
||||
}
|
||||
|
||||
LanaiTargetMachine::LanaiTargetMachine(const Target &TheTarget,
|
||||
const Triple &TargetTriple,
|
||||
StringRef Cpu, StringRef FeatureString,
|
||||
const TargetOptions &Options,
|
||||
Reloc::Model RelocationModel,
|
||||
CodeModel::Model CodeModel,
|
||||
CodeGenOpt::Level OptLevel)
|
||||
: LLVMTargetMachine(TheTarget, computeDataLayout(TargetTriple),
|
||||
TargetTriple, Cpu, FeatureString, Options,
|
||||
RelocationModel, CodeModel, OptLevel),
|
||||
Subtarget(TargetTriple, Cpu, FeatureString, *this, Options,
|
||||
RelocationModel, CodeModel, OptLevel),
|
||||
TLOF(new LanaiTargetObjectFile()) {
|
||||
initAsmInfo();
|
||||
}
|
||||
|
||||
TargetIRAnalysis LanaiTargetMachine::getTargetIRAnalysis() {
|
||||
return TargetIRAnalysis([this](const Function &F) {
|
||||
return TargetTransformInfo(LanaiTTIImpl(this, F));
|
||||
});
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Lanai Code Generator Pass Configuration Options.
|
||||
class LanaiPassConfig : public TargetPassConfig {
|
||||
public:
|
||||
LanaiPassConfig(LanaiTargetMachine *TM, PassManagerBase *PassManager)
|
||||
: TargetPassConfig(TM, *PassManager) {}
|
||||
|
||||
LanaiTargetMachine &getLanaiTargetMachine() const {
|
||||
return getTM<LanaiTargetMachine>();
|
||||
}
|
||||
|
||||
bool addInstSelector() override;
|
||||
void addPreSched2() override;
|
||||
void addPreEmitPass() override;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TargetPassConfig *
|
||||
LanaiTargetMachine::createPassConfig(PassManagerBase &PassManager) {
|
||||
return new LanaiPassConfig(this, &PassManager);
|
||||
}
|
||||
|
||||
// Install an instruction selector pass.
|
||||
bool LanaiPassConfig::addInstSelector() {
|
||||
addPass(createLanaiISelDag(getLanaiTargetMachine()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implemented by targets that want to run passes immediately before
|
||||
// machine code is emitted.
|
||||
void LanaiPassConfig::addPreEmitPass() {
|
||||
addPass(createLanaiDelaySlotFillerPass(getLanaiTargetMachine()));
|
||||
}
|
||||
|
||||
// Run passes after prolog-epilog insertion and before the second instruction
|
||||
// scheduling pass.
|
||||
void LanaiPassConfig::addPreSched2() {
|
||||
addPass(createLanaiMemAluCombinerPass());
|
||||
addPass(createLanaiSetflagAluCombinerPass());
|
||||
}
|
54
lib/Target/Lanai/LanaiTargetMachine.h
Normal file
54
lib/Target/Lanai/LanaiTargetMachine.h
Normal file
@ -0,0 +1,54 @@
|
||||
//===-- LanaiTargetMachine.h - Define TargetMachine for Lanai --- 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 Lanai specific subclass of TargetMachine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAITARGETMACHINE_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAITARGETMACHINE_H
|
||||
|
||||
#include "LanaiFrameLowering.h"
|
||||
#include "LanaiISelLowering.h"
|
||||
#include "LanaiInstrInfo.h"
|
||||
#include "LanaiSelectionDAGInfo.h"
|
||||
#include "LanaiSubtarget.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
namespace llvm {
|
||||
class formatted_raw_ostream;
|
||||
|
||||
class LanaiTargetMachine : public LLVMTargetMachine {
|
||||
LanaiSubtarget Subtarget;
|
||||
std::unique_ptr<TargetLoweringObjectFile> TLOF;
|
||||
|
||||
public:
|
||||
LanaiTargetMachine(const Target &TheTarget, const Triple &TargetTriple,
|
||||
StringRef Cpu, StringRef FeatureString,
|
||||
const TargetOptions &Options, Reloc::Model RelocationModel,
|
||||
CodeModel::Model CodeModel, CodeGenOpt::Level OptLevel);
|
||||
|
||||
const LanaiSubtarget *
|
||||
getSubtargetImpl(const llvm::Function &Fn) const override {
|
||||
return &Subtarget;
|
||||
}
|
||||
|
||||
TargetIRAnalysis getTargetIRAnalysis() override;
|
||||
|
||||
// Pass Pipeline Configuration
|
||||
TargetPassConfig *createPassConfig(PassManagerBase &pass_manager) override;
|
||||
|
||||
TargetLoweringObjectFile *getObjFileLowering() const override {
|
||||
return TLOF.get();
|
||||
}
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAITARGETMACHINE_H
|
123
lib/Target/Lanai/LanaiTargetObjectFile.cpp
Normal file
123
lib/Target/Lanai/LanaiTargetObjectFile.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiTargetObjectFile.h"
|
||||
|
||||
#include "LanaiSubtarget.h"
|
||||
#include "LanaiTargetMachine.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<unsigned> SSThreshold(
|
||||
"lanai-ssection-threshold", cl::Hidden,
|
||||
cl::desc("Small data and bss section threshold size (default=0)"),
|
||||
cl::init(0));
|
||||
|
||||
void LanaiTargetObjectFile::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
||||
InitializeELF(TM.Options.UseInitArray);
|
||||
|
||||
SmallDataSection = getContext().getELFSection(
|
||||
".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
|
||||
SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
|
||||
ELF::SHF_WRITE | ELF::SHF_ALLOC);
|
||||
}
|
||||
|
||||
// A address must be loaded from a small section if its size is less than the
|
||||
// small section size threshold. Data in this section must be addressed using
|
||||
// gp_rel operator.
|
||||
static bool isInSmallSection(uint64_t Size) {
|
||||
// gcc has traditionally not treated zero-sized objects as small data, so this
|
||||
// is effectively part of the ABI.
|
||||
return Size > 0 && Size <= SSThreshold;
|
||||
}
|
||||
|
||||
// Return true if this global address should be placed into small data/bss
|
||||
// section.
|
||||
bool LanaiTargetObjectFile::isGlobalInSmallSection(
|
||||
const GlobalValue *GV, const TargetMachine &TM) const {
|
||||
// We first check the case where global is a declaration, because finding
|
||||
// section kind using getKindForGlobal() is only allowed for global
|
||||
// definitions.
|
||||
if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage())
|
||||
return isGlobalInSmallSectionImpl(GV, TM);
|
||||
|
||||
return isGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM));
|
||||
}
|
||||
|
||||
// Return true if this global address should be placed into small data/bss
|
||||
// section.
|
||||
bool LanaiTargetObjectFile::isGlobalInSmallSection(const GlobalValue *GV,
|
||||
const TargetMachine &TM,
|
||||
SectionKind Kind) const {
|
||||
return (isGlobalInSmallSectionImpl(GV, TM) &&
|
||||
(Kind.isData() || Kind.isBSS() || Kind.isCommon()));
|
||||
}
|
||||
|
||||
// Return true if this global address should be placed into small data/bss
|
||||
// section. This method does all the work, except for checking the section
|
||||
// kind.
|
||||
bool LanaiTargetObjectFile::isGlobalInSmallSectionImpl(
|
||||
const GlobalValue *GV, const TargetMachine &TM) const {
|
||||
// Only global variables, not functions.
|
||||
const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV);
|
||||
if (!GVA)
|
||||
return false;
|
||||
|
||||
if (GV->hasLocalLinkage())
|
||||
return false;
|
||||
|
||||
if (((GV->hasExternalLinkage() && GV->isDeclaration()) ||
|
||||
GV->hasCommonLinkage()))
|
||||
return false;
|
||||
|
||||
Type *Ty = GV->getType()->getElementType();
|
||||
return isInSmallSection(
|
||||
GV->getParent()->getDataLayout().getTypeAllocSize(Ty));
|
||||
}
|
||||
|
||||
MCSection *
|
||||
LanaiTargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV,
|
||||
SectionKind Kind, Mangler &Mang,
|
||||
const TargetMachine &TM) const {
|
||||
// Handle Small Section classification here.
|
||||
if (Kind.isBSS() && isGlobalInSmallSection(GV, TM, Kind))
|
||||
return SmallBSSSection;
|
||||
if (Kind.isData() && isGlobalInSmallSection(GV, TM, Kind))
|
||||
return SmallDataSection;
|
||||
|
||||
// Otherwise, we work the same as ELF.
|
||||
return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,
|
||||
TM);
|
||||
}
|
||||
|
||||
/// Return true if this constant should be placed into small data section.
|
||||
bool LanaiTargetObjectFile::isConstantInSmallSection(
|
||||
const DataLayout &DL, const Constant *CN) const {
|
||||
return isInSmallSection(DL.getTypeAllocSize(CN->getType()));
|
||||
}
|
||||
|
||||
MCSection *LanaiTargetObjectFile::getSectionForConstant(const DataLayout &DL,
|
||||
SectionKind Kind,
|
||||
const Constant *C,
|
||||
unsigned &Align) const {
|
||||
if (isConstantInSmallSection(DL, C))
|
||||
return SmallDataSection;
|
||||
|
||||
// Otherwise, we work the same as ELF.
|
||||
return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align);
|
||||
}
|
46
lib/Target/Lanai/LanaiTargetObjectFile.h
Normal file
46
lib/Target/Lanai/LanaiTargetObjectFile.h
Normal file
@ -0,0 +1,46 @@
|
||||
//===-- LanaiTargetObjectFile.h - Lanai Object Info -----------------------===//
|
||||
//
|
||||
// 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_LANAI_LANAITARGETOBJECTFILE_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAITARGETOBJECTFILE_H
|
||||
|
||||
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
||||
|
||||
namespace llvm {
|
||||
class LanaiTargetMachine;
|
||||
class LanaiTargetObjectFile : public TargetLoweringObjectFileELF {
|
||||
MCSection *SmallDataSection;
|
||||
MCSection *SmallBSSSection;
|
||||
|
||||
public:
|
||||
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
|
||||
|
||||
/// Return true if this global address should be placed into small data/bss
|
||||
/// section.
|
||||
bool isGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM,
|
||||
SectionKind Kind) const;
|
||||
bool isGlobalInSmallSection(const GlobalValue *GV,
|
||||
const TargetMachine &TM) const;
|
||||
bool isGlobalInSmallSectionImpl(const GlobalValue *GV,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
||||
Mangler &Mang,
|
||||
const TargetMachine &TM) const override;
|
||||
|
||||
/// Return true if this constant should be placed into small data section.
|
||||
bool isConstantInSmallSection(const DataLayout &DL, const Constant *CN) const;
|
||||
|
||||
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
|
||||
const Constant *C,
|
||||
unsigned &Align) const override;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAITARGETOBJECTFILE_H
|
87
lib/Target/Lanai/LanaiTargetTransformInfo.h
Normal file
87
lib/Target/Lanai/LanaiTargetTransformInfo.h
Normal file
@ -0,0 +1,87 @@
|
||||
//===-- LanaiTargetTransformInfo.h - Lanai specific TTI ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file a TargetTransformInfo::Concept conforming object specific to the
|
||||
// Lanai target machine. It uses the target's detailed information to
|
||||
// provide more precise answers to certain TTI queries, while letting the
|
||||
// target independent and default TTI implementations handle the rest.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_LANAITARGETTRANSFORMINFO_H
|
||||
#define LLVM_LIB_TARGET_LANAI_LANAITARGETTRANSFORMINFO_H
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "LanaiSubtarget.h"
|
||||
#include "LanaiTargetMachine.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
#include "llvm/CodeGen/BasicTTIImpl.h"
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
class LanaiTTIImpl : public BasicTTIImplBase<LanaiTTIImpl> {
|
||||
typedef BasicTTIImplBase<LanaiTTIImpl> BaseT;
|
||||
typedef TargetTransformInfo TTI;
|
||||
friend BaseT;
|
||||
|
||||
const LanaiSubtarget *ST;
|
||||
const LanaiTargetLowering *TLI;
|
||||
|
||||
const LanaiSubtarget *getST() const { return ST; }
|
||||
const LanaiTargetLowering *getTLI() const { return TLI; }
|
||||
|
||||
public:
|
||||
explicit LanaiTTIImpl(const LanaiTargetMachine *TM, const Function &F)
|
||||
: BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)),
|
||||
TLI(ST->getTargetLowering()) {}
|
||||
|
||||
LanaiTTIImpl(const LanaiTTIImpl &Arg)
|
||||
: BaseT(static_cast<const BaseT &>(Arg)), ST(Arg.ST), TLI(Arg.TLI) {}
|
||||
LanaiTTIImpl(LanaiTTIImpl &&Arg)
|
||||
: BaseT(std::move(static_cast<BaseT &>(Arg))), ST(std::move(Arg.ST)),
|
||||
TLI(std::move(Arg.TLI)) {}
|
||||
|
||||
bool shouldBuildLookupTables() const { return false; }
|
||||
|
||||
TargetTransformInfo::PopcntSupportKind getPopcntSupport(unsigned TyWidth) {
|
||||
if (TyWidth == 32)
|
||||
return TTI::PSK_FastHardware;
|
||||
return TTI::PSK_Software;
|
||||
}
|
||||
|
||||
unsigned getArithmeticInstrCost(
|
||||
unsigned Opcode, Type *Ty,
|
||||
TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue,
|
||||
TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue,
|
||||
TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None,
|
||||
TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None) {
|
||||
int ISD = TLI->InstructionOpcodeToISD(Opcode);
|
||||
|
||||
switch (ISD) {
|
||||
default:
|
||||
return BaseT::getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info,
|
||||
Opd1PropInfo, Opd2PropInfo);
|
||||
case ISD::MUL:
|
||||
case ISD::SDIV:
|
||||
case ISD::UDIV:
|
||||
case ISD::UREM:
|
||||
// This increases the cost associated with multiplication and division
|
||||
// to 64 times what the baseline arithmetic cost is. The arithmetic
|
||||
// instruction cost was arbitrarily chosen to reduce the desirability
|
||||
// of emitting arithmetic instructions that are emulated in software.
|
||||
// TODO: Investigate the performance impact given specialized lowerings.
|
||||
return 64 * BaseT::getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info,
|
||||
Opd1PropInfo, Opd2PropInfo);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_LANAITARGETTRANSFORMINFO_H
|
8
lib/Target/Lanai/MCTargetDesc/CMakeLists.txt
Normal file
8
lib/Target/Lanai/MCTargetDesc/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
add_llvm_library(LLVMLanaiMCTargetDesc
|
||||
LanaiAsmBackend.cpp
|
||||
LanaiELFObjectWriter.cpp
|
||||
LanaiMCAsmInfo.cpp
|
||||
LanaiMCCodeEmitter.cpp
|
||||
LanaiMCExpr.cpp
|
||||
LanaiMCTargetDesc.cpp
|
||||
)
|
23
lib/Target/Lanai/MCTargetDesc/LLVMBuild.txt
Normal file
23
lib/Target/Lanai/MCTargetDesc/LLVMBuild.txt
Normal file
@ -0,0 +1,23 @@
|
||||
;===-- ./lib/Target/Lanai/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 = LanaiMCTargetDesc
|
||||
parent = Lanai
|
||||
required_libraries = LanaiInfo LanaiInstPrinter MC Support
|
||||
add_to_library_groups = Lanai
|
168
lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp
Normal file
168
lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
//===-- LanaiAsmBackend.cpp - Lanai Assembler Backend ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiFixupKinds.h"
|
||||
#include "MCTargetDesc/LanaiMCTargetDesc.h"
|
||||
#include "llvm/MC/MCAsmBackend.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCFixupKindInfo.h"
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// Prepare value for the target space
|
||||
static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
|
||||
switch (Kind) {
|
||||
case FK_Data_1:
|
||||
case FK_Data_2:
|
||||
case FK_Data_4:
|
||||
case FK_Data_8:
|
||||
return Value;
|
||||
case Lanai::FIXUP_LANAI_21:
|
||||
case Lanai::FIXUP_LANAI_21_F:
|
||||
case Lanai::FIXUP_LANAI_25:
|
||||
case Lanai::FIXUP_LANAI_32:
|
||||
case Lanai::FIXUP_LANAI_HI16:
|
||||
case Lanai::FIXUP_LANAI_LO16:
|
||||
return Value;
|
||||
default:
|
||||
llvm_unreachable("Unknown fixup kind!");
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
class LanaiAsmBackend : public MCAsmBackend {
|
||||
Triple::OSType OSType;
|
||||
|
||||
public:
|
||||
LanaiAsmBackend(const Target &T, Triple::OSType OST)
|
||||
: MCAsmBackend(), OSType(OST) {}
|
||||
|
||||
void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
|
||||
uint64_t Value, bool IsPCRel) const override;
|
||||
|
||||
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
|
||||
|
||||
// No instruction requires relaxation
|
||||
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
|
||||
const MCRelaxableFragment *DF,
|
||||
const MCAsmLayout &Layout) const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
|
||||
|
||||
unsigned getNumFixupKinds() const override {
|
||||
return Lanai::NumTargetFixupKinds;
|
||||
}
|
||||
|
||||
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
|
||||
|
||||
void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
|
||||
|
||||
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
|
||||
};
|
||||
|
||||
bool LanaiAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
|
||||
if ((Count % 4) != 0)
|
||||
return false;
|
||||
|
||||
for (uint64_t i = 0; i < Count; i += 4)
|
||||
OW->write32(0x15000000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LanaiAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
|
||||
unsigned DataSize, uint64_t Value,
|
||||
bool IsPCRel) const {
|
||||
MCFixupKind Kind = Fixup.getKind();
|
||||
Value = adjustFixupValue(static_cast<unsigned>(Kind), Value);
|
||||
|
||||
if (!Value)
|
||||
return; // This value doesn't change the encoding
|
||||
|
||||
// Where in the object and where the number of bytes that need
|
||||
// fixing up
|
||||
unsigned Offset = Fixup.getOffset();
|
||||
unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
|
||||
unsigned FullSize = 4;
|
||||
|
||||
// Grab current value, if any, from bits.
|
||||
uint64_t CurVal = 0;
|
||||
|
||||
// Load instruction and apply value
|
||||
for (unsigned i = 0; i != NumBytes; ++i) {
|
||||
unsigned Idx = (FullSize - 1 - i);
|
||||
CurVal |= static_cast<uint64_t>(static_cast<uint8_t>(Data[Offset + Idx]))
|
||||
<< (i * 8);
|
||||
}
|
||||
|
||||
uint64_t Mask =
|
||||
(static_cast<uint64_t>(-1) >> (64 - getFixupKindInfo(Kind).TargetSize));
|
||||
CurVal |= Value & Mask;
|
||||
|
||||
// Write out the fixed up bytes back to the code/data bits.
|
||||
for (unsigned i = 0; i != NumBytes; ++i) {
|
||||
unsigned Idx = (FullSize - 1 - i);
|
||||
Data[Offset + Idx] = static_cast<uint8_t>((CurVal >> (i * 8)) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
MCObjectWriter *
|
||||
LanaiAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
|
||||
return createLanaiELFObjectWriter(OS,
|
||||
MCELFObjectTargetWriter::getOSABI(OSType));
|
||||
}
|
||||
|
||||
const MCFixupKindInfo &
|
||||
LanaiAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
|
||||
static const MCFixupKindInfo Infos[Lanai::NumTargetFixupKinds] = {
|
||||
// This table *must* be in same the order of fixup_* kinds in
|
||||
// LanaiFixupKinds.h.
|
||||
// Note: The number of bits indicated here are assumed to be contiguous.
|
||||
// This does not hold true for LANAI_21 and LANAI_21_F which are applied
|
||||
// to bits 0x7cffff and 0x7cfffc, respectively. Since the 'bits' counts
|
||||
// here are used only for cosmetic purposes, we set the size to 16 bits
|
||||
// for these 21-bit relocation as llvm/lib/MC/MCAsmStreamer.cpp checks
|
||||
// no bits are set in the fixup range.
|
||||
//
|
||||
// name offset bits flags
|
||||
{"FIXUP_LANAI_NONE", 0, 32, 0},
|
||||
{"FIXUP_LANAI_21", 16, 16 /*21*/, 0},
|
||||
{"FIXUP_LANAI_21_F", 16, 16 /*21*/, 0},
|
||||
{"FIXUP_LANAI_25", 7, 25, 0},
|
||||
{"FIXUP_LANAI_32", 0, 32, 0},
|
||||
{"FIXUP_LANAI_HI16", 16, 16, 0},
|
||||
{"FIXUP_LANAI_LO16", 16, 16, 0}};
|
||||
|
||||
if (Kind < FirstTargetFixupKind)
|
||||
return MCAsmBackend::getFixupKindInfo(Kind);
|
||||
|
||||
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
|
||||
"Invalid kind!");
|
||||
return Infos[Kind - FirstTargetFixupKind];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MCAsmBackend *llvm::createLanaiAsmBackend(const Target &T,
|
||||
const MCRegisterInfo &MRI,
|
||||
const Triple &TheTriple,
|
||||
StringRef CPU) {
|
||||
if (!TheTriple.isOSBinFormatELF())
|
||||
llvm_unreachable("OS not supported");
|
||||
|
||||
return new LanaiAsmBackend(T, TheTriple.getOS());
|
||||
}
|
145
lib/Target/Lanai/MCTargetDesc/LanaiBaseInfo.h
Normal file
145
lib/Target/Lanai/MCTargetDesc/LanaiBaseInfo.h
Normal file
@ -0,0 +1,145 @@
|
||||
//===-- LanaiBaseInfo.h - Top level definitions for Lanai MC ----*- 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 small standalone helper functions and enum definitions for
|
||||
// the Lanai target useful for the compiler back-end and the MC libraries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIBASEINFO_H
|
||||
#define LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIBASEINFO_H
|
||||
|
||||
#include "LanaiMCTargetDesc.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// LanaiII - This namespace holds all of the target specific flags that
|
||||
// instruction info tracks.
|
||||
//
|
||||
namespace LanaiII {
|
||||
// Target Operand Flag enum.
|
||||
enum TOF {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Lanai Specific MachineOperand flags.
|
||||
MO_NO_FLAG,
|
||||
|
||||
// MO_ABS_HI/LO - Represents the hi or low part of an absolute symbol
|
||||
// address.
|
||||
MO_ABS_HI,
|
||||
MO_ABS_LO,
|
||||
|
||||
// MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the
|
||||
// immediate should get the value of the symbol minus the PIC base label:
|
||||
// SYMBOL_LABEL - PICBASELABEL
|
||||
MO_PIC_BASE_OFFSET,
|
||||
|
||||
// MO_GOT - On a symbol operand this indicates that the immediate is the
|
||||
// offset to the GOT entry for the symbol name from the base of the GOT.
|
||||
MO_GOT,
|
||||
|
||||
// MO_GOTOFFHI/MO_GOTOFFLO - On a symbol operand this indicates that the
|
||||
// immediate is the offset to the location of the symbol name from the
|
||||
// base of the GOT.
|
||||
MO_GOTOFFHI,
|
||||
MO_GOTOFFLO,
|
||||
|
||||
// MO_GOTPCHI/MO_GOTPCLO - On a symbol operand this indicates that
|
||||
// the immediate is an offset to the GOT entry for the symbol name
|
||||
// from the current code location.
|
||||
MO_GOTPCHI,
|
||||
MO_GOTPCLO,
|
||||
|
||||
// MO_PLT - On a symbol operand this indicates that the immediate is
|
||||
// offset to the PLT entry of symbol name from the current code location.
|
||||
MO_PLT
|
||||
};
|
||||
} // namespace LanaiII
|
||||
|
||||
static inline unsigned getLanaiRegisterNumbering(unsigned Reg) {
|
||||
switch (Reg) {
|
||||
case Lanai::R0:
|
||||
return 0;
|
||||
case Lanai::R1:
|
||||
return 1;
|
||||
case Lanai::R2:
|
||||
case Lanai::PC:
|
||||
return 2;
|
||||
case Lanai::R3:
|
||||
return 3;
|
||||
case Lanai::R4:
|
||||
case Lanai::SP:
|
||||
return 4;
|
||||
case Lanai::R5:
|
||||
case Lanai::FP:
|
||||
return 5;
|
||||
case Lanai::R6:
|
||||
return 6;
|
||||
case Lanai::R7:
|
||||
return 7;
|
||||
case Lanai::R8:
|
||||
case Lanai::RV:
|
||||
return 8;
|
||||
case Lanai::R9:
|
||||
return 9;
|
||||
case Lanai::R10:
|
||||
case Lanai::RR1:
|
||||
return 10;
|
||||
case Lanai::R11:
|
||||
case Lanai::RR2:
|
||||
return 11;
|
||||
case Lanai::R12:
|
||||
return 12;
|
||||
case Lanai::R13:
|
||||
return 13;
|
||||
case Lanai::R14:
|
||||
return 14;
|
||||
case Lanai::R15:
|
||||
case Lanai::RCA:
|
||||
return 15;
|
||||
case Lanai::R16:
|
||||
return 16;
|
||||
case Lanai::R17:
|
||||
return 17;
|
||||
case Lanai::R18:
|
||||
return 18;
|
||||
case Lanai::R19:
|
||||
return 19;
|
||||
case Lanai::R20:
|
||||
return 20;
|
||||
case Lanai::R21:
|
||||
return 21;
|
||||
case Lanai::R22:
|
||||
return 22;
|
||||
case Lanai::R23:
|
||||
return 23;
|
||||
case Lanai::R24:
|
||||
return 24;
|
||||
case Lanai::R25:
|
||||
return 25;
|
||||
case Lanai::R26:
|
||||
return 26;
|
||||
case Lanai::R27:
|
||||
return 27;
|
||||
case Lanai::R28:
|
||||
return 28;
|
||||
case Lanai::R29:
|
||||
return 29;
|
||||
case Lanai::R30:
|
||||
return 30;
|
||||
case Lanai::R31:
|
||||
return 31;
|
||||
default:
|
||||
llvm_unreachable("Unknown register number!");
|
||||
}
|
||||
}
|
||||
} // namespace llvm
|
||||
#endif // LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIBASEINFO_H
|
95
lib/Target/Lanai/MCTargetDesc/LanaiELFObjectWriter.cpp
Normal file
95
lib/Target/Lanai/MCTargetDesc/LanaiELFObjectWriter.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
//===-- LanaiELFObjectWriter.cpp - Lanai ELF Writer -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MCTargetDesc/LanaiBaseInfo.h"
|
||||
#include "MCTargetDesc/LanaiFixupKinds.h"
|
||||
#include "MCTargetDesc/LanaiMCTargetDesc.h"
|
||||
#include "llvm/MC/MCELFObjectWriter.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
class LanaiELFObjectWriter : public MCELFObjectTargetWriter {
|
||||
public:
|
||||
explicit LanaiELFObjectWriter(uint8_t OSABI);
|
||||
|
||||
~LanaiELFObjectWriter() override;
|
||||
|
||||
protected:
|
||||
unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
|
||||
const MCFixup &Fixup, bool IsPCRel) const override;
|
||||
bool needsRelocateWithSymbol(const MCSymbol &SD,
|
||||
unsigned Type) const override;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
LanaiELFObjectWriter::LanaiELFObjectWriter(uint8_t OSABI)
|
||||
: MCELFObjectTargetWriter(/*Is64Bit=*/false, OSABI, ELF::EM_LANAI,
|
||||
/*HasRelocationAddend=*/true) {}
|
||||
|
||||
LanaiELFObjectWriter::~LanaiELFObjectWriter() {}
|
||||
|
||||
unsigned LanaiELFObjectWriter::getRelocType(MCContext &Ctx,
|
||||
const MCValue &Target,
|
||||
const MCFixup &Fixup,
|
||||
bool IsPCRel) const {
|
||||
unsigned Type;
|
||||
unsigned Kind = static_cast<unsigned>(Fixup.getKind());
|
||||
switch (Kind) {
|
||||
case Lanai::FIXUP_LANAI_21:
|
||||
Type = ELF::R_LANAI_21;
|
||||
break;
|
||||
case Lanai::FIXUP_LANAI_21_F:
|
||||
Type = ELF::R_LANAI_21_F;
|
||||
break;
|
||||
case Lanai::FIXUP_LANAI_25:
|
||||
Type = ELF::R_LANAI_25;
|
||||
break;
|
||||
case Lanai::FIXUP_LANAI_32:
|
||||
case FK_Data_4:
|
||||
Type = ELF::R_LANAI_32;
|
||||
break;
|
||||
case Lanai::FIXUP_LANAI_HI16:
|
||||
Type = ELF::R_LANAI_HI16;
|
||||
break;
|
||||
case Lanai::FIXUP_LANAI_LO16:
|
||||
Type = ELF::R_LANAI_LO16;
|
||||
break;
|
||||
case Lanai::FIXUP_LANAI_NONE:
|
||||
Type = ELF::R_LANAI_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
llvm_unreachable("Invalid fixup kind!");
|
||||
}
|
||||
return Type;
|
||||
}
|
||||
|
||||
bool LanaiELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &SD,
|
||||
unsigned Type) const {
|
||||
switch (Type) {
|
||||
case ELF::R_LANAI_21:
|
||||
case ELF::R_LANAI_21_F:
|
||||
case ELF::R_LANAI_25:
|
||||
case ELF::R_LANAI_32:
|
||||
case ELF::R_LANAI_HI16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
MCObjectWriter *llvm::createLanaiELFObjectWriter(raw_pwrite_stream &OS,
|
||||
uint8_t OSABI) {
|
||||
MCELFObjectTargetWriter *MOTW = new LanaiELFObjectWriter(OSABI);
|
||||
return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
|
||||
}
|
43
lib/Target/Lanai/MCTargetDesc/LanaiFixupKinds.h
Normal file
43
lib/Target/Lanai/MCTargetDesc/LanaiFixupKinds.h
Normal file
@ -0,0 +1,43 @@
|
||||
//===-- LanaiFixupKinds.h - Lanai 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_LIB_TARGET_LANAI_MCTARGETDESC_LANAIFIXUPKINDS_H
|
||||
#define LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIFIXUPKINDS_H
|
||||
|
||||
#include "llvm/MC/MCFixup.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace Lanai {
|
||||
// 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[Lanai::NumTargetFixupKinds]
|
||||
// in LanaiAsmBackend.cpp.
|
||||
//
|
||||
enum Fixups {
|
||||
// Results in R_Lanai_NONE
|
||||
FIXUP_LANAI_NONE = FirstTargetFixupKind,
|
||||
|
||||
FIXUP_LANAI_21, // 21-bit symbol relocation
|
||||
FIXUP_LANAI_21_F, // 21-bit symbol relocation, last two bits masked to 0
|
||||
FIXUP_LANAI_25, // 25-bit branch targets
|
||||
FIXUP_LANAI_32, // general 32-bit relocation
|
||||
FIXUP_LANAI_HI16, // upper 16-bits of a symbolic relocation
|
||||
FIXUP_LANAI_LO16, // lower 16-bits of a symbolic relocation
|
||||
|
||||
// Marker
|
||||
LastTargetFixupKind,
|
||||
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
|
||||
};
|
||||
} // namespace Lanai
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIFIXUPKINDS_H
|
43
lib/Target/Lanai/MCTargetDesc/LanaiMCAsmInfo.cpp
Normal file
43
lib/Target/Lanai/MCTargetDesc/LanaiMCAsmInfo.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
//===-- LanaiMCAsmInfo.cpp - Lanai 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 LanaiMCAsmInfo properties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiMCAsmInfo.h"
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void LanaiMCAsmInfo::anchor() {}
|
||||
|
||||
LanaiMCAsmInfo::LanaiMCAsmInfo(const Triple &TheTriple) {
|
||||
IsLittleEndian = false;
|
||||
PrivateGlobalPrefix = ".L";
|
||||
WeakRefDirective = "\t.weak\t";
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
|
||||
// Lanai assembly requires ".section" before ".bss"
|
||||
UsesELFSectionDirectiveForBSS = true;
|
||||
|
||||
// Use the integrated assembler instead of system one.
|
||||
UseIntegratedAssembler = true;
|
||||
|
||||
// Use '!' as comment string to correspond with old toolchain.
|
||||
CommentString = "!";
|
||||
|
||||
// Target supports emission of debugging information.
|
||||
SupportsDebugInformation = true;
|
||||
|
||||
// Set the instruction alignment. Currently used only for address adjustment
|
||||
// in dwarf generation.
|
||||
MinInstAlignment = 4;
|
||||
}
|
32
lib/Target/Lanai/MCTargetDesc/LanaiMCAsmInfo.h
Normal file
32
lib/Target/Lanai/MCTargetDesc/LanaiMCAsmInfo.h
Normal file
@ -0,0 +1,32 @@
|
||||
//=====-- LanaiMCAsmInfo.h - Lanai 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 LanaiMCAsmInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCASMINFO_H
|
||||
#define LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCASMINFO_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/MC/MCAsmInfoELF.h"
|
||||
|
||||
namespace llvm {
|
||||
class Triple;
|
||||
|
||||
class LanaiMCAsmInfo : public MCAsmInfoELF {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
explicit LanaiMCAsmInfo(const Triple &TheTriple);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCASMINFO_H
|
325
lib/Target/Lanai/MCTargetDesc/LanaiMCCodeEmitter.cpp
Normal file
325
lib/Target/Lanai/MCTargetDesc/LanaiMCCodeEmitter.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
//===-- LanaiMCCodeEmitter.cpp - Convert Lanai code to machine code -------===//
|
||||
//
|
||||
// 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 LanaiMCCodeEmitter class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "MCTargetDesc/LanaiBaseInfo.h"
|
||||
#include "MCTargetDesc/LanaiFixupKinds.h"
|
||||
#include "MCTargetDesc/LanaiMCExpr.h"
|
||||
#include "MCTargetDesc/LanaiMCTargetDesc.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/MC/MCCodeEmitter.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/MC/MCSymbol.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#define DEBUG_TYPE "mccodeemitter"
|
||||
|
||||
STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
|
||||
|
||||
namespace llvm {
|
||||
namespace {
|
||||
class LanaiMCCodeEmitter : public MCCodeEmitter {
|
||||
LanaiMCCodeEmitter(const LanaiMCCodeEmitter &); // DO NOT IMPLEMENT
|
||||
void operator=(const LanaiMCCodeEmitter &); // DO NOT IMPLEMENT
|
||||
const MCInstrInfo &InstrInfo;
|
||||
MCContext &Context;
|
||||
|
||||
public:
|
||||
LanaiMCCodeEmitter(const MCInstrInfo &MCII, MCContext &C)
|
||||
: InstrInfo(MCII), Context(C) {}
|
||||
|
||||
~LanaiMCCodeEmitter() override {}
|
||||
|
||||
// The functions below are called by TableGen generated functions for getting
|
||||
// the binary encoding of instructions/opereands.
|
||||
|
||||
// getBinaryCodeForInstr - TableGen'erated function for getting the
|
||||
// binary encoding for an instruction.
|
||||
uint64_t getBinaryCodeForInstr(const MCInst &Inst,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const;
|
||||
|
||||
// getMachineOpValue - Return binary encoding of operand. If the machine
|
||||
// operand requires relocation, record the relocation and return zero.
|
||||
unsigned getMachineOpValue(const MCInst &Inst, const MCOperand &MCOp,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const;
|
||||
|
||||
unsigned getRiMemoryOpValue(const MCInst &Inst, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const;
|
||||
|
||||
unsigned getRrMemoryOpValue(const MCInst &Inst, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const;
|
||||
|
||||
unsigned getSplsOpValue(const MCInst &Inst, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const;
|
||||
|
||||
unsigned getBranchTargetOpValue(const MCInst &Inst, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const;
|
||||
|
||||
unsigned getCallTargetOpValue(const MCInst &Inst, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const;
|
||||
|
||||
void encodeInstruction(const MCInst &Inst, raw_ostream &Ostream,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const override;
|
||||
|
||||
unsigned adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
|
||||
unsigned adjustPqBitsSpls(const MCInst &Inst, unsigned Value,
|
||||
const MCSubtargetInfo &STI) const;
|
||||
};
|
||||
|
||||
Lanai::Fixups FixupKind(const MCExpr *Expr) {
|
||||
if (isa<MCSymbolRefExpr>(Expr))
|
||||
return Lanai::FIXUP_LANAI_21;
|
||||
if (const LanaiMCExpr *McExpr = dyn_cast<LanaiMCExpr>(Expr)) {
|
||||
LanaiMCExpr::VariantKind ExprKind = McExpr->getKind();
|
||||
switch (ExprKind) {
|
||||
case LanaiMCExpr::VK_Lanai_None:
|
||||
return Lanai::FIXUP_LANAI_21;
|
||||
case LanaiMCExpr::VK_Lanai_ABS_HI:
|
||||
return Lanai::FIXUP_LANAI_HI16;
|
||||
case LanaiMCExpr::VK_Lanai_ABS_LO:
|
||||
return Lanai::FIXUP_LANAI_LO16;
|
||||
}
|
||||
}
|
||||
return Lanai::Fixups(0);
|
||||
}
|
||||
|
||||
// getMachineOpValue - Return binary encoding of operand. If the machine
|
||||
// operand requires relocation, record the relocation and return zero.
|
||||
unsigned LanaiMCCodeEmitter::getMachineOpValue(
|
||||
const MCInst &Inst, const MCOperand &MCOp, SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const {
|
||||
if (MCOp.isReg())
|
||||
return getLanaiRegisterNumbering(MCOp.getReg());
|
||||
if (MCOp.isImm())
|
||||
return static_cast<unsigned>(MCOp.getImm());
|
||||
|
||||
// MCOp must be an expression
|
||||
assert(MCOp.isExpr());
|
||||
const MCExpr *Expr = MCOp.getExpr();
|
||||
|
||||
// Extract the symbolic reference side of a binary expression.
|
||||
if (Expr->getKind() == MCExpr::Binary) {
|
||||
const MCBinaryExpr *BinaryExpr = static_cast<const MCBinaryExpr *>(Expr);
|
||||
Expr = BinaryExpr->getLHS();
|
||||
}
|
||||
|
||||
assert(isa<LanaiMCExpr>(Expr) || Expr->getKind() == MCExpr::SymbolRef);
|
||||
// Push fixup (all info is contained within)
|
||||
Fixups.push_back(
|
||||
MCFixup::create(0, MCOp.getExpr(), MCFixupKind(FixupKind(Expr))));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Helper function to adjust P and Q bits on load and store instructions.
|
||||
unsigned adjustPqBits(const MCInst &Inst, unsigned Value, unsigned PBitShift,
|
||||
unsigned QBitShift) {
|
||||
const MCOperand AluOp = Inst.getOperand(3);
|
||||
unsigned AluCode = AluOp.getImm();
|
||||
|
||||
// Set the P bit to one iff the immediate is nonzero and not a post-op
|
||||
// instruction.
|
||||
const MCOperand Op2 = Inst.getOperand(2);
|
||||
Value &= ~(1 << PBitShift);
|
||||
if (!LPAC::isPostOp(AluCode) &&
|
||||
((Op2.isImm() && Op2.getImm() != 0) ||
|
||||
(Op2.isReg() && Op2.getReg() != Lanai::R0) || (Op2.isExpr())))
|
||||
Value |= (1 << PBitShift);
|
||||
|
||||
// Set the Q bit to one iff it is a post- or pre-op instruction.
|
||||
assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
|
||||
"Expected register operand.");
|
||||
Value &= ~(1 << QBitShift);
|
||||
if (LPAC::modifiesOp(AluCode) && ((Op2.isImm() && Op2.getImm() != 0) ||
|
||||
(Op2.isReg() && Op2.getReg() != Lanai::R0)))
|
||||
Value |= (1 << QBitShift);
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
unsigned
|
||||
LanaiMCCodeEmitter::adjustPqBitsRmAndRrm(const MCInst &Inst, unsigned Value,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return adjustPqBits(Inst, Value, 17, 16);
|
||||
}
|
||||
|
||||
unsigned
|
||||
LanaiMCCodeEmitter::adjustPqBitsSpls(const MCInst &Inst, unsigned Value,
|
||||
const MCSubtargetInfo &STI) const {
|
||||
return adjustPqBits(Inst, Value, 11, 10);
|
||||
}
|
||||
|
||||
void LanaiMCCodeEmitter::encodeInstruction(
|
||||
const MCInst &Inst, raw_ostream &Ostream, SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const {
|
||||
// Get instruction encoding and emit it
|
||||
unsigned Value = getBinaryCodeForInstr(Inst, Fixups, SubtargetInfo);
|
||||
++MCNumEmitted; // Keep track of the number of emitted insns.
|
||||
|
||||
// Emit bytes in big-endian
|
||||
for (int i = (4 - 1) * 8; i >= 0; i -= 8)
|
||||
Ostream << static_cast<char>((Value >> i) & 0xff);
|
||||
}
|
||||
|
||||
// Encode Lanai Memory Operand
|
||||
unsigned LanaiMCCodeEmitter::getRiMemoryOpValue(
|
||||
const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const {
|
||||
unsigned Encoding;
|
||||
const MCOperand Op1 = Inst.getOperand(OpNo + 0);
|
||||
const MCOperand Op2 = Inst.getOperand(OpNo + 1);
|
||||
const MCOperand AluOp = Inst.getOperand(OpNo + 2);
|
||||
|
||||
assert(Op1.isReg() && "First operand is not register.");
|
||||
assert((Op2.isImm() || Op2.isExpr()) &&
|
||||
"Second operand is neither an immediate nor an expression.");
|
||||
assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) &&
|
||||
"Register immediate only supports addition operator");
|
||||
|
||||
Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 18);
|
||||
if (Op2.isImm()) {
|
||||
assert(isInt<16>(Op2.getImm()) &&
|
||||
"Constant value truncated (limited to 16-bit)");
|
||||
|
||||
Encoding |= (Op2.getImm() & 0xffff);
|
||||
if (Op2.getImm() != 0) {
|
||||
if (LPAC::isPreOp(AluOp.getImm()))
|
||||
Encoding |= (0x3 << 16);
|
||||
if (LPAC::isPostOp(AluOp.getImm()))
|
||||
Encoding |= (0x1 << 16);
|
||||
}
|
||||
} else
|
||||
getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo);
|
||||
|
||||
return Encoding;
|
||||
}
|
||||
|
||||
unsigned LanaiMCCodeEmitter::getRrMemoryOpValue(
|
||||
const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const {
|
||||
unsigned Encoding;
|
||||
const MCOperand Op1 = Inst.getOperand(OpNo + 0);
|
||||
const MCOperand Op2 = Inst.getOperand(OpNo + 1);
|
||||
const MCOperand AluMCOp = Inst.getOperand(OpNo + 2);
|
||||
|
||||
assert(Op1.isReg() && "First operand is not register.");
|
||||
Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 15);
|
||||
assert(Op2.isReg() && "Second operand is not register.");
|
||||
Encoding |= (getLanaiRegisterNumbering(Op2.getReg()) << 10);
|
||||
|
||||
assert(AluMCOp.isImm() && "Third operator is not immediate.");
|
||||
// Set BBB
|
||||
unsigned AluOp = AluMCOp.getImm();
|
||||
Encoding |= LPAC::encodeLanaiAluCode(AluOp) << 5;
|
||||
// Set P and Q
|
||||
if (LPAC::isPreOp(AluOp))
|
||||
Encoding |= (0x3 << 8);
|
||||
if (LPAC::isPostOp(AluOp))
|
||||
Encoding |= (0x1 << 8);
|
||||
// Set JJJJ
|
||||
switch (LPAC::getAluOp(AluOp)) {
|
||||
case LPAC::SHL:
|
||||
case LPAC::SRL:
|
||||
Encoding |= 0x10;
|
||||
break;
|
||||
case LPAC::SRA:
|
||||
Encoding |= 0x18;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Encoding;
|
||||
}
|
||||
|
||||
unsigned
|
||||
LanaiMCCodeEmitter::getSplsOpValue(const MCInst &Inst, unsigned OpNo,
|
||||
SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const {
|
||||
unsigned Encoding;
|
||||
const MCOperand Op1 = Inst.getOperand(OpNo + 0);
|
||||
const MCOperand Op2 = Inst.getOperand(OpNo + 1);
|
||||
const MCOperand AluOp = Inst.getOperand(OpNo + 2);
|
||||
|
||||
assert(Op1.isReg() && "First operand is not register.");
|
||||
assert((Op2.isImm() || Op2.isExpr()) &&
|
||||
"Second operand is neither an immediate nor an expression.");
|
||||
assert((LPAC::getAluOp(AluOp.getImm()) == LPAC::ADD) &&
|
||||
"Register immediate only supports addition operator");
|
||||
|
||||
Encoding = (getLanaiRegisterNumbering(Op1.getReg()) << 12);
|
||||
if (Op2.isImm()) {
|
||||
assert(isInt<10>(Op2.getImm()) &&
|
||||
"Constant value truncated (limited to 10-bit)");
|
||||
|
||||
Encoding |= (Op2.getImm() & 0x3ff);
|
||||
if (Op2.getImm() != 0) {
|
||||
if (LPAC::isPreOp(AluOp.getImm()))
|
||||
Encoding |= (0x3 << 10);
|
||||
if (LPAC::isPostOp(AluOp.getImm()))
|
||||
Encoding |= (0x1 << 10);
|
||||
}
|
||||
} else
|
||||
getMachineOpValue(Inst, Op2, Fixups, SubtargetInfo);
|
||||
|
||||
return Encoding;
|
||||
}
|
||||
|
||||
unsigned LanaiMCCodeEmitter::getCallTargetOpValue(
|
||||
const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const {
|
||||
const MCOperand &MCOp = Inst.getOperand(OpNo);
|
||||
if (MCOp.isReg() || MCOp.isImm())
|
||||
return getMachineOpValue(Inst, MCOp, Fixups, SubtargetInfo);
|
||||
|
||||
Fixups.push_back(MCFixup::create(
|
||||
0, MCOp.getExpr(), static_cast<MCFixupKind>(Lanai::FIXUP_LANAI_25)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned LanaiMCCodeEmitter::getBranchTargetOpValue(
|
||||
const MCInst &Inst, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
|
||||
const MCSubtargetInfo &SubtargetInfo) const {
|
||||
const MCOperand &MCOp = Inst.getOperand(OpNo);
|
||||
if (MCOp.isReg() || MCOp.isImm())
|
||||
return getMachineOpValue(Inst, MCOp, Fixups, SubtargetInfo);
|
||||
|
||||
Fixups.push_back(MCFixup::create(
|
||||
0, MCOp.getExpr(), static_cast<MCFixupKind>(Lanai::FIXUP_LANAI_25)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "LanaiGenMCCodeEmitter.inc"
|
||||
} // namespace
|
||||
} // namespace llvm
|
||||
|
||||
llvm::MCCodeEmitter *
|
||||
llvm::createLanaiMCCodeEmitter(const MCInstrInfo &InstrInfo,
|
||||
const MCRegisterInfo &MRI, MCContext &context) {
|
||||
return new LanaiMCCodeEmitter(InstrInfo, context);
|
||||
}
|
60
lib/Target/Lanai/MCTargetDesc/LanaiMCExpr.cpp
Normal file
60
lib/Target/Lanai/MCTargetDesc/LanaiMCExpr.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
//===-- LanaiMCExpr.cpp - Lanai specific MC expression classes ------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiMCExpr.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "lanaimcexpr"
|
||||
|
||||
const LanaiMCExpr *LanaiMCExpr::create(VariantKind Kind, const MCExpr *Expr,
|
||||
MCContext &Ctx) {
|
||||
return new (Ctx) LanaiMCExpr(Kind, Expr);
|
||||
}
|
||||
|
||||
void LanaiMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
|
||||
if (Kind == VK_Lanai_None) {
|
||||
Expr->print(OS, MAI);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Kind) {
|
||||
default:
|
||||
llvm_unreachable("Invalid kind!");
|
||||
case VK_Lanai_ABS_HI:
|
||||
OS << "hi";
|
||||
break;
|
||||
case VK_Lanai_ABS_LO:
|
||||
OS << "lo";
|
||||
break;
|
||||
}
|
||||
|
||||
OS << '(';
|
||||
const MCExpr *Expr = getSubExpr();
|
||||
Expr->print(OS, MAI);
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
void LanaiMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
|
||||
Streamer.visitUsedExpr(*getSubExpr());
|
||||
}
|
||||
|
||||
bool LanaiMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const {
|
||||
if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
|
||||
return false;
|
||||
|
||||
Res =
|
||||
MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
|
||||
|
||||
return true;
|
||||
}
|
56
lib/Target/Lanai/MCTargetDesc/LanaiMCExpr.h
Normal file
56
lib/Target/Lanai/MCTargetDesc/LanaiMCExpr.h
Normal file
@ -0,0 +1,56 @@
|
||||
//===-- LanaiMCExpr.h - Lanai specific MC expression classes ----*- 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_LANAI_MCTARGETDESC_LANAIMCEXPR_H
|
||||
#define LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCEXPR_H
|
||||
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LanaiMCExpr : public MCTargetExpr {
|
||||
public:
|
||||
enum VariantKind { VK_Lanai_None, VK_Lanai_ABS_HI, VK_Lanai_ABS_LO };
|
||||
|
||||
private:
|
||||
const VariantKind Kind;
|
||||
const MCExpr *Expr;
|
||||
|
||||
explicit LanaiMCExpr(VariantKind Kind, const MCExpr *Expr)
|
||||
: Kind(Kind), Expr(Expr) {}
|
||||
|
||||
public:
|
||||
static const LanaiMCExpr *create(VariantKind Kind, const MCExpr *Expr,
|
||||
MCContext &Ctx);
|
||||
|
||||
// Returns the kind of this expression.
|
||||
VariantKind getKind() const { return Kind; }
|
||||
|
||||
// Returns the child of this expression.
|
||||
const MCExpr *getSubExpr() const { return Expr; }
|
||||
|
||||
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
|
||||
bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const override;
|
||||
void visitUsedExpr(MCStreamer &Streamer) const override;
|
||||
MCFragment *findAssociatedFragment() const override {
|
||||
return getSubExpr()->findAssociatedFragment();
|
||||
}
|
||||
|
||||
// There are no TLS LanaiMCExprs at the moment.
|
||||
void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
|
||||
|
||||
static bool classof(const MCExpr *E) {
|
||||
return E->getKind() == MCExpr::Target;
|
||||
}
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
163
lib/Target/Lanai/MCTargetDesc/LanaiMCTargetDesc.cpp
Normal file
163
lib/Target/Lanai/MCTargetDesc/LanaiMCTargetDesc.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
//===-- LanaiMCTargetDesc.cpp - Lanai 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 Lanai specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "LanaiMCTargetDesc.h"
|
||||
|
||||
#include "InstPrinter/LanaiInstPrinter.h"
|
||||
#include "LanaiMCAsmInfo.h"
|
||||
#include "llvm/MC/MCCodeGenInfo.h"
|
||||
#include "llvm/MC/MCInstrAnalysis.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
#define GET_INSTRINFO_MC_DESC
|
||||
#include "LanaiGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_MC_DESC
|
||||
#include "LanaiGenSubtargetInfo.inc"
|
||||
|
||||
#define GET_REGINFO_MC_DESC
|
||||
#include "LanaiGenRegisterInfo.inc"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static MCInstrInfo *createLanaiMCInstrInfo() {
|
||||
MCInstrInfo *X = new MCInstrInfo();
|
||||
InitLanaiMCInstrInfo(X);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCRegisterInfo *createLanaiMCRegisterInfo(const Triple &TT) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
InitLanaiMCRegisterInfo(X, Lanai::RCA, 0, 0, Lanai::PC);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCSubtargetInfo *
|
||||
createLanaiMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
|
||||
std::string CPUName = CPU;
|
||||
if (CPUName.empty())
|
||||
CPUName = "generic";
|
||||
|
||||
return createLanaiMCSubtargetInfoImpl(TT, CPUName, FS);
|
||||
}
|
||||
|
||||
static MCCodeGenInfo *createLanaiMCCodeGenInfo(const Triple &TT,
|
||||
Reloc::Model RM,
|
||||
CodeModel::Model CM,
|
||||
CodeGenOpt::Level OL) {
|
||||
MCCodeGenInfo *X = new MCCodeGenInfo();
|
||||
X->initMCCodeGenInfo(RM, CM, OL);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context,
|
||||
MCAsmBackend &MAB, raw_pwrite_stream &OS,
|
||||
MCCodeEmitter *Emitter, bool RelaxAll) {
|
||||
if (!T.isOSBinFormatELF())
|
||||
llvm_unreachable("OS not supported");
|
||||
|
||||
return createELFStreamer(Context, MAB, OS, Emitter, RelaxAll);
|
||||
}
|
||||
|
||||
static MCInstPrinter *createLanaiMCInstPrinter(const Triple &T,
|
||||
unsigned SyntaxVariant,
|
||||
const MCAsmInfo &MAI,
|
||||
const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI) {
|
||||
if (SyntaxVariant == 0)
|
||||
return new LanaiInstPrinter(MAI, MII, MRI);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MCRelocationInfo *createLanaiElfRelocation(const Triple &TheTriple,
|
||||
MCContext &Ctx) {
|
||||
return createMCRelocationInfo(TheTriple, Ctx);
|
||||
}
|
||||
|
||||
class LanaiMCInstrAnalysis : public MCInstrAnalysis {
|
||||
public:
|
||||
explicit LanaiMCInstrAnalysis(const MCInstrInfo *Info)
|
||||
: MCInstrAnalysis(Info) {}
|
||||
|
||||
bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
|
||||
uint64_t &Target) const override {
|
||||
if (Inst.getNumOperands() == 0)
|
||||
return false;
|
||||
|
||||
if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType ==
|
||||
MCOI::OPERAND_PCREL) {
|
||||
int64_t Imm = Inst.getOperand(0).getImm();
|
||||
Target = Addr + Size + Imm;
|
||||
return true;
|
||||
} else {
|
||||
int64_t Imm = Inst.getOperand(0).getImm();
|
||||
|
||||
// Skip case where immediate is 0 as that occurs in file that isn't linked
|
||||
// and the branch target inferred would be wrong.
|
||||
if (Imm == 0)
|
||||
return false;
|
||||
|
||||
Target = Imm;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static MCInstrAnalysis *createLanaiInstrAnalysis(const MCInstrInfo *Info) {
|
||||
return new LanaiMCInstrAnalysis(Info);
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeLanaiTargetMC() {
|
||||
// Register the MC asm info.
|
||||
RegisterMCAsmInfo<LanaiMCAsmInfo> X(TheLanaiTarget);
|
||||
|
||||
// Register the MC codegen info.
|
||||
TargetRegistry::RegisterMCCodeGenInfo(TheLanaiTarget,
|
||||
createLanaiMCCodeGenInfo);
|
||||
|
||||
// Register the MC instruction info.
|
||||
TargetRegistry::RegisterMCInstrInfo(TheLanaiTarget, createLanaiMCInstrInfo);
|
||||
|
||||
// Register the MC register info.
|
||||
TargetRegistry::RegisterMCRegInfo(TheLanaiTarget, createLanaiMCRegisterInfo);
|
||||
|
||||
// Register the MC subtarget info.
|
||||
TargetRegistry::RegisterMCSubtargetInfo(TheLanaiTarget,
|
||||
createLanaiMCSubtargetInfo);
|
||||
|
||||
// Register the MC code emitter
|
||||
TargetRegistry::RegisterMCCodeEmitter(TheLanaiTarget,
|
||||
llvm::createLanaiMCCodeEmitter);
|
||||
|
||||
// Register the ASM Backend
|
||||
TargetRegistry::RegisterMCAsmBackend(TheLanaiTarget, createLanaiAsmBackend);
|
||||
|
||||
// Register the MCInstPrinter.
|
||||
TargetRegistry::RegisterMCInstPrinter(TheLanaiTarget,
|
||||
createLanaiMCInstPrinter);
|
||||
|
||||
// Register the ELF streamer.
|
||||
TargetRegistry::RegisterELFStreamer(TheLanaiTarget, createMCStreamer);
|
||||
|
||||
// Register the MC relocation info.
|
||||
TargetRegistry::RegisterMCRelocationInfo(TheLanaiTarget,
|
||||
createLanaiElfRelocation);
|
||||
|
||||
// Register the MC instruction analyzer.
|
||||
TargetRegistry::RegisterMCInstrAnalysis(TheLanaiTarget,
|
||||
createLanaiInstrAnalysis);
|
||||
}
|
59
lib/Target/Lanai/MCTargetDesc/LanaiMCTargetDesc.h
Normal file
59
lib/Target/Lanai/MCTargetDesc/LanaiMCTargetDesc.h
Normal file
@ -0,0 +1,59 @@
|
||||
//===-- LanaiMCTargetDesc.h - Lanai 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 Lanai specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCTARGETDESC_H
|
||||
#define LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCTARGETDESC_H
|
||||
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmBackend;
|
||||
class MCCodeEmitter;
|
||||
class MCContext;
|
||||
class MCInstrInfo;
|
||||
class MCInstrAnalysis;
|
||||
class MCObjectWriter;
|
||||
class MCRelocationInfo;
|
||||
class MCSubtargetInfo;
|
||||
class Target;
|
||||
class Triple;
|
||||
class StringRef;
|
||||
class raw_pwrite_stream;
|
||||
|
||||
extern Target TheLanaiTarget;
|
||||
|
||||
MCCodeEmitter *createLanaiMCCodeEmitter(const MCInstrInfo &MCII,
|
||||
const MCRegisterInfo &MRI,
|
||||
MCContext &Ctx);
|
||||
|
||||
MCAsmBackend *createLanaiAsmBackend(const Target &T, const MCRegisterInfo &MRI,
|
||||
const Triple &TheTriple, StringRef CPU);
|
||||
|
||||
MCObjectWriter *createLanaiELFObjectWriter(raw_pwrite_stream &OS,
|
||||
uint8_t OSABI);
|
||||
} // namespace llvm
|
||||
|
||||
// Defines symbolic names for Lanai registers. This defines a mapping from
|
||||
// register name to register number.
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "LanaiGenRegisterInfo.inc"
|
||||
|
||||
// Defines symbolic names for the Lanai instructions.
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "LanaiGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "LanaiGenSubtargetInfo.inc"
|
||||
|
||||
#endif // LLVM_LIB_TARGET_LANAI_MCTARGETDESC_LANAIMCTARGETDESC_H
|
3
lib/Target/Lanai/TargetInfo/CMakeLists.txt
Normal file
3
lib/Target/Lanai/TargetInfo/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
add_llvm_library(LLVMLanaiInfo
|
||||
LanaiTargetInfo.cpp
|
||||
)
|
23
lib/Target/Lanai/TargetInfo/LLVMBuild.txt
Normal file
23
lib/Target/Lanai/TargetInfo/LLVMBuild.txt
Normal file
@ -0,0 +1,23 @@
|
||||
;===- ./lib/Target/Lanai/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 = LanaiInfo
|
||||
parent = Lanai
|
||||
required_libraries = Support
|
||||
add_to_library_groups = Lanai
|
20
lib/Target/Lanai/TargetInfo/LanaiTargetInfo.cpp
Normal file
20
lib/Target/Lanai/TargetInfo/LanaiTargetInfo.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
//===-- LanaiTargetInfo.cpp - Lanai Target Implementation -----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Lanai.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
Target llvm::TheLanaiTarget;
|
||||
|
||||
extern "C" void LLVMInitializeLanaiTargetInfo() {
|
||||
RegisterTarget<Triple::lanai> X(TheLanaiTarget, "lanai", "Lanai");
|
||||
}
|
30
test/CodeGen/Lanai/codemodel.ll
Normal file
30
test/CodeGen/Lanai/codemodel.ll
Normal file
@ -0,0 +1,30 @@
|
||||
; RUN: llc -march=lanai < %s | FileCheck %s
|
||||
; RUN: llc -march=lanai < %s -code-model=small | FileCheck -check-prefix CHECK-SMALL %s
|
||||
|
||||
@data = external global [0 x i32] ; <[0 x i32]*> [#uses=5]
|
||||
|
||||
define i32 @foo() nounwind readonly {
|
||||
entry:
|
||||
; CHECK-SMALL-LABEL: foo:
|
||||
; CHECK-SMALL: ld [data], %rv
|
||||
; CHECK-LABEL: foo:
|
||||
; CHECK: mov hi(data), %r[[REGISTER:[0-9]+]]
|
||||
; CHECK: or %r[[REGISTER]], lo(data), %r[[REGISTER]]
|
||||
; CHECK: ld 0[%r[[REGISTER]]], %rv
|
||||
%0 = load i32, i32* getelementptr ([0 x i32], [0 x i32]* @data, i64 0, i64 0), align 4 ; <i32> [#uses=1]
|
||||
ret i32 %0
|
||||
}
|
||||
|
||||
define i32 @foo1() nounwind readonly {
|
||||
entry:
|
||||
; CHECK-SMALL-LABEL: foo1:
|
||||
; CHECK-SMALL: mov data, %r[[REGISTER:[0-9]+]]
|
||||
; CHECK-SMALL: ld 40[%r[[REGISTER]]], %rv
|
||||
; CHECK-LABEL: foo1:
|
||||
; CHECK: mov hi(data), %r[[REGISTER:[0-9]+]]
|
||||
; CHECK: or %r[[REGISTER]], lo(data), %r[[REGISTER]]
|
||||
; CHECK: ld 40[%r[[REGISTER]]], %rv
|
||||
%0 = load i32, i32* getelementptr ([0 x i32], [0 x i32]* @data, i32 0, i64 10), align 4 ; <i32> [#uses=1]
|
||||
ret i32 %0
|
||||
}
|
||||
|
126
test/CodeGen/Lanai/combined_alu_setcc.ll
Normal file
126
test/CodeGen/Lanai/combined_alu_setcc.ll
Normal file
@ -0,0 +1,126 @@
|
||||
; RUN: llc < %s -march=lanai | FileCheck %s
|
||||
|
||||
; Test the alu setcc combiner.
|
||||
|
||||
; TODO: Enhance combiner to handle this case. This expands into:
|
||||
; sub %r7, %r6, %r3
|
||||
; sub.f %r7, %r6, %r0
|
||||
; sel.eq %r18, %r3, %rv
|
||||
; This is different from the pattern currently matched. If the lowered form had
|
||||
; been sub.f %r3, 0, %r0 then it would have matched.
|
||||
|
||||
; Function Attrs: norecurse nounwind readnone
|
||||
define i32 @test0a(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 inreg %d) #0 {
|
||||
entry:
|
||||
%sub = sub i32 %b, %a
|
||||
%cmp = icmp eq i32 %sub, 0
|
||||
%cond = select i1 %cmp, i32 %c, i32 %sub
|
||||
ret i32 %cond
|
||||
}
|
||||
; CHECK-LABEL: test0a
|
||||
; CHECK: sub.f %r7
|
||||
; CHECK: sel.eq
|
||||
|
||||
; Function Attrs: norecurse nounwind readnone
|
||||
define i32 @test0b(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 inreg %d) #0 {
|
||||
entry:
|
||||
%cmp = icmp eq i32 %b, %a
|
||||
%cond = select i1 %cmp, i32 %c, i32 %b
|
||||
ret i32 %cond
|
||||
}
|
||||
; CHECK-LABEL: test0b
|
||||
; CHECK: sub.f %r7, %r6, %r0
|
||||
; CHECK-NEXT: sel.eq
|
||||
|
||||
; Function Attrs: norecurse nounwind readnone
|
||||
define i32 @test1a(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 inreg %d) #0 {
|
||||
entry:
|
||||
%sub = sub i32 %b, %a
|
||||
%cmp = icmp slt i32 %sub, 0
|
||||
%cond = select i1 %cmp, i32 %c, i32 %d
|
||||
ret i32 %cond
|
||||
}
|
||||
; CHECK-LABEL: test1a
|
||||
; CHECK: sub.f %r7, %r6
|
||||
; CHECK-NEXT: sel.mi
|
||||
|
||||
; Function Attrs: norecurse nounwind readnone
|
||||
define i32 @test1b(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 inreg %d) #0 {
|
||||
entry:
|
||||
%sub = sub i32 %b, %a
|
||||
%cmp = icmp slt i32 %sub, 0
|
||||
%cond = select i1 %cmp, i32 %c, i32 %d
|
||||
ret i32 %cond
|
||||
}
|
||||
; CHECK-LABEL: test1b
|
||||
; CHECK: sub.f %r7, %r6
|
||||
; CHECK-NEXT: sel.mi
|
||||
|
||||
; Function Attrs: norecurse nounwind readnone
|
||||
define i32 @test2a(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 inreg %d) #0 {
|
||||
entry:
|
||||
%sub = sub i32 %b, %a
|
||||
%cmp = icmp sgt i32 %sub, -1
|
||||
%cond = select i1 %cmp, i32 %c, i32 %d
|
||||
ret i32 %cond
|
||||
}
|
||||
; CHECK-LABEL: test2a
|
||||
; CHECK: sub.f %r7, %r6
|
||||
; CHECK: sel.pl
|
||||
|
||||
; Function Attrs: norecurse nounwind readnone
|
||||
define i32 @test2b(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 inreg %d) #0 {
|
||||
entry:
|
||||
%sub = sub i32 %b, %a
|
||||
%cmp = icmp sgt i32 %sub, -1
|
||||
%cond = select i1 %cmp, i32 %c, i32 %d
|
||||
ret i32 %cond
|
||||
}
|
||||
; CHECK-LABEL: test2b
|
||||
; CHECK: sub.f %r7, %r6
|
||||
; CHECK: sel.pl
|
||||
|
||||
; Function Attrs: norecurse nounwind readnone
|
||||
define i32 @test3(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 inreg %d) #0 {
|
||||
entry:
|
||||
%sub = sub i32 %b, %a
|
||||
%cmp = icmp slt i32 %sub, 1
|
||||
%cond = select i1 %cmp, i32 %c, i32 %d
|
||||
ret i32 %cond
|
||||
}
|
||||
|
||||
; Function Attrs: norecurse nounwind readnone
|
||||
define i32 @test4(i32 inreg %a, i32 inreg %b, i32 inreg %c, i32 inreg %d) #0 {
|
||||
entry:
|
||||
%cmp = icmp ne i32 %a, 0
|
||||
%cmp1 = icmp ult i32 %a, %b
|
||||
%or.cond = and i1 %cmp, %cmp1
|
||||
br i1 %or.cond, label %return, label %if.end
|
||||
|
||||
if.end: ; preds = %entry
|
||||
%cmp2 = icmp ne i32 %b, 0
|
||||
%cmp4 = icmp ult i32 %b, %c
|
||||
%or.cond29 = and i1 %cmp2, %cmp4
|
||||
br i1 %or.cond29, label %return, label %if.end6
|
||||
|
||||
if.end6: ; preds = %if.end
|
||||
%cmp7 = icmp ne i32 %c, 0
|
||||
%cmp9 = icmp ult i32 %c, %d
|
||||
%or.cond30 = and i1 %cmp7, %cmp9
|
||||
br i1 %or.cond30, label %return, label %if.end11
|
||||
|
||||
if.end11: ; preds = %if.end6
|
||||
%cmp12 = icmp ne i32 %d, 0
|
||||
%cmp14 = icmp ult i32 %d, %a
|
||||
%or.cond31 = and i1 %cmp12, %cmp14
|
||||
%b. = select i1 %or.cond31, i32 %b, i32 21
|
||||
ret i32 %b.
|
||||
|
||||
return: ; preds = %if.end6, %if.end, %entry
|
||||
%retval.0 = phi i32 [ %c, %entry ], [ %d, %if.end ], [ %a, %if.end6 ]
|
||||
ret i32 %retval.0
|
||||
}
|
||||
; CHECK-LABEL: test4
|
||||
; CHECK: and.f
|
||||
; CHECK: and.f
|
||||
; CHECK: and.f
|
96
test/CodeGen/Lanai/comparisons_i32.ll
Normal file
96
test/CodeGen/Lanai/comparisons_i32.ll
Normal file
@ -0,0 +1,96 @@
|
||||
; RUN: llc < %s | FileCheck %s
|
||||
|
||||
; Test that basic 32-bit integer comparison operations assemble as expected.
|
||||
|
||||
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
|
||||
target triple = "lanai"
|
||||
|
||||
; CHECK-LABEL: eq_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: seq
|
||||
define i32 @eq_i32(i32 %x, i32 %y) {
|
||||
%a = icmp eq i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
; CHECK-LABEL: ne_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: sne
|
||||
define i32 @ne_i32(i32 %x, i32 %y) {
|
||||
%a = icmp ne i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
; CHECK-LABEL: slt_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: slt
|
||||
define i32 @slt_i32(i32 %x, i32 %y) {
|
||||
%a = icmp slt i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sle_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: sle
|
||||
define i32 @sle_i32(i32 %x, i32 %y) {
|
||||
%a = icmp sle i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
; CHECK-LABEL: ult_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: sult
|
||||
define i32 @ult_i32(i32 %x, i32 %y) {
|
||||
%a = icmp ult i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
; CHECK-LABEL: ule_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: sule
|
||||
define i32 @ule_i32(i32 %x, i32 %y) {
|
||||
%a = icmp ule i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sgt_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: sgt
|
||||
define i32 @sgt_i32(i32 %x, i32 %y) {
|
||||
%a = icmp sgt i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sge_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: sge
|
||||
define i32 @sge_i32(i32 %x, i32 %y) {
|
||||
%a = icmp sge i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
; CHECK-LABEL: ugt_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: sugt
|
||||
define i32 @ugt_i32(i32 %x, i32 %y) {
|
||||
%a = icmp ugt i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
||||
|
||||
; CHECK-LABEL: uge_i32:
|
||||
; CHECK: sub.f %r{{[0-9]+}}, %r{{[0-9]+}}, %r0
|
||||
; CHECK-NEXT: suge
|
||||
define i32 @uge_i32(i32 %x, i32 %y) {
|
||||
%a = icmp uge i32 %x, %y
|
||||
%b = zext i1 %a to i32
|
||||
ret i32 %b
|
||||
}
|
107
test/CodeGen/Lanai/constant_multiply.ll
Normal file
107
test/CodeGen/Lanai/constant_multiply.ll
Normal file
@ -0,0 +1,107 @@
|
||||
; RUN: llc < %s | FileCheck %s
|
||||
|
||||
; Test custom lowering for 32-bit integer multiplication.
|
||||
|
||||
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
|
||||
target triple = "lanai"
|
||||
|
||||
; CHECK-LABEL: f6:
|
||||
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @f6(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, 6
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f7:
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r6, %rv
|
||||
define i32 @f7(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, 7
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f8:
|
||||
; CHECK: sh %r6, 0x3, %rv
|
||||
define i32 @f8(i32 inreg %a) #0 {
|
||||
%1 = shl nsw i32 %a, 3
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f9:
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: add %r{{[0-9]+}}, %r6, %rv
|
||||
define i32 @f9(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, 9
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f10:
|
||||
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: add %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @f10(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, 10
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f1280:
|
||||
; CHECK: sh %r6, 0x8, %r{{[0-9]+}}
|
||||
; CHECK: sh %r6, 0xa, %r{{[0-9]+}}
|
||||
; CHECK: add %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @f1280(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, 1280
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: fm6:
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @fm6(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, -6
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: fm7:
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sub %r6, %r{{[0-9]+}}, %rv
|
||||
define i32 @fm7(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, -7
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: fm8:
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @fm8(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, -8
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: fm9:
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r6, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @fm9(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, -9
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: fm10:
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @fm10(i32 inreg %a) #0 {
|
||||
%1 = mul nsw i32 %a, -10
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: h1:
|
||||
; CHECK: __mulsi3
|
||||
define i32 @h1(i32 inreg %a) #0 {
|
||||
%1 = mul i32 %a, -1431655765
|
||||
ret i32 %1
|
||||
}
|
41
test/CodeGen/Lanai/delay_filler.ll
Normal file
41
test/CodeGen/Lanai/delay_filler.ll
Normal file
@ -0,0 +1,41 @@
|
||||
; RUN: llc -march=lanai < %s | FileCheck %s
|
||||
; RUN: llc -march=lanai --lanai-nop-delay-filler < %s | \
|
||||
; RUN: FileCheck %s --check-prefix=NOP
|
||||
|
||||
; CHECK: bt f
|
||||
; CHECK-NEXT: or
|
||||
; NOP: bt f
|
||||
; NOP-NEXT: nop
|
||||
|
||||
; ModuleID = 'delay_filler.c'
|
||||
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
|
||||
target triple = "lanai"
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @g(i32 inreg %n) #0 {
|
||||
entry:
|
||||
%cmp5 = icmp sgt i32 %n, 0
|
||||
br i1 %cmp5, label %for.body.preheader, label %for.cond.cleanup
|
||||
|
||||
for.body.preheader: ; preds = %entry
|
||||
br label %for.body
|
||||
|
||||
for.cond.cleanup.loopexit: ; preds = %for.body
|
||||
%call.lcssa = phi i32 [ %call, %for.body ]
|
||||
br label %for.cond.cleanup
|
||||
|
||||
for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry
|
||||
%a.0.lcssa = phi i32 [ undef, %entry ], [ %call.lcssa, %for.cond.cleanup.loopexit ]
|
||||
ret i32 %a.0.lcssa
|
||||
|
||||
for.body: ; preds = %for.body.preheader, %for.body
|
||||
%i.07 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
|
||||
%a.06 = phi i32 [ %call, %for.body ], [ undef, %for.body.preheader ]
|
||||
%call = tail call i32 @f(i32 inreg %a.06) #2
|
||||
%inc = add nuw nsw i32 %i.07, 1
|
||||
%exitcond = icmp eq i32 %inc, %n
|
||||
br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body
|
||||
}
|
||||
|
||||
declare i32 @f(i32 inreg) #1
|
||||
|
145
test/CodeGen/Lanai/i32.ll
Normal file
145
test/CodeGen/Lanai/i32.ll
Normal file
@ -0,0 +1,145 @@
|
||||
; RUN: llc < %s -asm-verbose=false | FileCheck %s
|
||||
|
||||
; Test that basic 32-bit integer operations assemble as expected.
|
||||
|
||||
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
|
||||
target triple = "lanai"
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @llvm.ctpop.i32(i32) #1
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @llvm.ctlz.i32(i32, i1) #1
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare i32 @llvm.cttz.i32(i32, i1) #1
|
||||
|
||||
; CHECK-LABEL: add32:
|
||||
; CHECK: add %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @add32(i32 %x, i32 %y) {
|
||||
%a = add i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sub32:
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @sub32(i32 %x, i32 %y) {
|
||||
%a = sub i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: mul32:
|
||||
; CHECK: bt __mulsi3
|
||||
define i32 @mul32(i32 %x, i32 %y) {
|
||||
%a = mul i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sdiv32:
|
||||
; CHECK: bt __divsi3
|
||||
define i32 @sdiv32(i32 %x, i32 %y) {
|
||||
%a = sdiv i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: udiv32:
|
||||
; CHECK: bt __udivsi3
|
||||
define i32 @udiv32(i32 %x, i32 %y) {
|
||||
%a = udiv i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: srem32:
|
||||
; CHECK: bt __modsi3
|
||||
define i32 @srem32(i32 %x, i32 %y) {
|
||||
%a = srem i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: urem32:
|
||||
; CHECK: bt __umodsi3
|
||||
define i32 @urem32(i32 %x, i32 %y) {
|
||||
%a = urem i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: and32:
|
||||
; CHECK: and %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @and32(i32 %x, i32 %y) {
|
||||
%a = and i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: or32:
|
||||
; CHECK: or %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @or32(i32 %x, i32 %y) {
|
||||
%a = or i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: xor32:
|
||||
; CHECK: xor %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @xor32(i32 %x, i32 %y) {
|
||||
%a = xor i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: shl32:
|
||||
; CHECK: sh %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @shl32(i32 %x, i32 %y) {
|
||||
%a = shl i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: shr32:
|
||||
; CHECK: sub %r0, %r{{[0-9]+}}, %r{{[0-9]+}}
|
||||
; CHECK: sh %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @shr32(i32 %x, i32 %y) {
|
||||
%a = lshr i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sar32
|
||||
; CHECK: sub %r0, %r{{[0-9]+}}, %r{{[0-9]+}}
|
||||
; CHECK: sha %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
define i32 @sar32(i32 %x, i32 %y) {
|
||||
%a = ashr i32 %x, %y
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: clz32:
|
||||
; CHECK: leadz %r{{[0-9]+}}, %rv
|
||||
define i32 @clz32(i32 %x) {
|
||||
%a = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: clz32_zero_undef:
|
||||
; CHECK-NOT: sub.f
|
||||
; CHECK: leadz %r{{[0-9]+}}, %rv
|
||||
define i32 @clz32_zero_undef(i32 %x) {
|
||||
%a = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: ctz32:
|
||||
; CHECK: trailz %r{{[0-9]+}}, %rv
|
||||
define i32 @ctz32(i32 %x) {
|
||||
%a = call i32 @llvm.cttz.i32(i32 %x, i1 false)
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: ctz32_zero_undef:
|
||||
; CHECK-NOT: sub.f
|
||||
; CHECK: trailz %r{{[0-9]+}}, %rv
|
||||
define i32 @ctz32_zero_undef(i32 %x) {
|
||||
%a = call i32 @llvm.cttz.i32(i32 %x, i1 true)
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: popcnt32:
|
||||
; CHECK: popc %r{{[0-9]+}}, %rv
|
||||
define i32 @popcnt32(i32 %x) {
|
||||
%a = call i32 @llvm.ctpop.i32(i32 %x)
|
||||
ret i32 %a
|
||||
}
|
3
test/CodeGen/Lanai/lit.local.cfg
Normal file
3
test/CodeGen/Lanai/lit.local.cfg
Normal file
@ -0,0 +1,3 @@
|
||||
if not 'Lanai' in config.root.targets:
|
||||
config.unsupported = True
|
||||
|
40
test/CodeGen/Lanai/mem_alu_combiner.ll
Normal file
40
test/CodeGen/Lanai/mem_alu_combiner.ll
Normal file
@ -0,0 +1,40 @@
|
||||
; RUN: llc < %s -march=lanai | FileCheck %s
|
||||
; RUN: llc < %s -march=lanai -disable-lanai-mem-alu-combiner | \
|
||||
; RUN: FileCheck %s -check-prefix=CHECK-DIS
|
||||
|
||||
; CHECK-LABEL: sum,
|
||||
; CHECK: ++],
|
||||
; CHECK-DIS-LABEL: sum,
|
||||
; CHECK-DIS-NOT: ++],
|
||||
|
||||
define i32 @sum(i32* inreg nocapture readonly %data, i32 inreg %n) #0 {
|
||||
entry:
|
||||
%cmp6 = icmp sgt i32 %n, 0
|
||||
br i1 %cmp6, label %for.body.preheader, label %for.cond.cleanup
|
||||
|
||||
for.body.preheader: ; preds = %entry
|
||||
br label %for.body
|
||||
|
||||
for.cond.cleanup.loopexit: ; preds = %for.body
|
||||
%add.lcssa = phi i32 [ %add, %for.body ]
|
||||
br label %for.cond.cleanup
|
||||
|
||||
for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry
|
||||
%sum_.0.lcssa = phi i32 [ 0, %entry ], [ %add.lcssa, %for.cond.cleanup.loopexit ]
|
||||
ret i32 %sum_.0.lcssa
|
||||
|
||||
for.body: ; preds = %for.body.preheader, %for.body
|
||||
%i.08 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ]
|
||||
%sum_.07 = phi i32 [ %add, %for.body ], [ 0, %for.body.preheader ]
|
||||
%arrayidx = getelementptr inbounds i32, i32* %data, i32 %i.08
|
||||
%0 = load i32, i32* %arrayidx, align 4, !tbaa !0
|
||||
%add = add nsw i32 %0, %sum_.07
|
||||
%inc = add nuw nsw i32 %i.08, 1
|
||||
%exitcond = icmp eq i32 %inc, %n
|
||||
br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body
|
||||
}
|
||||
|
||||
!0 = !{!1, !1, i64 0}
|
||||
!1 = !{!"int", !2, i64 0}
|
||||
!2 = !{!"omnipotent char", !3, i64 0}
|
||||
!3 = !{!"Simple C/C++ TBAA"}
|
60
test/CodeGen/Lanai/multiply.ll
Normal file
60
test/CodeGen/Lanai/multiply.ll
Normal file
@ -0,0 +1,60 @@
|
||||
; RUN: llc -march=lanai < %s | FileCheck %s
|
||||
|
||||
; Test the in place lowering of mul i32.
|
||||
|
||||
define i32 @f6(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%mul = mul nsw i32 %a, 6
|
||||
ret i32 %mul
|
||||
}
|
||||
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
|
||||
define i32 @f7(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%mul = mul nsw i32 %a, 7
|
||||
ret i32 %mul
|
||||
}
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r6, %rv
|
||||
|
||||
define i32 @f8(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%mul = shl nsw i32 %a, 3
|
||||
ret i32 %mul
|
||||
}
|
||||
; CHECK: sh %r6, 0x3, %rv
|
||||
|
||||
define i32 @fm6(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%mul = mul nsw i32 %a, -6
|
||||
ret i32 %mul
|
||||
}
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sh %r6, 0x1, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
|
||||
define i32 @fm7(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%mul = mul nsw i32 %a, -7
|
||||
ret i32 %mul
|
||||
}
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sub %r6, %r{{[0-9]+}}, %rv
|
||||
|
||||
define i32 @fm8(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%mul = mul nsw i32 %a, -8
|
||||
ret i32 %mul
|
||||
}
|
||||
; CHECK: sh %r6, 0x3, %r{{[0-9]+}}
|
||||
; CHECK: sub %r{{[0-9]+}}, %r{{[0-9]+}}, %rv
|
||||
|
||||
define i32 @h1(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%mul = mul i32 %a, -1431655765
|
||||
ret i32 %mul
|
||||
}
|
||||
; CHECK: h1
|
||||
; CHECK: mulsi3
|
41
test/CodeGen/Lanai/select.ll
Normal file
41
test/CodeGen/Lanai/select.ll
Normal file
@ -0,0 +1,41 @@
|
||||
; RUN: llc < %s | FileCheck %s
|
||||
|
||||
; Test that Lanai select instruction is selected from LLVM select instruction.
|
||||
|
||||
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
|
||||
target triple = "lanai"
|
||||
|
||||
; CHECK-LABEL: select_i32_bool:
|
||||
; CHECK: sub.f %r6, 0x0, %r0
|
||||
; CHECK: sel.ne %r7, %r18, %rv
|
||||
define i32 @select_i32_bool(i1 inreg %a, i32 inreg %b, i32 inreg %c) {
|
||||
%cond = select i1 %a, i32 %b, i32 %c
|
||||
ret i32 %cond
|
||||
}
|
||||
|
||||
; CHECK-LABEL: select_i32_eq:
|
||||
; CHECK: sub.f %r6, 0x0, %r0
|
||||
; CHECK: sel.eq %r7, %r18, %rv
|
||||
define i32 @select_i32_eq(i32 inreg %a, i32 inreg %b, i32 inreg %c) {
|
||||
%cmp = icmp eq i32 %a, 0
|
||||
%cond = select i1 %cmp, i32 %b, i32 %c
|
||||
ret i32 %cond
|
||||
}
|
||||
|
||||
; CHECK-LABEL: select_i32_ne:
|
||||
; CHECK: sub.f %r6, 0x0, %r0
|
||||
; CHECK: sel.ne %r7, %r18, %rv
|
||||
define i32 @select_i32_ne(i32 inreg %a, i32 inreg %b, i32 inreg %c) {
|
||||
%cmp = icmp ne i32 %a, 0
|
||||
%cond = select i1 %cmp, i32 %b, i32 %c
|
||||
ret i32 %cond
|
||||
}
|
||||
|
||||
; CHECK-LABEL: select_i32_lt:
|
||||
; CHECK: sub.f %r6, %r7, %r0
|
||||
; CHECK: sel.lt %r6, %r7, %rv
|
||||
define i32 @select_i32_lt(i32 inreg %x, i32 inreg %y) #0 {
|
||||
%1 = icmp slt i32 %x, %y
|
||||
%2 = select i1 %1, i32 %x, i32 %y
|
||||
ret i32 %2
|
||||
}
|
15
test/CodeGen/Lanai/set_and_hi.ll
Normal file
15
test/CodeGen/Lanai/set_and_hi.ll
Normal file
@ -0,0 +1,15 @@
|
||||
; RUN: llc < %s | FileCheck %s
|
||||
|
||||
; Test matching of and_hi.
|
||||
|
||||
target datalayout = "E-m:e-p:32:32-i64:64-a:0:32-n32-S64"
|
||||
target triple = "lanai"
|
||||
|
||||
@x = common global i32 0, align 4
|
||||
|
||||
; CHECK-LABEL: setandhi:
|
||||
; CHECK: mov 0xfffffe4a, %r{{[0-9]+}}
|
||||
define void @setandhi() #0 {
|
||||
store volatile i32 -438, i32* @x, align 4
|
||||
ret void
|
||||
}
|
28
test/CodeGen/Lanai/shift.ll
Normal file
28
test/CodeGen/Lanai/shift.ll
Normal file
@ -0,0 +1,28 @@
|
||||
; RUN: llc < %s -march=lanai | FileCheck %s
|
||||
|
||||
; Test lowering of shifts.
|
||||
|
||||
define i32 @irs(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%shr = ashr i32 %a, 13
|
||||
ret i32 %shr
|
||||
}
|
||||
; CHECK-LABEL: irs
|
||||
; CHECK: sha %r6, -0xd, %rv
|
||||
|
||||
define i32 @urs(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%shr = lshr i32 %a, 13
|
||||
ret i32 %shr
|
||||
}
|
||||
; CHECK-LABEL: urs
|
||||
; CHECK: sh %r6, -0xd, %rv
|
||||
|
||||
define i32 @ls(i32 inreg %a) #0 {
|
||||
entry:
|
||||
%shl = shl i32 %a, 13
|
||||
ret i32 %shl
|
||||
}
|
||||
; CHECK-LABEL: ls
|
||||
; CHECK: sh %r6, 0xd, %rv
|
||||
|
14
test/CodeGen/Lanai/stack-frame.ll
Normal file
14
test/CodeGen/Lanai/stack-frame.ll
Normal file
@ -0,0 +1,14 @@
|
||||
; RUN: llc -mtriple=lanai < %s -o - | FileCheck %s
|
||||
|
||||
define void @f1() {
|
||||
%c = alloca i8, align 1
|
||||
ret void
|
||||
}
|
||||
; CHECK-LABEL: f1:
|
||||
; CHECK: sub %sp, 0x10
|
||||
|
||||
define i32 @f2() {
|
||||
ret i32 1
|
||||
}
|
||||
; CHECK-LABEL: f2:
|
||||
; CHECK: sub %sp, 0x8
|
Binary file not shown.
@ -1,9 +1,5 @@
|
||||
; RUN: llvm-dwarfdump %p/../Inputs/lanai-processes-relocations.elf 2>&1 | FileCheck %s
|
||||
|
||||
; FIXME: Use llc with this file as input instead of binary file.
|
||||
; NOTE: this test is currently not using llc, but using a binary input as the
|
||||
; rest of the backend is not yet in tree. Once the Lanai backend is in tree,
|
||||
; the binary file will be removed and this test will use llc.
|
||||
; RUN: llc -filetype=obj -O0 < %s -mtriple lanai-unknown-unknown | \
|
||||
; RUN: llvm-dwarfdump - 2>&1 | FileCheck %s
|
||||
|
||||
; CHECK-NOT: failed to compute relocation
|
||||
|
||||
@ -15,5 +11,5 @@
|
||||
!1 = !{!"empty.c", !"/a"}
|
||||
!2 = !{}
|
||||
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 1}
|
||||
!5 = !{!"clang version 3.6.0 "}
|
||||
|
3
test/MC/Disassembler/Lanai/lit.local.cfg
Normal file
3
test/MC/Disassembler/Lanai/lit.local.cfg
Normal file
@ -0,0 +1,3 @@
|
||||
if not 'Lanai' in config.root.targets:
|
||||
config.unsupported = True
|
||||
|
762
test/MC/Disassembler/Lanai/v11.txt
Normal file
762
test/MC/Disassembler/Lanai/v11.txt
Normal file
@ -0,0 +1,762 @@
|
||||
# RUN: llvm-mc -disassemble -triple lanai %s | FileCheck %s
|
||||
|
||||
0x0a 0xc4 0x00 0x00
|
||||
# CHECK: add %r17, 0x0, %r21
|
||||
0x0a 0xc4 0x12 0x34
|
||||
# CHECK: add %r17, 0x1234, %r21
|
||||
0x0a 0xc5 0x12 0x34
|
||||
# CHECK: add %r17, 0x12340000, %r21
|
||||
0x0a 0xc6 0x00 0x00
|
||||
# CHECK: add.f %r17, 0x0, %r21
|
||||
0x0a 0xc6 0x12 0x34
|
||||
# CHECK: add.f %r17, 0x1234, %r21
|
||||
0x0a 0xc7 0x12 0x34
|
||||
# CHECK: add.f %r17, 0x12340000, %r21
|
||||
0xca 0xc4 0x90 0x00
|
||||
# CHECK: add %r17, %r18, %r21
|
||||
0xca 0xc6 0x90 0x00
|
||||
# CHECK: add.f %r17, %r18, %r21
|
||||
0xca 0xc4 0x91 0x00
|
||||
# CHECK: addc %r17, %r18, %r21
|
||||
0xca 0xc6 0x91 0x00
|
||||
# CHECK: addc.f %r17, %r18, %r21
|
||||
0x1a 0xc4 0x00 0x00
|
||||
# CHECK: addc %r17, 0x0, %r21
|
||||
0x1a 0xc4 0x12 0x34
|
||||
# CHECK: addc %r17, 0x1234, %r21
|
||||
0x1a 0xc5 0x12 0x34
|
||||
# CHECK: addc %r17, 0x12340000, %r21
|
||||
0x1a 0xc6 0x00 0x00
|
||||
# CHECK: addc.f %r17, 0x0, %r21
|
||||
0x1a 0xc6 0x12 0x34
|
||||
# CHECK: addc.f %r17, 0x1234, %r21
|
||||
0x1a 0xc7 0x12 0x34
|
||||
# CHECK: addc.f %r17, 0x12340000, %r21
|
||||
0x4a 0xc4 0x12 0x34
|
||||
# CHECK: and %r17, 0xffff1234, %r21
|
||||
0x4a 0xc5 0x12 0x34
|
||||
# CHECK: and %r17, 0x1234ffff, %r21
|
||||
0x4a 0xc6 0x12 0x34
|
||||
# CHECK: and.f %r17, 0xffff1234, %r21
|
||||
0x4a 0xc7 0x12 0x34
|
||||
# CHECK: and.f %r17, 0x1234ffff, %r21
|
||||
0xca 0xc4 0x94 0x00
|
||||
# CHECK: and %r17, %r18, %r21
|
||||
0xca 0xc6 0x94 0x00
|
||||
# CHECK: and.f %r17, %r18, %r21
|
||||
0xe0 0x12 0x34 0x54
|
||||
# CHECK: bt 0x123454
|
||||
0xe0 0x12 0x34 0x55
|
||||
# CHECK: bf 0x123454
|
||||
0xe2 0x12 0x34 0x54
|
||||
# CHECK: bugt 0x123454
|
||||
0xe2 0x12 0x34 0x55
|
||||
# CHECK: bule 0x123454
|
||||
0xe4 0x12 0x34 0x54
|
||||
# CHECK: bult 0x123454
|
||||
0xe4 0x12 0x34 0x55
|
||||
# CHECK: buge 0x123454
|
||||
0xe6 0x12 0x34 0x54
|
||||
# CHECK: bne 0x123454
|
||||
0xe6 0x12 0x34 0x55
|
||||
# CHECK: beq 0x123454
|
||||
0xe8 0x12 0x34 0x54
|
||||
# CHECK: bvc 0x123454
|
||||
0xe8 0x12 0x34 0x55
|
||||
# CHECK: bvs 0x123454
|
||||
0xea 0x12 0x34 0x54
|
||||
# CHECK: bpl 0x123454
|
||||
0xea 0x12 0x34 0x55
|
||||
# CHECK: bmi 0x123454
|
||||
0xec 0x12 0x34 0x54
|
||||
# CHECK: bge 0x123454
|
||||
0xec 0x12 0x34 0x55
|
||||
# CHECK: blt 0x123454
|
||||
0xee 0x12 0x34 0x54
|
||||
# CHECK: bgt 0x123454
|
||||
0xc1 0x00 0x9d 0x00
|
||||
# CHECK: bt %r19
|
||||
0xe1 0x00 0x56 0x7a
|
||||
# CHECK: bt.r 0x5678
|
||||
0xe1 0x00 0x56 0x7b
|
||||
# CHECK: bf.r 0x5678
|
||||
0xe3 0x00 0x56 0x7a
|
||||
# CHECK: bugt.r 0x5678
|
||||
0xe3 0x00 0x56 0x7b
|
||||
# CHECK: bule.r 0x5678
|
||||
0xe5 0x00 0x56 0x7a
|
||||
# CHECK: bult.r 0x5678
|
||||
0xe5 0x00 0x56 0x7b
|
||||
# CHECK: buge.r 0x5678
|
||||
0xe7 0x00 0x56 0x7a
|
||||
# CHECK: bne.r 0x5678
|
||||
0xe7 0x00 0x56 0x7b
|
||||
# CHECK: beq.r 0x5678
|
||||
0xe9 0x00 0x56 0x7a
|
||||
# CHECK: bvc.r 0x5678
|
||||
0xe9 0x00 0x56 0x7b
|
||||
# CHECK: bvs.r 0x5678
|
||||
0xeb 0x00 0x56 0x7a
|
||||
# CHECK: bpl.r 0x5678
|
||||
0xeb 0x00 0x56 0x7b
|
||||
# CHECK: bmi.r 0x5678
|
||||
0xed 0x00 0x56 0x7a
|
||||
# CHECK: bge.r 0x5678
|
||||
0xed 0x00 0x56 0x7b
|
||||
# CHECK: blt.r 0x5678
|
||||
0xef 0x00 0x56 0x7a
|
||||
# CHECK: bgt.r 0x5678
|
||||
0x8a 0xc6 0x80 0x00
|
||||
# CHECK: ld -32768[%r17], %r21
|
||||
0x8a 0xc6 0xfc 0x00
|
||||
# CHECK: ld -1024[%r17], %r21
|
||||
0x8a 0xc4 0x00 0x00
|
||||
# CHECK: ld 0[%r17], %r21
|
||||
0x8a 0xc6 0x04 0x00
|
||||
# CHECK: ld 1024[%r17], %r21
|
||||
0x8a 0xc6 0x7f 0xff
|
||||
# CHECK: ld 32767[%r17], %r21
|
||||
0xaa 0xc6 0x90 0x02
|
||||
# CHECK: ld [%r17 add %r18], %r21
|
||||
0xaa 0xc6 0x90 0x03
|
||||
# CHECK: uld [%r17 add %r18], %r21
|
||||
0xfa 0xc7 0x0a 0x00
|
||||
# CHECK: ld.h -512[%r17], %r21
|
||||
0xfa 0xc7 0x0b 0xf3
|
||||
# CHECK: ld.h -13[%r17], %r21
|
||||
0xfa 0xc7 0x08 0x12
|
||||
# CHECK: ld.h 18[%r17], %r21
|
||||
0xfa 0xc7 0x09 0xff
|
||||
# CHECK: ld.h 511[%r17], %r21
|
||||
0xfa 0xc7 0x4a 0x00
|
||||
# CHECK: ld.b -512[%r17], %r21
|
||||
0xfa 0xc7 0x4b 0xf3
|
||||
# CHECK: ld.b -13[%r17], %r21
|
||||
0xfa 0xc7 0x48 0x12
|
||||
# CHECK: ld.b 18[%r17], %r21
|
||||
0xfa 0xc7 0x49 0xff
|
||||
# CHECK: ld.b 511[%r17], %r21
|
||||
0xfa 0xc7 0x1a 0x00
|
||||
# CHECK: uld.h -512[%r17], %r21
|
||||
0xfa 0xc7 0x1b 0xf3
|
||||
# CHECK: uld.h -13[%r17], %r21
|
||||
0xfa 0xc7 0x18 0x12
|
||||
# CHECK: uld.h 18[%r17], %r21
|
||||
0xfa 0xc7 0x19 0xff
|
||||
# CHECK: uld.h 511[%r17], %r21
|
||||
0xfa 0xc7 0x5a 0x00
|
||||
# CHECK: uld.b -512[%r17], %r21
|
||||
0xfa 0xc7 0x5b 0xf3
|
||||
# CHECK: uld.b -13[%r17], %r21
|
||||
0xfa 0xc7 0x58 0x12
|
||||
# CHECK: uld.b 18[%r17], %r21
|
||||
0xfa 0xc7 0x59 0xff
|
||||
# CHECK: uld.b 511[%r17], %r21
|
||||
0x8a 0xc7 0x80 0x00
|
||||
# CHECK: ld -32768[*%r17], %r21
|
||||
0x8a 0xc7 0xfc 0x00
|
||||
# CHECK: ld -1024[*%r17], %r21
|
||||
0x8a 0xc7 0x04 0x00
|
||||
# CHECK: ld 1024[*%r17], %r21
|
||||
0x8a 0xc7 0x7f 0xff
|
||||
# CHECK: ld 32767[*%r17], %r21
|
||||
0x8a 0xc7 0xff 0xfc
|
||||
# CHECK: ld [--%r17], %r21
|
||||
0x8a 0xc7 0x00 0x04
|
||||
# CHECK: ld [++%r17], %r21
|
||||
0xfa 0xc7 0x0f 0xfe
|
||||
# CHECK: ld.h [--%r17], %r21
|
||||
0xfa 0xc7 0x0c 0x02
|
||||
# CHECK: ld.h [++%r17], %r21
|
||||
0xfa 0xc7 0x1f 0xfe
|
||||
# CHECK: uld.h [--%r17], %r21
|
||||
0xfa 0xc7 0x1c 0x02
|
||||
# CHECK: uld.h [++%r17], %r21
|
||||
0xfa 0xc7 0x4f 0xff
|
||||
# CHECK: ld.b [--%r17], %r21
|
||||
0xfa 0xc7 0x4c 0x01
|
||||
# CHECK: ld.b [++%r17], %r21
|
||||
0xfa 0xc7 0x5f 0xff
|
||||
# CHECK: uld.b [--%r17], %r21
|
||||
0xfa 0xc7 0x5c 0x01
|
||||
# CHECK: uld.b [++%r17], %r21
|
||||
0xaa 0xc7 0x90 0x02
|
||||
# CHECK: ld [*%r17 add %r18], %r21
|
||||
0xfa 0xc7 0x0e 0x00
|
||||
# CHECK: ld.h -512[*%r17], %r21
|
||||
0xfa 0xc7 0x0f 0xf3
|
||||
# CHECK: ld.h -13[*%r17], %r21
|
||||
0xfa 0xc7 0x0c 0x12
|
||||
# CHECK: ld.h 18[*%r17], %r21
|
||||
0xfa 0xc7 0x0d 0xff
|
||||
# CHECK: ld.h 511[*%r17], %r21
|
||||
0xfa 0xc7 0x4e 0x00
|
||||
# CHECK: ld.b -512[*%r17], %r21
|
||||
0xfa 0xc7 0x4f 0xf3
|
||||
# CHECK: ld.b -13[*%r17], %r21
|
||||
0xfa 0xc7 0x4c 0x12
|
||||
# CHECK: ld.b 18[*%r17], %r21
|
||||
0xfa 0xc7 0x4d 0xff
|
||||
# CHECK: ld.b 511[*%r17], %r21
|
||||
0xfa 0xc7 0x1e 0x00
|
||||
# CHECK: uld.h -512[*%r17], %r21
|
||||
0xfa 0xc7 0x1f 0xf3
|
||||
# CHECK: uld.h -13[*%r17], %r21
|
||||
0xfa 0xc7 0x1c 0x12
|
||||
# CHECK: uld.h 18[*%r17], %r21
|
||||
0xfa 0xc7 0x1d 0xff
|
||||
# CHECK: uld.h 511[*%r17], %r21
|
||||
0xfa 0xc7 0x5e 0x00
|
||||
# CHECK: uld.b -512[*%r17], %r21
|
||||
0xfa 0xc7 0x5f 0xf3
|
||||
# CHECK: uld.b -13[*%r17], %r21
|
||||
0xfa 0xc7 0x5c 0x12
|
||||
# CHECK: uld.b 18[*%r17], %r21
|
||||
0xfa 0xc7 0x5d 0xff
|
||||
# CHECK: uld.b 511[*%r17], %r21
|
||||
0x8a 0xc5 0x80 0x00
|
||||
# CHECK: ld -32768[%r17*], %r21
|
||||
0x8a 0xc5 0xfc 0x00
|
||||
# CHECK: ld -1024[%r17*], %r21
|
||||
0x8a 0xc5 0x04 0x00
|
||||
# CHECK: ld 1024[%r17*], %r21
|
||||
0x8a 0xc5 0x7f 0xff
|
||||
# CHECK: ld 32767[%r17*], %r21
|
||||
0x8a 0xc5 0xff 0xfc
|
||||
# CHECK: ld [%r17--], %r21
|
||||
0x8a 0xc5 0x00 0x04
|
||||
# CHECK: ld [%r17++], %r21
|
||||
0xfa 0xc7 0x07 0xfe
|
||||
# CHECK: ld.h [%r17--], %r21
|
||||
0xfa 0xc7 0x04 0x02
|
||||
# CHECK: ld.h [%r17++], %r21
|
||||
0xfa 0xc7 0x17 0xfe
|
||||
# CHECK: uld.h [%r17--], %r21
|
||||
0xfa 0xc7 0x14 0x02
|
||||
# CHECK: uld.h [%r17++], %r21
|
||||
0xfa 0xc7 0x47 0xff
|
||||
# CHECK: ld.b [%r17--], %r21
|
||||
0xfa 0xc7 0x44 0x01
|
||||
# CHECK: ld.b [%r17++], %r21
|
||||
0xfa 0xc7 0x57 0xff
|
||||
# CHECK: uld.b [%r17--], %r21
|
||||
0xfa 0xc7 0x54 0x01
|
||||
# CHECK: uld.b [%r17++], %r21
|
||||
0xaa 0xc5 0x90 0x02
|
||||
# CHECK: ld [%r17* add %r18], %r21
|
||||
0xfa 0xc7 0x06 0x00
|
||||
# CHECK: ld.h -512[%r17*], %r21
|
||||
0xfa 0xc7 0x07 0xf3
|
||||
# CHECK: ld.h -13[%r17*], %r21
|
||||
0xfa 0xc7 0x04 0x12
|
||||
# CHECK: ld.h 18[%r17*], %r21
|
||||
0xfa 0xc7 0x05 0xff
|
||||
# CHECK: ld.h 511[%r17*], %r21
|
||||
0xfa 0xc7 0x46 0x00
|
||||
# CHECK: ld.b -512[%r17*], %r21
|
||||
0xfa 0xc7 0x47 0xf3
|
||||
# CHECK: ld.b -13[%r17*], %r21
|
||||
0xfa 0xc7 0x44 0x12
|
||||
# CHECK: ld.b 18[%r17*], %r21
|
||||
0xfa 0xc7 0x45 0xff
|
||||
# CHECK: ld.b 511[%r17*], %r21
|
||||
0xfa 0xc7 0x16 0x00
|
||||
# CHECK: uld.h -512[%r17*], %r21
|
||||
0xfa 0xc7 0x17 0xf3
|
||||
# CHECK: uld.h -13[%r17*], %r21
|
||||
0xfa 0xc7 0x14 0x12
|
||||
# CHECK: uld.h 18[%r17*], %r21
|
||||
0xfa 0xc7 0x15 0xff
|
||||
# CHECK: uld.h 511[%r17*], %r21
|
||||
0xfa 0xc7 0x56 0x00
|
||||
# CHECK: uld.b -512[%r17*], %r21
|
||||
0xfa 0xc7 0x57 0xf3
|
||||
# CHECK: uld.b -13[%r17*], %r21
|
||||
0xfa 0xc7 0x54 0x12
|
||||
# CHECK: uld.b 18[%r17*], %r21
|
||||
0xfa 0xc7 0x55 0xff
|
||||
# CHECK: uld.b 511[%r17*], %r21
|
||||
0xaa 0xc6 0x90 0x02
|
||||
# CHECK: ld [%r17 add %r18], %r21
|
||||
0xaa 0xc6 0x91 0x02
|
||||
# CHECK: ld [%r17 addc %r18], %r21
|
||||
0xaa 0xc6 0x92 0x02
|
||||
# CHECK: ld [%r17 sub %r18], %r21
|
||||
0xaa 0xc6 0x93 0x02
|
||||
# CHECK: ld [%r17 subb %r18], %r21
|
||||
0xaa 0xc6 0x94 0x02
|
||||
# CHECK: ld [%r17 and %r18], %r21
|
||||
0xaa 0xc6 0x95 0x02
|
||||
# CHECK: ld [%r17 or %r18], %r21
|
||||
0xaa 0xc6 0x96 0x02
|
||||
# CHECK: ld [%r17 xor %r18], %r21
|
||||
0xaa 0xc6 0x97 0x82
|
||||
# CHECK: ld [%r17 sh %r18], %r21
|
||||
0xaa 0xc6 0x97 0xc2
|
||||
# CHECK: ld [%r17 sha %r18], %r21
|
||||
0xaa 0xc7 0x90 0x02
|
||||
# CHECK: ld [*%r17 add %r18], %r21
|
||||
0xaa 0xc7 0x91 0x02
|
||||
# CHECK: ld [*%r17 addc %r18], %r21
|
||||
0xaa 0xc7 0x92 0x02
|
||||
# CHECK: ld [*%r17 sub %r18], %r21
|
||||
0xaa 0xc7 0x93 0x02
|
||||
# CHECK: ld [*%r17 subb %r18], %r21
|
||||
0xaa 0xc7 0x94 0x02
|
||||
# CHECK: ld [*%r17 and %r18], %r21
|
||||
0xaa 0xc7 0x95 0x02
|
||||
# CHECK: ld [*%r17 or %r18], %r21
|
||||
0xaa 0xc7 0x96 0x02
|
||||
# CHECK: ld [*%r17 xor %r18], %r21
|
||||
0xaa 0xc7 0x97 0x82
|
||||
# CHECK: ld [*%r17 sh %r18], %r21
|
||||
0xaa 0xc7 0x97 0xc2
|
||||
# CHECK: ld [*%r17 sha %r18], %r21
|
||||
0xaa 0xc5 0x90 0x02
|
||||
# CHECK: ld [%r17* add %r18], %r21
|
||||
0xaa 0xc5 0x91 0x02
|
||||
# CHECK: ld [%r17* addc %r18], %r21
|
||||
0xaa 0xc5 0x92 0x02
|
||||
# CHECK: ld [%r17* sub %r18], %r21
|
||||
0xaa 0xc5 0x93 0x02
|
||||
# CHECK: ld [%r17* subb %r18], %r21
|
||||
0xaa 0xc5 0x94 0x02
|
||||
# CHECK: ld [%r17* and %r18], %r21
|
||||
0xaa 0xc5 0x95 0x02
|
||||
# CHECK: ld [%r17* or %r18], %r21
|
||||
0xaa 0xc5 0x96 0x02
|
||||
# CHECK: ld [%r17* xor %r18], %r21
|
||||
0xaa 0xc5 0x97 0x82
|
||||
# CHECK: ld [%r17* sh %r18], %r21
|
||||
0xaa 0xc5 0x97 0xc2
|
||||
# CHECK: ld [%r17* sha %r18], %r21
|
||||
0xfa 0x84 0x23 0x44
|
||||
# CHECK: ld [0x12344], %r21
|
||||
0xda 0xc4 0x00 0x02
|
||||
# CHECK: leadz %r17, %r21
|
||||
0x08 0x80 0x00 0x00
|
||||
# CHECK: mov 0x0, %r17
|
||||
0x08 0x80 0x12 0x34
|
||||
# CHECK: mov 0x1234, %r17
|
||||
0x08 0x81 0x12 0x34
|
||||
# CHECK: mov 0x12340000, %r17
|
||||
0x08 0x81 0xaa 0xaa
|
||||
# CHECK: mov 0xaaaa0000, %r17
|
||||
0xc8 0xc8 0x00 0x00
|
||||
# CHECK: mov %r18, %r17
|
||||
0xf8 0x86 0x23 0x44
|
||||
# CHECK: mov 0x12344, %r17
|
||||
0x48 0x84 0x12 0x34
|
||||
# CHECK: mov 0xffff1234, %r17
|
||||
0x48 0x85 0x12 0x34
|
||||
# CHECK: mov 0x1234ffff, %r17
|
||||
0x00 0x00 0x00 0x01
|
||||
# CHECK: nop
|
||||
0x5a 0xc4 0x00 0x00
|
||||
# CHECK: or %r17, 0x0, %r21
|
||||
0x5a 0xc4 0x12 0x34
|
||||
# CHECK: or %r17, 0x1234, %r21
|
||||
0x5a 0xc5 0x12 0x34
|
||||
# CHECK: or %r17, 0x12340000, %r21
|
||||
0x5a 0xc6 0x00 0x00
|
||||
# CHECK: or.f %r17, 0x0, %r21
|
||||
0x5a 0xc6 0x12 0x34
|
||||
# CHECK: or.f %r17, 0x1234, %r21
|
||||
0x5a 0xc7 0x12 0x34
|
||||
# CHECK: or.f %r17, 0x12340000, %r21
|
||||
0xca 0xc4 0x95 0x00
|
||||
# CHECK: or %r17, %r18, %r21
|
||||
0xca 0xc6 0x95 0x00
|
||||
# CHECK: or.f %r17, %r18, %r21
|
||||
0xda 0xc4 0x00 0x01
|
||||
# CHECK: popc %r17, %r21
|
||||
0xe0 0x54 0x00 0x02
|
||||
# CHECK: st %r21
|
||||
0xe2 0x54 0x00 0x02
|
||||
# CHECK: sugt %r21
|
||||
0xe2 0x54 0x00 0x03
|
||||
# CHECK: sule %r21
|
||||
0xe4 0x54 0x00 0x02
|
||||
# CHECK: sult %r21
|
||||
0xe4 0x54 0x00 0x03
|
||||
# CHECK: suge %r21
|
||||
0xe6 0x54 0x00 0x02
|
||||
# CHECK: sne %r21
|
||||
0xe6 0x54 0x00 0x03
|
||||
# CHECK: seq %r21
|
||||
0xe8 0x54 0x00 0x02
|
||||
# CHECK: svc %r21
|
||||
0xe8 0x54 0x00 0x03
|
||||
# CHECK: svs %r21
|
||||
0xea 0x54 0x00 0x02
|
||||
# CHECK: spl %r21
|
||||
0xea 0x54 0x00 0x03
|
||||
# CHECK: smi %r21
|
||||
0xec 0x54 0x00 0x02
|
||||
# CHECK: sge %r21
|
||||
0xec 0x54 0x00 0x03
|
||||
# CHECK: slt %r21
|
||||
0xee 0x54 0x00 0x02
|
||||
# CHECK: sgt %r21
|
||||
0x7a 0xc4 0xff 0xe1
|
||||
# CHECK: sh %r17, -0x1f, %r21
|
||||
0x7a 0xc4 0xff 0xfb
|
||||
# CHECK: sh %r17, -0x5, %r21
|
||||
0x7a 0xc4 0x00 0x02
|
||||
# CHECK: sh %r17, 0x2, %r21
|
||||
0x7a 0xc4 0x00 0x1f
|
||||
# CHECK: sh %r17, 0x1f, %r21
|
||||
0x7a 0xc6 0xff 0xe1
|
||||
# CHECK: sh.f %r17, -0x1f, %r21
|
||||
0x7a 0xc6 0xff 0xfb
|
||||
# CHECK: sh.f %r17, -0x5, %r21
|
||||
0x7a 0xc6 0x00 0x02
|
||||
# CHECK: sh.f %r17, 0x2, %r21
|
||||
0x7a 0xc6 0x00 0x1f
|
||||
# CHECK: sh.f %r17, 0x1f, %r21
|
||||
0xca 0xc4 0x97 0x80
|
||||
# CHECK: sh %r17, %r18, %r21
|
||||
0xca 0xc6 0x97 0x80
|
||||
# CHECK: sh.f %r17, %r18, %r21
|
||||
0x7a 0xc5 0xff 0xe1
|
||||
# CHECK: sha %r17, -0x1f, %r21
|
||||
0x7a 0xc5 0xff 0xfb
|
||||
# CHECK: sha %r17, -0x5, %r21
|
||||
0x7a 0xc5 0x00 0x02
|
||||
# CHECK: sha %r17, 0x2, %r21
|
||||
0x7a 0xc5 0x00 0x1f
|
||||
# CHECK: sha %r17, 0x1f, %r21
|
||||
0x7a 0xc7 0xff 0xe1
|
||||
# CHECK: sha.f %r17, -0x1f, %r21
|
||||
0x7a 0xc7 0xff 0xfb
|
||||
# CHECK: sha.f %r17, -0x5, %r21
|
||||
0x7a 0xc7 0x00 0x02
|
||||
# CHECK: sha.f %r17, 0x2, %r21
|
||||
0x7a 0xc7 0x00 0x1f
|
||||
# CHECK: sha.f %r17, 0x1f, %r21
|
||||
0xca 0xc4 0x97 0xc0
|
||||
# CHECK: sha %r17, %r18, %r21
|
||||
0xca 0xc6 0x97 0xc0
|
||||
# CHECK: sha.f %r17, %r18, %r21
|
||||
0x98 0xce 0x80 0x00
|
||||
# CHECK: st %r17, -32768[%r19]
|
||||
0x98 0xce 0xfc 0x00
|
||||
# CHECK: st %r17, -1024[%r19]
|
||||
0x98 0xcc 0x00 0x00
|
||||
# CHECK: st %r17, 0[%r19]
|
||||
0x98 0xce 0x04 0x00
|
||||
# CHECK: st %r17, 1024[%r19]
|
||||
0x98 0xce 0x7f 0xff
|
||||
# CHECK: st %r17, 32767[%r19]
|
||||
0xf8 0xcf 0x2a 0x00
|
||||
# CHECK: st.h %r17, -512[%r19]
|
||||
0xf8 0xcf 0x2b 0xf3
|
||||
# CHECK: st.h %r17, -13[%r19]
|
||||
0xf8 0xcf 0x28 0x12
|
||||
# CHECK: st.h %r17, 18[%r19]
|
||||
0xf8 0xcf 0x29 0xff
|
||||
# CHECK: st.h %r17, 511[%r19]
|
||||
0xf8 0xcf 0x6a 0x00
|
||||
# CHECK: st.b %r17, -512[%r19]
|
||||
0xf8 0xcf 0x6b 0xf3
|
||||
# CHECK: st.b %r17, -13[%r19]
|
||||
0xf8 0xcf 0x68 0x12
|
||||
# CHECK: st.b %r17, 18[%r19]
|
||||
0xf8 0xcf 0x69 0xff
|
||||
# CHECK: st.b %r17, 511[%r19]
|
||||
0xb8 0xce 0x90 0x02
|
||||
# CHECK: st %r17, [%r19 add %r18]
|
||||
0xb8 0xce 0x90 0x00
|
||||
# CHECK: st.h %r17, [%r19 add %r18]
|
||||
0xb8 0xce 0x90 0x04
|
||||
# CHECK: st.b %r17, [%r19 add %r18]
|
||||
0x98 0xcf 0x80 0x00
|
||||
# CHECK: st %r17, -32768[*%r19]
|
||||
0x98 0xcf 0xfc 0x00
|
||||
# CHECK: st %r17, -1024[*%r19]
|
||||
0x98 0xcf 0x04 0x00
|
||||
# CHECK: st %r17, 1024[*%r19]
|
||||
0x98 0xcf 0x7f 0xff
|
||||
# CHECK: st %r17, 32767[*%r19]
|
||||
0xf8 0xcf 0x2e 0x00
|
||||
# CHECK: st.h %r17, -512[*%r19]
|
||||
0xf8 0xcf 0x2f 0xf3
|
||||
# CHECK: st.h %r17, -13[*%r19]
|
||||
0xf8 0xcf 0x2c 0x12
|
||||
# CHECK: st.h %r17, 18[*%r19]
|
||||
0xf8 0xcf 0x2d 0xff
|
||||
# CHECK: st.h %r17, 511[*%r19]
|
||||
0xf8 0xcf 0x6e 0x00
|
||||
# CHECK: st.b %r17, -512[*%r19]
|
||||
0xf8 0xcf 0x6f 0xf3
|
||||
# CHECK: st.b %r17, -13[*%r19]
|
||||
0xf8 0xcf 0x6c 0x12
|
||||
# CHECK: st.b %r17, 18[*%r19]
|
||||
0xf8 0xcf 0x6d 0xff
|
||||
# CHECK: st.b %r17, 511[*%r19]
|
||||
0x98 0xcf 0xff 0xfc
|
||||
# CHECK: st %r17, [--%r19]
|
||||
0x98 0xcf 0x00 0x04
|
||||
# CHECK: st %r17, [++%r19]
|
||||
0xf8 0xcf 0x2f 0xfe
|
||||
# CHECK: st.h %r17, [--%r19]
|
||||
0xf8 0xcf 0x2c 0x02
|
||||
# CHECK: st.h %r17, [++%r19]
|
||||
0xf8 0xcf 0x6f 0xff
|
||||
# CHECK: st.b %r17, [--%r19]
|
||||
0xf8 0xcf 0x6c 0x01
|
||||
# CHECK: st.b %r17, [++%r19]
|
||||
0xb8 0xcf 0x90 0x02
|
||||
# CHECK: st %r17, [*%r19 add %r18]
|
||||
0xb8 0xcf 0x90 0x00
|
||||
# CHECK: st.h %r17, [*%r19 add %r18]
|
||||
0xb8 0xcf 0x90 0x04
|
||||
# CHECK: st.b %r17, [*%r19 add %r18]
|
||||
0x98 0xcd 0x80 0x00
|
||||
# CHECK: st %r17, -32768[%r19*]
|
||||
0x98 0xcd 0xfc 0x00
|
||||
# CHECK: st %r17, -1024[%r19*]
|
||||
0x98 0xcd 0x04 0x00
|
||||
# CHECK: st %r17, 1024[%r19*]
|
||||
0x98 0xcd 0x7f 0xff
|
||||
# CHECK: st %r17, 32767[%r19*]
|
||||
0xf8 0xcf 0x26 0x00
|
||||
# CHECK: st.h %r17, -512[%r19*]
|
||||
0xf8 0xcf 0x27 0xf3
|
||||
# CHECK: st.h %r17, -13[%r19*]
|
||||
0xf8 0xcf 0x24 0x12
|
||||
# CHECK: st.h %r17, 18[%r19*]
|
||||
0xf8 0xcf 0x25 0xff
|
||||
# CHECK: st.h %r17, 511[%r19*]
|
||||
0xf8 0xcf 0x66 0x00
|
||||
# CHECK: st.b %r17, -512[%r19*]
|
||||
0xf8 0xcf 0x67 0xf3
|
||||
# CHECK: st.b %r17, -13[%r19*]
|
||||
0xf8 0xcf 0x64 0x12
|
||||
# CHECK: st.b %r17, 18[%r19*]
|
||||
0xf8 0xcf 0x65 0xff
|
||||
# CHECK: st.b %r17, 511[%r19*]
|
||||
0x98 0xcd 0xff 0xfc
|
||||
# CHECK: st %r17, [%r19--]
|
||||
0x98 0xcd 0x00 0x04
|
||||
# CHECK: st %r17, [%r19++]
|
||||
0xf8 0xcf 0x27 0xfe
|
||||
# CHECK: st.h %r17, [%r19--]
|
||||
0xf8 0xcf 0x24 0x02
|
||||
# CHECK: st.h %r17, [%r19++]
|
||||
0xf8 0xcf 0x67 0xff
|
||||
# CHECK: st.b %r17, [%r19--]
|
||||
0xf8 0xcf 0x64 0x01
|
||||
# CHECK: st.b %r17, [%r19++]
|
||||
0xb8 0xcd 0x90 0x02
|
||||
# CHECK: st %r17, [%r19* add %r18]
|
||||
0xb8 0xcd 0x90 0x00
|
||||
# CHECK: st.h %r17, [%r19* add %r18]
|
||||
0xb8 0xcd 0x90 0x04
|
||||
# CHECK: st.b %r17, [%r19* add %r18]
|
||||
0xba 0xc6 0x90 0x02
|
||||
# CHECK: st %r21, [%r17 add %r18]
|
||||
0xba 0xc6 0x91 0x02
|
||||
# CHECK: st %r21, [%r17 addc %r18]
|
||||
0xba 0xc6 0x92 0x02
|
||||
# CHECK: st %r21, [%r17 sub %r18]
|
||||
0xba 0xc6 0x93 0x02
|
||||
# CHECK: st %r21, [%r17 subb %r18]
|
||||
0xba 0xc6 0x94 0x02
|
||||
# CHECK: st %r21, [%r17 and %r18]
|
||||
0xba 0xc6 0x95 0x02
|
||||
# CHECK: st %r21, [%r17 or %r18]
|
||||
0xba 0xc6 0x96 0x02
|
||||
# CHECK: st %r21, [%r17 xor %r18]
|
||||
0xba 0xc6 0x97 0x82
|
||||
# CHECK: st %r21, [%r17 sh %r18]
|
||||
0xba 0xc6 0x97 0xc2
|
||||
# CHECK: st %r21, [%r17 sha %r18]
|
||||
0xba 0xc6 0x90 0x00
|
||||
# CHECK: st.h %r21, [%r17 add %r18]
|
||||
0xba 0xc6 0x91 0x00
|
||||
# CHECK: st.h %r21, [%r17 addc %r18]
|
||||
0xba 0xc6 0x92 0x00
|
||||
# CHECK: st.h %r21, [%r17 sub %r18]
|
||||
0xba 0xc6 0x93 0x00
|
||||
# CHECK: st.h %r21, [%r17 subb %r18]
|
||||
0xba 0xc6 0x94 0x00
|
||||
# CHECK: st.h %r21, [%r17 and %r18]
|
||||
0xba 0xc6 0x95 0x00
|
||||
# CHECK: st.h %r21, [%r17 or %r18]
|
||||
0xba 0xc6 0x96 0x00
|
||||
# CHECK: st.h %r21, [%r17 xor %r18]
|
||||
0xba 0xc6 0x97 0x80
|
||||
# CHECK: st.h %r21, [%r17 sh %r18]
|
||||
0xba 0xc6 0x97 0xc0
|
||||
# CHECK: st.h %r21, [%r17 sha %r18]
|
||||
0xba 0xc6 0x90 0x04
|
||||
# CHECK: st.b %r21, [%r17 add %r18]
|
||||
0xba 0xc6 0x91 0x04
|
||||
# CHECK: st.b %r21, [%r17 addc %r18]
|
||||
0xba 0xc6 0x92 0x04
|
||||
# CHECK: st.b %r21, [%r17 sub %r18]
|
||||
0xba 0xc6 0x93 0x04
|
||||
# CHECK: st.b %r21, [%r17 subb %r18]
|
||||
0xba 0xc6 0x94 0x04
|
||||
# CHECK: st.b %r21, [%r17 and %r18]
|
||||
0xba 0xc6 0x95 0x04
|
||||
# CHECK: st.b %r21, [%r17 or %r18]
|
||||
0xba 0xc6 0x96 0x04
|
||||
# CHECK: st.b %r21, [%r17 xor %r18]
|
||||
0xba 0xc6 0x97 0x84
|
||||
# CHECK: st.b %r21, [%r17 sh %r18]
|
||||
0xba 0xc6 0x97 0xc4
|
||||
# CHECK: st.b %r21, [%r17 sha %r18]
|
||||
0xba 0xc7 0x90 0x02
|
||||
# CHECK: st %r21, [*%r17 add %r18]
|
||||
0xba 0xc7 0x91 0x02
|
||||
# CHECK: st %r21, [*%r17 addc %r18]
|
||||
0xba 0xc7 0x92 0x02
|
||||
# CHECK: st %r21, [*%r17 sub %r18]
|
||||
0xba 0xc7 0x93 0x02
|
||||
# CHECK: st %r21, [*%r17 subb %r18]
|
||||
0xba 0xc7 0x94 0x02
|
||||
# CHECK: st %r21, [*%r17 and %r18]
|
||||
0xba 0xc7 0x95 0x02
|
||||
# CHECK: st %r21, [*%r17 or %r18]
|
||||
0xba 0xc7 0x96 0x02
|
||||
# CHECK: st %r21, [*%r17 xor %r18]
|
||||
0xba 0xc7 0x97 0xc2
|
||||
# CHECK: st %r21, [*%r17 sha %r18]
|
||||
0xba 0xc7 0x90 0x00
|
||||
# CHECK: st.h %r21, [*%r17 add %r18]
|
||||
0xba 0xc7 0x91 0x00
|
||||
# CHECK: st.h %r21, [*%r17 addc %r18]
|
||||
0xba 0xc7 0x92 0x00
|
||||
# CHECK: st.h %r21, [*%r17 sub %r18]
|
||||
0xba 0xc7 0x93 0x00
|
||||
# CHECK: st.h %r21, [*%r17 subb %r18]
|
||||
0xba 0xc7 0x94 0x00
|
||||
# CHECK: st.h %r21, [*%r17 and %r18]
|
||||
0xba 0xc7 0x95 0x00
|
||||
# CHECK: st.h %r21, [*%r17 or %r18]
|
||||
0xba 0xc7 0x96 0x00
|
||||
# CHECK: st.h %r21, [*%r17 xor %r18]
|
||||
0xba 0xc7 0x97 0xc0
|
||||
# CHECK: st.h %r21, [*%r17 sha %r18]
|
||||
0xba 0xc7 0x90 0x04
|
||||
# CHECK: st.b %r21, [*%r17 add %r18]
|
||||
0xba 0xc7 0x91 0x04
|
||||
# CHECK: st.b %r21, [*%r17 addc %r18]
|
||||
0xba 0xc7 0x92 0x04
|
||||
# CHECK: st.b %r21, [*%r17 sub %r18]
|
||||
0xba 0xc7 0x93 0x04
|
||||
# CHECK: st.b %r21, [*%r17 subb %r18]
|
||||
0xba 0xc7 0x94 0x04
|
||||
# CHECK: st.b %r21, [*%r17 and %r18]
|
||||
0xba 0xc7 0x95 0x04
|
||||
# CHECK: st.b %r21, [*%r17 or %r18]
|
||||
0xba 0xc7 0x96 0x04
|
||||
# CHECK: st.b %r21, [*%r17 xor %r18]
|
||||
0xba 0xc7 0x97 0xc4
|
||||
# CHECK: st.b %r21, [*%r17 sha %r18]
|
||||
0xba 0xc5 0x90 0x02
|
||||
# CHECK: st %r21, [%r17* add %r18]
|
||||
0xba 0xc5 0x91 0x02
|
||||
# CHECK: st %r21, [%r17* addc %r18]
|
||||
0xba 0xc5 0x92 0x02
|
||||
# CHECK: st %r21, [%r17* sub %r18]
|
||||
0xba 0xc5 0x93 0x02
|
||||
# CHECK: st %r21, [%r17* subb %r18]
|
||||
0xba 0xc5 0x94 0x02
|
||||
# CHECK: st %r21, [%r17* and %r18]
|
||||
0xba 0xc5 0x95 0x02
|
||||
# CHECK: st %r21, [%r17* or %r18]
|
||||
0xba 0xc5 0x96 0x02
|
||||
# CHECK: st %r21, [%r17* xor %r18]
|
||||
0xba 0xc5 0x97 0x82
|
||||
# CHECK: st %r21, [%r17* sh %r18]
|
||||
0xba 0xc5 0x97 0xc2
|
||||
# CHECK: st %r21, [%r17* sha %r18]
|
||||
0xba 0xc5 0x90 0x00
|
||||
# CHECK: st.h %r21, [%r17* add %r18]
|
||||
0xba 0xc5 0x91 0x00
|
||||
# CHECK: st.h %r21, [%r17* addc %r18]
|
||||
0xba 0xc5 0x92 0x00
|
||||
# CHECK: st.h %r21, [%r17* sub %r18]
|
||||
0xba 0xc5 0x93 0x00
|
||||
# CHECK: st.h %r21, [%r17* subb %r18]
|
||||
0xba 0xc5 0x94 0x00
|
||||
# CHECK: st.h %r21, [%r17* and %r18]
|
||||
0xba 0xc5 0x95 0x00
|
||||
# CHECK: st.h %r21, [%r17* or %r18]
|
||||
0xba 0xc5 0x96 0x00
|
||||
# CHECK: st.h %r21, [%r17* xor %r18]
|
||||
0xba 0xc5 0x97 0x80
|
||||
# CHECK: st.h %r21, [%r17* sh %r18]
|
||||
0xba 0xc5 0x97 0xc0
|
||||
# CHECK: st.h %r21, [%r17* sha %r18]
|
||||
0xba 0xc5 0x90 0x04
|
||||
# CHECK: st.b %r21, [%r17* add %r18]
|
||||
0xba 0xc5 0x91 0x04
|
||||
# CHECK: st.b %r21, [%r17* addc %r18]
|
||||
0xba 0xc5 0x92 0x04
|
||||
# CHECK: st.b %r21, [%r17* sub %r18]
|
||||
0xba 0xc5 0x93 0x04
|
||||
# CHECK: st.b %r21, [%r17* subb %r18]
|
||||
0xba 0xc5 0x94 0x04
|
||||
# CHECK: st.b %r21, [%r17* and %r18]
|
||||
0xba 0xc5 0x95 0x04
|
||||
# CHECK: st.b %r21, [%r17* or %r18]
|
||||
0xba 0xc5 0x96 0x04
|
||||
# CHECK: st.b %r21, [%r17* xor %r18]
|
||||
0xba 0xc5 0x97 0x84
|
||||
# CHECK: st.b %r21, [%r17* sh %r18]
|
||||
0xba 0xc5 0x97 0xc4
|
||||
# CHECK: st.b %r21, [%r17* sha %r18]
|
||||
0xfa 0x85 0x23 0x44
|
||||
# CHECK: st %r21, [0x12344]
|
||||
0x2a 0xc4 0x00 0x00
|
||||
# CHECK: sub %r17, 0x0, %r21
|
||||
0x2a 0xc4 0x12 0x34
|
||||
# CHECK: sub %r17, 0x1234, %r21
|
||||
0x2a 0xc5 0x12 0x34
|
||||
# CHECK: sub %r17, 0x12340000, %r21
|
||||
0x2a 0xc6 0x00 0x00
|
||||
# CHECK: sub.f %r17, 0x0, %r21
|
||||
0x2a 0xc6 0x12 0x34
|
||||
# CHECK: sub.f %r17, 0x1234, %r21
|
||||
0x2a 0xc7 0x12 0x34
|
||||
# CHECK: sub.f %r17, 0x12340000, %r21
|
||||
0xca 0xc4 0x92 0x00
|
||||
# CHECK: sub %r17, %r18, %r21
|
||||
0xca 0xc6 0x92 0x00
|
||||
# CHECK: sub.f %r17, %r18, %r21
|
||||
0x3a 0xc4 0x00 0x00
|
||||
# CHECK: subb %r17, 0x0, %r21
|
||||
0x3a 0xc4 0x12 0x34
|
||||
# CHECK: subb %r17, 0x1234, %r21
|
||||
0x3a 0xc5 0x12 0x34
|
||||
# CHECK: subb %r17, 0x12340000, %r21
|
||||
0x3a 0xc6 0x00 0x00
|
||||
# CHECK: subb.f %r17, 0x0, %r21
|
||||
0x3a 0xc6 0x12 0x34
|
||||
# CHECK: subb.f %r17, 0x1234, %r21
|
||||
0x3a 0xc7 0x12 0x34
|
||||
# CHECK: subb.f %r17, 0x12340000, %r21
|
||||
0xca 0xc4 0x93 0x00
|
||||
# CHECK: subb %r17, %r18, %r21
|
||||
0xca 0xc6 0x93 0x00
|
||||
# CHECK: subb.f %r17, %r18, %r21
|
||||
0x6a 0xc4 0x00 0x00
|
||||
# CHECK: xor %r17, 0x0, %r21
|
||||
0x6a 0xc4 0x12 0x34
|
||||
# CHECK: xor %r17, 0x1234, %r21
|
||||
0x6a 0xc5 0x12 0x34
|
||||
# CHECK: xor %r17, 0x12340000, %r21
|
||||
0x6a 0xc6 0x00 0x00
|
||||
# CHECK: xor.f %r17, 0x0, %r21
|
||||
0x6a 0xc6 0x12 0x34
|
||||
# CHECK: xor.f %r17, 0x1234, %r21
|
||||
0x6a 0xc7 0x12 0x34
|
||||
# CHECK: xor.f %r17, 0x12340000, %r21
|
||||
0xca 0xc4 0x96 0x00
|
||||
# CHECK: xor %r17, %r18, %r21
|
||||
0xca 0xc6 0x96 0x00
|
||||
# CHECK: xor.f %r17, %r18, %r21
|
3
test/MC/Lanai/lit.local.cfg
Normal file
3
test/MC/Lanai/lit.local.cfg
Normal file
@ -0,0 +1,3 @@
|
||||
if not 'Lanai' in config.root.targets:
|
||||
config.unsupported = True
|
||||
|
830
test/MC/Lanai/v11.s
Normal file
830
test/MC/Lanai/v11.s
Normal file
@ -0,0 +1,830 @@
|
||||
! RUN: llvm-mc -arch=lanai -show-encoding %s | FileCheck %s
|
||||
|
||||
add %r17, 0, %r21
|
||||
! CHECK: 0x0a,0xc4,0x00,0x00
|
||||
add %r17, 0x00001234, %r21
|
||||
! CHECK: 0x0a,0xc4,0x12,0x34
|
||||
add %r17, 0x12340000, %r21
|
||||
! CHECK: 0x0a,0xc5,0x12,0x34
|
||||
add.f %r17, 0, %r21
|
||||
! CHECK: 0x0a,0xc6,0x00,0x00
|
||||
add.f %r17, 0x00001234, %r21
|
||||
! CHECK: 0x0a,0xc6,0x12,0x34
|
||||
add.f %r17, 0x12340000, %r21
|
||||
! CHECK: 0x0a,0xc7,0x12,0x34
|
||||
add %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc4,0x90,0x00
|
||||
add.f %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc6,0x90,0x00
|
||||
addc %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc4,0x91,0x00
|
||||
addc.f %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc6,0x91,0x00
|
||||
addc %r17, 0, %r21
|
||||
! CHECK: 0x1a,0xc4,0x00,0x00
|
||||
addc %r17, 0x00001234, %r21
|
||||
! CHECK: 0x1a,0xc4,0x12,0x34
|
||||
addc %r17, 0x12340000, %r21
|
||||
! CHECK: 0x1a,0xc5,0x12,0x34
|
||||
addc.f %r17, 0, %r21
|
||||
! CHECK: 0x1a,0xc6,0x00,0x00
|
||||
addc.f %r17, 0x00001234, %r21
|
||||
! CHECK: 0x1a,0xc6,0x12,0x34
|
||||
addc.f %r17, 0x12340000, %r21
|
||||
! CHECK: 0x1a,0xc7,0x12,0x34
|
||||
and %r17, 0xffff1234, %r21
|
||||
! CHECK: 0x4a,0xc4,0x12,0x34
|
||||
and %r17, 0x1234ffff, %r21
|
||||
! CHECK: 0x4a,0xc5,0x12,0x34
|
||||
and.f %r17, 0xffff1234, %r21
|
||||
! CHECK: 0x4a,0xc6,0x12,0x34
|
||||
and.f %r17, 0x1234ffff, %r21
|
||||
! CHECK: 0x4a,0xc7,0x12,0x34
|
||||
and %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc4,0x94,0x00
|
||||
and.f %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc6,0x94,0x00
|
||||
bt 0x123454
|
||||
! CHECK: 0xe0,0x12,0x34,0x54
|
||||
bf 0x123454
|
||||
! CHECK: 0xe0,0x12,0x34,0x55
|
||||
bhi 0x123454
|
||||
! CHECK: 0xe2,0x12,0x34,0x54
|
||||
bugt 0x123454
|
||||
! CHECK: 0xe2,0x12,0x34,0x54
|
||||
bls 0x123454
|
||||
! CHECK: 0xe2,0x12,0x34,0x55
|
||||
bule 0x123454
|
||||
! CHECK: 0xe2,0x12,0x34,0x55
|
||||
bcc 0x123454
|
||||
! CHECK: 0xe4,0x12,0x34,0x54
|
||||
bult 0x123454
|
||||
! CHECK: 0xe4,0x12,0x34,0x54
|
||||
bcs 0x123454
|
||||
! CHECK: 0xe4,0x12,0x34,0x55
|
||||
buge 0x123454
|
||||
! CHECK: 0xe4,0x12,0x34,0x55
|
||||
bne 0x123454
|
||||
! CHECK: 0xe6,0x12,0x34,0x54
|
||||
beq 0x123454
|
||||
! CHECK: 0xe6,0x12,0x34,0x55
|
||||
bvc 0x123454
|
||||
! CHECK: 0xe8,0x12,0x34,0x54
|
||||
bvs 0x123454
|
||||
! CHECK: 0xe8,0x12,0x34,0x55
|
||||
bpl 0x123454
|
||||
! CHECK: 0xea,0x12,0x34,0x54
|
||||
bmi 0x123454
|
||||
! CHECK: 0xea,0x12,0x34,0x55
|
||||
bge 0x123454
|
||||
! CHECK: 0xec,0x12,0x34,0x54
|
||||
blt 0x123454
|
||||
! CHECK: 0xec,0x12,0x34,0x55
|
||||
bgt 0x123454
|
||||
! CHECK: 0xee,0x12,0x34,0x54
|
||||
bt %r19
|
||||
! CHECK: 0xc1,0x00,0x9d,0x00
|
||||
bt.r 0x5678
|
||||
! CHECK: 0xe1,0x00,0x56,0x7a
|
||||
bf.r 0x5678
|
||||
! CHECK: 0xe1,0x00,0x56,0x7b
|
||||
bhi.r 0x5678
|
||||
! CHECK: 0xe3,0x00,0x56,0x7a
|
||||
bugt.r 0x5678
|
||||
! CHECK: 0xe3,0x00,0x56,0x7a
|
||||
bls.r 0x5678
|
||||
! CHECK: 0xe3,0x00,0x56,0x7b
|
||||
bule.r 0x5678
|
||||
! CHECK: 0xe3,0x00,0x56,0x7b
|
||||
bcc.r 0x5678
|
||||
! CHECK: 0xe5,0x00,0x56,0x7a
|
||||
bult.r 0x5678
|
||||
! CHECK: 0xe5,0x00,0x56,0x7a
|
||||
bcs.r 0x5678
|
||||
! CHECK: 0xe5,0x00,0x56,0x7b
|
||||
buge.r 0x5678
|
||||
! CHECK: 0xe5,0x00,0x56,0x7b
|
||||
bne.r 0x5678
|
||||
! CHECK: 0xe7,0x00,0x56,0x7a
|
||||
beq.r 0x5678
|
||||
! CHECK: 0xe7,0x00,0x56,0x7b
|
||||
bvc.r 0x5678
|
||||
! CHECK: 0xe9,0x00,0x56,0x7a
|
||||
bvs.r 0x5678
|
||||
! CHECK: 0xe9,0x00,0x56,0x7b
|
||||
bpl.r 0x5678
|
||||
! CHECK: 0xeb,0x00,0x56,0x7a
|
||||
bmi.r 0x5678
|
||||
! CHECK: 0xeb,0x00,0x56,0x7b
|
||||
bge.r 0x5678
|
||||
! CHECK: 0xed,0x00,0x56,0x7a
|
||||
blt.r 0x5678
|
||||
! CHECK: 0xed,0x00,0x56,0x7b
|
||||
bgt.r 0x5678
|
||||
! CHECK: 0xef,0x00,0x56,0x7a
|
||||
ld -32768[%r17], %r21
|
||||
! CHECK: 0x8a,0xc6,0x80,0x00
|
||||
ld -1024[%r17], %r21
|
||||
! CHECK: 0x8a,0xc6,0xfc,0x00
|
||||
ld 0[%r17], %r21
|
||||
! CHECK: 0x8a,0xc4,0x00,0x00
|
||||
ld 1024[%r17], %r21
|
||||
! CHECK: 0x8a,0xc6,0x04,0x00
|
||||
ld 32767[%r17], %r21
|
||||
! CHECK: 0x8a,0xc6,0x7f,0xff
|
||||
uld -32768[%r17], %r21
|
||||
! CHECK: 0x8a,0xc6,0x80,0x00
|
||||
uld -1024[%r17], %r21
|
||||
! CHECK: 0x8a,0xc6,0xfc,0x00
|
||||
uld 0[%r17], %r21
|
||||
! CHECK: 0x8a,0xc4,0x00,0x00
|
||||
uld 1024[%r17], %r21
|
||||
! CHECK: 0x8a,0xc6,0x04,0x00
|
||||
uld 32767[%r17], %r21
|
||||
! CHECK: 0x8a,0xc6,0x7f,0xff
|
||||
ld %r18[%r17], %r21
|
||||
! CHECK: 0xaa,0xc6,0x90,0x02
|
||||
uld %r18[%r17], %r21
|
||||
! CHECK: 0xaa,0xc6,0x90,0x03
|
||||
ld.h -512[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x0a,0x00
|
||||
ld.h -13[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x0b,0xf3
|
||||
ld.h 18[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x08,0x12
|
||||
ld.h 511[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x09,0xff
|
||||
ld.b -512[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x4a,0x00
|
||||
ld.b -13[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x4b,0xf3
|
||||
ld.b 18[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x48,0x12
|
||||
ld.b 511[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x49,0xff
|
||||
uld.h -512[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x1a,0x00
|
||||
uld.h -13[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x1b,0xf3
|
||||
uld.h 18[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x18,0x12
|
||||
uld.h 511[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x19,0xff
|
||||
uld.b -512[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x5a,0x00
|
||||
uld.b -13[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x5b,0xf3
|
||||
uld.b 18[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x58,0x12
|
||||
uld.b 511[%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x59,0xff
|
||||
ld -32768[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0x80,0x00
|
||||
ld -1024[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0xfc,0x00
|
||||
ld 0[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc4,0x00,0x00
|
||||
ld 1024[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0x04,0x00
|
||||
ld 32767[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0x7f,0xff
|
||||
uld -32768[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0x80,0x00
|
||||
uld -1024[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0xfc,0x00
|
||||
uld 0[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc4,0x00,0x00
|
||||
uld 1024[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0x04,0x00
|
||||
uld 32767[*%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0x7f,0xff
|
||||
ld [--%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0xff,0xfc
|
||||
ld [++%r17], %r21
|
||||
! CHECK: 0x8a,0xc7,0x00,0x04
|
||||
ld.h [--%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x0f,0xfe
|
||||
ld.h [++%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x0c,0x02
|
||||
uld.h [--%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x1f,0xfe
|
||||
uld.h [++%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x1c,0x02
|
||||
ld.b [--%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x4f,0xff
|
||||
ld.b [++%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x4c,0x01
|
||||
uld.b [--%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x5f,0xff
|
||||
uld.b [++%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x5c,0x01
|
||||
ld %r18[*%r17], %r21
|
||||
! CHECK: 0xaa,0xc7,0x90,0x02
|
||||
uld %r18[*%r17], %r21
|
||||
! CHECK: 0xaa,0xc7,0x90,0x03
|
||||
ld.h -512[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x0e,0x00
|
||||
ld.h -13[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x0f,0xf3
|
||||
ld.h 18[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x0c,0x12
|
||||
ld.h 511[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x0d,0xff
|
||||
ld.b -512[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x4e,0x00
|
||||
ld.b -13[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x4f,0xf3
|
||||
ld.b 18[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x4c,0x12
|
||||
ld.b 511[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x4d,0xff
|
||||
uld.h -512[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x1e,0x00
|
||||
uld.h -13[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x1f,0xf3
|
||||
uld.h 18[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x1c,0x12
|
||||
uld.h 511[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x1d,0xff
|
||||
uld.b -512[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x5e,0x00
|
||||
uld.b -13[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x5f,0xf3
|
||||
uld.b 18[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x5c,0x12
|
||||
uld.b 511[*%r17], %r21
|
||||
! CHECK: 0xfa,0xc7,0x5d,0xff
|
||||
ld -32768[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc5,0x80,0x00
|
||||
ld -1024[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc5,0xfc,0x00
|
||||
ld 0[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc4,0x00,0x00
|
||||
ld 1024[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc5,0x04,0x00
|
||||
ld 32767[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc5,0x7f,0xff
|
||||
uld -32768[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc5,0x80,0x00
|
||||
uld -1024[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc5,0xfc,0x00
|
||||
uld 0[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc4,0x00,0x00
|
||||
uld 1024[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc5,0x04,0x00
|
||||
uld 32767[%r17*], %r21
|
||||
! CHECK: 0x8a,0xc5,0x7f,0xff
|
||||
ld [%r17--], %r21
|
||||
! CHECK: 0x8a,0xc5,0xff,0xfc
|
||||
ld [%r17++], %r21
|
||||
! CHECK: 0x8a,0xc5,0x00,0x04
|
||||
ld.h [%r17--], %r21
|
||||
! CHECK: 0xfa,0xc7,0x07,0xfe
|
||||
ld.h [%r17++], %r21
|
||||
! CHECK: 0xfa,0xc7,0x04,0x02
|
||||
uld.h [%r17--], %r21
|
||||
! CHECK: 0xfa,0xc7,0x17,0xfe
|
||||
uld.h [%r17++], %r21
|
||||
! CHECK: 0xfa,0xc7,0x14,0x02
|
||||
ld.b [%r17--], %r21
|
||||
! CHECK: 0xfa,0xc7,0x47,0xff
|
||||
ld.b [%r17++], %r21
|
||||
! CHECK: 0xfa,0xc7,0x44,0x01
|
||||
uld.b [%r17--], %r21
|
||||
! CHECK: 0xfa,0xc7,0x57,0xff
|
||||
uld.b [%r17++], %r21
|
||||
! CHECK: 0xfa,0xc7,0x54,0x01
|
||||
ld %r18[%r17*], %r21
|
||||
! CHECK: 0xaa,0xc5,0x90,0x02
|
||||
uld %r18[%r17*], %r21
|
||||
! CHECK: 0xaa,0xc5,0x90,0x03
|
||||
ld.h -512[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x06,0x00
|
||||
ld.h -13[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x07,0xf3
|
||||
ld.h 18[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x04,0x12
|
||||
ld.h 511[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x05,0xff
|
||||
ld.b -512[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x46,0x00
|
||||
ld.b -13[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x47,0xf3
|
||||
ld.b 18[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x44,0x12
|
||||
ld.b 511[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x45,0xff
|
||||
uld.h -512[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x16,0x00
|
||||
uld.h -13[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x17,0xf3
|
||||
uld.h 18[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x14,0x12
|
||||
uld.h 511[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x15,0xff
|
||||
uld.b -512[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x56,0x00
|
||||
uld.b -13[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x57,0xf3
|
||||
uld.b 18[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x54,0x12
|
||||
uld.b 511[%r17*], %r21
|
||||
! CHECK: 0xfa,0xc7,0x55,0xff
|
||||
ld [%r17 add %r18], %r21
|
||||
! CHECK: 0xaa,0xc6,0x90,0x02
|
||||
ld [%r17 addc %r18], %r21
|
||||
! CHECK: 0xaa,0xc6,0x91,0x02
|
||||
ld [%r17 sub %r18], %r21
|
||||
! CHECK: 0xaa,0xc6,0x92,0x02
|
||||
ld [%r17 subb %r18], %r21
|
||||
! CHECK: 0xaa,0xc6,0x93,0x02
|
||||
ld [%r17 and %r18], %r21
|
||||
! CHECK: 0xaa,0xc6,0x94,0x02
|
||||
ld [%r17 or %r18], %r21
|
||||
! CHECK: 0xaa,0xc6,0x95,0x02
|
||||
ld [%r17 xor %r18], %r21
|
||||
! CHECK: 0xaa,0xc6,0x96,0x02
|
||||
ld [%r17 sh %r18], %r21
|
||||
! CHECK: 0xaa,0xc6,0x97,0x82
|
||||
ld [%r17 sha %r18], %r21
|
||||
! CHECK: 0xaa,0xc6,0x97,0xc2
|
||||
ld [*%r17 add %r18], %r21
|
||||
! CHECK: 0xaa,0xc7,0x90,0x02
|
||||
ld [*%r17 addc %r18], %r21
|
||||
! CHECK: 0xaa,0xc7,0x91,0x02
|
||||
ld [*%r17 sub %r18], %r21
|
||||
! CHECK: 0xaa,0xc7,0x92,0x02
|
||||
ld [*%r17 subb %r18], %r21
|
||||
! CHECK: 0xaa,0xc7,0x93,0x02
|
||||
ld [*%r17 and %r18], %r21
|
||||
! CHECK: 0xaa,0xc7,0x94,0x02
|
||||
ld [*%r17 or %r18], %r21
|
||||
! CHECK: 0xaa,0xc7,0x95,0x02
|
||||
ld [*%r17 xor %r18], %r21
|
||||
! CHECK: 0xaa,0xc7,0x96,0x02
|
||||
ld [*%r17 sh %r18], %r21
|
||||
! CHECK: 0xaa,0xc7,0x97,0x82
|
||||
ld [*%r17 sha %r18], %r21
|
||||
! CHECK: 0xaa,0xc7,0x97,0xc2
|
||||
ld [%r17* add %r18], %r21
|
||||
! CHECK: 0xaa,0xc5,0x90,0x02
|
||||
ld [%r17* addc %r18], %r21
|
||||
! CHECK: 0xaa,0xc5,0x91,0x02
|
||||
ld [%r17* sub %r18], %r21
|
||||
! CHECK: 0xaa,0xc5,0x92,0x02
|
||||
ld [%r17* subb %r18], %r21
|
||||
! CHECK: 0xaa,0xc5,0x93,0x02
|
||||
ld [%r17* and %r18], %r21
|
||||
! CHECK: 0xaa,0xc5,0x94,0x02
|
||||
ld [%r17* or %r18], %r21
|
||||
! CHECK: 0xaa,0xc5,0x95,0x02
|
||||
ld [%r17* xor %r18], %r21
|
||||
! CHECK: 0xaa,0xc5,0x96,0x02
|
||||
ld [%r17* sh %r18], %r21
|
||||
! CHECK: 0xaa,0xc5,0x97,0x82
|
||||
ld [%r17* sha %r18], %r21
|
||||
! CHECK: 0xaa,0xc5,0x97,0xc2
|
||||
ld [0x12344], %r21
|
||||
! CHECK: 0xfa,0x84,0x23,0x44
|
||||
leadz %r17, %r21
|
||||
! CHECK: 0xda,0xc4,0x00,0x02
|
||||
mov 0, %r17
|
||||
! CHECK: 0x08,0x80,0x00,0x00
|
||||
mov 0x00001234, %r17
|
||||
! CHECK: 0x08,0x80,0x12,0x34
|
||||
mov 0x12340000, %r17
|
||||
! CHECK: 0x08,0x81,0x12,0x34
|
||||
mov 0xaaaa0000, %r17
|
||||
! CHECK: 0x08,0x81,0xaa,0xaa
|
||||
mov %r18, %r17
|
||||
! CHECK: 0xc8,0xc8,0x00,0x00
|
||||
mov 0x12344, %r17
|
||||
! CHECK: 0xf8,0x86,0x23,0x44
|
||||
mov 0xffff1234, %r17
|
||||
! CHECK: 0x48,0x84,0x12,0x34
|
||||
mov 0x1234ffff, %r17
|
||||
! CHECK: 0x48,0x85,0x12,0x34
|
||||
nop
|
||||
! CHECK: 0x00,0x00,0x00,0x01
|
||||
or %r17, 0, %r21
|
||||
! CHECK: 0x5a,0xc4,0x00,0x00
|
||||
or %r17, 0x00001234, %r21
|
||||
! CHECK: 0x5a,0xc4,0x12,0x34
|
||||
or %r17, 0x12340000, %r21
|
||||
! CHECK: 0x5a,0xc5,0x12,0x34
|
||||
or.f %r17, 0, %r21
|
||||
! CHECK: 0x5a,0xc6,0x00,0x00
|
||||
or.f %r17, 0x00001234, %r21
|
||||
! CHECK: 0x5a,0xc6,0x12,0x34
|
||||
or.f %r17, 0x12340000, %r21
|
||||
! CHECK: 0x5a,0xc7,0x12,0x34
|
||||
or %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc4,0x95,0x00
|
||||
or.f %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc6,0x95,0x00
|
||||
popc %r17, %r21
|
||||
! CHECK: 0xda,0xc4,0x00,0x01
|
||||
st %r21
|
||||
! CHECK: 0xe0,0x54,0x00,0x02
|
||||
shi %r21
|
||||
! CHECK: 0xe2,0x54,0x00,0x02
|
||||
sugt %r21
|
||||
! CHECK: 0xe2,0x54,0x00,0x02
|
||||
sls %r21
|
||||
! CHECK: 0xe2,0x54,0x00,0x03
|
||||
sule %r21
|
||||
! CHECK: 0xe2,0x54,0x00,0x03
|
||||
scc %r21
|
||||
! CHECK: 0xe4,0x54,0x00,0x02
|
||||
sult %r21
|
||||
! CHECK: 0xe4,0x54,0x00,0x02
|
||||
scs %r21
|
||||
! CHECK: 0xe4,0x54,0x00,0x03
|
||||
suge %r21
|
||||
! CHECK: 0xe4,0x54,0x00,0x03
|
||||
sne %r21
|
||||
! CHECK: 0xe6,0x54,0x00,0x02
|
||||
seq %r21
|
||||
! CHECK: 0xe6,0x54,0x00,0x03
|
||||
svc %r21
|
||||
! CHECK: 0xe8,0x54,0x00,0x02
|
||||
svs %r21
|
||||
! CHECK: 0xe8,0x54,0x00,0x03
|
||||
spl %r21
|
||||
! CHECK: 0xea,0x54,0x00,0x02
|
||||
smi %r21
|
||||
! CHECK: 0xea,0x54,0x00,0x03
|
||||
sge %r21
|
||||
! CHECK: 0xec,0x54,0x00,0x02
|
||||
slt %r21
|
||||
! CHECK: 0xec,0x54,0x00,0x03
|
||||
sgt %r21
|
||||
! CHECK: 0xee,0x54,0x00,0x02
|
||||
sh %r17, -31, %r21
|
||||
! CHECK: 0x7a,0xc4,0xff,0xe1
|
||||
sh %r17, -5, %r21
|
||||
! CHECK: 0x7a,0xc4,0xff,0xfb
|
||||
sh %r17, 2, %r21
|
||||
! CHECK: 0x7a,0xc4,0x00,0x02
|
||||
sh %r17, 31, %r21
|
||||
! CHECK: 0x7a,0xc4,0x00,0x1f
|
||||
sh.f %r17, -31, %r21
|
||||
! CHECK: 0x7a,0xc6,0xff,0xe1
|
||||
sh.f %r17, -5, %r21
|
||||
! CHECK: 0x7a,0xc6,0xff,0xfb
|
||||
sh.f %r17, 2, %r21
|
||||
! CHECK: 0x7a,0xc6,0x00,0x02
|
||||
sh.f %r17, 31, %r21
|
||||
! CHECK: 0x7a,0xc6,0x00,0x1f
|
||||
sh %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc4,0x97,0x80
|
||||
sh.f %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc6,0x97,0x80
|
||||
sha %r17, -31, %r21
|
||||
! CHECK: 0x7a,0xc5,0xff,0xe1
|
||||
sha %r17, -5, %r21
|
||||
! CHECK: 0x7a,0xc5,0xff,0xfb
|
||||
sha %r17, 2, %r21
|
||||
! CHECK: 0x7a,0xc5,0x00,0x02
|
||||
sha %r17, 31, %r21
|
||||
! CHECK: 0x7a,0xc5,0x00,0x1f
|
||||
sha.f %r17, -31, %r21
|
||||
! CHECK: 0x7a,0xc7,0xff,0xe1
|
||||
sha.f %r17, -5, %r21
|
||||
! CHECK: 0x7a,0xc7,0xff,0xfb
|
||||
sha.f %r17, 2, %r21
|
||||
! CHECK: 0x7a,0xc7,0x00,0x02
|
||||
sha.f %r17, 31, %r21
|
||||
! CHECK: 0x7a,0xc7,0x00,0x1f
|
||||
sha %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc4,0x97,0xc0
|
||||
sha.f %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc6,0x97,0xc0
|
||||
st %r17, -32768[%r19]
|
||||
! CHECK: 0x98,0xce,0x80,0x00
|
||||
st %r17, -1024[%r19]
|
||||
! CHECK: 0x98,0xce,0xfc,0x00
|
||||
st %r17, 0[%r19]
|
||||
! CHECK: 0x98,0xcc,0x00,0x00
|
||||
st %r17, 1024[%r19]
|
||||
! CHECK: 0x98,0xce,0x04,0x00
|
||||
st %r17, 32767[%r19]
|
||||
! CHECK: 0x98,0xce,0x7f,0xff
|
||||
st.h %r17, -512[%r19]
|
||||
! CHECK: 0xf8,0xcf,0x2a,0x00
|
||||
st.h %r17, -13[%r19]
|
||||
! CHECK: 0xf8,0xcf,0x2b,0xf3
|
||||
st.h %r17, 18[%r19]
|
||||
! CHECK: 0xf8,0xcf,0x28,0x12
|
||||
st.h %r17, 511[%r19]
|
||||
! CHECK: 0xf8,0xcf,0x29,0xff
|
||||
st.b %r17, -512[%r19]
|
||||
! CHECK: 0xf8,0xcf,0x6a,0x00
|
||||
st.b %r17, -13[%r19]
|
||||
! CHECK: 0xf8,0xcf,0x6b,0xf3
|
||||
st.b %r17, 18[%r19]
|
||||
! CHECK: 0xf8,0xcf,0x68,0x12
|
||||
st.b %r17, 511[%r19]
|
||||
! CHECK: 0xf8,0xcf,0x69,0xff
|
||||
st %r17, %r18[%r19]
|
||||
! CHECK: 0xb8,0xce,0x90,0x02
|
||||
st.h %r17, %r18[%r19]
|
||||
! CHECK: 0xb8,0xce,0x90,0x00
|
||||
st.b %r17, %r18[%r19]
|
||||
! CHECK: 0xb8,0xce,0x90,0x04
|
||||
st %r17, -32768[*%r19]
|
||||
! CHECK: 0x98,0xcf,0x80,0x00
|
||||
st %r17, -1024[*%r19]
|
||||
! CHECK: 0x98,0xcf,0xfc,0x00
|
||||
st %r17, 0[*%r19]
|
||||
! CHECK: 0x98,0xcc,0x00,0x00
|
||||
st %r17, 1024[*%r19]
|
||||
! CHECK: 0x98,0xcf,0x04,0x00
|
||||
st %r17, 32767[*%r19]
|
||||
! CHECK: 0x98,0xcf,0x7f,0xff
|
||||
st.h %r17, -512[*%r19]
|
||||
! CHECK: 0xf8,0xcf,0x2e,0x00
|
||||
st.h %r17, -13[*%r19]
|
||||
! CHECK: 0xf8,0xcf,0x2f,0xf3
|
||||
st.h %r17, 18[*%r19]
|
||||
! CHECK: 0xf8,0xcf,0x2c,0x12
|
||||
st.h %r17, 511[*%r19]
|
||||
! CHECK: 0xf8,0xcf,0x2d,0xff
|
||||
st.b %r17, -512[*%r19]
|
||||
! CHECK: 0xf8,0xcf,0x6e,0x00
|
||||
st.b %r17, -13[*%r19]
|
||||
! CHECK: 0xf8,0xcf,0x6f,0xf3
|
||||
st.b %r17, 18[*%r19]
|
||||
! CHECK: 0xf8,0xcf,0x6c,0x12
|
||||
st.b %r17, 511[*%r19]
|
||||
! CHECK: 0xf8,0xcf,0x6d,0xff
|
||||
st %r17, [--%r19]
|
||||
! CHECK: 0x98,0xcf,0xff,0xfc
|
||||
st %r17, [++%r19]
|
||||
! CHECK: 0x98,0xcf,0x00,0x04
|
||||
st.h %r17, [--%r19]
|
||||
! CHECK: 0xf8,0xcf,0x2f,0xfe
|
||||
st.h %r17, [++%r19]
|
||||
! CHECK: 0xf8,0xcf,0x2c,0x02
|
||||
st.b %r17, [--%r19]
|
||||
! CHECK: 0xf8,0xcf,0x6f,0xff
|
||||
st.b %r17, [++%r19]
|
||||
! CHECK: 0xf8,0xcf,0x6c,0x01
|
||||
st %r17, %r18[*%r19]
|
||||
! CHECK: 0xb8,0xcf,0x90,0x02
|
||||
st.h %r17, %r18[*%r19]
|
||||
! CHECK: 0xb8,0xcf,0x90,0x00
|
||||
st.b %r17, %r18[*%r19]
|
||||
! CHECK: 0xb8,0xcf,0x90,0x04
|
||||
st %r17, -32768[%r19*]
|
||||
! CHECK: 0x98,0xcd,0x80,0x00
|
||||
st %r17, -1024[%r19*]
|
||||
! CHECK: 0x98,0xcd,0xfc,0x00
|
||||
st %r17, 0[%r19*]
|
||||
! CHECK: 0x98,0xcc,0x00,0x00
|
||||
st %r17, 1024[%r19*]
|
||||
! CHECK: 0x98,0xcd,0x04,0x00
|
||||
st %r17, 32767[%r19*]
|
||||
! CHECK: 0x98,0xcd,0x7f,0xff
|
||||
st.h %r17, -512[%r19*]
|
||||
! CHECK: 0xf8,0xcf,0x26,0x00
|
||||
st.h %r17, -13[%r19*]
|
||||
! CHECK: 0xf8,0xcf,0x27,0xf3
|
||||
st.h %r17, 18[%r19*]
|
||||
! CHECK: 0xf8,0xcf,0x24,0x12
|
||||
st.h %r17, 511[%r19*]
|
||||
! CHECK: 0xf8,0xcf,0x25,0xff
|
||||
st.b %r17, -512[%r19*]
|
||||
! CHECK: 0xf8,0xcf,0x66,0x00
|
||||
st.b %r17, -13[%r19*]
|
||||
! CHECK: 0xf8,0xcf,0x67,0xf3
|
||||
st.b %r17, 18[%r19*]
|
||||
! CHECK: 0xf8,0xcf,0x64,0x12
|
||||
st.b %r17, 511[%r19*]
|
||||
! CHECK: 0xf8,0xcf,0x65,0xff
|
||||
st %r17, [%r19--]
|
||||
! CHECK: 0x98,0xcd,0xff,0xfc
|
||||
st %r17, [%r19++]
|
||||
! CHECK: 0x98,0xcd,0x00,0x04
|
||||
st.h %r17, [%r19--]
|
||||
! CHECK: 0xf8,0xcf,0x27,0xfe
|
||||
st.h %r17, [%r19++]
|
||||
! CHECK: 0xf8,0xcf,0x24,0x02
|
||||
st.b %r17, [%r19--]
|
||||
! CHECK: 0xf8,0xcf,0x67,0xff
|
||||
st.b %r17, [%r19++]
|
||||
! CHECK: 0xf8,0xcf,0x64,0x01
|
||||
st %r17, %r18[%r19*]
|
||||
! CHECK: 0xb8,0xcd,0x90,0x02
|
||||
st.h %r17, %r18[%r19*]
|
||||
! CHECK: 0xb8,0xcd,0x90,0x00
|
||||
st.b %r17, %r18[%r19*]
|
||||
! CHECK: 0xb8,0xcd,0x90,0x04
|
||||
st %r21, [%r17 add %r18]
|
||||
! CHECK: 0xba,0xc6,0x90,0x02
|
||||
st %r21, [%r17 addc %r18]
|
||||
! CHECK: 0xba,0xc6,0x91,0x02
|
||||
st %r21, [%r17 sub %r18]
|
||||
! CHECK: 0xba,0xc6,0x92,0x02
|
||||
st %r21, [%r17 subb %r18]
|
||||
! CHECK: 0xba,0xc6,0x93,0x02
|
||||
st %r21, [%r17 and %r18]
|
||||
! CHECK: 0xba,0xc6,0x94,0x02
|
||||
st %r21, [%r17 or %r18]
|
||||
! CHECK: 0xba,0xc6,0x95,0x02
|
||||
st %r21, [%r17 xor %r18]
|
||||
! CHECK: 0xba,0xc6,0x96,0x02
|
||||
st %r21, [%r17 sh %r18]
|
||||
! CHECK: 0xba,0xc6,0x97,0x82
|
||||
st %r21, [%r17 sha %r18]
|
||||
! CHECK: 0xba,0xc6,0x97,0xc2
|
||||
st.h %r21, [%r17 add %r18]
|
||||
! CHECK: 0xba,0xc6,0x90,0x00
|
||||
st.h %r21, [%r17 addc %r18]
|
||||
! CHECK: 0xba,0xc6,0x91,0x00
|
||||
st.h %r21, [%r17 sub %r18]
|
||||
! CHECK: 0xba,0xc6,0x92,0x00
|
||||
st.h %r21, [%r17 subb %r18]
|
||||
! CHECK: 0xba,0xc6,0x93,0x00
|
||||
st.h %r21, [%r17 and %r18]
|
||||
! CHECK: 0xba,0xc6,0x94,0x00
|
||||
st.h %r21, [%r17 or %r18]
|
||||
! CHECK: 0xba,0xc6,0x95,0x00
|
||||
st.h %r21, [%r17 xor %r18]
|
||||
! CHECK: 0xba,0xc6,0x96,0x00
|
||||
st.h %r21, [%r17 sh %r18]
|
||||
! CHECK: 0xba,0xc6,0x97,0x80
|
||||
st.h %r21, [%r17 sha %r18]
|
||||
! CHECK: 0xba,0xc6,0x97,0xc0
|
||||
st.b %r21, [%r17 add %r18]
|
||||
! CHECK: 0xba,0xc6,0x90,0x04
|
||||
st.b %r21, [%r17 addc %r18]
|
||||
! CHECK: 0xba,0xc6,0x91,0x04
|
||||
st.b %r21, [%r17 sub %r18]
|
||||
! CHECK: 0xba,0xc6,0x92,0x04
|
||||
st.b %r21, [%r17 subb %r18]
|
||||
! CHECK: 0xba,0xc6,0x93,0x04
|
||||
st.b %r21, [%r17 and %r18]
|
||||
! CHECK: 0xba,0xc6,0x94,0x04
|
||||
st.b %r21, [%r17 or %r18]
|
||||
! CHECK: 0xba,0xc6,0x95,0x04
|
||||
st.b %r21, [%r17 xor %r18]
|
||||
! CHECK: 0xba,0xc6,0x96,0x04
|
||||
st.b %r21, [%r17 sh %r18]
|
||||
! CHECK: 0xba,0xc6,0x97,0x84
|
||||
st.b %r21, [%r17 sha %r18]
|
||||
! CHECK: 0xba,0xc6,0x97,0xc4
|
||||
st %r21, [*%r17 add %r18]
|
||||
! CHECK: 0xba,0xc7,0x90,0x02
|
||||
st %r21, [*%r17 addc %r18]
|
||||
! CHECK: 0xba,0xc7,0x91,0x02
|
||||
st %r21, [*%r17 sub %r18]
|
||||
! CHECK: 0xba,0xc7,0x92,0x02
|
||||
st %r21, [*%r17 subb %r18]
|
||||
! CHECK: 0xba,0xc7,0x93,0x02
|
||||
st %r21, [*%r17 and %r18]
|
||||
! CHECK: 0xba,0xc7,0x94,0x02
|
||||
st %r21, [*%r17 or %r18]
|
||||
! CHECK: 0xba,0xc7,0x95,0x02
|
||||
st %r21, [*%r17 xor %r18]
|
||||
! CHECK: 0xba,0xc7,0x96,0x02
|
||||
st %r21, [*%r17 sha %r18]
|
||||
! CHECK: 0xba,0xc7,0x97,0xc2
|
||||
st.h %r21, [*%r17 add %r18]
|
||||
! CHECK: 0xba,0xc7,0x90,0x00
|
||||
st.h %r21, [*%r17 addc %r18]
|
||||
! CHECK: 0xba,0xc7,0x91,0x00
|
||||
st.h %r21, [*%r17 sub %r18]
|
||||
! CHECK: 0xba,0xc7,0x92,0x00
|
||||
st.h %r21, [*%r17 subb %r18]
|
||||
! CHECK: 0xba,0xc7,0x93,0x00
|
||||
st.h %r21, [*%r17 and %r18]
|
||||
! CHECK: 0xba,0xc7,0x94,0x00
|
||||
st.h %r21, [*%r17 or %r18]
|
||||
! CHECK: 0xba,0xc7,0x95,0x00
|
||||
st.h %r21, [*%r17 xor %r18]
|
||||
! CHECK: 0xba,0xc7,0x96,0x00
|
||||
st.h %r21, [*%r17 sha %r18]
|
||||
! CHECK: 0xba,0xc7,0x97,0xc0
|
||||
st.b %r21, [*%r17 add %r18]
|
||||
! CHECK: 0xba,0xc7,0x90,0x04
|
||||
st.b %r21, [*%r17 addc %r18]
|
||||
! CHECK: 0xba,0xc7,0x91,0x04
|
||||
st.b %r21, [*%r17 sub %r18]
|
||||
! CHECK: 0xba,0xc7,0x92,0x04
|
||||
st.b %r21, [*%r17 subb %r18]
|
||||
! CHECK: 0xba,0xc7,0x93,0x04
|
||||
st.b %r21, [*%r17 and %r18]
|
||||
! CHECK: 0xba,0xc7,0x94,0x04
|
||||
st.b %r21, [*%r17 or %r18]
|
||||
! CHECK: 0xba,0xc7,0x95,0x04
|
||||
st.b %r21, [*%r17 xor %r18]
|
||||
! CHECK: 0xba,0xc7,0x96,0x04
|
||||
st.b %r21, [*%r17 sha %r18]
|
||||
! CHECK: 0xba,0xc7,0x97,0xc4
|
||||
st %r21, [%r17* add %r18]
|
||||
! CHECK: 0xba,0xc5,0x90,0x02
|
||||
st %r21, [%r17* addc %r18]
|
||||
! CHECK: 0xba,0xc5,0x91,0x02
|
||||
st %r21, [%r17* sub %r18]
|
||||
! CHECK: 0xba,0xc5,0x92,0x02
|
||||
st %r21, [%r17* subb %r18]
|
||||
! CHECK: 0xba,0xc5,0x93,0x02
|
||||
st %r21, [%r17* and %r18]
|
||||
! CHECK: 0xba,0xc5,0x94,0x02
|
||||
st %r21, [%r17* or %r18]
|
||||
! CHECK: 0xba,0xc5,0x95,0x02
|
||||
st %r21, [%r17* xor %r18]
|
||||
! CHECK: 0xba,0xc5,0x96,0x02
|
||||
st %r21, [%r17* sh %r18]
|
||||
! CHECK: 0xba,0xc5,0x97,0x82
|
||||
st %r21, [%r17* sha %r18]
|
||||
! CHECK: 0xba,0xc5,0x97,0xc2
|
||||
st.h %r21, [%r17* add %r18]
|
||||
! CHECK: 0xba,0xc5,0x90,0x00
|
||||
st.h %r21, [%r17* addc %r18]
|
||||
! CHECK: 0xba,0xc5,0x91,0x00
|
||||
st.h %r21, [%r17* sub %r18]
|
||||
! CHECK: 0xba,0xc5,0x92,0x00
|
||||
st.h %r21, [%r17* subb %r18]
|
||||
! CHECK: 0xba,0xc5,0x93,0x00
|
||||
st.h %r21, [%r17* and %r18]
|
||||
! CHECK: 0xba,0xc5,0x94,0x00
|
||||
st.h %r21, [%r17* or %r18]
|
||||
! CHECK: 0xba,0xc5,0x95,0x00
|
||||
st.h %r21, [%r17* xor %r18]
|
||||
! CHECK: 0xba,0xc5,0x96,0x00
|
||||
st.h %r21, [%r17* sh %r18]
|
||||
! CHECK: 0xba,0xc5,0x97,0x80
|
||||
st.h %r21, [%r17* sha %r18]
|
||||
! CHECK: 0xba,0xc5,0x97,0xc0
|
||||
st.b %r21, [%r17* add %r18]
|
||||
! CHECK: 0xba,0xc5,0x90,0x04
|
||||
st.b %r21, [%r17* addc %r18]
|
||||
! CHECK: 0xba,0xc5,0x91,0x04
|
||||
st.b %r21, [%r17* sub %r18]
|
||||
! CHECK: 0xba,0xc5,0x92,0x04
|
||||
st.b %r21, [%r17* subb %r18]
|
||||
! CHECK: 0xba,0xc5,0x93,0x04
|
||||
st.b %r21, [%r17* and %r18]
|
||||
! CHECK: 0xba,0xc5,0x94,0x04
|
||||
st.b %r21, [%r17* or %r18]
|
||||
! CHECK: 0xba,0xc5,0x95,0x04
|
||||
st.b %r21, [%r17* xor %r18]
|
||||
! CHECK: 0xba,0xc5,0x96,0x04
|
||||
st.b %r21, [%r17* sh %r18]
|
||||
! CHECK: 0xba,0xc5,0x97,0x84
|
||||
st.b %r21, [%r17* sha %r18]
|
||||
! CHECK: 0xba,0xc5,0x97,0xc4
|
||||
st %r21, [0x12344]
|
||||
! CHECK: 0xfa,0x85,0x23,0x44
|
||||
sub %r17, 0, %r21
|
||||
! CHECK: 0x2a,0xc4,0x00,0x00
|
||||
sub %r17, 0x00001234, %r21
|
||||
! CHECK: 0x2a,0xc4,0x12,0x34
|
||||
sub %r17, 0x12340000, %r21
|
||||
! CHECK: 0x2a,0xc5,0x12,0x34
|
||||
sub.f %r17, 0, %r21
|
||||
! CHECK: 0x2a,0xc6,0x00,0x00
|
||||
sub.f %r17, 0x00001234, %r21
|
||||
! CHECK: 0x2a,0xc6,0x12,0x34
|
||||
sub.f %r17, 0x12340000, %r21
|
||||
! CHECK: 0x2a,0xc7,0x12,0x34
|
||||
sub %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc4,0x92,0x00
|
||||
sub.f %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc6,0x92,0x00
|
||||
subb %r17, 0, %r21
|
||||
! CHECK: 0x3a,0xc4,0x00,0x00
|
||||
subb %r17, 0x00001234, %r21
|
||||
! CHECK: 0x3a,0xc4,0x12,0x34
|
||||
subb %r17, 0x12340000, %r21
|
||||
! CHECK: 0x3a,0xc5,0x12,0x34
|
||||
subb.f %r17, 0, %r21
|
||||
! CHECK: 0x3a,0xc6,0x00,0x00
|
||||
subb.f %r17, 0x00001234, %r21
|
||||
! CHECK: 0x3a,0xc6,0x12,0x34
|
||||
subb.f %r17, 0x12340000, %r21
|
||||
! CHECK: 0x3a,0xc7,0x12,0x34
|
||||
subb %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc4,0x93,0x00
|
||||
subb.f %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc6,0x93,0x00
|
||||
xor %r17, 0, %r21
|
||||
! CHECK: 0x6a,0xc4,0x00,0x00
|
||||
xor %r17, 0x00001234, %r21
|
||||
! CHECK: 0x6a,0xc4,0x12,0x34
|
||||
xor %r17, 0x12340000, %r21
|
||||
! CHECK: 0x6a,0xc5,0x12,0x34
|
||||
xor.f %r17, 0, %r21
|
||||
! CHECK: 0x6a,0xc6,0x00,0x00
|
||||
xor.f %r17, 0x00001234, %r21
|
||||
! CHECK: 0x6a,0xc6,0x12,0x34
|
||||
xor.f %r17, 0x12340000, %r21
|
||||
! CHECK: 0x6a,0xc7,0x12,0x34
|
||||
xor %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc4,0x96,0x00
|
||||
xor.f %r17, %r18, %r21
|
||||
! CHECK: 0xca,0xc6,0x96,0x00
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# RUN: yaml2obj -format=elf %s > %t
|
||||
# RUN: llvm-readobj -r %t | FileCheck %s
|
||||
|
||||
# CHECK : Relocations [
|
||||
# CHECK: Relocations [
|
||||
# CHECK-NEXT: Section (2) .rel.text {
|
||||
# CHECK-NEXT: 0x0 R_LANAI_32 main 0x0
|
||||
# CHECK-NEXT: 0x4 R_LANAI_NONE - 0x0
|
||||
|
Loading…
x
Reference in New Issue
Block a user